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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +29 -33
  3. data/lib/lutaml/cli/interactive_shell/export_handler.rb +25 -17
  4. data/lib/lutaml/cli/interactive_shell/help_display.rb +39 -45
  5. data/lib/lutaml/cli/interactive_shell/navigation_commands.rb +45 -26
  6. data/lib/lutaml/cli/interactive_shell/query_commands.rb +73 -47
  7. data/lib/lutaml/cli/interactive_shell.rb +53 -27
  8. data/lib/lutaml/cli/tree_view_formatter.rb +11 -3
  9. data/lib/lutaml/converter/xmi_to_uml.rb +11 -6
  10. data/lib/lutaml/formatter/graphviz.rb +65 -35
  11. data/lib/lutaml/model_transformations/parsers/base_parser.rb +27 -29
  12. data/lib/lutaml/qea/factory/association_builder.rb +144 -127
  13. data/lib/lutaml/qea/factory/class_transformer.rb +91 -53
  14. data/lib/lutaml/qea/factory/ea_to_uml_factory.rb +11 -22
  15. data/lib/lutaml/qea/factory/enum_transformer.rb +41 -31
  16. data/lib/lutaml/qea/factory/generalization_builder.rb +155 -125
  17. data/lib/lutaml/qea/factory/stereotype_loader.rb +13 -7
  18. data/lib/lutaml/qea/lookup_indexes.rb +31 -13
  19. data/lib/lutaml/uml/inheritance_walker.rb +11 -7
  20. data/lib/lutaml/uml_repository/exporters/markdown/class_page_builder.rb +33 -25
  21. data/lib/lutaml/uml_repository/exporters/markdown/index_page_builder.rb +17 -9
  22. data/lib/lutaml/uml_repository/exporters/markdown_exporter.rb +27 -20
  23. data/lib/lutaml/uml_repository/index_builders/association_index.rb +60 -48
  24. data/lib/lutaml/uml_repository/index_builders/class_index.rb +35 -24
  25. data/lib/lutaml/uml_repository/queries/class_query.rb +79 -48
  26. data/lib/lutaml/uml_repository/queries/inheritance_query.rb +42 -32
  27. data/lib/lutaml/uml_repository/queries/search_query.rb +93 -85
  28. data/lib/lutaml/uml_repository/query_dsl/conditions/package_condition.rb +9 -2
  29. data/lib/lutaml/uml_repository/repository/loader.rb +14 -7
  30. data/lib/lutaml/uml_repository/static_site/data_transformer.rb +64 -35
  31. data/lib/lutaml/uml_repository/static_site/search_index_builder.rb +32 -19
  32. data/lib/lutaml/uml_repository/static_site/serializers/class_serializer.rb +36 -20
  33. data/lib/lutaml/uml_repository/static_site/serializers/inheritance_resolver.rb +131 -105
  34. data/lib/lutaml/uml_repository/static_site/serializers/package_serializer.rb +15 -9
  35. data/lib/lutaml/uml_repository/static_site/serializers/package_tree_builder.rb +38 -24
  36. data/lib/lutaml/version.rb +1 -1
  37. data/lib/lutaml/xmi/liquid_drops/klass_drop.rb +34 -18
  38. data/lib/lutaml/xmi/parsers/xmi_connector.rb +35 -23
  39. metadata +2 -9
  40. data/TODO.cleanups/01-resolve-production-todos.md +0 -65
  41. data/TODO.cleanups/02-reduce-metrics-offenses.md +0 -37
  42. data/TODO.cleanups/03-reduce-rspec-multiple-expectations.md +0 -54
  43. data/TODO.cleanups/04-reduce-rspec-example-length.md +0 -45
  44. data/TODO.cleanups/07-fix-lint-offenses.md +0 -74
  45. data/TODO.cleanups/08-reduce-memoized-helpers-and-nesting.md +0 -43
  46. 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: Serializers::PackageTreeBuilder.new(repository,
37
- id_generator).build,
38
- packages: Serializers::PackageSerializer.new(repository,
39
- id_generator, options).build_map,
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: Serializers::OperationSerializer.new(repository,
46
- id_generator).build_map,
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
- next unless klass.association_generalization
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
- repository.classes_index.each do |klass|
56
- documents << build_class_document(klass)
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&.map(&:name)&.join(" "),
139
- klass.operations&.map(&:name)&.join(" "),
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) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
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.attributes || []).sort_by { |a| a.name || "" }
47
- .map { |attr| @id_generator.attribute_id(attr, klass) },
43
+ attributes: serialize_attribute_ids(klass),
48
44
  operations: serialize_class_operations(klass),
49
- associations: sorted_associations,
50
- generalizations: @inheritance_resolver.find_generalizations(klass),
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 = @repository.associations_index.find do |a|
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
- if assoc.owner_end_xmi_id == klass.xmi_id
74
- assoc.owner_end_attribute_name || assoc.owner_end || ""
75
- elsif assoc.member_end_xmi_id == klass.xmi_id
76
- assoc.member_end_attribute_name || assoc.member_end || ""
77
- else
78
- ""
79
- end
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
- parent_xmi_ids = @generalization_map[klass.xmi_id]
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 = klass.generalization
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
- if parent_class.attributes
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 compute_inherited_associations(klass, visited = Set.new)
97
- return [] unless klass.generalization
98
- return [] if visited.include?(klass.xmi_id)
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
- visited.add(klass.xmi_id)
101
- inherited = []
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
- while current_gen
106
- parent_class = class_lookup.by_xmi_id(current_gen.general_id)
107
- break unless parent_class
108
- break if visited.include?(parent_class.xmi_id)
124
+ resolve_parent_class_id(parent_xmi_id)
125
+ end
126
+ parents.empty? ? nil : parents
127
+ end
109
128
 
110
- visited.add(parent_class.xmi_id)
111
- parent_associations = find_class_associations(parent_class)
112
-
113
- assoc_with_roles = parent_associations.filter_map do |assoc_id|
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
- assoc_with_roles.sort_by { |a| a[:role] }.each do |item|
130
- inherited << Models::SpaInheritedAssociation.new(
131
- association_id: item[:id],
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
- parent_order += 1
140
- current_gen = current_gen.general
141
- end
150
+ def parent_inherited_assocs(parent_class, parent_order)
151
+ assoc_with_roles = collect_assoc_roles(parent_class)
142
152
 
143
- inherited
144
- rescue StandardError => e
145
- warn "Error computing inherited associations: #{e.message}"
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 serialize_generalization(klass, visited = Set.new)
150
- return nil unless klass.generalization
151
- return nil if visited.include?(klass.xmi_id)
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
- visited.add(klass.xmi_id)
154
- gen = klass.generalization
163
+ { id: assoc_id, role: resolve_local_role(assoc, parent_class) }
164
+ end
165
+ end
155
166
 
156
- {
157
- generalId: gen.general_id,
158
- generalName: gen.general_name,
159
- generalUpperKlass: gen.general_upper_klass,
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 serialize_general_attribute(attr)
176
- return nil unless attr
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
- name: attr.name,
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
- private
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.classes || []).map do |c|
39
- @id_generator.class_id(c)
40
- end,
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