lutaml-model 0.8.9 → 0.8.10
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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +12 -32
- data/lib/lutaml/key_value/transform.rb +5 -5
- data/lib/lutaml/key_value/transformation/collection_serializer.rb +25 -11
- data/lib/lutaml/key_value/transformation/value_serializer.rb +7 -7
- data/lib/lutaml/key_value/transformation.rb +27 -17
- data/lib/lutaml/model/adapter_resolver.rb +4 -6
- data/lib/lutaml/model/attribute.rb +26 -23
- data/lib/lutaml/model/cached_type_resolver.rb +10 -9
- data/lib/lutaml/model/cli.rb +1 -1
- data/lib/lutaml/model/collection.rb +4 -4
- data/lib/lutaml/model/comparable_model.rb +11 -11
- data/lib/lutaml/model/config.rb +1 -1
- data/lib/lutaml/model/consolidation/dispatcher.rb +1 -1
- data/lib/lutaml/model/consolidation/pattern_chunker.rb +3 -3
- data/lib/lutaml/model/format_registry.rb +6 -4
- data/lib/lutaml/model/global_context.rb +2 -2
- data/lib/lutaml/model/global_register.rb +1 -1
- data/lib/lutaml/model/instrumentation.rb +1 -1
- data/lib/lutaml/model/mapping/mapping_rule.rb +3 -3
- data/lib/lutaml/model/mapping/model_mapping.rb +1 -1
- data/lib/lutaml/model/mapping/model_mapping_rule.rb +1 -1
- data/lib/lutaml/model/register.rb +3 -3
- data/lib/lutaml/model/render_policy.rb +11 -17
- data/lib/lutaml/model/runtime_compatibility.rb +0 -1
- data/lib/lutaml/model/schema/xml_compiler/group.rb +1 -1
- data/lib/lutaml/model/schema/xml_compiler/registry_generator.rb +1 -1
- data/lib/lutaml/model/schema/xml_compiler/sequence.rb +0 -2
- data/lib/lutaml/model/schema/xml_compiler.rb +14 -14
- data/lib/lutaml/model/serialize/attribute_definition.rb +1 -1
- data/lib/lutaml/model/serialize/deserialization_context.rb +50 -0
- data/lib/lutaml/model/serialize/format_conversion.rb +2 -2
- data/lib/lutaml/model/serialize/initialization.rb +44 -7
- data/lib/lutaml/model/serialize/model_import.rb +1 -1
- data/lib/lutaml/model/serialize.rb +8 -1
- data/lib/lutaml/model/services/rule_value_extractor.rb +2 -1
- data/lib/lutaml/model/store.rb +27 -21
- data/lib/lutaml/model/transformation_registry.rb +1 -1
- data/lib/lutaml/model/type_context.rb +7 -1
- data/lib/lutaml/model/type_resolver.rb +1 -6
- data/lib/lutaml/model/utils.rb +19 -6
- data/lib/lutaml/model/validation_framework.rb +1 -1
- data/lib/lutaml/model/value_transformer.rb +2 -2
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/xml/adapter/adapter_helpers.rb +1 -1
- data/lib/lutaml/xml/adapter/base_adapter.rb +10 -14
- data/lib/lutaml/xml/adapter/namespace_uri_collector.rb +3 -3
- data/lib/lutaml/xml/adapter/plan_based_builder.rb +14 -14
- data/lib/lutaml/xml/adapter/xml_serializer.rb +3 -3
- data/lib/lutaml/xml/configurable.rb +2 -1
- data/lib/lutaml/xml/data_model.rb +2 -2
- data/lib/lutaml/xml/decisions/decision_context.rb +3 -3
- data/lib/lutaml/xml/decisions/rules/element_form_default_unqualified_rule.rb +1 -1
- data/lib/lutaml/xml/decisions/rules/element_form_option_rule.rb +1 -1
- data/lib/lutaml/xml/decisions/rules/used_prefix_rule.rb +1 -1
- data/lib/lutaml/xml/declaration_plan.rb +2 -2
- data/lib/lutaml/xml/declaration_planner.rb +12 -13
- data/lib/lutaml/xml/document.rb +13 -13
- data/lib/lutaml/xml/format_chooser.rb +3 -3
- data/lib/lutaml/xml/hoisting_algorithm.rb +1 -1
- data/lib/lutaml/xml/mapping.rb +2 -2
- data/lib/lutaml/xml/mapping_rule.rb +16 -3
- data/lib/lutaml/xml/model_transform.rb +17 -19
- data/lib/lutaml/xml/namespace_collector.rb +10 -10
- data/lib/lutaml/xml/namespace_declaration.rb +2 -2
- data/lib/lutaml/xml/namespace_declaration_data.rb +5 -8
- data/lib/lutaml/xml/namespace_scope_config.rb +3 -2
- data/lib/lutaml/xml/namespace_type_resolver.rb +4 -4
- data/lib/lutaml/xml/nokogiri/element.rb +2 -2
- data/lib/lutaml/xml/polymorphic_value_handler.rb +1 -1
- data/lib/lutaml/xml/schema/xsd/base.rb +7 -7
- data/lib/lutaml/xml/schema/xsd/choice.rb +2 -2
- data/lib/lutaml/xml/schema/xsd/complex_type.rb +5 -5
- data/lib/lutaml/xml/schema/xsd/errors/message_builder.rb +3 -3
- data/lib/lutaml/xml/schema/xsd/group.rb +2 -2
- data/lib/lutaml/xml/schema/xsd/sequence.rb +2 -2
- data/lib/lutaml/xml/schema/xsd_schema.rb +5 -5
- data/lib/lutaml/xml/serialization/format_conversion.rb +4 -3
- data/lib/lutaml/xml/transformation/element_builder.rb +4 -2
- data/lib/lutaml/xml/transformation/rule_applier.rb +2 -2
- data/lib/lutaml/xml/transformation/value_serializer.rb +4 -6
- data/lib/lutaml/xml/transformation.rb +4 -4
- data/lib/lutaml/xml/type/configurable.rb +0 -4
- data/lib/lutaml/xml/xml_element.rb +21 -13
- data/lutaml-model.gemspec +1 -1
- data/spec/lutaml/model/cached_type_resolver_spec.rb +3 -3
- data/spec/lutaml/model/optimization_spec.rb +228 -0
- data/spec/lutaml/model/store_spec.rb +41 -0
- data/spec/lutaml/xml/data_model_spec.rb +10 -28
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b1dea5a70c106b45dafcf2950dda9a8a1c2d8f2d37a4d32ec9a610e461b97a91
|
|
4
|
+
data.tar.gz: ca6332ea17ae83c4473a5143d454f155006ad369759dab98c48a1ba825aa6d74
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01c6623cc80b904875abe68601be5f4b76f441a0b6d0a599325db9454152072c4548985b29e12656b79cffeb28a965ddbf2d3191c6dc617503d914324cee3d35
|
|
7
|
+
data.tar.gz: 38c58ea41a62c035f56ba5a6ae758ed45e861417d7b41dba4003418600f36a88b6ab1a6ab753bd3ff54c3c45a2ed25ac13a68c774c9f488e9785d3d5c44894c6
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-05-
|
|
3
|
+
# on 2026-05-18 04:34:59 UTC using RuboCop version 1.86.0.
|
|
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
|
|
@@ -11,28 +11,13 @@ Gemspec/RequiredRubyVersion:
|
|
|
11
11
|
Exclude:
|
|
12
12
|
- 'lutaml-model.gemspec'
|
|
13
13
|
|
|
14
|
-
# Offense count:
|
|
15
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
16
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
17
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
18
|
-
Layout/ArgumentAlignment:
|
|
19
|
-
Exclude:
|
|
20
|
-
- 'lib/lutaml/model/store.rb'
|
|
21
|
-
|
|
22
|
-
# Offense count: 2982
|
|
14
|
+
# Offense count: 3012
|
|
23
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
24
16
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
25
17
|
# URISchemes: http, https
|
|
26
18
|
Layout/LineLength:
|
|
27
19
|
Enabled: false
|
|
28
20
|
|
|
29
|
-
# Offense count: 1
|
|
30
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
31
|
-
# Configuration parameters: AllowInHeredoc.
|
|
32
|
-
Layout/TrailingWhitespace:
|
|
33
|
-
Exclude:
|
|
34
|
-
- 'lib/lutaml/model/store.rb'
|
|
35
|
-
|
|
36
21
|
# Offense count: 21
|
|
37
22
|
# Configuration parameters: AllowedMethods.
|
|
38
23
|
# AllowedMethods: enums
|
|
@@ -129,23 +114,23 @@ Lint/UselessConstantScoping:
|
|
|
129
114
|
Exclude:
|
|
130
115
|
- 'lib/lutaml/xml/mapping_rule.rb'
|
|
131
116
|
|
|
132
|
-
# Offense count:
|
|
117
|
+
# Offense count: 345
|
|
133
118
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
134
119
|
Metrics/AbcSize:
|
|
135
120
|
Enabled: false
|
|
136
121
|
|
|
137
|
-
# Offense count:
|
|
122
|
+
# Offense count: 40
|
|
138
123
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
139
124
|
# AllowedMethods: refine
|
|
140
125
|
Metrics/BlockLength:
|
|
141
|
-
Max:
|
|
126
|
+
Max: 133
|
|
142
127
|
|
|
143
128
|
# Offense count: 16
|
|
144
129
|
# Configuration parameters: CountBlocks, CountModifierForms.
|
|
145
130
|
Metrics/BlockNesting:
|
|
146
131
|
Max: 6
|
|
147
132
|
|
|
148
|
-
# Offense count:
|
|
133
|
+
# Offense count: 310
|
|
149
134
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
150
135
|
Metrics/CyclomaticComplexity:
|
|
151
136
|
Enabled: false
|
|
@@ -161,7 +146,7 @@ Metrics/ParameterLists:
|
|
|
161
146
|
Max: 24
|
|
162
147
|
MaxOptionalParameters: 5
|
|
163
148
|
|
|
164
|
-
# Offense count:
|
|
149
|
+
# Offense count: 262
|
|
165
150
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
166
151
|
Metrics/PerceivedComplexity:
|
|
167
152
|
Enabled: false
|
|
@@ -253,7 +238,7 @@ RSpec/BeforeAfterAll:
|
|
|
253
238
|
RSpec/ContextWording:
|
|
254
239
|
Enabled: false
|
|
255
240
|
|
|
256
|
-
# Offense count:
|
|
241
|
+
# Offense count: 96
|
|
257
242
|
# Configuration parameters: IgnoredMetadata.
|
|
258
243
|
RSpec/DescribeClass:
|
|
259
244
|
Enabled: false
|
|
@@ -264,7 +249,7 @@ RSpec/DescribeMethod:
|
|
|
264
249
|
- 'spec/lutaml/xml/schema/xsd/schema_helper_methods_spec.rb'
|
|
265
250
|
- 'spec/lutaml/xml/serializable_namespace_spec.rb'
|
|
266
251
|
|
|
267
|
-
# Offense count:
|
|
252
|
+
# Offense count: 1257
|
|
268
253
|
# Configuration parameters: CountAsOne.
|
|
269
254
|
RSpec/ExampleLength:
|
|
270
255
|
Max: 68
|
|
@@ -339,7 +324,7 @@ RSpec/MultipleDescribes:
|
|
|
339
324
|
- 'spec/lutaml/xml/namespace_resolution_strategy_spec.rb'
|
|
340
325
|
- 'spec/lutaml/xml/xml_space_type_spec.rb'
|
|
341
326
|
|
|
342
|
-
# Offense count:
|
|
327
|
+
# Offense count: 1490
|
|
343
328
|
RSpec/MultipleExpectations:
|
|
344
329
|
Max: 21
|
|
345
330
|
|
|
@@ -393,7 +378,7 @@ RSpec/RepeatedExampleGroupDescription:
|
|
|
393
378
|
RSpec/SpecFilePathFormat:
|
|
394
379
|
Enabled: false
|
|
395
380
|
|
|
396
|
-
# Offense count:
|
|
381
|
+
# Offense count: 33
|
|
397
382
|
# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
|
|
398
383
|
RSpec/VerifiedDoubles:
|
|
399
384
|
Exclude:
|
|
@@ -401,6 +386,7 @@ RSpec/VerifiedDoubles:
|
|
|
401
386
|
- 'spec/lutaml/key_value/transformation/rule_compiler_spec.rb'
|
|
402
387
|
- 'spec/lutaml/key_value/transformation/value_serializer_spec.rb'
|
|
403
388
|
- 'spec/lutaml/model/compiled_rule_spec.rb'
|
|
389
|
+
- 'spec/lutaml/model/optimization_spec.rb'
|
|
404
390
|
- 'spec/lutaml/model/schema/renderer_spec.rb'
|
|
405
391
|
- 'spec/lutaml/model/transformation_builder_spec.rb'
|
|
406
392
|
- 'spec/lutaml/model/transformation_spec.rb'
|
|
@@ -457,12 +443,6 @@ Style/MixinUsage:
|
|
|
457
443
|
- 'bench/bench_unitsml.rb'
|
|
458
444
|
- 'bench/bench_xmi.rb'
|
|
459
445
|
|
|
460
|
-
# Offense count: 1
|
|
461
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
462
|
-
Style/MultilineIfModifier:
|
|
463
|
-
Exclude:
|
|
464
|
-
- 'lib/lutaml/model/store.rb'
|
|
465
|
-
|
|
466
446
|
# Offense count: 12
|
|
467
447
|
# Configuration parameters: AllowedClasses.
|
|
468
448
|
Style/OneClassPerFile:
|
|
@@ -33,7 +33,7 @@ module Lutaml
|
|
|
33
33
|
|
|
34
34
|
# transformation_for returns nil for cyclic dependencies or :building sentinel
|
|
35
35
|
# Fall back to legacy approach in these cases
|
|
36
|
-
if transformation.
|
|
36
|
+
if transformation.is_a?(Lutaml::KeyValue::Transformation)
|
|
37
37
|
# Use new Transformation to get KeyValueElement
|
|
38
38
|
kv_element = transformation.transform(instance, options)
|
|
39
39
|
# Convert KeyValueElement to hash for backward compatibility with adapters
|
|
@@ -68,7 +68,7 @@ module Lutaml
|
|
|
68
68
|
|
|
69
69
|
def process_mapping_for_instance(instance, hash, format, rule, options)
|
|
70
70
|
if rule.custom_methods[:to]
|
|
71
|
-
return instance.
|
|
71
|
+
return instance.public_send(rule.custom_methods[:to], instance, hash)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
attribute = attributes[rule.to]
|
|
@@ -223,13 +223,13 @@ format)
|
|
|
223
223
|
value = extract_value_for_delegate(instance, rule)
|
|
224
224
|
return if value.nil? && rule.value_map(:to)[:nil] == :omitted
|
|
225
225
|
|
|
226
|
-
attribute = instance.
|
|
226
|
+
attribute = instance.public_send(rule.delegate).class.attributes(lutaml_register)[rule.to]
|
|
227
227
|
hash[rule_from_name(rule)] =
|
|
228
228
|
attribute.serialize(value, format, lutaml_register)
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
def extract_value_for_delegate(instance, rule)
|
|
232
|
-
instance.
|
|
232
|
+
instance.public_send(rule.delegate).public_send(rule.to)
|
|
233
233
|
end
|
|
234
234
|
|
|
235
235
|
def extract_mappings(options, format)
|
|
@@ -268,7 +268,7 @@ format)
|
|
|
268
268
|
def process_custom_method(rule, instance, value)
|
|
269
269
|
return unless Lutaml::Model::Utils.present?(value)
|
|
270
270
|
|
|
271
|
-
model_class.new.
|
|
271
|
+
model_class.new.public_send(rule.custom_methods[:from], instance, value)
|
|
272
272
|
end
|
|
273
273
|
|
|
274
274
|
def cast_value(value, attr, format, rule, instance)
|
|
@@ -175,10 +175,14 @@ options = {})
|
|
|
175
175
|
items.each do |item|
|
|
176
176
|
next if item.nil?
|
|
177
177
|
|
|
178
|
-
key_value = item.
|
|
178
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
179
|
+
item.public_send(key_attribute)
|
|
180
|
+
end
|
|
179
181
|
next if key_value.nil?
|
|
180
182
|
|
|
181
|
-
attr_value = item.
|
|
183
|
+
attr_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(value_attribute)
|
|
184
|
+
item.public_send(value_attribute)
|
|
185
|
+
end
|
|
182
186
|
next if attr_value.nil? || Lutaml::Model::Utils.uninitialized?(attr_value)
|
|
183
187
|
|
|
184
188
|
# Get the attribute definition for the value attribute
|
|
@@ -193,7 +197,7 @@ options = {})
|
|
|
193
197
|
item_mapping = item_class.mappings_for(format, register_id)
|
|
194
198
|
item_mapping&.mappings&.each do |mapping_rule|
|
|
195
199
|
if mapping_rule.to == value_attribute
|
|
196
|
-
child_mappings = mapping_rule.child_mappings
|
|
200
|
+
child_mappings = mapping_rule.child_mappings
|
|
197
201
|
break
|
|
198
202
|
end
|
|
199
203
|
end
|
|
@@ -226,7 +230,9 @@ options)
|
|
|
226
230
|
|
|
227
231
|
keyed_hash = {}
|
|
228
232
|
items.each do |item|
|
|
229
|
-
key_value = item.
|
|
233
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
234
|
+
item.public_send(key_attribute)
|
|
235
|
+
end
|
|
230
236
|
next if key_value.nil?
|
|
231
237
|
|
|
232
238
|
item_hash = {}
|
|
@@ -281,7 +287,9 @@ options)
|
|
|
281
287
|
items.each do |item|
|
|
282
288
|
next if item.nil?
|
|
283
289
|
|
|
284
|
-
key_value = item.
|
|
290
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
291
|
+
item.public_send(key_attribute)
|
|
292
|
+
end
|
|
285
293
|
next if key_value.nil?
|
|
286
294
|
|
|
287
295
|
item_hash = {}
|
|
@@ -340,7 +348,9 @@ options)
|
|
|
340
348
|
value_attribute = find_value_attribute(child_mappings)
|
|
341
349
|
|
|
342
350
|
items.each do |item|
|
|
343
|
-
key_value = item.
|
|
351
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
352
|
+
item.public_send(key_attribute)
|
|
353
|
+
end
|
|
344
354
|
next if key_value.nil?
|
|
345
355
|
|
|
346
356
|
if value_attribute
|
|
@@ -371,7 +381,9 @@ options)
|
|
|
371
381
|
# Serialize a keyed collection item with value mapping.
|
|
372
382
|
def serialize_keyed_value_item(keyed_hash, item, key_value,
|
|
373
383
|
value_attribute, options)
|
|
374
|
-
attr_value = item.
|
|
384
|
+
attr_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(value_attribute)
|
|
385
|
+
item.public_send(value_attribute)
|
|
386
|
+
end
|
|
375
387
|
return if attr_value.nil? || Lutaml::Model::Utils.uninitialized?(attr_value)
|
|
376
388
|
|
|
377
389
|
item_class = item.class
|
|
@@ -419,7 +431,9 @@ options)
|
|
|
419
431
|
child_mappings.each do |attr_name, path_spec|
|
|
420
432
|
next if %i[key value].include?(path_spec)
|
|
421
433
|
|
|
422
|
-
attr_value = item.
|
|
434
|
+
attr_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(attr_name)
|
|
435
|
+
item.public_send(attr_name)
|
|
436
|
+
end
|
|
423
437
|
next if attr_value.nil? || Lutaml::Model::Utils.uninitialized?(attr_value)
|
|
424
438
|
|
|
425
439
|
attr_def = nil
|
|
@@ -508,7 +522,7 @@ options)
|
|
|
508
522
|
serialize_collection_value(value, attr_type, options)
|
|
509
523
|
elsif attr_type.is_a?(Class) && attr_type < Lutaml::Model::Serialize
|
|
510
524
|
serialize_nested_model(value, attr_type, options)
|
|
511
|
-
elsif attr_type.
|
|
525
|
+
elsif attr_type.is_a?(Class) && attr_type < Lutaml::Model::Type::Value
|
|
512
526
|
serialize_primitive(value, attr_type)
|
|
513
527
|
else
|
|
514
528
|
value
|
|
@@ -523,7 +537,7 @@ options)
|
|
|
523
537
|
# Handle Reference type collections - serialize each as a key
|
|
524
538
|
if attr_type == Lutaml::Model::Type::Reference
|
|
525
539
|
return items.map do |item|
|
|
526
|
-
item.
|
|
540
|
+
item.is_a?(Lutaml::Model::Type::Value) ? item.public_send(:"to_#{format}") : item
|
|
527
541
|
end
|
|
528
542
|
end
|
|
529
543
|
|
|
@@ -547,7 +561,7 @@ options)
|
|
|
547
561
|
# Serialize a primitive value.
|
|
548
562
|
def serialize_primitive(value, attr_type)
|
|
549
563
|
wrapped_value = attr_type.new(value)
|
|
550
|
-
wrapped_value.
|
|
564
|
+
wrapped_value.public_send(:"to_#{format}")
|
|
551
565
|
end
|
|
552
566
|
|
|
553
567
|
# Create a transformation for a type class.
|
|
@@ -128,13 +128,13 @@ model_class: nil)
|
|
|
128
128
|
if rule.attribute_type.is_a?(Class) &&
|
|
129
129
|
rule.attribute_type < Lutaml::Model::Serialize
|
|
130
130
|
validate_serializable_type!(value, rule)
|
|
131
|
-
return value.
|
|
131
|
+
return value.public_send(:"to_#{format}")
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
# Wrap value in type and call to_#{format}
|
|
135
|
-
if rule.attribute_type.
|
|
135
|
+
if rule.attribute_type.is_a?(Class) && rule.attribute_type < Lutaml::Model::Type::Value
|
|
136
136
|
wrapped_value = rule.attribute_type.new(value)
|
|
137
|
-
wrapped_value.
|
|
137
|
+
wrapped_value.public_send(:"to_#{format}")
|
|
138
138
|
else
|
|
139
139
|
value
|
|
140
140
|
end
|
|
@@ -152,7 +152,7 @@ model_class: nil)
|
|
|
152
152
|
subs = context.substitution_for(rule.attribute_type)
|
|
153
153
|
uses_type_substitution = subs.any? { |s| s.to_type == value.class }
|
|
154
154
|
|
|
155
|
-
if rule.attribute_type.
|
|
155
|
+
if rule.attribute_type.is_a?(Class) && rule.attribute_type.include?(Lutaml::Model::Serialize) && rule.attribute_type.model
|
|
156
156
|
# Mapper class: value should be an instance of the mapped model
|
|
157
157
|
unless value.is_a?(rule.attribute_type.model) || uses_type_substitution
|
|
158
158
|
msg = "attribute '#{rule.attribute_name}' value is a '#{value.class}' " \
|
|
@@ -227,7 +227,7 @@ model_class: nil)
|
|
|
227
227
|
# @param rule [CompiledRule] The compiled rule
|
|
228
228
|
# @return [Boolean] true if Reference type
|
|
229
229
|
def reference_type?(rule)
|
|
230
|
-
return false unless rule.
|
|
230
|
+
return false unless rule.is_a?(Lutaml::Model::CompiledRule)
|
|
231
231
|
return false unless model_class
|
|
232
232
|
|
|
233
233
|
# Get the attribute from the model class to check unresolved_type
|
|
@@ -256,8 +256,8 @@ model_class: nil)
|
|
|
256
256
|
end
|
|
257
257
|
|
|
258
258
|
# Fallback: just call to_format on the value
|
|
259
|
-
if value.
|
|
260
|
-
value.
|
|
259
|
+
if value.is_a?(Lutaml::Model::Type::Value) || value.is_a?(Lutaml::Model::Serialize)
|
|
260
|
+
value.public_send(:"to_#{format}")
|
|
261
261
|
else
|
|
262
262
|
value
|
|
263
263
|
end
|
|
@@ -209,8 +209,8 @@ register = self.register)
|
|
|
209
209
|
# Handle custom serialization methods (e.g., with: { to: ... })
|
|
210
210
|
if rule.has_custom_methods? && rule.custom_methods[:to]
|
|
211
211
|
# Call custom method which directly modifies the parent element
|
|
212
|
-
return model_instance.
|
|
213
|
-
|
|
212
|
+
return model_instance.public_send(rule.custom_methods[:to],
|
|
213
|
+
model_instance, parent)
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
# Handle delegation - extract value from delegated object
|
|
@@ -357,11 +357,15 @@ converted_from_empty_to_nil: false, converted_from_nil_to_empty: false)
|
|
|
357
357
|
next if item.nil?
|
|
358
358
|
|
|
359
359
|
# Get the key value from the item
|
|
360
|
-
key_value = item.
|
|
360
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
361
|
+
item.public_send(key_attribute)
|
|
362
|
+
end
|
|
361
363
|
next if key_value.nil?
|
|
362
364
|
|
|
363
365
|
# Get the value from the item
|
|
364
|
-
attr_value = item.
|
|
366
|
+
attr_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(value_attribute)
|
|
367
|
+
item.public_send(value_attribute)
|
|
368
|
+
end
|
|
365
369
|
next if attr_value.nil? || Lutaml::Model::Utils.uninitialized?(attr_value)
|
|
366
370
|
|
|
367
371
|
# For the value, we need to transform it appropriately
|
|
@@ -419,7 +423,7 @@ converted_from_empty_to_nil: false, converted_from_nil_to_empty: false)
|
|
|
419
423
|
item_class_mapping, format, register)
|
|
420
424
|
|
|
421
425
|
# Find the rule for the value_attribute in the item's class mapping
|
|
422
|
-
item_rule = item_class_transformation.
|
|
426
|
+
item_rule = item_class_transformation.compiled_rules.find do |r|
|
|
423
427
|
r.attribute_name == value_attribute
|
|
424
428
|
end
|
|
425
429
|
|
|
@@ -460,8 +464,9 @@ converted_from_empty_to_nil: false, converted_from_nil_to_empty: false)
|
|
|
460
464
|
items.each do |item|
|
|
461
465
|
next if item.nil?
|
|
462
466
|
|
|
463
|
-
|
|
464
|
-
|
|
467
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
468
|
+
item.public_send(key_attribute)
|
|
469
|
+
end
|
|
465
470
|
next if key_value.nil?
|
|
466
471
|
|
|
467
472
|
# Serialize all attributes except the key
|
|
@@ -573,7 +578,9 @@ child_mappings, options)
|
|
|
573
578
|
|
|
574
579
|
items.each do |item|
|
|
575
580
|
# Get the key value from the item
|
|
576
|
-
key_value = item.
|
|
581
|
+
key_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(key_attribute)
|
|
582
|
+
item.public_send(key_attribute)
|
|
583
|
+
end
|
|
577
584
|
|
|
578
585
|
if ENV["DEBUG_KEYED_COLLECTION"]
|
|
579
586
|
puts " item: #{item.inspect}, key_value=#{key_value.inspect}"
|
|
@@ -583,7 +590,9 @@ child_mappings, options)
|
|
|
583
590
|
|
|
584
591
|
# If there's a value mapping, serialize just that attribute value
|
|
585
592
|
if value_attribute
|
|
586
|
-
attr_value = item.
|
|
593
|
+
attr_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(value_attribute)
|
|
594
|
+
item.public_send(value_attribute)
|
|
595
|
+
end
|
|
587
596
|
next if attr_value.nil? || Lutaml::Model::Utils.uninitialized?(attr_value)
|
|
588
597
|
|
|
589
598
|
# Get the attribute definition for proper serialization
|
|
@@ -637,7 +646,9 @@ child_mappings, options)
|
|
|
637
646
|
next if path_spec == :value
|
|
638
647
|
|
|
639
648
|
# Get the attribute value
|
|
640
|
-
attr_value = item.
|
|
649
|
+
attr_value = if item.is_a?(Lutaml::Model::Serialize) && item.class.attributes.key?(attr_name)
|
|
650
|
+
item.public_send(attr_name)
|
|
651
|
+
end
|
|
641
652
|
|
|
642
653
|
if ENV["DEBUG_KEYED_COLLECTION"]
|
|
643
654
|
puts " #{attr_name}: path_spec=#{path_spec.inspect}, attr_value=#{attr_value.inspect}"
|
|
@@ -833,10 +844,9 @@ child_mappings, options)
|
|
|
833
844
|
child_hash = child_root.to_hash
|
|
834
845
|
child_hash["__root__"]
|
|
835
846
|
# Use the transformation to serialize the nested model
|
|
836
|
-
elsif attr_type.
|
|
837
|
-
# Serialize primitive value
|
|
847
|
+
elsif attr_type.is_a?(Class) && attr_type < Lutaml::Model::Type::Value
|
|
838
848
|
wrapped_value = attr_type.new(value)
|
|
839
|
-
wrapped_value.
|
|
849
|
+
wrapped_value.public_send(:"to_#{format}")
|
|
840
850
|
else
|
|
841
851
|
value
|
|
842
852
|
end
|
|
@@ -940,7 +950,7 @@ child_mappings, options)
|
|
|
940
950
|
subs = context.substitution_for(rule.attribute_type)
|
|
941
951
|
uses_type_substitution = subs.any? { |s| s.to_type == value.class }
|
|
942
952
|
|
|
943
|
-
if rule.attribute_type.
|
|
953
|
+
if rule.attribute_type.is_a?(Class) && rule.attribute_type.include?(Lutaml::Model::Serialize) && rule.attribute_type.model
|
|
944
954
|
# Mapper class: value should be an instance of the mapped model
|
|
945
955
|
# or a valid substituted type
|
|
946
956
|
unless value.is_a?(rule.attribute_type.model) || uses_type_substitution
|
|
@@ -1054,14 +1064,14 @@ child_mappings, options)
|
|
|
1054
1064
|
end
|
|
1055
1065
|
|
|
1056
1066
|
# Value is a valid Serialize instance - serialize it using its own to_#{format} method
|
|
1057
|
-
return value.
|
|
1067
|
+
return value.public_send(:"to_#{format}")
|
|
1058
1068
|
end
|
|
1059
1069
|
|
|
1060
1070
|
# Wrap value in type and call to_#{format} instance method (like legacy Attribute#serialize_value)
|
|
1061
1071
|
# This allows custom type subclasses to override to_json, to_yaml, etc.
|
|
1062
|
-
if rule.attribute_type.
|
|
1072
|
+
if rule.attribute_type.is_a?(Class) && rule.attribute_type < Lutaml::Model::Type::Value
|
|
1063
1073
|
wrapped_value = rule.attribute_type.new(value)
|
|
1064
|
-
wrapped_value.
|
|
1074
|
+
wrapped_value.public_send(:"to_#{format}")
|
|
1065
1075
|
else
|
|
1066
1076
|
value
|
|
1067
1077
|
end
|
|
@@ -225,7 +225,7 @@ module Lutaml
|
|
|
225
225
|
# @param type [String] normalized type name
|
|
226
226
|
def load_adapter_file(adapter, type)
|
|
227
227
|
loader = FormatRegistry.adapter_loader_for(adapter.to_sym)
|
|
228
|
-
if loader
|
|
228
|
+
if loader
|
|
229
229
|
loader.load_adapter_file(adapter, type)
|
|
230
230
|
return
|
|
231
231
|
end
|
|
@@ -248,10 +248,8 @@ module Lutaml
|
|
|
248
248
|
# @param format [Symbol] format name
|
|
249
249
|
def load_moxml_adapter(type_name, format)
|
|
250
250
|
loader = FormatRegistry.adapter_loader_for(format)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
format)
|
|
254
|
-
end
|
|
251
|
+
loader&.load_moxml_adapter(type_name,
|
|
252
|
+
format)
|
|
255
253
|
end
|
|
256
254
|
|
|
257
255
|
# Resolve the adapter class from the type name.
|
|
@@ -261,7 +259,7 @@ module Lutaml
|
|
|
261
259
|
# @return [Class] the adapter class
|
|
262
260
|
def class_for(adapter, type)
|
|
263
261
|
loader = FormatRegistry.adapter_loader_for(adapter.to_sym)
|
|
264
|
-
if loader
|
|
262
|
+
if loader
|
|
265
263
|
return loader.class_for(adapter, type)
|
|
266
264
|
end
|
|
267
265
|
|
|
@@ -36,20 +36,8 @@ module Lutaml
|
|
|
36
36
|
:string,
|
|
37
37
|
].freeze
|
|
38
38
|
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
# intentionally excluded — children must derive their own context.
|
|
42
|
-
CHILD_PROPAGATION_KEYS = %i[
|
|
43
|
-
lutaml_parent
|
|
44
|
-
lutaml_root
|
|
45
|
-
default_namespace
|
|
46
|
-
import_declaration_plan
|
|
47
|
-
polymorphic
|
|
48
|
-
collection
|
|
49
|
-
render_empty
|
|
50
|
-
render_nil
|
|
51
|
-
cdata
|
|
52
|
-
].freeze
|
|
39
|
+
# Delegate propagation to DeserializationContext for single source of truth.
|
|
40
|
+
CHILD_PROPAGATION_KEYS = Serialize::DeserializationContext::PROPAGATION_KEYS
|
|
53
41
|
|
|
54
42
|
# Methods where accidental override is likely to cause issues
|
|
55
43
|
# All names are allowed - this list only controls which ones get a warning
|
|
@@ -590,9 +578,10 @@ instance_object = nil)
|
|
|
590
578
|
type(register)
|
|
591
579
|
end
|
|
592
580
|
if collection_instance?(value) || value.is_a?(Array)
|
|
581
|
+
merged_opts = options.merge(resolved_type: resolved_type,
|
|
582
|
+
converted: true)
|
|
593
583
|
return build_collection(value.map do |v|
|
|
594
|
-
cast(v, format, register,
|
|
595
|
-
options.merge(resolved_type: resolved_type, converted: true))
|
|
584
|
+
cast(v, format, register, merged_opts)
|
|
596
585
|
end)
|
|
597
586
|
end
|
|
598
587
|
|
|
@@ -616,11 +605,11 @@ instance_object = nil)
|
|
|
616
605
|
|
|
617
606
|
klass = resolve_polymorphic_class(resolved_type, value, options)
|
|
618
607
|
if can_serialize?(klass, value, format, options)
|
|
619
|
-
propagated =
|
|
608
|
+
propagated = Serialize::DeserializationContext.propagate(options)
|
|
620
609
|
klass.apply_mappings(value, format,
|
|
621
610
|
propagated.merge(register: register))
|
|
622
611
|
elsif needs_conversion?(klass, value)
|
|
623
|
-
klass.
|
|
612
|
+
klass.public_send(:"from_#{format}", value)
|
|
624
613
|
else
|
|
625
614
|
# No need to use register#get_class,
|
|
626
615
|
# can_serialize? method already checks if type is Serializable or not.
|
|
@@ -711,9 +700,7 @@ instance_object = nil)
|
|
|
711
700
|
# Skip validation during deep_dup - options are already validated in original
|
|
712
701
|
# This prevents infinite recursion when process_options! tries to access collection
|
|
713
702
|
self.class.new(name, unresolved_type, duped_options).tap do |dup_attr|
|
|
714
|
-
|
|
715
|
-
dup_attr.send(:raw=, @raw)
|
|
716
|
-
dup_attr.send(:validations=, @validations)
|
|
703
|
+
dup_attr.copy_internal_state_from(self)
|
|
717
704
|
end
|
|
718
705
|
end
|
|
719
706
|
|
|
@@ -765,6 +752,22 @@ instance_object = nil)
|
|
|
765
752
|
type_namespace_class(register)&.prefix_default
|
|
766
753
|
end
|
|
767
754
|
|
|
755
|
+
# Copy internal state from another Attribute instance.
|
|
756
|
+
# Used by `dup` to transfer processed state without calling private writers.
|
|
757
|
+
def copy_internal_state_from(source)
|
|
758
|
+
@raw = source.raw?
|
|
759
|
+
@validations = source.validations
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
# Clear type resolution caches for this attribute.
|
|
763
|
+
# Called by GlobalContext.clear_caches to ensure stale entries
|
|
764
|
+
# from GC'd TypeContext objects don't persist.
|
|
765
|
+
def clear_type_cache
|
|
766
|
+
@type_cache&.clear
|
|
767
|
+
@cached_type_default = nil
|
|
768
|
+
@default_type_context = nil
|
|
769
|
+
end
|
|
770
|
+
|
|
768
771
|
private
|
|
769
772
|
|
|
770
773
|
attr_writer :raw, :validations
|
|
@@ -852,7 +855,7 @@ instance_object = nil)
|
|
|
852
855
|
register
|
|
853
856
|
end
|
|
854
857
|
|
|
855
|
-
as_options =
|
|
858
|
+
as_options = Serialize::DeserializationContext.propagate(options).merge(register: value_register)
|
|
856
859
|
|
|
857
860
|
# Respect mapping layer policy: render_empty from MappingRule
|
|
858
861
|
# Allow empty Serializable models when render_empty: true
|
|
@@ -874,7 +877,7 @@ instance_object = nil)
|
|
|
874
877
|
|
|
875
878
|
def serialize_value(value, format, resolved_type)
|
|
876
879
|
value = wrap_in_type_if_needed(value, resolved_type)
|
|
877
|
-
value.
|
|
880
|
+
value.public_send(:"to_#{format}")
|
|
878
881
|
end
|
|
879
882
|
|
|
880
883
|
def wrap_in_type_if_needed(value, resolved_type)
|
|
@@ -63,10 +63,11 @@ module Lutaml
|
|
|
63
63
|
# @return [Class] The resolved type class
|
|
64
64
|
# @raise [UnknownTypeError] If type cannot be resolved
|
|
65
65
|
def resolve(name, context)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
cache_key = if name.is_a?(Class)
|
|
67
|
+
[context.id, name]
|
|
68
|
+
else
|
|
69
|
+
build_cache_key(name, context)
|
|
70
|
+
end
|
|
70
71
|
|
|
71
72
|
@cache_backend.fetch_or_store(cache_key) do
|
|
72
73
|
@delegate.resolve(name, context)
|
|
@@ -79,14 +80,14 @@ module Lutaml
|
|
|
79
80
|
# @param context [TypeContext] The resolution context
|
|
80
81
|
# @return [Boolean] true if type can be resolved
|
|
81
82
|
def resolvable?(name, context)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
cache_key = if name.is_a?(Class)
|
|
84
|
+
[context.id, name]
|
|
85
|
+
else
|
|
86
|
+
build_cache_key(name, context)
|
|
87
|
+
end
|
|
85
88
|
|
|
86
|
-
# Check cache first (fast path)
|
|
87
89
|
return true if @cache_backend.key?(cache_key)
|
|
88
90
|
|
|
89
|
-
# Not in cache - delegate
|
|
90
91
|
@delegate.resolvable?(name, context)
|
|
91
92
|
end
|
|
92
93
|
|
data/lib/lutaml/model/cli.rb
CHANGED
|
@@ -70,7 +70,7 @@ module Lutaml
|
|
|
70
70
|
format = path.split(".").last.downcase
|
|
71
71
|
format = "yaml" if format == "yml"
|
|
72
72
|
|
|
73
|
-
model.
|
|
73
|
+
model.public_send("from_#{format}", content)
|
|
74
74
|
rescue StandardError => e
|
|
75
75
|
raise StandardError, "Error parsing file #{path}: #{e.message}"
|
|
76
76
|
end
|