archimate 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.projectile +18 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +4 -0
- data/.yardocs +15 -0
- data/Gemfile +5 -0
- data/Guardfile +27 -0
- data/LICENSE +201 -0
- data/README.md +94 -0
- data/Rakefile +29 -0
- data/TODOs.org +286 -0
- data/archimate.gemspec +51 -0
- data/bin/archimate +17 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/exe/archidiff +7 -0
- data/exe/archidiff-summary +7 -0
- data/exe/archimate +7 -0
- data/exe/archimerge +7 -0
- data/exe/fmtxml +7 -0
- data/lib/archimate/cli/archi.rb +189 -0
- data/lib/archimate/cli/cleanup.rb +54 -0
- data/lib/archimate/cli/conflict_resolver.rb +39 -0
- data/lib/archimate/cli/convert.rb +39 -0
- data/lib/archimate/cli/diff.rb +31 -0
- data/lib/archimate/cli/diff_summary.rb +101 -0
- data/lib/archimate/cli/duper.rb +85 -0
- data/lib/archimate/cli/lint.rb +16 -0
- data/lib/archimate/cli/mapper.rb +82 -0
- data/lib/archimate/cli/merge.rb +49 -0
- data/lib/archimate/cli/merger.rb +109 -0
- data/lib/archimate/cli/stats.rb +42 -0
- data/lib/archimate/cli/svger.rb +40 -0
- data/lib/archimate/color.rb +53 -0
- data/lib/archimate/config.rb +35 -0
- data/lib/archimate/data_model/any_attribute.rb +13 -0
- data/lib/archimate/data_model/any_element.rb +15 -0
- data/lib/archimate/data_model/archimate_node.rb +181 -0
- data/lib/archimate/data_model/bounds.rb +72 -0
- data/lib/archimate/data_model/color.rb +47 -0
- data/lib/archimate/data_model/concept.rb +14 -0
- data/lib/archimate/data_model/concern.rb +17 -0
- data/lib/archimate/data_model/connection.rb +107 -0
- data/lib/archimate/data_model/constants.rb +82 -0
- data/lib/archimate/data_model/container.rb +17 -0
- data/lib/archimate/data_model/diagram.rb +40 -0
- data/lib/archimate/data_model/diffable_array.rb +213 -0
- data/lib/archimate/data_model/diffable_primitive.rb +83 -0
- data/lib/archimate/data_model/documentation.rb +14 -0
- data/lib/archimate/data_model/element.rb +87 -0
- data/lib/archimate/data_model/font.rb +54 -0
- data/lib/archimate/data_model/label.rb +19 -0
- data/lib/archimate/data_model/lang_string.rb +41 -0
- data/lib/archimate/data_model/location.rb +31 -0
- data/lib/archimate/data_model/metadata.rb +14 -0
- data/lib/archimate/data_model/model.rb +217 -0
- data/lib/archimate/data_model/modeling_note.rb +13 -0
- data/lib/archimate/data_model/named_referenceable.rb +14 -0
- data/lib/archimate/data_model/organization.rb +40 -0
- data/lib/archimate/data_model/property.rb +25 -0
- data/lib/archimate/data_model/property_definition.rb +16 -0
- data/lib/archimate/data_model/referenceable.rb +29 -0
- data/lib/archimate/data_model/relationship.rb +85 -0
- data/lib/archimate/data_model/schema_info.rb +18 -0
- data/lib/archimate/data_model/style.rb +32 -0
- data/lib/archimate/data_model/view.rb +12 -0
- data/lib/archimate/data_model/view_concept.rb +18 -0
- data/lib/archimate/data_model/view_node.rb +114 -0
- data/lib/archimate/data_model/viewpoint.rb +87 -0
- data/lib/archimate/data_model.rb +54 -0
- data/lib/archimate/diff/archimate_array_reference.rb +113 -0
- data/lib/archimate/diff/archimate_identified_node_reference.rb +41 -0
- data/lib/archimate/diff/archimate_node_attribute_reference.rb +70 -0
- data/lib/archimate/diff/archimate_node_reference.rb +80 -0
- data/lib/archimate/diff/change.rb +49 -0
- data/lib/archimate/diff/conflict.rb +31 -0
- data/lib/archimate/diff/conflicts/base_conflict.rb +53 -0
- data/lib/archimate/diff/conflicts/deleted_items_child_updated_conflict.rb +30 -0
- data/lib/archimate/diff/conflicts/deleted_items_referenced_conflict.rb +63 -0
- data/lib/archimate/diff/conflicts/path_conflict.rb +51 -0
- data/lib/archimate/diff/conflicts.rb +89 -0
- data/lib/archimate/diff/delete.rb +41 -0
- data/lib/archimate/diff/difference.rb +113 -0
- data/lib/archimate/diff/insert.rb +43 -0
- data/lib/archimate/diff/merge.rb +70 -0
- data/lib/archimate/diff/move.rb +51 -0
- data/lib/archimate/diff.rb +17 -0
- data/lib/archimate/export/csv_export.rb +32 -0
- data/lib/archimate/export/cypher.rb +171 -0
- data/lib/archimate/export/graph_ml.rb +131 -0
- data/lib/archimate/export/n_quads.rb +142 -0
- data/lib/archimate/file_format.rb +30 -0
- data/lib/archimate/file_formats/archi_file_format.rb +151 -0
- data/lib/archimate/file_formats/archi_file_reader.rb +252 -0
- data/lib/archimate/file_formats/archi_file_writer.rb +230 -0
- data/lib/archimate/file_formats/archimate_v2.rb +461 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_lang_string.rb +35 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_metadata.rb +115 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_property_definitions.rb +28 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_property_defs.rb +27 -0
- data/lib/archimate/file_formats/model_exchange_file_reader.rb +237 -0
- data/lib/archimate/file_formats/model_exchange_file_reader_21.rb +73 -0
- data/lib/archimate/file_formats/model_exchange_file_reader_30.rb +134 -0
- data/lib/archimate/file_formats/model_exchange_file_writer.rb +157 -0
- data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +143 -0
- data/lib/archimate/file_formats/model_exchange_file_writer_30.rb +153 -0
- data/lib/archimate/file_formats/writer.rb +56 -0
- data/lib/archimate/lint/duplicate_entities.rb +121 -0
- data/lib/archimate/lint/linter.rb +146 -0
- data/lib/archimate/logging.rb +55 -0
- data/lib/archimate/maybe_io.rb +34 -0
- data/lib/archimate/progress_indicator.rb +29 -0
- data/lib/archimate/svg/archimate.css +232 -0
- data/lib/archimate/svg/child.rb +29 -0
- data/lib/archimate/svg/connection.rb +184 -0
- data/lib/archimate/svg/css_style.rb +31 -0
- data/lib/archimate/svg/diagram.rb +87 -0
- data/lib/archimate/svg/entity/and_junction.rb +14 -0
- data/lib/archimate/svg/entity/application_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/application_component.rb +41 -0
- data/lib/archimate/svg/entity/application_event.rb +13 -0
- data/lib/archimate/svg/entity/application_function.rb +13 -0
- data/lib/archimate/svg/entity/application_interaction.rb +13 -0
- data/lib/archimate/svg/entity/application_interface.rb +13 -0
- data/lib/archimate/svg/entity/application_process.rb +13 -0
- data/lib/archimate/svg/entity/application_service.rb +13 -0
- data/lib/archimate/svg/entity/artifact.rb +39 -0
- data/lib/archimate/svg/entity/assessment.rb +14 -0
- data/lib/archimate/svg/entity/base_entity.rb +128 -0
- data/lib/archimate/svg/entity/business_actor.rb +14 -0
- data/lib/archimate/svg/entity/business_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/business_event.rb +10 -0
- data/lib/archimate/svg/entity/business_function.rb +13 -0
- data/lib/archimate/svg/entity/business_interaction.rb +13 -0
- data/lib/archimate/svg/entity/business_interface.rb +13 -0
- data/lib/archimate/svg/entity/business_object.rb +13 -0
- data/lib/archimate/svg/entity/business_process.rb +13 -0
- data/lib/archimate/svg/entity/business_role.rb +14 -0
- data/lib/archimate/svg/entity/business_service.rb +13 -0
- data/lib/archimate/svg/entity/capability.rb +14 -0
- data/lib/archimate/svg/entity/communication_network.rb +14 -0
- data/lib/archimate/svg/entity/communication_path.rb +14 -0
- data/lib/archimate/svg/entity/constraint.rb +15 -0
- data/lib/archimate/svg/entity/contract.rb +13 -0
- data/lib/archimate/svg/entity/course_of_action.rb +14 -0
- data/lib/archimate/svg/entity/data_entity.rb +29 -0
- data/lib/archimate/svg/entity/data_object.rb +13 -0
- data/lib/archimate/svg/entity/deliverable.rb +13 -0
- data/lib/archimate/svg/entity/device.rb +48 -0
- data/lib/archimate/svg/entity/diagram_model_reference.rb +22 -0
- data/lib/archimate/svg/entity/diagram_object.rb +30 -0
- data/lib/archimate/svg/entity/distribution_network.rb +14 -0
- data/lib/archimate/svg/entity/driver.rb +14 -0
- data/lib/archimate/svg/entity/equipment.rb +16 -0
- data/lib/archimate/svg/entity/event_entity.rb +36 -0
- data/lib/archimate/svg/entity/facility.rb +16 -0
- data/lib/archimate/svg/entity/function_entity.rb +14 -0
- data/lib/archimate/svg/entity/gap.rb +21 -0
- data/lib/archimate/svg/entity/goal.rb +14 -0
- data/lib/archimate/svg/entity/group.rb +24 -0
- data/lib/archimate/svg/entity/implementation_event.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_function.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_interface.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_service.rb +13 -0
- data/lib/archimate/svg/entity/interaction_entity.rb +14 -0
- data/lib/archimate/svg/entity/interface_entity.rb +35 -0
- data/lib/archimate/svg/entity/junction.rb +19 -0
- data/lib/archimate/svg/entity/location.rb +14 -0
- data/lib/archimate/svg/entity/material.rb +14 -0
- data/lib/archimate/svg/entity/meaning.rb +40 -0
- data/lib/archimate/svg/entity/motivation_entity.rb +40 -0
- data/lib/archimate/svg/entity/network.rb +14 -0
- data/lib/archimate/svg/entity/node.rb +33 -0
- data/lib/archimate/svg/entity/node_shape.rb +64 -0
- data/lib/archimate/svg/entity/note.rb +30 -0
- data/lib/archimate/svg/entity/or_junction.rb +14 -0
- data/lib/archimate/svg/entity/outcome.rb +15 -0
- data/lib/archimate/svg/entity/path.rb +14 -0
- data/lib/archimate/svg/entity/plateau.rb +15 -0
- data/lib/archimate/svg/entity/principle.rb +15 -0
- data/lib/archimate/svg/entity/process_entity.rb +63 -0
- data/lib/archimate/svg/entity/product.rb +20 -0
- data/lib/archimate/svg/entity/rect.rb +13 -0
- data/lib/archimate/svg/entity/rect_entity.rb +25 -0
- data/lib/archimate/svg/entity/representation.rb +31 -0
- data/lib/archimate/svg/entity/requirement.rb +15 -0
- data/lib/archimate/svg/entity/resource.rb +14 -0
- data/lib/archimate/svg/entity/rounded_rect_entity.rb +23 -0
- data/lib/archimate/svg/entity/service_entity.rb +51 -0
- data/lib/archimate/svg/entity/sketch_model_sticky.rb +14 -0
- data/lib/archimate/svg/entity/stakeholder.rb +15 -0
- data/lib/archimate/svg/entity/system_software.rb +14 -0
- data/lib/archimate/svg/entity/technology_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/technology_event.rb +13 -0
- data/lib/archimate/svg/entity/technology_function.rb +13 -0
- data/lib/archimate/svg/entity/technology_interaction.rb +13 -0
- data/lib/archimate/svg/entity/technology_interface.rb +13 -0
- data/lib/archimate/svg/entity/technology_process.rb +13 -0
- data/lib/archimate/svg/entity/technology_service.rb +13 -0
- data/lib/archimate/svg/entity/value.rb +27 -0
- data/lib/archimate/svg/entity/work_package.rb +14 -0
- data/lib/archimate/svg/entity.rb +93 -0
- data/lib/archimate/svg/entity_factory.rb +17 -0
- data/lib/archimate/svg/extents.rb +27 -0
- data/lib/archimate/svg/point.rb +7 -0
- data/lib/archimate/svg/svg_template.rb +27 -0
- data/lib/archimate/svg/svg_template.svg.erb +169 -0
- data/lib/archimate/version.rb +4 -0
- data/lib/archimate.rb +114 -0
- metadata +623 -0
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
# This is the root model type.
|
6
|
+
# It is a container for the elements, relationships, diagrams and organizations of the model.
|
7
|
+
class Model < NamedReferenceable
|
8
|
+
using DataModel::DiffableArray
|
9
|
+
using DataModel::DiffablePrimitive
|
10
|
+
|
11
|
+
ARRAY_RE = Regexp.compile(/\[(\d+)\]/)
|
12
|
+
|
13
|
+
attribute :properties, Strict::Array.member(Property).default([]) # Properties.optional
|
14
|
+
attribute :metadata, Metadata.optional
|
15
|
+
attribute :elements, Strict::Array.member(Element).default([])
|
16
|
+
attribute :relationships, Strict::Array.member(Relationship).default([])
|
17
|
+
attribute :organizations, Strict::Array.member(Organization).default([])
|
18
|
+
attribute :property_definitions, Strict::Array.member(PropertyDefinition).default([])
|
19
|
+
attribute :version, Strict::String.optional
|
20
|
+
attribute :diagrams, Strict::Array.member(Diagram).default([])
|
21
|
+
attribute :viewpoints, Strict::Array.member(Viewpoint).default([])
|
22
|
+
# Following attributes are to hold info on where the model came from
|
23
|
+
attribute :filename, Strict::String.optional
|
24
|
+
attribute :file_format, Strict::Symbol.enum(*Archimate::SUPPORTED_FORMATS).optional
|
25
|
+
attribute :archimate_version, Strict::Symbol.default(:archimate_3_0).enum(*Archimate::ARCHIMATE_VERSIONS)
|
26
|
+
|
27
|
+
attribute :namespaces, Strict::Hash.default({})
|
28
|
+
attribute :schema_locations, Strict::Array.member(Strict::String).default([])
|
29
|
+
|
30
|
+
def initialize(attributes)
|
31
|
+
super
|
32
|
+
self.in_model = self
|
33
|
+
self.parent = nil
|
34
|
+
rebuild_index
|
35
|
+
end
|
36
|
+
|
37
|
+
def with(options = {})
|
38
|
+
super.organize
|
39
|
+
end
|
40
|
+
|
41
|
+
def lookup(id)
|
42
|
+
rebuild_index(id) unless @index_hash.include?(id)
|
43
|
+
@index_hash[id]
|
44
|
+
end
|
45
|
+
|
46
|
+
def entities
|
47
|
+
@index_hash.values
|
48
|
+
end
|
49
|
+
|
50
|
+
def rebuild_index(missing_id = :model_creation_event)
|
51
|
+
return self unless missing_id
|
52
|
+
@index_hash = build_index
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def register(node, parent)
|
57
|
+
node.in_model = self
|
58
|
+
node.parent = parent
|
59
|
+
@index_hash[node.id] = node
|
60
|
+
end
|
61
|
+
|
62
|
+
def deregister(node)
|
63
|
+
@index_hash.delete(node.id)
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_by_class(klass)
|
67
|
+
@index_hash.values.select { |item| item.is_a?(klass) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
"#{Archimate::Color.data_model('Model')}<#{id}>[#{Archimate::Color.color(name, [:white, :underline])}]"
|
72
|
+
end
|
73
|
+
|
74
|
+
# TODO: make these DSL like things added dynamically
|
75
|
+
def application_components
|
76
|
+
elements.select { |element| element.type == "ApplicationComponent" }
|
77
|
+
end
|
78
|
+
|
79
|
+
def element_type_names
|
80
|
+
elements.map(&:type).uniq
|
81
|
+
end
|
82
|
+
|
83
|
+
def elements_with_type(el_type)
|
84
|
+
elements.select { |element| element.type == el_type }
|
85
|
+
end
|
86
|
+
|
87
|
+
# TODO: make these DSL like things added dynamically
|
88
|
+
def all_properties
|
89
|
+
@index_hash.values.each_with_object([]) do |i, a|
|
90
|
+
a.concat(i.properties) if i.respond_to?(:properties)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# TODO: refactor to use property def structure instead of separate property objects
|
95
|
+
def property_keys
|
96
|
+
all_properties.map(&:key).uniq
|
97
|
+
end
|
98
|
+
|
99
|
+
# TODO: refactor to use property def structure instead of separate property objects
|
100
|
+
def property_def_id(key)
|
101
|
+
"propid-#{property_keys.index(key) + 1}"
|
102
|
+
end
|
103
|
+
|
104
|
+
# Iterate through the model and ensure that elements, relationships, and
|
105
|
+
# diagrams are all present in the model's organizations. If an item is missing
|
106
|
+
# then move it into the default top-level element for the item type.
|
107
|
+
def organize
|
108
|
+
[]
|
109
|
+
.concat(elements)
|
110
|
+
.concat(relationships)
|
111
|
+
.concat(diagrams).each do |item|
|
112
|
+
if find_in_organizations(item).nil?
|
113
|
+
default_organization = default_organization_for(item)
|
114
|
+
default_organization.items.push(item.id) unless default_organization.items.include?(item.id)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
def find_in_organizations(item, _fs = nil)
|
121
|
+
result = find_by_class(DataModel::Organization).select { |f| f.items.include?(item.id) }
|
122
|
+
# raise "Program Error! #{item.id} is located in more than one organization. #{result.map(&:to_s).inspect}\n#{item}\n" if result.size > 1
|
123
|
+
result.empty? ? nil : result.first
|
124
|
+
end
|
125
|
+
|
126
|
+
def default_organization_for(item)
|
127
|
+
case item
|
128
|
+
when Element
|
129
|
+
case item.layer
|
130
|
+
when "Strategy"
|
131
|
+
find_default_organization("strategy", "Strategy")
|
132
|
+
when "Business"
|
133
|
+
find_default_organization("business", "Business")
|
134
|
+
when "Application"
|
135
|
+
find_default_organization("application", "Application")
|
136
|
+
when "Technology"
|
137
|
+
find_default_organization("technology", "Technology")
|
138
|
+
when "Physical"
|
139
|
+
find_default_organization("physical", "Physical")
|
140
|
+
when "Motivation"
|
141
|
+
find_default_organization("motivation", "Motivation")
|
142
|
+
when "Implementation and Migration"
|
143
|
+
find_default_organization("implementation_migration", "Implementation & Migration")
|
144
|
+
when "Connectors"
|
145
|
+
find_default_organization("connectors", "Connectors")
|
146
|
+
else
|
147
|
+
raise StandardError, "Unexpected Element Layer: #{item.layer.inspect} for item type #{item.type.inspect}"
|
148
|
+
end
|
149
|
+
when Relationship
|
150
|
+
find_default_organization("relations", "Relations")
|
151
|
+
when Diagram
|
152
|
+
find_default_organization("diagrams", "Views")
|
153
|
+
else
|
154
|
+
raise StandardError, "Unexpected item type #{item.class}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def find_default_organization(type, name)
|
159
|
+
result = organizations.find { |f| f.type == type }
|
160
|
+
return result unless result.nil?
|
161
|
+
result = organizations.find { |f| f.name == name }
|
162
|
+
return result unless result.nil?
|
163
|
+
add_organization(type, name)
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_organization(type, name)
|
167
|
+
raise "Program Error: #{organizations.inspect}" unless organizations.none? { |f| f.type == type || f.name == name }
|
168
|
+
organization = Organization.new(id: make_unique_id, name: name, type: type, items: [], organizations: [])
|
169
|
+
register(organization, organizations)
|
170
|
+
organizations.push(organization)
|
171
|
+
organization
|
172
|
+
end
|
173
|
+
|
174
|
+
def make_unique_id
|
175
|
+
unique_id = random_id
|
176
|
+
unique_id = random_id while @index_hash.key?(unique_id)
|
177
|
+
unique_id
|
178
|
+
end
|
179
|
+
|
180
|
+
def referenced_identified_nodes
|
181
|
+
super.uniq
|
182
|
+
end
|
183
|
+
|
184
|
+
def identified_nodes
|
185
|
+
@index_hash.values.select { |node| node.is_a? Referenceable }
|
186
|
+
end
|
187
|
+
|
188
|
+
def unreferenced_nodes
|
189
|
+
identified_nodes - referenced_identified_nodes
|
190
|
+
end
|
191
|
+
|
192
|
+
def merge_entities(master_entity, copies)
|
193
|
+
copies.delete(master_entity)
|
194
|
+
copies.each do |copy|
|
195
|
+
entities.each do |entity|
|
196
|
+
case entity
|
197
|
+
when entity == master_entity
|
198
|
+
master_entity.merge(copy)
|
199
|
+
when Organization
|
200
|
+
entity.remove(copy.id)
|
201
|
+
when ViewNode, Relationship, Connection
|
202
|
+
entity.replace(copy, master_entity)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
deregister(copy)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
private
|
210
|
+
|
211
|
+
def random_id
|
212
|
+
@random ||= Random.new
|
213
|
+
format("%08x", @random.rand(0xffffffff))
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
# This is a set of notes to the modeler on how to use and model with this viewpoint. Could contain rules
|
6
|
+
# or constraints. The part hold the information for this element.
|
7
|
+
class ModelingNote < ArchimateNode
|
8
|
+
attribute :documentation, DocumentationGroup # .constrained(min_size: 1)
|
9
|
+
# `type` attribute expresses a type for the notes, e.g. OCL for OCL rules.
|
10
|
+
attribute :type, Strict::String.optional
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
class NamedReferenceable < Referenceable
|
6
|
+
# Note: minimum 1 name is required for a Named Referenceable
|
7
|
+
# attribute :name, Strict::Array.member(LangString).default([]) .constrained(min_size: 1)
|
8
|
+
# attribute :documentation, DocumentationGroup
|
9
|
+
# attribute :grp_any, Strict::Array.member(AnyGroup).default([])
|
10
|
+
end
|
11
|
+
|
12
|
+
Dry::Types.register_class(NamedReferenceable)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Archimate
|
3
|
+
module DataModel
|
4
|
+
# An organization element represents a structural node in a particular organization of the model concepts.
|
5
|
+
# An organization element may be a parent or sibling of other organization elements,
|
6
|
+
# each one representing a unique structural node.
|
7
|
+
#
|
8
|
+
# An organization element may reference an ArchiMate element, ArchiMate relationship,
|
9
|
+
# or nothing (in which case it is a structural container)
|
10
|
+
#
|
11
|
+
# An organization has no meaning unless it has at least child organization element.
|
12
|
+
#
|
13
|
+
# Note that Organization must fit into a tree structure (so strictly nested).
|
14
|
+
class Organization < ArchimateNode # was Referenceable
|
15
|
+
attribute :id, Identifier.optional # .constrained(format: /[[[:alpha:]]_][w-.]*/)
|
16
|
+
attribute :name, LangString.optional # LabelGroup in the XSD, TODO: this is a LangString collection
|
17
|
+
attribute :type, Strict::String.optional # I believe this is used only for Archi formats
|
18
|
+
attribute :documentation, DocumentationGroup
|
19
|
+
attribute :items, Strict::Array.member(Identifier).default([]) # TODO: Convert this to referenceable
|
20
|
+
attribute :organizations, Strict::Array.member(Organization).default([]) # item in the XSD
|
21
|
+
# attribute :other_elements, Strict::Array.member(AnyElement).default([])
|
22
|
+
# attribute :other_attributes, Strict::Array.member(AnyAttribute).default([])
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"#{Archimate::Color.data_model('Organization')}<#{id}>[#{Archimate::Color.color(name, [:white, :underline])}]"
|
26
|
+
end
|
27
|
+
|
28
|
+
def referenced_identified_nodes
|
29
|
+
organizations.reduce(items) do |a, e|
|
30
|
+
a.concat(e.referenced_identified_nodes)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove(id)
|
35
|
+
items.delete(id)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
Dry::Types.register_class(Organization)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Archimate
|
3
|
+
module DataModel
|
4
|
+
# A Property instance type declaring the reference to a Property definition and containing the Property value.
|
5
|
+
class Property < ArchimateNode
|
6
|
+
attribute :values, Strict::Array.member(LangString).default([]) # .constrained(min_size: 1)
|
7
|
+
attribute :property_definition, PropertyDefinition
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"Property(key: #{property_definition.name}, value: #{value || 'no value'})"
|
11
|
+
end
|
12
|
+
|
13
|
+
def key
|
14
|
+
property_definition.name
|
15
|
+
end
|
16
|
+
|
17
|
+
def value
|
18
|
+
values.first
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Dry::Types.register_class(Property)
|
23
|
+
PropertiesList = Strict::Array.member(Property).default([])
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
# A Property definition type containing its unique identifier, name, and data type.
|
6
|
+
class PropertyDefinition < NamedReferenceable
|
7
|
+
attribute :value_type, DataType
|
8
|
+
|
9
|
+
def self.identifier_for_key(key)
|
10
|
+
(self.class.hash ^ key.hash).to_s(16)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Dry::Types.register_class(PropertyDefinition)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
# Something that can be referenced in the model.
|
6
|
+
class Referenceable < ArchimateNode
|
7
|
+
attribute :id, Identifier
|
8
|
+
attribute :name, LangString.optional # TODO: Strict::Array.member(LangString).constrained(min_size: 1)
|
9
|
+
|
10
|
+
attribute :documentation, DocumentationGroup
|
11
|
+
# attribute :grp_any, Strict::Array.member(AnyNode).default([])
|
12
|
+
# attribute :other_attributes, Strict::Array.member(AnyAttribute).default([])
|
13
|
+
# attribute :properties, PropertiesList # Note: Referenceable doesn't have properties in the spec
|
14
|
+
attribute :type, Strict::String.optional # Note: type here was used for the Element/Relationship/Diagram type
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def find_my_index
|
19
|
+
id
|
20
|
+
end
|
21
|
+
|
22
|
+
# name isn't merged
|
23
|
+
def merge(node)
|
24
|
+
documentation.concat(node.documentation)
|
25
|
+
properties.concat(node.properties)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
RelationshipTypeEnum = %w[
|
6
|
+
Composition
|
7
|
+
Aggregation
|
8
|
+
Assignment
|
9
|
+
Realization
|
10
|
+
Serving
|
11
|
+
Access
|
12
|
+
Influence
|
13
|
+
Triggering
|
14
|
+
Flow
|
15
|
+
Specialization
|
16
|
+
Association
|
17
|
+
].freeze
|
18
|
+
RelationshipType = Strict::String.enum(*RelationshipTypeEnum)
|
19
|
+
AllowedRelationshipTypes = Strict::Array.member(RelationshipType).default([])
|
20
|
+
|
21
|
+
AccessType = %w[Access Read Write ReadWrite]
|
22
|
+
AccessTypeEnum = Strict::String.enum(*AccessType)
|
23
|
+
|
24
|
+
# A base relationship type that can be extended by concrete ArchiMate types.
|
25
|
+
#
|
26
|
+
# Note that RelationshipType is abstract, so one must have derived types of this type. this is indicated in xml
|
27
|
+
# by having a tag name of "relationship" and an attribute of xsi:type="AccessRelationship" where AccessRelationship is
|
28
|
+
# a derived type from RelationshipType.
|
29
|
+
class Relationship < Concept
|
30
|
+
attribute :source, Identifier
|
31
|
+
attribute :target, Identifier
|
32
|
+
attribute :access_type, AccessTypeEnum.optional
|
33
|
+
|
34
|
+
def replace(entity, with_entity)
|
35
|
+
@source = with_entity.id if source == entity.id
|
36
|
+
@target = with_entity.id if target == entity.id
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
Archimate::Color.color(
|
41
|
+
"#{Archimate::Color.data_model(type)}<#{id}>[#{Archimate::Color.color(name&.strip || '', %i[black underline])}]",
|
42
|
+
:on_light_magenta
|
43
|
+
) + " #{source_element} -> #{target_element}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def description
|
47
|
+
[
|
48
|
+
name.nil? ? nil : "#{name}:",
|
49
|
+
FileFormats::ArchimateV2::RELATION_VERBS.fetch(type, nil)
|
50
|
+
].compact.join(" ")
|
51
|
+
end
|
52
|
+
|
53
|
+
def referenced_identified_nodes
|
54
|
+
[@source, @target].compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def source_element
|
58
|
+
element_by_id(source)
|
59
|
+
end
|
60
|
+
|
61
|
+
def target_element
|
62
|
+
element_by_id(target)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Diagrams that this element is referenced in.
|
66
|
+
def diagrams
|
67
|
+
@diagrams ||= in_model.diagrams.select do |diagram|
|
68
|
+
diagram.relationship_ids.include?(id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Copy any attributes/docs, etc. from each of the others into the original.
|
73
|
+
# 1. Child `label`s with different `xml:lang` attribute values
|
74
|
+
# 2. Child `documentation` (and different `xml:lang` attribute values)
|
75
|
+
# 3. Child `properties`
|
76
|
+
# 4. Any other elements
|
77
|
+
# source and target don't change on a merge
|
78
|
+
def merge(relationship)
|
79
|
+
super
|
80
|
+
access_type ||= relationship.access_type
|
81
|
+
end
|
82
|
+
end
|
83
|
+
Dry::Types.register_class(Relationship)
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
class SchemaInfo < ArchimateNode
|
6
|
+
using DiffablePrimitive
|
7
|
+
|
8
|
+
attribute :schema, Strict::String.optional
|
9
|
+
attribute :schemaversion, Strict::String.optional
|
10
|
+
attribute :elements, Strict::Array.member(AnyElement).default([])
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"#{type.light_black}[#{schema} #{schemaversion}]"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
Dry::Types.register_class(SchemaInfo)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Archimate
|
3
|
+
module DataModel
|
4
|
+
class Style < ArchimateNode
|
5
|
+
attribute :text_alignment, Coercible::Int.optional # TODO: make this an enum
|
6
|
+
attribute :fill_color, Color.optional
|
7
|
+
attribute :line_color, Color.optional
|
8
|
+
attribute :font_color, Color.optional # TODO: move this to font
|
9
|
+
attribute :line_width, Coercible::Int.optional
|
10
|
+
attribute :font, Font.optional
|
11
|
+
attribute :text_position, Coercible::Int.optional # TODO: make this an enum
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
attr_name_vals = struct_instance_variables.map { |k| "#{k}: #{self[k]}" }.join(", ")
|
15
|
+
"Style(#{attr_name_vals})"
|
16
|
+
end
|
17
|
+
|
18
|
+
def text_align
|
19
|
+
case text_alignment
|
20
|
+
when "1"
|
21
|
+
"left"
|
22
|
+
when "2"
|
23
|
+
"center"
|
24
|
+
when "3"
|
25
|
+
"right"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Dry::Types.register_class(Style)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
# This is a container for all of the Views in the model.
|
6
|
+
class View < NamedReferenceable
|
7
|
+
attribute :properties, PropertiesList
|
8
|
+
attribute :viewpoint_type, Strict::String.optional # TODO: ViewpointType.optional is better, but is ArchiMate version dependent. Need to figure that out
|
9
|
+
attribute :viewpoint, Viewpoint.optional
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Archimate
|
4
|
+
module DataModel
|
5
|
+
# This is an abstract super-type of Node and Connection.
|
6
|
+
class ViewConcept < ArchimateNode
|
7
|
+
attribute :id, Identifier
|
8
|
+
attribute :labels, Strict::Array.member(LangString).constrained(min_size: 1)
|
9
|
+
attribute :documentation, DocumentationGroup
|
10
|
+
attribute :style, Style.optional
|
11
|
+
# the "viewRef" of an "Concept" is to a view that allows drill-down diagrams.
|
12
|
+
attribute :view_refs, Strict::Array.member(Identifier)
|
13
|
+
# TODO: any other attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
Dry::Types.register_class(ViewConcept)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Archimate
|
3
|
+
module DataModel
|
4
|
+
PositiveInteger = Strict::Int.constrained(gt: 0)
|
5
|
+
|
6
|
+
# Graphical node type. It can contain child node types.
|
7
|
+
# TODO: This is ViewNodeType in the v3 XSD
|
8
|
+
class ViewNode < Referenceable # < ViewConcept
|
9
|
+
using DiffableArray
|
10
|
+
|
11
|
+
# LocationGroup: TODO: Consider making this a mixin or extract object
|
12
|
+
# The x (towards the right, associated with width) attribute from the Top,Left (i.e. 0,0)
|
13
|
+
# corner of the diagram to the Top, Left corner of the bounding box of the concept.
|
14
|
+
# attribute :x, NonNegativeInteger
|
15
|
+
# The y (towards the bottom, associated with height) attribute from the Top,Left (i.e. 0,0)
|
16
|
+
# corner of the diagram to the Top, Left corner of the bounding box of the concept.
|
17
|
+
# attribute :y, NonNegativeInteger
|
18
|
+
|
19
|
+
# SizeGroup:
|
20
|
+
# The width (associated with x) attribute from the Left side to the right side of the
|
21
|
+
# bounding box of a concept.
|
22
|
+
# attribute :w, PositiveInteger
|
23
|
+
# The height (associated with y) attribute from the top side to the bottom side of the
|
24
|
+
# bounding box of a concept.
|
25
|
+
# attribute :h, PositiveInteger
|
26
|
+
|
27
|
+
attribute :model, Identifier.optional
|
28
|
+
attribute :content, Strict::String.optional
|
29
|
+
attribute :target_connections, Strict::Array.member(Identifier).default([])
|
30
|
+
attribute :archimate_element, Identifier.optional
|
31
|
+
attribute :bounds, Bounds.optional
|
32
|
+
attribute :nodes, Strict::Array.member(ViewNode).default([])
|
33
|
+
attribute :connections, ConnectionList
|
34
|
+
attribute :style, Style.optional
|
35
|
+
attribute :type, Strict::String.optional
|
36
|
+
attribute :child_type, Coercible::Int.optional
|
37
|
+
attribute :properties, PropertiesList # Note: this is not in the model under element
|
38
|
+
# it's added under Real Element
|
39
|
+
|
40
|
+
def replace(entity, with_entity)
|
41
|
+
if (archimate_element == entity.id)
|
42
|
+
@archimate_element = with_entity.id
|
43
|
+
@element = with_entity
|
44
|
+
end
|
45
|
+
if (model == entity.id)
|
46
|
+
@model = with_entity.id
|
47
|
+
@model_element = with_entity
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
"ViewNode[#{name || ''}](#{in_model.lookup(archimate_element) if archimate_element && in_model})"
|
53
|
+
end
|
54
|
+
|
55
|
+
def description
|
56
|
+
[
|
57
|
+
name.nil? ? nil : name.to_s,
|
58
|
+
element.nil? ? nil : element.name,
|
59
|
+
element&.type.nil? ? nil : "(#{element.type})"
|
60
|
+
].compact.join(" ")
|
61
|
+
end
|
62
|
+
|
63
|
+
def element
|
64
|
+
@element ||= in_model.lookup(archimate_element)
|
65
|
+
end
|
66
|
+
|
67
|
+
def model_element
|
68
|
+
@model_element ||= in_model.lookup(model)
|
69
|
+
end
|
70
|
+
|
71
|
+
def all_nodes
|
72
|
+
nodes.inject(Array.new(nodes)) { |child_ary, child| child_ary.concat(child.all_nodes) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def child_id_hash
|
76
|
+
nodes.each_with_object(id => self) { |i, a| a.merge!(i.child_id_hash) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def referenced_identified_nodes
|
80
|
+
(nodes + connections).reduce(
|
81
|
+
(target_connections + [archimate_element]).compact
|
82
|
+
) do |a, e|
|
83
|
+
a.concat(e.referenced_identified_nodes)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def in_diagram
|
88
|
+
@diagram ||= ->(node) { node = node.parent until node.nil? || node.is_a?(Diagram) }.call(self)
|
89
|
+
end
|
90
|
+
|
91
|
+
# TODO: Is this true for all or only Archi models?
|
92
|
+
def absolute_position
|
93
|
+
offset = bounds || Archimate::DataModel::Bounds.zero
|
94
|
+
el = parent.parent
|
95
|
+
while el.respond_to?(:bounds) && el.bounds
|
96
|
+
bounds = el.bounds
|
97
|
+
offset = offset.with(x: (offset.x || 0) + (bounds.x || 0), y: (offset.y || 0) + (bounds.y || 0))
|
98
|
+
el = el.parent.parent
|
99
|
+
end
|
100
|
+
offset
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Dry::Types.register_class(ViewNode)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Type is one of: ["archimate:DiagramModelReference", "archimate:Group", "archimate:DiagramObject"]
|
109
|
+
# textAlignment "2"
|
110
|
+
# model is on only type of archimate:DiagramModelReference and is id of another element type=archimate:ArchimateDiagramModel
|
111
|
+
# fillColor, lineColor, fontColor are web hex colors
|
112
|
+
# targetConnections is a string of space separated ids to connections on diagram objects found on DiagramObject
|
113
|
+
# archimateElement is an id of a model element found on DiagramObject types
|
114
|
+
# font is of this form: font="1|Arial|14.0|0|WINDOWS|1|0|0|0|0|0|0|0|0|1|0|0|0|0|Arial"
|