lutaml 0.10.4 → 0.10.6
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/.gitignore +8 -0
- data/.rubocop.yml +10 -0
- data/.rubocop_todo.yml +218 -94
- data/TODO.cleanups/01-resolve-production-todos.md +65 -0
- data/TODO.cleanups/02-reduce-metrics-offenses.md +37 -0
- data/TODO.cleanups/03-reduce-rspec-multiple-expectations.md +54 -0
- data/TODO.cleanups/04-reduce-rspec-example-length.md +45 -0
- data/TODO.cleanups/05-replace-marshal-load.md +37 -0
- data/TODO.cleanups/06-replace-eval-in-tests.md +41 -0
- data/TODO.cleanups/07-fix-lint-offenses.md +74 -0
- data/TODO.cleanups/08-reduce-memoized-helpers-and-nesting.md +43 -0
- data/TODO.cleanups/09-reduce-verified-doubles-and-rspec-style.md +57 -0
- data/TODO.cleanups/10-split-large-files.md +47 -0
- data/bin/console +0 -1
- data/exe/lutaml +1 -0
- data/lib/lutaml/cli/element_identifier.rb +3 -6
- data/lib/lutaml/cli/interactive_shell/bookmark_commands.rb +88 -0
- data/lib/lutaml/cli/interactive_shell/command_base.rb +32 -0
- data/lib/lutaml/cli/interactive_shell/export_handler.rb +67 -0
- data/lib/lutaml/cli/interactive_shell/help_display.rb +114 -0
- data/lib/lutaml/cli/interactive_shell/navigation_commands.rb +135 -0
- data/lib/lutaml/cli/interactive_shell/query_commands.rb +185 -0
- data/lib/lutaml/cli/interactive_shell.rb +116 -802
- data/lib/lutaml/cli/uml/build_command.rb +5 -5
- data/lib/lutaml/cli/uml/verify_command.rb +0 -1
- data/lib/lutaml/converter/xmi_to_uml.rb +3 -153
- data/lib/lutaml/converter/xmi_to_uml_generalization.rb +193 -0
- data/lib/lutaml/formatter/graphviz.rb +1 -2
- data/lib/lutaml/qea/database.rb +1 -47
- data/lib/lutaml/qea/factory/association_builder.rb +188 -0
- data/lib/lutaml/qea/factory/base_transformer.rb +0 -1
- data/lib/lutaml/qea/factory/class_transformer.rb +40 -590
- data/lib/lutaml/qea/factory/diagram_transformer.rb +0 -3
- data/lib/lutaml/qea/factory/generalization_builder.rb +211 -0
- data/lib/lutaml/qea/factory/package_transformer.rb +1 -2
- data/lib/lutaml/qea/factory/stereotype_loader.rb +34 -0
- data/lib/lutaml/qea/lookup_indexes.rb +54 -0
- data/lib/lutaml/qea/models/ea_datatype.rb +0 -2
- data/lib/lutaml/qea/validation/validation_engine.rb +0 -2
- data/lib/lutaml/uml/has_members.rb +0 -1
- data/lib/lutaml/uml/inheritance_walker.rb +92 -0
- data/lib/lutaml/uml/model_helpers.rb +129 -0
- data/lib/lutaml/uml/node/attribute.rb +3 -1
- data/lib/lutaml/uml/node/class_node.rb +3 -3
- data/lib/lutaml/uml/operation.rb +2 -0
- data/lib/lutaml/uml_repository/class_lookup_index.rb +40 -0
- data/lib/lutaml/uml_repository/exporters/markdown/class_page_builder.rb +179 -0
- data/lib/lutaml/uml_repository/exporters/markdown/formatting.rb +36 -0
- data/lib/lutaml/uml_repository/exporters/markdown/index_page_builder.rb +73 -0
- data/lib/lutaml/uml_repository/exporters/markdown/link_resolver.rb +40 -0
- data/lib/lutaml/uml_repository/exporters/markdown/package_page_builder.rb +107 -0
- data/lib/lutaml/uml_repository/exporters/markdown_exporter.rb +26 -538
- data/lib/lutaml/uml_repository/index_builder.rb +3 -271
- data/lib/lutaml/uml_repository/index_builders/association_index.rb +141 -0
- data/lib/lutaml/uml_repository/index_builders/class_index.rb +94 -0
- data/lib/lutaml/uml_repository/index_builders/package_index.rb +57 -0
- data/lib/lutaml/uml_repository/package_exporter.rb +10 -20
- data/lib/lutaml/uml_repository/package_loader.rb +37 -17
- data/lib/lutaml/uml_repository/repository/deprecated.rb +39 -0
- data/lib/lutaml/uml_repository/repository/loader.rb +112 -0
- data/lib/lutaml/uml_repository/repository.rb +7 -57
- data/lib/lutaml/uml_repository/static_site/association_serialization.rb +142 -0
- data/lib/lutaml/uml_repository/static_site/configuration.rb +0 -2
- data/lib/lutaml/uml_repository/static_site/data_transformer.rb +52 -873
- data/lib/lutaml/uml_repository/static_site/generator.rb +29 -8
- data/lib/lutaml/uml_repository/static_site/search_index_builder.rb +1 -4
- data/lib/lutaml/uml_repository/static_site/serializers/attribute_serializer.rb +78 -0
- data/lib/lutaml/uml_repository/static_site/serializers/class_serializer.rb +124 -0
- data/lib/lutaml/uml_repository/static_site/serializers/diagram_serializer.rb +60 -0
- data/lib/lutaml/uml_repository/static_site/serializers/inheritance_resolver.rb +258 -0
- data/lib/lutaml/uml_repository/static_site/serializers/metadata_builder.rb +48 -0
- data/lib/lutaml/uml_repository/static_site/serializers/operation_serializer.rb +57 -0
- data/lib/lutaml/uml_repository/static_site/serializers/package_serializer.rb +94 -0
- data/lib/lutaml/uml_repository/static_site/serializers/package_tree_builder.rb +93 -0
- data/lib/lutaml/version.rb +1 -1
- data/lib/lutaml/xmi/liquid_drops/association_drop.rb +13 -35
- data/lib/lutaml/xmi/liquid_drops/attribute_drop.rb +12 -18
- data/lib/lutaml/xmi/liquid_drops/cardinality_drop.rb +14 -6
- data/lib/lutaml/xmi/liquid_drops/connector_drop.rb +0 -3
- data/lib/lutaml/xmi/liquid_drops/constraint_drop.rb +1 -3
- data/lib/lutaml/xmi/liquid_drops/data_type_drop.rb +13 -70
- data/lib/lutaml/xmi/liquid_drops/dependency_drop.rb +2 -5
- data/lib/lutaml/xmi/liquid_drops/diagram_drop.rb +5 -11
- data/lib/lutaml/xmi/liquid_drops/enum_drop.rb +8 -16
- data/lib/lutaml/xmi/liquid_drops/enum_owned_literal_drop.rb +3 -9
- data/lib/lutaml/xmi/liquid_drops/generalization_attribute_drop.rb +11 -13
- data/lib/lutaml/xmi/liquid_drops/generalization_drop.rb +27 -85
- data/lib/lutaml/xmi/liquid_drops/klass_drop.rb +39 -91
- data/lib/lutaml/xmi/liquid_drops/operation_drop.rb +3 -9
- data/lib/lutaml/xmi/liquid_drops/package_drop.rb +16 -44
- data/lib/lutaml/xmi/liquid_drops/root_drop.rb +3 -11
- data/lib/lutaml/xmi/liquid_drops/source_target_drop.rb +2 -5
- data/lib/lutaml/xmi/parsers/xmi_base.rb +2 -749
- data/lib/lutaml/xmi/parsers/xmi_class_members.rb +45 -0
- data/lib/lutaml/xmi/parsers/xmi_connector.rb +251 -0
- data/lib/lutaml/xmi/parsers/xml.rb +7 -120
- data/lib/lutaml/xmi/xmi_lookup_service.rb +42 -0
- data/lib/lutaml.rb +0 -1
- metadata +48 -21
- data/lib/lutaml/cli/commands/base_command.rb +0 -118
- data/lib/lutaml/command_line.rb +0 -272
- data/lib/lutaml/sysml/allocate.rb +0 -9
- data/lib/lutaml/sysml/allocated.rb +0 -9
- data/lib/lutaml/sysml/binding_connector.rb +0 -9
- data/lib/lutaml/sysml/block.rb +0 -32
- data/lib/lutaml/sysml/constraint_block.rb +0 -14
- data/lib/lutaml/sysml/copy.rb +0 -8
- data/lib/lutaml/sysml/derive_requirement.rb +0 -9
- data/lib/lutaml/sysml/nested_connector_end.rb +0 -13
- data/lib/lutaml/sysml/refine.rb +0 -9
- data/lib/lutaml/sysml/requirement.rb +0 -44
- data/lib/lutaml/sysml/requirement_related.rb +0 -9
- data/lib/lutaml/sysml/satisfy.rb +0 -9
- data/lib/lutaml/sysml/test_case.rb +0 -25
- data/lib/lutaml/sysml/trace.rb +0 -9
- data/lib/lutaml/sysml/verify.rb +0 -8
- data/lib/lutaml/sysml/xmi_file.rb +0 -486
- data/lib/lutaml/sysml.rb +0 -11
|
@@ -69,8 +69,8 @@ module Lutaml
|
|
|
69
69
|
desc: "Load metadata from YAML file"
|
|
70
70
|
|
|
71
71
|
# Build options
|
|
72
|
-
thor_class.option :format, type: :string, default: "
|
|
73
|
-
desc: "Serialization format (
|
|
72
|
+
thor_class.option :format, type: :string, default: "yaml",
|
|
73
|
+
desc: "Serialization format (yaml)"
|
|
74
74
|
thor_class.option :validate, type: :boolean, default: true,
|
|
75
75
|
desc: "Validate before building"
|
|
76
76
|
thor_class.option :strict, type: :boolean, default: false,
|
|
@@ -166,7 +166,7 @@ module Lutaml
|
|
|
166
166
|
# Export to package with metadata
|
|
167
167
|
export_options = {
|
|
168
168
|
serialization_format: (
|
|
169
|
-
options[:format] || options["format"] || "
|
|
169
|
+
options[:format] || options["format"] || "yaml"
|
|
170
170
|
).to_sym,
|
|
171
171
|
metadata: metadata,
|
|
172
172
|
}
|
|
@@ -213,7 +213,7 @@ module Lutaml
|
|
|
213
213
|
name: options[:name] || File.basename(options[:output] || "model",
|
|
214
214
|
".lur"),
|
|
215
215
|
version: options[:version] || "1.0",
|
|
216
|
-
serialization_format: (options[:format] || "
|
|
216
|
+
serialization_format: (options[:format] || "yaml").to_s,
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
# Add optional fields if provided
|
|
@@ -273,7 +273,7 @@ module Lutaml
|
|
|
273
273
|
|
|
274
274
|
# Ensure serialization_format is set
|
|
275
275
|
metadata_hash["serialization_format"] ||= (
|
|
276
|
-
options[:format] || "
|
|
276
|
+
options[:format] || "yaml"
|
|
277
277
|
).to_s
|
|
278
278
|
|
|
279
279
|
Lutaml::UmlRepository::PackageMetadata.from_hash(metadata_hash)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "xmi_to_uml_generalization"
|
|
4
|
+
|
|
3
5
|
module Lutaml
|
|
4
6
|
module Converter
|
|
5
7
|
module XmiToUml
|
|
@@ -199,159 +201,6 @@ module Lutaml
|
|
|
199
201
|
end
|
|
200
202
|
end
|
|
201
203
|
|
|
202
|
-
def create_uml_attributes(uml_general_obj) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
203
|
-
upper_klass = uml_general_obj.general_upper_klass
|
|
204
|
-
gen_attrs = uml_general_obj.general_attributes
|
|
205
|
-
gen_name = uml_general_obj.general_name
|
|
206
|
-
|
|
207
|
-
gen_attrs&.each do |i|
|
|
208
|
-
name_ns = case i.type_ns
|
|
209
|
-
when "core", "gml"
|
|
210
|
-
upper_klass
|
|
211
|
-
else
|
|
212
|
-
i.type_ns
|
|
213
|
-
end
|
|
214
|
-
name_ns = upper_klass if name_ns.nil?
|
|
215
|
-
|
|
216
|
-
i.name_ns = name_ns
|
|
217
|
-
i.gen_name = gen_name
|
|
218
|
-
i.name = "" if i.name.nil?
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
gen_attrs
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def create_uml_generalization(klass) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
225
|
-
uml_general_obj, next_general_node_id = get_uml_general(klass.id)
|
|
226
|
-
return uml_general_obj unless next_general_node_id
|
|
227
|
-
|
|
228
|
-
if uml_general_obj.general
|
|
229
|
-
inherited_props = []
|
|
230
|
-
inherited_assoc_props = []
|
|
231
|
-
level = 0
|
|
232
|
-
|
|
233
|
-
loop_general_item(
|
|
234
|
-
uml_general_obj.general,
|
|
235
|
-
level,
|
|
236
|
-
inherited_props,
|
|
237
|
-
inherited_assoc_props,
|
|
238
|
-
)
|
|
239
|
-
uml_general_obj.inherited_props = inherited_props.reverse
|
|
240
|
-
uml_general_obj.inherited_assoc_props = inherited_assoc_props.reverse
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
uml_general_obj
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
def get_uml_general(general_id) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
247
|
-
general_node = find_packaged_element_by_id(general_id)
|
|
248
|
-
return [] unless general_node
|
|
249
|
-
|
|
250
|
-
general_node_attrs = get_uml_general_attributes(general_node)
|
|
251
|
-
general_upper_klass = find_upper_level_packaged_element(general_id)
|
|
252
|
-
next_general_node_id = get_next_general_node_id(general_node)
|
|
253
|
-
|
|
254
|
-
uml_general = ::Lutaml::Uml::Generalization.new.tap do |gen|
|
|
255
|
-
gen.general_id = general_id
|
|
256
|
-
gen.general_name = general_node.name
|
|
257
|
-
gen.general_attributes = general_node_attrs
|
|
258
|
-
gen.general_upper_klass = general_upper_klass&.name
|
|
259
|
-
gen.name = general_node.name
|
|
260
|
-
gen.type = general_node.type
|
|
261
|
-
gen.definition = lookup_element_prop_documentation(general_id)
|
|
262
|
-
gen_st = doc_node_attribute_value(general_id, "stereotype")
|
|
263
|
-
gen.stereotype = [gen_st] if gen_st
|
|
264
|
-
|
|
265
|
-
if next_general_node_id
|
|
266
|
-
gen.general = set_uml_generalization(
|
|
267
|
-
next_general_node_id,
|
|
268
|
-
)
|
|
269
|
-
gen.has_general = true
|
|
270
|
-
gen.general_id = general_node.id
|
|
271
|
-
gen.general_name = general_node.name
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
uml_general.attributes = create_uml_attributes(uml_general)
|
|
276
|
-
uml_general.owned_props = uml_general.attributes.select do |attr|
|
|
277
|
-
attr.association.nil?
|
|
278
|
-
end
|
|
279
|
-
uml_general.assoc_props = uml_general.attributes.select(&:association)
|
|
280
|
-
|
|
281
|
-
[uml_general, next_general_node_id]
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def get_uml_general_attributes(general_node) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
285
|
-
attrs = create_uml_class_attributes(general_node)
|
|
286
|
-
|
|
287
|
-
attrs.sort_by { |a| [a.name.to_s, a.id] }.map do |attr|
|
|
288
|
-
::Lutaml::Uml::GeneralAttribute.new.tap do |gen_attr|
|
|
289
|
-
gen_attr.id = attr.id
|
|
290
|
-
gen_attr.name = attr.name
|
|
291
|
-
gen_attr.type = attr.type
|
|
292
|
-
gen_attr.xmi_id = attr.xmi_id
|
|
293
|
-
gen_attr.is_derived = !!attr.is_derived
|
|
294
|
-
gen_attr.cardinality = attr.cardinality
|
|
295
|
-
gen_attr.definition = attr.definition&.strip
|
|
296
|
-
gen_attr.association = attr.association
|
|
297
|
-
gen_attr.has_association = !!attr.association
|
|
298
|
-
gen_attr.type_ns = attr.type_ns
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def set_uml_generalization(general_id)
|
|
304
|
-
uml_general_obj, next_general_node_id = get_uml_general(general_id)
|
|
305
|
-
|
|
306
|
-
if next_general_node_id
|
|
307
|
-
uml_general_obj.general = set_uml_generalization(
|
|
308
|
-
next_general_node_id,
|
|
309
|
-
)
|
|
310
|
-
uml_general_obj.has_general = true
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
uml_general_obj
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
def loop_general_item( # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
|
|
317
|
-
general_item, level, inherited_props, inherited_assoc_props
|
|
318
|
-
)
|
|
319
|
-
gen_upper_klass = general_item.general_upper_klass
|
|
320
|
-
gen_name = general_item.general_name
|
|
321
|
-
|
|
322
|
-
# reverse the order to show super class first
|
|
323
|
-
general_item.attributes.reverse_each do |attr|
|
|
324
|
-
attr.upper_klass = gen_upper_klass
|
|
325
|
-
attr.gen_name = gen_name
|
|
326
|
-
attr.level = level
|
|
327
|
-
|
|
328
|
-
if attr.association
|
|
329
|
-
inherited_assoc_props << attr
|
|
330
|
-
else
|
|
331
|
-
inherited_props << attr
|
|
332
|
-
end
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
if general_item&.has_general && general_item.general
|
|
336
|
-
level += 1
|
|
337
|
-
loop_general_item(
|
|
338
|
-
general_item.general, level, inherited_props, inherited_assoc_props
|
|
339
|
-
)
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
def create_uml_assoc_generalizations(klass) # rubocop:disable Metrics/AbcSize
|
|
344
|
-
return [] if klass.generalization.nil? || klass.generalization.empty?
|
|
345
|
-
|
|
346
|
-
klass.generalization.map do |gen|
|
|
347
|
-
::Lutaml::Uml::AssociationGeneralization.new.tap do |assoc_gen|
|
|
348
|
-
assoc_gen.id = gen.id
|
|
349
|
-
assoc_gen.type = gen.type
|
|
350
|
-
assoc_gen.general = gen.general
|
|
351
|
-
end
|
|
352
|
-
end
|
|
353
|
-
end
|
|
354
|
-
|
|
355
204
|
def create_uml_associations(xmi_id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
356
205
|
matched_element = xmi_index&.find_element(xmi_id)
|
|
357
206
|
|
|
@@ -424,6 +273,7 @@ module Lutaml
|
|
|
424
273
|
|
|
425
274
|
if !operation.respond_to?(:association) || operation.association.nil?
|
|
426
275
|
::Lutaml::Uml::Operation.new.tap do |op|
|
|
276
|
+
op.id = operation.id
|
|
427
277
|
op.xmi_id = uml_type_idref
|
|
428
278
|
op.name = operation.name
|
|
429
279
|
op.definition = lookup_attribute_documentation(operation.id)
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Converter
|
|
5
|
+
module XmiToUml
|
|
6
|
+
# Generalization-related conversion methods for XMI → UML
|
|
7
|
+
#
|
|
8
|
+
# These methods handle the recursive generalization hierarchy:
|
|
9
|
+
# creating UML generalization objects, walking the chain of
|
|
10
|
+
# parent classes, and collecting inherited properties.
|
|
11
|
+
|
|
12
|
+
def create_uml_attributes(uml_general_obj) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
13
|
+
upper_klass = uml_general_obj.general_upper_klass
|
|
14
|
+
gen_attrs = uml_general_obj.general_attributes
|
|
15
|
+
gen_name = uml_general_obj.general_name
|
|
16
|
+
|
|
17
|
+
gen_attrs&.each do |i|
|
|
18
|
+
name_ns = case i.type_ns
|
|
19
|
+
when "core", "gml"
|
|
20
|
+
upper_klass
|
|
21
|
+
else
|
|
22
|
+
i.type_ns
|
|
23
|
+
end
|
|
24
|
+
name_ns = upper_klass if name_ns.nil?
|
|
25
|
+
|
|
26
|
+
i.name_ns = name_ns
|
|
27
|
+
i.gen_name = gen_name
|
|
28
|
+
i.name = "" if i.name.nil?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
gen_attrs
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create_uml_generalization(klass) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
35
|
+
uml_general_obj, next_general_node_id = get_uml_general(klass.id)
|
|
36
|
+
return uml_general_obj unless next_general_node_id
|
|
37
|
+
|
|
38
|
+
if uml_general_obj.general
|
|
39
|
+
inherited_props = []
|
|
40
|
+
inherited_assoc_props = []
|
|
41
|
+
level = 0
|
|
42
|
+
|
|
43
|
+
loop_general_item(
|
|
44
|
+
uml_general_obj.general,
|
|
45
|
+
level,
|
|
46
|
+
inherited_props,
|
|
47
|
+
inherited_assoc_props,
|
|
48
|
+
)
|
|
49
|
+
uml_general_obj.inherited_props = inherited_props.reverse
|
|
50
|
+
uml_general_obj.inherited_assoc_props = inherited_assoc_props.reverse
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
uml_general_obj
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def get_next_general_node_id(general_node)
|
|
57
|
+
general_node.generalization.first&.general
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_uml_general(general_id) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
61
|
+
general_node = find_packaged_element_by_id(general_id)
|
|
62
|
+
return [] unless general_node
|
|
63
|
+
|
|
64
|
+
general_node_attrs = get_uml_general_attributes(general_node)
|
|
65
|
+
general_upper_klass = find_upper_level_packaged_element(general_id)
|
|
66
|
+
next_general_node_id = get_next_general_node_id(general_node)
|
|
67
|
+
|
|
68
|
+
uml_general = build_uml_general_node(
|
|
69
|
+
general_id, general_node, general_node_attrs,
|
|
70
|
+
general_upper_klass, next_general_node_id
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
assign_general_properties(uml_general)
|
|
74
|
+
|
|
75
|
+
[uml_general, next_general_node_id]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def build_uml_general_node(general_id, general_node, attrs, upper_klass,
|
|
79
|
+
next_id)
|
|
80
|
+
gen = ::Lutaml::Uml::Generalization.new
|
|
81
|
+
assign_general_basic_props(gen, general_id, general_node, attrs,
|
|
82
|
+
upper_klass)
|
|
83
|
+
assign_stereotype(gen, general_id)
|
|
84
|
+
assign_parent_generalization(gen, general_node, next_id)
|
|
85
|
+
gen
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def assign_general_basic_props(gen, general_id, general_node, attrs,
|
|
89
|
+
upper_klass)
|
|
90
|
+
gen.general_id = general_id
|
|
91
|
+
gen.general_name = general_node.name
|
|
92
|
+
gen.general_attributes = attrs
|
|
93
|
+
gen.general_upper_klass = upper_klass ? get_package_name(upper_klass) : nil
|
|
94
|
+
gen.name = general_node.name
|
|
95
|
+
gen.type = general_node.type
|
|
96
|
+
gen.definition = lookup_element_prop_documentation(general_id)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def assign_stereotype(gen, general_id)
|
|
100
|
+
gen_st = doc_node_attribute_value(general_id, "stereotype")
|
|
101
|
+
gen.stereotype = [gen_st] if gen_st
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def assign_parent_generalization(gen, general_node, next_id)
|
|
105
|
+
return unless next_id
|
|
106
|
+
|
|
107
|
+
gen.general = set_uml_generalization(next_id)
|
|
108
|
+
gen.has_general = true
|
|
109
|
+
gen.general_id = general_node.id
|
|
110
|
+
gen.general_name = general_node.name
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def assign_general_properties(uml_general)
|
|
114
|
+
uml_general.attributes = create_uml_attributes(uml_general)
|
|
115
|
+
uml_general.owned_props = uml_general.attributes.select do |attr|
|
|
116
|
+
attr.association.nil?
|
|
117
|
+
end
|
|
118
|
+
uml_general.assoc_props = uml_general.attributes.select(&:association)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def get_uml_general_attributes(general_node) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
122
|
+
attrs = create_uml_class_attributes(general_node)
|
|
123
|
+
|
|
124
|
+
attrs.map do |attr|
|
|
125
|
+
::Lutaml::Uml::GeneralAttribute.new.tap do |gen_attr|
|
|
126
|
+
gen_attr.id = attr.id
|
|
127
|
+
gen_attr.name = attr.name
|
|
128
|
+
gen_attr.type = attr.type
|
|
129
|
+
gen_attr.xmi_id = attr.xmi_id
|
|
130
|
+
gen_attr.is_derived = !!attr.is_derived
|
|
131
|
+
gen_attr.cardinality = attr.cardinality
|
|
132
|
+
gen_attr.definition = attr.definition&.strip
|
|
133
|
+
gen_attr.association = attr.association
|
|
134
|
+
gen_attr.has_association = !!attr.association
|
|
135
|
+
gen_attr.type_ns = attr.type_ns
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def set_uml_generalization(general_id)
|
|
141
|
+
uml_general_obj, next_general_node_id = get_uml_general(general_id)
|
|
142
|
+
|
|
143
|
+
if next_general_node_id
|
|
144
|
+
uml_general_obj.general = set_uml_generalization(
|
|
145
|
+
next_general_node_id,
|
|
146
|
+
)
|
|
147
|
+
uml_general_obj.has_general = true
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
uml_general_obj
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def loop_general_item( # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
|
|
154
|
+
general_item, level, inherited_props, inherited_assoc_props
|
|
155
|
+
)
|
|
156
|
+
gen_upper_klass = general_item.general_upper_klass
|
|
157
|
+
gen_name = general_item.general_name
|
|
158
|
+
|
|
159
|
+
# reverse the order to show super class first
|
|
160
|
+
general_item.attributes.reverse_each do |attr|
|
|
161
|
+
attr.upper_klass = gen_upper_klass
|
|
162
|
+
attr.gen_name = gen_name
|
|
163
|
+
attr.level = level
|
|
164
|
+
|
|
165
|
+
if attr.association
|
|
166
|
+
inherited_assoc_props << attr
|
|
167
|
+
else
|
|
168
|
+
inherited_props << attr
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
if general_item&.has_general && general_item.general
|
|
173
|
+
level += 1
|
|
174
|
+
loop_general_item(
|
|
175
|
+
general_item.general, level, inherited_props, inherited_assoc_props
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def create_uml_assoc_generalizations(klass) # rubocop:disable Metrics/AbcSize
|
|
181
|
+
return [] if klass.generalization.nil? || klass.generalization.empty?
|
|
182
|
+
|
|
183
|
+
klass.generalization.map do |gen|
|
|
184
|
+
::Lutaml::Uml::AssociationGeneralization.new.tap do |assoc_gen|
|
|
185
|
+
assoc_gen.id = gen.id
|
|
186
|
+
assoc_gen.type = gen.type
|
|
187
|
+
assoc_gen.general = gen.general
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
data/lib/lutaml/qea/database.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "repositories/object_repository"
|
|
4
|
+
require_relative "lookup_indexes"
|
|
4
5
|
|
|
5
6
|
module Lutaml
|
|
6
7
|
module Qea
|
|
@@ -425,53 +426,6 @@ module Lutaml
|
|
|
425
426
|
@collections.freeze
|
|
426
427
|
super
|
|
427
428
|
end
|
|
428
|
-
|
|
429
|
-
private
|
|
430
|
-
|
|
431
|
-
# Build a group index from a collection by a given attribute.
|
|
432
|
-
# BaseRepository overrides group_by to take a symbol (not a block),
|
|
433
|
-
# so we use each_with_object instead.
|
|
434
|
-
#
|
|
435
|
-
# @param collection [Array] Collection to index
|
|
436
|
-
# @param method [Symbol] Attribute method to group by
|
|
437
|
-
# @param single [Boolean] If true, return single object (last match)
|
|
438
|
-
# instead of array
|
|
439
|
-
# @return [Hash] Group index
|
|
440
|
-
def build_group_index(collection, method, single: false)
|
|
441
|
-
if single
|
|
442
|
-
collection.each_with_object({}) do |item, hash|
|
|
443
|
-
key = item.send(method)
|
|
444
|
-
hash[key] = item if key
|
|
445
|
-
end
|
|
446
|
-
else
|
|
447
|
-
collection.each_with_object({}) do |item, hash|
|
|
448
|
-
key = item.send(method)
|
|
449
|
-
(hash[key] ||= []) << item if key
|
|
450
|
-
end
|
|
451
|
-
end
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
# Eagerly build all lazy lookup indexes before freezing
|
|
455
|
-
def build_lookup_indexes
|
|
456
|
-
@objects_by_guid = build_group_index(objects, :ea_guid, single: true)
|
|
457
|
-
@attributes_by_object_id = build_group_index(attributes, :ea_object_id)
|
|
458
|
-
@operations_by_object_id = build_group_index(operations, :ea_object_id)
|
|
459
|
-
@operation_params_by_id = build_group_index(operation_params,
|
|
460
|
-
:operationid)
|
|
461
|
-
@connectors_by_start = build_group_index(connectors, :start_object_id)
|
|
462
|
-
@connectors_by_end = build_group_index(connectors, :end_object_id)
|
|
463
|
-
@packages_by_parent = build_group_index(packages, :parent_id)
|
|
464
|
-
@objects_by_package_id = build_group_index(objects, :package_id)
|
|
465
|
-
@diagrams_by_package_id = build_group_index(diagrams, :package_id)
|
|
466
|
-
@diagram_objects_by_id = build_group_index(diagram_objects, :diagram_id)
|
|
467
|
-
@diagram_links_by_id = build_group_index(diagram_links, :diagramid)
|
|
468
|
-
# Also build hash indexes for find_* methods
|
|
469
|
-
@packages_by_id = build_group_index(packages, :package_id, single: true)
|
|
470
|
-
@connectors_by_id = build_group_index(connectors, :connector_id,
|
|
471
|
-
single: true)
|
|
472
|
-
@diagrams_by_id = build_group_index(diagrams, :diagram_id, single: true)
|
|
473
|
-
@attributes_by_id = build_group_index(attributes, :id, single: true)
|
|
474
|
-
end
|
|
475
429
|
end
|
|
476
430
|
end
|
|
477
431
|
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base_transformer"
|
|
4
|
+
|
|
5
|
+
module Lutaml
|
|
6
|
+
module Qea
|
|
7
|
+
module Factory
|
|
8
|
+
class AssociationBuilder < BaseTransformer
|
|
9
|
+
ASSOC_TYPES = ["Association", "Aggregation", "Composition"].freeze
|
|
10
|
+
|
|
11
|
+
def load_class_associations(object_id, object_guid)
|
|
12
|
+
return [] if object_id.nil?
|
|
13
|
+
|
|
14
|
+
associations = []
|
|
15
|
+
normalized_owner_xmi_id = normalize_guid_to_xmi_format(object_guid,
|
|
16
|
+
"EAID")
|
|
17
|
+
|
|
18
|
+
assoc_connectors = database.connectors_for_object(object_id)
|
|
19
|
+
.select { |c| ASSOC_TYPES.include?(c.connector_type) }
|
|
20
|
+
|
|
21
|
+
assoc_connectors.each do |ea_connector|
|
|
22
|
+
is_start = ea_connector.start_object_id == object_id
|
|
23
|
+
|
|
24
|
+
owner_end_attribute_name = if is_start
|
|
25
|
+
ea_connector.destrole
|
|
26
|
+
else
|
|
27
|
+
ea_connector.sourcerole
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if owner_end_attribute_name.nil? || owner_end_attribute_name.empty?
|
|
31
|
+
next
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
member_obj = if is_start
|
|
35
|
+
find_object_by_id(ea_connector.end_object_id)
|
|
36
|
+
else
|
|
37
|
+
find_object_by_id(ea_connector.start_object_id)
|
|
38
|
+
end
|
|
39
|
+
next unless member_obj
|
|
40
|
+
|
|
41
|
+
member_end_attribute_name = if is_start
|
|
42
|
+
ea_connector.sourcerole
|
|
43
|
+
else
|
|
44
|
+
ea_connector.destrole
|
|
45
|
+
end
|
|
46
|
+
if member_end_attribute_name.nil? ||
|
|
47
|
+
member_end_attribute_name.empty?
|
|
48
|
+
member_end_attribute_name = member_obj.name
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
member_cardinality_str = if is_start
|
|
52
|
+
ea_connector.destcard
|
|
53
|
+
else
|
|
54
|
+
ea_connector.sourcecard
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
associations << Lutaml::Uml::Association.new.tap do |assoc|
|
|
58
|
+
assoc.xmi_id = normalize_guid_to_xmi_format(ea_connector.ea_guid,
|
|
59
|
+
"EAID")
|
|
60
|
+
assoc.name = ea_connector.name unless ea_connector.name.nil? || ea_connector.name.empty?
|
|
61
|
+
|
|
62
|
+
assoc.owner_end = find_object_by_id(object_id)&.name
|
|
63
|
+
assoc.owner_end_xmi_id = normalized_owner_xmi_id
|
|
64
|
+
assoc.owner_end_attribute_name = owner_end_attribute_name
|
|
65
|
+
|
|
66
|
+
assoc.member_end = member_obj.name
|
|
67
|
+
assoc.member_end_xmi_id = normalize_guid_to_xmi_format(
|
|
68
|
+
member_obj.ea_guid, "EAID"
|
|
69
|
+
)
|
|
70
|
+
assoc.member_end_attribute_name = member_end_attribute_name
|
|
71
|
+
|
|
72
|
+
assoc.member_end_type = ea_connector.connector_type&.downcase
|
|
73
|
+
|
|
74
|
+
if member_cardinality_str && !member_cardinality_str.empty?
|
|
75
|
+
parsed = parse_cardinality(member_cardinality_str)
|
|
76
|
+
if parsed[:min] || parsed[:max]
|
|
77
|
+
assoc.member_end_cardinality = Lutaml::Uml::Cardinality.new
|
|
78
|
+
.tap do |card|
|
|
79
|
+
card.min = parsed[:min]
|
|
80
|
+
card.max = parsed[:max]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
associations.compact
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def load_association_attributes(object_id)
|
|
91
|
+
return [] if object_id.nil?
|
|
92
|
+
|
|
93
|
+
attributes = []
|
|
94
|
+
assoc_connectors = database.connectors_for_object(object_id)
|
|
95
|
+
.select { |c| ASSOC_TYPES.include?(c.connector_type) }
|
|
96
|
+
obj = find_object_by_id(object_id)
|
|
97
|
+
obj_pkg_name = find_package_name(obj&.package_id)
|
|
98
|
+
|
|
99
|
+
assoc_connectors.each do |ea_connector|
|
|
100
|
+
if ea_connector.start_object_id == object_id
|
|
101
|
+
next if ea_connector.destrole.nil? || ea_connector.destrole.empty?
|
|
102
|
+
|
|
103
|
+
target_obj = find_object_by_id(ea_connector.end_object_id)
|
|
104
|
+
next unless target_obj
|
|
105
|
+
|
|
106
|
+
target_obj_pkg_name = find_package_name(target_obj.package_id)
|
|
107
|
+
|
|
108
|
+
attributes << create_association_attribute(
|
|
109
|
+
name: ea_connector.destrole,
|
|
110
|
+
type: target_obj.name,
|
|
111
|
+
type_xmi_id: target_obj.ea_guid,
|
|
112
|
+
association_xmi_id: ea_connector.ea_guid,
|
|
113
|
+
cardinality: ea_connector.destcard,
|
|
114
|
+
definition: ea_connector.notes,
|
|
115
|
+
gen_name: obj.name,
|
|
116
|
+
name_ns: obj_pkg_name,
|
|
117
|
+
type_ns: target_obj_pkg_name,
|
|
118
|
+
is_src: false,
|
|
119
|
+
)
|
|
120
|
+
elsif ea_connector.end_object_id == object_id
|
|
121
|
+
next if ea_connector.sourcerole.nil? || ea_connector.sourcerole.empty?
|
|
122
|
+
|
|
123
|
+
source_obj = find_object_by_id(ea_connector.start_object_id)
|
|
124
|
+
next unless source_obj
|
|
125
|
+
|
|
126
|
+
source_obj_pkg_name = find_package_name(source_obj.package_id)
|
|
127
|
+
|
|
128
|
+
attributes << create_association_attribute(
|
|
129
|
+
name: ea_connector.sourcerole,
|
|
130
|
+
type: source_obj.name,
|
|
131
|
+
type_xmi_id: source_obj.ea_guid,
|
|
132
|
+
association_xmi_id: ea_connector.ea_guid,
|
|
133
|
+
cardinality: ea_connector.sourcecard,
|
|
134
|
+
definition: ea_connector.notes,
|
|
135
|
+
gen_name: obj.name,
|
|
136
|
+
name_ns: obj_pkg_name,
|
|
137
|
+
type_ns: source_obj_pkg_name,
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
attributes.compact
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def create_association_attribute( # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/ParameterLists
|
|
146
|
+
name:, type:, type_xmi_id:,
|
|
147
|
+
association_xmi_id:, cardinality:, definition:,
|
|
148
|
+
gen_name:, name_ns:, type_ns:, is_src: true
|
|
149
|
+
)
|
|
150
|
+
Lutaml::Uml::GeneralAttribute.new.tap do |attr|
|
|
151
|
+
attr.name = name
|
|
152
|
+
attr.type = type
|
|
153
|
+
attr.gen_name = gen_name
|
|
154
|
+
attr.definition = definition
|
|
155
|
+
attr.xmi_id = normalize_guid_to_xmi_format(type_xmi_id, "EAID")
|
|
156
|
+
attr.association = normalize_guid_to_xmi_format(
|
|
157
|
+
association_xmi_id, "EAID"
|
|
158
|
+
)
|
|
159
|
+
attr.has_association = true
|
|
160
|
+
attr.id = normalize_guid_to_xmi_src_dst_format(
|
|
161
|
+
association_xmi_id, "EAID", is_src
|
|
162
|
+
)
|
|
163
|
+
attr.name_ns = name_ns
|
|
164
|
+
attr.type_ns = type_ns
|
|
165
|
+
|
|
166
|
+
if cardinality && !cardinality.empty?
|
|
167
|
+
parsed = parse_cardinality(cardinality)
|
|
168
|
+
if parsed[:min] || parsed[:max]
|
|
169
|
+
attr.cardinality = Lutaml::Uml::Cardinality.new.tap do |card|
|
|
170
|
+
card.min = parsed[:min]
|
|
171
|
+
card.max = parsed[:max]
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def find_package_name(package_id)
|
|
181
|
+
return nil if package_id.nil?
|
|
182
|
+
|
|
183
|
+
database.find_package(package_id)&.name
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|