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,252 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
module Archimate
|
5
|
+
module FileFormats
|
6
|
+
class ArchiFileReader
|
7
|
+
def initialize
|
8
|
+
@progress = nil
|
9
|
+
@random ||= Random.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse(doc)
|
13
|
+
@size = 0
|
14
|
+
doc.traverse { |_n| @size += 1 }
|
15
|
+
@progress = ProgressIndicator.new(total: @size, title: "Parsing")
|
16
|
+
@property_defs = {}
|
17
|
+
tick
|
18
|
+
diagrams = parse_diagrams(doc.root)
|
19
|
+
DataModel::Model.new(
|
20
|
+
id: doc.root["id"],
|
21
|
+
name: doc.root["name"],
|
22
|
+
documentation: parse_documentation(doc.root, "purpose"),
|
23
|
+
properties: parse_properties(doc.root),
|
24
|
+
elements: parse_elements(doc.root),
|
25
|
+
organizations: parse_organizations(doc.root),
|
26
|
+
relationships: parse_relationships(doc.root),
|
27
|
+
diagrams: diagrams,
|
28
|
+
viewpoints: [],
|
29
|
+
property_definitions: @property_defs.values,
|
30
|
+
namespaces: {},
|
31
|
+
schema_locations: []
|
32
|
+
)
|
33
|
+
ensure
|
34
|
+
@progress&.finish
|
35
|
+
@progress = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_documentation(node, element_name = "documentation")
|
39
|
+
node.css(">#{element_name}").each_with_object([]) do |i, a|
|
40
|
+
tick
|
41
|
+
a << DataModel::Documentation.new(text: i.content)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_properties(node)
|
46
|
+
node.css(">property").each_with_object([]) do |i, a|
|
47
|
+
tick
|
48
|
+
key = i["key"]
|
49
|
+
next unless key
|
50
|
+
if @property_defs.key?(key)
|
51
|
+
prop_def = @property_defs[key]
|
52
|
+
else
|
53
|
+
@property_defs[key] = prop_def = DataModel::PropertyDefinition.new(
|
54
|
+
id: DataModel::PropertyDefinition.identifier_for_key(key),
|
55
|
+
name: key,
|
56
|
+
documentation: [],
|
57
|
+
value_type: "string"
|
58
|
+
)
|
59
|
+
end
|
60
|
+
a << DataModel::Property.new(
|
61
|
+
values: [
|
62
|
+
DataModel::LangString.new(text: i["value"] || "en")
|
63
|
+
],
|
64
|
+
property_definition: prop_def
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_elements(model)
|
70
|
+
model.css(ArchiFileFormat::FOLDER_XPATHS.join(",")).css('element[id]').map do |i|
|
71
|
+
tick
|
72
|
+
DataModel::Element.new(
|
73
|
+
id: i["id"],
|
74
|
+
name: i["name"],
|
75
|
+
organization_id: i.parent["id"],
|
76
|
+
type: i["xsi:type"].sub("archimate:", ""),
|
77
|
+
documentation: parse_documentation(i),
|
78
|
+
properties: parse_properties(i)
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def parse_organizations(node)
|
84
|
+
node.css("> folder").each_with_object([]) do |i, a|
|
85
|
+
tick
|
86
|
+
a << DataModel::Organization.new(
|
87
|
+
id: i.attr("id"),
|
88
|
+
name: i.attr("name"),
|
89
|
+
type: i.attr("type"),
|
90
|
+
documentation: parse_documentation(i),
|
91
|
+
properties: parse_properties(i),
|
92
|
+
items: child_element_ids(i),
|
93
|
+
organizations: parse_organizations(i)
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def child_element_ids(node)
|
99
|
+
node.css(">element[id]").each_with_object([]) do |i, a|
|
100
|
+
tick
|
101
|
+
a << i.attr("id")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def parse_relationships(model)
|
106
|
+
model.css(ArchiFileFormat::RELATION_XPATHS.join(",")).css("element").map do |i|
|
107
|
+
tick
|
108
|
+
DataModel::Relationship.new(
|
109
|
+
id: i["id"],
|
110
|
+
type: i.attr("xsi:type").sub("archimate:", ""),
|
111
|
+
source: i.attr("source"),
|
112
|
+
target: i.attr("target"),
|
113
|
+
name: i["name"],
|
114
|
+
access_type: parse_access_type(i["accessType"]),
|
115
|
+
documentation: parse_documentation(i),
|
116
|
+
properties: parse_properties(i)
|
117
|
+
)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def parse_access_type(val)
|
122
|
+
return nil unless val && val.size > 0
|
123
|
+
i = val.to_i
|
124
|
+
return nil unless i >= 0 && i < DataModel::AccessType.size
|
125
|
+
DataModel::AccessType[i]
|
126
|
+
end
|
127
|
+
|
128
|
+
def parse_diagrams(model)
|
129
|
+
model.css(ArchiFileFormat::DIAGRAM_XPATHS.join(",")).css(
|
130
|
+
'element[xsi|type="archimate:ArchimateDiagramModel"]',
|
131
|
+
'element[xsi|type="archimate:SketchModel"]'
|
132
|
+
).map do |i|
|
133
|
+
tick
|
134
|
+
viewpoint_idx = i["viewpoint"]
|
135
|
+
viewpoint_idx = viewpoint_idx.to_i unless viewpoint_idx.nil?
|
136
|
+
viewpoint_type = viewpoint_idx.nil? ? nil : ArchiFileFormat::VIEWPOINTS[viewpoint_idx]
|
137
|
+
DataModel::Diagram.new(
|
138
|
+
id: i["id"],
|
139
|
+
name: i["name"],
|
140
|
+
viewpoint_type: viewpoint_type,
|
141
|
+
viewpoint: nil,
|
142
|
+
documentation: parse_documentation(i),
|
143
|
+
properties: parse_properties(i),
|
144
|
+
nodes: parse_nodes(i),
|
145
|
+
connections: parse_all_connections(i),
|
146
|
+
connection_router_type: i["connectionRouterType"],
|
147
|
+
type: i.attr("xsi:type"),
|
148
|
+
background: i.attr("background"),
|
149
|
+
organization_id: nil
|
150
|
+
)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def parse_nodes(node)
|
155
|
+
node.css("> child").each_with_object([]) do |child_node, a|
|
156
|
+
tick
|
157
|
+
a << DataModel::ViewNode.new(
|
158
|
+
id: child_node.attr("id"),
|
159
|
+
type: child_node.attr("xsi:type"),
|
160
|
+
model: child_node.attr("model"),
|
161
|
+
name: child_node.attr("name"),
|
162
|
+
target_connections: parse_target_connections(child_node.attr("targetConnections")),
|
163
|
+
archimate_element: child_node.attr("archimateElement"),
|
164
|
+
bounds: parse_bounds(child_node),
|
165
|
+
nodes: parse_nodes(child_node),
|
166
|
+
connections: parse_connections(child_node),
|
167
|
+
documentation: parse_documentation(child_node),
|
168
|
+
properties: parse_properties(child_node),
|
169
|
+
style: parse_style(child_node),
|
170
|
+
content: child_node.at_css("> content")&.text,
|
171
|
+
child_type: child_node.attr("type")
|
172
|
+
)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def parse_target_connections(str)
|
177
|
+
return [] if str.nil?
|
178
|
+
str.split(" ")
|
179
|
+
end
|
180
|
+
|
181
|
+
def parse_style(style)
|
182
|
+
tick
|
183
|
+
DataModel::Style.new(
|
184
|
+
text_alignment: style["textAlignment"],
|
185
|
+
fill_color: DataModel::Color.rgba(style["fillColor"]),
|
186
|
+
line_color: DataModel::Color.rgba(style["lineColor"]),
|
187
|
+
font_color: DataModel::Color.rgba(style["fontColor"]),
|
188
|
+
font: DataModel::Font.archi_font_string(style["font"]),
|
189
|
+
line_width: style["lineWidth"],
|
190
|
+
text_position: style["textPosition"]
|
191
|
+
)
|
192
|
+
end
|
193
|
+
|
194
|
+
def parse_bounds(node)
|
195
|
+
bounds = node.at_css("> bounds")
|
196
|
+
tick
|
197
|
+
unless bounds.nil?
|
198
|
+
DataModel::Bounds.new(
|
199
|
+
x: bounds.attr("x"),
|
200
|
+
y: bounds.attr("y"),
|
201
|
+
width: bounds.attr("width"),
|
202
|
+
height: bounds.attr("height")
|
203
|
+
)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def parse_all_connections(node)
|
208
|
+
node.css("sourceConnection").each_with_object([]) do |i, a|
|
209
|
+
tick
|
210
|
+
a << parse_connection(i)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def parse_connections(node)
|
215
|
+
node.css("> sourceConnection").each_with_object([]) { |i, a| a << parse_connection(i) }
|
216
|
+
end
|
217
|
+
|
218
|
+
def parse_connection(i)
|
219
|
+
DataModel::Connection.new(
|
220
|
+
id: i["id"],
|
221
|
+
type: i.attr("xsi:type"),
|
222
|
+
source: i["source"],
|
223
|
+
target: i["target"],
|
224
|
+
relationship: i["relationship"] || i["archimateRelationship"],
|
225
|
+
name: i["name"],
|
226
|
+
style: parse_style(i),
|
227
|
+
bendpoints: parse_bendpoints(i),
|
228
|
+
documentation: parse_documentation(i),
|
229
|
+
properties: parse_properties(i)
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
233
|
+
# startX = location.x - source_attachment.x
|
234
|
+
# startY = location.y - source_attachment.y
|
235
|
+
# endX = location.x - target_attachment.x
|
236
|
+
# endY = location.y - source_attachment.y
|
237
|
+
def parse_bendpoints(node)
|
238
|
+
node.css("bendpoint").each_with_object([]) do |i, a|
|
239
|
+
tick
|
240
|
+
a << DataModel::Location.new(
|
241
|
+
x: i.attr("startX") || 0, y: i.attr("startY") || 0,
|
242
|
+
end_x: i.attr("endX"), end_y: i.attr("endY")
|
243
|
+
)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def tick
|
248
|
+
@progress&.increment
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
module Archimate
|
5
|
+
module FileFormats
|
6
|
+
class ArchiFileWriter < Writer
|
7
|
+
using DataModel::DiffableArray
|
8
|
+
using DataModel::DiffablePrimitive
|
9
|
+
|
10
|
+
TEXT_SUBSTITUTIONS = [
|
11
|
+
[' ', '
'],
|
12
|
+
['"', '"'],
|
13
|
+
['>', '>']
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
def initialize(model)
|
17
|
+
super
|
18
|
+
@version = "3.1.1"
|
19
|
+
end
|
20
|
+
|
21
|
+
def process_text(doc_str)
|
22
|
+
%w(documentation content).each do |tag|
|
23
|
+
TEXT_SUBSTITUTIONS.each do |from, to|
|
24
|
+
doc_str.gsub!(%r{<#{tag}>([^<]*#{from}[^<]*)</#{tag}>}) do |str|
|
25
|
+
str.gsub(from, to)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
doc_str.gsub(
|
30
|
+
%r{<(/)?archimate:}, "<\\1"
|
31
|
+
).gsub(
|
32
|
+
%r{<(/)?model}, "<\\1archimate:model"
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def write(archifile_io)
|
37
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
38
|
+
serialize_model(xml)
|
39
|
+
end
|
40
|
+
archifile_io.write(
|
41
|
+
process_text(
|
42
|
+
builder.to_xml
|
43
|
+
)
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def serialize_model(xml)
|
48
|
+
xml["archimate"].model(
|
49
|
+
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
50
|
+
"xmlns:archimate" => "http://www.archimatetool.com/archimate",
|
51
|
+
"name" => model.name,
|
52
|
+
"id" => model.id,
|
53
|
+
"version" => @version
|
54
|
+
) do
|
55
|
+
serialize(xml, model.organizations)
|
56
|
+
serialize(xml, model.properties)
|
57
|
+
model.documentation.each { |d| serialize_documentation(xml, d, "purpose") }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def serialize_organization(xml, organization)
|
62
|
+
xml.folder(
|
63
|
+
remove_nil_values(name: organization.name, id: organization.id, type: organization.type)
|
64
|
+
) do
|
65
|
+
serialize(xml, organization.organizations)
|
66
|
+
serialize(xml, organization.documentation)
|
67
|
+
organization.items.each { |i| serialize_item(xml, i) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def serialize_property(xml, property)
|
72
|
+
xml.property(remove_nil_values(key: property.key, value: property.value))
|
73
|
+
end
|
74
|
+
|
75
|
+
def serialize_documentation(xml, documentation, element_name = "documentation")
|
76
|
+
xml.send(element_name) { xml.text(documentation.text) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def serialize_item(xml, item)
|
80
|
+
item_instance = model.lookup(item)
|
81
|
+
$stderr.puts "serialize_item item `#{item.inspect}` could not found." if item_instance.nil?
|
82
|
+
serialize(xml, item_instance)
|
83
|
+
end
|
84
|
+
|
85
|
+
def serialize_element(xml, element)
|
86
|
+
xml.element(
|
87
|
+
remove_nil_values(
|
88
|
+
"xsi:type" => "archimate:#{element.type}",
|
89
|
+
"id" => element.id,
|
90
|
+
"name" => element.name
|
91
|
+
)
|
92
|
+
) do
|
93
|
+
serialize(xml, element.documentation)
|
94
|
+
serialize(xml, element.properties)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def serialize_relationship(xml, rel)
|
99
|
+
xml.element(
|
100
|
+
remove_nil_values(
|
101
|
+
"xsi:type" => "archimate:#{rel.type}",
|
102
|
+
"id" => rel.id,
|
103
|
+
"name" => rel.name,
|
104
|
+
"source" => rel.source,
|
105
|
+
"target" => rel.target,
|
106
|
+
"accessType" => serialize_access_type(rel.access_type)
|
107
|
+
)
|
108
|
+
) do
|
109
|
+
serialize(xml, rel.documentation)
|
110
|
+
serialize(xml, rel.properties)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def serialize_access_type(val)
|
115
|
+
case val
|
116
|
+
when nil
|
117
|
+
nil
|
118
|
+
else
|
119
|
+
DataModel::AccessType.index(val)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def serialize_diagram(xml, diagram)
|
124
|
+
xml.element(
|
125
|
+
remove_nil_values(
|
126
|
+
"xsi:type" => diagram.type || "archimate:ArchimateDiagramModel",
|
127
|
+
"id" => diagram.id,
|
128
|
+
"name" => diagram.name,
|
129
|
+
"connectionRouterType" => diagram.connection_router_type,
|
130
|
+
"viewpoint" => ArchiFileFormat::VIEWPOINTS.index(diagram.viewpoint_type)&.to_s,
|
131
|
+
"background" => diagram.background
|
132
|
+
)
|
133
|
+
) do
|
134
|
+
serialize(xml, diagram.nodes)
|
135
|
+
serialize(xml, diagram.documentation)
|
136
|
+
serialize(xml, diagram.properties)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def archi_style_hash(style)
|
141
|
+
{
|
142
|
+
"fillColor" => style&.fill_color&.to_rgba,
|
143
|
+
"font" => style&.font&.to_archi_font,
|
144
|
+
"fontColor" => style&.font_color&.to_rgba,
|
145
|
+
"lineColor" => style&.line_color&.to_rgba,
|
146
|
+
"lineWidth" => style&.line_width&.to_s,
|
147
|
+
"textAlignment" => style&.text_alignment&.to_s,
|
148
|
+
"textPosition" => style&.text_position
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def serialize_view_node(xml, child)
|
153
|
+
style_hash = archi_style_hash(child.style)
|
154
|
+
fill_color = style_hash.delete("fillColor")
|
155
|
+
xml.child(
|
156
|
+
remove_nil_values(
|
157
|
+
{
|
158
|
+
"xsi:type" => child.type,
|
159
|
+
"id" => child.id,
|
160
|
+
"name" => child.name
|
161
|
+
}.merge(
|
162
|
+
style_hash.merge(
|
163
|
+
"targetConnections" => child.target_connections.empty? ? nil : child.target_connections.join(" "),
|
164
|
+
"fillColor" => fill_color,
|
165
|
+
"model" => child.model,
|
166
|
+
"archimateElement" => child.archimate_element,
|
167
|
+
"type" => child.child_type
|
168
|
+
)
|
169
|
+
)
|
170
|
+
)
|
171
|
+
) do
|
172
|
+
serialize(xml, child.bounds) unless child.bounds.nil?
|
173
|
+
serialize(xml, child.connections)
|
174
|
+
xml.content { xml.text child.content } unless child.content.nil?
|
175
|
+
serialize(xml, child.nodes)
|
176
|
+
serialize(xml, child.documentation)
|
177
|
+
serialize(xml, child.properties)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def serialize_bounds(xml, bounds)
|
182
|
+
xml.bounds(
|
183
|
+
remove_nil_values(
|
184
|
+
x: bounds.x&.to_i,
|
185
|
+
y: bounds.y&.to_i,
|
186
|
+
width: bounds.width&.to_i,
|
187
|
+
height: bounds.height&.to_i
|
188
|
+
)
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
def serialize_connection(xml, connection)
|
193
|
+
xml.sourceConnection(
|
194
|
+
remove_nil_values(
|
195
|
+
{
|
196
|
+
"xsi:type" => connection.type,
|
197
|
+
"id" => connection.id,
|
198
|
+
"name" => connection.name
|
199
|
+
}.merge(
|
200
|
+
archi_style_hash(connection.style).merge(
|
201
|
+
"source" => connection.source,
|
202
|
+
"target" => connection.target,
|
203
|
+
"relationship" => connection.relationship
|
204
|
+
)
|
205
|
+
)
|
206
|
+
)
|
207
|
+
) do
|
208
|
+
serialize(xml, connection.bendpoints)
|
209
|
+
serialize(xml, connection.documentation)
|
210
|
+
serialize(xml, connection.properties)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# startX = location.x - source_attachment.x
|
215
|
+
# startY = location.y - source_attachment.y
|
216
|
+
# endX = location.x - target_attachment.x
|
217
|
+
# endY = location.y - source_attachment.y
|
218
|
+
def serialize_location(xml, bendpoint)
|
219
|
+
xml.bendpoint(
|
220
|
+
remove_nil_values(
|
221
|
+
startX: bendpoint.x == 0 ? nil : bendpoint.x&.to_i,
|
222
|
+
startY: bendpoint.y == 0 ? nil : bendpoint.y&.to_i,
|
223
|
+
endX: bendpoint.end_x&.to_i,
|
224
|
+
endY: bendpoint.end_y&.to_i
|
225
|
+
)
|
226
|
+
)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|