Class: Lutaml::Xml::Decisions::DecisionContext

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/xml/decisions/decision_context.rb

Overview

Immutable value object containing all context needed for decisions

This is the ONLY source of truth for decision-making context. All decision rules read from this context, never from external state.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(element:, mapping:, needs:, options: {}, is_root: false, parent_format: nil, parent_namespace_class: nil, parent_namespace_prefix: nil, parent_hoisted: {}, element_used_prefix: nil) ⇒ DecisionContext

Returns a new instance of DecisionContext.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 25

def initialize(element:, mapping:, needs:, options: {},
               is_root: false,
               parent_format: nil,
               parent_namespace_class: nil,
               parent_namespace_prefix: nil,
               parent_hoisted: {},
               element_used_prefix: nil)
  @element = element
  @mapping = mapping
  @needs = needs
  @options = options
  @is_root = is_root
  @parent_format = parent_format
  @parent_namespace_class = parent_namespace_class
  @parent_namespace_prefix = parent_namespace_prefix
  @parent_hoisted = parent_hoisted || {}
  @element_used_prefix = element_used_prefix

  # Extract namespace info from element
  @namespace_class = element&.namespace_class
  @namespace_uri = @namespace_class&.uri
  @namespace_key = @namespace_class&.to_key

  freeze
end

Instance Attribute Details

#elementObject (readonly)

Returns the value of attribute element.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def element
  @element
end

#element_used_prefixObject (readonly)

Returns the value of attribute element_used_prefix.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def element_used_prefix
  @element_used_prefix
end

#is_rootObject (readonly)

Returns the value of attribute is_root.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def is_root
  @is_root
end

#mappingObject (readonly)

Returns the value of attribute mapping.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def mapping
  @mapping
end

#namespace_classObject (readonly)

Returns the value of attribute namespace_class.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def namespace_class
  @namespace_class
end

#namespace_keyObject (readonly)

Returns the value of attribute namespace_key.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def namespace_key
  @namespace_key
end

#namespace_uriObject (readonly)

Returns the value of attribute namespace_uri.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def namespace_uri
  @namespace_uri
end

#needsObject (readonly)

Returns the value of attribute needs.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def needs
  @needs
end

#optionsObject (readonly)

Returns the value of attribute options.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def options
  @options
end

#parent_formatObject (readonly)

Returns the value of attribute parent_format.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def parent_format
  @parent_format
end

#parent_hoistedObject (readonly)

Returns the value of attribute parent_hoisted.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def parent_hoisted
  @parent_hoisted
end

#parent_namespace_classObject (readonly)

Returns the value of attribute parent_namespace_class.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def parent_namespace_class
  @parent_namespace_class
end

#parent_namespace_prefixObject (readonly)

Returns the value of attribute parent_namespace_prefix.



11
12
13
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 11

def parent_namespace_prefix
  @parent_namespace_prefix
end

Instance Method Details

#element_namespace_prefixObject

Get the namespace prefix from the element Works for both Lutaml::Xml::XmlElement (from parsed XML) and DataModel::XmlElement (from serialization transform)

For DataModel::XmlElement, first checks @__xml_namespace_prefix. If not set, falls back to checking @__original_xml_element which preserves the original Lutaml::Xml::XmlElement wrapper from parsing.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 128

def element_namespace_prefix
  return nil unless @element

  if @element.is_a?(Lutaml::Xml::XmlElement)
    @element.namespace_prefix if @element.respond_to?(:namespace_prefix)
  else
    # For DataModel::XmlElement, check xml_namespace_prefix first
    prefix = @element.xml_namespace_prefix
    return prefix if prefix && !prefix.empty?

    # Fall back to original XmlElement wrapper if available
    original = @element.original_xml_element
    if original.respond_to?(:namespace_prefix)
      return original.namespace_prefix
    end

    nil
  end
end

#explicit_prefix_optionObject

Check if explicit prefix option is set NOTE: serialize.rb converts :prefix to :use_prefix, so we check that



150
151
152
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 150

def explicit_prefix_option
  @options[:use_prefix]
end

#has_namespace?Boolean

Check if element has a namespace

Returns:

  • (Boolean)


57
58
59
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 57

def has_namespace?
  !@namespace_class.nil?
end

#has_type_namespaces?Boolean

Check if there are Type namespaces that need prefix format Type namespaces are declared on parent and used by child elements

Returns:

  • (Boolean)


206
207
208
209
210
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 206

def has_type_namespaces?
  return false unless @needs

  @needs.type_refs.any?
