archimate 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.projectile +18 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +4 -0
  6. data/.yardocs +15 -0
  7. data/Gemfile +5 -0
  8. data/Guardfile +27 -0
  9. data/LICENSE +201 -0
  10. data/README.md +94 -0
  11. data/Rakefile +29 -0
  12. data/TODOs.org +286 -0
  13. data/archimate.gemspec +51 -0
  14. data/bin/archimate +17 -0
  15. data/bin/console +13 -0
  16. data/bin/setup +8 -0
  17. data/exe/archidiff +7 -0
  18. data/exe/archidiff-summary +7 -0
  19. data/exe/archimate +7 -0
  20. data/exe/archimerge +7 -0
  21. data/exe/fmtxml +7 -0
  22. data/lib/archimate/cli/archi.rb +189 -0
  23. data/lib/archimate/cli/cleanup.rb +54 -0
  24. data/lib/archimate/cli/conflict_resolver.rb +39 -0
  25. data/lib/archimate/cli/convert.rb +39 -0
  26. data/lib/archimate/cli/diff.rb +31 -0
  27. data/lib/archimate/cli/diff_summary.rb +101 -0
  28. data/lib/archimate/cli/duper.rb +85 -0
  29. data/lib/archimate/cli/lint.rb +16 -0
  30. data/lib/archimate/cli/mapper.rb +82 -0
  31. data/lib/archimate/cli/merge.rb +49 -0
  32. data/lib/archimate/cli/merger.rb +109 -0
  33. data/lib/archimate/cli/stats.rb +42 -0
  34. data/lib/archimate/cli/svger.rb +40 -0
  35. data/lib/archimate/color.rb +53 -0
  36. data/lib/archimate/config.rb +35 -0
  37. data/lib/archimate/data_model/any_attribute.rb +13 -0
  38. data/lib/archimate/data_model/any_element.rb +15 -0
  39. data/lib/archimate/data_model/archimate_node.rb +181 -0
  40. data/lib/archimate/data_model/bounds.rb +72 -0
  41. data/lib/archimate/data_model/color.rb +47 -0
  42. data/lib/archimate/data_model/concept.rb +14 -0
  43. data/lib/archimate/data_model/concern.rb +17 -0
  44. data/lib/archimate/data_model/connection.rb +107 -0
  45. data/lib/archimate/data_model/constants.rb +82 -0
  46. data/lib/archimate/data_model/container.rb +17 -0
  47. data/lib/archimate/data_model/diagram.rb +40 -0
  48. data/lib/archimate/data_model/diffable_array.rb +213 -0
  49. data/lib/archimate/data_model/diffable_primitive.rb +83 -0
  50. data/lib/archimate/data_model/documentation.rb +14 -0
  51. data/lib/archimate/data_model/element.rb +87 -0
  52. data/lib/archimate/data_model/font.rb +54 -0
  53. data/lib/archimate/data_model/label.rb +19 -0
  54. data/lib/archimate/data_model/lang_string.rb +41 -0
  55. data/lib/archimate/data_model/location.rb +31 -0
  56. data/lib/archimate/data_model/metadata.rb +14 -0
  57. data/lib/archimate/data_model/model.rb +217 -0
  58. data/lib/archimate/data_model/modeling_note.rb +13 -0
  59. data/lib/archimate/data_model/named_referenceable.rb +14 -0
  60. data/lib/archimate/data_model/organization.rb +40 -0
  61. data/lib/archimate/data_model/property.rb +25 -0
  62. data/lib/archimate/data_model/property_definition.rb +16 -0
  63. data/lib/archimate/data_model/referenceable.rb +29 -0
  64. data/lib/archimate/data_model/relationship.rb +85 -0
  65. data/lib/archimate/data_model/schema_info.rb +18 -0
  66. data/lib/archimate/data_model/style.rb +32 -0
  67. data/lib/archimate/data_model/view.rb +12 -0
  68. data/lib/archimate/data_model/view_concept.rb +18 -0
  69. data/lib/archimate/data_model/view_node.rb +114 -0
  70. data/lib/archimate/data_model/viewpoint.rb +87 -0
  71. data/lib/archimate/data_model.rb +54 -0
  72. data/lib/archimate/diff/archimate_array_reference.rb +113 -0
  73. data/lib/archimate/diff/archimate_identified_node_reference.rb +41 -0
  74. data/lib/archimate/diff/archimate_node_attribute_reference.rb +70 -0
  75. data/lib/archimate/diff/archimate_node_reference.rb +80 -0
  76. data/lib/archimate/diff/change.rb +49 -0
  77. data/lib/archimate/diff/conflict.rb +31 -0
  78. data/lib/archimate/diff/conflicts/base_conflict.rb +53 -0
  79. data/lib/archimate/diff/conflicts/deleted_items_child_updated_conflict.rb +30 -0
  80. data/lib/archimate/diff/conflicts/deleted_items_referenced_conflict.rb +63 -0
  81. data/lib/archimate/diff/conflicts/path_conflict.rb +51 -0
  82. data/lib/archimate/diff/conflicts.rb +89 -0
  83. data/lib/archimate/diff/delete.rb +41 -0
  84. data/lib/archimate/diff/difference.rb +113 -0
  85. data/lib/archimate/diff/insert.rb +43 -0
  86. data/lib/archimate/diff/merge.rb +70 -0
  87. data/lib/archimate/diff/move.rb +51 -0
  88. data/lib/archimate/diff.rb +17 -0
  89. data/lib/archimate/export/csv_export.rb +32 -0
  90. data/lib/archimate/export/cypher.rb +171 -0
  91. data/lib/archimate/export/graph_ml.rb +131 -0
  92. data/lib/archimate/export/n_quads.rb +142 -0
  93. data/lib/archimate/file_format.rb +30 -0
  94. data/lib/archimate/file_formats/archi_file_format.rb +151 -0
  95. data/lib/archimate/file_formats/archi_file_reader.rb +252 -0
  96. data/lib/archimate/file_formats/archi_file_writer.rb +230 -0
  97. data/lib/archimate/file_formats/archimate_v2.rb +461 -0
  98. data/lib/archimate/file_formats/model_exchange_file/xml_lang_string.rb +35 -0
  99. data/lib/archimate/file_formats/model_exchange_file/xml_metadata.rb +115 -0
  100. data/lib/archimate/file_formats/model_exchange_file/xml_property_definitions.rb +28 -0
  101. data/lib/archimate/file_formats/model_exchange_file/xml_property_defs.rb +27 -0
  102. data/lib/archimate/file_formats/model_exchange_file_reader.rb +237 -0
  103. data/lib/archimate/file_formats/model_exchange_file_reader_21.rb +73 -0
  104. data/lib/archimate/file_formats/model_exchange_file_reader_30.rb +134 -0
  105. data/lib/archimate/file_formats/model_exchange_file_writer.rb +157 -0
  106. data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +143 -0
  107. data/lib/archimate/file_formats/model_exchange_file_writer_30.rb +153 -0
  108. data/lib/archimate/file_formats/writer.rb +56 -0
  109. data/lib/archimate/lint/duplicate_entities.rb +121 -0
  110. data/lib/archimate/lint/linter.rb +146 -0
  111. data/lib/archimate/logging.rb +55 -0
  112. data/lib/archimate/maybe_io.rb +34 -0
  113. data/lib/archimate/progress_indicator.rb +29 -0
  114. data/lib/archimate/svg/archimate.css +232 -0
  115. data/lib/archimate/svg/child.rb +29 -0
  116. data/lib/archimate/svg/connection.rb +184 -0
  117. data/lib/archimate/svg/css_style.rb +31 -0
  118. data/lib/archimate/svg/diagram.rb +87 -0
  119. data/lib/archimate/svg/entity/and_junction.rb +14 -0
  120. data/lib/archimate/svg/entity/application_collaboration.rb +14 -0
  121. data/lib/archimate/svg/entity/application_component.rb +41 -0
  122. data/lib/archimate/svg/entity/application_event.rb +13 -0
  123. data/lib/archimate/svg/entity/application_function.rb +13 -0
  124. data/lib/archimate/svg/entity/application_interaction.rb +13 -0
  125. data/lib/archimate/svg/entity/application_interface.rb +13 -0
  126. data/lib/archimate/svg/entity/application_process.rb +13 -0
  127. data/lib/archimate/svg/entity/application_service.rb +13 -0
  128. data/lib/archimate/svg/entity/artifact.rb +39 -0
  129. data/lib/archimate/svg/entity/assessment.rb +14 -0
  130. data/lib/archimate/svg/entity/base_entity.rb +128 -0
  131. data/lib/archimate/svg/entity/business_actor.rb +14 -0
  132. data/lib/archimate/svg/entity/business_collaboration.rb +14 -0
  133. data/lib/archimate/svg/entity/business_event.rb +10 -0
  134. data/lib/archimate/svg/entity/business_function.rb +13 -0
  135. data/lib/archimate/svg/entity/business_interaction.rb +13 -0
  136. data/lib/archimate/svg/entity/business_interface.rb +13 -0
  137. data/lib/archimate/svg/entity/business_object.rb +13 -0
  138. data/lib/archimate/svg/entity/business_process.rb +13 -0
  139. data/lib/archimate/svg/entity/business_role.rb +14 -0
  140. data/lib/archimate/svg/entity/business_service.rb +13 -0
  141. data/lib/archimate/svg/entity/capability.rb +14 -0
  142. data/lib/archimate/svg/entity/communication_network.rb +14 -0
  143. data/lib/archimate/svg/entity/communication_path.rb +14 -0
  144. data/lib/archimate/svg/entity/constraint.rb +15 -0
  145. data/lib/archimate/svg/entity/contract.rb +13 -0
  146. data/lib/archimate/svg/entity/course_of_action.rb +14 -0
  147. data/lib/archimate/svg/entity/data_entity.rb +29 -0
  148. data/lib/archimate/svg/entity/data_object.rb +13 -0
  149. data/lib/archimate/svg/entity/deliverable.rb +13 -0
  150. data/lib/archimate/svg/entity/device.rb +48 -0
  151. data/lib/archimate/svg/entity/diagram_model_reference.rb +22 -0
  152. data/lib/archimate/svg/entity/diagram_object.rb +30 -0
  153. data/lib/archimate/svg/entity/distribution_network.rb +14 -0
  154. data/lib/archimate/svg/entity/driver.rb +14 -0
  155. data/lib/archimate/svg/entity/equipment.rb +16 -0
  156. data/lib/archimate/svg/entity/event_entity.rb +36 -0
  157. data/lib/archimate/svg/entity/facility.rb +16 -0
  158. data/lib/archimate/svg/entity/function_entity.rb +14 -0
  159. data/lib/archimate/svg/entity/gap.rb +21 -0
  160. data/lib/archimate/svg/entity/goal.rb +14 -0
  161. data/lib/archimate/svg/entity/group.rb +24 -0
  162. data/lib/archimate/svg/entity/implementation_event.rb +13 -0
  163. data/lib/archimate/svg/entity/infrastructure_function.rb +13 -0
  164. data/lib/archimate/svg/entity/infrastructure_interface.rb +13 -0
  165. data/lib/archimate/svg/entity/infrastructure_service.rb +13 -0
  166. data/lib/archimate/svg/entity/interaction_entity.rb +14 -0
  167. data/lib/archimate/svg/entity/interface_entity.rb +35 -0
  168. data/lib/archimate/svg/entity/junction.rb +19 -0
  169. data/lib/archimate/svg/entity/location.rb +14 -0
  170. data/lib/archimate/svg/entity/material.rb +14 -0
  171. data/lib/archimate/svg/entity/meaning.rb +40 -0
  172. data/lib/archimate/svg/entity/motivation_entity.rb +40 -0
  173. data/lib/archimate/svg/entity/network.rb +14 -0
  174. data/lib/archimate/svg/entity/node.rb +33 -0
  175. data/lib/archimate/svg/entity/node_shape.rb +64 -0
  176. data/lib/archimate/svg/entity/note.rb +30 -0
  177. data/lib/archimate/svg/entity/or_junction.rb +14 -0
  178. data/lib/archimate/svg/entity/outcome.rb +15 -0
  179. data/lib/archimate/svg/entity/path.rb +14 -0
  180. data/lib/archimate/svg/entity/plateau.rb +15 -0
  181. data/lib/archimate/svg/entity/principle.rb +15 -0
  182. data/lib/archimate/svg/entity/process_entity.rb +63 -0
  183. data/lib/archimate/svg/entity/product.rb +20 -0
  184. data/lib/archimate/svg/entity/rect.rb +13 -0
  185. data/lib/archimate/svg/entity/rect_entity.rb +25 -0
  186. data/lib/archimate/svg/entity/representation.rb +31 -0
  187. data/lib/archimate/svg/entity/requirement.rb +15 -0
  188. data/lib/archimate/svg/entity/resource.rb +14 -0
  189. data/lib/archimate/svg/entity/rounded_rect_entity.rb +23 -0
  190. data/lib/archimate/svg/entity/service_entity.rb +51 -0
  191. data/lib/archimate/svg/entity/sketch_model_sticky.rb +14 -0
  192. data/lib/archimate/svg/entity/stakeholder.rb +15 -0
  193. data/lib/archimate/svg/entity/system_software.rb +14 -0
  194. data/lib/archimate/svg/entity/technology_collaboration.rb +14 -0
  195. data/lib/archimate/svg/entity/technology_event.rb +13 -0
  196. data/lib/archimate/svg/entity/technology_function.rb +13 -0
  197. data/lib/archimate/svg/entity/technology_interaction.rb +13 -0
  198. data/lib/archimate/svg/entity/technology_interface.rb +13 -0
  199. data/lib/archimate/svg/entity/technology_process.rb +13 -0
  200. data/lib/archimate/svg/entity/technology_service.rb +13 -0
  201. data/lib/archimate/svg/entity/value.rb +27 -0
  202. data/lib/archimate/svg/entity/work_package.rb +14 -0
  203. data/lib/archimate/svg/entity.rb +93 -0
  204. data/lib/archimate/svg/entity_factory.rb +17 -0
  205. data/lib/archimate/svg/extents.rb +27 -0
  206. data/lib/archimate/svg/point.rb +7 -0
  207. data/lib/archimate/svg/svg_template.rb +27 -0
  208. data/lib/archimate/svg/svg_template.svg.erb +169 -0
  209. data/lib/archimate/version.rb +4 -0
  210. data/lib/archimate.rb +114 -0
  211. 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"