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.
Files changed (60) hide show
  1. data/Rakefile +1 -1
  2. data/container_spec.rb +14 -14
  3. data/lib/om.rb +12 -9
  4. data/lib/om/samples/mods_article.rb +9 -9
  5. data/lib/om/tree_node.rb +6 -6
  6. data/lib/om/version.rb +1 -1
  7. data/lib/om/xml.rb +33 -31
  8. data/lib/om/xml/container.rb +12 -12
  9. data/lib/om/xml/document.rb +19 -18
  10. data/lib/om/xml/dynamic_node.rb +50 -45
  11. data/lib/om/xml/named_term_proxy.rb +13 -13
  12. data/lib/om/xml/node_generator.rb +3 -3
  13. data/lib/om/xml/template_registry.rb +26 -18
  14. data/lib/om/xml/term.rb +46 -30
  15. data/lib/om/xml/term_value_operators.rb +56 -52
  16. data/lib/om/xml/term_xpath_generator.rb +57 -51
  17. data/lib/om/xml/terminology.rb +10 -8
  18. data/lib/om/xml/terminology_based_solrizer.rb +90 -0
  19. data/lib/om/xml/validation.rb +19 -19
  20. data/lib/om/xml/vocabulary.rb +4 -4
  21. data/lib/tasks/om.rake +6 -4
  22. data/om.gemspec +2 -1
  23. data/spec/fixtures/mods_article.rb +90 -0
  24. data/spec/fixtures/mods_articles/hydrangea_article1.xml +2 -2
  25. data/spec/integration/differentiated_elements_spec.rb +2 -2
  26. data/spec/integration/element_value_spec.rb +13 -13
  27. data/spec/integration/proxies_and_ref_spec.rb +15 -15
  28. data/spec/integration/querying_documents_spec.rb +18 -24
  29. data/spec/integration/rights_metadata_integration_example_spec.rb +18 -18
  30. data/spec/integration/selective_querying_spec.rb +1 -1
  31. data/spec/integration/serialization_spec.rb +13 -13
  32. data/spec/integration/set_reentrant_terminology_spec.rb +10 -10
  33. data/spec/integration/xpathy_stuff_spec.rb +16 -16
  34. data/spec/spec_helper.rb +2 -2
  35. data/spec/unit/container_spec.rb +29 -28
  36. data/spec/unit/document_spec.rb +50 -49
  37. data/spec/unit/dynamic_node_spec.rb +45 -57
  38. data/spec/unit/named_term_proxy_spec.rb +16 -16
  39. data/spec/unit/node_generator_spec.rb +7 -7
  40. data/spec/unit/nokogiri_sanity_spec.rb +30 -30
  41. data/spec/unit/om_spec.rb +5 -5
  42. data/spec/unit/template_registry_spec.rb +69 -69
  43. data/spec/unit/term_builder_spec.rb +77 -77
  44. data/spec/unit/term_spec.rb +73 -79
  45. data/spec/unit/term_value_operators_spec.rb +191 -186
  46. data/spec/unit/term_xpath_generator_spec.rb +43 -37
  47. data/spec/unit/terminology_builder_spec.rb +85 -85
  48. data/spec/unit/terminology_spec.rb +98 -98
  49. data/spec/unit/validation_spec.rb +22 -22
  50. data/spec/unit/xml_serialization_spec.rb +22 -21
  51. data/spec/unit/xml_spec.rb +7 -7
  52. data/spec/unit/xml_terminology_based_solrizer_spec.rb +109 -0
  53. metadata +57 -17
  54. checksums.yaml +0 -7
  55. data/.rspec +0 -1
  56. data/.rubocop.yml +0 -1
  57. data/.rubocop_todo.yml +0 -382
  58. data/.travis.yml +0 -10
  59. data/gemfiles/gemfile.rails3 +0 -11
  60. data/gemfiles/gemfile.rails4 +0 -10
@@ -3,12 +3,12 @@ require "logger"
3
3
 
4
4
  class OM::XML::ParentNodeNotFoundError < RuntimeError; end
5
5
  module OM::XML::TermValueOperators
6
-
6
+
7
7
  # Retrieves all of the nodes from the current document that match +term_pointer+ and returns an array of their values
8
8
  def term_values(*term_pointer)
9
9
  result = []
