lutaml 0.10.9 → 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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +10 -10
  3. data/lib/lutaml/cli/enhanced_formatter.rb +13 -22
  4. data/lib/lutaml/cli/interactive_shell/command_base.rb +2 -2
  5. data/lib/lutaml/cli/interactive_shell/query_commands.rb +2 -2
  6. data/lib/lutaml/cli/interactive_shell.rb +21 -18
  7. data/lib/lutaml/cli/output_formatter.rb +2 -2
  8. data/lib/lutaml/cli/resource_registry.rb +1 -1
  9. data/lib/lutaml/cli/tree_view_formatter.rb +4 -8
  10. data/lib/lutaml/cli/uml/build_command.rb +2 -3
  11. data/lib/lutaml/cli/uml/diagram_command.rb +10 -14
  12. data/lib/lutaml/cli/uml/find_command.rb +1 -1
  13. data/lib/lutaml/cli/uml/inspect_command.rb +1 -1
  14. data/lib/lutaml/converter/dsl_to_uml.rb +8 -8
  15. data/lib/lutaml/converter/xmi_to_uml.rb +2 -2
  16. data/lib/lutaml/ea/diagram/configuration.rb +3 -3
  17. data/lib/lutaml/ea/diagram/style_parser.rb +15 -15
  18. data/lib/lutaml/ea/diagram/style_resolver.rb +13 -20
  19. data/lib/lutaml/formatter/graphviz.rb +1 -1
  20. data/lib/lutaml/model_transformations/format_registry.rb +2 -2
  21. data/lib/lutaml/model_transformations/parsers/base_parser.rb +1 -1
  22. data/lib/lutaml/model_transformations/parsers/qea_parser.rb +5 -7
  23. data/lib/lutaml/model_transformations/parsers/xmi_parser.rb +3 -8
  24. data/lib/lutaml/model_transformations/transformation_engine.rb +1 -1
  25. data/lib/lutaml/qea/factory/document_builder.rb +3 -3
  26. data/lib/lutaml/qea/factory/ea_to_uml_factory.rb +2 -1
  27. data/lib/lutaml/qea/lookup_indexes.rb +2 -2
  28. data/lib/lutaml/qea/models/base_model.rb +1 -1
  29. data/lib/lutaml/qea/repositories/base_repository.rb +7 -7
  30. data/lib/lutaml/qea/validation/base_validator.rb +9 -4
  31. data/lib/lutaml/qea/validation/validation_engine.rb +1 -5
  32. data/lib/lutaml/qea/verification/document_normalizer.rb +11 -11
  33. data/lib/lutaml/qea/verification/element_comparator.rb +18 -47
  34. data/lib/lutaml/qea/verification/structure_matcher.rb +4 -4
  35. data/lib/lutaml/uml/association_generalization.rb +1 -0
  36. data/lib/lutaml/uml/class.rb +0 -1
  37. data/lib/lutaml/uml/classifier.rb +3 -0
  38. data/lib/lutaml/uml/data_type.rb +0 -1
  39. data/lib/lutaml/uml/has_attributes.rb +1 -1
  40. data/lib/lutaml/uml/has_members.rb +1 -1
  41. data/lib/lutaml/uml/inheritance_walker.rb +4 -4
  42. data/lib/lutaml/uml/model_helpers.rb +5 -62
  43. data/lib/lutaml/uml/operation.rb +6 -0
  44. data/lib/lutaml/uml/operation_parameter.rb +17 -0
  45. data/lib/lutaml/uml/qualified_name.rb +4 -5
  46. data/lib/lutaml/uml/top_element_attribute.rb +4 -0
  47. data/lib/lutaml/uml/validation/document_structure_validator.rb +4 -4
  48. data/lib/lutaml/uml_repository/class_lookup_index.rb +1 -1
  49. data/lib/lutaml/uml_repository/exporters/json_exporter.rb +1 -1
  50. data/lib/lutaml/uml_repository/exporters/markdown/class_page_builder.rb +2 -2
  51. data/lib/lutaml/uml_repository/index_builder.rb +15 -15
  52. data/lib/lutaml/uml_repository/index_builders/association_index.rb +6 -6
  53. data/lib/lutaml/uml_repository/package_exporter.rb +3 -5
  54. data/lib/lutaml/uml_repository/package_loader.rb +3 -3
  55. data/lib/lutaml/uml_repository/presenters/association_presenter.rb +3 -7
  56. data/lib/lutaml/uml_repository/presenters/attribute_presenter.rb +6 -10
  57. data/lib/lutaml/uml_repository/presenters/class_presenter.rb +1 -1
  58. data/lib/lutaml/uml_repository/presenters/datatype_presenter.rb +12 -20
  59. data/lib/lutaml/uml_repository/presenters/diagram_presenter.rb +32 -61
  60. data/lib/lutaml/uml_repository/presenters/element_presenter.rb +4 -5
  61. data/lib/lutaml/uml_repository/presenters/enum_presenter.rb +7 -9
  62. data/lib/lutaml/uml_repository/presenters/package_presenter.rb +5 -2
  63. data/lib/lutaml/uml_repository/queries/association_query.rb +2 -2
  64. data/lib/lutaml/uml_repository/queries/diagram_query.rb +1 -1
  65. data/lib/lutaml/uml_repository/queries/inheritance_query.rb +9 -13
  66. data/lib/lutaml/uml_repository/queries/package_query.rb +4 -10
  67. data/lib/lutaml/uml_repository/queries/search_query.rb +9 -9
  68. data/lib/lutaml/uml_repository/query_dsl/conditions/hash_condition.rb +2 -2
  69. data/lib/lutaml/uml_repository/query_dsl/conditions/package_condition.rb +2 -1
  70. data/lib/lutaml/uml_repository/query_dsl/order.rb +2 -2
  71. data/lib/lutaml/uml_repository/query_dsl/query_builder.rb +2 -2
  72. data/lib/lutaml/uml_repository/repository.rb +2 -2
  73. data/lib/lutaml/uml_repository/repository_enhanced.rb +1 -1
  74. data/lib/lutaml/uml_repository/static_site/association_serialization.rb +38 -86
  75. data/lib/lutaml/uml_repository/static_site/data_transformer.rb +13 -39
  76. data/lib/lutaml/uml_repository/static_site/models/spa_association.rb +32 -0
  77. data/lib/lutaml/uml_repository/static_site/models/spa_association_end.rb +28 -0
  78. data/lib/lutaml/uml_repository/static_site/models/spa_attribute.rb +42 -0
  79. data/lib/lutaml/uml_repository/static_site/models/spa_base.rb +12 -0
  80. data/lib/lutaml/uml_repository/static_site/models/spa_cardinality.rb +21 -0
  81. data/lib/lutaml/uml_repository/static_site/models/spa_class.rb +64 -0
  82. data/lib/lutaml/uml_repository/static_site/models/spa_diagram.rb +33 -0
  83. data/lib/lutaml/uml_repository/static_site/models/spa_document.rb +42 -0
  84. data/lib/lutaml/uml_repository/static_site/models/spa_inherited_association.rb +27 -0
  85. data/lib/lutaml/uml_repository/static_site/models/spa_inherited_attribute.rb +28 -0
  86. data/lib/lutaml/uml_repository/static_site/models/spa_literal.rb +21 -0
  87. data/lib/lutaml/uml_repository/static_site/models/spa_metadata.rb +26 -0
  88. data/lib/lutaml/uml_repository/static_site/models/spa_operation.rb +37 -0
  89. data/lib/lutaml/uml_repository/static_site/models/spa_package.rb +37 -0
  90. data/lib/lutaml/uml_repository/static_site/models/spa_package_tree_node.rb +35 -0
  91. data/lib/lutaml/uml_repository/static_site/models/spa_parameter.rb +23 -0
  92. data/lib/lutaml/uml_repository/static_site/models/spa_search_entry.rb +37 -0
  93. data/lib/lutaml/uml_repository/static_site/models/spa_statistics.rb +27 -0
  94. data/lib/lutaml/uml_repository/static_site/models/spa_tree_class_ref.rb +23 -0
  95. data/lib/lutaml/uml_repository/static_site/search_index_builder.rb +46 -131
  96. data/lib/lutaml/uml_repository/static_site/serializers/attribute_serializer.rb +11 -11
  97. data/lib/lutaml/uml_repository/static_site/serializers/class_serializer.rb +17 -16
  98. data/lib/lutaml/uml_repository/static_site/serializers/diagram_serializer.rb +8 -12
  99. data/lib/lutaml/uml_repository/static_site/serializers/inheritance_resolver.rb +44 -51
  100. data/lib/lutaml/uml_repository/static_site/serializers/metadata_builder.rb +8 -5
  101. data/lib/lutaml/uml_repository/static_site/serializers/operation_serializer.rb +14 -11
  102. data/lib/lutaml/uml_repository/static_site/serializers/package_serializer.rb +15 -17
  103. data/lib/lutaml/uml_repository/static_site/serializers/package_tree_builder.rb +19 -31
  104. data/lib/lutaml/uml_repository/statistics_calculator.rb +2 -4
  105. data/lib/lutaml/uml_repository/validators/repository_validator.rb +9 -9
  106. data/lib/lutaml/version.rb +1 -1
  107. data/lib/lutaml/xmi/parsers/xmi_base.rb +4 -4
  108. data/lib/lutaml/xmi/parsers/xmi_connector.rb +7 -7
  109. metadata +22 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c86294799b84e5b722bd271cba3e8f8bb47b5ca2b25a8e8a1fdfac763cc7ac42
