lutaml 0.10.13 → 0.10.15
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/.rubocop_todo.yml +29 -33
- data/lib/lutaml/cli/interactive_shell/export_handler.rb +25 -17
- data/lib/lutaml/cli/interactive_shell/help_display.rb +39 -45
- data/lib/lutaml/cli/interactive_shell/navigation_commands.rb +45 -26
- data/lib/lutaml/cli/interactive_shell/query_commands.rb +73 -47
- data/lib/lutaml/cli/interactive_shell.rb +53 -27
- data/lib/lutaml/cli/tree_view_formatter.rb +11 -3
- data/lib/lutaml/converter/xmi_to_uml.rb +11 -6
- data/lib/lutaml/formatter/graphviz.rb +65 -35
- data/lib/lutaml/model_transformations/parsers/base_parser.rb +27 -29
- data/lib/lutaml/qea/factory/association_builder.rb +144 -127
- data/lib/lutaml/qea/factory/class_transformer.rb +91 -53
- data/lib/lutaml/qea/factory/ea_to_uml_factory.rb +11 -22
- data/lib/lutaml/qea/factory/enum_transformer.rb +41 -31
- data/lib/lutaml/qea/factory/generalization_builder.rb +155 -125
- data/lib/lutaml/qea/factory/stereotype_loader.rb +13 -7
- data/lib/lutaml/qea/lookup_indexes.rb +31 -13
- data/lib/lutaml/uml/inheritance_walker.rb +11 -7
- data/lib/lutaml/uml_repository/exporters/markdown/class_page_builder.rb +33 -25
- data/lib/lutaml/uml_repository/exporters/markdown/index_page_builder.rb +17 -9
- data/lib/lutaml/uml_repository/exporters/markdown_exporter.rb +27 -20
- data/lib/lutaml/uml_repository/index_builders/association_index.rb +60 -48
- data/lib/lutaml/uml_repository/index_builders/class_index.rb +35 -24
- data/lib/lutaml/uml_repository/queries/class_query.rb +79 -48
- data/lib/lutaml/uml_repository/queries/inheritance_query.rb +42 -32
- data/lib/lutaml/uml_repository/queries/search_query.rb +93 -85
- data/lib/lutaml/uml_repository/query_dsl/conditions/package_condition.rb +9 -2
- data/lib/lutaml/uml_repository/repository/loader.rb +14 -7
- data/lib/lutaml/uml_repository/static_site/data_transformer.rb +64 -35
- data/lib/lutaml/uml_repository/static_site/search_index_builder.rb +32 -19
- data/lib/lutaml/uml_repository/static_site/serializers/class_serializer.rb +36 -20
- data/lib/lutaml/uml_repository/static_site/serializers/inheritance_resolver.rb +131 -105
- data/lib/lutaml/uml_repository/static_site/serializers/package_serializer.rb +15 -9
- data/lib/lutaml/uml_repository/static_site/serializers/package_tree_builder.rb +38 -24
- data/lib/lutaml/version.rb +1 -1
- data/lib/lutaml/xmi/liquid_drops/klass_drop.rb +34 -18
- data/lib/lutaml/xmi/parsers/xmi_connector.rb +35 -23
- metadata +2 -9
- data/TODO.cleanups/01-resolve-production-todos.md +0 -65
- data/TODO.cleanups/02-reduce-metrics-offenses.md +0 -37
- data/TODO.cleanups/03-reduce-rspec-multiple-expectations.md +0 -54
- data/TODO.cleanups/04-reduce-rspec-example-length.md +0 -45
- data/TODO.cleanups/07-fix-lint-offenses.md +0 -74
- data/TODO.cleanups/08-reduce-memoized-helpers-and-nesting.md +0 -43
- data/TODO.cleanups/09-reduce-verified-doubles-and-rspec-style.md +0 -57
|
@@ -33,24 +33,13 @@ module Lutaml
|
|
|
33
33
|
def transform
|
|
34
34
|
Models::SpaDocument.new(
|
|
35
35
|
metadata: Serializers::MetadataBuilder.new(repository).build,
|
|
36
|
-
package_tree:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
classes: Serializers::ClassSerializer.new(repository, id_generator,
|
|
41
|
-
options, inheritance_resolver).build_map,
|
|
42
|
-
attributes: Serializers::AttributeSerializer.new(repository,
|
|
43
|
-
id_generator, options).build_map,
|
|
36
|
+
package_tree: build_package_tree,
|
|
37
|
+
packages: build_packages_map,
|
|
38
|
+
classes: build_classes_map,
|
|
39
|
+
attributes: build_attributes_map,
|
|
44
40
|
associations: build_associations_map,
|
|
45
|
-
operations:
|
|
46
|
-
|
|
47
|
-
diagrams: if options[:include_diagrams]
|
|
48
|
-
Serializers::DiagramSerializer.new(
|
|
49
|
-
repository, id_generator, options
|
|
50
|
-
).build_map
|
|
51
|
-
else
|
|
52
|
-
{}
|
|
53
|
-
end,
|
|
41
|
+
operations: build_operations_map,
|
|
42
|
+
diagrams: build_diagrams_map,
|
|
54
43
|
)
|
|
55
44
|
end
|
|
56
45
|
|
|
@@ -74,24 +63,7 @@ module Lutaml
|
|
|
74
63
|
map = Hash.new { |h, k| h[k] = [] }
|
|
75
64
|
|
|
76
65
|
repository.classes_index.each do |klass|
|
|
77
|
-
|
|
78
|
-
unless klass.association_generalization && !klass.association_generalization.empty?
|
|
79
|
-
next
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
klass.association_generalization.each do |assoc_gen|
|
|
83
|
-
parent_object_id = assoc_gen.parent_object_id
|
|
84
|
-
next unless parent_object_id
|
|
85
|
-
|
|
86
|
-
parent_class = class_lookup.by_object_id(parent_object_id)
|
|
87
|
-
if parent_class&.xmi_id
|
|
88
|
-
next if parent_class.xmi_id == klass.xmi_id
|
|
89
|
-
|
|
90
|
-
unless map[klass.xmi_id].include?(parent_class.xmi_id)
|
|
91
|
-
map[klass.xmi_id] << parent_class.xmi_id
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
66
|
+
add_generalization_entries(map, klass)
|
|
95
67
|
end
|
|
96
68
|
|
|
97
69
|
map
|
|
@@ -101,6 +73,63 @@ module Lutaml
|
|
|
101
73
|
@class_lookup ||= ClassLookupIndex.new(repository.classes_index)
|
|
102
74
|
end
|
|
103
75
|
|
|
76
|
+
def build_package_tree
|
|
77
|
+
Serializers::PackageTreeBuilder.new(repository, id_generator).build
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def build_packages_map
|
|
81
|
+
Serializers::PackageSerializer.new(repository, id_generator,
|
|
82
|
+
options).build_map
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def build_classes_map
|
|
86
|
+
Serializers::ClassSerializer.new(repository, id_generator,
|
|
87
|
+
options, inheritance_resolver).build_map
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def build_attributes_map
|
|
91
|
+
Serializers::AttributeSerializer.new(repository, id_generator,
|
|
92
|
+
options).build_map
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_operations_map
|
|
96
|
+
Serializers::OperationSerializer.new(repository,
|
|
97
|
+
id_generator).build_map
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def build_diagrams_map
|
|
101
|
+
return {} unless options[:include_diagrams]
|
|
102
|
+
|
|
103
|
+
Serializers::DiagramSerializer.new(repository, id_generator,
|
|
104
|
+
options).build_map
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def add_generalization_entries(map, klass)
|
|
108
|
+
return unless klass.association_generalization
|
|
109
|
+
return if klass.association_generalization.empty?
|
|
110
|
+
|
|
111
|
+
klass.association_generalization.each do |assoc_gen|
|
|
112
|
+
add_valid_generalization_entry(map, klass, assoc_gen)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def add_valid_generalization_entry(map, klass, assoc_gen)
|
|
117
|
+
parent_xmi_id = resolve_parent_xmi_id(assoc_gen)
|
|
118
|
+
return unless parent_xmi_id
|
|
119
|
+
return if parent_xmi_id == klass.xmi_id
|
|
120
|
+
return if map[klass.xmi_id].include?(parent_xmi_id)
|
|
121
|
+
|
|
122
|
+
map[klass.xmi_id] << parent_xmi_id
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def resolve_parent_xmi_id(assoc_gen)
|
|
126
|
+
parent_object_id = assoc_gen.parent_object_id
|
|
127
|
+
return nil unless parent_object_id
|
|
128
|
+
|
|
129
|
+
parent_class = class_lookup.by_object_id(parent_object_id)
|
|
130
|
+
parent_class&.xmi_id
|
|
131
|
+
end
|
|
132
|
+
|
|
104
133
|
def format_definition(definition)
|
|
105
134
|
return nil if definition.nil? || definition.empty?
|
|
106
135
|
|
|
@@ -51,23 +51,9 @@ module Lutaml
|
|
|
51
51
|
|
|
52
52
|
def build_document_store
|
|
53
53
|
documents = []
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
klass.attributes&.each do |attr|
|
|
59
|
-
documents << build_attribute_document(attr, klass)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
repository.associations_index.each do |assoc|
|
|
64
|
-
documents << build_association_document(assoc)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
repository.packages_index.each do |package|
|
|
68
|
-
documents << build_package_document(package)
|
|
69
|
-
end
|
|
70
|
-
|
|
54
|
+
documents.concat(build_class_documents)
|
|
55
|
+
documents.concat(build_association_documents)
|
|
56
|
+
documents.concat(build_package_documents)
|
|
71
57
|
documents
|
|
72
58
|
end
|
|
73
59
|
|
|
@@ -135,8 +121,8 @@ module Lutaml
|
|
|
135
121
|
class_type(klass),
|
|
136
122
|
Array(klass.stereotype).join(" "),
|
|
137
123
|
klass.definition,
|
|
138
|
-
klass.attributes
|
|
139
|
-
klass.operations
|
|
124
|
+
collect_names(klass.attributes),
|
|
125
|
+
collect_names(klass.operations),
|
|
140
126
|
].compact
|
|
141
127
|
|
|
142
128
|
normalize_content(parts.join(" "))
|
|
@@ -186,6 +172,33 @@ module Lutaml
|
|
|
186
172
|
all_content.join(" ").gsub(/\s+/, " ").strip
|
|
187
173
|
end
|
|
188
174
|
|
|
175
|
+
def build_class_documents
|
|
176
|
+
docs = []
|
|
177
|
+
repository.classes_index.each do |klass|
|
|
178
|
+
docs << build_class_document(klass)
|
|
179
|
+
klass.attributes&.each do |attr|
|
|
180
|
+
docs << build_attribute_document(attr, klass)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
docs
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def build_association_documents
|
|
187
|
+
repository.associations_index.map do |assoc|
|
|
188
|
+
build_association_document(assoc)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def build_package_documents
|
|
193
|
+
repository.packages_index.map do |package|
|
|
194
|
+
build_package_document(package)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def collect_names(items)
|
|
199
|
+
items&.map(&:name)&.join(" ")
|
|
200
|
+
end
|
|
201
|
+
|
|
189
202
|
def class_type(klass)
|
|
190
203
|
klass.class.name.split("::").last
|
|
191
204
|
end
|
|
@@ -30,10 +30,7 @@ inheritance_resolver)
|
|
|
30
30
|
|
|
31
31
|
private
|
|
32
32
|
|
|
33
|
-
def serialize(klass, id)
|
|
34
|
-
class_associations = find_class_associations(klass)
|
|
35
|
-
sorted_associations = sort_associations(class_associations, klass)
|
|
36
|
-
|
|
33
|
+
def serialize(klass, id)
|
|
37
34
|
Models::SpaClass.new(
|
|
38
35
|
id: id,
|
|
39
36
|
xmi_id: klass.xmi_id,
|
|
@@ -43,17 +40,38 @@ inheritance_resolver)
|
|
|
43
40
|
package: package_id_for_class(klass),
|
|
44
41
|
stereotypes: normalize_stereotypes(klass.stereotype),
|
|
45
42
|
definition: format_definition(klass.definition),
|
|
46
|
-
attributes: (klass
|
|
47
|
-
.map { |attr| @id_generator.attribute_id(attr, klass) },
|
|
43
|
+
attributes: serialize_attribute_ids(klass),
|
|
48
44
|
operations: serialize_class_operations(klass),
|
|
49
|
-
associations:
|
|
50
|
-
|
|
51
|
-
specializations: @inheritance_resolver.find_specializations(klass),
|
|
45
|
+
associations: sort_associations(find_class_associations(klass),
|
|
46
|
+
klass),
|
|
52
47
|
is_abstract: klass.is_abstract,
|
|
53
48
|
literals: serialize_literals(klass),
|
|
49
|
+
**inheritance_data(klass),
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def inheritance_data(klass)
|
|
54
|
+
{
|
|
55
|
+
generalizations: @inheritance_resolver.find_generalizations(klass),
|
|
56
|
+
specializations: @inheritance_resolver.find_specializations(klass),
|
|
54
57
|
inherited_attributes: @inheritance_resolver.compute_inherited_attributes(klass),
|
|
55
58
|
inherited_associations: @inheritance_resolver.compute_inherited_associations(klass),
|
|
56
|
-
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def resolve_assoc_role(assoc, klass)
|
|
63
|
+
if assoc.owner_end_xmi_id == klass.xmi_id
|
|
64
|
+
assoc.owner_end_attribute_name || assoc.owner_end || ""
|
|
65
|
+
elsif assoc.member_end_xmi_id == klass.xmi_id
|
|
66
|
+
assoc.member_end_attribute_name || assoc.member_end || ""
|
|
67
|
+
else
|
|
68
|
+
""
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def serialize_attribute_ids(klass)
|
|
73
|
+
(klass.attributes || []).sort_by { |a| a.name || "" }
|
|
74
|
+
.map { |attr| @id_generator.attribute_id(attr, klass) }
|
|
57
75
|
end
|
|
58
76
|
|
|
59
77
|
def find_class_associations(klass)
|
|
@@ -65,18 +83,16 @@ inheritance_resolver)
|
|
|
65
83
|
|
|
66
84
|
def sort_associations(assoc_ids, klass)
|
|
67
85
|
assoc_ids.sort_by do |assoc_id|
|
|
68
|
-
assoc =
|
|
69
|
-
@id_generator.association_id(a) == assoc_id
|
|
70
|
-
end
|
|
86
|
+
assoc = find_assoc_by_id(assoc_id)
|
|
71
87
|
next "" unless assoc
|
|
72
88
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
89
|
+
resolve_assoc_role(assoc, klass)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def find_assoc_by_id(assoc_id)
|
|
94
|
+
@repository.associations_index.find do |a|
|
|
95
|
+
@id_generator.association_id(a) == assoc_id
|
|
80
96
|
end
|
|
81
97
|
end
|
|
82
98
|
|
|
@@ -22,17 +22,8 @@ module Lutaml
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def find_generalizations(klass)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if parent_xmi_ids && !parent_xmi_ids.empty?
|
|
28
|
-
parents = parent_xmi_ids.filter_map do |parent_xmi_id|
|
|
29
|
-
next if parent_xmi_id == klass.xmi_id
|
|
30
|
-
|
|
31
|
-
parent = class_lookup.by_xmi_id(parent_xmi_id)
|
|
32
|
-
parent ? @id_generator.class_id(parent) : nil
|
|
33
|
-
end
|
|
34
|
-
return parents unless parents.empty?
|
|
35
|
-
end
|
|
25
|
+
map_parents = generalization_map_parents(klass)
|
|
26
|
+
return map_parents unless map_parents.nil?
|
|
36
27
|
|
|
37
28
|
parent = @repository.supertype_of(klass)
|
|
38
29
|
return [] if parent && parent.xmi_id == klass.xmi_id
|
|
@@ -52,12 +43,59 @@ module Lutaml
|
|
|
52
43
|
end
|
|
53
44
|
|
|
54
45
|
def compute_inherited_attributes(klass, visited = Set.new)
|
|
46
|
+
walk_inheritance_chain(klass, visited, :parent_inherited_attrs)
|
|
47
|
+
rescue StandardError => e
|
|
48
|
+
warn "Error computing inherited attributes: #{e.message}"
|
|
49
|
+
[]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def compute_inherited_associations(klass, visited = Set.new)
|
|
53
|
+
walk_inheritance_chain(klass, visited, :parent_inherited_assocs)
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
warn "Error computing inherited associations: #{e.message}"
|
|
56
|
+
[]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def serialize_generalization(klass, visited = Set.new)
|
|
60
|
+
return nil unless klass.generalization
|
|
61
|
+
return nil if visited.include?(klass.xmi_id)
|
|
62
|
+
|
|
63
|
+
visited.add(klass.xmi_id)
|
|
64
|
+
gen = klass.generalization
|
|
65
|
+
|
|
66
|
+
gen_basic_fields(gen).merge(gen_collection_fields(gen))
|
|
67
|
+
rescue StandardError => e
|
|
68
|
+
warn "Error serializing generalization: #{e.message}"
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def serialize_general_attribute(attr)
|
|
73
|
+
return nil unless attr
|
|
74
|
+
|
|
75
|
+
{
|
|
76
|
+
name: attr.name,
|
|
77
|
+
type: attr.type,
|
|
78
|
+
cardinality: serialize_cardinality(attr.cardinality),
|
|
79
|
+
definition: format_definition(attr.definition),
|
|
80
|
+
upperKlass: attr.upper_klass,
|
|
81
|
+
nameNs: attr.name_ns,
|
|
82
|
+
typeNs: attr.type_ns,
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def walk_inheritance_chain(klass, visited, collector_method)
|
|
55
89
|
return [] unless klass.generalization
|
|
56
90
|
return [] if visited.include?(klass.xmi_id)
|
|
57
91
|
|
|
58
92
|
visited.add(klass.xmi_id)
|
|
93
|
+
collect_chain_items(klass.generalization, visited, collector_method)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def collect_chain_items(starting_gen, visited, collector_method)
|
|
59
97
|
inherited = []
|
|
60
|
-
current_gen =
|
|
98
|
+
current_gen = starting_gen
|
|
61
99
|
parent_order = 0
|
|
62
100
|
|
|
63
101
|
while current_gen
|
|
@@ -66,127 +104,93 @@ module Lutaml
|
|
|
66
104
|
break if visited.include?(parent_class.xmi_id)
|
|
67
105
|
|
|
68
106
|
visited.add(parent_class.xmi_id)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
sorted_attrs = parent_class.attributes.sort_by do |a|
|
|
72
|
-
a.name || ""
|
|
73
|
-
end
|
|
74
|
-
sorted_attrs.each do |attr|
|
|
75
|
-
attr_id = @id_generator.attribute_id(attr, parent_class)
|
|
76
|
-
inherited << Models::SpaInheritedAttribute.new(
|
|
77
|
-
attribute_id: attr_id,
|
|
78
|
-
attribute: serialize_attribute(attr, parent_class, attr_id),
|
|
79
|
-
inherited_from: @id_generator.class_id(parent_class),
|
|
80
|
-
inherited_from_name: parent_class.name,
|
|
81
|
-
parent_order: parent_order,
|
|
82
|
-
)
|
|
83
|
-
end
|
|
84
|
-
end
|
|
107
|
+
inherited.concat(send(collector_method, parent_class,
|
|
108
|
+
parent_order))
|
|
85
109
|
|
|
86
110
|
parent_order += 1
|
|
87
111
|
current_gen = current_gen.general
|
|
88
112
|
end
|
|
89
113
|
|
|
90
114
|
inherited
|
|
91
|
-
rescue StandardError => e
|
|
92
|
-
warn "Error computing inherited attributes: #{e.message}"
|
|
93
|
-
[]
|
|
94
115
|
end
|
|
95
116
|
|
|
96
|
-
def
|
|
97
|
-
|
|
98
|
-
return
|
|
117
|
+
def generalization_map_parents(klass)
|
|
118
|
+
parent_xmi_ids = @generalization_map[klass.xmi_id]
|
|
119
|
+
return nil if parent_xmi_ids.nil? || parent_xmi_ids.empty?
|
|
99
120
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
current_gen = klass.generalization
|
|
103
|
-
parent_order = 0
|
|
121
|
+
parents = parent_xmi_ids.filter_map do |parent_xmi_id|
|
|
122
|
+
next if parent_xmi_id == klass.xmi_id
|
|
104
123
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
resolve_parent_class_id(parent_xmi_id)
|
|
125
|
+
end
|
|
126
|
+
parents.empty? ? nil : parents
|
|
127
|
+
end
|
|
109
128
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
assoc = @repository.associations_index.find do |a|
|
|
115
|
-
@id_generator.association_id(a) == assoc_id
|
|
116
|
-
end
|
|
117
|
-
next unless assoc
|
|
118
|
-
|
|
119
|
-
local_role = if assoc.owner_end_xmi_id == parent_class.xmi_id
|
|
120
|
-
assoc.owner_end_attribute_name || assoc.owner_end || ""
|
|
121
|
-
elsif assoc.member_end_xmi_id == parent_class.xmi_id
|
|
122
|
-
assoc.member_end_attribute_name || assoc.member_end || ""
|
|
123
|
-
else
|
|
124
|
-
""
|
|
125
|
-
end
|
|
126
|
-
{ id: assoc_id, role: local_role }
|
|
127
|
-
end
|
|
129
|
+
def resolve_parent_class_id(parent_xmi_id)
|
|
130
|
+
parent = class_lookup.by_xmi_id(parent_xmi_id)
|
|
131
|
+
parent ? @id_generator.class_id(parent) : nil
|
|
132
|
+
end
|
|
128
133
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
def parent_inherited_attrs(parent_class, parent_order)
|
|
135
|
+
return [] unless parent_class.attributes
|
|
136
|
+
|
|
137
|
+
parent_class.attributes.sort_by { |a| a.name || "" }
|
|
138
|
+
.map do |attr|
|
|
139
|
+
attr_id = @id_generator.attribute_id(attr, parent_class)
|
|
140
|
+
Models::SpaInheritedAttribute.new(
|
|
141
|
+
attribute_id: attr_id,
|
|
142
|
+
attribute: serialize_attribute(attr, parent_class, attr_id),
|
|
132
143
|
inherited_from: @id_generator.class_id(parent_class),
|
|
133
144
|
inherited_from_name: parent_class.name,
|
|
134
145
|
parent_order: parent_order,
|
|
135
|
-
local_role: item[:role],
|
|
136
146
|
)
|
|
137
147
|
end
|
|
148
|
+
end
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
150
|
+
def parent_inherited_assocs(parent_class, parent_order)
|
|
151
|
+
assoc_with_roles = collect_assoc_roles(parent_class)
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
[]
|
|
153
|
+
assoc_with_roles.sort_by { |a| a[:role] }.map do |item|
|
|
154
|
+
build_inherited_assoc(item, parent_class, parent_order)
|
|
155
|
+
end
|
|
147
156
|
end
|
|
148
157
|
|
|
149
|
-
def
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
def collect_assoc_roles(parent_class)
|
|
159
|
+
find_class_associations(parent_class).filter_map do |assoc_id|
|
|
160
|
+
assoc = find_assoc_by_generated_id(assoc_id)
|
|
161
|
+
next unless assoc
|
|
152
162
|
|
|
153
|
-
|
|
154
|
-
|
|
163
|
+
{ id: assoc_id, role: resolve_local_role(assoc, parent_class) }
|
|
164
|
+
end
|
|
165
|
+
end
|
|
155
166
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
hasGeneral: gen.has_general,
|
|
161
|
-
name: gen.name,
|
|
162
|
-
type: gen.type,
|
|
163
|
-
definition: format_definition(gen.definition),
|
|
164
|
-
stereotype: gen.stereotype,
|
|
165
|
-
ownedProps: serialize_general_collection(gen.owned_props),
|
|
166
|
-
assocProps: serialize_general_collection(gen.assoc_props),
|
|
167
|
-
inheritedProps: serialize_general_collection(gen.inherited_props),
|
|
168
|
-
inheritedAssocProps: serialize_general_collection(gen.inherited_assoc_props),
|
|
169
|
-
}
|
|
170
|
-
rescue StandardError => e
|
|
171
|
-
warn "Error serializing generalization: #{e.message}"
|
|
172
|
-
nil
|
|
167
|
+
def find_assoc_by_generated_id(assoc_id)
|
|
168
|
+
@repository.associations_index.find do |a|
|
|
169
|
+
@id_generator.association_id(a) == assoc_id
|
|
170
|
+
end
|
|
173
171
|
end
|
|
174
172
|
|
|
175
|
-
def
|
|
176
|
-
|
|
173
|
+
def build_inherited_assoc(item, parent_class, parent_order)
|
|
174
|
+
Models::SpaInheritedAssociation.new(
|
|
175
|
+
association_id: item[:id],
|
|
176
|
+
inherited_from: @id_generator.class_id(parent_class),
|
|
177
|
+
inherited_from_name: parent_class.name,
|
|
178
|
+
parent_order: parent_order,
|
|
179
|
+
local_role: item[:role],
|
|
180
|
+
)
|
|
181
|
+
end
|
|
177
182
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
type: attr.type,
|
|
181
|
-
cardinality: serialize_cardinality(attr.cardinality),
|
|
182
|
-
definition: format_definition(attr.definition),
|
|
183
|
-
upperKlass: attr.upper_klass,
|
|
184
|
-
nameNs: attr.name_ns,
|
|
185
|
-
typeNs: attr.type_ns,
|
|
186
|
-
}
|
|
183
|
+
def resolve_local_role(assoc, parent_class)
|
|
184
|
+
role_for_end(assoc, parent_class.xmi_id) || ""
|
|
187
185
|
end
|
|
188
186
|
|
|
189
|
-
|
|
187
|
+
def role_for_end(assoc, xmi_id)
|
|
188
|
+
if assoc.owner_end_xmi_id == xmi_id
|
|
189
|
+
assoc.owner_end_attribute_name || assoc.owner_end
|
|
190
|
+
elsif assoc.member_end_xmi_id == xmi_id
|
|
191
|
+
assoc.member_end_attribute_name || assoc.member_end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
190
194
|
|
|
191
195
|
def class_lookup
|
|
192
196
|
@class_lookup ||= ClassLookupIndex.new(@repository.classes_index)
|
|
@@ -231,6 +235,28 @@ module Lutaml
|
|
|
231
235
|
)
|
|
232
236
|
end
|
|
233
237
|
|
|
238
|
+
def gen_basic_fields(gen)
|
|
239
|
+
{
|
|
240
|
+
generalId: gen.general_id,
|
|
241
|
+
generalName: gen.general_name,
|
|
242
|
+
generalUpperKlass: gen.general_upper_klass,
|
|
243
|
+
hasGeneral: gen.has_general,
|
|
244
|
+
name: gen.name,
|
|
245
|
+
type: gen.type,
|
|
246
|
+
definition: format_definition(gen.definition),
|
|
247
|
+
stereotype: gen.stereotype,
|
|
248
|
+
}
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def gen_collection_fields(gen)
|
|
252
|
+
{
|
|
253
|
+
ownedProps: serialize_general_collection(gen.owned_props),
|
|
254
|
+
assocProps: serialize_general_collection(gen.assoc_props),
|
|
255
|
+
inheritedProps: serialize_general_collection(gen.inherited_props),
|
|
256
|
+
inheritedAssocProps: serialize_general_collection(gen.inherited_assoc_props),
|
|
257
|
+
}
|
|
258
|
+
end
|
|
259
|
+
|
|
234
260
|
def format_definition(definition)
|
|
235
261
|
return nil if definition.nil? || definition.empty?
|
|
236
262
|
|
|
@@ -35,19 +35,25 @@ module Lutaml
|
|
|
35
35
|
path: package_path(package),
|
|
36
36
|
definition: format_definition(package.definition),
|
|
37
37
|
stereotypes: normalize_stereotypes(package.stereotype),
|
|
38
|
-
classes: (package
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
sub_packages: (package.packages || []).map do |p|
|
|
42
|
-
@id_generator.package_id(p)
|
|
43
|
-
end,
|
|
44
|
-
diagrams: package_diagrams(package).map do |d|
|
|
45
|
-
@id_generator.diagram_id(d)
|
|
46
|
-
end,
|
|
38
|
+
classes: collect_class_ids(package),
|
|
39
|
+
sub_packages: collect_sub_package_ids(package),
|
|
40
|
+
diagrams: collect_diagram_ids(package),
|
|
47
41
|
parent: parent_id(package),
|
|
48
42
|
)
|
|
49
43
|
end
|
|
50
44
|
|
|
45
|
+
def collect_class_ids(package)
|
|
46
|
+
(package.classes || []).map { |c| @id_generator.class_id(c) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def collect_sub_package_ids(package)
|
|
50
|
+
(package.packages || []).map { |p| @id_generator.package_id(p) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def collect_diagram_ids(package)
|
|
54
|
+
package_diagrams(package).map { |d| @id_generator.diagram_id(d) }
|
|
55
|
+
end
|
|
56
|
+
|
|
51
57
|
def parent_id(package)
|
|
52
58
|
return nil unless package.namespace.is_a?(Lutaml::Uml::Package)
|
|
53
59
|
|