lutaml 0.10.10 → 0.10.11

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +6 -40
  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. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6bf7ec9ab56a8d2d17b70b191ee22dda71459f5c0e00f6066aa499a26427cde
4
- data.tar.gz: a5b2f9ed9ac2f89b8bb76b65e0b648e41c42fd20fd94e422cc8a90403683c430
3
+ metadata.gz: 60815cadb4a74fcb9fcdc3b84a3f6c19b450e5a6f1670d918ffd4d2e66d4a3a5
4
+ data.tar.gz: 2e24af4ab233104a171c7cac58a7416e79e5248ce61831d45ba930e44d14685b
5
5
  SHA512:
6
- metadata.gz: 112cf5de38571225fd17e354dc1c4bd2debd878841f2681423c7e616176e6bd93a8935f7d504c5be181b9f4d3a6ad5220e3ff102def9753796c821e899576e65
7
- data.tar.gz: e7afc11d364ebfc3be4f651bb2fd389da30256504877209ee76154483be9b0525ca6a2dbd4fe2242a61d56447818030e304c31da02fdbd2b0851a7ff13d4d788
6
+ metadata.gz: 4ebc0be5174ba5dafb1fbda8aa962936d9c8de3b3d909d66844a83f35cf0f353c8131af4d45f945cdd1e9bfdf4975a52b09bbe17a18cf09eae571cc5eb297a83
7
+ data.tar.gz: e41165b1694af4e86a4b2373643ec94d6bc6c0a84310c2573ba001ad5dbc278917ba796f9e2a95174fdd1b12607fb68b4fbd487f46032b2a92b8850ff301d3ae
data/.rubocop_todo.yml CHANGED
@@ -1,45 +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 09:50:12 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
24
- # This cop supports safe autocorrection (--autocorrect).
25
- Layout/EmptyLines:
26
- Exclude:
27
- - 'lib/lutaml/ea/diagram/style_parser.rb'
28
-
29
- # Offense count: 159
9
+ # Offense count: 154
30
10
  # This cop supports safe autocorrection (--autocorrect).
31
11
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
32
12
  # URISchemes: http, https
33
13
  Layout/LineLength:
34
14
  Enabled: false
35
15
 
36
- # Offense count: 1
37
- # This cop supports safe autocorrection (--autocorrect).
38
- # Configuration parameters: AllowInHeredoc.
39
- Layout/TrailingWhitespace:
40
- Exclude:
41
- - 'lib/lutaml/ea/diagram/style_resolver.rb'
42
-
43
16
  # Offense count: 1
44
17
  Lint/BinaryOperatorWithIdenticalOperands:
45
18
  Exclude:
@@ -115,7 +88,7 @@ Metrics/AbcSize:
115
88
  Metrics/BlockLength:
116
89
  Max: 53
117
90
 
118
- # Offense count: 33
91
+ # Offense count: 35
119
92
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
120
93
  Metrics/CyclomaticComplexity:
121
94
  Enabled: false
@@ -125,7 +98,7 @@ Metrics/CyclomaticComplexity:
125
98
  Metrics/MethodLength:
126
99
  Max: 62
127
100
 
128
- # Offense count: 25
101
+ # Offense count: 26
129
102
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
130
103
  Metrics/PerceivedComplexity:
131
104
  Enabled: false
@@ -253,12 +226,12 @@ RSpec/MessageSpies:
253
226
  RSpec/MultipleExpectations:
254
227
  Max: 7
255
228
 
256
- # Offense count: 151
229
+ # Offense count: 149
257
230
  # Configuration parameters: AllowSubject.
258
231
  RSpec/MultipleMemoizedHelpers:
259
232
  Max: 11
260
233
 
261
- # Offense count: 35
234
+ # Offense count: 33
262
235
  # Configuration parameters: AllowedGroups.
263
236
  RSpec/NestedGroups:
264
237
  Max: 4
@@ -334,10 +307,3 @@ Style/SafeNavigationChainLength:
334
307
  Exclude:
335
308
  - 'lib/lutaml/qea/validation/attribute_validator.rb'
336
309
  - '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
 
@@ -222,7 +222,7 @@ module Lutaml
222
222
  def index_by_name(collection)
