Class: Lutaml::Xml::NamespaceCollector
- Inherits:
-
Object
- Object
- Lutaml::Xml::NamespaceCollector
- Defined in:
- lib/lutaml/xml/namespace_collector.rb
Overview
Phase 1: Bottom-Up Collection
Walks the model tree from leaves to root, collecting namespace needs. This provides full tree knowledge before any declaration decisions are made.
CRITICAL ARCHITECTURAL PRINCIPLE: XmlNamespace CLASS is the atomic unit of namespace configuration. Never track URI and prefix separately - they are inseparable.
REFACTORED (Session 176): Returns NamespaceNeeds object instead of schema-less hash Uses NamespaceUsage, TypeNamespace::Reference, NamespaceScopeConfig objects
Instance Method Summary collapse
-
#all_namespaces(needs) ⇒ Set<Class>
Get all unique namespaces that need declaration.
-
#collect(element, mapping, visited: nil) ⇒ NamespaceNeeds
Collect namespace needs for an element and its descendants.
-
#collect_collection(collection, mapping) ⇒ NamespaceNeeds
Collect namespace needs for a collection of instances.
-
#initialize(register = nil) ⇒ NamespaceCollector
constructor
Initialize collector with register for type resolution.
-
#namespace_used?(needs, namespace_class) ⇒ Boolean
Check if a namespace is used in descendants.
-
#needs_prefix?(needs, mapping) ⇒ Boolean
Check if namespace needs require prefix for root element.
Constructor Details
#initialize(register = nil) ⇒ NamespaceCollector
Initialize collector with register for type resolution
26 27 28 29 30 31 32 |
# File 'lib/lutaml/xml/namespace_collector.rb', line 26 def initialize(register = nil) @register = register || Lutaml::Model::Config.default_register # VISITED TYPE TRACKING # Thread-local call stack for circular reference detection Thread.current[:namespace_collector_call_stack] ||= [] end |
Instance Method Details
#all_namespaces(needs) ⇒ Set<Class>
Get all unique namespaces that need declaration
108 109 110 |
# File 'lib/lutaml/xml/namespace_collector.rb', line 108 def all_namespaces(needs) needs.all_namespace_classes end |
#collect(element, mapping, visited: nil) ⇒ NamespaceNeeds
Collect namespace needs for an element and its descendants
40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/lutaml/xml/namespace_collector.rb', line 40 def collect(element, mapping, visited: nil, **) # If this is a top-level call (no visited yet), ensure cleanup if visited.nil? Thread.current[:namespace_collector_call_stack] = [] begin collect_internal(element, mapping, visited: nil, **) ensure Thread.current[:namespace_collector_call_stack] = nil end else # Nested call - don't clean up yet collect_internal(element, mapping, visited: visited, **) end end |
#collect_collection(collection, mapping) ⇒ NamespaceNeeds
Collect namespace needs for a collection of instances
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/lutaml/xml/namespace_collector.rb', line 60 def collect_collection(collection, mapping) needs = collect(nil, mapping) # If collection has instances, collect needs from instance type if collection.respond_to?(:instances) && mapping.respond_to?(:find_element) instance_rule = mapping.find_element(:instances) || mapping.elements.first if instance_rule attr_def = collection.class.attributes[instance_rule.to] if attr_def instance_type = attr_def.type(@register) if instance_type.respond_to?(:<) && instance_type < Lutaml::Model::Serialize instance_mapping = instance_type.mappings_for(:xml) if instance_mapping instance_needs = collect(nil, instance_mapping) needs.merge(instance_needs) end end end end end needs end |
#namespace_used?(needs, namespace_class) ⇒ Boolean
Check if a namespace is used in descendants
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/lutaml/xml/namespace_collector.rb', line 117 def namespace_used?(needs, namespace_class) validate_namespace_class(namespace_class) # Look up by string key key = namespace_class.to_key return true if needs.namespace(key) needs.children.each_value do |child_needs| return true if namespace_used?(child_needs, namespace_class) end false end |
#needs_prefix?(needs, mapping) ⇒ Boolean
Check if namespace needs require prefix for root element
This implements the W3C rule: if any XML attributes are in the same namespace as the root element, the root must use a prefix.
95 96 97 98 99 100 101 102 |
# File 'lib/lutaml/xml/namespace_collector.rb', line 95 def needs_prefix?(needs, mapping) return false unless mapping.namespace_class # Look up by string key key = mapping.namespace_class.to_key usage = needs.namespace(key) usage&.used_in_attributes? end |