end

#hoisted_on_parent?Boolean

Check if namespace is hoisted on parent Accounts for URI aliases: parent may have declared an alias URI while the namespace class uses the canonical URI (or vice versa).

Returns:

  • (Boolean)


177
178
179
180
181
182
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 177

def hoisted_on_parent?
  return false unless @namespace_uri

  all_uris = namespace_all_uris
  @parent_hoisted.any? { |_prefix, uri| all_uris.include?(uri) }
end

#hoisted_prefix_on_parentObject

Get the prefix that was hoisted on parent Accounts for URI aliases when matching.



186
187
188
189
190
191
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 186

def hoisted_prefix_on_parent
  return nil unless @namespace_uri

  all_uris = namespace_all_uris
  @parent_hoisted.find { |_prefix, uri| all_uris.include?(uri) }&.first
end

#namespace_matches_parent_default?Boolean

Check if element’s namespace matches parent’s default namespace This handles the case where parent has xmlns=“uri” and child is in that namespace Accounts for URI aliases when matching.

Returns:

  • (Boolean)


196
197
198
199
200
201
202
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 196

def namespace_matches_parent_default?
  return false unless @namespace_uri
  return false unless @parent_hoisted.key?(nil)

  all_uris = namespace_all_uris
  all_uris.include?(@parent_hoisted[nil])
end

#namespace_scope_configObject

Check if namespace is in namespace_scope



155
156
157
158
159
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 155

def namespace_scope_config
  return nil unless @namespace_class

  @needs.scope_config_for(@namespace_class)
end

#namespace_usageObject

Get namespace usage for this element’s namespace



62
63
64
65
66
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 62

def namespace_usage
  return nil unless @namespace_key

  @needs.namespace(@namespace_key)
end

#parent_uses_default_format?Boolean

Check if parent uses default format

Returns:

  • (Boolean)


162
163
164
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 162

def parent_uses_default_format?
  @parent_format == :default
end

#preserved_input_formatObject

Check if input format is preserved for this namespace

Checks both:

  1. input_formats - namespace-level format (root-level namespaces)

  2. input_prefix_formats - per-prefix format (for child element namespaces)

NOTE: Only check input_prefix_formats when the element has an explicit prefix. If the element has no prefix (namespace inherited or default), use input_formats.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 88

def preserved_input_format
  return nil unless @namespace_uri
  return nil unless @options[:input_formats]

  # First try namespace-level format (root-level)
  format = @options[:input_formats][@namespace_uri]
  return format if format

  # Fall back to per-prefix format ONLY if this element has an explicit prefix.
  # This handles the case where a child element declares its own namespace
  # with a specific prefix (e.g., <xhtml:div xmlns:xhtml="...">).
  # If the element has no explicit prefix, the namespace was either inherited
  # from parent or declared at root level, so we should use input_formats.
  prefix = element_namespace_prefix
  return nil unless prefix && !prefix.empty?

  # Look up input_prefix_formats directly from stored plan
  input_prefix_formats = @options[:stored_xml_declaration_plan]&.input_prefix_formats
  return nil unless input_prefix_formats

  # Look up prefix:uri format, trying all URIs (canonical + aliases)
  # This handles the case where input XML used an alias URI but the model
  # uses canonical URI (or vice versa).
  all_uris = @namespace_class&.all_uris || [@namespace_uri]
  all_uris.each do |uri|
    key = "#{prefix}:#{uri}"
    format = input_prefix_formats[key]
    return format if format
  end

  nil
end

#root?Boolean

Check if this is the root element

Returns:

  • (Boolean)


52
53
54
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 52

def root?
  @is_root
end

#same_namespace_as_parent?Boolean

Check if element is in same namespace as parent

Returns:

  • (Boolean)


167
168
169
170
171
172
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 167

def same_namespace_as_parent?
  return false unless @namespace_class
  return false unless @parent_namespace_class

  @namespace_key == @parent_namespace_class.to_key
end

#used_in_attributes?Boolean

Check if namespace is used in attributes

Returns:

  • (Boolean)


69
70
71
72
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 69

def used_in_attributes?
  usage = namespace_usage
  usage&.used_in_attributes?
end

#used_in_elements?Boolean

Check if namespace is used in elements

Returns:

  • (Boolean)


75
76
77
78
# File 'lib/lutaml/xml/decisions/decision_context.rb', line 75

def used_in_elements?
  usage = namespace_usage
  usage&.used_in_elements?
end