223
223
  index = {}
224
224
  collection.each do |element|
225
- next unless element.respond_to?(:name) && element.name
225
+ next unless element.name
226
226
 
227
227
  index[element.name] = element
228
228
  end
@@ -243,10 +243,10 @@ module Lutaml
243
243
 
244
244
  # Build operation signature for matching
245
245
  def build_operation_signature(operation)
246
- return operation.name unless operation.respond_to?(:parameters)
246
+ return operation.name unless operation.owned_parameter
247
247
 
248
- param_types = (operation.parameters || []).map do |param|
249
- param.respond_to?(:type) ? param.type : "unknown"
248
+ param_types = operation.owned_parameter.map do |param|
249
+ param.type || "unknown"
250
250
  end.join(",")
251
251
 
252
252
  "#{operation.name}(#{param_types})"
@@ -14,7 +14,7 @@ module Lutaml
14
14
  # Collect class-level associations (QEA/EA format)
15
15
  # Note: This requires qualified_names index to be built first
16
16
  @qualified_names.each_value do |klass|
17
- next unless klass.respond_to?(:associations) && klass.associations
17
+ next unless (klass.is_a?(Lutaml::Uml::Class) || klass.is_a?(Lutaml::Uml::DataType)) && klass.associations
18
18
 
19
19
  klass.associations.each do |assoc|
20
20
  next unless assoc.xmi_id
@@ -73,13 +73,13 @@ module Lutaml
73
73
  next unless klass.associations
74
74
 
75
75
  klass.associations.each do |assoc|
76
- next unless assoc.respond_to?(:member_end_type)
76
+ next unless assoc.member_end_type
77
77
  next unless assoc.member_end_type == "inheritance"
78
78
 
79
79
  parent_name = assoc.member_end
80
80
  next unless parent_name
81
81
 
82
- parent_name = parent_name.name if parent_name.respond_to?(:name)
82
+ parent_name = parent_name.name if parent_name.is_a?(Lutaml::Uml::Generalization)
83
83
  next unless parent_name.is_a?(String) && !parent_name.empty?
84
84
 
85
85
  parent_qname = resolve_qualified_name(parent_name, package_path)
@@ -101,14 +101,14 @@ module Lutaml
101
101
  return nil unless generalization
102
102
 
103
103
  # Check for general attribute (could be a string or object)
104
- if generalization.respond_to?(:general)
104
+ if generalization.general
105
105
  parent = generalization.general
106
- return parent.name if parent.respond_to?(:name)
106
+ return parent.name if parent
107
107
  return parent.to_s if parent
108
108
  end
109
109
 
110
110
  # Check for name attribute directly
111
- if generalization.respond_to?(:name) && generalization.name
111
+ if generalization.name
112
112
  return generalization.name
113
113
  end
114
114
 
@@ -20,12 +20,9 @@ module Lutaml
20
20
  lines << ("=" * 50)
21
21
  lines << ""
22
22
  lines << "Name: #{element.name || '(unnamed)'}"
23
- if element.respond_to?(:xmi_id)
23
+ if element.xmi_id
24
24
  lines << "XMI ID: #{element.xmi_id}"
25
25
  end
26
- if element.respond_to?(:xmi_type)
27
- lines << "Type: #{element.xmi_type}"
28
- end
29
26
  lines << ""
30
27
  lines << "Source: #{source_display}"
31
28
  lines << "Target: #{target_display}"
@@ -48,8 +45,7 @@ module Lutaml
48
45
  target: target_display,
49
46
  }
50
47
 
51
- data[:xmi_id] = element.xmi_id if element.respond_to?(:xmi_id)
52
- data[:xmi_type] = element.xmi_type if element.respond_to?(:xmi_type)
48
+ data[:xmi_id] = element.xmi_id if element.xmi_id
53
49
 
54
50
  data
55
51
  end
@@ -66,7 +62,7 @@ module Lutaml
66
62
  # then symbol key (from show command)
67
63
  if @context["target"] || @context[:target]
68
64
  @context["target"] || @context[:target]
69
- elsif element.respond_to?(:member_end) && element.member_end
65
+ elsif element.member_end
70
66
  member_end = element.member_end.first
71
67
  if member_end.is_a?(Hash)
