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
|
@@ -15,34 +15,52 @@ module Lutaml
|
|
|
15
15
|
# instead of array
|
|
16
16
|
# @return [Hash] Group index
|
|
17
17
|
def build_group_index(collection, method, single: false)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
else
|
|
24
|
-
collection.each_with_object({}) do |item, hash|
|
|
25
|
-
key = item.public_send(method)
|
|
26
|
-
(hash[key] ||= []) << item if key
|
|
27
|
-
end
|
|
18
|
+
collection.each_with_object({}) do |item, hash|
|
|
19
|
+
key = item.public_send(method)
|
|
20
|
+
next unless key
|
|
21
|
+
|
|
22
|
+
single ? (hash[key] = item) : ((hash[key] ||= []) << item)
|
|
28
23
|
end
|
|
29
24
|
end
|
|
30
25
|
|
|
31
26
|
# Eagerly build all lazy lookup indexes before freezing
|
|
32
27
|
def build_lookup_indexes
|
|
28
|
+
build_primary_indexes
|
|
29
|
+
build_secondary_indexes
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build_primary_indexes
|
|
33
|
+
build_object_indexes
|
|
34
|
+
build_feature_indexes
|
|
35
|
+
build_connector_indexes
|
|
36
|
+
build_diagram_indexes
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def build_object_indexes
|
|
33
40
|
@objects_by_guid = build_group_index(objects, :ea_guid, single: true)
|
|
41
|
+
@objects_by_package_id = build_group_index(objects, :package_id)
|
|
42
|
+
@packages_by_parent = build_group_index(packages, :parent_id)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build_feature_indexes
|
|
34
46
|
@attributes_by_object_id = build_group_index(attributes, :ea_object_id)
|
|
35
47
|
@operations_by_object_id = build_group_index(operations, :ea_object_id)
|
|
36
48
|
@operation_params_by_id = build_group_index(operation_params,
|
|
37
49
|
:operationid)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def build_connector_indexes
|
|
38
53
|
@connectors_by_start = build_group_index(connectors, :start_object_id)
|
|
39
54
|
@connectors_by_end = build_group_index(connectors, :end_object_id)
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def build_diagram_indexes
|
|
42
58
|
@diagrams_by_package_id = build_group_index(diagrams, :package_id)
|
|
43
59
|
@diagram_objects_by_id = build_group_index(diagram_objects, :diagram_id)
|
|
44
60
|
@diagram_links_by_id = build_group_index(diagram_links, :diagramid)
|
|
45
|
-
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def build_secondary_indexes
|
|
46
64
|
@packages_by_id = build_group_index(packages, :package_id, single: true)
|
|
47
65
|
@connectors_by_id = build_group_index(connectors, :connector_id,
|
|
48
66
|
single: true)
|
|
@@ -36,13 +36,7 @@ module Lutaml
|
|
|
36
36
|
ancestors = []
|
|
37
37
|
@visited.clear
|
|
38
38
|
collect_ancestors(klass, ancestors)
|
|
39
|
-
ancestors
|
|
40
|
-
break if @visited.include?(ancestor.xmi_id)
|
|
41
|
-
|
|
42
|
-
@visited.add(ancestor.xmi_id)
|
|
43
|
-
yield(ancestor, level) if block_given?
|
|
44
|
-
end
|
|
45
|
-
ancestors.reverse_each.with_index(1)
|
|
39
|
+
yield_ancestors(ancestors)
|
|
46
40
|
end
|
|
47
41
|
|
|
48
42
|
# Get the direct supertype (immediate parent) of a class.
|
|
@@ -65,6 +59,16 @@ module Lutaml
|
|
|
65
59
|
|
|
66
60
|
private
|
|
67
61
|
|
|
62
|
+
def yield_ancestors(ancestors)
|
|
63
|
+
ancestors.reverse_each.with_index(1) do |ancestor, level|
|
|
64
|
+
break if @visited.include?(ancestor.xmi_id)
|
|
65
|
+
|
|
66
|
+
@visited.add(ancestor.xmi_id)
|
|
67
|
+
yield(ancestor, level) if block_given?
|
|
68
|
+
end
|
|
69
|
+
ancestors.reverse_each.with_index(1)
|
|
70
|
+
end
|
|
71
|
+
|
|
68
72
|
# Collect ancestors recursively into the result array.
|
|
69
73
|
# Uses a trail set for cycle detection (avoids Set mutation issues across calls).
|
|
70
74
|
def collect_ancestors(klass, result, trail = [])
|
|
@@ -39,7 +39,7 @@ module Lutaml
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
#{build_navigation_links(pkg_path)}
|
|
43
43
|
MARKDOWN
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -67,21 +67,8 @@ module Lutaml
|
|
|
67
67
|
return "" if parent.nil? && children.empty?
|
|
68
68
|
|
|
69
69
|
content = "## Inheritance\n\n"
|
|
70
|
-
|
|
71
|
-
if
|
|
72
|
-
parent_qname = @link_resolver.qualified_name(parent)
|
|
73
|
-
content += "**Extends**: [#{parent.name}](#{@link_resolver.class_link(parent_qname)})\n\n"
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
if children.any?
|
|
77
|
-
content += "**Extended by**:\n\n"
|
|
78
|
-
children.each do |child|
|
|
79
|
-
child_qname = @link_resolver.qualified_name(child)
|
|
80
|
-
content += "- [#{child.name}](#{@link_resolver.class_link(child_qname)})\n"
|
|
81
|
-
end
|
|
82
|
-
content += "\n"
|
|
83
|
-
end
|
|
84
|
-
|
|
70
|
+
content += build_parent_link(parent) if parent
|
|
71
|
+
content += build_children_links(children) if children.any?
|
|
85
72
|
content
|
|
86
73
|
rescue StandardError
|
|
87
74
|
""
|
|
@@ -138,15 +125,7 @@ module Lutaml
|
|
|
138
125
|
end
|
|
139
126
|
|
|
140
127
|
def format_association_row(association, klass)
|
|
141
|
-
|
|
142
|
-
target_end = association.member_end&.last
|
|
143
|
-
|
|
144
|
-
end_obj = if source_end&.type&.xmi_id == klass.xmi_id
|
|
145
|
-
target_end
|
|
146
|
-
else
|
|
147
|
-
source_end
|
|
148
|
-
end
|
|
149
|
-
|
|
128
|
+
end_obj = resolve_target_end(association, klass)
|
|
150
129
|
return "" unless end_obj&.type
|
|
151
130
|
|
|
152
131
|
target_qname = @link_resolver.qualified_name(end_obj.type)
|
|
@@ -172,6 +151,35 @@ module Lutaml
|
|
|
172
151
|
|
|
173
152
|
"#{content}\n"
|
|
174
153
|
end
|
|
154
|
+
|
|
155
|
+
def build_navigation_links(pkg_path)
|
|
156
|
+
"[Back to Package](#{@link_resolver.package_link(pkg_path)}) | [Back to Index](../index.md)"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def build_parent_link(parent)
|
|
160
|
+
parent_qname = @link_resolver.qualified_name(parent)
|
|
161
|
+
"**Extends**: [#{parent.name}](#{@link_resolver.class_link(parent_qname)})\n\n"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def build_children_links(children)
|
|
165
|
+
content = "**Extended by**:\n\n"
|
|
166
|
+
children.each do |child|
|
|
167
|
+
child_qname = @link_resolver.qualified_name(child)
|
|
168
|
+
content += "- [#{child.name}](#{@link_resolver.class_link(child_qname)})\n"
|
|
169
|
+
end
|
|
170
|
+
"#{content}\n"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def resolve_target_end(association, klass)
|
|
174
|
+
source_end = association.member_end&.first
|
|
175
|
+
target_end = association.member_end&.last
|
|
176
|
+
|
|
177
|
+
if source_end&.type&.xmi_id == klass.xmi_id
|
|
178
|
+
target_end
|
|
179
|
+
else
|
|
180
|
+
source_end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
175
183
|
end
|
|
176
184
|
end
|
|
177
185
|
end
|
|
@@ -54,16 +54,24 @@ module Lutaml
|
|
|
54
54
|
indent = " " * depth
|
|
55
55
|
path = node[:path]
|
|
56
56
|
link = @link_resolver.package_link(path)
|
|
57
|
-
result =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
node[:children].each do |child|
|
|
63
|
-
result += build_tree_node(child, depth + 1)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
57
|
+
result = format_tree_line(indent, node[:name], link,
|
|
58
|
+
node[:classes_count])
|
|
59
|
+
|
|
60
|
+
append_child_nodes(result, node[:children], depth)
|
|
61
|
+
end
|
|
66
62
|
|
|
63
|
+
def format_tree_line(indent, name, link, classes_count)
|
|
64
|
+
line = "#{indent}- [#{name}](#{link})"
|
|
65
|
+
line += " (#{classes_count} classes)" if classes_count&.positive?
|
|
66
|
+
"#{line}\n"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def append_child_nodes(result, children, depth)
|
|
70
|
+
return result unless children&.any?
|
|
71
|
+
|
|
72
|
+
children.each do |child|
|
|
73
|
+
result << build_tree_node(child, depth + 1)
|
|
74
|
+
end
|
|
67
75
|
result
|
|
68
76
|
end
|
|
69
77
|
end
|
|
@@ -54,32 +54,39 @@ module Lutaml
|
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
builder = Markdown::PackagePageBuilder.new(repository, link_resolver)
|
|
57
|
-
packages.each
|
|
58
|
-
path = link_resolver.package_path(package)
|
|
59
|
-
content = builder.build(package, path)
|
|
60
|
-
filename = link_resolver.sanitize_filename("#{path}.md")
|
|
61
|
-
File.write(File.join(output_dir, "packages", filename), content)
|
|
62
|
-
end
|
|
57
|
+
packages.each { |pkg| write_package_page(builder, pkg) }
|
|
63
58
|
end
|
|
64
59
|
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
else
|
|
72
|
-
indexes&.dig(:classes)&.values || []
|
|
73
|
-
end
|
|
60
|
+
def write_package_page(builder, package)
|
|
61
|
+
path = link_resolver.package_path(package)
|
|
62
|
+
content = builder.build(package, path)
|
|
63
|
+
filename = link_resolver.sanitize_filename("#{path}.md")
|
|
64
|
+
File.write(File.join(output_dir, "packages", filename), content)
|
|
65
|
+
end
|
|
74
66
|
|
|
67
|
+
def generate_class_pages
|
|
68
|
+
classes = collect_export_classes
|
|
75
69
|
builder = Markdown::ClassPageBuilder.new(repository, link_resolver)
|
|
76
|
-
classes.each
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
classes.each { |klass| write_class_page(builder, klass) }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def collect_export_classes
|
|
74
|
+
if options[:package]
|
|
75
|
+
repository.classes_in_package(
|
|
76
|
+
options[:package],
|
|
77
|
+
recursive: options.fetch(:recursive, true),
|
|
78
|
+
)
|
|
79
|
+
else
|
|
80
|
+
indexes&.dig(:classes)&.values || []
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
|
+
|
|
84
|
+
def write_class_page(builder, klass)
|
|
85
|
+
qname = link_resolver.qualified_name(klass)
|
|
86
|
+
content = builder.build(klass, qname)
|
|
87
|
+
filename = link_resolver.sanitize_filename("#{qname}.md")
|
|
88
|
+
File.write(File.join(output_dir, "classes", filename), content)
|
|
89
|
+
end
|
|
83
90
|
end
|
|
84
91
|
end
|
|
85
92
|
end
|
|
@@ -3,28 +3,35 @@
|
|
|
3
3
|
module Lutaml
|
|
4
4
|
module UmlRepository
|
|
5
5
|
class IndexBuilder
|
|
6
|
-
def build_association_index
|
|
7
|
-
|
|
6
|
+
def build_association_index
|
|
7
|
+
index_document_associations
|
|
8
|
+
index_class_level_associations
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def index_document_associations
|
|
8
12
|
@document.associations&.each do |assoc|
|
|
9
13
|
next unless assoc.xmi_id
|
|
10
14
|
|
|
11
15
|
@associations[assoc.xmi_id] = assoc
|
|
12
16
|
end
|
|
17
|
+
end
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
# Note: This requires qualified_names index to be built first
|
|
19
|
+
def index_class_level_associations
|
|
16
20
|
@qualified_names.each_value do |klass|
|
|
17
|
-
next unless
|
|
21
|
+
next unless klassifiable?(klass) && klass.associations
|
|
18
22
|
|
|
19
23
|
klass.associations.each do |assoc|
|
|
20
24
|
next unless assoc.xmi_id
|
|
21
25
|
|
|
22
|
-
# Avoid duplicates - only add if not already present
|
|
23
26
|
@associations[assoc.xmi_id] ||= assoc
|
|
24
27
|
end
|
|
25
28
|
end
|
|
26
29
|
end
|
|
27
30
|
|
|
31
|
+
def klassifiable?(klass)
|
|
32
|
+
klass.is_a?(Lutaml::Uml::Class) || klass.is_a?(Lutaml::Uml::DataType)
|
|
33
|
+
end
|
|
34
|
+
|
|
28
35
|
# Build the inheritance graph index
|
|
29
36
|
#
|
|
30
37
|
# Creates a hash mapping parent qualified names to arrays of
|
|
@@ -49,70 +56,68 @@ module Lutaml
|
|
|
49
56
|
#
|
|
50
57
|
# @param classes [Array<Lutaml::Uml::Class>] Classes to process
|
|
51
58
|
# @param package_path [String] Package path for these classes
|
|
52
|
-
def process_generalizations(classes, package_path)
|
|
59
|
+
def process_generalizations(classes, package_path)
|
|
53
60
|
return unless classes
|
|
54
61
|
|
|
55
62
|
classes.each do |klass|
|
|
56
63
|
next unless klass.name
|
|
57
64
|
|
|
58
65
|
child_qname = "#{package_path}::#{klass.name}"
|
|
66
|
+
index_generalization_edge(child_qname, klass, package_path)
|
|
67
|
+
index_inheritance_assoc_edges(child_qname, klass, package_path)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
59
70
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
parent_name = extract_parent_name(klass.generalization)
|
|
63
|
-
if parent_name
|
|
64
|
-
parent_qname = resolve_qualified_name(parent_name, package_path)
|
|
65
|
-
if parent_qname && child_qname != parent_qname
|
|
66
|
-
@inheritance_graph[parent_qname] ||= []
|
|
67
|
-
@inheritance_graph[parent_qname] << child_qname
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Handle inheritance associations
|
|
73
|
-
next unless klass.associations
|
|
71
|
+
def index_generalization_edge(child_qname, klass, package_path)
|
|
72
|
+
return unless klass.generalization
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
next unless assoc.member_end_type == "inheritance"
|
|
74
|
+
parent_name = extract_parent_name(klass.generalization)
|
|
75
|
+
return unless parent_name
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
parent_qname = resolve_qualified_name(parent_name, package_path)
|
|
78
|
+
return unless parent_qname && child_qname != parent_qname
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
(@inheritance_graph[parent_qname] ||= []) << child_qname
|
|
81
|
+
end
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
next if child_qname == parent_qname
|
|
83
|
+
def index_inheritance_assoc_edges(child_qname, klass, package_path)
|
|
84
|
+
return unless klass.associations
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
klass.associations
|
|
87
|
+
.select { |assoc| assoc.member_end_type == "inheritance" }
|
|
88
|
+
.each do |assoc|
|
|
89
|
+
index_inheritance_edge(child_qname, assoc,
|
|
90
|
+
package_path)
|
|
92
91
|
end
|
|
93
92
|
end
|
|
94
93
|
|
|
94
|
+
def index_inheritance_edge(child_qname, assoc, package_path)
|
|
95
|
+
parent_name = resolve_parent_name_from_assoc(assoc)
|
|
96
|
+
return unless parent_name
|
|
97
|
+
|
|
98
|
+
parent_qname = resolve_qualified_name(parent_name, package_path)
|
|
99
|
+
return unless parent_qname && child_qname != parent_qname
|
|
100
|
+
|
|
101
|
+
(@inheritance_graph[parent_qname] ||= []) << child_qname
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def resolve_parent_name_from_assoc(assoc)
|
|
105
|
+
parent_name = assoc.member_end
|
|
106
|
+
return nil unless parent_name
|
|
107
|
+
|
|
108
|
+
parent_name = parent_name.name if parent_name.is_a?(Lutaml::Uml::Generalization)
|
|
109
|
+
parent_name.is_a?(String) && !parent_name.empty? ? parent_name : nil
|
|
110
|
+
end
|
|
111
|
+
|
|
95
112
|
# Extract parent name from generalization object
|
|
96
113
|
#
|
|
97
114
|
# @param generalization [Lutaml::Uml::Generalization]
|
|
98
115
|
# Generalization object
|
|
99
116
|
# @return [String, nil] Parent class name
|
|
100
|
-
def extract_parent_name(generalization)
|
|
117
|
+
def extract_parent_name(generalization)
|
|
101
118
|
return nil unless generalization
|
|
102
119
|
|
|
103
|
-
|
|
104
|
-
if generalization.general
|
|
105
|
-
parent = generalization.general
|
|
106
|
-
return parent.name if parent
|
|
107
|
-
return parent.to_s if parent
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Check for name attribute directly
|
|
111
|
-
if generalization.name
|
|
112
|
-
return generalization.name
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
nil
|
|
120
|
+
name_from_general(generalization) || generalization.name
|
|
116
121
|
end
|
|
117
122
|
|
|
118
123
|
# Resolve a class name to its qualified name
|
|
@@ -124,6 +129,13 @@ module Lutaml
|
|
|
124
129
|
# @param name [String] Class name to resolve
|
|
125
130
|
# @param current_package_path [String] Current package context
|
|
126
131
|
# @return [String, nil] Resolved qualified name
|
|
132
|
+
def name_from_general(generalization)
|
|
133
|
+
parent = generalization.general
|
|
134
|
+
return nil unless parent
|
|
135
|
+
|
|
136
|
+
parent.respond_to?(:name) ? parent.name : parent.to_s
|
|
137
|
+
end
|
|
138
|
+
|
|
127
139
|
def resolve_qualified_name(name, current_package_path)
|
|
128
140
|
# If name contains "::", it might already be qualified
|
|
129
141
|
return name if @qualified_names.key?(name)
|
|
@@ -8,8 +8,12 @@ module Lutaml
|
|
|
8
8
|
# Creates a hash mapping qualified names to Class/DataType/Enum objects:
|
|
9
9
|
# "ModelRoot::i-UR::urf::Building" => Class{}
|
|
10
10
|
# @api public
|
|
11
|
-
def build_qualified_name_index
|
|
12
|
-
|
|
11
|
+
def build_qualified_name_index
|
|
12
|
+
index_document_classifiers
|
|
13
|
+
index_package_classifiers
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def index_document_classifiers
|
|
13
17
|
if @document.classes
|
|
14
18
|
index_classifiers(@document.classes,
|
|
15
19
|
ROOT_PACKAGE_NAME)
|
|
@@ -19,8 +23,9 @@ module Lutaml
|
|
|
19
23
|
ROOT_PACKAGE_NAME)
|
|
20
24
|
end
|
|
21
25
|
index_classifiers(@document.enums, ROOT_PACKAGE_NAME) if @document.enums
|
|
26
|
+
end
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
def index_package_classifiers
|
|
24
29
|
traverse_packages(@document.packages,
|
|
25
30
|
parent_path: ROOT_PACKAGE_NAME) do |package, path|
|
|
26
31
|
index_classifiers(package.classes, path) if package.classes
|
|
@@ -35,13 +40,18 @@ module Lutaml
|
|
|
35
40
|
# "featureType" => [Class{}, Class{}],
|
|
36
41
|
# "dataType" => [Class{}]
|
|
37
42
|
# @api public
|
|
38
|
-
def build_stereotype_index
|
|
39
|
-
|
|
43
|
+
def build_stereotype_index
|
|
44
|
+
index_document_stereotypes
|
|
45
|
+
index_package_stereotypes
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def index_document_stereotypes
|
|
40
49
|
index_by_stereotype(@document.classes) if @document.classes
|
|
41
50
|
index_by_stereotype(@document.data_types) if @document.data_types
|
|
42
51
|
index_by_stereotype(@document.enums) if @document.enums
|
|
52
|
+
end
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
def index_package_stereotypes
|
|
45
55
|
traverse_packages(@document.packages) do |package, _path|
|
|
46
56
|
index_by_stereotype(package.classes) if package.classes
|
|
47
57
|
index_by_stereotype(package.data_types) if package.data_types
|
|
@@ -53,42 +63,43 @@ module Lutaml
|
|
|
53
63
|
#
|
|
54
64
|
# @param classifiers [Array] Array of classifier objects
|
|
55
65
|
# @param package_path [String] Package path for these classifiers
|
|
56
|
-
def index_classifiers(classifiers, package_path)
|
|
66
|
+
def index_classifiers(classifiers, package_path)
|
|
57
67
|
return unless classifiers
|
|
58
68
|
|
|
59
69
|
classifiers.each do |classifier|
|
|
60
70
|
next unless classifier.name
|
|
61
71
|
|
|
62
|
-
|
|
63
|
-
@qualified_names[qualified_name] = classifier
|
|
64
|
-
if classifier.xmi_id
|
|
65
|
-
@class_to_qname[classifier.xmi_id] =
|
|
66
|
-
qualified_name
|
|
67
|
-
end
|
|
68
|
-
@classes[classifier.xmi_id] = classifier if classifier.xmi_id
|
|
69
|
-
@simple_name_to_qnames[classifier.name] ||= []
|
|
70
|
-
@simple_name_to_qnames[classifier.name] << qualified_name
|
|
71
|
-
(@package_to_classes[package_path] ||= []) << classifier
|
|
72
|
+
index_classifier(classifier, package_path)
|
|
72
73
|
end
|
|
73
74
|
end
|
|
74
75
|
|
|
76
|
+
def index_classifier(classifier, package_path)
|
|
77
|
+
qualified_name = "#{package_path}::#{classifier.name}"
|
|
78
|
+
@qualified_names[qualified_name] = classifier
|
|
79
|
+
@class_to_qname[classifier.xmi_id] = qualified_name if classifier.xmi_id
|
|
80
|
+
@classes[classifier.xmi_id] = classifier if classifier.xmi_id
|
|
81
|
+
(@simple_name_to_qnames[classifier.name] ||= []) << qualified_name
|
|
82
|
+
(@package_to_classes[package_path] ||= []) << classifier
|
|
83
|
+
end
|
|
84
|
+
|
|
75
85
|
# Index classifiers by their stereotypes
|
|
76
86
|
#
|
|
77
87
|
# @param classifiers [Array] Array of classifier objects
|
|
78
|
-
def index_by_stereotype(classifiers)
|
|
88
|
+
def index_by_stereotype(classifiers)
|
|
79
89
|
return unless classifiers
|
|
80
90
|
|
|
81
91
|
classifiers.each do |classifier|
|
|
82
|
-
next unless classifier
|
|
92
|
+
next unless has_stereotype?(classifier)
|
|
83
93
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
stereotypes.each do |stereotype|
|
|
87
|
-
@stereotypes[stereotype] ||= []
|
|
88
|
-
@stereotypes[stereotype] << classifier
|
|
94
|
+
Array(classifier.stereotype).each do |stereotype|
|
|
95
|
+
(@stereotypes[stereotype] ||= []) << classifier
|
|
89
96
|
end
|
|
90
97
|
end
|
|
91
98
|
end
|
|
99
|
+
|
|
100
|
+
def has_stereotype?(classifier)
|
|
101
|
+
classifier.stereotype && !classifier.stereotype.empty?
|
|
102
|
+
end
|
|
92
103
|
end
|
|
93
104
|
end
|
|
94
105
|
end
|