4
- data.tar.gz: c32950a48ea9681d0091b16f5df20e99c64c107703677467709a28353630cc92
3
+ metadata.gz: 60815cadb4a74fcb9fcdc3b84a3f6c19b450e5a6f1670d918ffd4d2e66d4a3a5
4
+ data.tar.gz: 2e24af4ab233104a171c7cac58a7416e79e5248ce61831d45ba930e44d14685b
5
5
  SHA512:
6
- metadata.gz: 46ac28ea247ea946d5fa18d93824698d7b10756abb75b28992e148d22ea0e9c97e00a48b54eaa6929b1240a7732cca7edc60914edb243cbccb311de589611422
7
- data.tar.gz: 83e71c5fd9dd4237743ca89894edbc6ecbad02d67d47f115d24e20f085531322b6e94cdcbede356665c35c2e6fec4ae81facafc1de689fa934ad1f1db06685eb
6
+ metadata.gz: 4ebc0be5174ba5dafb1fbda8aa962936d9c8de3b3d909d66844a83f35cf0f353c8131af4d45f945cdd1e9bfdf4975a52b09bbe17a18cf09eae571cc5eb297a83
7
+ data.tar.gz: e41165b1694af4e86a4b2373643ec94d6bc6c0a84310c2573ba001ad5dbc278917ba796f9e2a95174fdd1b12607fb68b4fbd487f46032b2a92b8850ff301d3ae
data/.rubocop_todo.yml CHANGED
@@ -1,12 +1,12 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-08 06:29:20 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: 172
9
+ # Offense count: 154
10
10
  # This cop supports safe autocorrection (--autocorrect).
