Class: Archimate::FileFormats::ModelExchangeFileReader

Inherits:
Object
  • Object
show all
Defined in:
lib/archimate/file_formats/model_exchange_file_reader.rb

Overview

This class implements common methods for the ArchiMate Model Exchange Format

Instance Method Summary collapse

Instance Method Details

#identifier_to_id(str) ⇒ Object



231
232
233
234
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 231

def identifier_to_id(str)
  # str&.sub(/^id-/, "")
  str
end

#parse(doc) ⇒ Object

Parses a Nokogiri document into an Archimate::Model



9
10
11
12
13
14
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 9

def parse(doc)
  return unless doc
  @property_defs = []
  @viewpoints = []
  parse_model(doc.root)
end

#parse_bendpoints(node) ⇒ Object



223
224
225
226
227
228
229
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 223

def parse_bendpoints(node)
  node.css("bendpoint").map do |i|
    DataModel::Location.new(
      x: i.attr("x"), y: i.attr("y")
    )
  end
end

#parse_bounds(node) ⇒ Object



197
198
199
200
201
202
203
204
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 197

def parse_bounds(node)
  DataModel::Bounds.new(
    x: node.attr("x"),
    y: node.attr("y"),
    width: node.attr("w"),
    height: node.attr("h")
  )
end

#parse_color(node, el_name) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 185

def parse_color(node, el_name)
  return unless node
  color_node = node.at_css(el_name)
  return unless color_node
  DataModel::Color.new(
    r: color_node["r"]&.to_i,
    g: color_node["g"]&.to_i,
    b: color_node["b"]&.to_i,
    a: color_node["a"]&.to_i
  )
end

#parse_connections(node) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 206

def parse_connections(node)
  node.css("> connection").map do |i|
    DataModel::Connection.new(
      id: identifier_to_id(i["identifier"]),
      type: i.attr(view_node_type_attr),
      source: identifier_to_id(i["source"]),
      target: identifier_to_id(i["target"]),
      relationship: identifier_to_id(i[connection_relationship_ref]),
      name: i.at_css("label")&.content,
      style: parse_style(i),
      bendpoints: parse_bendpoints(i),
      documentation: parse_documentation(i),
      properties: parse_properties(i)
    )
  end
end

#parse_diagrams(model) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 115

def parse_diagrams(model)
  model.css(diagrams_path).map do |i|
    nodes = parse_nodes(i)
    connections = parse_connections(i)
    child_id_hash = nodes.each_with_object({}) { |i2, a| a.merge!(i2.child_id_hash) }
    connections.each do |c|
      child_id_hash[c.source].connections << c
    end
    DataModel::Diagram.new(
      id: identifier_to_id(i["identifier"]),
      name: parse_element_name(i),
      viewpoint_type: i["viewpoint"],
      viewpoint: nil, # TODO: support this for ArchiMate v3
      documentation: parse_documentation(i),
      properties: parse_properties(i),
      nodes: nodes,
      connections: connections,
      connection_router_type: i["connectionRouterType"],
      type: i.attr("xsi:type"),
      background: i.attr("background")
    )
  end
end

#parse_documentation(node, element_name = "documentation") ⇒ Object



43
44
45
46
47
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 43

def parse_documentation(node, element_name = "documentation")
  node.css(">#{element_name}").map do |doc|
    DataModel::Documentation.new(text: doc.content, lang: doc["xml:lang"])
  end
end

#parse_elements(model) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 74

def parse_elements(model)
  model.css(">elements>element").map do |i|
    DataModel::Element.new(
      id: identifier_to_id(i["identifier"]),
      name: parse_element_name(i),
      type: i["xsi:type"],
      documentation: parse_documentation(i),
      properties: parse_properties(i)
    )
  end
end

#parse_font(node) ⇒ Object



174
175
176
177
178
179
180
181
182
183
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 174

def parse_font(node)
  font_node = node.at_css(">font")
  return unless font_node && font_node["name"] && font_node["size"]
  DataModel::Font.new(
    name: font_node["name"],
    size: font_node["size"],
    style: style_to_int(font_node["style"]),
    font_data: nil
  )
end

#parse_model(root) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 16

