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
|
@@ -298,7 +298,7 @@ module Lutaml
|
|
|
298
298
|
def build_collection_item_plans(collection, _mapping, _needs)
|
|
299
299
|
children_plans = {}
|
|
300
300
|
|
|
301
|
-
return children_plans unless collection.
|
|
301
|
+
return children_plans unless collection.is_a?(Array)
|
|
302
302
|
|
|
303
303
|
# Get the item type from the collection class
|
|
304
304
|
item_type = begin
|
|
@@ -595,7 +595,7 @@ mapper_class: nil)
|
|
|
595
595
|
|
|
596
596
|
# Get child's element namespace if available
|
|
597
597
|
child_type = attr_def.type(mapper_class ? register_for(mapper_class) : @register)
|
|
598
|
-
if child_type.
|
|
598
|
+
if child_type.is_a?(Class) && child_type < Lutaml::Model::Serialize
|
|
599
599
|
child_reg = register_for(child_type)
|
|
600
600
|
child_mapping = child_type.mappings_for(:xml, child_reg)
|
|
601
601
|
if child_mapping&.namespace_class
|
|
@@ -675,7 +675,7 @@ mapper_class: nil)
|
|
|
675
675
|
# prefix declarations are NOT needed by any child element.
|
|
676
676
|
if is_root && !options.key?(:use_prefix)
|
|
677
677
|
stored_plan = options[:stored_xml_declaration_plan]
|
|
678
|
-
if stored_plan.
|
|
678
|
+
if stored_plan.is_a?(Lutaml::Xml::DeclarationPlan) && stored_plan.root_node.is_a?(Lutaml::Xml::DeclarationPlan::ElementNode)
|
|
679
679
|
root_has_input_prefix = xml_element.xml_namespace_prefix.to_s != ""
|
|
680
680
|
|
|
681
681
|
unless root_has_input_prefix
|
|
@@ -706,7 +706,7 @@ mapper_class: nil)
|
|
|
706
706
|
#
|
|
707
707
|
# Note: The transformation sets @needs_xmlns_blank on the XmlElement when the child
|
|
708
708
|
# model has explicit `namespace :blank` declaration.
|
|
709
|
-
element_marked_blank = xml_element.
|
|
709
|
+
element_marked_blank = xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement) && xml_element.needs_xmlns_blank
|
|
710
710
|
|
|
711
711
|
# Add xmlns="" when parent's effective namespace form is :qualified.
|
|
712
712
|
# This implements the W3C XML Schema default behavior:
|
|
@@ -803,7 +803,7 @@ mapper_class: nil)
|
|
|
803
803
|
if attr_def
|
|
804
804
|
child_reg = mapper_class ? register_for(mapper_class) : @register
|
|
805
805
|
child_type = attr_def.type(child_reg)
|
|
806
|
-
if child_type.
|
|
806
|
+
if child_type.is_a?(Class) && child_type < Lutaml::Model::Serialize
|
|
807
807
|
child_type_reg = register_for(child_type)
|
|
808
808
|
child_mapping_obj = child_type.mappings_for(:xml,
|
|
809
809
|
child_type_reg)
|
|
@@ -1041,7 +1041,6 @@ mapper_class: nil)
|
|
|
1041
1041
|
ns_key = xml_element.namespace_class.to_key
|
|
1042
1042
|
ns_usage = needs.namespaces[ns_key]
|
|
1043
1043
|
ns_from_wrapper = xml_element.is_a?(Lutaml::Xml::XmlElement) &&
|
|
1044
|
-
xml_element.respond_to?(:namespace_prefix_explicit) &&
|
|
1045
1044
|
xml_element.namespace_prefix_explicit
|
|
1046
1045
|
if ns_from_wrapper
|
|
1047
1046
|
used_prefix = ns_usage&.used_prefix
|
|
@@ -1195,7 +1194,7 @@ mapper_class: nil)
|
|
|
1195
1194
|
# 3. Parent declared canonical/alias-A, child wants alias-B → NOT hoisted (child must declare its alias)
|
|
1196
1195
|
# This ensures round-trip fidelity: if input used alias URI, output preserves it.
|
|
1197
1196
|
ns_hoisted_by_parent = parent_hoisted.value?(ns_uri)
|
|
1198
|
-
if !ns_hoisted_by_parent && ns_class.
|
|
1197
|
+
if !ns_hoisted_by_parent && ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace &&
|
|
1199
1198
|
ns_uri == ns_class.uri # child is using canonical URI
|
|
1200
1199
|
# Parent declared an alias of this namespace — child doesn't need to re-declare
|
|
1201
1200
|
# because the alias already establishes the namespace binding
|
|
@@ -1227,7 +1226,7 @@ mapper_class: nil)
|
|
|
1227
1226
|
# Namespace is already hoisted by parent, and we have an explicit prefix
|
|
1228
1227
|
# Check if parent has the SAME prefix declaration (accounting for URI aliases)
|
|
1229
1228
|
parent_uri_for_prefix = parent_hoisted[element_prefix]
|
|
1230
|
-
all_uris = ns_class.
|
|
1229
|
+
all_uris = ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace ? ns_class.all_uris : [ns_uri]
|
|
1231
1230
|
parent_has_same_prefix = parent_uri_for_prefix && all_uris.include?(parent_uri_for_prefix)
|
|
1232
1231
|
if parent_has_same_prefix
|
|
1233
1232
|
# Parent already declared this namespace with the same prefix - don't re-declare
|
|
@@ -1256,7 +1255,7 @@ mapper_class: nil)
|
|
|
1256
1255
|
# Use namespaces_at_path([]) to verify this namespace was actually at root level.
|
|
1257
1256
|
# Note: namespace_locations only has child paths, not root. Root namespaces
|
|
1258
1257
|
# are stored in root_node.hoisted_declarations, which namespaces_at_path returns.
|
|
1259
|
-
if is_root && hoisted.key?(nil) && hoisted[nil] == ns_uri && xml_element.
|
|
1258
|
+
if is_root && hoisted.key?(nil) && hoisted[nil] == ns_uri && xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
1260
1259
|
stored_plan = options[:stored_xml_declaration_plan]
|
|
1261
1260
|
root_ns_at_input = stored_plan&.namespaces_at_path([])
|
|
1262
1261
|
namespace_was_at_root = if root_ns_at_input
|
|
@@ -1405,7 +1404,7 @@ mapper_class: nil)
|
|
|
1405
1404
|
|
|
1406
1405
|
# Only skip hoisting if child uses namespace AND parent doesn't use it for attributes
|
|
1407
1406
|
# Check if parent element instance has attributes with this namespace
|
|
1408
|
-
parent_has_attr_with_ns = if xml_element.
|
|
1407
|
+
parent_has_attr_with_ns = if xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
1409
1408
|
xml_element.attributes.any? do |xml_attr|
|
|
1410
1409
|
next false unless xml_attr.namespace_class
|
|
1411
1410
|
|
|
@@ -1454,7 +1453,7 @@ mapper_class: nil)
|
|
|
1454
1453
|
end
|
|
1455
1454
|
|
|
1456
1455
|
# Only skip hoisting if child uses namespace AND parent doesn't use it for attributes
|
|
1457
|
-
parent_has_attr_with_ns = if xml_element.
|
|
1456
|
+
parent_has_attr_with_ns = if xml_element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
1458
1457
|
xml_element.attributes.any? do |xml_attr|
|
|
1459
1458
|
next false unless xml_attr.namespace_class
|
|
1460
1459
|
|
|
@@ -1711,7 +1710,7 @@ mapper_class: nil)
|
|
|
1711
1710
|
|
|
1712
1711
|
# Check all namespace classes in needs
|
|
1713
1712
|
needs.all_namespace_classes.any? do |ns_class|
|
|
1714
|
-
ns_class.
|
|
1713
|
+
ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace && ns_class.schema_location
|
|
1715
1714
|
end
|
|
1716
1715
|
end
|
|
1717
1716
|
|
|
@@ -1829,7 +1828,7 @@ mapper_class: nil)
|
|
|
1829
1828
|
|
|
1830
1829
|
# Collect all namespace classes that have schema_location
|
|
1831
1830
|
namespaces_with_schema = needs.all_namespace_classes.select do |ns_class|
|
|
1832
|
-
ns_class.
|
|
1831
|
+
ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace && ns_class.schema_location
|
|
1833
1832
|
end
|
|
1834
1833
|
|
|
1835
1834
|
return nil if namespaces_with_schema.empty?
|
data/lib/lutaml/xml/document.rb
CHANGED
|
@@ -63,7 +63,7 @@ module Lutaml
|
|
|
63
63
|
# @return [String, nil] the DOCTYPE declaration or nil if no DOCTYPE
|
|
64
64
|
def doctype_declaration
|
|
65
65
|
# Prefer native Nokogiri DOCTYPE
|
|
66
|
-
if @parsed_doc.
|
|
66
|
+
if defined?(::Nokogiri) && @parsed_doc.is_a?(::Nokogiri::XML::Document) && @parsed_doc.internal_subset
|
|
67
67
|
return "#{@parsed_doc.internal_subset}\n"
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -97,15 +97,15 @@ module Lutaml
|
|
|
97
97
|
result.attribute_order = element.attribute_order
|
|
98
98
|
|
|
99
99
|
element.children.each do |child|
|
|
100
|
-
next if child.
|
|
101
|
-
next if child.
|
|
100
|
+
next if child.is_a?(Lutaml::Xml::XmlElement) && child.comment?
|
|
101
|
+
next if child.is_a?(Lutaml::Xml::XmlElement) && child.processing_instruction?
|
|
102
102
|
|
|
103
103
|
if klass&.<= Serialize
|
|
104
104
|
attr = klass.attribute_for_child(self.class.name_of(child),
|
|
105
105
|
format)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
-
if child.
|
|
108
|
+
if child.is_a?(Lutaml::Xml::XmlElement) && child.text?
|
|
109
109
|
result.assign_or_append_value(
|
|
110
110
|
self.class.name_of(child),
|
|
111
111
|
self.class.text_of(child),
|
|
@@ -148,7 +148,7 @@ module Lutaml
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def ordered?(element, options = {})
|
|
151
|
-
return false unless element.
|
|
151
|
+
return false unless element.is_a?(Lutaml::Model::Serialize)
|
|
152
152
|
|
|
153
153
|
mapper_class = options[:mapper_class]
|
|
154
154
|
xml_mapping = mapper_class&.mappings_for(:xml)
|
|
@@ -198,7 +198,7 @@ module Lutaml
|
|
|
198
198
|
return unless content_rule
|
|
199
199
|
|
|
200
200
|
if content_rule.custom_methods[:to]
|
|
201
|
-
mapper_class.new.
|
|
201
|
+
mapper_class.new.public_send(
|
|
202
202
|
content_rule.custom_methods[:to],
|
|
203
203
|
element,
|
|
204
204
|
xml.parent,
|
|
@@ -216,16 +216,16 @@ module Lutaml
|
|
|
216
216
|
klass = mapper_class || element.class
|
|
217
217
|
return klass.attributes[rule.to] unless rule.delegate
|
|
218
218
|
|
|
219
|
-
delegated_obj = element.
|
|
219
|
+
delegated_obj = element.public_send(rule.delegate)
|
|
220
220
|
return nil if delegated_obj.nil?
|
|
221
221
|
|
|
222
222
|
delegated_obj.class.attributes[rule.to]
|
|
223
223
|
end
|
|
224
224
|
|
|
225
225
|
def attribute_value_for(element, rule)
|
|
226
|
-
return element.
|
|
226
|
+
return element.public_send(rule.to) unless rule.delegate
|
|
227
227
|
|
|
228
|
-
element.
|
|
228
|
+
element.public_send(rule.delegate).public_send(rule.to)
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
def self.type
|
|
@@ -254,7 +254,7 @@ module Lutaml
|
|
|
254
254
|
# For text + entity without elements, return joined String.
|
|
255
255
|
has_element_children = @root.children.any? do |child|
|
|
256
256
|
!child.text? && !entity_reference_node?(child) &&
|
|
257
|
-
!(child.
|
|
257
|
+
!(child.is_a?(Lutaml::Xml::XmlElement) && child.processing_instruction?)
|
|
258
258
|
end
|
|
259
259
|
return @root.text_children.map(&:text) if has_element_children
|
|
260
260
|
|
|
@@ -273,7 +273,7 @@ module Lutaml
|
|
|
273
273
|
return false unless child.is_a?(Lutaml::Xml::NokogiriElement)
|
|
274
274
|
|
|
275
275
|
node = child.adapter_node
|
|
276
|
-
node.
|
|
276
|
+
defined?(::Nokogiri) && node.is_a?(::Nokogiri::XML::EntityReference) && node.entity_reference?
|
|
277
277
|
end
|
|
278
278
|
|
|
279
279
|
def setup_register(register)
|
|
@@ -281,7 +281,7 @@ module Lutaml
|
|
|
281
281
|
|
|
282
282
|
return_register = if register.is_a?(Lutaml::Model::Register)
|
|
283
283
|
register.id
|
|
284
|
-
elsif @root.
|
|
284
|
+
elsif @root.is_a?(Lutaml::Model::Serialize)
|
|
285
285
|
@root.lutaml_register
|
|
286
286
|
end
|
|
287
287
|
return_register || Lutaml::Model::Config.default_register
|
|
@@ -377,7 +377,7 @@ module Lutaml
|
|
|
377
377
|
ns_entry
|
|
378
378
|
end
|
|
379
379
|
|
|
380
|
-
ns_class.
|
|
380
|
+
ns_class.is_a?(Class) && ns_class < Lutaml::Xml::XmlNamespace && ns_class.uri == namespace_uri
|
|
381
381
|
end
|
|
382
382
|
end
|
|
383
383
|
end
|
|
@@ -60,7 +60,7 @@ module Lutaml
|
|
|
60
60
|
# 3. Check if any child elements use :inherit
|
|
61
61
|
# If they do and we have a prefix, use prefixed format
|
|
62
62
|
# so children can properly reference the namespace
|
|
63
|
-
if mapping.namespace_class.prefix_default && mapping.
|
|
63
|
+
if mapping.namespace_class.prefix_default && mapping.is_a?(Lutaml::Xml::Mapping)
|
|
64
64
|
has_inherit_children = mapping.elements.any? do |elem_rule|
|
|
65
65
|
elem_rule.namespace_param == :inherit
|
|
66
66
|
end
|
|
@@ -99,7 +99,7 @@ module Lutaml
|
|
|
99
99
|
has_explicit_pref = options.key?(:prefix) || options.key?(:use_prefix)
|
|
100
100
|
if !has_explicit_pref && options[:stored_xml_declaration_plan]
|
|
101
101
|
stored_plan = options[:stored_xml_declaration_plan]
|
|
102
|
-
if stored_plan.
|
|
102
|
+
if stored_plan.is_a?(Lutaml::Xml::DeclarationPlan)
|
|
103
103
|
# Check canonical URI and all aliases
|
|
104
104
|
uris_to_check = [effective_ns_class.uri] + effective_ns_class.uri_aliases
|
|
105
105
|
stored_plan.input_prefix_formats.each do |key, format|
|
|
@@ -165,7 +165,7 @@ module Lutaml
|
|
|
165
165
|
end
|
|
166
166
|
|
|
167
167
|
# 3. Check if any child elements use :inherit or form: :qualified
|
|
168
|
-
if effective_ns_class.prefix_default && mapping.
|
|
168
|
+
if effective_ns_class.prefix_default && mapping.is_a?(Lutaml::Xml::Mapping)
|
|
169
169
|
has_inherit_children = mapping.elements.any? do |elem_rule|
|
|
170
170
|
elem_rule.namespace_param == :inherit
|
|
171
171
|
end
|
|
@@ -44,7 +44,7 @@ module Lutaml
|
|
|
44
44
|
|
|
45
45
|
# Check if element or its descendants use a namespace
|
|
46
46
|
def element_needs_namespace?(element, namespace_class)
|
|
47
|
-
return false unless element.
|
|
47
|
+
return false unless element.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
|
48
48
|
|
|
49
49
|
element.children.each do |child|
|
|
50
50
|
next unless child.is_a?(Lutaml::Xml::DataModel::XmlElement)
|
data/lib/lutaml/xml/mapping.rb
CHANGED
|
@@ -130,7 +130,7 @@ module Lutaml
|
|
|
130
130
|
delegate = @content_mapping.delegate
|
|
131
131
|
attr_def = if delegate
|
|
132
132
|
delegate_obj = mapper_class.attributes[delegate]
|
|
133
|
-
delegate_obj&.type&.attributes&.dig(attr_name) if delegate_obj&.type.
|
|
133
|
+
delegate_obj&.type&.attributes&.dig(attr_name) if delegate_obj&.type.is_a?(Class) && delegate_obj&.type.include?(Lutaml::Model::Serialize)
|
|
134
134
|
else
|
|
135
135
|
mapper_class.attributes[attr_name]
|
|
136
136
|
end
|
|
@@ -638,7 +638,7 @@ module Lutaml
|
|
|
638
638
|
|
|
639
639
|
if name == "schemaLocation"
|
|
640
640
|
location = caller_locations(1, 1)[0]
|
|
641
|
-
caller_file = if defined?(File)
|
|
641
|
+
caller_file = if defined?(File)
|
|
642
642
|
File.basename(location.path)
|
|
643
643
|
else
|
|
644
644
|
location.path.to_s.split("/").last
|
|
@@ -90,6 +90,19 @@ module Lutaml
|
|
|
90
90
|
!!@namespace_set
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
+
# Pre-computed frozen Hash for the static namespace override case.
|
|
94
|
+
# Returns nil when no static override is needed — the caller should
|
|
95
|
+
# use the parent options directly, avoiding per-rule Hash allocation.
|
|
96
|
+
#
|
|
97
|
+
# Only rules with an explicit namespace (namespace_set? && != :inherit)
|
|
98
|
+
# produce a static override. The result is frozen and shared across
|
|
99
|
+
# all elements that evaluate this rule.
|
|
100
|
+
def static_namespace_option
|
|
101
|
+
return nil unless namespace_set? && @namespace_param != :inherit
|
|
102
|
+
|
|
103
|
+
@static_namespace_option ||= { default_namespace: namespace }.freeze
|
|
104
|
+
end
|
|
105
|
+
|
|
93
106
|
def content_mapping?
|
|
94
107
|
name.nil?
|
|
95
108
|
end
|
|
@@ -215,14 +228,14 @@ module Lutaml
|
|
|
215
228
|
).tap do |dup_rule|
|
|
216
229
|
# Manually preserve the exact @namespace_class object to avoid
|
|
217
230
|
# recreating anonymous classes (which would have different object_ids)
|
|
218
|
-
dup_rule.
|
|
231
|
+
dup_rule.namespace_class = @namespace_class
|
|
219
232
|
|
|
220
233
|
# Manually ensure @namespace and @prefix are new string objects
|
|
221
234
|
if dup_rule.namespace
|
|
222
|
-
dup_rule.
|
|
235
|
+
dup_rule.namespace = dup_rule.namespace.dup
|
|
223
236
|
end
|
|
224
237
|
if dup_rule.prefix
|
|
225
|
-
dup_rule.
|
|
238
|
+
dup_rule.prefix = dup_rule.prefix.dup
|
|
226
239
|
end
|
|
227
240
|
end
|
|
228
241
|
end
|
|
@@ -252,7 +252,7 @@ effective_register = nil, instance_is_serialize = nil)
|
|
|
252
252
|
# Performance: Pre-build Set of child namespaced names for fast rule matching.
|
|
253
253
|
# This allows skipping value_for_rule for ~91% of rules that have no matching child.
|
|
254
254
|
child_names_set = nil
|
|
255
|
-
if doc.
|
|
255
|
+
if doc.is_a?(::Lutaml::Xml::XmlElement) || doc.is_a?(::Lutaml::Xml::Document)
|
|
256
256
|
ec = doc.element_children
|
|
257
257
|
unless ec.empty?
|
|
258
258
|
child_names_set = Set.new
|
|
@@ -268,7 +268,7 @@ effective_register = nil, instance_is_serialize = nil)
|
|
|
268
268
|
rule.name
|
|
269
269
|
rule_to = rule.to
|
|
270
270
|
rule_namespace_set = rule.namespace_set?
|
|
271
|
-
|
|
271
|
+
rule_namespace_set ? rule.namespace_param : nil
|
|
272
272
|
|
|
273
273
|
attr = attribute_for_rule(rule)
|
|
274
274
|
next if attr&.derived?
|
|
@@ -277,15 +277,14 @@ effective_register = nil, instance_is_serialize = nil)
|
|
|
277
277
|
rule, attr
|
|
278
278
|
)
|
|
279
279
|
|
|
280
|
-
# Performance:
|
|
281
|
-
#
|
|
282
|
-
new_opts =
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
end
|
|
280
|
+
# Performance: Use pre-computed frozen Hash for static namespace overrides.
|
|
281
|
+
# Falls back to per-element hash only for the dynamic namespace_uri case.
|
|
282
|
+
new_opts = rule.static_namespace_option ||
|
|
283
|
+
if default_namespace.nil? && namespace_uri
|
|
284
|
+
{ default_namespace: namespace_uri }
|
|
285
|
+
else
|
|
286
|
+
options
|
|
287
|
+
end
|
|
289
288
|
|
|
290
289
|
value = if rule.raw_mapping?
|
|
291
290
|
doc.root.inner_xml
|
|
@@ -333,9 +332,6 @@ effective_register = nil, instance_is_serialize = nil)
|
|
|
333
332
|
value = rule.transform_value(attr, value, :from, :xml)
|
|
334
333
|
rule.deserialize(instance, value, attributes, context)
|
|
335
334
|
|
|
336
|
-
# Mark attribute as set from XML (not using default).
|
|
337
|
-
# Needed for instances created via allocate_for_deserialization
|
|
338
|
-
# which use Hash.new(true) as @using_default default.
|
|
339
335
|
instance.value_set_for(rule_to)
|
|
340
336
|
end
|
|
341
337
|
|
|
@@ -364,7 +360,7 @@ effective_register = nil, instance_is_serialize = nil)
|
|
|
364
360
|
mixed_content_option, xml_mapping = nil,
|
|
365
361
|
instance_is_serialize = nil)
|
|
366
362
|
instance.element_order = doc.root.order
|
|
367
|
-
if doc.root.
|
|
363
|
+
if instance_is_serialize && doc.root.is_a?(::Lutaml::Xml::XmlElement)
|
|
368
364
|
instance.attribute_order = doc.root.attribute_order
|
|
369
365
|
end
|
|
370
366
|
|
|
@@ -399,10 +395,12 @@ _effective_register)
|
|
|
399
395
|
pi_mappings = xml_mapping.processing_instruction_mappings
|
|
400
396
|
return if pi_mappings.empty?
|
|
401
397
|
|
|
402
|
-
doc_pis = if doc.
|
|
398
|
+
doc_pis = if doc.is_a?(::Lutaml::Xml::XmlElement)
|
|
403
399
|
doc.processing_instructions
|
|
404
|
-
elsif doc.
|
|
400
|
+
elsif doc.is_a?(::Lutaml::Xml::Document)
|
|
405
401
|
doc.root.processing_instructions
|
|
402
|
+
else
|
|
403
|
+
[]
|
|
406
404
|
end || []
|
|
407
405
|
|
|
408
406
|
pi_attr = Lutaml::Xml::DataModel::XmlProcessingInstruction
|
|
@@ -427,7 +425,7 @@ _effective_register)
|
|
|
427
425
|
next if value.nil?
|
|
428
426
|
|
|
429
427
|
instance.public_send(:"#{pi_mapping.to}=", value)
|
|
430
|
-
instance.value_set_for(pi_mapping.to) if instance.
|
|
428
|
+
instance.value_set_for(pi_mapping.to) if instance.is_a?(::Lutaml::Model::Serialize)
|
|
431
429
|
end
|
|
432
430
|
end
|
|
433
431
|
|
|
@@ -946,7 +944,7 @@ effective_register = lutaml_register)
|
|
|
946
944
|
next unless collection.class.organization
|
|
947
945
|
|
|
948
946
|
mappings = collection.class.mappings_for(:xml, register)
|
|
949
|
-
next unless mappings.
|
|
947
|
+
next unless mappings.is_a?(::Lutaml::Xml::Mapping)
|
|
950
948
|
next if mappings.consolidation_maps.empty?
|
|
951
949
|
|
|
952
950
|
mappings.consolidation_maps.each do |map|
|
|
@@ -61,15 +61,15 @@ module Lutaml
|
|
|
61
61
|
needs = collect(nil, mapping)
|
|
62
62
|
|
|
63
63
|
# If collection has instances, collect needs from instance type
|
|
64
|
-
if collection.
|
|
65
|
-
mapping.
|
|
64
|
+
if collection.is_a?(Lutaml::Model::Collection) &&
|
|
65
|
+
mapping.is_a?(Lutaml::Xml::Mapping)
|
|
66
66
|
instance_rule = mapping.find_element(:instances) ||
|
|
67
67
|
mapping.elements.first
|
|
68
68
|
if instance_rule
|
|
69
69
|
attr_def = collection.class.attributes[instance_rule.to]
|
|
70
70
|
if attr_def
|
|
71
71
|
instance_type = attr_def.type(@register)
|
|
72
|
-
if instance_type.
|
|
72
|
+
if instance_type.is_a?(Class) &&
|
|
73
73
|
instance_type < Lutaml::Model::Serialize
|
|
74
74
|
instance_mapping = instance_type.mappings_for(:xml)
|
|
75
75
|
if instance_mapping
|
|
@@ -314,7 +314,7 @@ module Lutaml
|
|
|
314
314
|
|
|
315
315
|
# INSTANCE-AWARE COLLECTION
|
|
316
316
|
if element
|
|
317
|
-
value = element.
|
|
317
|
+
value = element.public_send(attr_rule.to) if element.is_a?(Lutaml::Model::Serialize) && element.class.attributes.key?(attr_rule.to)
|
|
318
318
|
next if value.nil? || ::Lutaml::Model::Utils.uninitialized?(value)
|
|
319
319
|
end
|
|
320
320
|
|
|
@@ -346,7 +346,7 @@ module Lutaml
|
|
|
346
346
|
# ==================================================================
|
|
347
347
|
# PHASE 3: NAMESPACE_SCOPE CONFIGURATION
|
|
348
348
|
# ==================================================================
|
|
349
|
-
if mapping.
|
|
349
|
+
if mapping.is_a?(Lutaml::Xml::Mapping) && mapping.namespace_scope_config&.any?
|
|
350
350
|
mapping.namespace_scope_config.each do |cfg|
|
|
351
351
|
config = NamespaceScopeConfig.new(cfg[:namespace],
|
|
352
352
|
cfg[:declare] || :auto)
|
|
@@ -374,8 +374,8 @@ module Lutaml
|
|
|
374
374
|
next unless child_type
|
|
375
375
|
|
|
376
376
|
# Get child instance BEFORE adding Type ref
|
|
377
|
-
child_instance = if element.
|
|
378
|
-
element.
|
|
377
|
+
child_instance = if element.is_a?(Lutaml::Model::Serialize) && element.class.attributes.key?(elem_rule.to)
|
|
378
|
+
element.public_send(elem_rule.to)
|
|
379
379
|
end
|
|
380
380
|
|
|
381
381
|
# TYPE NAMESPACE INTEGRATION
|
|
@@ -390,7 +390,7 @@ module Lutaml
|
|
|
390
390
|
needs.add_type_ref(ref)
|
|
391
391
|
end
|
|
392
392
|
|
|
393
|
-
next unless child_type.
|
|
393
|
+
next unless child_type.is_a?(Class) &&
|
|
394
394
|
child_type < Lutaml::Model::Serialize
|
|
395
395
|
|
|
396
396
|
# Get child mapping
|
|
@@ -541,7 +541,7 @@ module Lutaml
|
|
|
541
541
|
end
|
|
542
542
|
|
|
543
543
|
# Collect namespace_scope configuration from mapping
|
|
544
|
-
if mapping.
|
|
544
|
+
if mapping.is_a?(Lutaml::Xml::Mapping) && mapping.namespace_scope_config&.any?
|
|
545
545
|
mapping.namespace_scope_config.each do |cfg|
|
|
546
546
|
config = NamespaceScopeConfig.new(cfg[:namespace],
|
|
547
547
|
cfg[:declare] || :auto)
|
|
@@ -573,7 +573,7 @@ module Lutaml
|
|
|
573
573
|
@register
|
|
574
574
|
end
|
|
575
575
|
child_type = attr_def.type(child_register)
|
|
576
|
-
if child_type.
|
|
576
|
+
if child_type.is_a?(Class) && child_type < Lutaml::Model::Serialize
|
|
577
577
|
child_mapping = child_type.mappings_for(:xml)
|
|
578
578
|
if child_mapping
|
|
579
579
|
# Recursively collect with child's mapping and register context
|
|
@@ -131,7 +131,7 @@ module Lutaml
|
|
|
131
131
|
#
|
|
132
132
|
# @return [Symbol] :qualified or :unqualified
|
|
133
133
|
def element_form_default
|
|
134
|
-
if @ns_object.
|
|
134
|
+
if @ns_object.is_a?(Class) && @ns_object < Lutaml::Xml::Namespace
|
|
135
135
|
@ns_object.element_form_default
|
|
136
136
|
else
|
|
137
137
|
:qualified # W3C default
|
|
@@ -142,7 +142,7 @@ module Lutaml
|
|
|
142
142
|
#
|
|
143
143
|
# @return [Symbol] :qualified or :unqualified
|
|
144
144
|
def attribute_form_default
|
|
145
|
-
if @ns_object.
|
|
145
|
+
if @ns_object.is_a?(Class) && @ns_object < Lutaml::Xml::Namespace
|
|
146
146
|
@ns_object.attribute_form_default
|
|
147
147
|
else
|
|
148
148
|
:unqualified # W3C default
|
|
@@ -94,7 +94,7 @@ module Lutaml
|
|
|
94
94
|
# Get element_form_default setting
|
|
95
95
|
# @return [Symbol] :qualified or :unqualified
|
|
96
96
|
def element_form_default
|
|
97
|
-
if @namespace_class.
|
|
97
|
+
if @namespace_class.is_a?(Class) && @namespace_class < Lutaml::Xml::Namespace
|
|
98
98
|
@namespace_class.element_form_default
|
|
99
99
|
else
|
|
100
100
|
:qualified # W3C default
|
|
@@ -104,7 +104,7 @@ module Lutaml
|
|
|
104
104
|
# Get attribute_form_default setting
|
|
105
105
|
# @return [Symbol] :qualified or :unqualified
|
|
106
106
|
def attribute_form_default
|
|
107
|
-
if @namespace_class.
|
|
107
|
+
if @namespace_class.is_a?(Class) && @namespace_class < Lutaml::Xml::Namespace
|
|
108
108
|
@namespace_class.attribute_form_default
|
|
109
109
|
else
|
|
110
110
|
:unqualified # W3C default
|
|
@@ -169,12 +169,9 @@ module Lutaml
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
# Validate that namespace class has required methods
|
|
172
|
-
unless @namespace_class.
|
|
173
|
-
raise ArgumentError,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
unless @namespace_class.respond_to?(:to_key)
|
|
177
|
-
raise ArgumentError, "Namespace class must respond to :to_key"
|
|
172
|
+
unless @namespace_class.is_a?(Class) && @namespace_class < Lutaml::Xml::Namespace
|
|
173
|
+
raise ArgumentError,
|
|
174
|
+
"Namespace class must be a Lutaml::Xml::Namespace subclass"
|
|
178
175
|
end
|
|
179
176
|
end
|
|
180
177
|
end
|
|
@@ -100,8 +100,9 @@ module Lutaml
|
|
|
100
100
|
raise ArgumentError, "Namespace class cannot be nil"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
unless @namespace_class.
|
|
104
|
-
raise ArgumentError,
|
|
103
|
+
unless @namespace_class.is_a?(Class) && @namespace_class < Lutaml::Xml::Namespace
|
|
104
|
+
raise ArgumentError,
|
|
105
|
+
"Namespace class must be a Lutaml::Xml::Namespace subclass"
|
|
105
106
|
end
|
|
106
107
|
end
|
|
107
108
|
end
|
|
@@ -58,7 +58,7 @@ module Lutaml
|
|
|
58
58
|
# @example Find all types in a namespace
|
|
59
59
|
# types = resolver.resolve_types_by_namespace("http://example.com/ns")
|
|
60
60
|
def resolve_types_by_namespace(uri)
|
|
61
|
-
return [] unless context.
|
|
61
|
+
return [] unless context.is_a?(Lutaml::Model::TypeContext)
|
|
62
62
|
|
|
63
63
|
context.registry.types.select do |_name, type_class|
|
|
64
64
|
next false unless type_class <= Lutaml::Model::Type::Value
|
|
@@ -92,7 +92,7 @@ module Lutaml
|
|
|
92
92
|
type_ns = type_class.namespace_class
|
|
93
93
|
return nil unless type_ns
|
|
94
94
|
|
|
95
|
-
type_ns.
|
|
95
|
+
type_ns.is_a?(Class) && type_ns < Lutaml::Xml::Namespace ? type_ns.uri : nil
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
private
|
|
@@ -125,8 +125,8 @@ module Lutaml
|
|
|
125
125
|
return true if ns1 == ns2
|
|
126
126
|
|
|
127
127
|
# Compare by URI if both have it
|
|
128
|
-
uri1 = ns1.
|
|
129
|
-
uri2 = ns2.
|
|
128
|
+
uri1 = ns1.is_a?(Class) && ns1 < Lutaml::Xml::Namespace ? ns1.uri : nil
|
|
129
|
+
uri2 = ns2.is_a?(Class) && ns2 < Lutaml::Xml::Namespace ? ns2.uri : nil
|
|
130
130
|
|
|
131
131
|
uri1 && uri2 && uri1 == uri2
|
|
132
132
|
end
|
|
@@ -4,7 +4,7 @@ module Lutaml
|
|
|
4
4
|
module Xml
|
|
5
5
|
class NokogiriElement < AdapterElement
|
|
6
6
|
def initialize(node, parent: nil, default_namespace: nil)
|
|
7
|
-
@raw_text = node.
|
|
7
|
+
@raw_text = node.raw_content if node.is_a?(Moxml::Text)
|
|
8
8
|
super
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -27,7 +27,7 @@ module Lutaml
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def attribute_value_for_build(attr)
|
|
30
|
-
attr.
|
|
30
|
+
attr.raw_value
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
end
|
|
@@ -23,7 +23,7 @@ module Lutaml
|
|
|
23
23
|
# @return [Boolean] true if value should use polymorphic serialization
|
|
24
24
|
def polymorphic_value?(attribute, value)
|
|
25
25
|
return false unless attribute
|
|
26
|
-
return false unless value
|
|
26
|
+
return false unless value
|
|
27
27
|
|
|
28
28
|
# Check if attribute explicitly declares polymorphism
|
|
29
29
|
return true if attribute.options[:polymorphic] || attribute.polymorphic?
|
|
@@ -84,13 +84,13 @@ module Lutaml
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def min_occurrences
|
|
87
|
-
return unless
|
|
87
|
+
return unless is_a?(Element) || is_a?(Group) || is_a?(Any)
|
|
88
88
|
|
|
89
89
|
@min_occurs&.to_i || 1
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
def max_occurrences
|
|
93
|
-
return unless
|
|
93
|
+
return unless is_a?(Element) || is_a?(Group) || is_a?(Any)
|
|
94
94
|
return "*" if @max_occurs == "unbounded"
|
|
95
95
|
|
|
96
96
|
@max_occurs&.to_i || 1
|
|
@@ -106,13 +106,13 @@ module Lutaml
|
|
|
106
106
|
|
|
107
107
|
seen[self] = true
|
|
108
108
|
resolved_element_order&.each do |element|
|
|
109
|
-
if element.
|
|
109
|
+
if element.is_a?(Element) && element.ref
|
|
110
110
|
if resolvable_reference?(element.ref)
|
|
111
111
|
element.referenced_object&.unresolvable_items(array, seen)
|
|
112
112
|
else
|
|
113
113
|
array << element
|
|
114
114
|
end
|
|
115
|
-
elsif element.
|
|
115
|
+
elsif element.is_a?(Base)
|
|
116
116
|
element.unresolvable_items(array, seen)
|
|
117
117
|
end
|
|
118
118
|
end
|
|
@@ -174,7 +174,7 @@ module Lutaml
|
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
def find_object_for_ref(reference)
|
|
177
|
-
if
|
|
177
|
+
if is_a?(Element) || is_a?(Group) || is_a?(AttributeGroup) || is_a?(Attribute) || is_a?(ExtensionComplexContent)
|
|
178
178
|
referenced_object
|
|
179
179
|
else
|
|
180
180
|
find_object(collection_for_reference(reference), reference)
|
|
@@ -196,14 +196,14 @@ module Lutaml
|
|
|
196
196
|
next unless element == instance
|
|
197
197
|
|
|
198
198
|
method_name = ::Lutaml::Model::Utils.snake_case(instance.name)
|
|
199
|
-
array[i] = Array(
|
|
199
|
+
array[i] = Array(public_send(method_name))[index]
|
|
200
200
|
index += 1
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
|
|
204
204
|
def assign_root_value!(value, root, seen)
|
|
205
205
|
Array(value).each do |child|
|
|
206
|
-
next unless child.
|
|
206
|
+
next unless child.is_a?(Base)
|
|
207
207
|
|
|
208
208
|
child_root = child.is_a?(Schema) ? child : root
|
|
209
209
|
child.assign_root!(child_root, seen)
|