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
|
@@ -79,7 +79,7 @@ module Lutaml
|
|
|
79
79
|
klass = ::Lutaml::Model::Config.mappings_class_for(format)
|
|
80
80
|
@mappings[format] ||= klass.new
|
|
81
81
|
mapping = @mappings[format]
|
|
82
|
-
if mapping.
|
|
82
|
+
if mapping.is_a?(Mapping)
|
|
83
83
|
mapping.import_model_mappings(model,
|
|
84
84
|
register_id)
|
|
85
85
|
end
|
|
@@ -6,6 +6,8 @@ module Lutaml
|
|
|
6
6
|
# Autoload subdirectory modules
|
|
7
7
|
autoload :Initialization, "#{__dir__}/serialize/initialization"
|
|
8
8
|
autoload :AttributeDefinition, "#{__dir__}/serialize/attribute_definition"
|
|
9
|
+
autoload :DeserializationContext,
|
|
10
|
+
"#{__dir__}/serialize/deserialization_context"
|
|
9
11
|
autoload :EnumHandling, "#{__dir__}/serialize/enum_handling"
|
|
10
12
|
autoload :ModelImport, "#{__dir__}/serialize/model_import"
|
|
11
13
|
autoload :FormatConversion, "#{__dir__}/serialize/format_conversion"
|
|
@@ -161,6 +163,11 @@ module Lutaml
|
|
|
161
163
|
@using_default[attribute_name] = false
|
|
162
164
|
end
|
|
163
165
|
|
|
166
|
+
def values_set_for(attribute_names)
|
|
167
|
+
@using_default ||= ::Hash.new(true)
|
|
168
|
+
attribute_names.each { |name| @using_default[name] = false }
|
|
169
|
+
end
|
|
170
|
+
|
|
164
171
|
def using_default?(attribute_name)
|
|
165
172
|
# nil means "all attributes using default" — return true without allocation
|
|
166
173
|
return true if @using_default.nil?
|
|
@@ -259,7 +266,7 @@ module Lutaml
|
|
|
259
266
|
end
|
|
260
267
|
|
|
261
268
|
def register_in_reference_store
|
|
262
|
-
Lutaml::Model::Store.register(self)
|
|
269
|
+
Lutaml::Model::Store.register(self) if self.class.reference_resolvable?
|
|
263
270
|
end
|
|
264
271
|
|
|
265
272
|
private
|
|
@@ -36,7 +36,8 @@ instance_object)
|
|
|
36
36
|
# When name is nil but document is a hash-like object with a single key matching
|
|
37
37
|
# the attribute name, extract that value. This handles the case where
|
|
38
38
|
# map to: :content is used and the document is {"content": "value"}
|
|
39
|
-
# Note: doc may be
|
|
39
|
+
# Note: doc may be an Oj-generated Hash which is_a?(Hash) returns false for,
|
|
40
|
+
# so we use respond_to? for the hash-like protocol check.
|
|
40
41
|
if name.nil? && doc.respond_to?(:key?) && doc.respond_to?(:values) && doc.size == 1
|
|
41
42
|
attr_name = rule.to
|
|
42
43
|
if doc.key?(attr_name.to_s) || doc.key?(attr_name.to_sym)
|
data/lib/lutaml/model/store.rb
CHANGED
|
@@ -36,8 +36,8 @@ module Lutaml
|
|
|
36
36
|
|
|
37
37
|
def initialize
|
|
38
38
|
@store = ::Hash.new { |hash, key| hash[key] = [] }
|
|
39
|
-
#
|
|
40
|
-
#
|
|
39
|
+
# Nested index: { model_key => { reference_key => { value => WeakRef(object) } } }
|
|
40
|
+
# Grouped by model_key so register only iterates this class's own indices.
|
|
41
41
|
@index = {}
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -53,23 +53,17 @@ module Lutaml
|
|
|
53
53
|
|
|
54
54
|
def resolve(model_class, reference_key, reference_value)
|
|
55
55
|
model_key = model_class.to_s
|
|
56
|
-
|
|
56
|
+
model_indices = @index[model_key]
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
reference_key)
|
|
58
|
+
unless model_indices&.key?(reference_key)
|
|
59
|
+
model_indices = ensure_model_index(model_key)
|
|
60
|
+
build_index(model_indices, model_key, reference_key)
|
|
62
61
|
end
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
entry = @index[index_key][reference_value]
|
|
63
|
+
entry = model_indices[reference_key][reference_value]
|
|
66
64
|
return nil unless entry
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
entry.__getobj__ if entry.weakref_alive?
|
|
70
|
-
rescue WeakRef::RefError
|
|
71
|
-
nil
|
|
72
|
-
end
|
|
66
|
+
dereference(entry)
|
|
73
67
|
end
|
|
74
68
|
|
|
75
69
|
def clear
|
|
@@ -89,9 +83,13 @@ module Lutaml
|
|
|
89
83
|
|
|
90
84
|
private
|
|
91
85
|
|
|
86
|
+
def ensure_model_index(model_key)
|
|
87
|
+
@index[model_key] ||= {}
|
|
88
|
+
end
|
|
89
|
+
|
|
92
90
|
# Build index for a (model_class, reference_key) pair by scanning existing instances.
|
|
93
|
-
def
|
|
94
|
-
entries =
|
|
91
|
+
def build_index(model_indices, model_key, reference_key)
|
|
92
|
+
entries = model_indices[reference_key] = {}
|
|
95
93
|
@store[model_key]&.each do |ref|
|
|
96
94
|
obj = ref.__getobj__
|
|
97
95
|
value = obj.public_send(reference_key)
|
|
@@ -101,19 +99,27 @@ module Lutaml
|
|
|
101
99
|
end
|
|
102
100
|
end
|
|
103
101
|
|
|
104
|
-
# Update indices that already exist for this model class.
|
|
102
|
+
# Update indices that already exist for this model class only.
|
|
103
|
+
# O(K) where K = number of reference keys indexed for this class,
|
|
104
|
+
# not O(N×K) across all classes.
|
|
105
105
|
def update_existing_indices(object, model_key)
|
|
106
|
-
@index
|
|
107
|
-
|
|
106
|
+
model_indices = @index[model_key]
|
|
107
|
+
return unless model_indices
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
value = object.public_send(
|
|
109
|
+
model_indices.each do |reference_key, entries|
|
|
110
|
+
value = object.public_send(reference_key)
|
|
111
111
|
entries[value] = WeakRef.new(object) if value
|
|
112
112
|
rescue WeakRef::RefError
|
|
113
113
|
next
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
+
def dereference(entry)
|
|
118
|
+
entry.__getobj__ if entry.weakref_alive?
|
|
119
|
+
rescue WeakRef::RefError
|
|
120
|
+
nil
|
|
121
|
+
end
|
|
122
|
+
|
|
117
123
|
def compact_if_needed(refs)
|
|
118
124
|
return unless refs.size > COMPACTION_THRESHOLD
|
|
119
125
|
|
|
@@ -185,7 +185,7 @@ module Lutaml
|
|
|
185
185
|
# Build mapping OUTSIDE any lock to avoid deadlock
|
|
186
186
|
# (ensure_mappings_imported! may recursively call get_or_build_mapping)
|
|
187
187
|
mapping = model_class.mappings[format]
|
|
188
|
-
mapping = mapping || model_class.
|
|
188
|
+
mapping = mapping || model_class.default_mappings(format)
|
|
189
189
|
|
|
190
190
|
mapping.ensure_mappings_imported!(register_id)
|
|
191
191
|
|
|
@@ -47,6 +47,9 @@ module Lutaml
|
|
|
47
47
|
# @return [Array<TypeSubstitution>] Type substitution rules
|
|
48
48
|
attr_reader :substitutions
|
|
49
49
|
|
|
50
|
+
# @return [Hash{Class => Class}] Pre-built Hash for O(1) substitution lookup
|
|
51
|
+
attr_reader :substitution_hash
|
|
52
|
+
|
|
50
53
|
# @return [Array<TypeContext>] Fallback contexts (in order)
|
|
51
54
|
attr_reader :fallback_contexts
|
|
52
55
|
|
|
@@ -60,6 +63,9 @@ module Lutaml
|
|
|
60
63
|
@id = id.to_sym
|
|
61
64
|
@registry = registry
|
|
62
65
|
@substitutions = Array(substitutions).freeze
|
|
66
|
+
@substitution_hash = @substitutions.to_h do |s|
|
|
67
|
+
[s.from_type, s.to_type]
|
|
68
|
+
end.freeze
|
|
63
69
|
@fallback_contexts = Array(fallback_contexts).freeze
|
|
64
70
|
freeze
|
|
65
71
|
end
|
|
@@ -254,7 +260,7 @@ module Lutaml
|
|
|
254
260
|
ctx
|
|
255
261
|
when Symbol, String
|
|
256
262
|
# Try to look up from GlobalContext if available
|
|
257
|
-
if defined?(GlobalContext)
|
|
263
|
+
if defined?(GlobalContext)
|
|
258
264
|
GlobalContext.registry.lookup(ctx)
|
|
259
265
|
end
|
|
260
266
|
end
|
|
@@ -157,12 +157,7 @@ module Lutaml
|
|
|
157
157
|
def self.apply_substitutions(type, context)
|
|
158
158
|
return type if context.nil? || context.substitutions.empty?
|
|
159
159
|
|
|
160
|
-
context.
|
|
161
|
-
substituted = sub.apply(type)
|
|
162
|
-
return substituted if substituted
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
type
|
|
160
|
+
context.substitution_hash[type] || type
|
|
166
161
|
end
|
|
167
162
|
|
|
168
163
|
# Get all available type names from context and fallbacks.
|
data/lib/lutaml/model/utils.rb
CHANGED
|
@@ -163,12 +163,25 @@ module Lutaml
|
|
|
163
163
|
# fetch_str_or_sym(hash, :key) # => "value"
|
|
164
164
|
# fetch_str_or_sym(hash, "invalid_key") # => nil
|
|
165
165
|
def fetch_str_or_sym(hash, key, default = nil)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
case key
|
|
167
|
+
when String
|
|
168
|
+
if hash.key?(key)
|
|
169
|
+
hash[key]
|
|
170
|
+
else
|
|
171
|
+
(hash.key?(key.to_sym) ? hash[key.to_sym] : default)
|
|
172
|
+
end
|
|
173
|
+
when Symbol
|
|
174
|
+
if hash.key?(key)
|
|
175
|
+
hash[key]
|
|
176
|
+
else
|
|
177
|
+
(hash.key?(key.to_s) ? hash[key.to_s] : default)
|
|
178
|
+
end
|
|
170
179
|
else
|
|
171
|
-
|
|
180
|
+
if hash.key?(key.to_s)
|
|
181
|
+
hash[key.to_s]
|
|
182
|
+
else
|
|
183
|
+
(hash.key?(key.to_sym) ? hash[key.to_sym] : default)
|
|
184
|
+
end
|
|
172
185
|
end
|
|
173
186
|
end
|
|
174
187
|
|
|
@@ -183,7 +196,7 @@ module Lutaml
|
|
|
183
196
|
end
|
|
184
197
|
|
|
185
198
|
def add_singleton_method_if_not_defined(instance, method_name, &)
|
|
186
|
-
return if instance.
|
|
199
|
+
return if instance.singleton_class.method_defined?(method_name, false)
|
|
187
200
|
|
|
188
201
|
instance.define_singleton_method(method_name, &)
|
|
189
202
|
end
|
|
@@ -10,11 +10,11 @@ module Lutaml
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def self.from(value, format)
|
|
13
|
-
new.
|
|
13
|
+
new.public_send(:"from_#{format}", value)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def self.to(value, format)
|
|
17
|
-
new(value).
|
|
17
|
+
new(value).public_send(:"to_#{format}")
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def self.can_transform?(method, format)
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -90,7 +90,7 @@ module Lutaml
|
|
|
90
90
|
# @param node [Moxml::Node] The XML node
|
|
91
91
|
# @return [String] The namespaced name (e.g., "uri:name" or "name")
|
|
92
92
|
def namespaced_name_of(node)
|
|
93
|
-
return name_of(node) unless node.
|
|
93
|
+
return name_of(node) unless node.is_a?(Lutaml::Xml::XmlElement)
|
|
94
94
|
|
|
95
95
|
[node&.namespace&.uri, node.name].compact.join(":")
|
|
96
96
|
end
|
|
@@ -126,7 +126,7 @@ module Lutaml
|
|
|
126
126
|
# @param options [Hash] serialization options
|
|
127
127
|
# @return [Boolean] true if element has ordered content
|
|
128
128
|
def ordered?(element, options = {})
|
|
129
|
-
return false unless element.
|
|
129
|
+
return false unless element.is_a?(Lutaml::Model::Serialize)
|
|
130
130
|
|
|
131
131
|
mapper_class = options[:mapper_class]
|
|
132
132
|
xml_mapping = mapper_class&.mappings_for(:xml)
|
|
@@ -156,7 +156,7 @@ module Lutaml
|
|
|
156
156
|
klass = mapper_class || element.class
|
|
157
157
|
return klass.attributes[rule.to] unless rule.delegate
|
|
158
158
|
|
|
159
|
-
delegated_obj = element.
|
|
159
|
+
delegated_obj = element.public_send(rule.delegate)
|
|
160
160
|
return nil if delegated_obj.nil?
|
|
161
161
|
|
|
162
162
|
delegated_obj.class.attributes[rule.to]
|
|
@@ -168,12 +168,12 @@ module Lutaml
|
|
|
168
168
|
# @param rule [MappingRule] the mapping rule
|
|
169
169
|
# @return [Object, nil] the attribute value or nil if delegate is nil
|
|
170
170
|
def attribute_value_for(element, rule)
|
|
171
|
-
return element.
|
|
171
|
+
return element.public_send(rule.to) unless rule.delegate
|
|
172
172
|
|
|
173
|
-
delegate_obj = element.
|
|
173
|
+
delegate_obj = element.public_send(rule.delegate)
|
|
174
174
|
return nil if delegate_obj.nil?
|
|
175
175
|
|
|
176
|
-
delegate_obj.
|
|
176
|
+
delegate_obj.public_send(rule.to)
|
|
177
177
|
end
|
|
178
178
|
|
|
179
179
|
# Process content mapping for an element
|
|
@@ -186,7 +186,7 @@ module Lutaml
|
|
|
186
186
|
return unless content_rule
|
|
187
187
|
|
|
188
188
|
if content_rule.custom_methods[:to]
|
|
189
|
-
mapper_class.new.
|
|
189
|
+
mapper_class.new.public_send(
|
|
190
190
|
content_rule.custom_methods[:to],
|
|
191
191
|
element,
|
|
192
192
|
xml.parent,
|
|
@@ -225,15 +225,11 @@ module Lutaml
|
|
|
225
225
|
private
|
|
226
226
|
|
|
227
227
|
def attribute_values(element, &)
|
|
228
|
-
|
|
229
|
-
element.attributes_each_value(&)
|
|
230
|
-
else
|
|
231
|
-
element.attributes.each_value(&)
|
|
232
|
-
end
|
|
228
|
+
element.attributes.each_value(&)
|
|
233
229
|
end
|
|
234
230
|
|
|
235
231
|
def schema_location_attribute?(attr)
|
|
236
|
-
attr_name = if attr.
|
|
232
|
+
attr_name = if attr.is_a?(Lutaml::Xml::XmlAttribute)
|
|
237
233
|
attr.unprefixed_name
|
|
238
234
|
else
|
|
239
235
|
attr.name
|
|
@@ -242,7 +238,7 @@ module Lutaml
|
|
|
242
238
|
end
|
|
243
239
|
|
|
244
240
|
def attribute_namespace_prefix(attr)
|
|
245
|
-
if attr.
|
|
241
|
+
if attr.is_a?(Lutaml::Xml::XmlAttribute)
|
|
246
242
|
attr.namespace_prefix
|
|
247
243
|
else
|
|
248
244
|
attr.namespace&.prefix
|
|
@@ -250,7 +246,7 @@ module Lutaml
|
|
|
250
246
|
end
|
|
251
247
|
|
|
252
248
|
def attribute_hash_name(attr)
|
|
253
|
-
if attr.
|
|
249
|
+
if attr.is_a?(Lutaml::Xml::XmlAttribute)
|
|
254
250
|
attr.namespaced_name
|
|
255
251
|
else
|
|
256
252
|
self.class.namespaced_attr_name(attr)
|
|
@@ -29,7 +29,7 @@ module Lutaml
|
|
|
29
29
|
|
|
30
30
|
visited.add(model.object_id)
|
|
31
31
|
|
|
32
|
-
if model.
|
|
32
|
+
if model.is_a?(::Lutaml::Model::Serialize) && model.class.attributes.key?(:original_namespace_uri) && model.original_namespace_uri
|
|
33
33
|
original_uri = model.original_namespace_uri
|
|
34
34
|
if original_uri && !original_uri.empty?
|
|
35
35
|
ns_class = model.class.mappings_for(:xml)&.namespace_class
|
|
@@ -47,12 +47,12 @@ module Lutaml
|
|
|
47
47
|
next unless attr_def
|
|
48
48
|
|
|
49
49
|
child_type = attr_def.type(Lutaml::Model::Config.default_register)
|
|
50
|
-
next unless child_type.
|
|
50
|
+
next unless child_type.is_a?(Class) && child_type < ::Lutaml::Model::Serializable
|
|
51
51
|
|
|
52
52
|
child_mapping = child_type.mappings_for(:xml)
|
|
53
53
|
next unless child_mapping
|
|
54
54
|
|
|
55
|
-
child_instance = model.public_send(elem_rule.to) if model.
|
|
55
|
+
child_instance = model.public_send(elem_rule.to) if model.class.attributes.key?(elem_rule.to)
|
|
56
56
|
|
|
57
57
|
if child_instance.is_a?(Array) || child_instance.is_a?(::Lutaml::Model::Collection)
|
|
58
58
|
instances = child_instance.is_a?(::Lutaml::Model::Collection) ? child_instance.collection : child_instance
|
|
@@ -158,8 +158,8 @@ module Lutaml
|
|
|
158
158
|
prefix: prefix) do |inner_xml|
|
|
159
159
|
# Call attribute custom methods now that element is created
|
|
160
160
|
attribute_custom_methods.each do |attribute_rule|
|
|
161
|
-
mapper_class.new.
|
|
162
|
-
|
|
161
|
+
mapper_class.new.public_send(attribute_rule.custom_methods[:to],
|
|
162
|
+
element, inner_xml.parent, inner_xml)
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
if ordered?(element, options.merge(mapper_class: mapper_class))
|
|
@@ -292,7 +292,7 @@ module Lutaml
|
|
|
292
292
|
end
|
|
293
293
|
|
|
294
294
|
# Check if element was created from nil value with render_nil option
|
|
295
|
-
if element.
|
|
295
|
+
if element.is_a?(Lutaml::Xml::DataModel::XmlElement) && element.xsi_nil
|
|
296
296
|
attributes["xsi:nil"] = true
|
|
297
297
|
end
|
|
298
298
|
|
|
@@ -301,7 +301,7 @@ module Lutaml
|
|
|
301
301
|
prefix: prefix) do |inner_xml|
|
|
302
302
|
# Handle raw content (map_all directive)
|
|
303
303
|
has_raw_content = false
|
|
304
|
-
if element.
|
|
304
|
+
if element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
305
305
|
raw_content = element.raw_content
|
|
306
306
|
if raw_content && !raw_content.to_s.empty?
|
|
307
307
|
inner_xml.add_xml_fragment(inner_xml, raw_content.to_s)
|
|
@@ -361,8 +361,8 @@ module Lutaml
|
|
|
361
361
|
|
|
362
362
|
# Handle custom methods
|
|
363
363
|
if element_rule.custom_methods[:to]
|
|
364
|
-
mapper_class.new.
|
|
365
|
-
|
|
364
|
+
mapper_class.new.public_send(element_rule.custom_methods[:to], element,
|
|
365
|
+
xml.parent, xml)
|
|
366
366
|
next
|
|
367
367
|
end
|
|
368
368
|
|
|
@@ -432,8 +432,8 @@ module Lutaml
|
|
|
432
432
|
|
|
433
433
|
# Handle custom methods
|
|
434
434
|
if element_rule.custom_methods[:to]
|
|
435
|
-
mapper_class.new.
|
|
436
|
-
|
|
435
|
+
mapper_class.new.public_send(element_rule.custom_methods[:to], element,
|
|
436
|
+
xml.parent, xml)
|
|
437
437
|
next
|
|
438
438
|
end
|
|
439
439
|
|
|
@@ -468,7 +468,7 @@ module Lutaml
|
|
|
468
468
|
attribute_def = mapper_class.attributes[element_rule.to]
|
|
469
469
|
next unless attribute_def
|
|
470
470
|
|
|
471
|
-
value = element.
|
|
471
|
+
value = element.public_send(element_rule.to)
|
|
472
472
|
next unless element_rule.render?(value, element)
|
|
473
473
|
|
|
474
474
|
# For type-only models, children plans may not be available
|
|
@@ -500,7 +500,7 @@ module Lutaml
|
|
|
500
500
|
attribute_def = mapper_class.attributes[element_rule.to]
|
|
501
501
|
next unless attribute_def
|
|
502
502
|
|
|
503
|
-
value = element.
|
|
503
|
+
value = element.public_send(element_rule.to)
|
|
504
504
|
next unless element_rule.render?(value, element)
|
|
505
505
|
|
|
506
506
|
child_plan = plan.child_plan(element_rule.to)
|
|
@@ -805,10 +805,10 @@ module Lutaml
|
|
|
805
805
|
value = nil
|
|
806
806
|
|
|
807
807
|
if element_rule.delegate
|
|
808
|
-
delegate_obj = element.
|
|
809
|
-
if delegate_obj.
|
|
808
|
+
delegate_obj = element.public_send(element_rule.delegate)
|
|
809
|
+
if delegate_obj.is_a?(Lutaml::Model::Serialize) && delegate_obj.class.attributes.key?(element_rule.to)
|
|
810
810
|
attribute_def = delegate_obj.class.attributes[element_rule.to]
|
|
811
|
-
value = delegate_obj.
|
|
811
|
+
value = delegate_obj.public_send(element_rule.to)
|
|
812
812
|
end
|
|
813
813
|
else
|
|
814
814
|
attribute_def = attribute_definition_for(element, element_rule,
|
|
@@ -828,7 +828,7 @@ module Lutaml
|
|
|
828
828
|
# @param content [Array] accumulated content strings
|
|
829
829
|
def process_ordered_content(element, xml_mapping, xml, curr_index,
|
|
830
830
|
content)
|
|
831
|
-
text = element.
|
|
831
|
+
text = element.public_send(xml_mapping.content_mapping.to)
|
|
832
832
|
text = text[curr_index] if text.is_a?(Array)
|
|
833
833
|
|
|
834
834
|
if element.mixed?
|
|
@@ -83,7 +83,7 @@ module Lutaml
|
|
|
83
83
|
def build_xml_element_with_plan(builder, xml_element, plan,
|
|
84
84
|
options = {})
|
|
85
85
|
# Add processing instructions before the root element
|
|
86
|
-
if xml_element.
|
|
86
|
+
if xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
87
87
|
xml_element.processing_instructions.each do |pi|
|
|
88
88
|
builder.add_processing_instruction(pi.target, pi.content)
|
|
89
89
|
end
|
|
@@ -230,7 +230,7 @@ module Lutaml
|
|
|
230
230
|
attributes[attr_node.qualified_name] = xml_attr.value.to_s
|
|
231
231
|
end
|
|
232
232
|
|
|
233
|
-
if xml_element.
|
|
233
|
+
if xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement) && xml_element.xsi_nil
|
|
234
234
|
attributes["xsi:nil"] = "true"
|
|
235
235
|
end
|
|
236
236
|
|
|
@@ -240,7 +240,7 @@ module Lutaml
|
|
|
240
240
|
attributes["xmlns"] = "" if needs_xmlns_blank
|
|
241
241
|
|
|
242
242
|
xml.create_and_add_element(qualified_name, attributes: attributes) do
|
|
243
|
-
if xml_element.
|
|
243
|
+
if xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
244
244
|
raw_content = xml_element.raw_content
|
|
245
245
|
if raw_content && !raw_content.to_s.empty?
|
|
246
246
|
xml.add_xml_fragment(xml, raw_content.to_s)
|
|
@@ -119,7 +119,8 @@ module Lutaml
|
|
|
119
119
|
# @return [void]
|
|
120
120
|
def inherit_mapping_from(mapping_class)
|
|
121
121
|
# Get the parent mapping instance that has DSL already evaluated
|
|
122
|
-
parent_mapping = if mapping_class.
|
|
122
|
+
parent_mapping = if mapping_class.is_a?(Class) &&
|
|
123
|
+
(mapping_class < Lutaml::Xml::Mapping || mapping_class.include?(Lutaml::Model::Serialize)) &&
|
|
123
124
|
mapping_class.xml_mapping_instance
|
|
124
125
|
mapping_class.xml_mapping_instance
|
|
125
126
|
else
|
|
@@ -133,7 +133,7 @@ module Lutaml
|
|
|
133
133
|
def qualified_name(prefix = nil)
|
|
134
134
|
if prefix
|
|
135
135
|
"#{prefix}:#{name}"
|
|
136
|
-
elsif namespace_class.
|
|
136
|
+
elsif namespace_class.is_a?(Class) && namespace_class < Lutaml::Xml::Namespace
|
|
137
137
|
ns_prefix = namespace_class.prefix_default
|
|
138
138
|
ns_prefix ? "#{ns_prefix}:#{name}" : name
|
|
139
139
|
else
|
|
@@ -202,7 +202,7 @@ module Lutaml
|
|
|
202
202
|
def qualified_name(prefix = nil)
|
|
203
203
|
if prefix
|
|
204
204
|
"#{prefix}:#{name}"
|
|
205
|
-
elsif namespace_class.
|
|
205
|
+
elsif namespace_class.is_a?(Class) && namespace_class < Lutaml::Xml::Namespace
|
|
206
206
|
ns_prefix = namespace_class.prefix_default
|
|
207
207
|
ns_prefix ? "#{ns_prefix}:#{name}" : name
|
|
208
208
|
else
|
|
@@ -129,7 +129,7 @@ module Lutaml
|
|
|
129
129
|
return nil unless @element
|
|
130
130
|
|
|
131
131
|
if @element.is_a?(Lutaml::Xml::XmlElement)
|
|
132
|
-
@element.namespace_prefix
|
|
132
|
+
@element.namespace_prefix
|
|
133
133
|
else
|
|
134
134
|
# For DataModel::XmlElement, check xml_namespace_prefix first
|
|
135
135
|
prefix = @element.xml_namespace_prefix
|
|
@@ -137,7 +137,7 @@ module Lutaml
|
|
|
137
137
|
|
|
138
138
|
# Fall back to original XmlElement wrapper if available
|
|
139
139
|
original = @element.original_xml_element
|
|
140
|
-
if original.
|
|
140
|
+
if original.is_a?(Lutaml::Xml::XmlElement)
|
|
141
141
|
return original.namespace_prefix
|
|
142
142
|
end
|
|
143
143
|
|
|
@@ -213,7 +213,7 @@ module Lutaml
|
|
|
213
213
|
|
|
214
214
|
# Returns all URIs for the current namespace (canonical + aliases).
|
|
215
215
|
def namespace_all_uris
|
|
216
|
-
if @namespace_class.
|
|
216
|
+
if @namespace_class.is_a?(Class) && @namespace_class < Lutaml::Xml::Namespace
|
|
217
217
|
@namespace_class.all_uris
|
|
218
218
|
else
|
|
219
219
|
[@namespace_uri]
|
|
@@ -51,7 +51,7 @@ module Lutaml
|
|
|
51
51
|
|
|
52
52
|
# Only apply if no explicit form option on the element
|
|
53
53
|
# ElementFormOptionRule (Priority -0.5) handles explicit form options
|
|
54
|
-
return false if context.element.
|
|
54
|
+
return false if context.element.is_a?(Lutaml::Xml::DataModel::XmlElement) && !context.element.form.nil?
|
|
55
55
|
|
|
56
56
|
true
|
|
57
57
|
end
|
|
@@ -30,7 +30,7 @@ module Lutaml
|
|
|
30
30
|
def applies?(context)
|
|
31
31
|
return false unless context.element
|
|
32
32
|
# Check if element responds to :form before accessing it
|
|
33
|
-
return false unless context.element.
|
|
33
|
+
return false unless context.element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
34
34
|
|
|
35
35
|
# Check if element has form attribute
|
|
36
36
|
form = context.element.form
|
|
@@ -44,7 +44,7 @@ module Lutaml
|
|
|
44
44
|
# Skip if namespace does NOT have element_form_default :qualified
|
|
45
45
|
# Namespaces without explicit :qualified should use default format
|
|
46
46
|
# (e.g., dcterms namespace uses default format, not prefix)
|
|
47
|
-
return false unless ns_class.
|
|
47
|
+
return false unless ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace &&
|
|
48
48
|
ns_class.element_form_default_set? &&
|
|
49
49
|
ns_class.element_form_default == :qualified
|
|
50
50
|
|
|
@@ -441,7 +441,7 @@ module Lutaml
|
|
|
441
441
|
ns_classes = []
|
|
442
442
|
collect_ns_classes_recursive(@root_node, ns_classes)
|
|
443
443
|
ns_classes.uniq.select do |ns_class|
|
|
444
|
-
ns_class.
|
|
444
|
+
ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace && ns_class.schema_location
|
|
445
445
|
end
|
|
446
446
|
end
|
|
447
447
|
|
|
@@ -452,7 +452,7 @@ module Lutaml
|
|
|
452
452
|
# @return [void]
|
|
453
453
|
def collect_ns_classes_recursive(element_node, ns_classes)
|
|
454
454
|
# Add namespace from element's own namespace_class
|
|
455
|
-
if element_node.
|
|
455
|
+
if element_node.is_a?(Lutaml::Xml::DeclarationPlan::ElementNode) && @namespace_classes
|
|
456
456
|
# Try to find namespace class from namespace_classes by matching URI
|
|
457
457
|
# The ElementNode itself doesn't store ns_class, but we can check if
|
|
458
458
|
# any of our namespace_classes match the element's context
|