summaryrefslogtreecommitdiffstats
path: root/lib/puppet/simple_graph.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/simple_graph.rb')
-rw-r--r--lib/puppet/simple_graph.rb82
1 files changed, 78 insertions, 4 deletions
diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb
index c8fa40e06..48bf4991e 100644
--- a/lib/puppet/simple_graph.rb
+++ b/lib/puppet/simple_graph.rb
@@ -54,8 +54,11 @@ class Puppet::SimpleGraph
# The other vertex in the edge.
def other_vertex(direction, edge)
- method = direction == :in ? :source : :target
- edge.send(method)
+ case direction
+ when :in: edge.source
+ else
+ edge.target
+ end
end
# Remove an edge from our list. Assumes that we've already checked
@@ -82,6 +85,17 @@ class Puppet::SimpleGraph
true
end
+ # Return a reversed version of this graph.
+ def reversal
+ result = self.class.new
+ vertices.each { |vertex| result.add_vertex!(vertex) }
+ edges.each do |edge|
+ newedge = edge.class.new(edge.target, edge.source, edge.label)
+ result.add_edge!(newedge)
+ end
+ result
+ end
+
# Return the size of the graph. Used by GRATR.
def size
@vertices.length
@@ -119,9 +133,9 @@ class Puppet::SimpleGraph
# Add a new edge. The graph user has to create the edge instance,
# since they have to specify what kind of edge it is.
- def add_edge!(source, target = nil)
+ def add_edge!(source, target = nil, label = nil)
if target
- edge = Puppet::Relationship.new(source, target)
+ edge = Puppet::Relationship.new(source, target, label)
else
edge = source
end
@@ -138,6 +152,11 @@ class Puppet::SimpleGraph
@edges.each_with_index { |test_edge, index| return test_edge if test_edge.source == source and test_edge.target == target }
end
+ def edge_label(source, target)
+ return nil unless edge = edge(source, target)
+ edge.label
+ end
+
# Is there an edge between the two vertices?
def edge?(source, target)
return false unless vertex?(source) and vertex?(target)
@@ -174,4 +193,59 @@ class Puppet::SimpleGraph
def setup_vertex(vertex)
@vertices[vertex] = VertexWrapper.new(vertex)
end
+
+ public
+
+ # LAK:FIXME This is just a paste of the GRATR code with slight modifications.
+
+ # Return a DOT::DOTDigraph for directed graphs or a DOT::DOTSubgraph for an
+ # undirected Graph. _params_ can contain any graph property specified in
+ # rdot.rb. If an edge or vertex label is a kind of Hash then the keys
+ # which match +dot+ properties will be used as well.
+ def to_dot_graph (params = {})
+ params['name'] ||= self.class.name.gsub(/:/,'_')
+ fontsize = params['fontsize'] ? params['fontsize'] : '8'
+ graph = (directed? ? DOT::DOTDigraph : DOT::DOTSubgraph).new(params)
+ edge_klass = directed? ? DOT::DOTDirectedEdge : DOT::DOTEdge
+ vertices.each do |v|
+ name = v.to_s
+ params = {'name' => '"'+name+'"',
+ 'fontsize' => fontsize,
+ 'label' => name}
+ v_label = vertex_label(v)
+ params.merge!(v_label) if v_label and v_label.kind_of? Hash
+ graph << DOT::DOTNode.new(params)
+ end
+ edges.each do |e|
+ params = {'from' => '"'+ e.source.to_s + '"',
+ 'to' => '"'+ e.target.to_s + '"',
+ 'fontsize' => fontsize }
+ e_label = edge_label(e)
+ params.merge!(e_label) if e_label and e_label.kind_of? Hash
+ graph << edge_klass.new(params)
+ end
+ graph
+ end
+
+ # Output the dot format as a string
+ def to_dot (params={}) to_dot_graph(params).to_s; end
+
+ # Call +dotty+ for the graph which is written to the file 'graph.dot'
+ # in the # current directory.
+ def dotty (params = {}, dotfile = 'graph.dot')
+ File.open(dotfile, 'w') {|f| f << to_dot(params) }
+ system('dotty', dotfile)
+ end
+
+ # Use +dot+ to create a graphical representation of the graph. Returns the
+ # filename of the graphics file.
+ def write_to_graphic_file (fmt='png', dotfile='graph')
+ src = dotfile + '.dot'
+ dot = dotfile + '.' + fmt
+
+ File.open(src, 'w') {|f| f << self.to_dot << "\n"}
+
+ system( "dot -T#{fmt} #{src} -o #{dot}" )
+ dot
+ end
end