11
11
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
12
12
  # URISchemes: http, https
@@ -88,17 +88,17 @@ Metrics/AbcSize:
88
88
  Metrics/BlockLength:
89
89
  Max: 53
90
90
 
91
- # Offense count: 37
91
+ # Offense count: 35
92
92
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
93
93
  Metrics/CyclomaticComplexity:
94
94
  Enabled: false
95
95
 
96
- # Offense count: 68
96
+ # Offense count: 74
97
97
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
98
98
  Metrics/MethodLength:
99
99
  Max: 62
100
100
 
101
- # Offense count: 29
101
+ # Offense count: 26
102
102
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
103
103
  Metrics/PerceivedComplexity:
104
104
  Enabled: false
@@ -168,7 +168,7 @@ RSpec/ContextWording:
168
168
  RSpec/DescribeClass:
169
169
  Enabled: false
170
170
 
171
- # Offense count: 654
171
+ # Offense count: 652
172
172
  # Configuration parameters: CountAsOne.
173
173
  RSpec/ExampleLength:
174
174
  Max: 30
@@ -222,16 +222,16 @@ RSpec/MessageSpies:
222
222
  - 'spec/lutaml/uml_repository/presenters/diagram_presenter_spec.rb'
223
223
  - 'spec/lutaml/uml_repository/repository_spec.rb'