10
10
  xpath = self.class.terminology.xpath_with_indexes(*term_pointer)
11
- # if value is on line by itself sometimes does not trim leading and trailing whitespace for a text node so will detect and fix it
11
+ #if value is on line by itself sometimes does not trim leading and trailing whitespace for a text node so will detect and fix it
12
12
  trim_text = !xpath.nil? && !xpath.index("text()").nil?
13
13
  find_by_terms(*term_pointer).each {|node| result << (trim_text ? node.text.strip : node.text) }
14
14
 
@@ -20,59 +20,61 @@ module OM::XML::TermValueOperators
20
20
  term.deserialize(result)
21
21
  end
22
22
  end
23
-
23
+
24
24
  # alias for term_values
25
25
  def property_values(*lookup_args)
26
26
  term_values(*lookup_args)
27
27
  end
28
-
29
- #
28
+
29
+ #
30
30
  # example term values hash: {[{":person"=>"0"}, "role", "text"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, [{:person=>1}, :family_name]=>"Andronicus", [{"person"=>"1"},:given_name]=>["Titus"],[{:person=>1},:role,:text]=>["otherrole1","otherrole2"] }
31
31
  def update_values(params={})
32
- # remove any terms from params that this datastream doesn't recognize
33
-
34
- params.delete_if do |term_pointer,new_values|
32
+ # remove any terms from params that this datastream doesn't recognize
33
+
34
+ params.delete_if do |term_pointer,new_values|
35
35
  if term_pointer.kind_of?(String)
36
36
  true
37
37
  else
38
38
  !self.class.terminology.has_term?(*OM.destringify(term_pointer))
39
39
  end
40
40
  end
41
-
41
+
42
42
  result = params.dup
43
-
43
+
44
44
  params.each_pair do |term_pointer,new_values|
45
45
  pointer = OM.destringify(term_pointer)
46
46
  template_pointer = OM.pointers_to_flat_array(pointer,false)
47
47
  hn = OM::XML::Terminology.term_hierarchical_name(*pointer)
48
-
48
+
49
49
  term = self.class.terminology.retrieve_term( *OM.pointers_to_flat_array(pointer,false) )
50
50
 
51
51
  # Sanitize new_values to always be a hash with indexes
52
52
  new_values = term.sanitize_new_values(new_values)
53
-
53
+
54
54
  # Populate the response hash appropriately, using hierarchical names for terms as keys rather than the given pointers.
55
55
  result.delete(term_pointer)
56
56
  result[hn] = new_values.dup
57
-
57
+
58
58
  # Skip any submitted values if the new value matches the current values
59
59
  current_values = term_values(*pointer)
60
60
  new_values.keys.sort { |a,b| a.to_i <=> b.to_i }.each do |y|
61
61
  z = new_values[y]
62
- new_values.delete(y) if current_values[y.to_i]==z && y.to_i > -1
63
- end
64
-
62
+ if current_values[y.to_i]==z and y.to_i > -1
63
+ new_values.delete(y)
64
+ end
65
+ end
66
+
65
67
  # Fill out the pointer completely if the final term is a NamedTermProxy
66
68
  if term.kind_of? OM::XML::NamedTermProxy
67
69
  pointer.pop
68
70
  pointer = pointer.concat(term.proxy_pointer)
69
71
  end
70
-
72
+
71
73
  xpath = self.class.terminology.xpath_with_indexes(*pointer)
72
74
  parent_pointer = pointer.dup
73
75
  parent_pointer.pop
74
76
  parent_xpath = self.class.terminology.xpath_with_indexes(*parent_pointer)
75
-
77
+
76
78
  # If the value doesn't exist yet, append it. Otherwise, update the existing value.
77
79
  new_values.keys.sort { |a,b| a.to_i <=> b.to_i }.each do |y|
78
80
  z = new_values[y]
@@ -87,18 +89,18 @@ module OM::XML::TermValueOperators
87
89
  end
88
90
  end
89
91
  end
90
- result
92
+ return result
91
93
  end
92
-
94
+
93
95
  def term_values_append(opts={})
94
96
  parent_select = Array( opts[:parent_select] )
95
97
  parent_index = opts[:parent_index]
96
98
  template = opts[:template]
97
- new_values = Array( opts[:values] )
98
-
99
+ new_values = Array( opts[:values] )
100
+
99
101
  parent_nodeset = find_by_terms(*parent_select)
