Class: Lutaml::KeyValue::DataModel::Element

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/key_value/data_model/element.rb

Overview

Represents a key-value element for JSON, YAML, TOML formats.

This class provides an intermediate representation for key-value data structures, separating content (what to serialize) from presentation (how to serialize).

Unlike Hash, Element is an explicit OOP model that can:

  • Track metadata about value types

  • Support transformation logic

  • Maintain clear separation of concerns

  • Enable format-specific optimizations

Examples:

Simple key-value

element = Element.new("name", "John")
element.to_hash
# => {"name" => "John"}

Nested structure

parent = Element.new("person")
parent.add_child(Element.new("name", "John"))
parent.add_child(Element.new("age", 30))
parent.to_hash
# => {"person" => {"name" => "John", "age" => 30}}

Array values

element = Element.new("items")
element.add_child("apple")
element.add_child("banana")
element.to_hash
# => {"items" => ["apple", "banana"]}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, value = nil) ⇒ Element

Initialize a new key-value element

Parameters:

  • key (String, Symbol)

    The key name

  • value (Object, nil) (defaults to: nil)

    Optional direct value



50
51
52
53
54
# File 'lib/lutaml/key_value/data_model/element.rb', line 50

def initialize(key, value = nil)
  @key = key.to_s
  @value = value
  @children = []
end

Instance Attribute Details

#childrenArray<Element, Object> (readonly)

Returns Child elements.

Returns:

  • (Array<Element, Object>)

    Child elements



44
45
46
# File 'lib/lutaml/key_value/data_model/element.rb', line 44

def children
  @children
end

#keyString (readonly)

Returns Key name.

Returns:

  • (String)

    Key name



38
39
40
# File 'lib/lutaml/key_value/data_model/element.rb', line 38

def key
  @key
end

#valueObject?

Returns Direct value (for leaf nodes).

Returns:

  • (Object, nil)

    Direct value (for leaf nodes)



41
42
43
# File 'lib/lutaml/key_value/data_model/element.rb', line 41

def value
  @value
end

Instance Method Details

#[](key) ⇒ Object

Hash-like access for backward compatibility

Allows Element to be used like a hash in tests and existing code. Converts to hash first, then accesses the key.

Parameters:

  • key (String, Symbol)

    Key to access

Returns:

  • (Object)

    Value for the key



131
132
133
134
135
136
137
138
139
140
# File 'lib/lutaml/key_value/data_model/element.rb', line 131

def [](key)
  hash = to_hash
  # If this is the root element, access the inner hash
  if @key == "__root__" && hash.key?("__root__")
    inner = hash["__root__"]
    inner.is_a?(Hash) ? inner[key.to_s] : nil
  else
    hash[key.to_s]
  end
end

#[]=(key, value) ⇒ Object

Hash-like assignment for backward compatibility

Allows Element to be used like a hash in tests and existing code. Creates a new child Element for the key-value pair.

Parameters:

  • key (String, Symbol)

    Key to set

  • value (Object)

    Value to set

Returns:

  • (Object)

    The assigned value



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/lutaml/key_value/data_model/element.rb', line 150

def []=(key, value)
  # For root element, add child with the key-value pair
  if @key == "__root__"
    # Remove existing child with same key if any
    @children.reject! do |child|
      child.is_a?(Element) && child.key == key.to_s
    end
    # Add new child
  else
    # For non-root elements, convert to hash and merge
    # This shouldn't normally happen in the transformation flow
  end
  @children << Element.new(key.to_s, value)
  value
end

#add_child(child) ⇒ self

Add a child element or value

This supports building nested structures and arrays.

Parameters:

  • child (Element, Object)

    Child to add

Returns:

  • (self)


62
63
64
65
# File 'lib/lutaml/key_value/data_model/element.rb', line 62

def add_child(child)
  @children << child
  self
end

#has_children?Boolean

Check if element has children

Returns:

  • (Boolean)


70
71
72
# File 'lib/lutaml/key_value/data_model/element.rb', line 70

def has_children?
  !@children.empty?
end

#has_value?Boolean

Check if element has a direct value

Returns:

  • (Boolean)


77
78
79
# File 'lib/lutaml/key_value/data_model/element.rb', line 77

def has_value?
  !@value.nil?
end

#inspectString

Detailed inspection for debugging

Returns:

  • (String)


169
170
171
# File 'lib/lutaml/key_value/data_model/element.rb', line 169

def inspect
  to_s
end

#leaf?Boolean

Check if this is a leaf node (has value, no children)

Returns:

  • (Boolean)


84
85
86
# File 'lib/lutaml/key_value/data_model/element.rb', line 84

def leaf?
  has_value? && !has_children?
end

#to_hashHash

Convert to Hash representation

This is the primary method for adapter rendering. The conversion logic follows these rules:

  1. If has direct value and no children: => value

  2. If has children that are all Elements: => merged_hash

  3. If has children that are mixed/primitives: => array

  4. If has both value and children: children take precedence

  5. Special case: __root__ with no children returns empty hash (for omitted attributes)

Returns:

  • (Hash)


99
100
101
102
103
104
105
106
107
108
109
# File 'lib/lutaml/key_value/data_model/element.rb', line 99

def to_hash
  if has_children?
    { @key => children_to_value }
  elsif has_value?
    { @key => @value }
  else
    # Special case: __root__ element should return empty hash when all attributes omitted
    # This allows hash["__root__"].keys to work without raising NoMethodError
    { @key => (@key == "__root__" ? {} : nil) }
  end
end

#to_sString

String representation for debugging

Returns:

  • (String)


114
115
116
117
118
119
120
121
122
# File 'lib/lutaml/key_value/data_model/element.rb', line 114

def to_s
  if leaf?
    "<Element key=#{@key.inspect} value=#{@value.inspect}>"
  elsif has_children?
    "<Element key=#{@key.inspect} children=#{@children.length}>"
  else
    "<Element key=#{@key.inspect}>"
  end
end