lib/hanuman/graph.rb in wukong-3.0.0.pre vs lib/hanuman/graph.rb in wukong-3.0.0.pre2
- old
+ new
@@ -1,51 +1,75 @@
module Hanuman
+ class Graph < Stage
+ include TSort
- class Graph < Action
- collection :stages, Hanuman::Stage, :doc => 'the sequence of stages on this graph', :key_method => :name
- field :edges, Hash, :doc => 'connections among all stages on the graph', :default => {}
- include Hanuman::IsOwnInputSlot
- include Hanuman::IsOwnOutputSlot
+ field :stages, Hash, :default => {}
+ field :links, Array, :default => []
+
+ def tsort_each_node(&blk)
+ stages.keys.each(&blk)
+ end
- def next_name_for(stage, basename=nil)
- "#{basename || stage.class.handle}_#{stages.size}"
+ def tsort_each_child(node, &blk)
+ links.select{ |link| link.into == node }.map(&:from).each(&blk)
end
- def add_stage(stage)
- stage.write_attribute(:name, next_name_for(stage)) if stage.name.nil?
- stage.write_attribute(:owner, self)
- stages << stage
- stage
+ def directed_sort() self.tsort ; end
+ end
+
+ class GraphBuilder < StageBuilder
+ include TSort
+
+ field :stages, Hash, :default => {}
+ field :links, Array, :default => []
+
+ def define(&blk)
+ graph = for_class || define_class(label)
+ self.instance_eval(&blk) if block_given?
+ extract_links!
+ graph.register
end
- def connect(from_slot, into_slot)
- from_slot = lookup(from_slot)
- into_slot = lookup(into_slot)
- actual_from_slot = from_slot.set_output(into_slot)
- actual_into_slot = into_slot.set_input( from_slot)
- #
- edges[actual_from_slot] = actual_into_slot
- [from_slot, into_slot]
+ def build(options = {})
+ attrs = serialize
+ stages = attrs.delete(:stages).inject({}){ |hsh, (name, builder)| hsh[name] = builder.build(options) ; hsh }
+ for_class.receive attrs.merge(stages: stages)
end
- def lookup(ref)
- ref.is_a?(Symbol) ? resource(ref) : ref
+ def namespace() Hanuman::Graph ; end
+
+ def handle_dsl_arguments_for(stage, *args, &blk)
+ options = args.extract_options!
+ stage.merge!(options)
+ stage
end
- def tree(options={})
- super.merge( :stages => stages.to_a.map{|stage| stage.tree(options) } )
+ def extract_links!
+ stages.each_pair{ |name, builder| links << builder.links }
+ links.flatten!
end
+
+ def serialize
+ attrs = attributes
+ args = attrs.delete(:args)
+ attrs.delete(:for_class)
+ attrs.merge(args)
+ end
- def graph(name, &block)
- stage(name, :_type => Hanuman::Graph, &block)
+ def tsort_each_node(&blk)
+ stages.keys.each(&blk)
end
- def action(name, &block)
- stage(name, :_type => Hanuman::Action, &block)
+ def tsort_each_child(node, &blk)
+ links.select{ |link| link.into == node }.map(&:from).each(&blk)
end
- def resource(name, &block)
- stage(name, :_type => Hanuman::Resource, &block)
+ def directed_sort() self.tsort ; end
+
+ def clone
+ cloned_attrs = Hash[ serialize.select{ |key, val| key != :stages }.map{ |key, val| dup_key = key.dup rescue key ; dup_val = val.dup rescue val ; [ dup_key, dup_val ] } ]
+ cloned_links = links.map{ |link| link.dup }
+ cloned_stages = Hash[ stages.map{ |stage| stage.clone } ]
+ self.class.receive(cloned_attrs.merge(links: cloned_links).merge(stages: cloned_stages).merge(for_class: for_class))
end
end
-
end