100
102
  parent_node = node_from_set(parent_nodeset, parent_index)
101
-
103
+
102
104
  if parent_node.nil?
103
105
  if parent_select.empty?
104
106
  parent_node = ng_xml.root
@@ -108,12 +110,12 @@ module OM::XML::TermValueOperators
108
110
  end
109
111
 
110
112
  insert_from_template(parent_node, new_values, template)
111
-
112
- parent_node
113
-
113
+
114
+ return parent_node
115
+
114
116
  end
115
117
 
116
- # Insert xml containing +new_values+ into +parent_node+. Generate the xml based on +template+
118
+ # Insert xml containing +new_values+ into +parent_node+. Generate the xml based on +template+
117
119
  # @param [Nokogiri::XML::Node] parent_node to insert new xml into
118
120
  # @param [Array] new_values to build the xml around
119
121
  # @param [Array -- (OM term pointer array) OR String -- (like what you would pass into Nokogiri::XML::Builder.new)] template for building the new xml. Use the syntax that Nokogiri::XML::Builder uses.
@@ -131,23 +133,23 @@ module OM::XML::TermValueOperators
131
133
  template = self.class.terminology.xml_builder_template( *template_args )
132
134
  end
133
135
 
134
- # if there is an xpath element pointing to text() need to change to just 'text' so it references the text method for the parent node
136
+ #if there is an xpath element pointing to text() need to change to just 'text' so it references the text method for the parent node
135
137
  template.gsub!(/text\(\)/, 'text')
136
-
138
+
137
139
  builder = Nokogiri::XML::Builder.with(parent_node) do |xml|
138
140
  new_values.each do |builder_new_value|
