class Hash
Alteration to Hash and Array for support of structural processing: additional methods to address elements of, and process, structural combinations of Hashes, Arrays, and ByteArrays SOMEDAY: @Hash extend these to the pain-in-the-ass Struct class as well.
Public Class Methods
gxg_import(the_exported_record=nil)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3579 def self.gxg_import(the_exported_record=nil) result = nil if the_exported_record.is_a?(Hash) if the_exported_record[:type] == "Array" result = ::Array::gxg_import(the_exported_record) else import_value = Proc.new do |type,value| if value.is_a?(String) begin the_class = eval(type) if the_class.respond_to?(:parse) value = the_class.parse(value) else if the_class.respond_to?(:new) value = the_class.new(value) else if the_class.respond_to?(:try_convert) value = the_class.try_convert(value) end end end rescue Exception => the_error end end value end if the_exported_record[:type] == "Hash" result = {} import_db = [{:parent => nil, :parent_selector => nil, :object => result, :record => the_exported_record}] while import_db.size > 0 do entry = import_db.shift if entry[:record][:content].is_a?(Hash) entry[:record][:content].each_pair do |selector, value| if value[:type] == "Hash" entry[:object][(selector)] = {} import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value} else if value[:type] == "Array" entry[:object][(selector)] = [] import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value} else entry[:object][(selector)] = import_value.call(value[:type], value[:content]) end end end else if entry[:record][:content].is_a?(Array) entry[:record][:content].each_with_index do |value, selector| if value[:type] == "Hash" entry[:object][(selector)] = {} import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value} else if value[:type] == "Array" entry[:object][(selector)] = [] import_db << {:parent => entry[:object], :parent_selector => selector, :object => entry[:object][(selector)], :record => value} else entry[:object][(selector)] = import_value.call(value[:type], value[:content]) end end end end end end else result = import_value.call(the_exported_record[:type], the_exported_record[:content]) end end end result end
process(the_hash={},&block)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3291 def self.process(the_hash={},&block) new_hash = {} if block.respond_to?(:call) if the_hash.is_any?(::Array, ::Hash, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray) new_hash = the_hash.process!(&block) else raise ArgumentError, "you must pass a Hash or an Array, or a ByteArray" end end new_hash end
search(the_hash={},&block)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3303 def self.search(the_hash={},&block) new_hash = {} if block.respond_to?(:call) if the_hash.is_any?(::Array, ::Hash, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray) new_hash = the_hash.search(&block) else raise ArgumentError, "you must pass a Hash or an Array, or a ByteArray" end end new_hash end
Public Instance Methods
get_at_path(the_path="/")
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3466 def get_at_path(the_path="/") result = nil if the_path == "/" result = self else object_stack = [(self)] path_stack = the_path.split("/") path_stack.to_enum.each do |path_element| element = nil if path_element.size > 0 if (path_element =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0 element = path_element.to_i else element = path_element element.gsub!("%2f","/") if element[0] == ":" element = element[(1..-1)].to_sym end end end if element result = object_stack.first[(element)] if result.is_a?(NilClass) break else object_stack.unshift(result) end else # ignore double slashes? '//' # break end end end result end
gxg_export()
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3533 def gxg_export() result = {:type => "Hash", :content => {}} export_db = [{:parent => nil, :parent_selector => nil, :object => self, :record => result}] children_of = Proc.new do |the_parent=nil| list = [] export_db.each do |node| if node[:parent].object_id == the_parent.object_id list << node end end list end export_record = Proc.new do |the_value| if the_value.is_any?(Integer, Float, String) {:type => (the_value.class.to_s), :content => the_value} else {:type => (the_value.class.to_s), :content => the_value.to_s} end end # Build up export_db: self.search do |the_value, the_selector, the_container| if the_value.is_a?(::Hash) export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => "Hash", :content => {}}} else if the_value.is_a?(::Array) export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => {:type => "Array", :content => []}} else export_db << {:parent => the_container, :parent_selector => the_selector.clone, :object => the_value, :record => export_record.call(the_value)} end end end # Collect children export content: link_db =[(export_db[0])] while link_db.size > 0 do entry = link_db.shift children_of.call(entry[:object]).each do |the_child| entry[:record][:content][(the_child[:parent_selector])] = the_child[:record] if the_child[:object].is_any?(Hash, Array) link_db << the_child end end end # result end
iterative(&block)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3315 def iterative(&block) result = [] visit = Proc.new do |the_node=nil, accumulator=[]| node_stack = [] if the_node node_stack << ({:parent => nil, :parent_selector => nil, :object => (the_node)}) while (node_stack.size > 0) do a_node = node_stack.shift # if a_node[:object].is_any?(::Hash, ::Struct, ::GxG::Database::PersistedHash) a_node[:object].each_pair do |the_key, the_value| node_stack << ({:parent => a_node[:object], :parent_selector => the_key, :object => the_value}) end end if a_node[:object].is_any?(::Array, ::GxG::Database::PersistedArray) a_node[:object].each_with_index do |the_value, the_index| node_stack << ({:parent => a_node[:object], :parent_selector => the_index, :object => the_value}) end end # accumulator << a_node end end accumulator end # children_of = Proc.new do |the_db=[], the_parent=nil| list = [] the_db.each do |node| if node[:parent].object_id == the_parent.object_id list << node end end list end # begin database = visit.call(self,[]) link_db = children_of.call(database, self) if block.respond_to?(:call) while (link_db.size > 0) do entry = link_db.shift unless entry[:object].object_id == self.object_id # calls with parameters: the_value, the_key/the_index (the_selector), the_container raw_result = block.call(entry[:object], entry[:parent_selector], entry[:parent]) if raw_result result << raw_result end end if entry[:object].object_id != nil.object_id children = children_of.call(database, entry[:object]) children.each do |child| link_db << child end end end end # rescue Exception => the_error log_error({:error => the_error, :parameters => {}}) end # result end
paths_to(the_object=nil,base_path="")
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3399 def paths_to(the_object=nil,base_path="") # new idea here: search_results = [] unless base_path[0] == "/" base_path = ("/" << base_path) end if base_path.size > 1 path_stack = base_path.split("/")[1..-1].reverse else path_stack = [] end origin = self.get_at_path(base_path) container_stack = [{:selector => nil, :container => origin, :prefix => "/"}] find_container = Proc.new do |the_container| result = nil container_stack.each_with_index do |entry, index| if entry[:container] == the_container result = entry break end end result end last_container = origin found = false # tester = {:a=>1, :b=>2, :c=>[0, 5], :testing=>{:d=>4.0, :e=>0.9, :f => nil}} if origin.is_any?(::Hash, ::Array, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray) origin.process! do |the_value, selector, container| if last_container.object_id != container.object_id container_record = find_container.call(container) if container_record path_stack = container_record[:prefix].split("/").reverse if path_stack.size == 0 path_stack << "" end end last_container = container end if selector.is_a?(Symbol) safe_key = (":" + selector.to_s) else safe_key = selector.to_s end safe_key = safe_key.gsub("/","%2f") path_stack.unshift(safe_key) # compare the_value found = false if (the_value == the_object) found = true end if found search_results << ("/" << path_stack.reverse.join("/")) end # if the_value.is_any?(::Array, ::Hash, ::Struct, ::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray) container_stack.unshift({:selector => selector, :container => the_value, :prefix => (path_stack.reverse.join("/"))}) end path_stack.shift # nil end else search_results << ("/" << path_stack.join("/")) end search_results end
process(&block)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3380 def process(&block) result = self.clone result.iterative(&block) result end
process!(&block)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3386 def process!(&block) self.iterative(&block) self end
search(&block)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3391 def search(&block) results = [] if block.respond_to?(:call) results = self.iterative(&block) end results end
set_at_path(the_path="/",the_value=nil)
click to toggle source
# File lib/gxg/gxg_augmented.rb, line 3502 def set_at_path(the_path="/",the_value=nil) result = nil if the_path != "/" container = self.get_at_path(::File::dirname(the_path)) if container raw_selector = ::File::basename(the_path) selector = nil if raw_selector.size > 0 if (raw_selector =~ /^(?:[0-9])*[0-9](?:[0-9])*$/) == 0 selector = raw_selector.to_i else selector = raw_selector selector.gsub!("%2f","/") if selector[0] == ":" selector = selector[(1..-1)].to_sym end end end if selector container[(selector)] = the_value result = container[(selector)] else # ignore double slashes? '//' # break end # end end result end
symbolize_keys()
click to toggle source
def to_xml_simple(options={})
# keyattr keeproot contentkey noattr rootname # xmldeclaration outputfile noescape suppressempty # anonymoustag indent grouptags noindent attrprefix the_options = {:xmldeclaration => true, :rootname => :root, :keeproot => false} if options.is_a?(::Hash) if options[:XmlDeclaration].is_any?(::TrueClass, ::FalseClass) the_options[:xmldeclaration] = options[:XmlDeclaration] end if options[:xmldeclaration].is_any?(::TrueClass, ::FalseClass) the_options[:xmldeclaration] = options[:xmldeclaration] end if options[:RootName].is_any?(::String, ::Symbol) the_options[:rootname] = options[:RootName] end if options[:rootname].is_any?(::String, ::Symbol) the_options[:rootname] = options[:rootname] end if options[:KeepRoot].is_any?(::TrueClass, ::FalseClass) the_options[:keeproot] = options[:KeepRoot] end if options[:keeproot].is_any?(::TrueClass, ::FalseClass) the_options[:keeproot] = options[:keeproot] end else raise ArgumentError, "You MUST provide options in the form of a Hash." end ::XmlSimple.xml_out(self, the_options).gsub("\n", "")
end
def to_json()
::JSON.generate(self)
end
# File lib/gxg/gxg_augmented.rb, line 3684 def symbolize_keys() self.process! do |value, selector, container| if container.is_a?(::Hash) unless selector.is_a?(::Symbol) container[(selector.to_sym)] = container.delete(selector) end end nil end self end