archimate 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"