139
141
  builder_new_value = builder_new_value.gsub(/'/, "\\\\'") # escape any apostrophes in the new value
140
142
  if matchdata = /xml\.@(\w+)/.match(template)
141
143
  parent_node.set_attribute(matchdata[1], builder_new_value)
142
- else
144
+ else
143
145
  builder_arg = eval('"'+ template + '"') # this inserts builder_new_value into the builder template
144
146
  eval(builder_arg)
145
147
  end
146
148
  end
147
149
  end
148
- parent_node
150
+ return parent_node
149
151
  end
150
-
152
+
151
153
  # Creates necesary ancestor nodes to support inserting a new term value where the ancestor node(s) don't exist yet.
152
154
  # Corrects node indexes in the pointer array to correspond to the ancestors that it creates.
153
155
  # Returns a two-value array with the 'parent' node and a corrected pointer array
@@ -157,18 +159,20 @@ module OM::XML::TermValueOperators
157
159
  parent_select = Array(parent_select)
158
160
  parent_nodeset = find_by_terms(*parent_select)
159
161
  starting_point = node_from_set(parent_nodeset, parent_index)
160
- starting_point = [] if starting_point.nil?
162
+ if starting_point.nil?
163
+ starting_point = []
164
+ end
161
165
  to_build = []
162
- while starting_point.empty?
166
+ until !starting_point.empty?
163
167
  to_build = [parent_select.pop] + to_build
164
168
  starting_point = find_by_terms(*parent_select)
165
- if starting_point.empty? && parent_select.empty?
169
+ if starting_point.empty? && parent_select.empty?
166
170
  raise OM::XML::TemplateMissingException, "Cannot insert nodes into the document because it is empty. Try defining self.xml_template on the #{self.class} class."
167
171
  end
168
172
  end
169
- to_build.each do |term_pointer|
173
+ to_build.each do |term_pointer|
170
174
  parent_select << term_pointer
171
-
175
+
172
176
  # If pointers in parent_select don't match with the indexes of built ancestors, correct the hash
173
177
  if find_by_terms(*parent_select+[{}]).length == 0
174
178
  if parent_select.last.kind_of?(Hash)
@@ -194,13 +198,13 @@ module OM::XML::TermValueOperators
194
198
  if parent_index > starting_point.length
195
199
  parent_index = starting_point.length - 1
196
200
  end
197
- node_from_set(starting_point, parent_index)
201
+ return node_from_set(starting_point, parent_index)
198
202
  end
199
-
203
+
200
204
  def term_value_update(node_select,node_index,new_value,opts={})
201
205
  ng_xml_will_change!
202
206
  # template = opts.fetch(:template,nil)
203
-
207
+
204
208
  node = find_by_terms_and_value(*node_select)[node_index]
205
209
  if delete_on_update?(node, new_value)
206
210
  node.remove
@@ -212,23 +216,23 @@ module OM::XML::TermValueOperators
212
216
  def delete_on_update?(node, new_value)
213
217
  new_value == "" || new_value == :delete
214
218
  end
215
-
219
+
216
220
  # def term_value_set(term_ref, query_opts, node_index, new_value)
217
221
  # end
218
-
222
+
219
223
  def term_value_delete(opts={})
220
224
  ng_xml_will_change!
221
225
  parent_select = Array( opts[:parent_select] )
222
226
  parent_index = opts[:parent_index]
223
227
  child_index = opts[:child_index]
224
228
  xpath_select = opts[:select]
225
-
229
+
226
230
  if !xpath_select.nil?
227
231
  node = find_by_terms_and_value(xpath_select).first
228
232
  else
229
233
  # parent_nodeset = find_by_terms_and_value(parent_select, parent_select)
230
234
  parent_nodeset = find_by_terms_and_value(*parent_select)
231
-
235
+
232
236
  if parent_index.nil?
233
237
  node = node_from_set(parent_nodeset, child_index)
234
238
  else
@@ -237,24 +241,24 @@ module OM::XML::TermValueOperators
237
241
  node = node_from_set(parent.xpath("*"), child_index)
238
242
  end
239
243
  end
240
-
244
+
241
245
  node.remove
242
246
  end
243
-
244
-
247
+
248
+
245
249
  # Allows you to provide an array index _or_ a symbol representing the function to call on the nodeset in order to retrieve the node.
246
250
  def node_from_set(nodeset, index)
247
251
  if index.kind_of?(Integer)
248
252
  node = nodeset[index]
249
- elsif index.kind_of?(Symbol) && nodeset.respond_to?(index)
253
+ elsif index.kind_of?(Symbol) && nodeset.respond_to?(index)
250
254
  node = nodeset.send(index)
251
255
  else
252
256
  raise "Could not retrieve node using index #{index}."
253
257
  end
254
-
255
- node
258
+
259
+ return node
256
260
  end
257
-
261
+
258
262
  private :node_from_set
259
-
263
+
260
264
  end
@@ -1,27 +1,27 @@
1
1
  require 'loggable'
2
2
  module OM::XML::TermXpathGenerator
3
3
  include Loggable
4
-
4
+
5
5
  # Generate relative xpath for a term
6
6
  # @param [OM::XML::Term] term that you want to generate relative xpath for
7
7
  #
8
8
  # In most cases, the resulting xpath will be the Term's path with the appropriate namespace appended to it.
9
- # If the Term specifies any attributes,
9
+ # If the Term specifies any attributes,
10
10
  # Special Case: attribute Terms
11
- # If the Term's path is set to {:attribute=>attr_name}, the resulting xpath will points to a node attribute named attr_name
11
+ # If the Term's path is set to {:attribute=>attr_name}, the resulting xpath will points to a node attribute named attr_name
12
12
  # ie. a path fo {:attribute=>"lang"} will result in a relative xpath of "@lang"
13
13
  # Special Case: xpath functions
14
14
  # If the Term's path variable is text(), it will be treated as an xpath function (no namespace) and turned into "text()[normalize-space(.)]"
15
15
  def self.generate_relative_xpath(term)
16
16
  template = ""
17
17
  predicates = []
18
-
18
+
19
19
  if term.namespace_prefix.nil?
20
20
  complete_prefix = ""
21
21
  else
22
22
  complete_prefix = term.namespace_prefix + ":"
23
23
  end
24
-
24
+
25
25
  if term.path.kind_of?(Hash)
26
26
  if term.path.has_key?(:attribute)
27
27
  base_path = "@"+term.path[:attribute]
@@ -32,12 +32,14 @@ module OM::XML::TermXpathGenerator
32
32
  if term.path == "text()"
33
33
  base_path = "#{term.path}[normalize-space(.)]"
34
34
  else
35
- template << complete_prefix unless term.namespace_prefix.nil?
35
+ unless term.namespace_prefix.nil?
36
+ template << complete_prefix
37
+ end
36
38
  base_path = term.path
37
39
  end
38
40
  end
39
41
  template << base_path
40
-
42
+
41
43
  unless term.attributes.nil?
42
44
  term.attributes.each_pair do |attr_name, attr_value|
43
45
  if attr_value == :none
@@ -47,14 +49,14 @@ module OM::XML::TermXpathGenerator
47
49
  end
48
50
  end
49
51
  end
50
-
51
- unless predicates.empty?
52
+
53
+ unless predicates.empty?
52
54
  template << "["+ delimited_list(predicates, " and ")+"]"
53
55
  end
54
-
55
- template
56
+
57
+ return template
56
58
  end
57
-
59
+
58
60
  # Generate absolute xpath for a Term
59
61
  # @param [OM::XML::Term] term that you want to generate absolute xpath for
60
62
  #
@@ -67,36 +69,36 @@ module OM::XML::TermXpathGenerator
67
69
  return term.parent.xpath_absolute + "/" + relative
68
70
  end
69
71
  end
70
-
72
+
71
73
  def self.generate_constrained_xpath(term)
72
74
  if term.namespace_prefix.nil?
73
75
  complete_prefix = ""
74
76
  else
75
77
  complete_prefix = term.namespace_prefix + ":"
76
78
  end
77
-
79
+
78
80
  absolute = generate_absolute_xpath(term)
79
81
  constraint_predicates = []
80
-
82
+
81
83
  arguments_for_contains_function = []
82
84
 
83
- unless term.default_content_path.nil?
85
+ if !term.default_content_path.nil?
84
86
  arguments_for_contains_function << "#{complete_prefix}#{term.default_content_path}"
85
87
  end
86
-
88
+
87
89
  # If no subelements have been specified to search within, set contains function to search within the current node
88
90
  if arguments_for_contains_function.empty?
89
91
  arguments_for_contains_function << "."
90
92
  end
91
-
93
+
92
94
  arguments_for_contains_function << "\":::constraint_value:::\""
93
-
95
+
94
96
  contains_function = "contains(#{delimited_list(arguments_for_contains_function)})"
95
97
 
96
98
  template = add_predicate(absolute, contains_function)
97
- template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }.gsub('"', '\"')
99
+ return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }.gsub('"', '\"')
98
100
  end
