archimate 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.projectile +18 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +4 -0
  6. data/.yardocs +15 -0
  7. data/Gemfile +5 -0
  8. data/Guardfile +27 -0
  9. data/LICENSE +201 -0
  10. data/README.md +94 -0
  11. data/Rakefile +29 -0
  12. data/TODOs.org +286 -0
  13. data/archimate.gemspec +51 -0
  14. data/bin/archimate +17 -0
  15. data/bin/console +13 -0
  16. data/bin/setup +8 -0
  17. data/exe/archidiff +7 -0
  18. data/exe/archidiff-summary +7 -0
  19. data/exe/archimate +7 -0
  20. data/exe/archimerge +7 -0
  21. data/exe/fmtxml +7 -0
  22. data/lib/archimate/cli/archi.rb +189 -0
  23. data/lib/archimate/cli/cleanup.rb +54 -0
  24. data/lib/archimate/cli/conflict_resolver.rb +39 -0
  25. data/lib/archimate/cli/convert.rb +39 -0
  26. data/lib/archimate/cli/diff.rb +31 -0
  27. data/lib/archimate/cli/diff_summary.rb +101 -0
  28. data/lib/archimate/cli/duper.rb +85 -0
  29. data/lib/archimate/cli/lint.rb +16 -0
  30. data/lib/archimate/cli/mapper.rb +82 -0
  31. data/lib/archimate/cli/merge.rb +49 -0
  32. data/lib/archimate/cli/merger.rb +109 -0
  33. data/lib/archimate/cli/stats.rb +42 -0
  34. data/lib/archimate/cli/svger.rb +40 -0
  35. data/lib/archimate/color.rb +53 -0
  36. data/lib/archimate/config.rb +35 -0
  37. data/lib/archimate/data_model/any_attribute.rb +13 -0
  38. data/lib/archimate/data_model/any_element.rb +15 -0
  39. data/lib/archimate/data_model/archimate_node.rb +181 -0
  40. data/lib/archimate/data_model/bounds.rb +72 -0
  41. data/lib/archimate/data_model/color.rb +47 -0
  42. data/lib/archimate/data_model/concept.rb +14 -0
  43. data/lib/archimate/data_model/concern.rb +17 -0
  44. data/lib/archimate/data_model/connection.rb +107 -0
  45. data/lib/archimate/data_model/constants.rb +82 -0
  46. data/lib/archimate/data_model/container.rb +17 -0
  47. data/lib/archimate/data_model/diagram.rb +40 -0
  48. data/lib/archimate/data_model/diffable_array.rb +213 -0
  49. data/lib/archimate/data_model/diffable_primitive.rb +83 -0
  50. data/lib/archimate/data_model/documentation.rb +14 -0
  51. data/lib/archimate/data_model/element.rb +87 -0
  52. data/lib/archimate/data_model/font.rb +54 -0
  53. data/lib/archimate/data_model/label.rb +19 -0
  54. data/lib/archimate/data_model/lang_string.rb +41 -0
  55. data/lib/archimate/data_model/location.rb +31 -0
  56. data/lib/archimate/data_model/metadata.rb +14 -0
  57. data/lib/archimate/data_model/model.rb +217 -0
  58. data/lib/archimate/data_model/modeling_note.rb +13 -0
  59. data/lib/archimate/data_model/named_referenceable.rb +14 -0
  60. data/lib/archimate/data_model/organization.rb +40 -0
  61. data/lib/archimate/data_model/property.rb +25 -0
  62. data/lib/archimate/data_model/property_definition.rb +16 -0
  63. data/lib/archimate/data_model/referenceable.rb +29 -0
  64. data/lib/archimate/data_model/relationship.rb +85 -0
  65. data/lib/archimate/data_model/schema_info.rb +18 -0
  66. data/lib/archimate/data_model/style.rb +32 -0
  67. data/lib/archimate/data_model/view.rb +12 -0
  68. data/lib/archimate/data_model/view_concept.rb +18 -0
  69. data/lib/archimate/data_model/view_node.rb +114 -0
  70. data/lib/archimate/data_model/viewpoint.rb +87 -0
  71. data/lib/archimate/data_model.rb +54 -0
  72. data/lib/archimate/diff/archimate_array_reference.rb +113 -0
  73. data/lib/archimate/diff/archimate_identified_node_reference.rb +41 -0
  74. data/lib/archimate/diff/archimate_node_attribute_reference.rb +70 -0
  75. data/lib/archimate/diff/archimate_node_reference.rb +80 -0
  76. data/lib/archimate/diff/change.rb +49 -0
  77. data/lib/archimate/diff/conflict.rb +31 -0
  78. data/lib/archimate/diff/conflicts/base_conflict.rb +53 -0
  79. data/lib/archimate/diff/conflicts/deleted_items_child_updated_conflict.rb +30 -0
  80. data/lib/archimate/diff/conflicts/deleted_items_referenced_conflict.rb +63 -0
  81. data/lib/archimate/diff/conflicts/path_conflict.rb +51 -0
  82. data/lib/archimate/diff/conflicts.rb +89 -0
  83. data/lib/archimate/diff/delete.rb +41 -0
  84. data/lib/archimate/diff/difference.rb +113 -0
  85. data/lib/archimate/diff/insert.rb +43 -0
  86. data/lib/archimate/diff/merge.rb +70 -0
  87. data/lib/archimate/diff/move.rb +51 -0
  88. data/lib/archimate/diff.rb +17 -0
  89. data/lib/archimate/export/csv_export.rb +32 -0
  90. data/lib/archimate/export/cypher.rb +171 -0
  91. data/lib/archimate/export/graph_ml.rb +131 -0
  92. data/lib/archimate/export/n_quads.rb +142 -0
  93. data/lib/archimate/file_format.rb +30 -0
  94. data/lib/archimate/file_formats/archi_file_format.rb +151 -0
  95. data/lib/archimate/file_formats/archi_file_reader.rb +252 -0
  96. data/lib/archimate/file_formats/archi_file_writer.rb +230 -0
  97. data/lib/archimate/file_formats/archimate_v2.rb +461 -0
  98. data/lib/archimate/file_formats/model_exchange_file/xml_lang_string.rb +35 -0
  99. data/lib/archimate/file_formats/model_exchange_file/xml_metadata.rb +115 -0
  100. data/lib/archimate/file_formats/model_exchange_file/xml_property_definitions.rb +28 -0
  101. data/lib/archimate/file_formats/model_exchange_file/xml_property_defs.rb +27 -0
  102. data/lib/archimate/file_formats/model_exchange_file_reader.rb +237 -0
  103. data/lib/archimate/file_formats/model_exchange_file_reader_21.rb +73 -0
  104. data/lib/archimate/file_formats/model_exchange_file_reader_30.rb +134 -0
  105. data/lib/archimate/file_formats/model_exchange_file_writer.rb +157 -0
  106. data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +143 -0
  107. data/lib/archimate/file_formats/model_exchange_file_writer_30.rb +153 -0
  108. data/lib/archimate/file_formats/writer.rb +56 -0
  109. data/lib/archimate/lint/duplicate_entities.rb +121 -0
  110. data/lib/archimate/lint/linter.rb +146 -0
  111. data/lib/archimate/logging.rb +55 -0
  112. data/lib/archimate/maybe_io.rb +34 -0
  113. data/lib/archimate/progress_indicator.rb +29 -0
  114. data/lib/archimate/svg/archimate.css +232 -0
  115. data/lib/archimate/svg/child.rb +29 -0
  116. data/lib/archimate/svg/connection.rb +184 -0
  117. data/lib/archimate/svg/css_style.rb +31 -0
  118. data/lib/archimate/svg/diagram.rb +87 -0
  119. data/lib/archimate/svg/entity/and_junction.rb +14 -0
  120. data/lib/archimate/svg/entity/application_collaboration.rb +14 -0
  121. data/lib/archimate/svg/entity/application_component.rb +41 -0
  122. data/lib/archimate/svg/entity/application_event.rb +13 -0
  123. data/lib/archimate/svg/entity/application_function.rb +13 -0
  124. data/lib/archimate/svg/entity/application_interaction.rb +13 -0
  125. data/lib/archimate/svg/entity/application_interface.rb +13 -0
  126. data/lib/archimate/svg/entity/application_process.rb +13 -0
  127. data/lib/archimate/svg/entity/application_service.rb +13 -0
  128. data/lib/archimate/svg/entity/artifact.rb +39 -0
  129. data/lib/archimate/svg/entity/assessment.rb +14 -0
  130. data/lib/archimate/svg/entity/base_entity.rb +128 -0
  131. data/lib/archimate/svg/entity/business_actor.rb +14 -0
  132. data/lib/archimate/svg/entity/business_collaboration.rb +14 -0
  133. data/lib/archimate/svg/entity/business_event.rb +10 -0
  134. data/lib/archimate/svg/entity/business_function.rb +13 -0
  135. data/lib/archimate/svg/entity/business_interaction.rb +13 -0
  136. data/lib/archimate/svg/entity/business_interface.rb +13 -0
  137. data/lib/archimate/svg/entity/business_object.rb +13 -0
  138. data/lib/archimate/svg/entity/business_process.rb +13 -0
  139. data/lib/archimate/svg/entity/business_role.rb +14 -0
  140. data/lib/archimate/svg/entity/business_service.rb +13 -0
  141. data/lib/archimate/svg/entity/capability.rb +14 -0
  142. data/lib/archimate/svg/entity/communication_network.rb +14 -0
  143. data/lib/archimate/svg/entity/communication_path.rb +14 -0
  144. data/lib/archimate/svg/entity/constraint.rb +15 -0
  145. data/lib/archimate/svg/entity/contract.rb +13 -0
  146. data/lib/archimate/svg/entity/course_of_action.rb +14 -0
  147. data/lib/archimate/svg/entity/data_entity.rb +29 -0
  148. data/lib/archimate/svg/entity/data_object.rb +13 -0
  149. data/lib/archimate/svg/entity/deliverable.rb +13 -0
  150. data/lib/archimate/svg/entity/device.rb +48 -0
  151. data/lib/archimate/svg/entity/diagram_model_reference.rb +22 -0
  152. data/lib/archimate/svg/entity/diagram_object.rb +30 -0
  153. data/lib/archimate/svg/entity/distribution_network.rb +14 -0
  154. data/lib/archimate/svg/entity/driver.rb +14 -0
  155. data/lib/archimate/svg/entity/equipment.rb +16 -0
  156. data/lib/archimate/svg/entity/event_entity.rb +36 -0
  157. data/lib/archimate/svg/entity/facility.rb +16 -0
  158. data/lib/archimate/svg/entity/function_entity.rb +14 -0
  159. data/lib/archimate/svg/entity/gap.rb +21 -0
  160. data/lib/archimate/svg/entity/goal.rb +14 -0
  161. data/lib/archimate/svg/entity/group.rb +24 -0
  162. data/lib/archimate/svg/entity/implementation_event.rb +13 -0
  163. data/lib/archimate/svg/entity/infrastructure_function.rb +13 -0
  164. data/lib/archimate/svg/entity/infrastructure_interface.rb +13 -0
  165. data/lib/archimate/svg/entity/infrastructure_service.rb +13 -0
  166. data/lib/archimate/svg/entity/interaction_entity.rb +14 -0
  167. data/lib/archimate/svg/entity/interface_entity.rb +35 -0
  168. data/lib/archimate/svg/entity/junction.rb +19 -0
  169. data/lib/archimate/svg/entity/location.rb +14 -0
  170. data/lib/archimate/svg/entity/material.rb +14 -0
  171. data/lib/archimate/svg/entity/meaning.rb +40 -0
  172. data/lib/archimate/svg/entity/motivation_entity.rb +40 -0
  173. data/lib/archimate/svg/entity/network.rb +14 -0
  174. data/lib/archimate/svg/entity/node.rb +33 -0
  175. data/lib/archimate/svg/entity/node_shape.rb +64 -0
  176. data/lib/archimate/svg/entity/note.rb +30 -0
  177. data/lib/archimate/svg/entity/or_junction.rb +14 -0
  178. data/lib/archimate/svg/entity/outcome.rb +15 -0
  179. data/lib/archimate/svg/entity/path.rb +14 -0
  180. data/lib/archimate/svg/entity/plateau.rb +15 -0
  181. data/lib/archimate/svg/entity/principle.rb +15 -0
  182. data/lib/archimate/svg/entity/process_entity.rb +63 -0
  183. data/lib/archimate/svg/entity/product.rb +20 -0
  184. data/lib/archimate/svg/entity/rect.rb +13 -0
  185. data/lib/archimate/svg/entity/rect_entity.rb +25 -0
  186. data/lib/archimate/svg/entity/representation.rb +31 -0
  187. data/lib/archimate/svg/entity/requirement.rb +15 -0
  188. data/lib/archimate/svg/entity/resource.rb +14 -0
  189. data/lib/archimate/svg/entity/rounded_rect_entity.rb +23 -0
  190. data/lib/archimate/svg/entity/service_entity.rb +51 -0
  191. data/lib/archimate/svg/entity/sketch_model_sticky.rb +14 -0
  192. data/lib/archimate/svg/entity/stakeholder.rb +15 -0
  193. data/lib/archimate/svg/entity/system_software.rb +14 -0
  194. data/lib/archimate/svg/entity/technology_collaboration.rb +14 -0
  195. data/lib/archimate/svg/entity/technology_event.rb +13 -0
  196. data/lib/archimate/svg/entity/technology_function.rb +13 -0
  197. data/lib/archimate/svg/entity/technology_interaction.rb +13 -0
  198. data/lib/archimate/svg/entity/technology_interface.rb +13 -0
  199. data/lib/archimate/svg/entity/technology_process.rb +13 -0
  200. data/lib/archimate/svg/entity/technology_service.rb +13 -0
  201. data/lib/archimate/svg/entity/value.rb +27 -0
  202. data/lib/archimate/svg/entity/work_package.rb +14 -0
  203. data/lib/archimate/svg/entity.rb +93 -0
  204. data/lib/archimate/svg/entity_factory.rb +17 -0
  205. data/lib/archimate/svg/extents.rb +27 -0
  206. data/lib/archimate/svg/point.rb +7 -0
  207. data/lib/archimate/svg/svg_template.rb +27 -0
  208. data/lib/archimate/svg/svg_template.svg.erb +169 -0
  209. data/lib/archimate/version.rb +4 -0
  210. data/lib/archimate.rb +114 -0
  211. metadata +623 -0
@@ -0,0 +1,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
+ ['&#13;', '&#xD;'],
12
+ ['"', '&quot;'],
13
+ ['&gt;', '>']
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