class Extractor
Public Class Methods
new(roxml_objs, runtime, root_class, definitions = nil, &block)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 13 def initialize(roxml_objs, runtime, root_class, definitions = nil, &block) @roxml_objs = roxml_objs @runtime = runtime @root_class = root_class @definitions = {} if block_given? eval_definitions root_class, &block else definitions.each {|defin| eval_definitions root_class, defin } if definitions end end
Public Instance Methods
add_old_metadata(obj, old_metadata, current_metadata)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 123 def add_old_metadata(obj, old_metadata, current_metadata) # only keep the keys that don't exist in the template's metadata (current) # that metadata will be availabled when evaluate the roxml object # obj._metadata = old_metadata.merge current_metadata diff_keys = old_metadata.keys.inject([]) do |out, key| out << key unless current_metadata.key? key out end new_metadata = old_metadata.delete_if {|k, _| !diff_keys.include? k} obj._metadata = new_metadata end
convert_roxml_obj(obj)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 89 def convert_roxml_obj (obj) name = obj.class.class_name old_metadata = obj._metadata defs = @definitions[name] defs.each do |defin| diffs = diff_definition(defin, obj) if diffs.all? {|diff| diff.operation == '~' && (diff.template_val.is_a?(Utils::UndefinedParam) || diff.template_val == nil || interpolated_diff(diff)) } new_obj = defin.class.new param_values = diffs.inject({}) do |values, diff| name = diff.template_val ? diff.template_val.name : diff.key values[name] = interpolated_diff(diff) ? extract_interpolated_diff(diff) : diff.obj_val values end set_attributes new_obj, param_values # return convert_roxml_obj new_obj add_old_metadata new_obj, old_metadata, defin._metadata obj = new_obj end end if defs obj.class.roxml_attrs.each do |a| if a.array? elements = a.sought_type.class == Class ? obj.send(a.accessor).map {|el| convert_roxml_obj el} : obj.send(a.accessor) obj.send a.setter.to_sym, elements elsif a.sought_type.class == Class current_value = obj.send(a.accessor) obj.send a.setter.to_sym, convert_roxml_obj(current_value) if current_value end end obj end
convert_roxml_objs()
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 82 def convert_roxml_objs def_names = @definitions.keys @roxml_objs.map do |obj| convert_roxml_obj obj end end
diff_definition(defin, obj)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 56 def diff_definition(defin, obj) def_hash = defin.to_hash obj_hash = obj.to_hash [def_hash, obj_hash].each do |h| h.delete '__class' end diffs = HashDiff.diff(obj_hash, def_hash).map do |diff| accessor_name = if diff[3].is_a?(String) && match = diff[3].match(/#{Utils::UNDEFINED_PARAM}:(\w*)/) match[1].to_sym end if accessor_name && defin.class.plain_accessors.include?(accessor_name) matcher = defin.class.plain_accessors(true)[accessor_name] end template_val = diff[3].is_a?(String) && accessor_name ? Utils::UndefinedParam.new(accessor_name, diff[3]) : diff[3] ROXMLDiff.new diff[0], diff[1], from_hash(diff[2]), template_val, matcher end diffs end
eval_definitions(root_class, str = nil, &block)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 25 def eval_definitions(root_class, str = nil, &block) if block_given? @runtime.evaluate_raw '', root_class, &block else @runtime.evaluate_raw str, root_class end def_names = @runtime.instance_variable_get(:@classes).inject([]) do |out, (name, clazz)| out << name if clazz.subclass? out end @definitions = def_names.inject(@definitions) do |out, name| clazz = @runtime.fetch(name) parent = get_root_class clazz obj = clazz.new cleanroom = @runtime.create_cleanroom clazz, true cleanroom.get_el.process.each { |p| cleanroom.evaluate &p } out[parent] ||= [] out[parent] << cleanroom.get_el out end end
extract_interpolated_diff(diff)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 139 def extract_interpolated_diff(diff) s_diff = Differ.diff_by_word(diff.obj_val, diff.template_val.original).to_s value = s_diff.match(/(\{"\s*#{Utils::UNDEFINED_PARAM}:([\S]*)\s*" >> "(.*)"})/)[3] value.strip.match(diff.matcher)[1] end
from_hash(hash)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 76 def from_hash(hash) return hash unless hash.is_a? Hash @runtime.fetch(hash['__class']).from_hash @runtime, hash end
get_root_class(clazz)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 47 def get_root_class(clazz) super_clazz = @runtime.fetch clazz.superclass.class_name if super_clazz.subclass? get_root_class super_clazz else super_clazz.class_name end end
interpolated_diff(diff)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 135 def interpolated_diff(diff) diff.obj_val.is_a?(String) && diff.template_val.is_a?(Utils::UndefinedParam) && diff.template_val.original && diff.template_val.original.match(/#{Utils::UNDEFINED_PARAM}:/) end
set_attributes(obj, params)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 145 def set_attributes(obj, params) params.each do |param, val| methods = param.to_s.split '.' methods << val set_deep_attributes obj, methods # obj.send "#{param}=", val end end
set_deep_attributes(obj, methods)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 155 def set_deep_attributes(obj, methods) index = methods[0].match(/\[(\d+)\]/) child = index ? nil : obj.send(methods[0]) method = methods[0] method.gsub!(/\[\d+\]/, '') if child set_deep_attributes child, methods[1..methods.size] else if index arr = obj.send(method) || [] arr[Integer(index[1])] = methods[1..1][0] # hacky way to get second element obj.send("#{method}=", arr) else obj.send(methods[0] + '=', set_deep_attributes_helper(obj, methods)) end end end
set_deep_attributes_helper(obj, methods)
click to toggle source
# File lib/roundtrip_xml/extractor.rb, line 173 def set_deep_attributes_helper(obj, methods) method = methods.shift index = method.match(/\[(\d+)\]/) return obj.send(method + '=', methods.first) if !index && methods.size == 1 method.gsub!(/\[\d+\]/, '') child = obj.send(method) unless child || methods.size == 1 clazz_name = method.dup clazz_name[0] = clazz_name[0].upcase child = @runtime.fetch(clazz_name.to_sym).new obj.send("#{method}=", child) end if index arr = obj.send(method) || [] arr[Integer(index[1])] = methods.first obj.send("#{method}=", arr) else obj.send(method + '=', set_deep_attributes_helper(child, methods)) end child.is_a?(Array) ? obj : child || obj end