push more responsibility down to node
expose simple attribute write long or short many test got more compact, good
This commit is contained in:
@ -26,35 +26,29 @@ module Sof
|
||||
super(ref)
|
||||
@children = []
|
||||
end
|
||||
attr_reader :children
|
||||
|
||||
def add c
|
||||
@children << c
|
||||
end
|
||||
|
||||
# The output of a Array can be a long or a short format
|
||||
# The short is used for 7 or less SimpleNodes
|
||||
def out io , level
|
||||
super
|
||||
def is_simple?
|
||||
return false if(@children.length > 7 )
|
||||
short = true
|
||||
children.each do |c|
|
||||
short = false unless c.is_a?(SimpleNode)
|
||||
end
|
||||
if(short and children.length < 7 )
|
||||
short_out(io , level)
|
||||
else
|
||||
long_out(io , level)
|
||||
@children.each do |c|
|
||||
short = false unless c.is_simple?
|
||||
end
|
||||
short
|
||||
end
|
||||
|
||||
private
|
||||
# This defines the short output which is basically what you would write in ruby
|
||||
# ie [ value1 , value2 , ...]
|
||||
# The short is used for 7 or less SimpleNodes
|
||||
def short_out(io,level)
|
||||
io.write("[")
|
||||
@children.each_with_index do |child , i|
|
||||
child.out(io , level + 1 )
|
||||
io.write ", " unless (i+1) == children.length
|
||||
io.write ", " unless (i+1) == @children.length
|
||||
end
|
||||
io.write("]")
|
||||
end
|
||||
|
@ -28,39 +28,32 @@ module Sof
|
||||
super(ref)
|
||||
@children = []
|
||||
end
|
||||
attr_reader :children
|
||||
|
||||
def add key , val
|
||||
@children << [key,val]
|
||||
end
|
||||
|
||||
# The output of a Hash can be a long or a short format
|
||||
# The short is used for 7 or less SimpleNodes
|
||||
def out io , level
|
||||
super
|
||||
short = true
|
||||
children.each do |k,v|
|
||||
short = false unless k.is_a?(SimpleNode)
|
||||
short = false unless v.is_a?(SimpleNode)
|
||||
end
|
||||
if(short and children.length < 7 )
|
||||
short_out(io,level)
|
||||
else
|
||||
long_out(io , level)
|
||||
def is_simple?
|
||||
return false if(@children.length > 7 )
|
||||
@children.each do |k,v|
|
||||
return false unless k.is_simple?
|
||||
return false unless v.is_simple?
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
# This defines the short output which is basically what you would write in ruby
|
||||
# ie { key1 => value1 , ... }
|
||||
# The short is used for 7 or less SimpleNodes
|
||||
def short_out(io,level)
|
||||
io.write("{")
|
||||
children.each_with_index do |child , i|
|
||||
@children.each_with_index do |child , i|
|
||||
key , val = child
|
||||
key.out(io , level + 1)
|
||||
io.write " => "
|
||||
val.out(io , level + 1)
|
||||
io.write ", " unless (i+1) == children.length
|
||||
io.write ", " unless (i+1) == @children.length
|
||||
end
|
||||
io.write("}")
|
||||
end
|
||||
@ -70,7 +63,7 @@ module Sof
|
||||
# and each line has the association key => value, same as used for the {} syntax
|
||||
def long_out io , level
|
||||
indent = " " * level
|
||||
children.each_with_index do |child , i|
|
||||
@children.each_with_index do |child , i|
|
||||
key , val = child
|
||||
io.write "\n#{indent}" unless i == 0
|
||||
io.write "- "
|
||||
|
@ -29,14 +29,15 @@ module Sof
|
||||
|
||||
# see if we we came accross this before
|
||||
if( occurence = @objects[object.object_id] )
|
||||
#puts "reset level #{level} at #{occurence.level}"
|
||||
puts "reset level #{level} at #{occurence.level}" if occurence.referenced == 19
|
||||
if occurence.level > level
|
||||
#always store the most shallow level
|
||||
occurence.level = level
|
||||
end
|
||||
# and only one Occurence for each object, create a reference for the second occurence
|
||||
unless occurence.referenced
|
||||
#puts "referencing #{@counter} , at level #{level}/#{occurence.level} "
|
||||
puts "referencing #{@counter} #{occurence.object.name}, at level #{level}/#{occurence.level} " if @counter == 14
|
||||
puts "referencing #{@counter} #{occurence.object.name}, at level #{level}/#{occurence.level} " if @counter == 19
|
||||
occurence.set_reference(@counter)
|
||||
@counter = @counter + 1
|
||||
end
|
||||
|
@ -7,7 +7,13 @@ module Sof
|
||||
#
|
||||
# There are only two subclasses, SimpleNode and ObejctNode, for simple or not
|
||||
# The base class only holds the referenced flag
|
||||
# Also nodes must implement the out function
|
||||
|
||||
# Node implements the out function which just checks wether a node is_simple?
|
||||
# and either calls short_out or long_out
|
||||
#
|
||||
# Notice that different instances of the same clas may be simple or not
|
||||
|
||||
# So deriving classes must implement is_simple? and accordingly long/and or short_out
|
||||
|
||||
class Node
|
||||
include Util
|
||||
@ -20,10 +26,23 @@ module Sof
|
||||
end
|
||||
attr_reader :referenced
|
||||
|
||||
# must be able to output to a stream
|
||||
# This function must be called as super as it handles possible reference marker "& num"
|
||||
# This ochastrates the output of derived classes to the stream
|
||||
# It writes any possible reference and sees if the noe is_simple? (see there)
|
||||
# and calls long / or short_out respectively
|
||||
def out io ,level
|
||||
io.write "&#{@referenced} " if @referenced
|
||||
if( is_simple? )
|
||||
short_out(io,level)
|
||||
else
|
||||
long_out(io,level)
|
||||
end
|
||||
end
|
||||
|
||||
# Determine wether node is simple, meaning short, in the 30 char region
|
||||
# The point of hoisting this property into the public api is that
|
||||
# other nodes may ask of their children and output accordingly
|
||||
def is_simple?
|
||||
raise "abstact function is_simple called for #{self}"
|
||||
end
|
||||
|
||||
# helper function to return the output as a string
|
||||
@ -33,5 +52,14 @@ module Sof
|
||||
out(io,level)
|
||||
io.string
|
||||
end
|
||||
|
||||
private
|
||||
def short_out io , level
|
||||
raise "abstact function short_out called for #{self}"
|
||||
end
|
||||
|
||||
def long_out io , level
|
||||
raise "abstact function long_out called for #{self}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,31 +8,48 @@ module Sof
|
||||
|
||||
# init with a string, much like a simple node
|
||||
# structure is added after construction and kept in a children array
|
||||
def initialize data , ref
|
||||
def initialize name , ref
|
||||
super(ref)
|
||||
@data = data
|
||||
@children = []
|
||||
@name = name
|
||||
@simple = {}
|
||||
@complex = {}
|
||||
end
|
||||
attr_reader :children , :data
|
||||
|
||||
# children array hold key value pairs
|
||||
# attributes hold key value pairs
|
||||
def add k , v
|
||||
@children << [k,v]
|
||||
raise "Key should be symbol not #{k}" unless k.is_a? Symbol
|
||||
if( v.is_simple?)
|
||||
@simple[k] = v
|
||||
else
|
||||
@complex[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
def is_simple?
|
||||
true if( @referenced.nil? and @complex.empty? and head.length < 30 )
|
||||
end
|
||||
|
||||
# write out at the given level
|
||||
# level determines the indentation (level * space)
|
||||
# write out the data and then the children (always key value on one line)
|
||||
def out io , level
|
||||
super
|
||||
io.write(@data)
|
||||
def long_out io , level
|
||||
io.write(head)
|
||||
indent = " " * (level + 1)
|
||||
@children.each do |k,v|
|
||||
@complex.each do |k,v|
|
||||
io.write "\n#{indent}"
|
||||
k.out(io , level + 1)
|
||||
io.write ":#{k}"
|
||||
io.write " "
|
||||
v.out(io , level + 1)
|
||||
end
|
||||
end
|
||||
|
||||
def short_out io , level
|
||||
io.write head
|
||||
end
|
||||
|
||||
def head
|
||||
body = @simple.collect {|a,val| ":#{a} => #{val.as_string(1)}"}.join(", ")
|
||||
"#{@name}(#{body})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -13,12 +13,17 @@ module Sof
|
||||
super(ref)
|
||||
@data = data
|
||||
end
|
||||
attr_reader :data
|
||||
|
||||
# A SimpleNode is always simple (aha).
|
||||
# accordingly there is no long_out
|
||||
def is_simple?
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
# just write the data given in construcor. simple. hence the name.
|
||||
def out io , level
|
||||
super(io,level)
|
||||
io.write(data)
|
||||
def short_out io , level
|
||||
io.write(@data)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,19 +66,11 @@ module Sof
|
||||
# small means only simple attributes and only 30 chars of them
|
||||
# object nodes are basically arrays (see there)
|
||||
def object_sof_node( object , level , ref)
|
||||
head = object.class.name + "("
|
||||
atts = {}
|
||||
node = ObjectNode.new(object.class.name , ref)
|
||||
attributes_for(object).each() do |a|
|
||||
val = get_value(object , a)
|
||||
next if val.nil?
|
||||
atts[a] = to_sof_node(val , level + 1)
|
||||
end
|
||||
immediate , extended = atts.partition {|a,val| val.is_a?(SimpleNode) }
|
||||
head += immediate.collect {|a,val| "#{a.to_sof()} => #{val.as_string(level + 1)}"}.join(", ") + ")"
|
||||
return SimpleNode.new(head) if( ref.nil? and extended.empty? and head.length < 30 )
|
||||
node = ObjectNode.new(head , ref)
|
||||
extended.each do |a , val|
|
||||
node.add( to_sof_node(a,level + 1) , val )
|
||||
node.add( a , to_sof_node( val , level + 1) )
|
||||
end
|
||||
node
|
||||
end
|
||||
|
Reference in New Issue
Block a user