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
@@ -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
@@ -301,12 +301,10 @@ module Lutaml
301
301
  }
302
302
 
303
303
  # Store metadata using various approaches
304
- if document.respond_to?(:parsing_metadata=)
304
+ if document.class.method_defined?(:parsing_metadata=)
305
305
  document.parsing_metadata = metadata
306
- elsif document.respond_to?(:metadata=)
306
+ elsif document.class.method_defined?(:metadata=)
307
307
  document.metadata = metadata
308
- else
309
- document.instance_variable_set(:@qea_metadata, metadata)
310
308
  end
311
309
  end
312
310
 
@@ -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
 
@@ -165,13 +165,8 @@ module Lutaml
165
165
  options: @options,
166
166
  }
167
167
 
168
- # Store metadata if document supports it
169
- if document.respond_to?(:parsing_metadata=)
168
+ if document.class.method_defined?(:parsing_metadata=)
170
169
  document.parsing_metadata = metadata
171
- elsif document.respond_to?(:instance_variable_set)
172
- # Store in custom attribute if available
173
- document.instance_variable_set(:@parsing_metadata,
174
- metadata)
175
170
  end
176
171
  end
177
172
 
@@ -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 " \
@@ -238,7 +238,7 @@ module Lutaml
238
238
  # @param valid_ids [Set<String>] Set of valid xmi_ids
239
239
  # @return [Boolean] True if valid or nil
240
240
  def check_association_end_valid?(assoc, attr, valid_ids)
241
- value = assoc.send(attr)
241
+ value = assoc.public_send(attr)
242
242
  return true if value.nil?
243
243
 
244
244
  valid_ids.include?(value)
@@ -250,14 +250,14 @@ module Lutaml
250
250
  # @param valid_ids [Set<String>] Set of valid xmi_ids
251
251
  # @param warnings [Array<String>] Warning accumulator
252
252
  def add_invalid_end_warning(assoc, attr, valid_ids, warnings) # rubocop:disable Metrics/MethodLength
253
- value = assoc.send(attr)
253
+ value = assoc.public_send(attr)
254
254
  return if value.nil?
255
255
 
256
256
  unless valid_ids.include?(value)
257
257
  # Get the corresponding name attribute for better error messages
258
258
  name_attr = attr.to_s.gsub("_xmi_id", "").to_sym
259
259
  name_value = begin
260
- assoc.send(name_attr)
260
+ assoc.public_send(name_attr)
261
261
  rescue StandardError
262
262
  nil
263
263
  end
@@ -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
@@ -17,12 +17,12 @@ module Lutaml
17
17
  def build_group_index(collection, method, single: false)
18
18
  if single
19
19
  collection.each_with_object({}) do |item, hash|
20
- key = item.send(method)
20
+ key = item.public_send(method)
21
21
  hash[key] = item if key
22
22
  end
23
23
  else
24
24
  collection.each_with_object({}) do |item, hash|
25
- key = item.send(method)
25
+ key = item.public_send(method)
26
26
  (hash[key] ||= []) << item if key
27
27
  end
28
28
  end
@@ -25,7 +25,7 @@ module Lutaml
25
25
  # Returns the primary key value for this instance
26
26
  # @return [Object] the primary key value
27
27
  def primary_key
28
- send(self.class.primary_key_column)
28
+ public_send(self.class.primary_key_column)
29
29
  end
30
30
 
31
31
  # Create instance from database row hash
@@ -57,7 +57,7 @@ module Lutaml
57
57
  # @param id [Object] key value
58
58
  # @return [Object, nil] The record or nil if not found
59
59
  def find_by_key(key, id)
60
- @records.find { |record| record.send(key) == id }
60
+ @records.find { |record| record.public_send(key) == id }
61
61
  end
62
62
 
63
63
  # Filter records by conditions
@@ -79,7 +79,7 @@ module Lutaml
79
79
  elsif conditions.is_a?(Hash)
80
80
  @records.select do |record|
81
81
  conditions.all? do |attr, value|
82
- record.respond_to?(attr) && record.send(attr) == value
82
+ record.public_send(attr) == value
83
83
  end
84
84
  end
85
85
  else
@@ -150,8 +150,8 @@ module Lutaml
150
150
  # # => [{id: 1, name: "Test"}, {id: 2, name: "Other"}]
