module Xampl class RubyPrinter $USE_A_PROC = false def initialize(mentions=nil) @obj_count = 0 @map = {} @lookup_map={} @mentions = mentions end def show_attributes(thing, name, depth) return "" unless thing.attributes out = "" indent = " " + (" " * depth) if thing.persist_required and (1 < depth) accessor = thing.indexed_by value = thing.get_the_index if value then out << indent << "#{name}.#{accessor} = #{value.inspect}\n" end else thing.attributes.each do |attribute| value = thing.instance_variable_get(attribute[0]) if value then if value.kind_of?(XamplObject) then vname = "root_#{@obj_count += 1}" out << to_ruby_as_attr(value, depth, vname) out << indent << "#{name}.instance_variable_set(:#{attribute[0]}, #{vname})\n" else out << indent << "#{name}.instance_variable_set(:#{attribute[0]}, #{value.inspect})\n" end end end end return out end def show_children_tree(thing, name, depth) out = "" indent = " " + (" " * depth) if thing.persist_required and (1 < depth) then return out << indent << "#{name}.load_needed = true\n" end if (!thing.kind_of? XamplWithMixedContent) and (!thing.kind_of? XamplWithoutContent) and thing._content then out << indent << "#{name} << #{thing._content.inspect}\n" end thing.children.each do |child| if child.kind_of? XamplObject then cname = "v_#{child.safe_name}_#{@obj_count += 1}" cout = "" cout << show_attributes(child, cname, 1 + depth) cout << show_children_tree(child, cname, 1 + depth) if 0 < cout.size then out << indent << "#{name} << #{child.class.to_s}.new { | #{cname} |\n" out << cout out << indent << "}\n" else out << indent << "#{name} << #{child.class.to_s}.new\n" end else out << indent << "#{name} << #{child.inspect}\n" end end return out end def show_attributes_flat(thing, depth) return "" unless thing.attributes out = "" if thing.persist_required and (1 < depth) accessor = thing.indexed_by value = thing.get_the_index if value then out << " " << "xampl.#{accessor} = #{value.inspect}\n" end else thing.attributes.each do |attribute| value = thing.instance_variable_get(attribute[0]) if value then out << " " << "xampl.instance_variable_set(:#{attribute[0]}, #{value.inspect})\n" end end end return out end def show_children_flat(thing, name, depth) out = "" thing.children.each do |child| if child.kind_of? XamplObject and (nil == @map[child]) then cname = "v_#{child.safe_name}_#{@obj_count += 1}" @map[child] = cname cout = "" cout << show_attributes_flat(child, 1 + depth) if 0 < cout.size then if child.persist_required then out << " " << "#{cname} = #{child.class.to_s}['#{child.get_the_index}']\n" @mentions << child if @mentions else out << " " << "#{cname} = #{child.class.to_s}.new { | xampl |\n" out << cout out << " " << "}\n" end else out << " " << "#{cname} = #{child.class.to_s}.new\n" end out << show_children_flat(child, cname, 1 + depth) unless child.persist_required end end return out end def show_children_stitch_start(thing, depth) @lookup_map.merge!(@map) return show_children_stitch(thing, depth) end def show_children_stitch(thing, depth) out = "" return out if thing.persist_required and (0 < depth) name = @map[thing] if name then @map.delete(thing) else return out end if (!thing.kind_of? XamplWithMixedContent) and (!thing.kind_of? XamplWithoutContent) and thing._content then out << " " << "#{name} << #{thing._content.inspect}\n" end thing.children.each do |child| if child.kind_of? XamplObject then out << " " << "#{name} << #{@lookup_map[child]}\n" else out << " " << "#{name} << #{child.inspect}\n" end end thing.children.each do |child| if child.kind_of? XamplObject then out << show_children_stitch(child, 1 + depth) end end return out end def to_ruby(thing, depth=0, name="root") thing.accessed @obj_count = 0 @map = {} @lookup_map={} @map[thing] = name if $USE_A_PROC then return %Q{ module XamplRubyDefinition @@proc = Proc.new { | target | #{name} = target ? target : #{thing.class.to_s}.new #{show_attributes(thing, name, depth)} #{show_children_flat(thing, name, depth)} #{show_children_stitch_start(thing, depth)} #{name} } end } else return %Q{ module XamplRubyDefinition def XamplRubyDefinition.build_it(target) #{name} = target ? target : #{thing.class.to_s}.new #{show_attributes(thing, name, depth)} #{show_children_flat(thing, name, depth)} #{show_children_stitch_start(thing, depth)} #{name} end end } end end def to_ruby_as_attr(thing, depth, name) thing.accessed @map[thing] = name return %Q{ #{name} = #{thing.class.name}.new #{show_attributes(thing, name, depth)} #{show_children_flat(thing, name, depth)} #{show_children_stitch_start(thing, depth)} } end end end