Module: OM::XML::TermValueOperators
- Defined in:
- lib/om/xml/term_value_operators.rb
Instance Method Summary collapse
-
#build_ancestors(parent_select, parent_index) ⇒ Nokogiri::XML::Node, Array
Creates necesary ancestor nodes to support inserting a new term value where the ancestor node(s) don’t exist yet.
-
#insert_from_template(parent_node, new_values, template) ⇒ Nokogiri::XML::Node
Insert xml containing
new_values
intoparent_node
. -
#property_values(*lookup_args) ⇒ Object
alias for term_values.
-
#term_value_delete(opts = {}) ⇒ Object
def term_value_set(term_ref, query_opts, node_index, new_value) end.
- #term_value_update(node_select, node_index, new_value, opts = {}) ⇒ Object
-
#term_values(*term_pointer) ⇒ Object
Retrieves all of the nodes from the current document that match
term_pointer
and returns an array of their values. - #term_values_append(opts = {}) ⇒ Object
-
#update_values(params = {}) ⇒ Object
example term values hash: [{“:person”=>“0”, “role”, “text”]=>“1”=>“role2”, “2”=>“role3”, [:person=>1, :family_name]=>“Andronicus”, [“person”=>“1”,:given_name]=>,[:person=>1,:role,:text]=> }.
Instance Method Details
#build_ancestors(parent_select, parent_index) ⇒ Nokogiri::XML::Node, Array
Creates necesary ancestor nodes to support inserting a new term value where the ancestor node(s) don’t exist yet. Corrects node indexes in the pointer array to correspond to the ancestors that it creates. Returns a two-value array with the ‘parent’ node and a corrected pointer array
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/om/xml/term_value_operators.rb', line 157 def build_ancestors(parent_select, parent_index) parent_select = Array(parent_select) parent_nodeset = find_by_terms(*parent_select) starting_point = node_from_set(parent_nodeset, parent_index) if starting_point.nil? starting_point = [] end to_build = [] until !starting_point.empty? to_build = [parent_select.pop] + to_build starting_point = find_by_terms(*parent_select) if starting_point.empty? && parent_select.empty? raise OM::XML::TemplateMissingException, "Cannot insert nodes into the document because it is empty. Try defining self.xml_template on the #{self.class} class." end end to_build.each do |term_pointer| parent_select << term_pointer # If pointers in parent_select don't match with the indexes of built ancestors, correct the hash if find_by_terms(*parent_select+[{}]).length == 0 if parent_select.last.kind_of?(Hash) suspect_pointer = parent_select.pop term_key = suspect_pointer.keys.first if parent_select.empty? corrected_term_index = find_by_terms(term_key).length else corrected_term_index = find_by_terms(*parent_select+[{}]).length end parent_select << {term_key => corrected_term_index} end end template_pointer = OM.pointers_to_flat_array(parent_select,false) new_values = [""] insert_from_template(starting_point.first, new_values, template_pointer) starting_point = find_by_terms(*parent_select+[{}]) # If pointers in parent_select don't match with the indexes of built ancestors, correct the hash if starting_point.empty? raise ::StandardError, "Oops. Something went wrong adding #{term_pointer.inspect} to #{parent_select.inspect} while building ancestors. Expected to find something at #{self.class.terminology.xpath_for(*parent_select)}. The current xml is\n #{self.to_xml}" end end if parent_index > starting_point.length parent_index = starting_point.length - 1 end return node_from_set(starting_point, parent_index), parent_select end |
#insert_from_template(parent_node, new_values, template) ⇒ Nokogiri::XML::Node
Insert xml containing new_values
into parent_node
. Generate the xml based on template
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/om/xml/term_value_operators.rb', line 123 def insert_from_template(parent_node, new_values, template) # If template is a string, use it as the template, otherwise use it as arguments to xml_builder_template unless template.instance_of?(String) template_args = Array(template) if template_args.last.kind_of?(Hash) template_opts = template_args.delete_at(template_args.length - 1) template_args << template_opts end template_args = OM.pointers_to_flat_array(template_args,false) template = self.class.terminology.xml_builder_template( *template_args ) end #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 template.gsub!(/text\(\)/, 'text') builder = Nokogiri::XML::Builder.with(parent_node) do |xml| new_values.each do |builder_new_value| builder_new_value.gsub!(/'/, "\\\\'") # escape any apostrophes in the new value if matchdata = /xml\.@(\w+)/.match(template) parent_node.set_attribute(matchdata[1], builder_new_value) else builder_arg = eval('"'+ template + '"') # this inserts builder_new_value into the builder template eval(builder_arg) end end end return parent_node end |
#property_values(*lookup_args) ⇒ Object
alias for term_values
19 20 21 |
# File 'lib/om/xml/term_value_operators.rb', line 19 def property_values(*lookup_args) term_values(*lookup_args) end |
#term_value_delete(opts = {}) ⇒ Object
def term_value_set(term_ref, query_opts, node_index, new_value) end
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/om/xml/term_value_operators.rb', line 217 def term_value_delete(opts={}) parent_select = Array( opts[:parent_select] ) parent_index = opts[:parent_index] child_index = opts[:child_index] xpath_select = opts[:select] if !xpath_select.nil? node = find_by_terms_and_value(xpath_select).first else # parent_nodeset = find_by_terms_and_value(parent_select, parent_select) parent_nodeset = find_by_terms_and_value(*parent_select) if parent_index.nil? node = node_from_set(parent_nodeset, child_index) else parent = node_from_set(parent_nodeset, parent_index) # this next line is a hack around the fact that element_children() sometimes doesn't work. node = node_from_set(parent.xpath("*"), child_index) end end node.remove end |
#term_value_update(node_select, node_index, new_value, opts = {}) ⇒ Object
203 204 205 206 207 208 209 210 211 212 |
# File 'lib/om/xml/term_value_operators.rb', line 203 def term_value_update(node_select,node_index,new_value,opts={}) # template = opts.fetch(:template,nil) node = find_by_terms_and_value(*node_select)[node_index] if new_value == "" || new_value == :delete node.remove else node.content = new_value end end |
#term_values(*term_pointer) ⇒ Object
Retrieves all of the nodes from the current document that match term_pointer
and returns an array of their values
8 9 10 11 12 13 14 15 16 |
# File 'lib/om/xml/term_value_operators.rb', line 8 def term_values(*term_pointer) result = [] xpath = self.class.terminology.xpath_with_indexes(*term_pointer) #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 trim_text = !xpath.nil? && !xpath.index("text()").nil? find_by_terms(*term_pointer).each {|node| result << (trim_text ? node.text.strip : node.text) } # find_by_terms(*OM.destringify(term_pointer)).each {|node| result << node.text } return result end |
#term_values_append(opts = {}) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/om/xml/term_value_operators.rb', line 96 def term_values_append(opts={}) parent_select = Array( opts[:parent_select] ) parent_index = opts[:parent_index] template = opts[:template] new_values = Array( opts[:values] ) parent_nodeset = find_by_terms(*parent_select) parent_node = node_from_set(parent_nodeset, parent_index) if parent_node.nil? parent_node, parent_select = build_ancestors(parent_select, parent_index) # parent_nodeset = find_by_terms(*parent_select) # parent_node = node_from_set(parent_nodeset, :last) # raise OM::XML::ParentNodeNotFoundError, "Failed to find a parent node to insert values into based on :parent_select #{parent_select.inspect} with :parent_index #{parent_index.inspect}" end insert_from_template(parent_node, new_values, template) return parent_node end |
#update_values(params = {}) ⇒ Object
example term values hash: [{“:person”=>“0”, “role”, “text”]=>“1”=>“role2”, “2”=>“role3”, [:person=>1, :family_name]=>“Andronicus”, [“person”=>“1”,:given_name]=>,[:person=>1,:role,:text]=> }
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/om/xml/term_value_operators.rb', line 25 def update_values(params={}) # remove any terms from params that this datastream doesn't recognize params.delete_if do |term_pointer,new_values| if term_pointer.kind_of?(String) true else !self.class.terminology.has_term?(*OM.destringify(term_pointer)) end end result = params.dup params.each_pair do |term_pointer,new_values| pointer = OM.destringify(term_pointer) template_pointer = OM.pointers_to_flat_array(pointer,false) hn = OM::XML::Terminology.term_hierarchical_name(*pointer) # Sanitize new_values to always be a hash with indexes case new_values when Hash when Array nv = new_values.dup new_values = {} nv.each {|v| new_values[nv.index(v).to_s] = v} else new_values = {"0"=>new_values} end # Populate the response hash appropriately, using hierarchical names for terms as keys rather than the given pointers. result.delete(term_pointer) result[hn] = new_values.dup # Skip any submitted values if the new value matches the current values current_values = term_values(*pointer) new_values.delete_if do |y,z| if current_values[y.to_i]==z and y.to_i > -1 true else false end end # Fill out the pointer completely if the final term is a NamedTermProxy term = self.class.terminology.retrieve_term( *OM.pointers_to_flat_array(pointer,false) ) if term.kind_of? OM::XML::NamedTermProxy pointer.pop pointer = pointer.concat(term.proxy_pointer) end xpath = self.class.terminology.xpath_with_indexes(*pointer) parent_pointer = pointer.dup parent_pointer.pop parent_xpath = self.class.terminology.xpath_with_indexes(*parent_pointer) # If the value doesn't exist yet, append it. Otherwise, update the existing value. new_values.each do |y,z| if find_by_terms(*pointer)[y.to_i].nil? || y.to_i == -1 result[hn].delete(y) term_values_append(:parent_select=>parent_pointer,:parent_index=>0,:template=>template_pointer,:values=>z) # term_values_append(:parent_select=>parent_xpath,:parent_index=>0,:template=>template_pointer,:values=>z) new_array_index = find_by_terms(*pointer).length - 1 result[hn][new_array_index.to_s] = z else term_value_update(xpath, y.to_i, z) end end end return result end |