224
224
 
225
- # Offense count: 38
225
+ # Offense count: 39
226
226
  RSpec/MultipleExpectations:
227
- Max: 6
227
+ Max: 7
228
228
 
229
- # Offense count: 151
229
+ # Offense count: 149
230
230
  # Configuration parameters: AllowSubject.
231
231
  RSpec/MultipleMemoizedHelpers:
232
232
  Max: 11
233
233
 
234
- # Offense count: 35
234
+ # Offense count: 33
235
235
  # Configuration parameters: AllowedGroups.
236
236
  RSpec/NestedGroups:
237
237
  Max: 4
@@ -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
@@ -14,7 +14,7 @@ module Lutaml
14
14
  def current_path = shell.current_path
15
15
 
16
16
  def current_path=(path)
17
- shell.instance_variable_set(:@current_path, path)
17
+ shell.current_path = path
18
18
  end
19
19
 
20
20
  def config = shell.config
@@ -22,7 +22,7 @@ module Lutaml
22
22
  def last_results = shell.last_results
23
23
 
24
24
  def last_results=(results)
25
- shell.instance_variable_set(:@last_results, results)
25
+ shell.last_results = results
26
26
  end
27
27
 
28
28
  def path_history = shell.path_history
@@ -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|
@@ -110,7 +110,7 @@ module Lutaml
110
110
  end
111
111
 
112
112
  def show_package(path)
113
- nav = shell.instance_variable_get(:@navigation)
113
+ nav = shell.navigation
114
114
  path = nav.resolve_path(path)
115
115
  pkg = repository.find_package(path)
116
116
 
@@ -17,8 +17,11 @@ module Lutaml
17
17
  HISTORY_FILE = File.expand_path("~/.lutaml-xmi-history")
18
18
  MAX_HISTORY = 1000
19
19
 
20
- attr_reader :repository, :current_path, :config, :bookmarks,
21
- :last_results, :path_history
20
+ attr_reader :repository, :config, :bookmarks,
21
+ :path_history,
22
+ :navigation, :query, :bookmarks_cmd, :export, :help
23
+
24
+ attr_accessor :current_path, :last_results
22
25
 
23
26
  def initialize(lur_path_or_repo, config: nil)
