om 1.8.0 → 1.8.1
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 +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +382 -0
- data/.travis.yml +10 -0
- data/Rakefile +1 -1
- data/container_spec.rb +14 -14
- data/gemfiles/gemfile.rails3 +11 -0
- data/gemfiles/gemfile.rails4 +10 -0
- data/lib/om.rb +9 -12
- data/lib/om/samples/mods_article.rb +9 -9
- data/lib/om/tree_node.rb +6 -6
- data/lib/om/version.rb +1 -1
- data/lib/om/xml.rb +18 -20
- data/lib/om/xml/container.rb +12 -12
- data/lib/om/xml/document.rb +3 -7
- data/lib/om/xml/dynamic_node.rb +45 -50
- data/lib/om/xml/named_term_proxy.rb +13 -13
- data/lib/om/xml/node_generator.rb +3 -3
- data/lib/om/xml/template_registry.rb +18 -26
- data/lib/om/xml/term.rb +30 -46
- data/lib/om/xml/term_value_operators.rb +52 -56
- data/lib/om/xml/term_xpath_generator.rb +51 -57
- data/lib/om/xml/terminology.rb +8 -10
- data/lib/om/xml/validation.rb +19 -19
- data/lib/om/xml/vocabulary.rb +4 -4
- data/lib/tasks/om.rake +4 -6
- data/om.gemspec +1 -2
- data/spec/integration/differentiated_elements_spec.rb +2 -2
- data/spec/integration/element_value_spec.rb +13 -13
- data/spec/integration/proxies_and_ref_spec.rb +15 -15
- data/spec/integration/querying_documents_spec.rb +24 -18
- data/spec/integration/rights_metadata_integration_example_spec.rb +18 -18
- data/spec/integration/selective_querying_spec.rb +1 -1
- data/spec/integration/serialization_spec.rb +13 -13
- data/spec/integration/set_reentrant_terminology_spec.rb +7 -7
- data/spec/integration/xpathy_stuff_spec.rb +16 -16
- data/spec/spec_helper.rb +2 -3
- data/spec/unit/container_spec.rb +28 -29
- data/spec/unit/document_spec.rb +49 -50
- data/spec/unit/dynamic_node_spec.rb +55 -47
- data/spec/unit/named_term_proxy_spec.rb +16 -16
- data/spec/unit/node_generator_spec.rb +7 -7
- data/spec/unit/nokogiri_sanity_spec.rb +30 -30
- data/spec/unit/om_spec.rb +5 -5
- data/spec/unit/template_registry_spec.rb +69 -69
- data/spec/unit/term_builder_spec.rb +77 -77
- data/spec/unit/term_spec.rb +78 -72
- data/spec/unit/term_value_operators_spec.rb +186 -191
- data/spec/unit/term_xpath_generator_spec.rb +37 -43
- data/spec/unit/terminology_builder_spec.rb +85 -85
- data/spec/unit/terminology_spec.rb +98 -98
- data/spec/unit/validation_spec.rb +22 -22
- data/spec/unit/xml_serialization_spec.rb +21 -22
- data/spec/unit/xml_spec.rb +7 -7
- metadata +143 -147
data/lib/om.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
3
|
-
require 'active_model/dirty'
|
2
|
+
require 'active_model'
|
4
3
|
require 'deprecation'
|
5
4
|
require 'nokogiri'
|
6
5
|
|
@@ -10,7 +9,7 @@ module OM
|
|
10
9
|
# Converts [{":person"=>"0"}, ":last_name"] to [{:person=>0}, :last_name]
|
11
10
|
def self.destringify(params)
|
12
11
|
case params
|
13
|
-
when String
|
12
|
+
when String
|
14
13
|
if params == "0" || params.to_i != 0
|
15
14
|
result = params.to_i
|
16
15
|
elsif params[0,1] == ":"
|
@@ -19,13 +18,13 @@ module OM
|
|
19
18
|
result = params.to_sym
|
20
19
|
end
|
21
20
|
return result
|
22
|
-
when Hash
|
21
|
+
when Hash
|
23
22
|
result = {}
|
24
23
|
params.each_pair do |k,v|
|
25
24
|
result[ destringify(k) ] = destringify(v)
|
26
25
|
end
|
27
26
|
return result
|
28
|
-
when Array
|
27
|
+
when Array
|
29
28
|
result = []
|
30
29
|
params.each do |x|
|
31
30
|
result << destringify(x)
|
@@ -35,31 +34,29 @@ module OM
|
|
35
34
|
return params
|
36
35
|
end
|
37
36
|
end
|
38
|
-
|
37
|
+
|
39
38
|
# Convert a Term pointer into a flat array without Hashes.
|
40
39
|
# If include_indices is set to false, node indices will be removed.
|
41
40
|
#
|
42
41
|
# @param [Array] pointers array that you would pass into other Accessor methods
|
43
42
|
# @param [Boolean] include_indices (default: true) if set to false, parent indices will be excluded from the array
|
44
43
|
# @example Turn a pointer into a flat array with node indices preserved
|
45
|
-
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text] )
|
44
|
+
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text] )
|
46
45
|
# => [:conference, 0, :role, 1, :text]
|
47
46
|
# @example Remove node indices by setting include_indices to false
|
48
|
-
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text], false )
|
47
|
+
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text], false )
|
49
48
|
# => [:conference, :role, :text]
|
50
49
|
def self.pointers_to_flat_array(pointers, include_indices=true)
|
51
50
|
flat_array = []
|
52
51
|
pointers.each do |pointer|
|
53
52
|
if pointer.kind_of?(Hash)
|
54
53
|
flat_array << pointer.keys.first
|
55
|
-
if include_indices
|
56
|
-
flat_array << pointer.values.first
|
57
|
-
end
|
54
|
+
flat_array << pointer.values.first if include_indices
|
58
55
|
else
|
59
56
|
flat_array << pointer
|
60
57
|
end
|
61
58
|
end
|
62
|
-
|
59
|
+
flat_array
|
63
60
|
end
|
64
61
|
|
65
62
|
def self.version
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class OM::Samples::ModsArticle
|
2
|
-
|
2
|
+
|
3
3
|
include OM::XML::Document
|
4
|
-
|
4
|
+
|
5
5
|
set_terminology do |t|
|
6
6
|
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd", "xmlns:foo"=>"http://my.custom.namespace")
|
7
7
|
|
@@ -11,17 +11,17 @@ class OM::Samples::ModsArticle
|
|
11
11
|
t.main_title_lang(:path=>{:attribute=> "xml:lang"})
|
12
12
|
}
|
13
13
|
t.french_title(:ref=>[:title_info,:main_title], :attributes=>{"xml:lang"=>"fre"})
|
14
|
-
|
14
|
+
|
15
15
|
t.language(:index_as=>[:facetable],:path=>{:attribute=>"lang"})
|
16
|
-
}
|
16
|
+
}
|
17
17
|
t.language{
|
18
18
|
t.lang_code(:index_as=>[:facetable], :path=>"languageTerm", :attributes=>{:type=>"code"})
|
19
19
|
}
|
20
|
-
t.abstract
|
20
|
+
t.abstract
|
21
21
|
t.subject {
|
22
22
|
t.topic(:index_as=>[:facetable])
|
23
|
-
}
|
24
|
-
t.topic_tag(:proxy=>[:subject, :topic])
|
23
|
+
}
|
24
|
+
t.topic_tag(:proxy=>[:subject, :topic])
|
25
25
|
# t.topic_tag(:index_as=>[:facetable],:path=>"subject", :default_content_path=>"topic")
|
26
26
|
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
27
27
|
t.name_ {
|
@@ -40,7 +40,7 @@ class OM::Samples::ModsArticle
|
|
40
40
|
t.computing_id
|
41
41
|
t.name_content(:path=>"text()")
|
42
42
|
}
|
43
|
-
# lookup :person, :first_name
|
43
|
+
# lookup :person, :first_name
|
44
44
|
t.person(:ref=>:name, :attributes=>{:type=>"personal"}, :index_as=>[:facetable])
|
45
45
|
t.department(:proxy=>[:person,:description],:index_as=>[:facetable])
|
46
46
|
t.organization(:ref=>:name, :attributes=>{:type=>"corporate"}, :index_as=>[:facetable])
|
@@ -78,7 +78,7 @@ class OM::Samples::ModsArticle
|
|
78
78
|
t.title(:proxy=>[:title_info, :main_title])
|
79
79
|
t.journal_title(:proxy=>[:journal, :title_info, :main_title])
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
# Changes from OM::Properties implementation
|
83
83
|
# renamed family_name => last_name
|
84
84
|
# start_page & end_page now accessible as [:journal, :issue, :pages, :start] (etc.)
|
data/lib/om/tree_node.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
module OM::TreeNode
|
2
|
-
|
2
|
+
|
3
3
|
attr_accessor :ancestors
|
4
|
-
|
4
|
+
|
5
5
|
# insert the mapper into the given parent
|
6
6
|
def set_parent(parent_mapper)
|
7
7
|
parent_mapper.children[@name] = self
|
8
8
|
@ancestors << parent_mapper
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# insert the given mapper into the current mappers children
|
12
12
|
def add_child(child_mapper)
|
13
13
|
child_mapper.ancestors << self
|
14
|
-
@children[child_mapper.name.to_sym] = child_mapper
|
14
|
+
@children[child_mapper.name.to_sym] = child_mapper
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def retrieve_child(child_name)
|
18
18
|
child = @children.fetch(child_name, nil)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def parent
|
22
22
|
ancestors.last
|
23
23
|
end
|
data/lib/om/version.rb
CHANGED
data/lib/om/xml.rb
CHANGED
@@ -13,46 +13,44 @@ require "om/xml/dynamic_node"
|
|
13
13
|
require "om/xml/template_registry"
|
14
14
|
|
15
15
|
module OM::XML
|
16
|
-
|
16
|
+
|
17
17
|
# Raised when the XML document or XML template can't be found during an operation
|
18
18
|
class TemplateMissingException < StandardError; end
|
19
|
-
|
19
|
+
|
20
20
|
attr_accessor :ng_xml
|
21
|
-
|
21
|
+
|
22
22
|
# Module Methods -- These methods can be called directly on the Module itself
|
23
|
-
|
23
|
+
|
24
24
|
# Transforms an array of values into a string delimited by +delimiter+
|
25
25
|
def self.delimited_list( values_array, delimiter=", ")
|
26
26
|
values_array.join(delimiter)
|
27
27
|
end
|
28
|
-
|
29
|
-
# Class Methods -- These methods will be available on classes that include this Module
|
30
|
-
|
28
|
+
|
29
|
+
# Class Methods -- These methods will be available on classes that include this Module
|
30
|
+
|
31
31
|
module ClassMethods
|
32
|
-
|
32
|
+
|
33
33
|
# @pointer accessor or property info pointer
|
34
|
-
#
|
34
|
+
#
|
35
35
|
# ex. [[:person,1],:role] will be converted to [{:person=>1},:role]
|
36
|
-
def sanitize_pointer(pointer)
|
37
|
-
if pointer.kind_of?(Array)
|
36
|
+
def sanitize_pointer(pointer)
|
37
|
+
if pointer.kind_of?(Array)
|
38
38
|
pointer.each do |x|
|
39
|
-
if x.kind_of?(Array)
|
40
|
-
pointer[pointer.index(x)] = Hash[x[0],x[1]]
|
41
|
-
end
|
39
|
+
pointer[pointer.index(x)] = Hash[x[0],x[1]] if x.kind_of?(Array)
|
42
40
|
end
|
43
41
|
end
|
44
|
-
|
42
|
+
pointer
|
45
43
|
end
|
46
|
-
|
44
|
+
|
47
45
|
end
|
48
|
-
|
46
|
+
|
49
47
|
# Instance Methods -- These methods will be available on instances of classes that include this module
|
50
|
-
|
48
|
+
|
51
49
|
def self.included(klass)
|
52
50
|
klass.extend(ClassMethods)
|
53
51
|
klass.send(:include, OM::XML::Container)
|
54
52
|
klass.send(:include, OM::XML::Validation)
|
55
53
|
end
|
56
|
-
|
57
|
-
|
54
|
+
|
55
|
+
|
58
56
|
end
|
data/lib/om/xml/container.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module OM::XML::Container
|
2
2
|
extend ActiveSupport::Concern
|
3
|
-
|
3
|
+
|
4
4
|
attr_accessor :ng_xml
|
5
|
-
|
6
|
-
# Class Methods -- These methods will be available on classes that include this Module
|
7
|
-
|
5
|
+
|
6
|
+
# Class Methods -- These methods will be available on classes that include this Module
|
7
|
+
|
8
8
|
module ClassMethods
|
9
|
-
|
9
|
+
|
10
10
|
# @xml String, File or Nokogiri::XML::Node
|
11
11
|
# @tmpl ActiveFedora::MetadataDatastream
|
12
12
|
# Careful! If you call this from a constructor, be sure to provide something 'ie. self' as the @tmpl. Otherwise, you will get an infinite loop!
|
@@ -18,25 +18,25 @@ module OM::XML::Container
|
|
18
18
|
else
|
19
19
|
tmpl.ng_xml = Nokogiri::XML::Document.parse(xml)
|
20
20
|
end
|
21
|
-
|
21
|
+
tmpl
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# By default, new OM Document instances will create an empty xml document, but if you override self.xml_template to return a different object (e.g. Nokogiri::XML::Document), that will be created instead.
|
25
25
|
# You can make this method create the documents however you want as long as it returns a Nokogiri::XML::Document.
|
26
|
-
# In the tutorials, we use Nokogiri::XML::Builder in this mehtod and call its .doc method at the end of xml_template in order to return the Nokogiri::XML::Document object. Instead of using Nokogiri::XML::Builder, you could put your template into an actual xml file and have xml_template use Nokogiri::XML::Document.parse to load it. That’s up to you.
|
26
|
+
# In the tutorials, we use Nokogiri::XML::Builder in this mehtod and call its .doc method at the end of xml_template in order to return the Nokogiri::XML::Document object. Instead of using Nokogiri::XML::Builder, you could put your template into an actual xml file and have xml_template use Nokogiri::XML::Document.parse to load it. That’s up to you.
|
27
27
|
# @return Nokogiri::XML::Document
|
28
28
|
def xml_template
|
29
29
|
Nokogiri::XML::Document.parse("")
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def ng_xml
|
35
35
|
@ng_xml ||= self.class.xml_template
|
36
36
|
end
|
37
37
|
|
38
38
|
# Instance Methods -- These methods will be available on instances of classes that include this module
|
39
|
-
|
39
|
+
|
40
40
|
def to_xml(xml = ng_xml)
|
41
41
|
if xml == ng_xml
|
42
42
|
return xml.to_xml
|
@@ -52,5 +52,5 @@ module OM::XML::Container
|
|
52
52
|
raise "You can only pass instances of Nokogiri::XML::Node into this method. You passed in #{xml}"
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
end
|
data/lib/om/xml/document.rb
CHANGED
@@ -35,7 +35,7 @@ module OM::XML::Document
|
|
35
35
|
self.terminology_builder.extend_terminology(&block)
|
36
36
|
rebuild_terminology!
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# (Explicitly) inherit terminology from upstream classes
|
40
40
|
def use_terminology klass
|
41
41
|
self.terminology_builder = klass.terminology_builder.dup
|
@@ -69,9 +69,7 @@ module OM::XML::Document
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def ng_xml_will_change!
|
72
|
-
if self.respond_to?(:dirty=)
|
73
|
-
self.dirty = true
|
74
|
-
end
|
72
|
+
self.dirty = true if self.respond_to?(:dirty=)
|
75
73
|
|
76
74
|
# throw away older version.
|
77
75
|
changed_attributes['ng_xml'] = nil
|
@@ -196,9 +194,7 @@ module OM::XML::Document
|
|
196
194
|
|
197
195
|
private
|
198
196
|
def manipulate_node(method, target, *args, &block)
|
199
|
-
if target.is_a?(Array)
|
200
|
-
target = self.find_by_terms(*target)
|
201
|
-
end
|
197
|
+
target = self.find_by_terms(*target) if target.is_a?(Array)
|
202
198
|
raise "You must call define_template before calling #{method}" if template_registry.nil?
|
203
199
|
ng_xml_will_change!
|
204
200
|
template_registry.send(method, target, *args, &block)
|
data/lib/om/xml/dynamic_node.rb
CHANGED
@@ -3,8 +3,8 @@ module OM
|
|
3
3
|
#
|
4
4
|
# Provides a natural syntax for using OM Terminologies to access values from xml Documents
|
5
5
|
#
|
6
|
-
# *Note*: All of these examples assume that @article is an instance of OM::Samples::ModsArticle. Look at that file to see the Terminology.
|
7
|
-
#
|
6
|
+
# *Note*: All of these examples assume that @article is an instance of OM::Samples::ModsArticle. Look at that file to see the Terminology.
|
7
|
+
#
|
8
8
|
# @example Return an array of the value(s) "start page" node(s) from the second issue node within the first journal node
|
9
9
|
# # Using DynamicNode syntax:
|
10
10
|
# @article.journal(0).issue(1).pages.start
|
@@ -30,7 +30,7 @@ module OM
|
|
30
30
|
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ }
|
31
31
|
|
32
32
|
attr_accessor :key, :index, :parent, :addressed_node, :term
|
33
|
-
def initialize(key, index, document, term, parent=nil)
|
33
|
+
def initialize(key, index, document, term, parent=nil) # #TODO a real term object in here would make it easier to lookup
|
34
34
|
self.key = key
|
35
35
|
self.index = index
|
36
36
|
@document = document
|
@@ -38,33 +38,23 @@ module OM
|
|
38
38
|
self.parent = parent
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
else
|
51
|
-
val.send(name, *args, &block)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def new_update_node(name, args)
|
57
|
-
modified_name = name.to_s.chop.to_sym
|
58
|
-
child = term.retrieve_term(modified_name)
|
59
|
-
node = OM::XML::DynamicNode.new(modified_name, nil, @document, child, self)
|
60
|
-
node.val=args
|
41
|
+
# In practice, method_missing will respond 4 different ways:
|
42
|
+
# (1) ALL assignment operations are accepted/attempted as new nodes,
|
43
|
+
# (2) ANY operation with multiple arguments is accepted/attempted as a new node (w/ index),
|
44
|
+
# (3) With an auto-constructed sub DynamicNode object,
|
45
|
+
# (4) By handing off to val. This is the only route that will return NoMethodError.
|
46
|
+
#
|
47
|
+
# Here we don't have args, so we cannot handle cases 2 and 3. But we can at least do 1 and 4.
|
48
|
+
def respond_to_missing?(name, include_private = false)
|
49
|
+
/=$/.match(name.to_s) || val.respond_to?(name, include_private) || super
|
61
50
|
end
|
62
51
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
52
|
+
def method_missing(name, *args, &block)
|
53
|
+
return new_update_node(name.to_s.chop.to_sym, nil, args) if /=$/.match(name.to_s)
|
54
|
+
return new_update_node(name, args.shift, args) if args.length > 1
|
55
|
+
child = term_child_by_name(term.nil? ? parent.term : term, name)
|
56
|
+
return OM::XML::DynamicNode.new(name, args.first, @document, child, self) if child
|
57
|
+
val.send(name, *args, &block)
|
68
58
|
end
|
69
59
|
|
70
60
|
def val=(args)
|
@@ -82,16 +72,7 @@ module OM
|
|
82
72
|
end
|
83
73
|
end
|
84
74
|
|
85
|
-
|
86
|
-
def term_child_by_name(term, name)
|
87
|
-
if (term.kind_of? NamedTermProxy)
|
88
|
-
@document.class.terminology.retrieve_node(*(term.proxy_pointer.dup << name))
|
89
|
-
else
|
90
|
-
term.retrieve_term(name)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def val
|
75
|
+
def val
|
95
76
|
query = xpath
|
96
77
|
trim_text = !query.index("text()").nil?
|
97
78
|
val = @document.find_by_xpath(query).collect {|node| (trim_text ? node.text.strip : node.text) }
|
@@ -101,13 +82,13 @@ module OM
|
|
101
82
|
def nodeset
|
102
83
|
query = xpath
|
103
84
|
trim_text = !query.index("text()").nil?
|
104
|
-
|
85
|
+
@document.find_by_xpath(query)
|
105
86
|
end
|
106
87
|
|
107
88
|
def delete
|
108
89
|
nodeset.delete
|
109
90
|
end
|
110
|
-
|
91
|
+
|
111
92
|
def inspect
|
112
93
|
val.inspect
|
113
94
|
end
|
@@ -126,7 +107,7 @@ module OM
|
|
126
107
|
else ### A pointer
|
127
108
|
parent.nil? ? [key] : parent.to_pointer << key
|
128
109
|
end
|
129
|
-
end
|
110
|
+
end
|
130
111
|
|
131
112
|
def xpath
|
132
113
|
if parent.nil?
|
@@ -135,10 +116,8 @@ module OM
|
|
135
116
|
chain = retrieve_addressed_node( )
|
136
117
|
'//' + chain.map { |n| n.xpath}.join('/')
|
137
118
|
end
|
138
|
-
|
139
119
|
end
|
140
120
|
|
141
|
-
|
142
121
|
class AddressedNode
|
143
122
|
attr_accessor :xpath, :key, :pointer
|
144
123
|
def initialize (pointer, xpath, key)
|
@@ -147,15 +126,12 @@ module OM
|
|
147
126
|
self.pointer = pointer
|
148
127
|
end
|
149
128
|
end
|
150
|
-
|
129
|
+
|
151
130
|
##
|
152
131
|
# This is very similar to Terminology#retrieve_term, however it expands proxy paths out into their cannonical paths
|
153
132
|
def retrieve_addressed_node()
|
154
133
|
chain = []
|
155
|
-
|
156
|
-
if parent
|
157
|
-
chain += parent.retrieve_addressed_node()
|
158
|
-
end
|
134
|
+
chain += parent.retrieve_addressed_node() if parent
|
159
135
|
if (self.index)
|
160
136
|
### This is an index
|
161
137
|
node = AddressedNode.new(key, term.xpath_relative, self)
|
@@ -166,17 +142,36 @@ module OM
|
|
166
142
|
first = proxy.shift
|
167
143
|
p = @document.class.terminology.retrieve_node(*first)
|
168
144
|
chain << AddressedNode.new(p, p.xpath_relative, self)
|
169
|
-
|
145
|
+
until proxy.empty?
|
170
146
|
first = proxy.shift
|
171
147
|
p = p.retrieve_term(first)
|
172
148
|
chain << AddressedNode.new(p, p.xpath_relative, self)
|
173
149
|
end
|
174
|
-
else
|
150
|
+
else
|
175
151
|
chain << AddressedNode.new(key, term.xpath_relative, self)
|
176
152
|
end
|
177
153
|
chain
|
178
154
|
end
|
179
155
|
|
156
|
+
private
|
157
|
+
|
158
|
+
# Only to be called by method_missing, hence the NoMethodError.
|
159
|
+
# We know term.sanitize_new_values would fail in .val= if we pass a nil term.
|
160
|
+
def new_update_node(name, index, args)
|
161
|
+
child = term.retrieve_term(name)
|
162
|
+
raise NoMethodError, "undefined method `#{name}' in OM::XML::DynamicNode for #{self}:#{self.class}" if child.nil?
|
163
|
+
node = OM::XML::DynamicNode.new(name, index, @document, child, self)
|
164
|
+
node.val = args
|
165
|
+
end
|
166
|
+
|
167
|
+
# Only to be called by method_missing
|
168
|
+
def term_child_by_name(term, name)
|
169
|
+
if (term.kind_of? NamedTermProxy)
|
170
|
+
@document.class.terminology.retrieve_node(*(term.proxy_pointer.dup << name))
|
171
|
+
else
|
172
|
+
term.retrieve_term(name)
|
173
|
+
end
|
174
|
+
end
|
180
175
|
|
181
176
|
end
|
182
177
|
end
|