72
68
  member_end[:xmi_type] || "Unknown"
@@ -24,15 +24,13 @@ module Lutaml
24
24
  lines << "Class: #{class_name}"
25
25
  lines << "Type: #{element.type || 'Unknown'}"
26
26
  lines << "Cardinality: #{format_cardinality(element)}"
27
- if element.respond_to?(:visibility) && element.visibility
27
+ if element.visibility
28
28
  lines << "Visibility: #{element.visibility}"
29
29
  end
30
- if element.respond_to?(:stereotype) && element.stereotype
30
+ if element.stereotype && !element.stereotype.empty?
31
31
  lines << "Stereotype: #{element.stereotype}"
32
32
  end
33
- if element.respond_to?(:is_derived)
34
- lines << "Is Derived: #{element.is_derived}"
35
- end
33
+ lines << "Is Derived: #{element.is_derived}"
36
34
  lines.join("\n")
37
35
  end
38
36
 
@@ -53,15 +51,13 @@ module Lutaml
53
51
  cardinality: format_cardinality(element),
54
52
  }
55
53
 
56
- if element.respond_to?(:visibility)
54
+ if element.visibility
57
55
  data[:visibility] = element.visibility
58
56
  end
59
- if element.respond_to?(:stereotype)
57
+ if element.stereotype
60
58
  data[:stereotype] = element.stereotype
61
59
  end
62
- if element.respond_to?(:is_derived)
63
- data[:is_derived] = element.is_derived
64
- end
60
+ data[:is_derived] = element.is_derived
65
61
 
66
62
  data
67
63
  end
@@ -60,7 +60,7 @@ module Lutaml
60
60
  private
61
61
 
62
62
  def stereotype_display
63
- if element.respond_to?(:stereotype) && element.stereotype
63
+ if element.stereotype && !element.stereotype.empty?
64
64
  "<<#{element.stereotype}>>"
65
65
  else
66
66
  ""
@@ -20,21 +20,19 @@ module Lutaml
20
20
  lines << ("=" * 50)
21
21
  lines << ""
22
22
  lines << "Name: #{element.name}"
23
- if element.respond_to?(:xmi_id) && element.xmi_id
23
+ if element.xmi_id
24
24
  lines << "XMI ID: #{element.xmi_id}"
25
25
  end
26
- if element.respond_to?(:type) && element.type
26
+ if element.type
27
27
  lines << "Type: #{element.type}"
28
28
  end
29
- if element.respond_to?(:stereotype) && element.stereotype
29
+ if element.stereotype && !element.stereotype.empty?
30
30
  lines << "Stereotype: #{element.stereotype}"
31
31
  end
32
- if element.respond_to?(:visibility) && element.visibility
32
+ if element.visibility
33
33
  lines << "Visibility: #{element.visibility}"
34
34
  end
35
- if element.respond_to?(:is_abstract)
36
- lines << "Abstract: #{element.is_abstract}"
37
- end
35
+ lines << "Abstract: #{element.is_abstract}"
38
36
  lines << ""
39
37
 
40
38
  if element.attributes && !element.attributes.empty?
@@ -46,8 +44,7 @@ module Lutaml
46
44
  lines << ""
47
45
  end
48
46
 
49
- if element.respond_to?(:operations) && element.operations &&
50
- !element.operations.empty?
47
+ if element.operations && !element.operations.empty?
51
48
  lines << "Operations (#{element.operations.size}):"
52
49
  element.operations.each do |op|
53
50
  lines << " - #{op.name}()"
@@ -72,16 +69,12 @@ module Lutaml
72
69
  name: element.name,
73
70
  }
74
71
 
75
- data[:xmi_id] = element.xmi_id if
76
- element.respond_to?(:xmi_id) && element.xmi_id
77
- data[:data_type] = element.type if
78
- element.respond_to?(:type) && element.type
72
+ data[:xmi_id] = element.xmi_id if element.xmi_id
73
+ data[:data_type] = element.type if element.type
79
74
  data[:stereotype] = element.stereotype if