151
151
  def pluck(*attributes)
152
152
  @records.map do |record|
153
- attributes.each_with_object({}) do |attr, hash|
154
- hash[attr] = record.send(attr) if record.respond_to?(attr)
153
+ attributes.to_h do |attr|
154
+ [attr, record.public_send(attr)]
155
155
  end
156
156
  end
157
157
  end
@@ -165,7 +165,7 @@ module Lutaml
165
165
  # repository.group_by(:type)
166
166
  # # => {"Class" => [obj1, obj2], "Interface" => [obj3]}
167
167
  def group_by(attribute)
168
- @records.group_by { |record| record.send(attribute) }
168
+ @records.group_by { |record| record.public_send(attribute) }
169
169
  end
170
170
 
171
171
  # Sort records by an attribute
@@ -178,7 +178,7 @@ module Lutaml
178
178
  # repository.order_by(:name)
179
179
  # repository.order_by(:created_at, :desc)
180
180
  def order_by(attribute, order = :asc)
181
- sorted = @records.sort_by { |record| record.send(attribute) }
181
+ sorted = @records.sort_by { |record| record.public_send(attribute) }
182
182
  order == :desc ? sorted.reverse : sorted
183
183
  end
184
184
 
@@ -191,7 +191,7 @@ module Lutaml
191
191
  # repository.distinct(:type)
192
192
  # # => ["Class", "Interface", "Component"]
193
193
  def distinct(attribute)
194
- @records.map { |record| record.send(attribute) }.uniq
194
+ @records.map { |record| record.public_send(attribute) }.uniq
195
195
  end
196
196
 
197
197
  # Check if repository is empty
@@ -122,7 +122,9 @@ module Lutaml
122
122
  collection = get_collection_for_table(table)
123
123
  return false unless collection
124
124
 
125
- collection.any? { |record| record.send(id_column) == reference_id }
125
+ collection.any? do |record|
126
+ record.public_send(id_column) == reference_id
127
+ end
126
128
  end
127
129
 
128
130
  # Maps table names to their corresponding collections in Database
@@ -207,7 +209,10 @@ module Lutaml
207
209
  # @param value [Object] Value to check
208
210
  # @return [Boolean]
209
211
  def present?(value)
210
- !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
211
216
  end
212
217
 
213
218
  # Finds entity name from database
@@ -223,8 +228,8 @@ module Lutaml
223
228
  collection = get_collection_for_table(table)
224
229
  return nil unless collection
225
230
 
226
- record = collection.find { |r| r.send(id_column) == id }
227
- record&.send(name_column)
231
+ record = collection.find { |r| r.public_send(id_column) == id }
232
+ record&.public_send(name_column)
228
233
  end
229
234
 
230
235
  # Validates a collection of entities
@@ -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
 
@@ -52,25 +52,19 @@ module Lutaml
52
52
  end
53
53
 
54
54
  # Compare is_abstract
55
- if xmi_class.respond_to?(:is_abstract) &&
56
- qea_class.respond_to?(:is_abstract) &&
57
- xmi_class.is_abstract != qea_class.is_abstract
55
+ if xmi_class.is_abstract != qea_class.is_abstract
58
56
  differences << "is_abstract: #{xmi_class.is_abstract} " \
59
57
  "vs #{qea_class.is_abstract}"
60
58
  end
61
59
 
62
60
  # Compare type
63
- if xmi_class.respond_to?(:type) &&
64
- qea_class.respond_to?(:type) &&
65
- normalize_value(xmi_class.type) != normalize_value(qea_class.type)
61
+ if normalize_value(xmi_class.type) != normalize_value(qea_class.type)
66
62
  differences << "type: '#{xmi_class.type}' vs '#{qea_class.type}'"
67
63
  end
68
64
 
69
65
  # Compare modifier
70
- if xmi_class.respond_to?(:modifier) &&
71
- qea_class.respond_to?(:modifier) &&
72
- normalize_value(xmi_class.modifier) !=
73
- normalize_value(qea_class.modifier)
66
+ if normalize_value(xmi_class.modifier) !=
67
+ normalize_value(qea_class.modifier)
74
68
  differences << "modifier: '#{xmi_class.modifier}' " \