def parse_model(root)
  @property_defs = parse_property_defs(root)
  @viewpoints = parse_viewpoints(root)
  DataModel::Model.new(
    index_hash: {},
    id: identifier_to_id(root["identifier"]),
    name: ModelExchangeFile::XmlLangString.parse(root.at_css(">name")),
    version: root["version"],
    metadata: ModelExchangeFile::XmlMetadata.parse(root.at_css(">metadata")),
    documentation: parse_documentation(root),
    properties: parse_properties(root),
    elements: parse_elements(root),
    relationships: parse_relationships(root),
    organizations: parse_organizations(root.css(organizations_root_selector)),
    diagrams: parse_diagrams(root),
    viewpoints: @viewpoints,
    property_definitions: @property_defs,
    schema_locations: root.attr("xsi:schemaLocation").split(" "),
    namespaces: root.namespaces,
    archimate_version: parse_archimate_version(root)
  )
end

#parse_nodes(node) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 139

def parse_nodes(node)
  node.css("> node").map do |i|
    DataModel::ViewNode.new(
      id: identifier_to_id(i["identifier"]),
      type: i.attr(view_node_type_attr),
      model: nil,
      name: ModelExchangeFile::XmlLangString.parse(i.at_css(">label")),
      target_connections: [], # TODO: needed? "targetConnections",
      archimate_element: identifier_to_id(i[view_node_element_ref]),
      bounds: parse_bounds(i),
      nodes: parse_nodes(i),
      connections: parse_connections(i),
      documentation: parse_documentation(i),
      properties: parse_properties(i),
      style: parse_style(i),
      content: i.at_css("> content")&.text,
      child_type: nil
    )
  end
end

#parse_organizations(nodes) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 86

def parse_organizations(nodes)
  nodes.map do |i|
    child_items = i.css(">item")
    ref_items = child_items.select { |ci| ci.has_attribute?(identifier_ref_name) }
    DataModel::Organization.new(
      id: i["identifier"], # TODO: model exchange doesn't assign ids to organization items
      name: ModelExchangeFile::XmlLangString.parse(i.at_css(">label")),
      documentation: parse_documentation(i),
      items: ref_items.map { |ri| identifier_to_id(ri[identifier_ref_name]) },
      organizations: parse_organizations(child_items.reject { |ci| ci.has_attribute?(identifier_ref_name) })
    )
  end
end

#parse_properties(node) ⇒ Object



49
50
51
52
53
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 49

def parse_properties(node)
  node.css("> properties > property").map do |i|
    parse_property(i)
  end
end

#parse_property(node) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 55

def parse_property(node)
  property_def = @property_defs.find { |prop_def| prop_def.id == node.attr(property_def_attr_name) }
  DataModel::Property.new(
    property_definition: property_def,
    values: [ModelExchangeFile::XmlLangString.parse(node.at_css("value"))].compact
  )
end

#parse_property_defs(node) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 63

def parse_property_defs(node)
  @property_defs = node.css(property_defs_selector).map do |i|
    DataModel::PropertyDefinition.new(
      id: i["identifier"],
      name: property_def_name(i),
      documentation: parse_documentation(i),
      value_type: i["type"]
    )
  end
end

#parse_relationships(model) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 100

def parse_relationships(model)
  model.css(">relationships>relationship").map do |i|
    DataModel::Relationship.new(
      id: identifier_to_id(i["identifier"]),
      type: i.attr("xsi:type"),
      source: identifier_to_id(i.attr("source")),
      target: identifier_to_id(i.attr("target")),
      name: parse_element_name(i),
      access_type: i["accessType"],
      documentation: parse_documentation(i),
      properties: parse_properties(i)
    )
  end
end

#parse_style(node) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 160

def parse_style(node)
  style = node.at_css(">style")
  return nil unless style
  DataModel::Style.new(
    text_alignment: style["textAlignment"],
    fill_color: parse_color(style, "fillColor"),
    line_color: parse_color(style, "lineColor"),
    font_color: parse_color(style.at_css(">font"), "color"),
    font: parse_font(style),
    line_width: style["lineWidth"],
    text_position: style.at_css("textPosition")
  )
end

#parse_viewpoints(_node) ⇒ Object



39
40
41
# File 'lib/archimate/file_formats/model_exchange_file_reader.rb', line 39

def parse_viewpoints(_node)
  return []
end