80
- element.respond_to?(:stereotype) && element.stereotype
81
- data[:visibility] = element.visibility if
82
- element.respond_to?(:visibility) && element.visibility
83
- data[:is_abstract] = element.is_abstract if
84
- element.respond_to?(:is_abstract)
75
+ element.stereotype && !element.stereotype.empty?
76
+ data[:visibility] = element.visibility if element.visibility
77
+ data[:is_abstract] = element.is_abstract
85
78
 
86
79
  if element.attributes && !element.attributes.empty?
87
80
  data[:attributes] = element.attributes.map do |attr|
@@ -92,8 +85,7 @@ module Lutaml
92
85
  end
93
86
  end
94
87
 
95
- if element.respond_to?(:operations) && element.operations &&
96
- !element.operations.empty?
88
+ if element.operations && !element.operations.empty?
97
89
  data[:operations] = element.operations.map(&:name)
98
90
  end
99
91
 
@@ -256,10 +256,10 @@ module Lutaml
256
256
  # @param diagram_object [Object] Diagram object
257
257
  # @return [String, nil] EA internal ID (DUID from style)
258
258
  def extract_ea_id(diagram_object)
259
- # EA stores the internal ID as DUID in the style string
260
- unless diagram_object.respond_to?(:style) && diagram_object.style
261
- return nil
262
- end
259
+ return nil unless diagram_object.style
260
+
261
+ # Parse DUID from style string
262
+ # Style format: "NSL=0;LCol=-1;...;DUID=82C649C4;BCol=16764159;..."
263
263
 
264
264
  # Parse DUID from style string
265
265
  # Style format: "NSL=0;LCol=-1;...;DUID=82C649C4;BCol=16764159;..."
@@ -300,20 +300,17 @@ module Lutaml
300
300
  return connector if connector
301
301
 
302
302
  repository.classes_index.each do |klass|
303
- if klass.respond_to?(:generalization) && klass.generalization
304
- # Look in class-level generalizations
303
+ if klass.is_a?(Lutaml::Uml::Class) && klass.generalization
305
304
  gen = klass.generalization
306
-
307
- # Handle both single generalization and array of generalizations
308
305
  generalizations = gen.is_a?(Array) ? gen : [gen]
309
-
310
306
  generalizations.each do |g|
311
- return g if g.respond_to?(:xmi_id) && g.xmi_id == xmi_id
307
+ return g if g.xmi_id == xmi_id
312
308
  end
313
- elsif klass.respond_to?(:associations) && klass.associations
314
- # Look in class-level associations
309
+ elsif (klass.is_a?(Lutaml::Uml::Class) ||
310
+ klass.is_a?(Lutaml::Uml::DataType)) &&
311
+ klass.associations
315
312
  assoc = klass.associations.find do |a|
316
- a.respond_to?(:xmi_id) && a.xmi_id == xmi_id
313
+ a.xmi_id == xmi_id
317
314
  end
318
315
  return assoc if assoc
319
316
  end
@@ -328,25 +325,15 @@ module Lutaml
328
325
  # @param elements_map [Hash] Map of element ID to element data
329
326
  # @return [Hash, nil] Target element data
330
327
  def find_connector_target(connector, elements_map) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
331
- target_id = nil
332
-
333
- if connector.respond_to?(:target) && connector.target
334
- target_id = connector.target
335
- elsif connector.respond_to?(:supplier) && connector.supplier
336
- target_id = connector.supplier
337
- elsif connector.respond_to?(:general) && connector.general
338
- target_id = connector.general
339
- elsif connector.respond_to?(:member_end) && connector.member_end
340
- # For associations, use the second member_end
341
- ends = if connector.member_end.is_a?(Array)
342
- connector.member_end
343
- else
344
- [connector.member_end]
345
- end
346
- if ends.size > 1
347
- target_id = ends[1]
348
- end
349
- end
328
+ target_id = case connector
329
+ when Lutaml::Uml::Generalization
330
+ connector.general
331
+ when Lutaml::Uml::Dependency
332
+ Array(connector.supplier).first
333
+ when Lutaml::Uml::Association
334
+ ends = Array(connector.member_end)
335
+ ends.size > 1 ? ends[1] : nil
336
+ end
350
337
 
351
338
  elements_map[target_id]
352
339
  end
@@ -357,27 +344,14 @@ module Lutaml
357
344
  # @param elements_map [Hash] Map of element ID to element data
