ea 0.6.132 → 0.6.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ea/model/document.rb +2 -11
- data/lib/ea/model/package_alias_index.rb +22 -0
- data/lib/ea/model.rb +1 -0
- data/lib/ea/sources/qea/diagram_builder/routing.rb +37 -0
- data/lib/ea/sources/xmi/classifier_builder.rb +6 -10
- data/lib/ea/sources/xmi/diagram_builder/umldi_edges.rb +32 -6
- data/lib/ea/sources/xmi/diagram_builder.rb +39 -17
- data/lib/ea/sources/xmi/legend_builder.rb +40 -0
- data/lib/ea/sources/xmi/note_builder.rb +16 -7
- data/lib/ea/sources/xmi/relationship_builder.rb +34 -7
- data/lib/ea/sources/xmi.rb +1 -0
- data/lib/ea/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3320f99ef26e1639eaa88eba212fe6620cc7c25b5337681431bf1ba991c384c1
|
|
4
|
+
data.tar.gz: 3a72b42b4c3dd40b4254ec74684b3e74a25e6f35f1efc85ec8e7bb1fc59f113b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ce24e25f39d48215c9dcbe03b8c86a932ffd310d64f228e6e5603448814faf84fc023f1a07dae736f4dabb926970b86d1bd478e51d640366462c1765a643796
|
|
7
|
+
data.tar.gz: 19a7f0f2e20a3985c32de44288755f7daa7f5f35e41908c6491a9ada31562059c20826e75d7482ad494b8e9c2e15ab32f5635f1801607c359f7fcdc6a455ea50
|
data/lib/ea/model/document.rb
CHANGED
|
@@ -58,11 +58,8 @@ module Ea
|
|
|
58
58
|
# `model_element_ref` lookups from diagram elements resolve.
|
|
59
59
|
def index_by_id
|
|
60
60
|
@index_by_id ||= begin
|
|
61
|
-
idx =
|
|
62
|
-
packages.each
|
|
63
|
-
idx[p.id] = p
|
|
64
|
-
alias_eaid_for_package(idx, p)
|
|
65
|
-
end
|
|
61
|
+
idx = PackageAliasIndex.new
|
|
62
|
+
packages.each { |p| idx[p.id] = p }
|
|
66
63
|
classifiers.each { |c| idx[c.id] = c }
|
|
67
64
|
relationships.each { |r| idx[r.id] = r }
|
|
68
65
|
stereotypes.each { |s| idx[s.id] = s }
|
|
@@ -98,12 +95,6 @@ module Ea
|
|
|
98
95
|
property_index[id]
|
|
99
96
|
end
|
|
100
97
|
|
|
101
|
-
def alias_eaid_for_package(idx, package)
|
|
102
|
-
return unless package.id&.start_with?("EAPK_")
|
|
103
|
-
|
|
104
|
-
idx["EAID_#{package.id[5..]}"] = package
|
|
105
|
-
end
|
|
106
|
-
|
|
107
98
|
def root_packages
|
|
108
99
|
packages.select { |p| p.parent_id.nil? }
|
|
109
100
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Model
|
|
5
|
+
# Id-keyed lookup in which a package stored under `EAPK_<guid>`
|
|
6
|
+
# also answers to `EAID_<guid>`, without a second entry: `values`
|
|
7
|
+
# lists each package once.
|
|
8
|
+
class PackageAliasIndex < Hash
|
|
9
|
+
def [](id)
|
|
10
|
+
super || package_alias(id)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def package_alias(id)
|
|
16
|
+
return unless id.is_a?(String) && id.start_with?("EAID_")
|
|
17
|
+
|
|
18
|
+
fetch("EAPK_#{id[5..]}", nil)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/ea/model.rb
CHANGED
|
@@ -19,6 +19,7 @@ module Ea
|
|
|
19
19
|
autoload :Base, "ea/model/base"
|
|
20
20
|
autoload :Metadata, "ea/model/metadata"
|
|
21
21
|
autoload :Point, "ea/model/point"
|
|
22
|
+
autoload :PackageAliasIndex, "ea/model/package_alias_index"
|
|
22
23
|
autoload :Bounds, "ea/model/bounds"
|
|
23
24
|
autoload :Waypoint, "ea/model/waypoint"
|
|
24
25
|
autoload :Annotation, "ea/model/annotation"
|
|
@@ -182,6 +182,7 @@ module Ea
|
|
|
182
182
|
def correct_stored_ray_origins(model, link_row, diagram_row, geom, context)
|
|
183
183
|
return model if context
|
|
184
184
|
return notelink_stored_ray(model, link_row, diagram_row, geom) if model.connector_type == "NoteLink"
|
|
185
|
+
return package_stored_ray(model, link_row, diagram_row, geom) if model.connector_type == "Package"
|
|
185
186
|
return model unless stored_ray_candidate?(model, link_row, geom)
|
|
186
187
|
|
|
187
188
|
source, target = stored_ray_boxes(link_row, diagram_row)
|
|
@@ -199,6 +200,42 @@ module Ea
|
|
|
199
200
|
model
|
|
200
201
|
end
|
|
201
202
|
|
|
203
|
+
# An empty custom-line package import has no authored bend. When
|
|
204
|
+
# its stored mathematical origins share a row inside both boxes,
|
|
205
|
+
# clip that ray instead of the computed EDGE2 port jog.
|
|
206
|
+
def package_stored_ray(model, link_row, diagram_row, geom)
|
|
207
|
+
return model unless package_ray_candidate?(model, link_row, geom)
|
|
208
|
+
|
|
209
|
+
boxes = stored_ray_boxes(link_row, diagram_row)
|
|
210
|
+
origins = level_package_origins(boxes, geom)
|
|
211
|
+
return model unless origins
|
|
212
|
+
|
|
213
|
+
model.waypoints = package_ray_waypoints(boxes, origins.first.y)
|
|
214
|
+
model.source_anchor, model.target_anchor = origins
|
|
215
|
+
model
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def package_ray_candidate?(model, link_row, geom)
|
|
219
|
+
model.waypoints.size == 3 && link_row.path.to_s.empty? &&
|
|
220
|
+
model.style.values_at(:mode, :lwidth, :tree) == ["3", "0", nil] &&
|
|
221
|
+
geom[:edge] == 2 && geom.values_at(:sx, :sy, :ex, :ey).all?
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def level_package_origins(boxes, geom)
|
|
225
|
+
return unless horizontal_ray_gap?(*boxes)
|
|
226
|
+
|
|
227
|
+
origins = association_ray_origins(*boxes, geom, "0")
|
|
228
|
+
origins if origins && origins.first.y == origins.last.y
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def package_ray_waypoints(boxes, row)
|
|
232
|
+
rightward = boxes[0].x < boxes[1].x
|
|
233
|
+
boxes.each_with_index.map do |box, index|
|
|
234
|
+
x = box.x + (rightward == index.zero? ? box.width : 0)
|
|
235
|
+
Ea::Model::Waypoint.new(position: Ea::Model::Point.new(x: x, y: row))
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
202
239
|
# A straight top-docked NoteLink uses mathematical saved Y offsets,
|
|
203
240
|
# like the other custom rays, while authored bends keep their ports.
|
|
204
241
|
def notelink_stored_ray(model, link_row, diagram_row, geom)
|
|
@@ -82,18 +82,14 @@ module Ea
|
|
|
82
82
|
{ literals: literals }
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
+
# A name that already carries a namespace prefix
|
|
86
|
+
# (e.g. "gml:CodeType") is the qualified name as saved.
|
|
85
87
|
def qualified_name(element, containing_package)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# produce "xs::xs:string". Strip the existing namespace
|
|
90
|
-
# prefix from the simple name before composing the
|
|
91
|
-
# qualified name.
|
|
92
|
-
raw = element.name.to_s
|
|
93
|
-
simple = raw.split(":").last
|
|
94
|
-
simple = raw if simple.nil? || simple.empty?
|
|
88
|
+
name = element.name.to_s
|
|
89
|
+
return name if name.include?(":")
|
|
90
|
+
|
|
95
91
|
pkg_name = containing_package&.name
|
|
96
|
-
pkg_name ? "#{pkg_name}::#{
|
|
92
|
+
pkg_name ? "#{pkg_name}::#{name}" : name
|
|
97
93
|
end
|
|
98
94
|
|
|
99
95
|
def boolean(value)
|
|
@@ -6,9 +6,10 @@ module Ea
|
|
|
6
6
|
module Sources
|
|
7
7
|
module Xmi
|
|
8
8
|
class DiagramBuilder
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
9
|
+
# The UMLDI edge EA exported for a connector on a diagram: its
|
|
10
|
+
# ordered waypoints and its source/target model elements. A connector
|
|
11
|
+
# drawn by more than one edge in the same diagram has neither; an edge
|
|
12
|
+
# with fewer than two waypoints has no route.
|
|
12
13
|
class UmldiEdges
|
|
13
14
|
def initialize(xmi_path)
|
|
14
15
|
@xmi_path = xmi_path
|
|
@@ -18,8 +19,34 @@ module Ea
|
|
|
18
19
|
routes.dig(diagram_id, connector_id)
|
|
19
20
|
end
|
|
20
21
|
|
|
22
|
+
def ends_for(diagram_id, connector_id)
|
|
23
|
+
ends.dig(diagram_id, connector_id)
|
|
24
|
+
end
|
|
25
|
+
|
|
21
26
|
private
|
|
22
27
|
|
|
28
|
+
def ends
|
|
29
|
+
@ends ||= doc.xpath("//*[local-name()=\"Diagram\"]").to_h do |diagram|
|
|
30
|
+
[diagram["id"] || diagram["xmi:id"], diagram_ends(diagram)]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def diagram_ends(diagram)
|
|
35
|
+
unique_edges(diagram).each_with_object({}) do |(connector_id, edge), acc|
|
|
36
|
+
acc[connector_id] = [edge["source"], edge["target"]] if edge["source"] && edge["target"]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Edges keyed by connector, keeping only connectors drawn by exactly
|
|
41
|
+
# one edge of the diagram, whatever that edge carries.
|
|
42
|
+
def unique_edges(diagram)
|
|
43
|
+
diagram.xpath("./ownedElement[@modelElement]")
|
|
44
|
+
.select { |node| node.attributes["type"]&.value.to_s.end_with?("UMLEdge") }
|
|
45
|
+
.group_by { |edge| edge["modelElement"] }
|
|
46
|
+
.select { |_, same| same.one? }
|
|
47
|
+
.transform_values(&:first)
|
|
48
|
+
end
|
|
49
|
+
|
|
23
50
|
def routes
|
|
24
51
|
@routes ||= doc.xpath("//*[local-name()=\"Diagram\"]").to_h do |diagram|
|
|
25
52
|
[diagram["id"] || diagram["xmi:id"], diagram_routes(diagram)]
|
|
@@ -27,9 +54,8 @@ module Ea
|
|
|
27
54
|
end
|
|
28
55
|
|
|
29
56
|
def diagram_routes(diagram)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
points = same.one? ? waypoints(same.first) : []
|
|
57
|
+
unique_edges(diagram).each_with_object({}) do |(connector_id, edge), acc|
|
|
58
|
+
points = waypoints(edge)
|
|
33
59
|
acc[connector_id] = points if points.size >= 2
|
|
34
60
|
end
|
|
35
61
|
end
|
|
@@ -52,10 +52,12 @@ module Ea
|
|
|
52
52
|
name: props&.name || ext_diagram.id,
|
|
53
53
|
package_id: ext_diagram.model&.package,
|
|
54
54
|
diagram_type: props&.type&.split(":")&.last&.downcase,
|
|
55
|
-
bounds:
|
|
55
|
+
bounds: page_bounds(ext_diagram),
|
|
56
56
|
style: style_for(ext_diagram),
|
|
57
57
|
style_ex: style_ex_for(ext_diagram),
|
|
58
58
|
show_notes: style_ex_for(ext_diagram).to_s.include?("ShowNotes=1"),
|
|
59
|
+
show_package_contents: style_flag?(ext_diagram, "PackageContents"),
|
|
60
|
+
show_foreign: style_flag?(ext_diagram, "HighlightForeign"),
|
|
59
61
|
elements: build_elements(placed_elements, id, umldi_keywords),
|
|
60
62
|
connectors: build_connectors(placed_connectors,
|
|
61
63
|
placed_elements, id),
|
|
@@ -89,18 +91,18 @@ module Ea
|
|
|
89
91
|
|
|
90
92
|
private
|
|
91
93
|
|
|
92
|
-
def
|
|
93
|
-
|
|
94
|
+
def style_flag?(ext_diagram, key)
|
|
95
|
+
value = style_for(ext_diagram).to_s[/(?:\A|;)#{key}=(\d+)/, 1]
|
|
96
|
+
value.to_i.nonzero? ? true : false
|
|
97
|
+
end
|
|
94
98
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return nil unless
|
|
99
|
+
def page_bounds(ext_diagram)
|
|
100
|
+
style = style_for(ext_diagram).to_s
|
|
101
|
+
width = style[/(?:\A|;)DocSize\.cx=(\d+)/, 1]
|
|
102
|
+
height = style[/(?:\A|;)DocSize\.cy=(\d+)/, 1]
|
|
103
|
+
return nil unless width && height
|
|
100
104
|
|
|
101
|
-
Ea::Model::Bounds.new(x: 0, y: 0,
|
|
102
|
-
width: right - left,
|
|
103
|
-
height: bottom - top)
|
|
105
|
+
Ea::Model::Bounds.new(x: 0, y: 0, width: width.to_i, height: height.to_i)
|
|
104
106
|
end
|
|
105
107
|
|
|
106
108
|
def build_elements(placed, owner_id, umldi_keywords = {})
|
|
@@ -110,12 +112,13 @@ module Ea
|
|
|
110
112
|
def build_element(placed, owner_id, umldi_keywords = {})
|
|
111
113
|
geom = placed.geometry
|
|
112
114
|
style = placed.style
|
|
115
|
+
bounds = build_bounds(geom.left, geom.top, geom.right, geom.bottom)
|
|
113
116
|
Ea::Model::DiagramElement.new(
|
|
114
117
|
id: IdNormalizer.synthetic_id(owner_id, "elem", placed.subject),
|
|
115
118
|
diagram_id: owner_id,
|
|
116
119
|
model_element_ref: placed.subject,
|
|
117
|
-
bounds:
|
|
118
|
-
image_bounds: build_bounds(geom.img_left, geom.img_top, geom.img_right, geom.img_bottom),
|
|
120
|
+
bounds: bounds,
|
|
121
|
+
image_bounds: (build_bounds(geom.img_left, geom.img_top, geom.img_right, geom.img_bottom) unless bounds),
|
|
119
122
|
background_color: style.background_color,
|
|
120
123
|
line_color: style.line_color,
|
|
121
124
|
line_width: style.line_width,
|
|
@@ -146,17 +149,19 @@ module Ea
|
|
|
146
149
|
by_duid = placed_elements.each_with_object({}) do |pe, acc|
|
|
147
150
|
acc[pe.style.duid] = pe if pe.style.duid
|
|
148
151
|
end
|
|
152
|
+
by_subject = placed_elements.group_by { |pe| guid_key(pe.subject) }
|
|
149
153
|
|
|
150
154
|
placed_connectors.each_with_index.map do |placed, index|
|
|
151
|
-
build_connector(placed, by_duid, owner_id, index)
|
|
155
|
+
build_connector(placed, by_duid, by_subject, owner_id, index)
|
|
152
156
|
end
|
|
153
157
|
end
|
|
154
158
|
|
|
155
|
-
def build_connector(placed, by_duid, owner_id, rank)
|
|
159
|
+
def build_connector(placed, by_duid, by_subject, owner_id, rank)
|
|
156
160
|
geom = placed.geometry
|
|
157
161
|
style = placed.style
|
|
158
|
-
|
|
159
|
-
|
|
162
|
+
edge_source, edge_target = umldi_ends(owner_id, placed)
|
|
163
|
+
source = by_duid[style.soid] || sole_placement(by_subject, edge_source)
|
|
164
|
+
target = by_duid[style.eoid] || sole_placement(by_subject, edge_target)
|
|
160
165
|
ext_meta = connector_meta(placed.subject)
|
|
161
166
|
route = connector_route(placed, source, target, owner_id, ext_meta[:ea_type])
|
|
162
167
|
Ea::Model::DiagramConnector.new(
|
|
@@ -234,6 +239,23 @@ module Ea
|
|
|
234
239
|
route&.map { |x, y| Ea::Model::Waypoint.new(position: Ea::Model::Point.new(x: x, y: y)) }
|
|
235
240
|
end
|
|
236
241
|
|
|
242
|
+
def umldi_ends(diagram_id, placed)
|
|
243
|
+
return unless xmi_path
|
|
244
|
+
|
|
245
|
+
umldi_edges.ends_for(diagram_id, placed.subject)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def sole_placement(by_subject, subject)
|
|
249
|
+
placements = by_subject[guid_key(subject)]
|
|
250
|
+
placements.first if placements&.one?
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# EA spells one GUID with an EAID_ or EAPK_ prefix and mixed case
|
|
254
|
+
# depending on the element kind.
|
|
255
|
+
def guid_key(subject)
|
|
256
|
+
subject&.sub(/\AEA(?:ID|PK)_/, "")&.upcase
|
|
257
|
+
end
|
|
258
|
+
|
|
237
259
|
def umldi_edges
|
|
238
260
|
@umldi_edges ||= UmldiEdges.new(xmi_path)
|
|
239
261
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Sources
|
|
5
|
+
module Xmi
|
|
6
|
+
# Builds an `Ea::Model::Legend` from the `value` of an element's
|
|
7
|
+
# `<xrefs>` element. The CustomProperties description inside it
|
|
8
|
+
# uses the same `@PROP=...@ENDPROP;` encoding as the QEA t_xref
|
|
9
|
+
# row, so parsing is delegated to the QEA legend builder.
|
|
10
|
+
#
|
|
11
|
+
# Returns nil when the value carries no legend properties.
|
|
12
|
+
class LegendBuilder
|
|
13
|
+
CLIENT = "xmi-element"
|
|
14
|
+
|
|
15
|
+
XrefRow = Struct.new(:name, :description)
|
|
16
|
+
|
|
17
|
+
# Answers the one CustomProperties xref lookup the QEA builder makes.
|
|
18
|
+
class SingleElementXrefs
|
|
19
|
+
def initialize(description)
|
|
20
|
+
@rows = [XrefRow.new(Qea::LegendBuilder::LEGEND_XREF_NAME, description)]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def xrefs_for_client(_guid)
|
|
24
|
+
@rows
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(xrefs_value)
|
|
29
|
+
@xrefs_value = xrefs_value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build
|
|
33
|
+
return nil if @xrefs_value.to_s.empty?
|
|
34
|
+
|
|
35
|
+
Qea::LegendBuilder.new(SingleElementXrefs.new(@xrefs_value)).build_for(CLIENT)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -10,9 +10,12 @@ module Ea
|
|
|
10
10
|
# inside `<xmi:Extension>/<elements>`. Each carries a
|
|
11
11
|
# `<properties documentation="..."/>` child with the body text.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# `uml:Text` elements are projected the same way; those whose
|
|
14
|
+
# CustomProperties xref carries legend configuration also
|
|
15
|
+
# get an `Ea::Model::Legend` payload.
|
|
15
16
|
class NoteBuilder
|
|
17
|
+
NOTE_TYPES = { "uml:Note" => "Note", "uml:Text" => "Text" }.freeze
|
|
18
|
+
|
|
16
19
|
attr_reader :root
|
|
17
20
|
|
|
18
21
|
def initialize(root)
|
|
@@ -29,17 +32,23 @@ module Ea
|
|
|
29
32
|
private
|
|
30
33
|
|
|
31
34
|
def build_one(ext_element)
|
|
32
|
-
|
|
33
|
-
return nil unless
|
|
35
|
+
note_type = NOTE_TYPES[ext_element.type]
|
|
36
|
+
return nil unless note_type
|
|
34
37
|
|
|
35
|
-
props = ext_element.properties
|
|
36
38
|
Ea::Model::Note.new(
|
|
37
39
|
id: ext_element.idref,
|
|
38
40
|
name: ext_element.name,
|
|
39
|
-
body:
|
|
40
|
-
note_type:
|
|
41
|
+
body: ext_element.properties&.documentation,
|
|
42
|
+
note_type: note_type,
|
|
43
|
+
legend: legend_for(ext_element, note_type)
|
|
41
44
|
)
|
|
42
45
|
end
|
|
46
|
+
|
|
47
|
+
def legend_for(ext_element, note_type)
|
|
48
|
+
return nil unless note_type == "Text"
|
|
49
|
+
|
|
50
|
+
LegendBuilder.new(ext_element.xrefs&.value).build
|
|
51
|
+
end
|
|
43
52
|
end
|
|
44
53
|
end
|
|
45
54
|
end
|
|
@@ -9,6 +9,8 @@ module Ea
|
|
|
9
9
|
class RelationshipBuilder
|
|
10
10
|
# Connector types that imply an aggregation on the source end
|
|
11
11
|
# when the end itself records none.
|
|
12
|
+
CONNECTOR_STEREOTYPE = /(?<=@STEREO;Name=)[^;]+/
|
|
13
|
+
|
|
12
14
|
AGGREGATION_FOR_CONNECTOR_TYPE = {
|
|
13
15
|
"Aggregation" => "shared",
|
|
14
16
|
"Composition" => "composite"
|
|
@@ -28,7 +30,7 @@ module Ea
|
|
|
28
30
|
rel = build_one(element)
|
|
29
31
|
relationships << rel if rel
|
|
30
32
|
end
|
|
31
|
-
relationships
|
|
33
|
+
relationships + package_import_relationships(relationships)
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
def build_one(element)
|
|
@@ -40,6 +42,30 @@ module Ea
|
|
|
40
42
|
|
|
41
43
|
private
|
|
42
44
|
|
|
45
|
+
def package_import_relationships(built)
|
|
46
|
+
built_ids = built.to_set(&:id)
|
|
47
|
+
connector_index.filter_map do |id, connector|
|
|
48
|
+
next if built_ids.include?(id) || connector.properties&.ea_type != "Package"
|
|
49
|
+
|
|
50
|
+
package_import_relationship(id, connector)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def connector_stereotype(connector)
|
|
55
|
+
connector&.xrefs&.value.to_s[CONNECTOR_STEREOTYPE]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def package_import_relationship(id, connector)
|
|
59
|
+
Ea::Model::Association.new(
|
|
60
|
+
id: id,
|
|
61
|
+
stereotype: connector_stereotype(connector),
|
|
62
|
+
source_id: connector.source&.idref,
|
|
63
|
+
target_id: connector.target&.idref,
|
|
64
|
+
source_navigable: navigable?(id, :source),
|
|
65
|
+
target_navigable: navigable?(id, :target)
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
43
69
|
def walk(element, &block)
|
|
44
70
|
yield element if block
|
|
45
71
|
element.packaged_element.each { |inner| walk(inner, &block) }
|
|
@@ -51,6 +77,7 @@ module Ea
|
|
|
51
77
|
id: id,
|
|
52
78
|
name: element.name,
|
|
53
79
|
qualified_name: element.name,
|
|
80
|
+
stereotype: connector_stereotype(connector_index[id]),
|
|
54
81
|
annotations: AnnotationBuilder.from_element(element, id)
|
|
55
82
|
}
|
|
56
83
|
end
|
|
@@ -88,8 +115,8 @@ module Ea
|
|
|
88
115
|
target_multiplicity_raw: raw_card(target.type&.multiplicity),
|
|
89
116
|
source_aggregation: source_aggregation(connector),
|
|
90
117
|
target_aggregation: target.type&.aggregation || "none",
|
|
91
|
-
source_navigable: navigable?(element, :source),
|
|
92
|
-
target_navigable: navigable?(element, :target)
|
|
118
|
+
source_navigable: navigable?(element.id, :source),
|
|
119
|
+
target_navigable: navigable?(element.id, :target)
|
|
93
120
|
}
|
|
94
121
|
end
|
|
95
122
|
|
|
@@ -118,8 +145,8 @@ module Ea
|
|
|
118
145
|
target_multiplicity_upper: parse_upper(target_end),
|
|
119
146
|
source_aggregation: source_end&.aggregation || "none",
|
|
120
147
|
target_aggregation: target_end&.aggregation || "none",
|
|
121
|
-
source_navigable: navigable?(element, :source),
|
|
122
|
-
target_navigable: navigable?(element, :target)
|
|
148
|
+
source_navigable: navigable?(element.id, :source),
|
|
149
|
+
target_navigable: navigable?(element.id, :target)
|
|
123
150
|
}
|
|
124
151
|
end
|
|
125
152
|
|
|
@@ -197,8 +224,8 @@ module Ea
|
|
|
197
224
|
end
|
|
198
225
|
end
|
|
199
226
|
|
|
200
|
-
def navigable?(
|
|
201
|
-
connector = connector_index[
|
|
227
|
+
def navigable?(id, endpoint)
|
|
228
|
+
connector = connector_index[id]
|
|
202
229
|
end_element = connector&.public_send(endpoint)
|
|
203
230
|
flag = end_element&.modifiers&.is_navigable
|
|
204
231
|
flag.nil? || flag
|
data/lib/ea/sources/xmi.rb
CHANGED
|
@@ -25,6 +25,7 @@ module Ea
|
|
|
25
25
|
autoload :RelationshipBuilder, "ea/sources/xmi/relationship_builder"
|
|
26
26
|
autoload :AnnotationBuilder, "ea/sources/xmi/annotation_builder"
|
|
27
27
|
autoload :TagBuilder, "ea/sources/xmi/tag_builder"
|
|
28
|
+
autoload :LegendBuilder, "ea/sources/xmi/legend_builder"
|
|
28
29
|
autoload :NoteBuilder, "ea/sources/xmi/note_builder"
|
|
29
30
|
autoload :StereotypeBuilder, "ea/sources/xmi/stereotype_builder"
|
|
30
31
|
autoload :DiagramBuilder, "ea/sources/xmi/diagram_builder"
|
data/lib/ea/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ea
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.134
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -680,6 +680,7 @@ files:
|
|
|
680
680
|
- lib/ea/model/note.rb
|
|
681
681
|
- lib/ea/model/operation.rb
|
|
682
682
|
- lib/ea/model/package.rb
|
|
683
|
+
- lib/ea/model/package_alias_index.rb
|
|
683
684
|
- lib/ea/model/parameter.rb
|
|
684
685
|
- lib/ea/model/point.rb
|
|
685
686
|
- lib/ea/model/polymorphic_maps.rb
|
|
@@ -858,6 +859,7 @@ files:
|
|
|
858
859
|
- lib/ea/sources/xmi/extension_types.rb
|
|
859
860
|
- lib/ea/sources/xmi/id_normalizer.rb
|
|
860
861
|
- lib/ea/sources/xmi/instance_builder.rb
|
|
862
|
+
- lib/ea/sources/xmi/legend_builder.rb
|
|
861
863
|
- lib/ea/sources/xmi/metadata_builder.rb
|
|
862
864
|
- lib/ea/sources/xmi/note_builder.rb
|
|
863
865
|
- lib/ea/sources/xmi/operation_builder.rb
|