om 1.8.1 → 1.9.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/container_spec.rb +14 -14
- data/lib/om.rb +12 -9
- 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 +33 -31
- data/lib/om/xml/container.rb +12 -12
- data/lib/om/xml/document.rb +19 -18
- data/lib/om/xml/dynamic_node.rb +50 -45
- 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 +26 -18
- data/lib/om/xml/term.rb +46 -30
- data/lib/om/xml/term_value_operators.rb +56 -52
- data/lib/om/xml/term_xpath_generator.rb +57 -51
- data/lib/om/xml/terminology.rb +10 -8
- data/lib/om/xml/terminology_based_solrizer.rb +90 -0
- data/lib/om/xml/validation.rb +19 -19
- data/lib/om/xml/vocabulary.rb +4 -4
- data/lib/tasks/om.rake +6 -4
- data/om.gemspec +2 -1
- data/spec/fixtures/mods_article.rb +90 -0
- data/spec/fixtures/mods_articles/hydrangea_article1.xml +2 -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 +18 -24
- 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 +10 -10
- data/spec/integration/xpathy_stuff_spec.rb +16 -16
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/container_spec.rb +29 -28
- data/spec/unit/document_spec.rb +50 -49
- data/spec/unit/dynamic_node_spec.rb +45 -57
- 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 +73 -79
- data/spec/unit/term_value_operators_spec.rb +191 -186
- data/spec/unit/term_xpath_generator_spec.rb +43 -37
- 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 +22 -21
- data/spec/unit/xml_spec.rb +7 -7
- data/spec/unit/xml_terminology_based_solrizer_spec.rb +109 -0
- metadata +57 -17
- checksums.yaml +0 -7
- data/.rspec +0 -1
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +0 -382
- data/.travis.yml +0 -10
- data/gemfiles/gemfile.rails3 +0 -11
- data/gemfiles/gemfile.rails4 +0 -10
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,23 +38,33 @@ module OM
|
|
38
38
|
self.parent = parent
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
def method_missing (name, *args, &block)
|
42
|
+
if /=$/.match(name.to_s)
|
43
|
+
new_update_node(name, args)
|
44
|
+
elsif args.length > 1
|
45
|
+
new_update_node_with_index(name, args)
|
46
|
+
else
|
47
|
+
child = term_child_by_name(term.nil? ? parent.term : term, name)
|
48
|
+
if child
|
49
|
+
OM::XML::DynamicNode.new(name, args.first, @document, child, self)
|
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
|
50
61
|
end
|
51
62
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
val.send(name, *args, &block)
|
63
|
+
def new_update_node_with_index(name, args)
|
64
|
+
index = args.shift
|
65
|
+
child = term.retrieve_term(name)
|
66
|
+
node = OM::XML::DynamicNode.new(name, index, @document, child, self)
|
67
|
+
node.val=args
|
58
68
|
end
|
59
69
|
|
60
70
|
def val=(args)
|
@@ -72,7 +82,16 @@ module OM
|
|
72
82
|
end
|
73
83
|
end
|
74
84
|
|
75
|
-
|
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
|
76
95
|
query = xpath
|
77
96
|
trim_text = !query.index("text()").nil?
|
78
97
|
val = @document.find_by_xpath(query).collect {|node| (trim_text ? node.text.strip : node.text) }
|
@@ -82,13 +101,13 @@ module OM
|
|
82
101
|
def nodeset
|
83
102
|
query = xpath
|
84
103
|
trim_text = !query.index("text()").nil?
|
85
|
-
@document.find_by_xpath(query)
|
104
|
+
return @document.find_by_xpath(query)
|
86
105
|
end
|
87
106
|
|
88
107
|
def delete
|
89
108
|
nodeset.delete
|
90
109
|
end
|
91
|
-
|
110
|
+
|
92
111
|
def inspect
|
93
112
|
val.inspect
|
94
113
|
end
|
@@ -107,7 +126,7 @@ module OM
|
|
107
126
|
else ### A pointer
|
108
127
|
parent.nil? ? [key] : parent.to_pointer << key
|
109
128
|
end
|
110
|
-
end
|
129
|
+
end
|
111
130
|
|
112
131
|
def xpath
|
113
132
|
if parent.nil?
|
@@ -116,8 +135,10 @@ module OM
|
|
116
135
|
chain = retrieve_addressed_node( )
|
117
136
|
'//' + chain.map { |n| n.xpath}.join('/')
|
118
137
|
end
|
138
|
+
|
119
139
|
end
|
120
140
|
|
141
|
+
|
121
142
|
class AddressedNode
|
122
143
|
attr_accessor :xpath, :key, :pointer
|
123
144
|
def initialize (pointer, xpath, key)
|
@@ -126,12 +147,15 @@ module OM
|
|
126
147
|
self.pointer = pointer
|
127
148
|
end
|
128
149
|
end
|
129
|
-
|
150
|
+
|
130
151
|
##
|
131
152
|
# This is very similar to Terminology#retrieve_term, however it expands proxy paths out into their cannonical paths
|
132
153
|
def retrieve_addressed_node()
|
133
154
|
chain = []
|
134
|
-
|
155
|
+
|
156
|
+
if parent
|
157
|
+
chain += parent.retrieve_addressed_node()
|
158
|
+
end
|
135
159
|
if (self.index)
|
136
160
|
### This is an index
|
137
161
|
node = AddressedNode.new(key, term.xpath_relative, self)
|
@@ -142,36 +166,17 @@ module OM
|
|
142
166
|
first = proxy.shift
|
143
167
|
p = @document.class.terminology.retrieve_node(*first)
|
144
168
|
chain << AddressedNode.new(p, p.xpath_relative, self)
|
145
|
-
|
169
|
+
while !proxy.empty?
|
146
170
|
first = proxy.shift
|
147
171
|
p = p.retrieve_term(first)
|
148
172
|
chain << AddressedNode.new(p, p.xpath_relative, self)
|
149
173
|
end
|
150
|
-
else
|
174
|
+
else
|
151
175
|
chain << AddressedNode.new(key, term.xpath_relative, self)
|
152
176
|
end
|
153
177
|
chain
|
154
178
|
end
|
155
179
|
|
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
|
175
180
|
|
176
181
|
end
|
177
182
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class OM::XML::NamedTermProxy
|
2
|
-
|
2
|
+
|
3
3
|
attr_accessor :proxy_pointer, :name, :terminology
|
4
|
-
|
4
|
+
|
5
5
|
include OM::TreeNode
|
6
|
-
|
6
|
+
|
7
7
|
# Creates a Named Proxy that points to another term in the Terminology.
|
8
8
|
# Unlike regular terms, NamedTermProxy requires you to provide a reference to the containing Terminology.
|
9
9
|
# This is to ensure that it will always be able to look up the term that it's referencing.
|
@@ -14,13 +14,13 @@ class OM::XML::NamedTermProxy
|
|
14
14
|
def initialize(name, proxy_pointer, terminology, opts={})
|
15
15
|
opts = {:namespace_prefix=>"oxns", :ancestors=>[], :children=>{}}.merge(opts)
|
16
16
|
[:children, :ancestors, :index_as].each do |accessor_name|
|
17
|
-
instance_variable_set("@#{accessor_name}", opts.fetch(accessor_name, nil) )
|
17
|
+
instance_variable_set("@#{accessor_name}", opts.fetch(accessor_name, nil) )
|
18
18
|
end
|
19
19
|
@terminology = terminology
|
20
20
|
@name = name
|
21
21
|
@proxy_pointer = proxy_pointer
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def proxied_term
|
25
25
|
if self.parent.nil?
|
26
26
|
pt = self.terminology.retrieve_term(*self.proxy_pointer)
|
@@ -33,18 +33,18 @@ class OM::XML::NamedTermProxy
|
|
33
33
|
return pt
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
# do nothing -- this is to prevent errors when the parent term calls generate_xpath_queries! on its children
|
38
38
|
def generate_xpath_queries!
|
39
39
|
# do nothing
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
# A proxy term can never serve as the root term of a Terminology.
|
43
43
|
# Explicitly setting is_root_term? to return false to support proxies that are _at_ the root of the Terminology but aren't _the_ root term.
|
44
44
|
def is_root_term?
|
45
|
-
false
|
45
|
+
return false
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
##
|
49
49
|
# Always co-erce :index_as attributes into an Array
|
50
50
|
def index_as
|
@@ -54,10 +54,10 @@ class OM::XML::NamedTermProxy
|
|
54
54
|
self.proxied_term.index_as
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
# Any unknown method calls will be proxied to the proxied term
|
59
|
-
def method_missing method, *args, &block
|
60
|
-
self.proxied_term.send(method, *args)
|
59
|
+
def method_missing method, *args, &block
|
60
|
+
return self.proxied_term.send(method, *args)
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module OM::XML::NodeGenerator
|
2
|
-
|
2
|
+
|
3
3
|
# Module Methods -- These methods can be called directly on the Module itself
|
4
4
|
# @param OM::XML::Term term The term to generate a node based on
|
5
5
|
# @param String builder_new_value The new value to insert into the generated node
|
@@ -14,8 +14,8 @@ module OM::XML::NodeGenerator
|
|
14
14
|
builder = Nokogiri::XML::Builder.new do |xml|
|
15
15
|
eval( builder_call_body )
|
16
16
|
end
|
17
|
-
|
18
|
-
builder.doc
|
17
|
+
|
18
|
+
return builder.doc
|
19
19
|
end
|
20
20
|
|
21
21
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
# Extend an OM::XML::Document with reusable templates, then use them to add content to
|
1
|
+
# Extend an OM::XML::Document with reusable templates, then use them to add content to
|
2
2
|
# instance documents.
|
3
3
|
#
|
4
4
|
# Example:
|
5
5
|
#
|
6
6
|
# require 'om/samples/mods_article'
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# class OM::Samples::ModsArticle
|
9
9
|
# define_template :personalName do |xml, family, given, address|
|
10
10
|
# xml.name(:type => 'personal') do
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# xml.namePart(:type => 'termsOfAddress') { xml.text(address) }
|
14
14
|
# end
|
15
15
|
# end
|
16
|
-
#
|
16
|
+
#
|
17
17
|
# define_template :role do |xml, text, attrs|
|
18
18
|
# xml.role do
|
19
19
|
# attrs = { :type => 'text' }.merge(attrs)
|
@@ -21,9 +21,9 @@
|
|
21
21
|
# end
|
22
22
|
# end
|
23
23
|
# end
|
24
|
-
#
|
24
|
+
#
|
25
25
|
# mods = OM::Samples::ModsArticle.from_xml(File.read('./spec/fixtures/CBF_MODS/ARS0025_016.xml'))
|
26
|
-
#
|
26
|
+
#
|
27
27
|
# mods.add_previous_sibling_node([:person => 0], :personalName, 'Shmoe', 'Joseph', 'Dr.') { |person|
|
28
28
|
# person.add_child(mods.template(:role, 'author', :authority => 'marcrelator'))
|
29
29
|
# person.add_child(mods.template(:role, 'sub', :authority => 'local', :type => 'code'))
|
@@ -44,7 +44,7 @@ class OM::XML::TemplateRegistry
|
|
44
44
|
unless node_type.is_a?(Symbol)
|
45
45
|
raise TypeError, "Registered node type must be a Symbol (e.g., :person)"
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
@templates[node_type] = block
|
49
49
|
node_type
|
50
50
|
end
|
@@ -77,9 +77,11 @@ class OM::XML::TemplateRegistry
|
|
77
77
|
result = create_detached_node(nil, node_type, *args)
|
78
78
|
# Strip namespaces from text and CDATA nodes. Stupid Nokogiri.
|
79
79
|
result.traverse { |node|
|
80
|
-
|
80
|
+
if node.is_a?(Nokogiri::XML::CharacterData)
|
81
|
+
node.namespace = nil
|
82
|
+
end
|
81
83
|
}
|
82
|
-
result
|
84
|
+
return result
|
83
85
|
end
|
84
86
|
|
85
87
|
# +instantiate+ a node and add it as a child of the [Nokogiri::XML::Node] specified by +target_node+
|
@@ -123,7 +125,7 @@ class OM::XML::TemplateRegistry
|
|
123
125
|
def swap(target_node, node_type, *args, &block)
|
124
126
|
attach_node(:swap, target_node, :parent, node_type, *args, &block)
|
125
127
|
end
|
126
|
-
|
128
|
+
|
127
129
|
def methods
|
128
130
|
super + @templates.keys.collect { |k| k.to_s }
|
129
131
|
end
|
@@ -138,7 +140,7 @@ class OM::XML::TemplateRegistry
|
|
138
140
|
end
|
139
141
|
|
140
142
|
private
|
141
|
-
|
143
|
+
|
142
144
|
# Create a new Nokogiri::XML::Node based on the template for +node_type+
|
143
145
|
#
|
144
146
|
# @param [Nokogiri::XML::Node] builder_node The node to use as starting point for building the node using Nokogiri::XML::Builder.with(builder_node). This provides namespace info, etc for constructing the new Node object. If nil, defaults to {OM::XML::TemplateRegistry#empty_root_node}. This is just used to create the new node and will not be included in the response.
|
@@ -146,9 +148,13 @@ class OM::XML::TemplateRegistry
|
|
146
148
|
# @param [Array] args any additional args
|
147
149
|
def create_detached_node(builder_node, node_type, *args)
|
148
150
|
proc = @templates[node_type]
|
149
|
-
|
150
|
-
|
151
|
-
|
151
|
+
if proc.nil?
|
152
|
+
raise NameError, "Unknown node type: #{node_type.to_s}"
|
153
|
+
end
|
154
|
+
if builder_node.nil?
|
155
|
+
builder_node = empty_root_node
|
156
|
+
end
|
157
|
+
|
152
158
|
builder = Nokogiri::XML::Builder.with(builder_node) do |xml|
|
153
159
|
proc.call(xml,*args)
|
154
160
|
end
|
@@ -159,11 +165,11 @@ class OM::XML::TemplateRegistry
|
|
159
165
|
#
|
160
166
|
# @param [Symbol] method name that should be called on +target_node+, usually a Nokogiri::XML::Node instance method
|
161
167
|
# @param [Nokogiri::XML::Node or Nokogiri::XML::NodeSet with only one Node in it] target_node
|
162
|
-
# @param [Symbol] builder_node_offset Indicates node to use as the starting point for _constructing_ the new node using {OM::XML::TemplateRegistry#create_detached_node}. If this is set to :parent, target_node.parent will be used. Otherwise, target_node will be used.
|
168
|
+
# @param [Symbol] builder_node_offset Indicates node to use as the starting point for _constructing_ the new node using {OM::XML::TemplateRegistry#create_detached_node}. If this is set to :parent, target_node.parent will be used. Otherwise, target_node will be used.
|
163
169
|
# @param node_type
|
164
170
|
# @param [Array] args any additional arguments for creating the node
|
165
171
|
def attach_node(method, target_node, builder_node_offset, node_type, *args, &block)
|
166
|
-
if target_node.is_a?(Nokogiri::XML::NodeSet)
|
172
|
+
if target_node.is_a?(Nokogiri::XML::NodeSet) and target_node.length == 1
|
167
173
|
target_node = target_node.first
|
168
174
|
end
|
169
175
|
builder_node = builder_node_offset == :parent ? target_node.parent : target_node
|
@@ -171,7 +177,9 @@ class OM::XML::TemplateRegistry
|
|
171
177
|
result = target_node.send(method, new_node)
|
172
178
|
# Strip namespaces from text and CDATA nodes. Stupid Nokogiri.
|
173
179
|
new_node.traverse { |node|
|
174
|
-
|
180
|
+
if node.is_a?(Nokogiri::XML::CharacterData)
|
181
|
+
node.namespace = nil
|
182
|
+
end
|
175
183
|
}
|
176
184
|
if block_given?
|
177
185
|
yield result
|
@@ -179,9 +187,9 @@ class OM::XML::TemplateRegistry
|
|
179
187
|
return result
|
180
188
|
end
|
181
189
|
end
|
182
|
-
|
190
|
+
|
183
191
|
def empty_root_node
|
184
192
|
Nokogiri::XML('<root/>').root
|
185
193
|
end
|
186
|
-
|
194
|
+
|
187
195
|
end
|
data/lib/om/xml/term.rb
CHANGED
@@ -56,14 +56,16 @@ class OM::XML::Term
|
|
56
56
|
trail = ""
|
57
57
|
nodes_visited.each_with_index do |node, z|
|
58
58
|
trail << node.name.inspect
|
59
|
-
|
59
|
+
unless z == nodes_visited.length-1
|
60
|
+
trail << " => "
|
61
|
+
end
|
60
62
|
end
|
61
63
|
raise OM::XML::Terminology::CircularReferenceError, "Circular reference in Terminology: #{trail}"
|
62
64
|
end
|
63
65
|
result << target
|
64
66
|
result.concat( target.lookup_refs(nodes_visited << self) )
|
65
67
|
end
|
66
|
-
result
|
68
|
+
return result
|
67
69
|
end
|
68
70
|
|
69
71
|
# If a :ref value has been set, looks up the target of that ref and merges the target's settings & children with the current builder's settings & children
|
@@ -79,7 +81,7 @@ class OM::XML::Term
|
|
79
81
|
@settings[:path] = name_of_last_ref.to_s
|
80
82
|
end
|
81
83
|
@settings.delete :ref
|
82
|
-
self
|
84
|
+
return self
|
83
85
|
end
|
84
86
|
|
85
87
|
# Returns a new Hash that merges +downstream_hash+ with +upstream_hash+
|
@@ -94,7 +96,7 @@ class OM::XML::Term
|
|
94
96
|
up.delete(setting_name)
|
95
97
|
end
|
96
98
|
end
|
97
|
-
up.merge(dn)
|
99
|
+
return up.merge(dn)
|
98
100
|
end
|
99
101
|
|
100
102
|
# Builds a new OM::XML::Term based on the Builder object's current settings
|
@@ -119,29 +121,31 @@ class OM::XML::Term
|
|
119
121
|
term.generate_xpath_queries!
|
120
122
|
end
|
121
123
|
|
122
|
-
term
|
124
|
+
return term
|
123
125
|
end
|
124
126
|
|
125
127
|
# :data_type accessor has been deprecated in favor of :type
|
126
128
|
# Any value set for :data_type will get set for :type instead
|
127
129
|
def data_type value
|
128
130
|
@settings[:type] = value
|
129
|
-
self
|
131
|
+
return self
|
130
132
|
end
|
131
133
|
deprecation_deprecate :data_type
|
132
134
|
|
133
135
|
# We have to add this method so it will play nice with ruby 1.8.7
|
134
136
|
def type value
|
135
137
|
@settings[:type] = value
|
136
|
-
self
|
138
|
+
return self
|
137
139
|
end
|
138
140
|
|
139
141
|
|
140
142
|
# Any unknown method calls will add an entry to the settings hash and return the current object
|
141
143
|
def method_missing method, *args, &block
|
142
|
-
|
144
|
+
if args.length == 1
|
145
|
+
args = args.first
|
146
|
+
end
|
143
147
|
@settings[method] = args
|
144
|
-
self
|
148
|
+
return self
|
145
149
|
end
|
146
150
|
end
|
147
151
|
|
@@ -193,9 +197,9 @@ class OM::XML::Term
|
|
193
197
|
# @param name [Symbol] the name to refer to this term by
|
194
198
|
# @param opts [Hash]
|
195
199
|
# @options opts [Array] :index_as a list of indexing hints provided to to_solr
|
196
|
-
# @options opts [String] :path partial xpath that points to the node.
|
197
|
-
# @options opts [Hash] :attributes xml attributes to match in the selector
|
198
|
-
# @options opts [String] :namespace_prefix xml namespace for this node
|
200
|
+
# @options opts [String] :path partial xpath that points to the node.
|
201
|
+
# @options opts [Hash] :attributes xml attributes to match in the selector
|
202
|
+
# @options opts [String] :namespace_prefix xml namespace for this node
|
199
203
|
# @options opts [Symbol] :type one of :string, :date, :integer. Defaults to :string
|
200
204
|
def initialize(name, opts={}, terminology=nil)
|
201
205
|
opts = {:ancestors=>[], :children=>{}}.merge(opts)
|
@@ -207,11 +211,15 @@ class OM::XML::Term
|
|
207
211
|
|
208
212
|
unless terminology.nil?
|
209
213
|
if opts[:namespace_prefix].nil?
|
210
|
-
|
214
|
+
unless terminology.namespaces["xmlns"].nil?
|
215
|
+
@namespace_prefix = "oxns"
|
216
|
+
end
|
211
217
|
end
|
212
218
|
end
|
213
219
|
@name = name
|
214
|
-
|
220
|
+
if @path.nil? || @path.empty?
|
221
|
+
@path = name.to_s
|
222
|
+
end
|
215
223
|
end
|
216
224
|
|
217
225
|
|
@@ -229,7 +237,7 @@ class OM::XML::Term
|
|
229
237
|
end
|
230
238
|
new_values
|
231
239
|
end
|
232
|
-
|
240
|
+
|
233
241
|
# @param val [String,Date,Integer]
|
234
242
|
def serialize (val)
|
235
243
|
case type
|
@@ -237,7 +245,7 @@ class OM::XML::Term
|
|
237
245
|
val.to_s
|
238
246
|
when :boolean
|
239
247
|
val.to_s
|
240
|
-
else
|
248
|
+
else
|
241
249
|
val
|
242
250
|
end
|
243
251
|
end
|
@@ -247,14 +255,14 @@ class OM::XML::Term
|
|
247
255
|
def deserialize(val)
|
248
256
|
case type
|
249
257
|
when :date
|
250
|
-
#
|
258
|
+
#TODO use present?
|
251
259
|
val.map { |v| !v.empty? ? Date.parse(v) : nil}
|
252
260
|
when :integer
|
253
|
-
#
|
261
|
+
#TODO use blank?
|
254
262
|
val.map { |v| v.empty? ? nil : v.to_i}
|
255
263
|
when :boolean
|
256
264
|
val.map { |v| v == 'true' }
|
257
|
-
else
|
265
|
+
else
|
258
266
|
val
|
259
267
|
end
|
260
268
|
end
|
@@ -279,7 +287,7 @@ class OM::XML::Term
|
|
279
287
|
new_mapper.add_child(child)
|
280
288
|
end
|
281
289
|
|
282
|
-
new_mapper
|
290
|
+
return new_mapper
|
283
291
|
end
|
284
292
|
|
285
293
|
##
|
@@ -304,7 +312,7 @@ class OM::XML::Term
|
|
304
312
|
return nil
|
305
313
|
end
|
306
314
|
end
|
307
|
-
target
|
315
|
+
return target
|
308
316
|
end
|
309
317
|
|
310
318
|
def is_root_term?
|
@@ -328,7 +336,7 @@ class OM::XML::Term
|
|
328
336
|
else
|
329
337
|
node_options = ["\':::builder_new_value:::\'"]
|
330
338
|
end
|
331
|
-
|
339
|
+
if !self.attributes.nil?
|
332
340
|
self.attributes.merge(extra_attributes).each_pair do |k,v|
|
333
341
|
node_options << "\'#{k}\'=>\'#{v}\'" unless v == :none
|
334
342
|
end
|
@@ -338,7 +346,7 @@ class OM::XML::Term
|
|
338
346
|
if builder_method.include?(":")
|
339
347
|
builder_ref = "xml['#{self.path[0..path.index(":")-1]}']"
|
340
348
|
builder_method = self.path[path.index(":")+1..-1]
|
341
|
-
elsif !self.namespace_prefix.nil?
|
349
|
+
elsif !self.namespace_prefix.nil? and self.namespace_prefix != 'oxns'
|
342
350
|
builder_ref = "xml['#{self.namespace_prefix}']"
|
343
351
|
elsif self.path.kind_of?(Hash) && self.path[:attribute]
|
344
352
|
builder_method = "@#{self.path[:attribute]}"
|
@@ -347,7 +355,7 @@ class OM::XML::Term
|
|
347
355
|
builder_method += "_"
|
348
356
|
end
|
349
357
|
template = "#{builder_ref}.#{builder_method}( #{OM::XML.delimited_list(node_options)} )" + node_child_template
|
350
|
-
template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }
|
358
|
+
return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }
|
351
359
|
end
|
352
360
|
|
353
361
|
# Generates absolute, relative, and constrained xpaths for the term, setting xpath, xpath_relative, and xpath_constrained accordingly.
|
@@ -357,7 +365,7 @@ class OM::XML::Term
|
|
357
365
|
self.xpath_constrained = OM::XML::TermXpathGenerator.generate_constrained_xpath(self)
|
358
366
|
self.xpath_relative = OM::XML::TermXpathGenerator.generate_relative_xpath(self)
|
359
367
|
self.children.each_value {|child| child.generate_xpath_queries! }
|
360
|
-
self
|
368
|
+
return self
|
361
369
|
end
|
362
370
|
|
363
371
|
# Return an XML representation of the Term
|
@@ -372,7 +380,9 @@ class OM::XML::Term
|
|
372
380
|
def to_xml(options={}, document=Nokogiri::XML::Document.new)
|
373
381
|
builder = Nokogiri::XML::Builder.with(document) do |xml|
|
374
382
|
xml.term(:name=>name) {
|
375
|
-
|
383
|
+
if is_root_term?
|
384
|
+
xml.is_root_term("true")
|
385
|
+
end
|
376
386
|
xml.path path
|
377
387
|
xml.namespace_prefix namespace_prefix
|
378
388
|
unless attributes.nil? || attributes.empty?
|
@@ -383,11 +393,15 @@ class OM::XML::Term
|
|
383
393
|
}
|
384
394
|
end
|
385
395
|
xml.index_as {
|
386
|
-
|
396
|
+
unless index_as.nil?
|
397
|
+
index_as.each { |index_type| xml.index_type }
|
398
|
+
end
|
387
399
|
}
|
388
400
|
xml.required required
|
389
401
|
xml.data_type type
|
390
|
-
|
402
|
+
unless variant_of.nil?
|
403
|
+
xml.variant_of variant_of
|
404
|
+
end
|
391
405
|
unless default_content_path.nil?
|
392
406
|
xml.default_content_path default_content_path
|
393
407
|
end
|
@@ -396,14 +410,16 @@ class OM::XML::Term
|
|
396
410
|
xml.absolute xpath
|
397
411
|
xml.constrained xpath_constrained
|
398
412
|
}
|
399
|
-
|
413
|
+
if options.fetch(:children, true)
|
414
|
+
xml.children
|
415
|
+
end
|
400
416
|
}
|
401
417
|
end
|
402
418
|
doc = builder.doc
|
403
419
|
if options.fetch(:children, true)
|
404
420
|
children.values.each {|child| child.to_xml(options, doc.xpath("//term[@name=\"#{name}\"]/children").first)}
|
405
421
|
end
|
406
|
-
doc
|
422
|
+
return doc
|
407
423
|
end
|
408
424
|
|
409
425
|
# private :update_xpath_values
|