358
345
  # @return [Hash, nil] Source element data
359
346
  def find_connector_source(connector, elements_map) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
360
- source_id = nil
361
-
362
- if connector.respond_to?(:source) && connector.source
363
- source_id = connector.source
364
- elsif connector.respond_to?(:client) && connector.client
365
- source_id = connector.client
366
- elsif connector.respond_to?(:specific) && connector.specific
367
- source_id = connector.specific
368
- elsif connector.respond_to?(:owner_end) && connector.owner_end
369
- source_id = connector.owner_end
370
- elsif connector.respond_to?(:member_end) && connector.member_end
371
- # For associations, use the first member_end
372
- ends = if connector.member_end.is_a?(Array)
373
- connector.member_end
374
- else
375
- [connector.member_end]
376
- end
377
- if ends.any?
378
- source_id = ends[0]
379
- end
380
- end
347
+ source_id = case connector
348
+ when Lutaml::Uml::Generalization
349
+ nil
350
+ when Lutaml::Uml::Dependency
351
+ Array(connector.client).first
352
+ when Lutaml::Uml::Association
353
+ connector.owner_end || Array(connector.member_end).first
354
+ end
381
355
 
382
356
  elements_map[source_id]
383
357
  end
@@ -421,8 +395,6 @@ module Lutaml
421
395
  # @param uml_element [Object] UML element
422
396
  # @return [String, nil] Stereotype name
423
397
  def extract_stereotype(uml_element)
424
- return nil unless uml_element.respond_to?(:stereotype)
425
-
426
398
  stereotype = uml_element.stereotype
427
399
  return nil unless stereotype && !stereotype.empty?
428
400
 
@@ -434,14 +406,14 @@ module Lutaml
434
406
  # @param uml_element [Object] UML element
435
407
  # @return [Array<Hash>] Array of attribute data
436
408
  def extract_attributes(uml_element)
437
- return [] unless uml_element.respond_to?(:attributes)
409
+ return [] unless uml_element.is_a?(Lutaml::Uml::Classifier)
438
410
  return [] unless uml_element.attributes
439
411
 
440
412
  uml_element.attributes.map do |attr|
441
413
  {
442
414
  name: attr.name,
443
415
  type: attr.type,
444
- visibility: attr.respond_to?(:visibility) ? attr.visibility : nil,
416
+ visibility: attr.visibility,
445
417
  }
446
418
  end
447
419
  end
@@ -451,14 +423,14 @@ module Lutaml
451
423
  # @param uml_element [Object] UML element
452
424
  # @return [Array<Hash>] Array of operation data
453
425
  def extract_operations(uml_element)
454
- return [] unless uml_element.respond_to?(:operations)
426
+ return [] unless uml_element.is_a?(Lutaml::Uml::Classifier)
455
427
  return [] unless uml_element.operations
456
428
 
457
429
  uml_element.operations.map do |op|
458
430
  {
459
431
  name: op.name,
460
- visibility: op.respond_to?(:visibility) ? op.visibility : nil,
461
- return_type: op.respond_to?(:return_type) ? op.return_type : nil,
432
+ visibility: op.visibility,
433
+ return_type: op.return_type,
462
434
  parameters: extract_parameters(op),
463
435
  }
464
436
  end
@@ -469,7 +441,6 @@ module Lutaml
469
441
  # @param operation [Object] UML operation
470
442
  # @return [Array<Hash>] Array of parameter data
471
443
  def extract_parameters(operation)
472
- return [] unless operation.respond_to?(:owned_parameter)
473
444
  return [] unless operation.owned_parameter
474
445
 
475
446
  operation.owned_parameter.map do |param|
@@ -55,13 +55,12 @@ module Lutaml
55
55
  #
56
56
  # @param attr [Object] Attribute or property with cardinality
57
57
  # @return [String] Formatted cardinality like "[1..1]" or "[0..*]"
58
- def format_cardinality(attr) # rubocop:disable Metrics/CyclomaticComplexity
59
- return "" unless attr.respond_to?(:cardinality) &&
60
- attr.cardinality
58
+ def format_cardinality(attr)
59
+ return "" unless attr.cardinality
61
60
 
