Class: OM::XML::DynamicNode
- Inherits:
-
Object
- Object
- OM::XML::DynamicNode
- Defined in:
- lib/om/xml/dynamic_node.rb
Overview
Provides a natural syntax for using OM Terminologies to access values from xml Documents
Note: All of these examples assume that @article is an instance of OM::Samples::ModsArticle. Look at that file to see the Terminology.
Defined Under Namespace
Classes: AddressedNode
Instance Attribute Summary collapse
-
#addressed_node ⇒ Object
Returns the value of attribute addressed_node.
-
#index ⇒ Object
Returns the value of attribute index.
-
#key ⇒ Object
Returns the value of attribute key.
-
#parent ⇒ Object
Returns the value of attribute parent.
-
#term ⇒ Object
Returns the value of attribute term.
Instance Method Summary collapse
- #!=(other) ⇒ Object
- #==(other) ⇒ Object
- #delete ⇒ Object
- #eql?(other) ⇒ Boolean
-
#initialize(key, index, document, term, parent = nil) ⇒ DynamicNode
constructor
TODO a real term object in here would make it easier to lookup.
- #inspect ⇒ Object
- #method_missing(name, *args, &block) ⇒ Object
- #nodeset ⇒ Object
-
#respond_to_missing?(name, include_private = false) ⇒ Boolean
In practice, method_missing will respond 4 different ways: (1) ALL assignment operations are accepted/attempted as new nodes, (2) ANY operation with multiple arguments is accepted/attempted as a new node (w/ index), (3) With an auto-constructed sub DynamicNode object, (4) By handing off to val.
-
#retrieve_addressed_node ⇒ Object
This is very similar to Terminology#retrieve_term, however it expands proxy paths out into their cannonical paths.
- #to_pointer ⇒ Object
-
#val ⇒ Array
This resolves the target of this dynamic node into a reified Array.
- #val=(args) ⇒ Object
- #xpath ⇒ Object
Constructor Details
#initialize(key, index, document, term, parent = nil) ⇒ DynamicNode
TODO a real term object in here would make it easier to lookup
33 34 35 36 37 38 39 |
# File 'lib/om/xml/dynamic_node.rb', line 33 def initialize(key, index, document, term, parent=nil) ##TODO a real term object in here would make it easier to lookup self.key = key self.index = index @document = document self.term = term self.parent = parent end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/om/xml/dynamic_node.rb', line 52 def method_missing(name, *args, &block) return new_update_node(name.to_s.chop.to_sym, nil, args) if /=$/.match(name.to_s) return new_update_node(name, args.shift, args) if args.length > 1 child = term_child_by_name(term.nil? ? parent.term : term, name) return OM::XML::DynamicNode.new(name, args.first, @document, child, self) if child val.send(name, *args, &block) end |
Instance Attribute Details
#addressed_node ⇒ Object
Returns the value of attribute addressed_node.
32 33 34 |
# File 'lib/om/xml/dynamic_node.rb', line 32 def addressed_node @addressed_node end |
#index ⇒ Object
Returns the value of attribute index.
32 33 34 |
# File 'lib/om/xml/dynamic_node.rb', line 32 def index @index end |
#key ⇒ Object
Returns the value of attribute key.
32 33 34 |
# File 'lib/om/xml/dynamic_node.rb', line 32 def key @key end |
#parent ⇒ Object
Returns the value of attribute parent.
32 33 34 |
# File 'lib/om/xml/dynamic_node.rb', line 32 def parent @parent end |
#term ⇒ Object
Returns the value of attribute term.
32 33 34 |
# File 'lib/om/xml/dynamic_node.rb', line 32 def term @term end |
Instance Method Details
#!=(other) ⇒ Object
112 113 114 |
# File 'lib/om/xml/dynamic_node.rb', line 112 def !=(other) val != other end |
#==(other) ⇒ Object
108 109 110 |
# File 'lib/om/xml/dynamic_node.rb', line 108 def ==(other) other == val end |
#delete ⇒ Object
100 101 102 |
# File 'lib/om/xml/dynamic_node.rb', line 100 def delete nodeset.delete end |
#eql?(other) ⇒ Boolean
116 117 118 |
# File 'lib/om/xml/dynamic_node.rb', line 116 def eql?(other) self == other end |
#inspect ⇒ Object
104 105 106 |
# File 'lib/om/xml/dynamic_node.rb', line 104 def inspect val.inspect end |
#nodeset ⇒ Object
94 95 96 97 98 |
# File 'lib/om/xml/dynamic_node.rb', line 94 def nodeset query = xpath trim_text = !query.index("text()").nil? return @document.find_by_xpath(query) end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
In practice, method_missing will respond 4 different ways: (1) ALL assignment operations are accepted/attempted as new nodes, (2) ANY operation with multiple arguments is accepted/attempted as a new node (w/ index), (3) With an auto-constructed sub DynamicNode object, (4) By handing off to val. This is the only route that will return NoMethodError.
Here we don’t have args, so we cannot handle cases 2 and 3. But we can at least do 1 and 4.
48 49 50 |
# File 'lib/om/xml/dynamic_node.rb', line 48 def respond_to_missing?(name, include_private = false) /=$/.match(name.to_s) || val.respond_to?(name, include_private) || super end |
#retrieve_addressed_node ⇒ Object
This is very similar to Terminology#retrieve_term, however it expands proxy paths out into their cannonical paths
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/om/xml/dynamic_node.rb', line 148 def retrieve_addressed_node() chain = [] chain += parent.retrieve_addressed_node() if parent if (self.index) ### This is an index node = AddressedNode.new(key, term.xpath_relative, self) node.xpath = OM::XML::TermXpathGenerator.add_node_index_predicate(node.xpath, index) chain << node elsif (term.kind_of? NamedTermProxy) proxy = term.proxy_pointer.dup first = proxy.shift p = @document.class.terminology.retrieve_node(*first) chain << AddressedNode.new(p, p.xpath_relative, self) while !proxy.empty? first = proxy.shift p = p.retrieve_term(first) chain << AddressedNode.new(p, p.xpath_relative, self) end else chain << AddressedNode.new(key, term.xpath_relative, self) end chain end |
#to_pointer ⇒ Object
120 121 122 123 124 125 126 |
# File 'lib/om/xml/dynamic_node.rb', line 120 def to_pointer if self.index parent.nil? ? [{key => index}] : parent.to_pointer << {key => index} else ### A pointer parent.nil? ? [key] : parent.to_pointer << key end end |
#val ⇒ Array
This resolves the target of this dynamic node into a reified Array
87 88 89 90 91 92 |
# File 'lib/om/xml/dynamic_node.rb', line 87 def val query = xpath trim_text = !query.index("text()").nil? val = @document.find_by_xpath(query).collect {|node| (trim_text ? node.text.strip : node.text) } term.deserialize(val) end |
#val=(args) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/om/xml/dynamic_node.rb', line 60 def val=(args) @document.ng_xml_will_change! new_values = term.sanitize_new_values(args.first) existing_nodes = @document.find_by_xpath(xpath) if existing_nodes.length > new_values.length starting_index = new_values.length + 1 starting_index.upto(existing_nodes.size).each do |index| @document.term_value_delete select: xpath, child_index: index end end new_values.each_with_index do |z, y| ## If we pass something that already has an index on it, we should be able to add it. if existing_nodes[y.to_i].nil? parent_pointer = if parent parent.to_pointer elsif term.is_a? NamedTermProxy term.proxy_pointer[0..-2] end @document.term_values_append(:parent_select=> parent_pointer,:parent_index=>0,:template=>to_pointer,:values=>z) else @document.term_value_update(xpath, y.to_i, z) end end end |
#xpath ⇒ Object
128 129 130 131 132 133 134 135 |
# File 'lib/om/xml/dynamic_node.rb', line 128 def xpath if parent.nil? @document.class.terminology.xpath_with_indexes(*(to_pointer << {})) ### last element is always filters else chain = retrieve_addressed_node( ) '//' + chain.map { |n| n.xpath}.join('/') end end |