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.
- 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"
|