lutaml 0.10.10 → 0.10.12

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +15 -33
  3. data/lib/lutaml/cli/enhanced_formatter.rb +13 -22
  4. data/lib/lutaml/cli/interactive_shell/query_commands.rb +1 -1
  5. data/lib/lutaml/cli/output_formatter.rb +2 -2
  6. data/lib/lutaml/cli/tree_view_formatter.rb +4 -8
  7. data/lib/lutaml/cli/uml/build_command.rb +2 -3
  8. data/lib/lutaml/cli/uml/diagram_command.rb +10 -14
  9. data/lib/lutaml/cli/uml/find_command.rb +1 -1
  10. data/lib/lutaml/ea/diagram/configuration.rb +3 -3
  11. data/lib/lutaml/ea/diagram/style_resolver.rb +9 -17
  12. data/lib/lutaml/model_transformations/format_registry.rb +2 -2
  13. data/lib/lutaml/model_transformations/parsers/base_parser.rb +1 -1
  14. data/lib/lutaml/model_transformations/parsers/qea_parser.rb +3 -3
  15. data/lib/lutaml/model_transformations/parsers/xmi_parser.rb +2 -2
  16. data/lib/lutaml/model_transformations/transformation_engine.rb +1 -1
  17. data/lib/lutaml/qea/factory/ea_to_uml_factory.rb +2 -1
  18. data/lib/lutaml/qea/validation/base_validator.rb +4 -1
  19. data/lib/lutaml/qea/validation/validation_engine.rb +1 -5
  20. data/lib/lutaml/qea/verification/document_normalizer.rb +11 -11
  21. data/lib/lutaml/qea/verification/structure_matcher.rb +4 -4
  22. data/lib/lutaml/uml_repository/index_builders/association_index.rb +6 -6
  23. data/lib/lutaml/uml_repository/presenters/association_presenter.rb +3 -7
  24. data/lib/lutaml/uml_repository/presenters/attribute_presenter.rb +6 -10
  25. data/lib/lutaml/uml_repository/presenters/class_presenter.rb +1 -1
  26. data/lib/lutaml/uml_repository/presenters/datatype_presenter.rb +12 -20
  27. data/lib/lutaml/uml_repository/presenters/diagram_presenter.rb +32 -61
  28. data/lib/lutaml/uml_repository/presenters/element_presenter.rb +4 -5
  29. data/lib/lutaml/uml_repository/presenters/enum_presenter.rb +7 -9
  30. data/lib/lutaml/uml_repository/presenters/package_presenter.rb +5 -2
  31. data/lib/lutaml/uml_repository/queries/diagram_query.rb +1 -1
  32. data/lib/lutaml/uml_repository/queries/package_query.rb +4 -10
  33. data/lib/lutaml/uml_repository/queries/search_query.rb +2 -2
  34. data/lib/lutaml/uml_repository/query_dsl/conditions/package_condition.rb +2 -1
  35. data/lib/lutaml/uml_repository/validators/repository_validator.rb +9 -9
  36. data/lib/lutaml/version.rb +1 -1
  37. data/lib/lutaml/xmi/liquid_drops/data_type_drop.rb +4 -4
  38. data/lib/lutaml/xmi/liquid_drops/enum_drop.rb +1 -1
  39. data/lib/lutaml/xmi/liquid_drops/klass_drop.rb +8 -8
  40. data/lib/lutaml/xmi/liquid_drops/package_drop.rb +6 -6
  41. data/lib/lutaml/xmi/liquid_drops/root_drop.rb +2 -2
  42. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6bf7ec9ab56a8d2d17b70b191ee22dda71459f5c0e00f6066aa499a26427cde
4
- data.tar.gz: a5b2f9ed9ac2f89b8bb76b65e0b648e41c42fd20fd94e422cc8a90403683c430
3
+ metadata.gz: e6c2a2164de4ea6ec27e076a4724d35d573af91829fa0103fc3e129707597de8
4
+ data.tar.gz: 811651ff02e1b7001d056f70b3f9e96bd52c227a67d9e943134816b3408dc321
5
5
  SHA512:
6
- metadata.gz: 112cf5de38571225fd17e354dc1c4bd2debd878841f2681423c7e616176e6bd93a8935f7d504c5be181b9f4d3a6ad5220e3ff102def9753796c821e899576e65
7
- data.tar.gz: e7afc11d364ebfc3be4f651bb2fd389da30256504877209ee76154483be9b0525ca6a2dbd4fe2242a61d56447818030e304c31da02fdbd2b0851a7ff13d4d788
6
+ metadata.gz: '086fe280c4b5555a9e03d3718c5976bfbaaa7dbc9a7d4722fd6557e7779b6a673e372c5ea5e26cf9272c768067a8663672e06a2b3914bc6bbba459568a85faa5'
7
+ data.tar.gz: 49c1c37825b6e3390b696a30584998c29433dd182bb2dfbf733985fc960306913d7ed2706b38959ba9766ec2d6458f2e552180a904fef22d655c409acb276183
data/.rubocop_todo.yml CHANGED
@@ -1,30 +1,18 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-11 04:25:12 UTC using RuboCop version 1.86.1.
3
+ # on 2026-05-11 22:46:59 UTC using RuboCop version 1.86.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
10
- # This cop supports safe autocorrection (--autocorrect).
11
- # Configuration parameters: IndentationWidth.
12
- Layout/AssignmentIndentation:
13
- Exclude:
14
- - 'lib/lutaml/ea/diagram/style_resolver.rb'
15
-
16
- # Offense count: 1
17
- # This cop supports safe autocorrection (--autocorrect).
18
- # Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines.
19
- Layout/EmptyLineBetweenDefs:
20
- Exclude:
21
- - 'lib/lutaml/ea/diagram/style_parser.rb'
22
-
23
- # Offense count: 1
9
+ # Offense count: 5
24
10
  # This cop supports safe autocorrection (--autocorrect).
25
- Layout/EmptyLines:
11
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
12
+ # SupportedStyles: with_first_argument, with_fixed_indentation
13
+ Layout/ArgumentAlignment:
26
14
  Exclude:
27
- - 'lib/lutaml/ea/diagram/style_parser.rb'
15
+ - 'spec/lutaml/xmi/liquid_drops/nil_safety_spec.rb'
28
16
 
29
17
  # Offense count: 159
30
18
  # This cop supports safe autocorrection (--autocorrect).
@@ -33,12 +21,12 @@ Layout/EmptyLines:
33
21
  Layout/LineLength:
34
22
  Enabled: false
35
23
 
36
- # Offense count: 1
24
+ # Offense count: 5
37
25
  # This cop supports safe autocorrection (--autocorrect).
38
26
  # Configuration parameters: AllowInHeredoc.
39
27
  Layout/TrailingWhitespace:
40
28
  Exclude:
41
- - 'lib/lutaml/ea/diagram/style_resolver.rb'
29
+ - 'spec/lutaml/xmi/liquid_drops/nil_safety_spec.rb'
42
30
 
43
31
  # Offense count: 1
44
32
  Lint/BinaryOperatorWithIdenticalOperands:
@@ -115,7 +103,7 @@ Metrics/AbcSize:
115
103
  Metrics/BlockLength:
116
104
  Max: 53
117
105
 
118
- # Offense count: 33
106
+ # Offense count: 35
119
107
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
120
108
  Metrics/CyclomaticComplexity:
121
109
  Enabled: false
@@ -125,7 +113,7 @@ Metrics/CyclomaticComplexity:
125
113
  Metrics/MethodLength:
126
114
  Max: 62
127
115
 
128
- # Offense count: 25
116
+ # Offense count: 26
129
117
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
130
118
  Metrics/PerceivedComplexity:
131
119
  Enabled: false
@@ -139,13 +127,14 @@ Naming/MethodParameterName:
139
127
  - 'lib/lutaml/uml_repository/static_site/generator.rb'
140
128
  - 'spec/lutaml/parsers/serialize_xmi_to_liquid_spec.rb'
141
129
 
142
- # Offense count: 1
130
+ # Offense count: 3
143
131
  # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
