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