om 1.8.1 → 1.9.0.pre1
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.
- 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
|