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,237 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
|
|
4
|
+
module Archimate
|
|
5
|
+
module FileFormats
|
|
6
|
+
# This class implements common methods for the ArchiMate Model Exchange Format
|
|
7
|
+
class ModelExchangeFileReader
|
|
8
|
+
# Parses a Nokogiri document into an Archimate::Model
|
|
9
|
+
def parse(doc)
|
|
10
|
+
return unless doc
|
|
11
|
+
@property_defs = []
|
|
12
|
+
@viewpoints = []
|
|
13
|
+
parse_model(doc.root)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def parse_model(root)
|
|
17
|
+
@property_defs = parse_property_defs(root)
|
|
18
|
+
@viewpoints = parse_viewpoints(root)
|
|
19
|
+
DataModel::Model.new(
|
|
20
|
+
index_hash: {},
|
|
21
|
+
id: identifier_to_id(root["identifier"]),
|
|
22
|
+
name: ModelExchangeFile::XmlLangString.parse(root.at_css(">name")),
|
|
23
|
+
version: root["version"],
|
|
24
|
+
metadata: ModelExchangeFile::XmlMetadata.parse(root.at_css(">metadata")),
|
|
25
|
+
documentation: parse_documentation(root),
|
|
26
|
+
properties: parse_properties(root),
|
|
27
|
+
elements: parse_elements(root),
|
|
28
|
+
relationships: parse_relationships(root),
|
|
29
|
+
organizations: parse_organizations(root.css(organizations_root_selector)),
|
|
30
|
+
diagrams: parse_diagrams(root),
|
|
31
|
+
viewpoints: @viewpoints,
|
|
32
|
+
property_definitions: @property_defs,
|
|
33
|
+
schema_locations: root.attr("xsi:schemaLocation").split(" "),
|
|
34
|
+
namespaces: root.namespaces,
|
|
35
|
+
archimate_version: parse_archimate_version(root)
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def parse_viewpoints(_node)
|
|
40
|
+
return []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def parse_documentation(node, element_name = "documentation")
|
|
44
|
+
node.css(">#{element_name}").map do |doc|
|
|
45
|
+
DataModel::Documentation.new(text: doc.content, lang: doc["xml:lang"])
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def parse_properties(node)
|
|
50
|
+
node.css("> properties > property").map do |i|
|
|
51
|
+
parse_property(i)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def parse_property(node)
|
|
56
|
+
property_def = @property_defs.find { |prop_def| prop_def.id == node.attr(property_def_attr_name) }
|
|
57
|
+
DataModel::Property.new(
|
|
58
|
+
property_definition: property_def,
|
|
59
|
+
values: [ModelExchangeFile::XmlLangString.parse(node.at_css("value"))].compact
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def parse_property_defs(node)
|
|
64
|
+
@property_defs = node.css(property_defs_selector).map do |i|
|
|
65
|
+
DataModel::PropertyDefinition.new(
|
|
66
|
+
id: i["identifier"],
|
|
67
|
+
name: property_def_name(i),
|
|
68
|
+
documentation: parse_documentation(i),
|
|
69
|
+
value_type: i["type"]
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parse_elements(model)
|
|
75
|
+
model.css(">elements>element").map do |i|
|
|
76
|
+
DataModel::Element.new(
|
|
77
|
+
id: identifier_to_id(i["identifier"]),
|
|
78
|
+
name: parse_element_name(i),
|
|
79
|
+
type: i["xsi:type"],
|
|
80
|
+
documentation: parse_documentation(i),
|
|
81
|
+
properties: parse_properties(i)
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def parse_organizations(nodes)
|
|
87
|
+
nodes.map do |i|
|
|
88
|
+
child_items = i.css(">item")
|
|
89
|
+
ref_items = child_items.select { |ci| ci.has_attribute?(identifier_ref_name) }
|
|
90
|
+
DataModel::Organization.new(
|
|
91
|
+
id: i["identifier"], # TODO: model exchange doesn't assign ids to organization items
|
|
92
|
+
name: ModelExchangeFile::XmlLangString.parse(i.at_css(">label")),
|
|
93
|
+
documentation: parse_documentation(i),
|
|
94
|
+
items: ref_items.map { |ri| identifier_to_id(ri[identifier_ref_name]) },
|
|
95
|
+
organizations: parse_organizations(child_items.reject { |ci| ci.has_attribute?(identifier_ref_name) })
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def parse_relationships(model)
|
|
101
|
+
model.css(">relationships>relationship").map do |i|
|
|
102
|
+
DataModel::Relationship.new(
|
|
103
|
+
id: identifier_to_id(i["identifier"]),
|
|
104
|
+
type: i.attr("xsi:type"),
|
|
105
|
+
source: identifier_to_id(i.attr("source")),
|
|
106
|
+
target: identifier_to_id(i.attr("target")),
|
|
107
|
+
name: parse_element_name(i),
|
|
108
|
+
access_type: i["accessType"],
|
|
109
|
+
documentation: parse_documentation(i),
|
|
110
|
+
properties: parse_properties(i)
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def parse_diagrams(model)
|
|
116
|
+
model.css(diagrams_path).map do |i|
|
|
117
|
+
nodes = parse_nodes(i)
|
|
118
|
+
connections = parse_connections(i)
|
|
119
|
+
child_id_hash = nodes.each_with_object({}) { |i2, a| a.merge!(i2.child_id_hash) }
|
|
120
|
+
connections.each do |c|
|
|
121
|
+
child_id_hash[c.source].connections << c
|
|
122
|
+
end
|
|
123
|
+
DataModel::Diagram.new(
|
|
124
|
+
id: identifier_to_id(i["identifier"]),
|
|
125
|
+
name: parse_element_name(i),
|
|
126
|
+
viewpoint_type: i["viewpoint"],
|
|
127
|
+
viewpoint: nil, # TODO: support this for ArchiMate v3
|
|
128
|
+
documentation: parse_documentation(i),
|
|
129
|
+
properties: parse_properties(i),
|
|
130
|
+
nodes: nodes,
|
|
131
|
+
connections: connections,
|
|
132
|
+
connection_router_type: i["connectionRouterType"],
|
|
133
|
+
type: i.attr("xsi:type"),
|
|
134
|
+
background: i.attr("background")
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def parse_nodes(node)
|
|
140
|
+
node.css("> node").map do |i|
|
|
141
|
+
DataModel::ViewNode.new(
|
|
142
|
+
id: identifier_to_id(i["identifier"]),
|
|
143
|
+
type: i.attr(view_node_type_attr),
|
|
144
|
+
model: nil,
|
|
145
|
+
name: ModelExchangeFile::XmlLangString.parse(i.at_css(">label")),
|
|
146
|
+
target_connections: [], # TODO: needed? "targetConnections",
|
|
147
|
+
archimate_element: identifier_to_id(i[view_node_element_ref]),
|
|
148
|
+
bounds: parse_bounds(i),
|
|
149
|
+
nodes: parse_nodes(i),
|
|
150
|
+
connections: parse_connections(i),
|
|
151
|
+
documentation: parse_documentation(i),
|
|
152
|
+
properties: parse_properties(i),
|
|
153
|
+
style: parse_style(i),
|
|
154
|
+
content: i.at_css("> content")&.text,
|
|
155
|
+
child_type: nil
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def parse_style(node)
|
|
161
|
+
style = node.at_css(">style")
|
|
162
|
+
return nil unless style
|
|
163
|
+
DataModel::Style.new(
|
|
164
|
+
text_alignment: style["textAlignment"],
|
|
165
|
+
fill_color: parse_color(style, "fillColor"),
|
|
166
|
+
line_color: parse_color(style, "lineColor"),
|
|
167
|
+
font_color: parse_color(style.at_css(">font"), "color"),
|
|
168
|
+
font: parse_font(style),
|
|
169
|
+
line_width: style["lineWidth"],
|
|
170
|
+
text_position: style.at_css("textPosition")
|
|
171
|
+
)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def parse_font(node)
|
|
175
|
+
font_node = node.at_css(">font")
|
|
176
|
+
return unless font_node && font_node["name"] && font_node["size"]
|
|
177
|
+
DataModel::Font.new(
|
|
178
|
+
name: font_node["name"],
|
|
179
|
+
size: font_node["size"],
|
|
180
|
+
style: style_to_int(font_node["style"]),
|
|
181
|
+
font_data: nil
|
|
182
|
+
)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def parse_color(node, el_name)
|
|
186
|
+
return unless node
|
|
187
|
+
color_node = node.at_css(el_name)
|
|
188
|
+
return unless color_node
|
|
189
|
+
DataModel::Color.new(
|
|
190
|
+
r: color_node["r"]&.to_i,
|
|
191
|
+
g: color_node["g"]&.to_i,
|
|
192
|
+
b: color_node["b"]&.to_i,
|
|
193
|
+
a: color_node["a"]&.to_i
|
|
194
|
+
)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def parse_bounds(node)
|
|
198
|
+
DataModel::Bounds.new(
|
|
199
|
+
x: node.attr("x"),
|
|
200
|
+
y: node.attr("y"),
|
|
201
|
+
width: node.attr("w"),
|
|
202
|
+
height: node.attr("h")
|
|
203
|
+
)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def parse_connections(node)
|
|
207
|
+
node.css("> connection").map do |i|
|
|
208
|
+
DataModel::Connection.new(
|
|
209
|
+
id: identifier_to_id(i["identifier"]),
|
|
210
|
+
type: i.attr(view_node_type_attr),
|
|
211
|
+
source: identifier_to_id(i["source"]),
|
|
212
|
+
target: identifier_to_id(i["target"]),
|
|
213
|
+
relationship: identifier_to_id(i[connection_relationship_ref]),
|
|
214
|
+
name: i.at_css("label")&.content,
|
|
215
|
+
style: parse_style(i),
|
|
216
|
+
bendpoints: parse_bendpoints(i),
|
|
217
|
+
documentation: parse_documentation(i),
|
|
218
|
+
properties: parse_properties(i)
|
|
219
|
+
)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def parse_bendpoints(node)
|
|
224
|
+
node.css("bendpoint").map do |i|
|
|
225
|
+
DataModel::Location.new(
|
|
226
|
+
x: i.attr("x"), y: i.attr("y")
|
|
227
|
+
)
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def identifier_to_id(str)
|
|
232
|
+
# str&.sub(/^id-/, "")
|
|
233
|
+
str
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
|
|
4
|
+
module Archimate
|
|
5
|
+
module FileFormats
|
|
6
|
+
# This class implements a file reader for ArchiMate 2.1 Model Exchange Format
|
|
7
|
+
class ModelExchangeFileReader21 < ModelExchangeFileReader
|
|
8
|
+
def parse_archimate_version(root)
|
|
9
|
+
case root.namespace.href
|
|
10
|
+
when "http://www.opengroup.org/xsd/archimate"
|
|
11
|
+
:archimate_2_1
|
|
12
|
+
else
|
|
13
|
+
raise "Unexpected namespace: #{root.namespace.href}"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def organizations_root_selector
|
|
18
|
+
">organization>item"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def property_defs_selector
|
|
22
|
+
">propertydefs>propertydef"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def property_def_attr_name
|
|
26
|
+
"identifierref"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def property_def_name(node)
|
|
30
|
+
node["name"]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def parse_element_name(el)
|
|
34
|
+
ModelExchangeFile::XmlLangString.parse(el.at_css(">label"))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def identifier_ref_name
|
|
38
|
+
"identifierref"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def diagrams_path
|
|
42
|
+
">views>view"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def view_node_element_ref
|
|
46
|
+
"elementref"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def view_node_type_attr
|
|
50
|
+
"type"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def connection_relationship_ref
|
|
54
|
+
"relationshipref"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def style_to_int(str)
|
|
58
|
+
case str
|
|
59
|
+
when nil
|
|
60
|
+
0
|
|
61
|
+
when "italic"
|
|
62
|
+
1
|
|
63
|
+
when "bold"
|
|
64
|
+
2
|
|
65
|
+
when "bold|italic"
|
|
66
|
+
3
|
|
67
|
+
else
|
|
68
|
+
raise "Broken for value: #{str}"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
|
|
4
|
+
module Archimate
|
|
5
|
+
module FileFormats
|
|
6
|
+
class ModelExchangeFileReader30 < ModelExchangeFileReader
|
|
7
|
+
def parse_archimate_version(root)
|
|
8
|
+
case root.namespace.href
|
|
9
|
+
when "http://www.opengroup.org/xsd/archimate/3.0/"
|
|
10
|
+
:archimate_3_0
|
|
11
|
+
else
|
|
12
|
+
raise "Unexpected namespace version: #{root.namespace.href}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def organizations_root_selector
|
|
17
|
+
">organizations"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def property_defs_selector
|
|
21
|
+
">propertyDefinitions>propertyDefinition"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def property_def_attr_name
|
|
25
|
+
"propertyDefinitionRef"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def property_def_name(node)
|
|
29
|
+
ModelExchangeFile::XmlLangString.parse(node.at_css("name"))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def parse_element_name(el)
|
|
33
|
+
ModelExchangeFile::XmlLangString.parse(el.at_css(">name"))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def identifier_ref_name
|
|
37
|
+
"identifierRef"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def diagrams_path
|
|
41
|
+
">views>diagrams>view"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def view_node_element_ref
|
|
45
|
+
"elementRef"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def view_node_type_attr
|
|
49
|
+
"xsi:type"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def connection_relationship_ref
|
|
53
|
+
"relationshipRef"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def style_to_int(str)
|
|
57
|
+
case str
|
|
58
|
+
when nil
|
|
59
|
+
0
|
|
60
|
+
when "italic"
|
|
61
|
+
1
|
|
62
|
+
when "bold"
|
|
63
|
+
2
|
|
64
|
+
when "bold italic"
|
|
65
|
+
3
|
|
66
|
+
else
|
|
67
|
+
raise "Broken for value: #{str}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# <xs:simpleType name="ViewpointPurposeEnum">
|
|
72
|
+
# <xs:restriction base="xs:NMTOKEN">
|
|
73
|
+
# <xs:enumeration value="Designing" />
|
|
74
|
+
# <xs:enumeration value="Deciding" />
|
|
75
|
+
# <xs:enumeration value="Informing" />
|
|
76
|
+
# </xs:restriction>
|
|
77
|
+
# </xs:simpleType>
|
|
78
|
+
|
|
79
|
+
# <xs:simpleType name="ViewpointPurposeType">
|
|
80
|
+
# <xs:list itemType="ViewpointPurposeEnum" />
|
|
81
|
+
# </xs:simpleType>
|
|
82
|
+
|
|
83
|
+
# <xs:simpleType name="ViewpointContentEnum">
|
|
84
|
+
# <xs:restriction base="xs:NMTOKEN">
|
|
85
|
+
# <xs:enumeration value="Details" />
|
|
86
|
+
# <xs:enumeration value="Coherence" />
|
|
87
|
+
# <xs:enumeration value="Overview" />
|
|
88
|
+
# </xs:restriction>
|
|
89
|
+
# </xs:simpleType>
|
|
90
|
+
|
|
91
|
+
# <xs:simpleType name="ViewpointContentType">
|
|
92
|
+
# <xs:list itemType="ViewpointContentEnum" />
|
|
93
|
+
# </xs:simpleType>
|
|
94
|
+
|
|
95
|
+
# <xs:complexType name="ViewpointType">
|
|
96
|
+
# <xs:complexContent>
|
|
97
|
+
# <xs:extension base="NamedReferenceableType">
|
|
98
|
+
# <xs:sequence>
|
|
99
|
+
# <xs:group ref="PropertiesGroup" />
|
|
100
|
+
# <xs:element name="concern" type="ConcernType" minOccurs="0" maxOccurs="unbounded" />
|
|
101
|
+
# <xs:element name="viewpointPurpose" type="ViewpointPurposeType" minOccurs="0" maxOccurs="1" />
|
|
102
|
+
# <xs:element name="viewpointContent" type="ViewpointContentType" minOccurs="0" maxOccurs="1" />
|
|
103
|
+
# <xs:element name="allowedElementType" type="AllowedElementTypeType" minOccurs="0" maxOccurs="unbounded" />
|
|
104
|
+
# <xs:element name="allowedRelationshipType" type="AllowedRelationshipTypeType" minOccurs="0" maxOccurs="unbounded" />
|
|
105
|
+
# <xs:element name="modelingNote" type="ModelingNoteType" minOccurs="0" maxOccurs="unbounded" />
|
|
106
|
+
# </xs:sequence>
|
|
107
|
+
# </xs:extension>
|
|
108
|
+
# </xs:complexContent>
|
|
109
|
+
# </xs:complexType>
|
|
110
|
+
def parse_viewpoints(model)
|
|
111
|
+
[]
|
|
112
|
+
# model.css("views > viewpoints").map do |i|
|
|
113
|
+
# attribute :concern, ConcernList
|
|
114
|
+
# attribute :viewpointPurpose, ViewpointPurpose.optional
|
|
115
|
+
# attribute :viewpointContent, ViewpointContent.optional
|
|
116
|
+
# attribute :allowedElementTypes, AllowedElementTypes
|
|
117
|
+
# attribute :allowedRelationshipTypes, AllowedRelationshipTypes
|
|
118
|
+
# attribute :modelingNotes, Strict::Array.member(ModelingNote).default([])
|
|
119
|
+
# DataModel::Viewpoint.new(
|
|
120
|
+
# id: identifier_to_id(i["identifier"]),
|
|
121
|
+
# name: parse_element_name(i),
|
|
122
|
+
# documentation: parse_documentation(i),
|
|
123
|
+
# properties: parse_properties(i),
|
|
124
|
+
# nodes: nodes,
|
|
125
|
+
# connections: connections,
|
|
126
|
+
# connection_router_type: i["connectionRouterType"],
|
|
127
|
+
# type: i.attr("xsi:type"),
|
|
128
|
+
# background: i.attr("background")
|
|
129
|
+
# )
|
|
130
|
+
# end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
|
|
4
|
+
module Archimate
|
|
5
|
+
module FileFormats
|
|
6
|
+
class ModelExchangeFileWriter < Writer
|
|
7
|
+
attr_reader :model
|
|
8
|
+
|
|
9
|
+
def initialize(model)
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def write(output_io)
|
|
14
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
|
15
|
+
serialize_model(xml)
|
|
16
|
+
end
|
|
17
|
+
output_io.write(builder.to_xml)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serialize_elements(xml)
|
|
21
|
+
xml.elements { serialize(xml, model.elements) } unless model.elements.empty?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def serialize_element(xml, element)
|
|
25
|
+
return if element.type == "SketchModel" # TODO: print a warning that data is lost
|
|
26
|
+
xml.element(identifier: identifier(element['id']),
|
|
27
|
+
"xsi:type" => meff_type(element.type)) do
|
|
28
|
+
elementbase(xml, element)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def elementbase(xml, element)
|
|
33
|
+
serialize_label(xml, element.name)
|
|
34
|
+
serialize(xml, element.documentation)
|
|
35
|
+
serialize_properties(xml, element)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def serialize_label(xml, str)
|
|
39
|
+
return if str.nil? || str.strip.empty?
|
|
40
|
+
name_attrs = str.lang && !str.lang.empty? ? {"xml:lang" => str.lang} : {}
|
|
41
|
+
xml.label(name_attrs) { xml.text text_proc(str) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def serialize_relationships(xml)
|
|
45
|
+
return if model.relationships.empty?
|
|
46
|
+
xml.relationships { serialize(xml, model.relationships) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def relationship_attributes(relationship)
|
|
50
|
+
{
|
|
51
|
+
identifier: identifier(relationship.id),
|
|
52
|
+
source: identifier(relationship.source),
|
|
53
|
+
target: identifier(relationship.target),
|
|
54
|
+
"xsi:type" => meff_type(relationship.type)
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def serialize_relationship(xml, relationship)
|
|
59
|
+
xml.relationship(
|
|
60
|
+
relationship_attributes(relationship)
|
|
61
|
+
) do
|
|
62
|
+
elementbase(xml, relationship)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def serialize_organization_root(xml, organizations)
|
|
67
|
+
return unless organizations && organizations.size > 0
|
|
68
|
+
xml.organization do
|
|
69
|
+
serialize(xml, organizations)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def serialize_organization(xml, organization)
|
|
74
|
+
return if organization.items.empty? && organization.documentation.empty? && organization.organizations.empty?
|
|
75
|
+
item_attrs = organization.id.nil? || organization.id.empty? ? {} : {identifier: organization.id}
|
|
76
|
+
xml.item(item_attrs) do
|
|
77
|
+
serialize_organization_body(xml, organization)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def serialize_organization_body(xml, organization)
|
|
82
|
+
return if organization.items.empty? && organization.documentation.empty? && organization.organizations.empty?
|
|
83
|
+
str = organization.name
|
|
84
|
+
label_attrs = organization.name&.lang && !organization.name.lang.empty? ? {"xml:lang" => organization.name.lang} : {}
|
|
85
|
+
xml.label(label_attrs) { xml.text text_proc(str) } unless str.nil? || str.strip.empty?
|
|
86
|
+
serialize(xml, organization.documentation)
|
|
87
|
+
serialize(xml, organization.organizations)
|
|
88
|
+
organization.items.each { |i| serialize_item(xml, i) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def serialize_properties(xml, element)
|
|
92
|
+
return if element.properties.empty?
|
|
93
|
+
xml.properties do
|
|
94
|
+
serialize(xml, element.properties)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def serialize_style(xml, style)
|
|
99
|
+
return unless style
|
|
100
|
+
xml.style(
|
|
101
|
+
remove_nil_values(
|
|
102
|
+
lineWidth: style.line_width
|
|
103
|
+
)
|
|
104
|
+
) do
|
|
105
|
+
serialize_color(xml, style.fill_color, :fillColor)
|
|
106
|
+
serialize_color(xml, style.line_color, :lineColor)
|
|
107
|
+
serialize_font(xml, style)
|
|
108
|
+
# TODO: complete this
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def serialize_font(xml, style)
|
|
113
|
+
return unless style && (style.font || style.font_color)
|
|
114
|
+
xml.font(
|
|
115
|
+
remove_nil_values(
|
|
116
|
+
name: style.font&.name,
|
|
117
|
+
size: style.font&.size&.round,
|
|
118
|
+
style: font_style_string(style.font)
|
|
119
|
+
)
|
|
120
|
+
) { serialize_color(xml, style&.font_color, :color) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def serialize_color(xml, color, sym)
|
|
124
|
+
return if color.nil?
|
|
125
|
+
h = {
|
|
126
|
+
r: color.r,
|
|
127
|
+
g: color.g,
|
|
128
|
+
b: color.b,
|
|
129
|
+
a: color.a
|
|
130
|
+
}
|
|
131
|
+
h.delete(:a) if color.a.nil? || color.a == 100
|
|
132
|
+
xml.send(sym, h)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def serialize_location(xml, location)
|
|
136
|
+
xml.bendpoint(x: location.x.round, y: location.y.round)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# # Processes text for text elements
|
|
140
|
+
def text_proc(str)
|
|
141
|
+
str.strip.tr("\r", "\n")
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# TODO: this should replace namespaces as appropriate for the desired export version
|
|
145
|
+
def model_namespaces
|
|
146
|
+
model.namespaces
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# TODO: Archi uses hex numbers for ids which may not be valid for
|
|
150
|
+
# identifer. If we are converting from Archi, decorate the IDs here.
|
|
151
|
+
def identifier(str)
|
|
152
|
+
return "id-#{str}" if str =~ /^\d/
|
|
153
|
+
str
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|