75
69
  "vs '#{qea_class.modifier}'"
76
70
  end
@@ -105,27 +99,22 @@ module Lutaml
105
99
  end
106
100
 
107
101
  # Compare type
108
- if xmi_attr.respond_to?(:type) &&
109
- qea_attr.respond_to?(:type) &&
110
- normalize_value(xmi_attr.type) !=
111
- normalize_value(qea_attr.type)
102
+ if normalize_value(xmi_attr.type) !=
103
+ normalize_value(qea_attr.type)
112
104
  differences << "type: '#{xmi_attr.type}' vs '#{qea_attr.type}'"
113
105
  end
114
106
 
115
107
  # Compare visibility
116
- if xmi_attr.respond_to?(:visibility) &&
117
- qea_attr.respond_to?(:visibility) &&
118
- normalize_value(xmi_attr.visibility) !=
119
- normalize_value(qea_attr.visibility)
108
+ if normalize_value(xmi_attr.visibility) !=
109
+ normalize_value(qea_attr.visibility)
120
110
  differences << "visibility: '#{xmi_attr.visibility}' " \
121
111
  "vs '#{qea_attr.visibility}'"
122
112
  end
123
113
 
124
114
  # Compare cardinality if present
125
- if xmi_attr.respond_to?(:cardinality) &&
126
- qea_attr.respond_to?(:cardinality)
127
- xmi_card = xmi_attr.cardinality
128
- qea_card = qea_attr.cardinality
115
+ xmi_card = xmi_attr.cardinality
116
+ qea_card = qea_attr.cardinality
117
+ if xmi_card || qea_card
129
118
  if xmi_card && qea_card
130
119
  unless cardinalities_equal?(xmi_card, qea_card)
131
120
  differences << "cardinality: #{format_cardinality(xmi_card)} " \
@@ -157,19 +146,15 @@ module Lutaml
157
146
  end
158
147
 
159
148
  # Compare return type
160
- if xmi_op.respond_to?(:return_type) &&
161
- qea_op.respond_to?(:return_type) &&
162
- normalize_value(xmi_op.return_type) !=
163
- normalize_value(qea_op.return_type)
149
+ if normalize_value(xmi_op.return_type) !=
150
+ normalize_value(qea_op.return_type)
164
151
  differences << "return_type: '#{xmi_op.return_type}' " \
165
152
  "vs '#{qea_op.return_type}'"
166
153
  end
167
154
 
168
155
  # Compare visibility
169
- if xmi_op.respond_to?(:visibility) &&
170
- qea_op.respond_to?(:visibility) &&
171
- normalize_value(xmi_op.visibility) !=
172
- normalize_value(qea_op.visibility)
156
+ if normalize_value(xmi_op.visibility) !=
157
+ normalize_value(qea_op.visibility)
173
158
  differences << "visibility: '#{xmi_op.visibility}' " \
174
159
  "vs '#{qea_op.visibility}'"
175
160
  end
@@ -273,32 +258,18 @@ module Lutaml
273
258
  end
274
259
 
275
260
  # Check if cardinalities are equal
276
- def cardinalities_equal?(card1, card2) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
261
+ def cardinalities_equal?(card1, card2)
277
262
  return true if card1.nil? && card2.nil?
278
263
  return false if card1.nil? || card2.nil?
279
264
 
280
- min_equal = (
281
- card1.min || (card1.respond_to?(:min_value) && card1.min_value)
282
- ) == (
283
- card2.min || (card2.respond_to?(:min_value) && card2.min_value)
284
- )
285
- max_equal = (
286
- card1.max || (card1.respond_to?(:max_value) && card1.max_value)
287
- ) == (
288
- card2.max || (card2.respond_to?(:max_value) && card2.max_value)
289
- )
290
-
291
- min_equal && max_equal
265
+ card1.min == card2.min && card1.max == card2.max
292
266
  end
293
267
 
294
268
  # Format cardinality for display
295
269
  def format_cardinality(card)
296
270
  return "nil" if card.nil?
297
271
 
298
- min = card.min || (card.respond_to?(:min_value) && card.min_value)
299
- max = card.max || (card.respond_to?(:max_value) && card.max_value)
300
-
301
- "#{min}..#{max}"
272
+ "\#{card.min}..\#{card.max}"
302
273
  end
