lutaml 0.10.2 → 0.10.4
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.yml +1 -1
- data/.rubocop_todo.yml +40 -35
- data/CHANGELOG.md +108 -0
- data/lib/lutaml/cli/uml_commands.rb +2 -2
- data/lib/lutaml/command_line.rb +1 -1
- data/lib/lutaml/converter/xmi_to_uml.rb +12 -3
- data/lib/lutaml/model_transformations/parsers/base_parser.rb +1 -1
- data/lib/lutaml/model_transformations/transformation_engine.rb +1 -1
- data/lib/lutaml/qea/database.rb +157 -4
- data/lib/lutaml/qea/factory/association_transformer.rb +1 -5
- data/lib/lutaml/qea/factory/attribute_transformer.rb +4 -10
- data/lib/lutaml/qea/factory/base_transformer.rb +1 -5
- data/lib/lutaml/qea/factory/class_transformer.rb +26 -62
- data/lib/lutaml/qea/factory/data_type_transformer.rb +7 -21
- data/lib/lutaml/qea/factory/diagram_transformer.rb +6 -20
- data/lib/lutaml/qea/factory/document_builder.rb +1 -1
- data/lib/lutaml/qea/factory/enum_transformer.rb +3 -5
- data/lib/lutaml/qea/factory/generalization_transformer.rb +2 -7
- data/lib/lutaml/qea/factory/instance_transformer.rb +2 -10
- data/lib/lutaml/qea/factory/operation_transformer.rb +2 -8
- data/lib/lutaml/qea/factory/package_transformer.rb +4 -13
- data/lib/lutaml/qea/repositories/base_repository.rb +6 -6
- data/lib/lutaml/qea/validation/base_validator.rb +2 -3
- data/lib/lutaml/qea/validation/validation_message.rb +2 -2
- data/lib/lutaml/qea/validation/validation_result.rb +2 -2
- data/lib/lutaml/sysml.rb +1 -1
- data/lib/lutaml/uml/has_members.rb +1 -1
- data/lib/lutaml/uml/parsers/dsl.rb +1 -1
- data/lib/lutaml/uml.rb +1 -1
- data/lib/lutaml/uml_repository/index_builder.rb +19 -17
- data/lib/lutaml/uml_repository/queries/class_query.rb +44 -10
- data/lib/lutaml/uml_repository/queries/inheritance_query.rb +0 -1
- data/lib/lutaml/uml_repository/repository.rb +14 -10
- data/lib/lutaml/uml_repository/statistics_calculator.rb +28 -16
- data/lib/lutaml/version.rb +1 -1
- data/lib/lutaml/xmi/parsers/xmi_base.rb +28 -5
- data/lib/lutaml.rb +3 -1
- data/lutaml.gemspec +2 -2
- metadata +5 -4
|
@@ -108,15 +108,9 @@ module Lutaml
|
|
|
108
108
|
def load_attributes(object_id)
|
|
109
109
|
return [] if object_id.nil?
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
rows = database.connection.execute(query, object_id)
|
|
111
|
+
ea_attributes = database.attributes_for_object(object_id)
|
|
112
|
+
.sort_by { |a| a.pos || 0 }
|
|
114
113
|
|
|
115
|
-
ea_attributes = rows.map do |row|
|
|
116
|
-
Models::EaAttribute.from_db_row(row)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Transform to UML attributes
|
|
120
114
|
attribute_transformer = AttributeTransformer.new(database)
|
|
121
115
|
attribute_transformer.transform_collection(ea_attributes)
|
|
122
116
|
end
|
|
@@ -127,15 +121,9 @@ module Lutaml
|
|
|
127
121
|
def load_operations(object_id)
|
|
128
122
|
return [] if object_id.nil?
|
|
129
123
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
rows = database.connection.execute(query, object_id)
|
|
133
|
-
|
|
134
|
-
ea_operations = rows.map do |row|
|
|
135
|
-
Models::EaOperation.from_db_row(row)
|
|
136
|
-
end
|
|
124
|
+
ea_operations = database.operations_for_object(object_id)
|
|
125
|
+
.sort_by { |op| op.pos || 0 }
|
|
137
126
|
|
|
138
|
-
# Transform to UML operations
|
|
139
127
|
operation_transformer = OperationTransformer.new(database)
|
|
140
128
|
operation_transformer.transform_collection(ea_operations)
|
|
141
129
|
end
|
|
@@ -245,24 +233,21 @@ module Lutaml
|
|
|
245
233
|
return nil unless current_obj
|
|
246
234
|
|
|
247
235
|
# 2. Find generalization connector where this class is the subtype
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
rows = database.connection.execute(query, object_id)
|
|
236
|
+
ea_connector = database.connectors_for_object(object_id)
|
|
237
|
+
.find { |c| c.generalization? && c.start_object_id == object_id }
|
|
251
238
|
|
|
252
239
|
# 3. Create generalization object for current class
|
|
253
240
|
# Even if no parent exists, we need a Generalization
|
|
254
241
|
# representing this class
|
|
255
|
-
|
|
242
|
+
gen_transformer = GeneralizationTransformer.new(database)
|
|
243
|
+
generalization = if ea_connector.nil?
|
|
256
244
|
# No parent - create terminal generalization
|
|
257
|
-
gen_transformer
|
|
258
|
-
generalization = gen_transformer.transform(nil, current_obj)
|
|
245
|
+
gen_transformer.transform(nil, current_obj)
|
|
259
246
|
else
|
|
260
247
|
# Has parent - create generalization with parent connector
|
|
261
|
-
|
|
262
|
-
gen_transformer = GeneralizationTransformer.new(database)
|
|
263
|
-
generalization = gen_transformer
|
|
248
|
+
gen_transformer
|
|
264
249
|
.transform(ea_connector, current_obj)
|
|
265
|
-
|
|
250
|
+
end
|
|
266
251
|
return nil unless generalization
|
|
267
252
|
|
|
268
253
|
# 4. Load CURRENT object attributes and convert to GeneralAttribute
|
|
@@ -452,19 +437,13 @@ module Lutaml
|
|
|
452
437
|
def load_association_generalizations(object_id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
453
438
|
return [] if object_id.nil?
|
|
454
439
|
|
|
455
|
-
#
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
"AND Connector_Type = 'Generalization'"
|
|
459
|
-
rows = database.connection.execute(query, object_id)
|
|
440
|
+
# Find ALL generalization connectors for this class
|
|
441
|
+
gen_connectors = database.connectors_for_object(object_id)
|
|
442
|
+
.select { |c| c.generalization? && c.start_object_id == object_id }
|
|
460
443
|
|
|
461
|
-
|
|
462
|
-
guid =
|
|
463
|
-
parent_object_id =
|
|
464
|
-
row["End_Object_ID"] || row[:End_Object_ID]
|
|
465
|
-
else
|
|
466
|
-
row[1]
|
|
467
|
-
end
|
|
444
|
+
gen_connectors.filter_map do |ea_connector|
|
|
445
|
+
guid = ea_connector.ea_guid
|
|
446
|
+
parent_object_id = ea_connector.end_object_id
|
|
468
447
|
|
|
469
448
|
# Find parent object to get its GUID
|
|
470
449
|
parent_obj = find_object_by_id(parent_object_id)
|
|
@@ -493,16 +472,11 @@ module Lutaml
|
|
|
493
472
|
normalized_owner_xmi_id = normalize_guid_to_xmi_format(object_guid,
|
|
494
473
|
"EAID")
|
|
495
474
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
"AND Connector_Type IN " \
|
|
500
|
-
"('Association', 'Aggregation', 'Composition')"
|
|
501
|
-
rows = database.connection.execute(query, [object_id, object_id])
|
|
502
|
-
|
|
503
|
-
rows.each do |row| # rubocop:disable Metrics/BlockLength
|
|
504
|
-
ea_connector = Models::EaConnector.from_db_row(row)
|
|
475
|
+
assoc_types = ["Association", "Aggregation", "Composition"].freeze
|
|
476
|
+
assoc_connectors = database.connectors_for_object(object_id)
|
|
477
|
+
.select { |c| assoc_types.include?(c.connector_type) }
|
|
505
478
|
|
|
479
|
+
assoc_connectors.each do |ea_connector| # rubocop:disable Metrics/BlockLength
|
|
506
480
|
# Determine which end this class is on
|
|
507
481
|
is_start = ea_connector.start_object_id == object_id
|
|
508
482
|
|
|
@@ -600,19 +574,13 @@ module Lutaml
|
|
|
600
574
|
|
|
601
575
|
attributes = []
|
|
602
576
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
"WHERE (Start_Object_ID = ? OR End_Object_ID = ?) " \
|
|
607
|
-
"AND Connector_Type IN " \
|
|
608
|
-
"('Association', 'Aggregation', 'Composition')"
|
|
609
|
-
rows = database.connection.execute(query, [object_id, object_id])
|
|
577
|
+
assoc_types = ["Association", "Aggregation", "Composition"].freeze
|
|
578
|
+
assoc_connectors = database.connectors_for_object(object_id)
|
|
579
|
+
.select { |c| assoc_types.include?(c.connector_type) }
|
|
610
580
|
obj = find_object_by_id(object_id)
|
|
611
581
|
obj_pkg_name = find_package_name(obj&.package_id)
|
|
612
582
|
|
|
613
|
-
|
|
614
|
-
ea_connector = Models::EaConnector.from_db_row(row)
|
|
615
|
-
|
|
583
|
+
assoc_connectors.each do |ea_connector| # rubocop:disable Metrics/BlockLength
|
|
616
584
|
# Check if this object is the source (owner) or target (member)
|
|
617
585
|
if ea_connector.start_object_id == object_id
|
|
618
586
|
# This class is the source - check for dest role
|
|
@@ -711,11 +679,7 @@ module Lutaml
|
|
|
711
679
|
def find_package_name(package_id)
|
|
712
680
|
return nil if package_id.nil?
|
|
713
681
|
|
|
714
|
-
|
|
715
|
-
rows = database.connection.execute(query, [package_id])
|
|
716
|
-
return nil if rows.empty?
|
|
717
|
-
|
|
718
|
-
rows.first["Name"]
|
|
682
|
+
database.find_package(package_id)&.name
|
|
719
683
|
end
|
|
720
684
|
end
|
|
721
685
|
end
|
|
@@ -64,12 +64,8 @@ module Lutaml
|
|
|
64
64
|
def load_attributes(object_id)
|
|
65
65
|
return [] if object_id.nil?
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
ea_attributes = rows.map do |row|
|
|
71
|
-
Models::EaAttribute.from_db_row(row)
|
|
72
|
-
end
|
|
67
|
+
ea_attributes = database.attributes_for_object(object_id)
|
|
68
|
+
.sort_by { |a| a.pos || 0 }
|
|
73
69
|
|
|
74
70
|
attribute_transformer = AttributeTransformer.new(database)
|
|
75
71
|
attribute_transformer.transform_collection(ea_attributes)
|
|
@@ -81,12 +77,8 @@ module Lutaml
|
|
|
81
77
|
def load_operations(object_id)
|
|
82
78
|
return [] if object_id.nil?
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
ea_operations = rows.map do |row|
|
|
88
|
-
Models::EaOperation.from_db_row(row)
|
|
89
|
-
end
|
|
80
|
+
ea_operations = database.operations_for_object(object_id)
|
|
81
|
+
.sort_by { |op| op.pos || 0 }
|
|
90
82
|
|
|
91
83
|
operation_transformer = OperationTransformer.new(database)
|
|
92
84
|
operation_transformer.transform_collection(ea_operations)
|
|
@@ -129,19 +121,13 @@ module Lutaml
|
|
|
129
121
|
def load_associations(object_id, object_guid) # rubocop:disable Metrics/MethodLength
|
|
130
122
|
return [] if object_id.nil?
|
|
131
123
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
WHERE Connector_Type = 'Association'
|
|
135
|
-
AND (Start_Object_ID = ? OR End_Object_ID = ?)
|
|
136
|
-
SQL
|
|
137
|
-
|
|
138
|
-
rows = database.connection.execute(query, [object_id, object_id])
|
|
124
|
+
assoc_connectors = database.connectors_for_object(object_id)
|
|
125
|
+
.select { |c| c.connector_type == "Association" }
|
|
139
126
|
|
|
140
127
|
assoc_transformer = AssociationTransformer.new(database)
|
|
141
128
|
normalized_xmi_id = normalize_guid_to_xmi_format(object_guid, "EAID")
|
|
142
129
|
|
|
143
|
-
|
|
144
|
-
ea_connector = Models::EaConnector.from_db_row(row)
|
|
130
|
+
assoc_connectors.filter_map do |ea_connector|
|
|
145
131
|
assoc = assoc_transformer.transform(ea_connector)
|
|
146
132
|
|
|
147
133
|
next unless assoc && assoc.owner_end_xmi_id == normalized_xmi_id
|
|
@@ -72,11 +72,7 @@ module Lutaml
|
|
|
72
72
|
def find_package(package_id)
|
|
73
73
|
return nil if package_id.nil?
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
rows = database.connection.execute(query, package_id)
|
|
77
|
-
return nil if rows.empty?
|
|
78
|
-
|
|
79
|
-
Models::EaPackage.from_db_row(rows.first)
|
|
75
|
+
database.find_package(package_id)
|
|
80
76
|
end
|
|
81
77
|
|
|
82
78
|
# Load diagram objects for a diagram
|
|
@@ -85,11 +81,8 @@ module Lutaml
|
|
|
85
81
|
def load_diagram_objects(diagram_id)
|
|
86
82
|
return [] if diagram_id.nil?
|
|
87
83
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
rows.filter_map do |row|
|
|
92
|
-
ea_obj = Models::EaDiagramObject.from_db_row(row)
|
|
84
|
+
ea_objects = database.diagram_objects_for(diagram_id)
|
|
85
|
+
ea_objects.filter_map do |ea_obj|
|
|
93
86
|
transform_diagram_object(ea_obj)
|
|
94
87
|
end
|
|
95
88
|
end
|
|
@@ -127,11 +120,8 @@ module Lutaml
|
|
|
127
120
|
def load_diagram_links(diagram_id)
|
|
128
121
|
return [] if diagram_id.nil?
|
|
129
122
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
rows.filter_map do |row|
|
|
134
|
-
ea_link = Models::EaDiagramLink.from_db_row(row)
|
|
123
|
+
ea_links = database.diagram_links_for(diagram_id)
|
|
124
|
+
ea_links.filter_map do |ea_link|
|
|
135
125
|
transform_diagram_link(ea_link)
|
|
136
126
|
end
|
|
137
127
|
end
|
|
@@ -167,11 +157,7 @@ module Lutaml
|
|
|
167
157
|
def find_connector_by_id(connector_id)
|
|
168
158
|
return nil if connector_id.nil?
|
|
169
159
|
|
|
170
|
-
|
|
171
|
-
rows = database.connection.execute(query, connector_id)
|
|
172
|
-
return nil if rows.empty?
|
|
173
|
-
|
|
174
|
-
Models::EaConnector.from_db_row(rows.first)
|
|
160
|
+
database.find_connector(connector_id)
|
|
175
161
|
end
|
|
176
162
|
end
|
|
177
163
|
end
|
|
@@ -50,12 +50,10 @@ module Lutaml
|
|
|
50
50
|
def load_enum_values(object_id) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
51
51
|
return [] if object_id.nil?
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
rows.filter_map do |row|
|
|
57
|
-
ea_attr = Models::EaAttribute.from_db_row(row)
|
|
53
|
+
ea_attrs = database.attributes_for_object(object_id)
|
|
54
|
+
.sort_by { |a| a.pos || 0 }
|
|
58
55
|
|
|
56
|
+
ea_attrs.filter_map do |ea_attr|
|
|
59
57
|
Lutaml::Uml::Value.new.tap do |value|
|
|
60
58
|
value.name = ea_attr.name
|
|
61
59
|
value.id = normalize_guid_to_xmi_format(ea_attr.ea_guid, "EAID")
|
|
@@ -72,11 +72,7 @@ module Lutaml
|
|
|
72
72
|
def find_object(object_id)
|
|
73
73
|
return nil if object_id.nil?
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
rows = database.connection.execute(query, object_id)
|
|
77
|
-
return nil if rows.empty?
|
|
78
|
-
|
|
79
|
-
Models::EaObject.from_db_row(rows.first)
|
|
75
|
+
database.find_object(object_id)
|
|
80
76
|
end
|
|
81
77
|
|
|
82
78
|
# Find package by ID
|
|
@@ -84,9 +80,8 @@ module Lutaml
|
|
|
84
80
|
# @return [EaPackage, nil] EA package or nil if not found
|
|
85
81
|
def find_package(package_id)
|
|
86
82
|
return nil if package_id.nil?
|
|
87
|
-
return nil unless database.packages
|
|
88
83
|
|
|
89
|
-
database.
|
|
84
|
+
database.find_package(package_id)
|
|
90
85
|
end
|
|
91
86
|
|
|
92
87
|
# Extract package prefix from package
|
|
@@ -54,11 +54,7 @@ module Lutaml
|
|
|
54
54
|
def find_classifier(classifier_id)
|
|
55
55
|
return nil if classifier_id.nil? || classifier_id.zero?
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
rows = database.connection.execute(query, classifier_id)
|
|
59
|
-
return nil if rows.empty?
|
|
60
|
-
|
|
61
|
-
Models::EaObject.from_db_row(rows.first)
|
|
57
|
+
database.find_object(classifier_id)
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
# Find classifier object by GUID
|
|
@@ -67,11 +63,7 @@ module Lutaml
|
|
|
67
63
|
def find_classifier_by_guid(classifier_guid)
|
|
68
64
|
return nil if classifier_guid.nil? || classifier_guid.empty?
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
rows = database.connection.execute(query, classifier_guid)
|
|
72
|
-
return nil if rows.empty?
|
|
73
|
-
|
|
74
|
-
Models::EaObject.from_db_row(rows.first)
|
|
66
|
+
database.find_object_by_guid(classifier_guid)
|
|
75
67
|
end
|
|
76
68
|
|
|
77
69
|
# Load and transform tagged values for an instance
|
|
@@ -60,14 +60,8 @@ module Lutaml
|
|
|
60
60
|
def load_parameters(operation_id)
|
|
61
61
|
return [] if operation_id.nil?
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"ORDER BY Pos"
|
|
66
|
-
rows = database.connection.execute(query, operation_id)
|
|
67
|
-
|
|
68
|
-
rows.map do |row|
|
|
69
|
-
Models::EaOperationParam.from_db_row(row)
|
|
70
|
-
end
|
|
63
|
+
database.operation_params_for(operation_id)
|
|
64
|
+
.sort_by { |p| p.pos || 0 }
|
|
71
65
|
end
|
|
72
66
|
end
|
|
73
67
|
end
|
|
@@ -70,11 +70,8 @@ module Lutaml
|
|
|
70
70
|
def load_child_packages(parent_id)
|
|
71
71
|
return [] if parent_id.nil?
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
rows = database.connection.execute(query, parent_id)
|
|
76
|
-
|
|
77
|
-
rows.map { |row| Models::EaPackage.from_db_row(row) }
|
|
73
|
+
database.child_packages_for(parent_id)
|
|
74
|
+
.sort_by { |p| p.tpos || 0 }
|
|
78
75
|
end
|
|
79
76
|
|
|
80
77
|
# Load package contents (objects and diagrams)
|
|
@@ -94,10 +91,7 @@ module Lutaml
|
|
|
94
91
|
# @param pkg [Lutaml::Uml::Package] UML package
|
|
95
92
|
# @param package_id [Integer] Package ID
|
|
96
93
|
def load_package_objects(pkg, package_id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
97
|
-
|
|
98
|
-
rows = database.connection.execute(query, package_id)
|
|
99
|
-
|
|
100
|
-
ea_objects = rows.map { |row| Models::EaObject.from_db_row(row) }
|
|
94
|
+
ea_objects = database.objects_in_package(package_id)
|
|
101
95
|
|
|
102
96
|
class_transformer = ClassTransformer.new(database)
|
|
103
97
|
enum_transformer = EnumTransformer.new(database)
|
|
@@ -155,10 +149,7 @@ module Lutaml
|
|
|
155
149
|
def load_package_diagrams(pkg, package_id)
|
|
156
150
|
diagram_transformer = DiagramTransformer.new(database)
|
|
157
151
|
|
|
158
|
-
|
|
159
|
-
rows = database.connection.execute(query, package_id)
|
|
160
|
-
|
|
161
|
-
ea_diagrams = rows.map { |row| Models::EaDiagram.from_db_row(row) }
|
|
152
|
+
ea_diagrams = database.diagrams_in_package(package_id)
|
|
162
153
|
pkg.diagrams = diagram_transformer.transform_collection(ea_diagrams)
|
|
163
154
|
end
|
|
164
155
|
|
|
@@ -118,8 +118,8 @@ module Lutaml
|
|
|
118
118
|
# @example
|
|
119
119
|
# repository.find_first(name: "Test")
|
|
120
120
|
# repository.find_first { |r| r.name.start_with?("Test") }
|
|
121
|
-
def find_first(conditions = nil, &
|
|
122
|
-
where(conditions, &
|
|
121
|
+
def find_first(conditions = nil, &)
|
|
122
|
+
where(conditions, &).first
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
# Check if any records match conditions
|
|
@@ -127,8 +127,8 @@ module Lutaml
|
|
|
127
127
|
# @param conditions [Hash, nil] Optional conditions
|
|
128
128
|
# @yield [record] Optional block for custom filtering
|
|
129
129
|
# @return [Boolean] true if any records match
|
|
130
|
-
def any?(conditions = nil, &
|
|
131
|
-
!where(conditions, &
|
|
130
|
+
def any?(conditions = nil, &)
|
|
131
|
+
!where(conditions, &).empty?
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
# Check if no records match conditions
|
|
@@ -136,8 +136,8 @@ module Lutaml
|
|
|
136
136
|
# @param conditions [Hash, nil] Optional conditions
|
|
137
137
|
# @yield [record] Optional block for custom filtering
|
|
138
138
|
# @return [Boolean] true if no records match
|
|
139
|
-
def none?(conditions = nil, &
|
|
140
|
-
where(conditions, &
|
|
139
|
+
def none?(conditions = nil, &)
|
|
140
|
+
where(conditions, &).empty?
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
# Select specific attributes from records
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "set"
|
|
4
3
|
require_relative "validation_result"
|
|
5
4
|
|
|
6
5
|
module Lutaml
|
|
@@ -233,8 +232,8 @@ module Lutaml
|
|
|
233
232
|
# @param entities [Array] Collection of entities to validate
|
|
234
233
|
# @yield [entity] Validation block for each entity
|
|
235
234
|
# @return [ValidationResult]
|
|
236
|
-
def validate_each(entities, &
|
|
237
|
-
entities.each(&
|
|
235
|
+
def validate_each(entities, &)
|
|
236
|
+
entities.each(&)
|
|
238
237
|
@result
|
|
239
238
|
end
|
|
240
239
|
|
data/lib/lutaml/sysml.rb
CHANGED
|
@@ -10,7 +10,7 @@ require "lutaml/converter/dsl_to_uml"
|
|
|
10
10
|
module Lutaml
|
|
11
11
|
module Uml
|
|
12
12
|
module Parsers
|
|
13
|
-
class ParsingError <
|
|
13
|
+
class ParsingError < Lutaml::Error; end
|
|
14
14
|
|
|
15
15
|
# Class for parsing LutaML dsl into Lutaml::Uml::Document
|
|
16
16
|
class Dsl < Parslet::Parser
|
data/lib/lutaml/uml.rb
CHANGED
|
@@ -42,18 +42,8 @@ module Lutaml
|
|
|
42
42
|
# - :class_to_qname - Maps class XMI IDs to qualified names
|
|
43
43
|
# - :classes - Maps class XMI IDs to Class objects
|
|
44
44
|
# - :associations - Maps association XMI IDs to Association objects
|
|
45
|
-
def self.build_all(document)
|
|
46
|
-
|
|
47
|
-
package_paths: build_package_paths(document),
|
|
48
|
-
qualified_names: build_qualified_names(document),
|
|
49
|
-
stereotypes: build_stereotypes(document),
|
|
50
|
-
inheritance_graph: build_inheritance_graph(document, nil),
|
|
51
|
-
diagram_index: build_diagram_index(document, nil),
|
|
52
|
-
package_to_path: build_package_to_path(document),
|
|
53
|
-
class_to_qname: build_class_to_qname(document),
|
|
54
|
-
classes: build_classes(document),
|
|
55
|
-
associations: build_associations(document),
|
|
56
|
-
}.freeze
|
|
45
|
+
def self.build_all(document)
|
|
46
|
+
new(document).build_all
|
|
57
47
|
end
|
|
58
48
|
|
|
59
49
|
# Build package paths index
|
|
@@ -160,6 +150,8 @@ module Lutaml
|
|
|
160
150
|
@class_to_qname = {}
|
|
161
151
|
@classes = {}
|
|
162
152
|
@associations = {}
|
|
153
|
+
@simple_name_to_qnames = {}
|
|
154
|
+
@package_to_classes = {}
|
|
163
155
|
end
|
|
164
156
|
|
|
165
157
|
# Build all indexes and return them as a frozen hash
|
|
@@ -183,6 +175,7 @@ module Lutaml
|
|
|
183
175
|
class_to_qname: @class_to_qname.freeze,
|
|
184
176
|
classes: @classes.freeze,
|
|
185
177
|
associations: @associations.freeze,
|
|
178
|
+
package_to_classes: plain_hash(@package_to_classes).freeze,
|
|
186
179
|
}.freeze
|
|
187
180
|
end
|
|
188
181
|
|
|
@@ -358,6 +351,9 @@ module Lutaml
|
|
|
358
351
|
qualified_name
|
|
359
352
|
end
|
|
360
353
|
@classes[classifier.xmi_id] = classifier if classifier.xmi_id
|
|
354
|
+
@simple_name_to_qnames[classifier.name] ||= []
|
|
355
|
+
@simple_name_to_qnames[classifier.name] << qualified_name
|
|
356
|
+
(@package_to_classes[package_path] ||= []) << classifier
|
|
361
357
|
end
|
|
362
358
|
end
|
|
363
359
|
|
|
@@ -466,12 +462,18 @@ module Lutaml
|
|
|
466
462
|
local_qname = "#{current_package_path}::#{name}"
|
|
467
463
|
return local_qname if @qualified_names.key?(local_qname)
|
|
468
464
|
|
|
469
|
-
#
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
465
|
+
# O(1) lookup using reverse index instead of O(n) scan
|
|
466
|
+
candidates = @simple_name_to_qnames[name]
|
|
467
|
+
candidates&.first
|
|
468
|
+
end
|
|
473
469
|
|
|
474
|
-
|
|
470
|
+
private
|
|
471
|
+
|
|
472
|
+
# Convert a hash with default proc to a plain hash (Marshal-safe)
|
|
473
|
+
# @param hash [Hash] Hash possibly with default proc
|
|
474
|
+
# @return [Hash] Plain hash without default proc
|
|
475
|
+
def plain_hash(hash_with_default)
|
|
476
|
+
hash_with_default.each_with_object({}) { |(k, v), h| h[k] = v }
|
|
475
477
|
end
|
|
476
478
|
end
|
|
477
479
|
end
|