144
132
  # AllowedMethods: call
145
133
  # WaywardPredicates: infinite?, nonzero?
146
134
  Naming/PredicateMethod:
147
135
  Exclude:
148
136
  - 'lib/lutaml/qea/factory/document_builder.rb'
137
+ - 'spec/lutaml/xmi/liquid_drops/nil_safety_spec.rb'
149
138
 
150
139
  # Offense count: 3
151
140
  # Configuration parameters: MinSize.
@@ -190,7 +179,7 @@ RSpec/ContextWording:
190
179
  - 'spec/lutaml/qea/integration/full_parsing_spec.rb'
191
180
  - 'spec/lutaml/xml/parsers/xml_spec.rb'
192
181
 
193
- # Offense count: 21
182
+ # Offense count: 22
194
183
  # Configuration parameters: IgnoredMetadata.
195
184
  RSpec/DescribeClass:
196
185
  Enabled: false
@@ -253,12 +242,12 @@ RSpec/MessageSpies:
253
242
  RSpec/MultipleExpectations:
254
243
  Max: 7
255
244
 
256
- # Offense count: 151
245
+ # Offense count: 149
257
246
  # Configuration parameters: AllowSubject.
258
247
  RSpec/MultipleMemoizedHelpers:
259
248
  Max: 11
260
249
 
261
- # Offense count: 35
250
+ # Offense count: 33
262
251
  # Configuration parameters: AllowedGroups.
263
252
  RSpec/NestedGroups:
264
253
  Max: 4
@@ -334,10 +323,3 @@ Style/SafeNavigationChainLength:
334
323
  Exclude:
335
324
  - 'lib/lutaml/qea/validation/attribute_validator.rb'
336
325
  - 'lib/lutaml/qea/validation/operation_validator.rb'
337
-
338
- # Offense count: 3
339
- # This cop supports unsafe autocorrection (--autocorrect-all).
340
- # Configuration parameters: AllowSend.
341
- Style/SendWithLiteralMethodName:
342
- Exclude:
343
- - 'lib/lutaml/ea/diagram/style_resolver.rb'
@@ -125,7 +125,7 @@ module Lutaml
125
125
  # @param klass [Object] Class object to display
126
126
  # @param path_formatter [Proc] Formatter for package paths
127
127
  # @return [String] Enhanced class details
128
- def self.format_class_details_enhanced(klass, path_formatter = nil) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
128
+ def self.format_class_details_enhanced(klass, _path_formatter = nil) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
129
129
  lines = []
130
130
 
131
131
  # Header box
@@ -137,25 +137,21 @@ module Lutaml
137
137
 
138
138
  # Basic information
139
139
  lines << colorize("Basic Information:", :cyan)
140
- if klass.respond_to?(:xmi_id)
140
+ if klass.is_a?(Lutaml::Uml::TopElement) && klass.xmi_id
141
141
  lines << " XMI ID: #{klass.xmi_id}"
142
142
  end
143
- if klass.respond_to?(:stereotype) && klass.stereotype && !klass.stereotype.empty?
143
+ if klass.is_a?(Lutaml::Uml::TopElement) && klass.stereotype && !klass.stereotype.empty?
144
144
  st = klass.stereotype
145
145
  st_str = st.is_a?(Array) ? st.join(", ") : st
146
146
  lines << " Stereotype: #{st_str}"
147
147
  end
148
- if klass.respond_to?(:is_abstract)
148
+ if klass.is_a?(Lutaml::Uml::Classifier)
149
149
  lines << " Abstract: #{klass.is_abstract ? 'Yes' : 'No'}"
150
150
  end
151
- if path_formatter && klass.respond_to?(:package)
152
- package_path = path_formatter.call(klass.package)
153
- lines << " Package: #{ICONS[:package]} #{package_path}"
154
- end
155
151
  lines << ""
156
152
 
157
153
  # Attributes
158
- if klass.respond_to?(:attributes) && klass.attributes &&
154
+ if klass.is_a?(Lutaml::Uml::Classifier) && klass.attributes &&
159
155
  !klass.attributes.empty?