303
274
  end
304
275
  end
@@ -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})"
@@ -6,6 +6,7 @@ module Lutaml
6
6
  attribute :id, :string
7
7
  attribute :type, :string
8
8
  attribute :general, :string
9
+ attribute :parent_object_id, :string
9
10
 
10
11
  yaml do
11
12
  map "id", to: :id
@@ -13,7 +13,6 @@ module Lutaml
13
13
  class Class < Classifier
14
14
  attribute :nested_classifier, :string, collection: true,
15
15
  default: -> { [] }
16
- attribute :is_abstract, :boolean, default: false
17
16
  attribute :stereotype, :string, collection: true, default: -> { [] }
18
17
  attribute :type, :string
19
18
  attribute :attributes, TopElementAttribute, collection: true
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "top_element"
4
4
  require_relative "association_generalization"
5
+ require_relative "operation"
5
6
 
6
7
  module Lutaml
7
8
  module Uml
@@ -9,6 +10,8 @@ module Lutaml
9
10
  attribute :association_generalization,
10
11
  ::Lutaml::Uml::AssociationGeneralization,
11
12
  collection: true, default: -> { [] }
13
+ attribute :operations, Operation, collection: true, default: -> { [] }
14
+ attribute :is_abstract, :boolean, default: false
12
15
 
13
16
  yaml do
14
17
  map "generalization", to: :association_generalization
@@ -11,7 +11,6 @@ module Lutaml
11
11
  class DataType < Classifier
12
12
  attribute :nested_classifier, :string, collection: true,
13
13
  default: -> { [] }
14
- attribute :is_abstract, :boolean, default: false
15
14
  attribute :type, :string
16
15
  attribute :attributes, TopElementAttribute, collection: true
17
16
  attribute :modifier, :string
@@ -5,7 +5,7 @@ module Lutaml
5
5
  module HasAttributes
6
6
  def update_attributes(attributes = {})
7
7
  attributes.to_h.each do |name, value|
8
- value = value.str if value.respond_to?(:str)
8
+ value = value.str if value.is_a?(Parslet::Slice)
9
9
  public_send(:"#{name}=", value)
10
10
  end
11
11
  end
@@ -21,7 +21,7 @@ module Lutaml
21
21
  private
22
22
 
23
23
  def association_type(type)
24
- return type if respond_to?(:"#{type}=")
24
+ return type if self.class.attributes.key?(type.to_sym)
25
25
 
26
26
  raise(UnknownMemberTypeError, "Unknown member type: #{type}")
27
27
  end
@@ -31,7 +31,7 @@ module Lutaml
31
31
  # puts "#{' ' * (level - 1)}Parent #{level}: #{parent.name}"
32
32
  # end
33
33
  def walk(klass)
34
- return [] unless klass.respond_to?(:generalization) && klass.generalization
34
+ return [] unless klass.is_a?(Lutaml::Uml::Class) && klass.generalization
35
35
 
36
36
  ancestors = []
37
37
  @visited.clear
@@ -69,12 +69,12 @@ module Lutaml
69
69
  # Uses a trail set for cycle detection (avoids Set mutation issues across calls).
70
70
  def collect_ancestors(klass, result, trail = [])
71
71
  return [] if trail.include?(klass.xmi_id) # cycle guard
72
- return [] unless klass.respond_to?(:generalization) && klass.generalization
72
+ return [] unless klass.is_a?(Lutaml::Uml::Class) && klass.generalization
73
73
 
74
74
  trail = trail.dup
75
75
  trail << klass.xmi_id
76
76
 
77
- general_id = klass.generalization.respond_to?(:general_id) ? klass.generalization.general_id : nil
77
+ general_id = klass.generalization.general_id
78
78
  parent = general_id ? find_class_by_id(general_id) : nil
79
79
 
80
80
  return [] unless parent
@@ -85,7 +85,7 @@ module Lutaml
85
85
 
86
86
  def find_class_by_id(xmi_id)
87
87
  @repository.indexes&.dig(:qualified_names, xmi_id) ||
88
- @repository.send(:classes_index)&.find { |c| c.xmi_id == xmi_id }
88
+ @repository.classes_index&.find { |c| c.xmi_id == xmi_id }
89
89
  end
90
90
  end
91
91
  end