62
61
  card = attr.cardinality
63
- min = card.respond_to?(:min) ? (card.min || "0") : "0"
64
- max = card.respond_to?(:max) ? (card.max || "*") : "*"
62
+ min = card.min || "0"
63
+ max = card.max || "*"
65
64
 
66
65
  "[#{min}..#{max}]"
67
66
  end
@@ -20,13 +20,13 @@ module Lutaml
20
20
  lines << ("=" * 50)
21
21
  lines << ""
22
22
  lines << "Name: #{element.name}"
23
- if element.respond_to?(:xmi_id) && element.xmi_id
23
+ if element.xmi_id
24
24
  lines << "XMI ID: #{element.xmi_id}"
25
25
  end
26
- if element.respond_to?(:stereotype) && element.stereotype
26
+ if element.stereotype && !element.stereotype.empty?
27
27
  lines << "Stereotype: #{element.stereotype}"
28
28
  end
29
- if element.respond_to?(:visibility) && element.visibility
29
+ if element.visibility
30
30
  lines << "Visibility: #{element.visibility}"
31
31
  end
32
32
  lines << ""
@@ -59,16 +59,14 @@ module Lutaml
59
59
  value_count: element.values ? element.values.size : 0,
60
60
  }
61
61
 
62
- data[:xmi_id] = element.xmi_id if
63
- element.respond_to?(:xmi_id) && element.xmi_id
62
+ data[:xmi_id] = element.xmi_id if element.xmi_id
64
63
  data[:stereotype] = element.stereotype if
65
- element.respond_to?(:stereotype) && element.stereotype
66
- data[:visibility] = element.visibility if
67
- element.respond_to?(:visibility) && element.visibility
64
+ element.stereotype && !element.stereotype.empty?
65
+ data[:visibility] = element.visibility if element.visibility
68
66
 
69
67
  if element.values && !element.values.empty?
70
68
  data[:values] = element.values.map do |v|
71
- v.respond_to?(:name) ? v.name : v.to_s
69
+ v.name || v.to_s
72
70
  end
73
71
  end
74
72
 
@@ -20,7 +20,7 @@ module Lutaml
20
20
  lines << ("=" * 50)
21
21
  lines << ""
22
22
  lines << "Name: #{element.name}"
23
- if element.respond_to?(:xmi_id)
23
+ if element.is_a?(Lutaml::Uml::TopElement) && element.xmi_id
24
24
  lines << "XMI ID: #{element.xmi_id}"
25
25
  end
26
26
  lines.join("\n")
@@ -35,7 +35,10 @@ module Lutaml
35
35
  name: element.name,
36
36
  }
37
37
 
38
- data[:xmi_id] = element.xmi_id if element.respond_to?(:xmi_id)
38
+ if element.is_a?(Lutaml::Uml::TopElement) && element.xmi_id
39
+ data[:xmi_id] =
40
+ element.xmi_id
41
+ end
39
42
 
40
43
  data
41
44
  end
@@ -38,7 +38,7 @@ module Lutaml
38
38
  package = indexes[:package_paths][package_path_string]
39
39
  return [] unless package
40
40
 
41
- package_id = package.respond_to?(:xmi_id) ? package.xmi_id : nil
41
+ package_id = package.is_a?(Lutaml::Uml::Package) ? package.xmi_id : nil
42
42
  return [] unless package_id
43
43
 
44
44
  indexes[:diagram_index][package_id] || []
@@ -188,15 +188,9 @@ module Lutaml
188
188
  # @return [Integer] Number of classes
189
189
  def count_classes(package) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
190
190
  count = 0
191
- count += if package.respond_to?(:classes) && package.classes
192
- package.classes.size
193
- end
194
- count += if package.respond_to?(:data_types) && package.data_types
195
- package.data_types.size
196
- end
197
- count += if package.respond_to?(:enums) && package.enums
198
- package.enums.size
199
- end
191
+ count += package.classes&.size
192
+ count += package.data_types&.size
193
+ count += package.enums&.size
200
194
  count
201
195
  end
202
196
 
@@ -206,7 +200,7 @@ module Lutaml
206
200
  # The package
207
201
  # @return [Integer] Number of diagrams