160
156
  lines << colorize(
161
157
  "#{ICONS[:attribute]} Attributes (#{klass.attributes.size}):",
@@ -173,21 +169,21 @@ module Lutaml
173
169
  end
174
170
 
175
171
  # Operations
176
- if klass.respond_to?(:operations) && klass.operations &&
172
+ if klass.is_a?(Lutaml::Uml::Classifier) && klass.operations &&
177
173
  !klass.operations.empty?
178
174
  lines << colorize(
179
175
  "#{ICONS[:operation]} Operations (#{klass.operations.size}):",
180
176
  :yellow,
181
177
  )
182
178
  klass.operations.each do |op|
183
- params = if op.respond_to?(:parameters) && op.parameters
184
- op.parameters.map do |p|
179
+ params = if op.owned_parameter
180
+ op.owned_parameter.map do |p|
185
181
  "#{p.name}: #{p.type}"
186
182
  end.join(", ")
187
183
  else
188
184
  ""
189
185
  end
190
- return_type = if op.respond_to?(:return_type) && op.return_type
186
+ return_type = if op.return_type
191
187
  " : #{op.return_type}"
192
188
  else
193
189
  ""
@@ -486,18 +482,13 @@ module Lutaml
486
482
  #
487
483
  # @param attr [Object] Attribute with cardinality
488
484
  # @return [String] Formatted cardinality
489
- def self.format_cardinality(attr) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
490
- return "" unless attr.respond_to?(:cardinality)
485
+ def self.format_cardinality(attr)
491
486
  return "" unless attr.cardinality
492
487
 
493
488
  card = attr.cardinality
494
- if card.respond_to?(:min) && card.respond_to?(:max)
495
- min = card.min || "0"
496
- max = card.max || "*"
497
- "[#{min}..#{max}]"
498
- else
499
- ""
500
- end
489
+ min = card.min || "0"
490
+ max = card.max || "*"
491
+ "[#{min}..#{max}]"
501
492
  end
502
493
  end
503
494
  end
@@ -99,7 +99,7 @@ module Lutaml
99
99
  puts ""
100
100
  puts "Name: #{cls.name}"
101
101
 
102
- if cls.respond_to?(:attributes) && cls.attributes && !cls.attributes.empty?
102
+ if cls.is_a?(Lutaml::Uml::Classifier) && cls.attributes && !cls.attributes.empty?
103
103
  puts ""
104
104
  puts OutputFormatter.colorize("Attributes:", :yellow)
105
105
  cls.attributes.each do |attr|
@@ -69,7 +69,7 @@ module Lutaml
69
69
  data
70
70
  else
71
71
  # For complex objects, convert to string representation
72
- data.respond_to?(:name) ? data.name : data.to_s
72
+ data.is_a?(Lutaml::Uml::TopElement) ? data.name : data.to_s
73
73
  end
74
74
  end
75
75
 
@@ -271,7 +271,7 @@ module Lutaml
271
271
  stats[:most_complex_classes].first(5).each do |item|
272
272
  klass = item[:class]
273
273
  complexity = item[:complexity]
274
- class_name = klass.respond_to?(:name) ? klass.name : klass.to_s
274
+ class_name = klass&.name || klass.to_s
275
275
 
276
276
  lines << " #{class_name} (complexity: #{complexity})"
277
277
  end
@@ -163,7 +163,7 @@ module Lutaml
163
163
  children = []
164
164
 
165
165
  # Add attributes
166
- if @show_attributes && klass.respond_to?(:attributes) &&
166
+ if @show_attributes && klass.is_a?(Lutaml::Uml::Classifier) &&
167
167
  klass.attributes
168
168
  children.concat(klass.attributes.map do |a|
169
169
  { type: :attribute, obj: a }
@@ -171,7 +171,7 @@ module Lutaml
171
171
  end
172
172
 
173
173
  # Add operations
174
- if @show_operations && klass.respond_to?(:operations) &&
174
+ if @show_operations && klass.is_a?(Lutaml::Uml::Classifier) &&
175
175
  klass.operations
176
176
  children.concat(klass.operations.map do |o|
177
177
  { type: :operation, obj: o }
@@ -239,11 +239,7 @@ module Lutaml
239
239
  return "" if @max_depth && depth >= @max_depth
240
240
 
241
241
  assoc_name = assoc.name || "(unnamed)"
242
- target = if assoc.respond_to?(:member_end) && assoc.member_end&.first
243
- assoc.member_end.first.xmi_type || "Unknown"
244
- else
245
- "Unknown"
246
- end
242
+ target = assoc.member_end || "Unknown"
247
243
 
248
244
  connector = is_last ? TREE_CHARS[:last_branch] : TREE_CHARS[:branch]
249
245
  icon = ICONS[:association]
@@ -280,7 +276,7 @@ module Lutaml
280
276
  # Determine class type (class, interface, enumeration)
281
277
  def determine_class_type(klass)
282
278
  return :enumeration if klass.class.name&.include?("Enum")
283
- return :interface if klass.respond_to?(:stereotype) &&
279
+ return :interface if klass.is_a?(Lutaml::Uml::TopElement) &&
284
280
  Array(klass.stereotype).any? { |s| s&.downcase == "interface" }
285
281
 
286
282
  :class
@@ -141,7 +141,7 @@ module Lutaml
141
141
  OutputFormatter.progress_done
142
142
 
143
143
  # Display verbose validation if requested
144
- if options[:verbose] && result.respond_to?(:validation_details)
144
+ if options[:verbose] && result.validation_details
145
145
  display_verbose_validation(result.validation_details)
146
146
  end
147
147
 
@@ -149,8 +149,7 @@ module Lutaml
149
149
  handle_validation_result(result)
150
150
 
151
151
  # Display unique unresolved types if present
152
- if result.respond_to?(:external_references) &&
153
- result.external_references.any?
152
+ if result.external_references&.any?
154
153
  display_unresolved_types(result.external_references)
155
154
  end
156
155
 
@@ -83,12 +83,12 @@ module Lutaml
83
83
  }
84
84
 
85
85
  # Add stereotype if available
86
- if uml_element.respond_to?(:stereotype) && uml_element.stereotype && !uml_element.stereotype.empty?
86
+ if uml_element.is_a?(Lutaml::Uml::TopElement) && uml_element.stereotype && !uml_element.stereotype.empty?
87
87
  element_data[:stereotype] = uml_element.stereotype.first
88
88
  end
89
89
 
90
90
  # Add attributes and operations for classes
91
- if uml_element.respond_to?(:attributes) && uml_element.attributes
91
+ if uml_element.is_a?(Lutaml::Uml::Classifier) && uml_element.attributes
92
92
  element_data[:attributes] = uml_element.attributes.map do |attr|
93
93
  {
94
94
  name: attr.name,
@@ -98,7 +98,7 @@ module Lutaml
98
98
  end
99
99
  end
100
100
 
101
- if uml_element.respond_to?(:operations) && uml_element.operations
101
+ if uml_element.is_a?(Lutaml::Uml::Classifier) && uml_element.operations
102
102
  element_data[:operations] = uml_element.operations.map do |op|
103
103
  {
104
104
  name: op.name,
@@ -131,30 +131,30 @@ module Lutaml
131
131
  }
132
132
 
133
133
  # Add role and multiplicity information if available
134
- if connector.respond_to?(:owner_end_attribute_name) &&
134
+ if connector.is_a?(Lutaml::Uml::Association) &&
135
135
  connector.owner_end_attribute_name
136
136
  connector_data[:source_role] = connector.owner_end_attribute_name
137
137
  end
138
138
 
139
- if connector.respond_to?(:member_end_attribute_name) &&
139
+ if connector.is_a?(Lutaml::Uml::Association) &&
140
140
  connector.member_end_attribute_name
141
141
  connector_data[:target_role] = connector.member_end_attribute_name
142
142
  end
143
143
 
144
- if connector.respond_to?(:owner_end_cardinality) &&
144
+ if connector.is_a?(Lutaml::Uml::Association) &&
145
145
  connector.owner_end_cardinality
146
146
  connector_data[:source_multiplicity] =
147
147
  format_cardinality(connector.owner_end_cardinality)
148
148
  end
149
149
 
150
- if connector.respond_to?(:member_end_cardinality) &&
150
+ if connector.is_a?(Lutaml::Uml::Association) &&
151
151
  connector.member_end_cardinality
152
152
  connector_data[:target_multiplicity] =
153
153
  format_cardinality(connector.member_end_cardinality)
154
154
  end
155
155
 
156
156
  # Add source and target information if available
157
- if connector.respond_to?(:source) && connector.source
157
+ if connector.is_a?(Lutaml::Uml::Association) && connector.owner_end
158
158
  source_obj = find_diagram_object_for_element(
159
159
  connector.source.xmi_id, diagram
160
160
  )
@@ -166,7 +166,7 @@ module Lutaml
166
166
  end
167
167
  end
168
168
 
169
- if connector.respond_to?(:target) && connector.target
169
+ if connector.is_a?(Lutaml::Uml::Association) && connector.member_end
170
170
  target_obj = find_diagram_object_for_element(
171
171
  connector.target.xmi_id, diagram
172
172
  )
@@ -405,11 +405,7 @@ module Lutaml
405
405
  def format_cardinality(cardinality)
406
406
  return "" unless cardinality
407
407
 
408
- if cardinality.respond_to?(:to_s)
409
- cardinality.to_s
410
- else
411
- ""
412
- end
408
+ cardinality.to_s
413
409
  end
414
410
  end
415
411
  end
@@ -84,7 +84,7 @@ module Lutaml
84
84
  end
85
85
 
86
86
  output = classes.map do |cls|
87
- cls.respond_to?(:name) ? (cls.name || cls.to_s) : cls.to_s
87
+ cls.is_a?(Lutaml::Uml::TopElement) ? cls.name : cls.to_s
88
88
  end
89
89
 
90
90
  # output result based on the format option
@@ -47,14 +47,14 @@ module Lutaml
47
47
  value = nil
48
48
 
49
49
  # 1. Try class-specific override (highest priority)
50
- if element.respond_to?(:name) && element.name
50
+ if element.is_a?(Lutaml::Uml::TopElement) && element.name
51
51
  class_config = dig_config("classes.#{element.name}.#{property}")
52
52
  value = class_config if class_config
53
53
  end
54
54
 
55
55
  # 2. Try package-based styling
56
56
  if !value &&
57
- element.respond_to?(:package_name) && element.package_name
57
+ element.is_a?(Lutaml::Uml::Diagram) && element.package_name
58
58
  # Support wildcards: "CityGML::*"
59
59
  package_configs = config_data["packages"] || {}
60
60
  package_configs.each do |pattern, pkg_config|
@@ -67,7 +67,7 @@ module Lutaml
67
67
  end
68
68
 
69
69
  # 3. Try stereotype-based styling
70
- if !value && element.respond_to?(:stereotype) && element.stereotype
70
+ if !value && element.is_a?(Lutaml::Uml::TopElement) && element.stereotype
71
71
  stereotypes = Array(element.stereotype)
72
72
  stereotypes.each do |stereo|
73
73
  stereo_value = dig_config("stereotypes.#{stereo}.#{property}")
@@ -264,23 +264,15 @@ module Lutaml
264
264
  #
265
265
  # @param connector [Object] Association connector
266
266
  # @return [String] Specific association type
267
- def determine_association_type(connector) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
268
- return "association" unless connector.respond_to?(:member_end)
269
- return "association" unless connector.member_end
270
-
271
- # Ensure member_end is an array (handle legacy data
272
- # where it might be a string)
273
- member_ends = Array(connector.member_end)
274
-
275
- # Check for aggregation or composition
276
- member_ends.each do |end_point|
277
- if end_point.respond_to?(:aggregation)
278
- case end_point.aggregation&.downcase
279
- when "shared"
280
- return "aggregation"
281
- when "composite"
282
- return "composition"
283
- end
267
+ def determine_association_type(connector)
268
+ return "association" unless connector.is_a?(Lutaml::Uml::Association)
269
+
270
+ [connector.owner_end_type, connector.member_end_type].each do |type|
271
+ case type&.downcase
272
+ when "aggregation"
273
+ return "aggregation"
274
+ when "composition"
275
+ return "composition"
284
276
  end
285
277
  end
286
278
 
@@ -63,7 +63,7 @@ module Lutaml
63
63
  # @return [void]
64
64
  def auto_register_from_parser(parser_class)
65
65
  supported_extensions = ""
66
- if parser_class.new.respond_to?(:supported_extensions)
66
+ if parser_class.method_defined?(:supported_extensions)
67
67
  supported_extensions = parser_class.new.supported_extensions
68
68
  end
69
69
  register(supported_extensions, parser_class)
@@ -255,7 +255,7 @@ module Lutaml
255
255
 
256
256
  # Check header match for content patterns
257
257
  @parsers.each do |ext, parser_class|
258
- if parser_class.new.respond_to? :content_patterns
258
+ if parser_class.method_defined?(:content_patterns)
259
259
  parser_klass = parser_class.new
260
260
  parser_klass.content_patterns.each do |pattern|
261
261
  if header.match?(pattern)
@@ -107,7 +107,7 @@ module Lutaml
107
107
  extension = File.extname(file_path).downcase
108
108
  return true if supported_extensions.include?(extension)
109
109
 
110
- if respond_to?(:content_patterns) && File.exist?(file_path)
110
+ if self.class.method_defined?(:content_patterns) && File.exist?(file_path)
111
111
  File.open(file_path, "rb") do |file|
112
112
  header = file.read(1024) # Read first 1KB
113
113
  return false if header.nil? || header.empty?
@@ -269,16 +269,16 @@ module Lutaml
269
269
  # @return [void]
270
270
  def post_process_qea_document(document, file_path)
271
271
  # Set QEA-specific source information
272
- if document.respond_to?(:source_file=)
272
+ if document.class.method_defined?(:source_file=)
273
273
  document.source_file = file_path
274
274
  end
275
275
 
276
- if document.respond_to?(:source_format=)
276
+ if document.class.method_defined?(:source_format=)
277
277
  document.source_format = "QEA"
278
278
  end
279
279
 
280
280
  # Store database statistics
281
- if document.respond_to?(:database_stats=)
281
+ if document.class.method_defined?(:database_stats=)
282
282
  document.database_stats = @database_stats
283
283
  end
284
284
  end
@@ -138,12 +138,12 @@ module Lutaml
138
138
  # @return [void]
139
139
  def post_process_xmi_document(document, file_path)
140
140
  # Set source file information
141
- if document.respond_to?(:source_file=)
141
+ if document.class.method_defined?(:source_file=)
142
142
  document.source_file = file_path
143
143
  end
144
144
 
145
145
  # Add timestamp
146
- if document.respond_to?(:parsed_at=)
146
+ if document.class.method_defined?(:parsed_at=)
147
147
  document.parsed_at = Time.now
148
148
  end
149
149
 
@@ -256,7 +256,7 @@ module Lutaml
256
256
  @format_registry.all_parsers.each_value do |parser_class|
257
257
  # Try to create instance to validate
258
258
  parser = parser_class.new(configuration: @configuration)
259
- if parser.respond_to?(:parse)
259
+ if parser.class.method_defined?(:parse)
260
260
  results[:parsers_loaded] += 1
261
261
  else
262
262
  results[:parser_errors] << "Parser #{parser_class} does not " \
@@ -244,7 +244,8 @@ module Lutaml
244
244
  def collect_package_associations(package, associations) # rubocop:disable Metrics/CyclomaticComplexity
245
245
  # Collect from classes in this package
246
246
  package.classes&.each do |klass|
247
- if klass.respond_to?(:associations) && klass.associations
247
+ if (klass.is_a?(Lutaml::Uml::Class) ||
248
+ klass.is_a?(Lutaml::Uml::DataType)) && klass.associations
248
249
  associations.concat(klass.associations)
249
250
  end
250
251
  end
@@ -209,7 +209,10 @@ module Lutaml
209
209
  # @param value [Object] Value to check
210
210
  # @return [Boolean]
211
211
  def present?(value)
212
- !value.nil? && (value.respond_to?(:empty?) ? !value.empty? : true)
212
+ return false if value.nil?
213
+ return !value.empty? if value.is_a?(String) || value.is_a?(Array)
214
+
215
+ true
213
216
  end
214
217
 
215
218
  # Finds entity name from database
@@ -223,11 +223,7 @@ module Lutaml
223
223
  # Note: Use document entities for primary validation
224
224
  if @database
225
225
  context[:db_packages] = @database.packages || []
226
- context[:db_objects] = if @database.objects.respond_to?(:all)
227
- @database.objects.all
228
- else
229
- @database.objects || []
230
- end
226
+ context[:db_objects] = @database.objects.all
231
227
  context[:attributes] = @database.attributes || []
232
228
  context[:operations] = @database.operations || []
233
229
  context[:connectors] = @database.connectors || []
@@ -73,7 +73,7 @@ module Lutaml
73
73
  # Process packages recursively to remove XMI IDs
74
74
  def process_packages(packages) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
75
75
  packages.each do |package|
76
- package.xmi_id = nil if package.respond_to?(:xmi_id=)
76
+ package.xmi_id = nil
77
77
  process_classes(package.classes) if package.classes
78
78
  process_enums(package.enums) if package.enums
79
79
  process_data_types(package.data_types) if package.data_types
@@ -84,23 +84,23 @@ module Lutaml
84
84
  # Process classes to remove XMI IDs
85
85
  def process_classes(classes) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
86
86
  classes.each do |klass|
87
- klass.xmi_id = nil if klass.respond_to?(:xmi_id=)
87
+ klass.xmi_id = nil
88
88
 
89
89
  # Remove XMI IDs from attributes
90
90
  klass.attributes&.each do |attr|
91
- attr.xmi_id = nil if attr.respond_to?(:xmi_id=)
91
+ attr.xmi_id = nil
92
92
  end
93
93
 
94
94
  # Remove XMI IDs from operations
95
95
  klass.operations&.each do |op|
96
- op.xmi_id = nil if op.respond_to?(:xmi_id=)
96
+ op.xmi_id = nil
97
97
  op.parameters&.each do |param|
98
- param.xmi_id = nil if param.respond_to?(:xmi_id=)
98
+ param.xmi_id = nil if param.class.attributes.key?(:xmi_id)
99
99
  end
100
100
  end
101
101
 
102
102
  # Process nested classes
103
- if klass.respond_to?(:classes) && klass.classes
103
+ if klass.is_a?(Lutaml::Uml::Package) && klass.classes
104
104
  process_classes(klass.classes)
105
105
  end
106
106
  end
@@ -109,11 +109,11 @@ module Lutaml
109
109
  # Process associations to remove XMI IDs
110
110
  def process_associations(associations)
111
111
  associations.each do |assoc|
112
- assoc.xmi_id = nil if assoc.respond_to?(:xmi_id=)
113
- if assoc.respond_to?(:owner_end_xmi_id=)
112
+ assoc.xmi_id = nil
113
+ if assoc.owner_end_xmi_id
114
114
  assoc.owner_end_xmi_id = nil
115
115
  end
116
- if assoc.respond_to?(:member_end_xmi_id=)
116
+ if assoc.member_end_xmi_id
117
117
  assoc.member_end_xmi_id = nil
118
118
  end
119
119
  end
@@ -122,14 +122,14 @@ module Lutaml
122
122
  # Process enums to remove XMI IDs
123
123
  def process_enums(enums)
124
124
  enums.each do |enum|
125
- enum.xmi_id = nil if enum.respond_to?(:xmi_id=)
125
+ enum.xmi_id = nil
126
126
  end
127
127
  end
128
128
 
129
129
  # Process data types to remove XMI IDs
130
130
  def process_data_types(data_types)
131
131
  data_types.each do |dt|
132
- dt.xmi_id = nil if dt.respond_to?(:xmi_id=)
132
+ dt.xmi_id = nil
133
133
  end
134
134
  end
135
135