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.
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