99
-
101
+
100
102
  # Generate an xpath of the chosen +type+ for the given Term.
101
103
  # @param [OM::XML::Term] term that you want to generate relative xpath for
102
104
  # @param [Symbol] the type of xpath to generate, :relative, :abolute, or :constrained
@@ -110,9 +112,9 @@ module OM::XML::TermXpathGenerator
110
112
  self.generate_constrained_xpath(term)
111
113
  end
112
114
  end
113
-
115
+
114
116
  # Use the given +terminology+ to generate an xpath with (optional) node indexes for each of the term pointers.
115
- # Ex. OM::XML::TermXpathGenerator.xpath_with_indexes(my_terminology, {:conference=>0}, {:role=>1}, :text )
117
+ # Ex. OM::XML::TermXpathGenerator.xpath_with_indexes(my_terminology, {:conference=>0}, {:role=>1}, :text )
116
118
  # will yield an xpath similar to this: '//oxns:name[@type="conference"][1]/oxns:role[2]/oxns:roleTerm[@type="text"]'
117
119
  # @param [OM::XML::Terminology] terminology to generate xpath based on
118
120
  # @param [String -- OM term pointer] pointers identifying the node to generate xpath for
@@ -125,28 +127,30 @@ module OM::XML::TermXpathGenerator
125
127
  return root_term.xpath
126
128
  end
127
129
  end
128
-
130
+
129
131
  query_constraints = nil
130
-
132
+
131
133
  if pointers.length > 1 && pointers.last.kind_of?(Hash)
132
134
  constraints = pointers.pop
133
- query_constraints = constraints unless constraints.empty?
135
+ unless constraints.empty?
136
+ query_constraints = constraints
137
+ end
134
138
  end
135
139
 
136
140
  if pointers.length == 1 && pointers.first.instance_of?(String)
137
141
  return xpath_query = pointers.first
138
142
  end
139
-
143
+
140
144
  # if pointers.first.kind_of?(String)
141
145
  # return pointers.first
142
146
  # end
143
-
147
+
144
148
  keys = []