208
202
  def count_diagrams(package)
209
- return 0 unless package.respond_to?(:diagrams) && package.diagrams
203
+ return 0 unless package.diagrams
210
204
 
211
205
  package.diagrams.size
212
206
  end
@@ -260,13 +260,13 @@ module Lutaml
260
260
  all_associations = []
261
261
 
262
262
  # Get all associations defined at document level and
263
- if document.respond_to?(:associations) && document.associations
263
+ if document.is_a?(Lutaml::Uml::Document) && document.associations
264
264
  all_associations << document.associations
265
265
  end
266
266
 
267
267
  # Get all associations defined within classes
268
268
  indexes[:qualified_names].each_value do |entity|
269
- next unless entity.respond_to?(:associations) && entity.associations
269
+ next unless (entity.is_a?(Lutaml::Uml::Class) || entity.is_a?(Lutaml::Uml::DataType)) && entity.associations
270
270
 
271
271
  all_associations << entity.associations
272
272
  end
@@ -68,7 +68,8 @@ module Lutaml
68
68
  # @param obj [Object] The object to extract path from
69
69
  # @return [PackagePath, nil] The object's package path
70
70
  def extract_package_path(obj)
71
- return nil unless obj.respond_to?(:package_path)
71
+ return nil unless obj.is_a?(Lutaml::Model::Serializable) &&
72
+ obj.class.attributes&.key?(:package_path)
72
73
 
73
74
  path = obj.package_path
74
75
  return nil unless path
@@ -156,13 +156,13 @@ module Lutaml
156
156
 
157
157
  klass.associations.each do |assoc|
158
158
  # Check member_end references
159
- if assoc.respond_to?(:member_end) && assoc.member_end
159
+ if assoc.member_end
160
160
  check_association_end_type(assoc.member_end, qname)
161
161
  end
162
162
 
163
- # Check owned_end references
164
- if assoc.respond_to?(:owned_end) && assoc.owned_end
165
- check_association_end_type(assoc.owned_end, qname)
163
+ # Check owner_end references
164
+ if assoc.owner_end
165
+ check_association_end_type(assoc.owner_end, qname)
166
166
  end
167
167
  end
168
168
  end
@@ -176,11 +176,11 @@ module Lutaml
176
176
  ends_array = ends.is_a?(Array) ? ends : [ends]
177
177
 
178
178
  ends_array.each do |end_obj|
179
- next unless end_obj.respond_to?(:type)
179
+ next unless end_obj.is_a?(Lutaml::Uml::TopElementAttribute)
180
180
  next unless end_obj.type
181
181
 
182
182
  type_name = end_obj.type
183
- type_name = type_name.name if type_name.respond_to?(:name)
183
+ type_name = type_name.name if type_name.is_a?(Lutaml::Uml::TopElement)
184
184
 
185
185
  next if @indexes[:qualified_names].key?(type_name)
186
186
 
@@ -196,7 +196,7 @@ module Lutaml
196
196
  next unless klass.attributes
197
197
 
198
198
  klass.attributes.each do |attr|
199
- next unless attr.respond_to?(:cardinality)
199
+ next unless attr.cardinality
200
200
  next unless attr.cardinality
201
201
 
202
202
  cardinality = attr.cardinality
@@ -234,7 +234,7 @@ module Lutaml
234
234
  # @param cardinality [Object] Cardinality object
235
235
  # @return [Integer, nil] Min value
236
236
  def extract_min_value(cardinality)
237
- return nil unless cardinality.respond_to?(:min)
237
+ return nil unless cardinality.min
238
238
 
239
239
  min_val = cardinality.min
240
240
  return nil unless min_val
@@ -247,7 +247,7 @@ module Lutaml
247
247
  # @param cardinality [Object] Cardinality object
248
248
  # @return [Integer, String, nil] Max value (could be "*" for unlimited)
249
249
  def extract_max_value(cardinality)
250
- return nil unless cardinality.respond_to?(:max)
250
+ return nil unless cardinality.max
251
251
 
252
252
  max_val = cardinality.max
253
253
  return nil unless max_val
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lutaml
4
- VERSION = "0.10.10"
4
+ VERSION = "0.10.11"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.10
4
+ version: 0.10.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.