24
27
  @config = {
@@ -83,25 +86,25 @@ module Lutaml
83
86
 
84
87
  COMMAND_DISPATCH = {
85
88
  # Navigation
86
- "cd" => :@navigation, "pwd" => :@navigation,
87
- "ls" => :@navigation, "list" => :@navigation,
88
- "tree" => :@navigation, "up" => :@navigation,
89
- "root" => :@navigation, "back" => :@navigation,
89
+ "cd" => :navigation, "pwd" => :navigation,
90
+ "ls" => :navigation, "list" => :navigation,
91
+ "tree" => :navigation, "up" => :navigation,
92
+ "root" => :navigation, "back" => :navigation,
90
93
  # Query
91
- "find" => :@query, "f" => :@query,
92
- "show" => :@query, "s" => :@query,
93
- "search" => :@query, "?" => :@query,
94
- "results" => :@query,
94
+ "find" => :query, "f" => :query,
95
+ "show" => :query, "s" => :query,
96
+ "search" => :query, "?" => :query,
97
+ "results" => :query,
95
98
  # Bookmarks
96
- "bookmark" => :@bookmarks_cmd, "bm" => :@bookmarks_cmd,
99
+ "bookmark" => :bookmarks_cmd, "bm" => :bookmarks_cmd,
97
100
  # Export
98
- "export" => :@export,
101
+ "export" => :export,
99
102
  # Utilities
100
- "help" => :@help, "h" => :@help,
101
- "history" => :@help,
102
- "clear" => :@help, "cls" => :@help,
103
- "config" => :@help,
104
- "stats" => :@help
103
+ "help" => :help, "h" => :help,
104
+ "history" => :help,
105
+ "clear" => :help, "cls" => :help,
106
+ "config" => :help,
107
+ "stats" => :help
105
108
  }.freeze
106
109
 
107
110
  METHOD_MAP = {
@@ -136,7 +139,7 @@ module Lutaml
136
139
  method_name = METHOD_MAP[command]
137
140
 
138
141
  if handler_var && method_name
139
- instance_variable_get(handler_var).send(method_name, args)
142
+ public_send(handler_var).public_send(method_name, args)
140
143
  else
141
144
  puts OutputFormatter.warning("Unknown command: #{command}")
142
145
  puts "Type 'help' for available commands"
@@ -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
@@ -10,7 +10,7 @@ module Lutaml
10
10
  #
11
11
  # @example Get configuration for a type
12
12
  # config = ResourceRegistry.config_for(:class)
13
- # classes = repository.send(config[:list_method])
13
+ # classes = repository.public_send(config[:list_method])
14
14
  #
15
15
  # @example List all available types
16
16
  # ResourceRegistry.types # => [:package, :class, :diagram, ...]
@@ -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
@@ -66,7 +66,7 @@ module Lutaml
66
66
  config = ResourceRegistry.config_for(identifier.type)
67
67
  return nil unless config
68
68
 
69
- repo.send(config[:find_method], identifier.path)
69
+ repo.public_send(config[:find_method], identifier.path)
70
70
  end
71
71
 
72
72
  def display_element_details(element, identifier, repo)
@@ -101,14 +101,14 @@ module Lutaml
101
101
  .split("\n").map(&:strip).join("\n")
102
102
  end
103
103
 
104
- if model.respond_to?("#{key}=")
105
- if model.class.attributes[key.to_sym].options[:collection]
106
- values = model.send(key.to_sym).to_a
107
- values << value
108
- model.send("#{key}=", values)
109
- else
110
- model.send("#{key}=", value)
111
- end
104
+ next unless model.class.attributes.key?(key.to_sym)
105
+
106
+ if model.class.attributes[key.to_sym].options[:collection]
107
+ values = model.public_send(key.to_sym).to_a
108
+ values << value
109
+ model.public_send("#{key}=", values)
110
+ else
111
+ model.public_send("#{key}=", value)
112
112
  end
113
113
  end
114
114
  end
@@ -271,7 +271,7 @@ module Lutaml
271
271
  uml_type = operation.uml_type.first
272
272
  uml_type_idref = uml_type.idref if uml_type
273
273
 
274
- if !operation.respond_to?(:association) || operation.association.nil?
274
+ if !operation.class.attributes.key?(:association) || operation.association.nil?
275
275
  ::Lutaml::Uml::Operation.new.tap do |op|
276
276
  op.id = operation.id
277
277
  op.xmi_id = uml_type_idref
@@ -289,7 +289,7 @@ module Lutaml
289
289
  # In ea-xmi-2.5.1, constraints are moved to source/target under
290
290
  # connectors
291
291
  constraints = %i[source target].map do |st|
292
- connector_node.send(st).constraints.constraint
292
+ connector_node.public_send(st).constraints.constraint
293
293
  end.flatten
294
294
 
295
295
  constraints.map do |constraint|
@@ -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}")
@@ -139,6 +139,21 @@ module Lutaml
139
139
  base_style
140
140
  end
141
141
 
142
+ # Convert EA color integer to hex color
143
+ # (EA stores colors as BGR integers)
144
+ # @param ea_color [Integer] EA color value
145
+ # @return [String] Hex color string
146
+ def color_from_ea_color(ea_color)
147
+ return EA_COLORS[:class_fill] if ea_color.zero?
148
+
149
+ # EA colors are stored as BGR, convert to RGB
150
+ b = (ea_color & 0xFF0000) >> 16
151
+ g = (ea_color & 0x00FF00) >> 8
152
+ r = ea_color & 0x0000FF
153
+
154
+ format("#%02x%02x%02x", r, g, b).upcase # rubocop:disable Style/FormatStringToken
155
+ end
156
+
142
157
  private
143
158
 
144
159
  def get_base_element_style(element_type) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
@@ -277,21 +292,6 @@ module Lutaml
277
292
  style
278
293
  end
279
294
 
280
- # Convert EA color integer to hex color
281
- # (EA stores colors as BGR integers)
282
- # @param ea_color [Integer] EA color value
283
- # @return [String] Hex color string
284
- def color_from_ea_color(ea_color)
285
- return EA_COLORS[:class_fill] if ea_color.zero?
286
-
287
- # EA colors are stored as BGR, convert to RGB
288
- b = (ea_color & 0xFF0000) >> 16
289
- g = (ea_color & 0x00FF00) >> 8
290
- r = ea_color & 0x0000FF
291
-
292
- format("#%02x%02x%02x", r, g, b).upcase # rubocop:disable Style/FormatStringToken
293
- end
294
-
295
295
  # Get stereotype-specific styling
296
296
  # (EA has specific colors for stereotypes)
297
297
  # @param stereotype [String] Stereotype name
@@ -182,11 +182,12 @@ module Lutaml
182
182
  case key.strip
183
183
  when "BCol"
184
184
  # Background color (BGR integer)
185
- style[:fill] = style_parser.send(:color_from_ea_color, value.to_i)
185
+ style[:fill] =
186
+ style_parser.color_from_ea_color(value.to_i)
186
187
  when "LCol"
187
188
  # Line color (BGR integer)
188
189
  style[:stroke] =
189
- style_parser.send(:color_from_ea_color, value.to_i)
190
+ style_parser.color_from_ea_color(value.to_i)
190
191
  when "BFol"
191
192
  # Bold font (0 or 1)
192
193
  style[:font_weight] = value == "1" ? 700 : 400
@@ -220,7 +221,7 @@ module Lutaml
220
221
  when "LCol"
221
222
  # Line color
222
223
  style[:stroke] =
223
- style_parser.send(:color_from_ea_color, value.to_i)
224
+ style_parser.color_from_ea_color(value.to_i)
224
225
  when "LWth"
225
226
  # Line width
226
227
  style[:stroke_width] = value.to_i
@@ -263,23 +264,15 @@ module Lutaml
263
264
  #
264
265
  # @param connector [Object] Association connector
265
266
  # @return [String] Specific association type
266
- def determine_association_type(connector) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
267
- return "association" unless connector.respond_to?(:member_end)
268
- return "association" unless connector.member_end
269
-
270
- # Ensure member_end is an array (handle legacy data
271
- # where it might be a string)
272
- member_ends = Array(connector.member_end)
273
-
274
- # Check for aggregation or composition
275
- member_ends.each do |end_point|
276
- if end_point.respond_to?(:aggregation)
277
- case end_point.aggregation&.downcase
278
- when "shared"
279
- return "aggregation"
280
- when "composite"
281
- return "composition"
282
- 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"
283
276
  end
284
277
  end
285
278
 
@@ -237,7 +237,7 @@ module Lutaml
237
237
  HEREDOC
238
238
 
239
239
  field_table = format_member_rows(node.attributes, hide_members)
240
- method_table = if node.respond_to?(:operations)
240
+ method_table = if node.operations&.any?
241
241
  format_member_rows(node.operations, hide_members)
242
242
  end
243
243
  table_body = [name_html, field_table, method_table].map do |type|