145
149
  xpath = "//"
146
150
 
147
151
  pointers = OM.destringify(pointers)
148
152
  pointers.each_with_index do |pointer, pointer_index|
149
-
153
+
150
154
  if pointer.kind_of?(Hash)
151
155
  k = pointer.keys.first
152
156
  index = pointer[k]
@@ -154,13 +158,13 @@ module OM::XML::TermXpathGenerator
154
158
  k = pointer
155
159
  index = nil
156
160
  end
157
-
161
+
158
162
  keys << k
159
-
160
- term = terminology.retrieve_term(*keys)
163
+
164
+ term = terminology.retrieve_term(*keys)
161
165
  # Return nil if there is no term to work with
162
166
  return if term.nil?
163
-
167
+
164
168
  # If we've encountered a NamedTermProxy, insert path sections corresponding to each entry in its proxy_pointer (rather than just the final term that it points to).
165
169
  # TODO Looks like this only works if the last key is a NamedTermProxy, what if we cross proxies on the way there?
166
170
  if term.kind_of? OM::XML::NamedTermProxy
@@ -183,20 +187,22 @@ module OM::XML::TermXpathGenerator
183
187
  raise "There's a problem with the #{term.name} OM::XML::NamedTermProxy, whose proxy pointer is #{term.proxy_pointer}. The #{proxy_pointer} pointer is returning #{proxy_term.inspect}"
184
188
  end
185
189
  end
186
- else
190
+ else
187
191
  relative_path = term.xpath_relative
188
-
192
+
189
193
  unless index.nil?
190
194
  relative_path = add_node_index_predicate(relative_path, index)
191
195
  end
192
196
  end
193
-
194
- relative_path = "/"+relative_path if pointer_index > 0
195
- xpath << relative_path
197
+
198
+ if pointer_index > 0
199
+ relative_path = "/"+relative_path
200
+ end
201
+ xpath << relative_path
196
202
  end
197
-
198
- final_term = terminology.retrieve_term(*keys)
199
-
203
+
204
+ final_term = terminology.retrieve_term(*keys)
205
+
200
206
  if query_constraints.kind_of?(Hash)
201
207
  contains_functions = []
202
208
  query_constraints.each_pair do |k,v|
@@ -207,20 +213,20 @@ module OM::XML::TermXpathGenerator
207
213
  end
208
214
  contains_functions << "contains(#{constraint_path}, \"#{v}\")"
209
215
  end
210
-
216
+
211
217
  xpath = add_predicate(xpath, delimited_list(contains_functions, " and ") )
212
218
  end
213
-
214
- xpath
219
+
220
+ return xpath
215
221
  end
216
-
222
+
217
223
  # @see OM::XML.delimited_list
218
224
  def self.delimited_list(*args)
219
225
  OM::XML.delimited_list(*args)
220
226
  end
221
-
227
+
222
228
  # Adds xpath xpath node index predicate to the end of your xpath query
223
- # Example:
229
+ # Example:
224
230
  # add_node_index_predicate("//oxns:titleInfo",0)
225
231
  # => "//oxns:titleInfo[1]"
226
232
  #
@@ -230,9 +236,9 @@ module OM::XML::TermXpathGenerator
230
236
  modified_query = xpath_query.dup
231
237
  modified_query << "[#{array_index_value + 1}]"
232
238
  end
233
-
239
+
234
240
  # Adds xpath:position() method call to the end of your xpath query
235
- # Examples:
241
+ # Examples:
236
242
  #
237
243
  # add_position_predicate("//oxns:titleInfo",0)
238
244
  # => "//oxns:titleInfo[position()=1]"
@@ -243,7 +249,7 @@ module OM::XML::TermXpathGenerator
243
249
  position_function = "position()=#{array_index_value + 1}"
244
250
  self.add_predicate(xpath_query, position_function)
245
251
  end
246
-
252
+
247
253
  def self.add_predicate(xpath_query, predicate)
248
254
  modified_query = xpath_query.dup
249
255
  # if xpath_query.include?("]")
@@ -252,7 +258,7 @@ module OM::XML::TermXpathGenerator
252
258
  else
253
259
  modified_query << "[#{predicate}]"
254
260
  end
255
- modified_query
261
+ return modified_query
256
262
  end
257
263
 
258
264
  end