archimate 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.projectile +18 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +4 -0
- data/.yardocs +15 -0
- data/Gemfile +5 -0
- data/Guardfile +27 -0
- data/LICENSE +201 -0
- data/README.md +94 -0
- data/Rakefile +29 -0
- data/TODOs.org +286 -0
- data/archimate.gemspec +51 -0
- data/bin/archimate +17 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/exe/archidiff +7 -0
- data/exe/archidiff-summary +7 -0
- data/exe/archimate +7 -0
- data/exe/archimerge +7 -0
- data/exe/fmtxml +7 -0
- data/lib/archimate/cli/archi.rb +189 -0
- data/lib/archimate/cli/cleanup.rb +54 -0
- data/lib/archimate/cli/conflict_resolver.rb +39 -0
- data/lib/archimate/cli/convert.rb +39 -0
- data/lib/archimate/cli/diff.rb +31 -0
- data/lib/archimate/cli/diff_summary.rb +101 -0
- data/lib/archimate/cli/duper.rb +85 -0
- data/lib/archimate/cli/lint.rb +16 -0
- data/lib/archimate/cli/mapper.rb +82 -0
- data/lib/archimate/cli/merge.rb +49 -0
- data/lib/archimate/cli/merger.rb +109 -0
- data/lib/archimate/cli/stats.rb +42 -0
- data/lib/archimate/cli/svger.rb +40 -0
- data/lib/archimate/color.rb +53 -0
- data/lib/archimate/config.rb +35 -0
- data/lib/archimate/data_model/any_attribute.rb +13 -0
- data/lib/archimate/data_model/any_element.rb +15 -0
- data/lib/archimate/data_model/archimate_node.rb +181 -0
- data/lib/archimate/data_model/bounds.rb +72 -0
- data/lib/archimate/data_model/color.rb +47 -0
- data/lib/archimate/data_model/concept.rb +14 -0
- data/lib/archimate/data_model/concern.rb +17 -0
- data/lib/archimate/data_model/connection.rb +107 -0
- data/lib/archimate/data_model/constants.rb +82 -0
- data/lib/archimate/data_model/container.rb +17 -0
- data/lib/archimate/data_model/diagram.rb +40 -0
- data/lib/archimate/data_model/diffable_array.rb +213 -0
- data/lib/archimate/data_model/diffable_primitive.rb +83 -0
- data/lib/archimate/data_model/documentation.rb +14 -0
- data/lib/archimate/data_model/element.rb +87 -0
- data/lib/archimate/data_model/font.rb +54 -0
- data/lib/archimate/data_model/label.rb +19 -0
- data/lib/archimate/data_model/lang_string.rb +41 -0
- data/lib/archimate/data_model/location.rb +31 -0
- data/lib/archimate/data_model/metadata.rb +14 -0
- data/lib/archimate/data_model/model.rb +217 -0
- data/lib/archimate/data_model/modeling_note.rb +13 -0
- data/lib/archimate/data_model/named_referenceable.rb +14 -0
- data/lib/archimate/data_model/organization.rb +40 -0
- data/lib/archimate/data_model/property.rb +25 -0
- data/lib/archimate/data_model/property_definition.rb +16 -0
- data/lib/archimate/data_model/referenceable.rb +29 -0
- data/lib/archimate/data_model/relationship.rb +85 -0
- data/lib/archimate/data_model/schema_info.rb +18 -0
- data/lib/archimate/data_model/style.rb +32 -0
- data/lib/archimate/data_model/view.rb +12 -0
- data/lib/archimate/data_model/view_concept.rb +18 -0
- data/lib/archimate/data_model/view_node.rb +114 -0
- data/lib/archimate/data_model/viewpoint.rb +87 -0
- data/lib/archimate/data_model.rb +54 -0
- data/lib/archimate/diff/archimate_array_reference.rb +113 -0
- data/lib/archimate/diff/archimate_identified_node_reference.rb +41 -0
- data/lib/archimate/diff/archimate_node_attribute_reference.rb +70 -0
- data/lib/archimate/diff/archimate_node_reference.rb +80 -0
- data/lib/archimate/diff/change.rb +49 -0
- data/lib/archimate/diff/conflict.rb +31 -0
- data/lib/archimate/diff/conflicts/base_conflict.rb +53 -0
- data/lib/archimate/diff/conflicts/deleted_items_child_updated_conflict.rb +30 -0
- data/lib/archimate/diff/conflicts/deleted_items_referenced_conflict.rb +63 -0
- data/lib/archimate/diff/conflicts/path_conflict.rb +51 -0
- data/lib/archimate/diff/conflicts.rb +89 -0
- data/lib/archimate/diff/delete.rb +41 -0
- data/lib/archimate/diff/difference.rb +113 -0
- data/lib/archimate/diff/insert.rb +43 -0
- data/lib/archimate/diff/merge.rb +70 -0
- data/lib/archimate/diff/move.rb +51 -0
- data/lib/archimate/diff.rb +17 -0
- data/lib/archimate/export/csv_export.rb +32 -0
- data/lib/archimate/export/cypher.rb +171 -0
- data/lib/archimate/export/graph_ml.rb +131 -0
- data/lib/archimate/export/n_quads.rb +142 -0
- data/lib/archimate/file_format.rb +30 -0
- data/lib/archimate/file_formats/archi_file_format.rb +151 -0
- data/lib/archimate/file_formats/archi_file_reader.rb +252 -0
- data/lib/archimate/file_formats/archi_file_writer.rb +230 -0
- data/lib/archimate/file_formats/archimate_v2.rb +461 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_lang_string.rb +35 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_metadata.rb +115 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_property_definitions.rb +28 -0
- data/lib/archimate/file_formats/model_exchange_file/xml_property_defs.rb +27 -0
- data/lib/archimate/file_formats/model_exchange_file_reader.rb +237 -0
- data/lib/archimate/file_formats/model_exchange_file_reader_21.rb +73 -0
- data/lib/archimate/file_formats/model_exchange_file_reader_30.rb +134 -0
- data/lib/archimate/file_formats/model_exchange_file_writer.rb +157 -0
- data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +143 -0
- data/lib/archimate/file_formats/model_exchange_file_writer_30.rb +153 -0
- data/lib/archimate/file_formats/writer.rb +56 -0
- data/lib/archimate/lint/duplicate_entities.rb +121 -0
- data/lib/archimate/lint/linter.rb +146 -0
- data/lib/archimate/logging.rb +55 -0
- data/lib/archimate/maybe_io.rb +34 -0
- data/lib/archimate/progress_indicator.rb +29 -0
- data/lib/archimate/svg/archimate.css +232 -0
- data/lib/archimate/svg/child.rb +29 -0
- data/lib/archimate/svg/connection.rb +184 -0
- data/lib/archimate/svg/css_style.rb +31 -0
- data/lib/archimate/svg/diagram.rb +87 -0
- data/lib/archimate/svg/entity/and_junction.rb +14 -0
- data/lib/archimate/svg/entity/application_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/application_component.rb +41 -0
- data/lib/archimate/svg/entity/application_event.rb +13 -0
- data/lib/archimate/svg/entity/application_function.rb +13 -0
- data/lib/archimate/svg/entity/application_interaction.rb +13 -0
- data/lib/archimate/svg/entity/application_interface.rb +13 -0
- data/lib/archimate/svg/entity/application_process.rb +13 -0
- data/lib/archimate/svg/entity/application_service.rb +13 -0
- data/lib/archimate/svg/entity/artifact.rb +39 -0
- data/lib/archimate/svg/entity/assessment.rb +14 -0
- data/lib/archimate/svg/entity/base_entity.rb +128 -0
- data/lib/archimate/svg/entity/business_actor.rb +14 -0
- data/lib/archimate/svg/entity/business_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/business_event.rb +10 -0
- data/lib/archimate/svg/entity/business_function.rb +13 -0
- data/lib/archimate/svg/entity/business_interaction.rb +13 -0
- data/lib/archimate/svg/entity/business_interface.rb +13 -0
- data/lib/archimate/svg/entity/business_object.rb +13 -0
- data/lib/archimate/svg/entity/business_process.rb +13 -0
- data/lib/archimate/svg/entity/business_role.rb +14 -0
- data/lib/archimate/svg/entity/business_service.rb +13 -0
- data/lib/archimate/svg/entity/capability.rb +14 -0
- data/lib/archimate/svg/entity/communication_network.rb +14 -0
- data/lib/archimate/svg/entity/communication_path.rb +14 -0
- data/lib/archimate/svg/entity/constraint.rb +15 -0
- data/lib/archimate/svg/entity/contract.rb +13 -0
- data/lib/archimate/svg/entity/course_of_action.rb +14 -0
- data/lib/archimate/svg/entity/data_entity.rb +29 -0
- data/lib/archimate/svg/entity/data_object.rb +13 -0
- data/lib/archimate/svg/entity/deliverable.rb +13 -0
- data/lib/archimate/svg/entity/device.rb +48 -0
- data/lib/archimate/svg/entity/diagram_model_reference.rb +22 -0
- data/lib/archimate/svg/entity/diagram_object.rb +30 -0
- data/lib/archimate/svg/entity/distribution_network.rb +14 -0
- data/lib/archimate/svg/entity/driver.rb +14 -0
- data/lib/archimate/svg/entity/equipment.rb +16 -0
- data/lib/archimate/svg/entity/event_entity.rb +36 -0
- data/lib/archimate/svg/entity/facility.rb +16 -0
- data/lib/archimate/svg/entity/function_entity.rb +14 -0
- data/lib/archimate/svg/entity/gap.rb +21 -0
- data/lib/archimate/svg/entity/goal.rb +14 -0
- data/lib/archimate/svg/entity/group.rb +24 -0
- data/lib/archimate/svg/entity/implementation_event.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_function.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_interface.rb +13 -0
- data/lib/archimate/svg/entity/infrastructure_service.rb +13 -0
- data/lib/archimate/svg/entity/interaction_entity.rb +14 -0
- data/lib/archimate/svg/entity/interface_entity.rb +35 -0
- data/lib/archimate/svg/entity/junction.rb +19 -0
- data/lib/archimate/svg/entity/location.rb +14 -0
- data/lib/archimate/svg/entity/material.rb +14 -0
- data/lib/archimate/svg/entity/meaning.rb +40 -0
- data/lib/archimate/svg/entity/motivation_entity.rb +40 -0
- data/lib/archimate/svg/entity/network.rb +14 -0
- data/lib/archimate/svg/entity/node.rb +33 -0
- data/lib/archimate/svg/entity/node_shape.rb +64 -0
- data/lib/archimate/svg/entity/note.rb +30 -0
- data/lib/archimate/svg/entity/or_junction.rb +14 -0
- data/lib/archimate/svg/entity/outcome.rb +15 -0
- data/lib/archimate/svg/entity/path.rb +14 -0
- data/lib/archimate/svg/entity/plateau.rb +15 -0
- data/lib/archimate/svg/entity/principle.rb +15 -0
- data/lib/archimate/svg/entity/process_entity.rb +63 -0
- data/lib/archimate/svg/entity/product.rb +20 -0
- data/lib/archimate/svg/entity/rect.rb +13 -0
- data/lib/archimate/svg/entity/rect_entity.rb +25 -0
- data/lib/archimate/svg/entity/representation.rb +31 -0
- data/lib/archimate/svg/entity/requirement.rb +15 -0
- data/lib/archimate/svg/entity/resource.rb +14 -0
- data/lib/archimate/svg/entity/rounded_rect_entity.rb +23 -0
- data/lib/archimate/svg/entity/service_entity.rb +51 -0
- data/lib/archimate/svg/entity/sketch_model_sticky.rb +14 -0
- data/lib/archimate/svg/entity/stakeholder.rb +15 -0
- data/lib/archimate/svg/entity/system_software.rb +14 -0
- data/lib/archimate/svg/entity/technology_collaboration.rb +14 -0
- data/lib/archimate/svg/entity/technology_event.rb +13 -0
- data/lib/archimate/svg/entity/technology_function.rb +13 -0
- data/lib/archimate/svg/entity/technology_interaction.rb +13 -0
- data/lib/archimate/svg/entity/technology_interface.rb +13 -0
- data/lib/archimate/svg/entity/technology_process.rb +13 -0
- data/lib/archimate/svg/entity/technology_service.rb +13 -0
- data/lib/archimate/svg/entity/value.rb +27 -0
- data/lib/archimate/svg/entity/work_package.rb +14 -0
- data/lib/archimate/svg/entity.rb +93 -0
- data/lib/archimate/svg/entity_factory.rb +17 -0
- data/lib/archimate/svg/extents.rb +27 -0
- data/lib/archimate/svg/point.rb +7 -0
- data/lib/archimate/svg/svg_template.rb +27 -0
- data/lib/archimate/svg/svg_template.svg.erb +169 -0
- data/lib/archimate/version.rb +4 -0
- data/lib/archimate.rb +114 -0
- metadata +623 -0
@@ -0,0 +1,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
|