ruby-graphviz 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - jruby
data/AUTHORS CHANGED
@@ -15,6 +15,7 @@ oupo <http://github.com/oupo>
15
15
  Daniel Zollinger <https://github.com/dznz>
16
16
  Ronen Barzel <https://github.com/ronen>
17
17
  Jamison Dance <https://github.com/jergason>
18
+ hirochachacha <https://github.com/hirochachacha>
18
19
 
19
20
  Thanks to :
20
21
 
@@ -16,6 +16,12 @@ Interface to the GraphViz graphing tool
16
16
 
17
17
  == CHANGELOG
18
18
 
19
+ === 1.0.2 :
20
+ * Add PageRank algorithm
21
+ * Major bug corrections
22
+ * Fix utils/colors.rb's case syntax
23
+ * Modify deprecated method: Hash#index to Hash#key
24
+
19
25
  === 1.0.1 :
20
26
  * Add GraphViz::DSL
21
27
  * Change project to use Bundler gem tools
data/Rakefile CHANGED
@@ -42,7 +42,13 @@ RDoc::Task.new do |rdoc|
42
42
  end
43
43
 
44
44
  Rake::TestTask.new(:test) do |t|
45
- t.test_files = FileList['test/test_*.rb']
45
+ require 'graphviz/utils'
46
+ include GVUtils
47
+ if find_executable("dot", nil).nil?
48
+ t.test_files = FileList['test/test_*.rb'].exclude("test/test_examples.rb")
49
+ else
50
+ t.test_files = FileList['test/test_*.rb']
51
+ end
46
52
  end
47
53
 
48
54
  Bundler::GemHelper.install_tasks
@@ -21,4 +21,4 @@ end
21
21
 
22
22
  puts "---------"
23
23
 
24
- puts hello_world.output( :dot => String )
24
+ puts hello_world.output( :canon => String )
@@ -39,15 +39,17 @@ puts "Symmetric ? #{t.symmetric?}"
39
39
 
40
40
  puts "Incidence matrix :"
41
41
  puts t.incidence_matrix
42
- # => [ 1 1 1 1 0 0 0 0 0 0]
43
- # [ 0 -1 0 0 1 1 1 0 0 0]
44
- # [ 0 0 0 0 -1 0 0 1 1 0]
45
- # [ 0 0 -1 0 0 -1 0 -1 0 1]
46
- # [ 0 0 0 0 0 0 -1 0 0 -1]
47
- # [ 0 0 0 -1 0 0 0 0 -1 0]
42
+ # => [ 1 1 1 0 0 0 0 0 0]
43
+ # [ -1 0 0 1 1 1 0 0 0]
44
+ # [ 0 0 0 -1 0 0 1 1 0]
45
+ # [ 0 -1 0 0 -1 0 -1 0 1]
46
+ # [ 0 0 0 0 0 -1 0 0 -1]
47
+ # [ 0 0 -1 0 0 0 0 -1 0]
48
48
 
49
49
  g.each_node do |name, node|
50
50
  puts "Degree of node `#{name}' = #{t.degree(node)}"
51
+ print "neighbors : "; p t.neighbors(name).map{ |e| e.id } # = node.neighbors.map { |e| e.id }
52
+ print "incidents : "; p t.incidents(name).map{ |e| e.id } # = node.incidents.map { |e| e.id }
51
53
  end
52
54
 
53
55
  puts "Laplacian matrix :"
@@ -78,4 +80,8 @@ puts "Your graph contains circuits" if rr.include?(nil)
78
80
  puts "Critical path : "
79
81
  rrr = t.critical_path
80
82
  print "\tPath "; p rrr[:path]
81
- puts "\tDistance : #{rrr[:distance]}"
83
+ puts "\tDistance : #{rrr[:distance]}"
84
+
85
+ t.pagerank.each { |node, rank|
86
+ puts "Pagerank for node #{node.id} = #{rank}"
87
+ }
@@ -93,31 +93,33 @@ class GraphViz
93
93
  # Return the GraphViz::Node object created
94
94
  #
95
95
  def add_node( xNodeName, hOpts = {} )
96
- return @hoNodes[xNodeName] || Proc.new {
96
+ node = @hoNodes[xNodeName]
97
+
98
+ if node.nil?
97
99
  @hoNodes[xNodeName] = GraphViz::Node::new( xNodeName, self )
98
100
  @hoNodes[xNodeName].index = @elements_order.size_of( "node" )
99
101
 
100
102
  unless hOpts.keys.include?(:label) or hOpts.keys.include?("label")
101
103
  hOpts[:label] = xNodeName
102
104
  end
103
-
104
- hOpts.each do |xKey, xValue|
105
- @hoNodes[xNodeName][xKey.to_s] = xValue
106
- end
107
105
 
108
106
  @elements_order.push( {
109
107
  "type" => "node",
110
108
  "name" => xNodeName,
111
109
  "value" => @hoNodes[xNodeName]
112
110
  } )
113
-
114
- return( @hoNodes[xNodeName] )
115
- }.call
111
+
112
+ node = @hoNodes[xNodeName]
113
+ end
114
+
115
+ hOpts.each do |xKey, xValue|
116
+ @hoNodes[xNodeName][xKey.to_s] = xValue
117
+ end
118
+
119
+ return node
116
120
  end
117
121
 
118
- #
119
- # Return the node object for the given name (or nil)
120
- #
122
+ # Return the node object for the given name (or nil) in the current graph
121
123
  def get_node( xNodeName, &block )
122
124
  node = @hoNodes[xNodeName] || nil
123
125
 
@@ -125,6 +127,23 @@ class GraphViz
125
127
 
126
128
  return node
127
129
  end
130
+
131
+ # Returns the first node found in the entire graph, starting from the root graph
132
+ def find_node(name)
133
+ root = root_graph
134
+ return root.search_node(name)
135
+ end
136
+
137
+ # Return the first node found in the current graph, and it subgraphs
138
+ def search_node(name)
139
+ n = get_node(name)
140
+ return n unless n.nil?
141
+ each_graph { |_, g|
142
+ n = g.search_node(name)
143
+ return n unless n.nil?
144
+ }
145
+ return nil
146
+ end
128
147
 
129
148
  #
130
149
  # Return the node object for the given index
@@ -764,6 +783,10 @@ class GraphViz
764
783
  complete
765
784
  end
766
785
 
786
+ # Return true if the graph is directed.
787
+ def directed?
788
+ not (/digraph/ =~ "bla digraph bla").nil?
789
+ end
767
790
  ## ----------------------------------------------------------------------------
768
791
 
769
792
  private
@@ -15,54 +15,49 @@
15
15
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
  class GraphViz
18
- class Attrs
19
- @data
20
- @name
21
- @attributs
22
- @graphviz
23
-
24
- attr_accessor :data
18
+ class Attrs
19
+ attr_accessor :data
25
20
 
26
- def initialize( gviz, name, attributs )
27
- @name = name
28
- @attributs = attributs
29
- @data = Hash::new( )
30
- @graphviz = gviz
31
- end
21
+ def initialize( gviz, name, attributs )
22
+ @name = name
23
+ @attributs = attributs
24
+ @data = Hash::new( )
25
+ @graphviz = gviz
26
+ end
32
27
 
33
- def each
34
- @data.each do |k, v|
35
- yield(k, v)
28
+ def each
29
+ @data.each do |k, v|
30
+ yield(k, v)
31
+ end
36
32
  end
37
- end
38
-
39
- def to_h
40
- @data.clone
41
- end
42
33
 
43
- def []( xKey )
44
- if xKey.class == Hash
45
- xKey.each do |k, v|
46
- self[k] = v
47
- end
48
- else
49
- if @data.key?( xKey.to_s ) == false
50
- nil
51
- end
52
- @data[xKey.to_s]
34
+ def to_h
35
+ @data.clone
53
36
  end
54
- end
55
-
56
- def []=( xKey, xValue )
57
- unless @attributs.keys.include?( xKey.to_s )
58
- raise ArgumentError, "#{@name} attribut '#{xKey.to_s}' invalid"
37
+
38
+ def []( key )
39
+ if key.class == Hash
40
+ key.each do |k, v|
41
+ self[k] = v
42
+ end
43
+ else
44
+ if @data.key?( key.to_s ) == false
45
+ nil
46
+ end
47
+ @data[key.to_s]
48
+ end
59
49
  end
60
-
61
- @data[xKey.to_s] = GraphViz::Types.const_get(@attributs[xKey.to_s]).new( xValue )
62
50
 
63
- if @graphviz.nil? == false
64
- @graphviz.set_position( @name, xKey.to_s, @data[xKey.to_s] )
51
+ def []=( key, value )
52
+ unless @attributs.keys.include?( key.to_s )
53
+ raise ArgumentError, "#{@name} attribut '#{key.to_s}' invalid"
54
+ end
55
+
56
+ @data[key.to_s] = GraphViz::Types.const_get(@attributs[key.to_s]).new( value )
57
+
58
+ if @graphviz.nil? == false
59
+ @graphviz.set_position( @name, key.to_s, @data[key.to_s] )
60
+ end
65
61
  end
66
- end
67
- end
62
+ end
68
63
  end
@@ -40,7 +40,7 @@
40
40
  # C => cluster
41
41
  #
42
42
  module Constants
43
- RGV_VERSION = "1.0.1"
43
+ RGV_VERSION = "1.0.2"
44
44
 
45
45
  ## Const: Output formats
46
46
  FORMATS = [
@@ -103,8 +103,8 @@ module Constants
103
103
  ## Const: graphs type
104
104
  GRAPHTYPE = [
105
105
  "digraph",
106
- "graph",
107
- "strict digraph"
106
+ "graph",
107
+ "strict digraph"
108
108
  ]
109
109
 
110
110
  def self.getAttrsFor( x )
@@ -63,4 +63,11 @@ class Hash
63
63
  yield( k, v ) unless (key_table.size > 0 and key_table.include?(k)) or (key_regexp.size > 0 and k.to_s.match(key_regexp)) or (value_table.size > 0 and value_table.include?(v)) or (value_regexp.size > 0 and v.to_s.match(value_regexp))
64
64
  end
65
65
  end
66
+
67
+ unless self.method_defined? :key
68
+ # Add Hash#key to Ruby < 1.9
69
+ def key(v)
70
+ index(v)
71
+ end
72
+ end
66
73
  end
@@ -3,12 +3,13 @@ require 'graphviz'
3
3
  class GraphViz::DSL
4
4
  attr_accessor :graph
5
5
 
6
- def initialize(name, hOpts = {}, &block)
7
- @graph = GraphViz.new(name, hOpts)
6
+ # Create a new graph
7
+ def initialize(name, options = {}, &block)
8
+ @graph = GraphViz.new(name, options)
8
9
  instance_eval(&block) if block
9
10
  end
10
11
 
11
- def method_missing(sym, *args, &block)
12
+ def method_missing(sym, *args, &block) #:nodoc:
12
13
  return @graph.get_graph(sym.to_s) unless @graph.get_graph(sym.to_s).nil?
13
14
  return @graph.get_node(sym.to_s) unless @graph.get_node(sym.to_s).nil?
14
15
  if(@graph.respond_to?(sym, true))
@@ -20,11 +21,13 @@ class GraphViz::DSL
20
21
  end
21
22
  end
22
23
 
24
+ # Add a new node
23
25
  def n(name)
24
26
  return @graph.get_node(name) unless @graph.get_node(name.to_s).nil?
25
27
  @graph.add_node(name)
26
28
  end
27
29
 
30
+ # Create edges
28
31
  def e(*args)
29
32
  e = nil
30
33
  last = args.shift
@@ -35,25 +38,30 @@ class GraphViz::DSL
35
38
  return e
36
39
  end
37
40
 
41
+ # Add a subgraph
38
42
  def subgraph(name, &block)
39
43
  @graph.add_graph(GraphViz::DSL.new(name, { :parent => @graph, :type => @graph.type }, &block).graph)
40
44
  end
41
45
  alias :cluster :subgraph
42
46
 
43
- def output(hOpts = {})
44
- @graph.output(hOpts)
47
+ # Generate output
48
+ def output(options = {})
49
+ @graph.output(options)
45
50
  end
46
51
  end
47
52
 
48
- def graph(name, hOpts = {}, &block)
49
- GraphViz::DSL.new(name, hOpts.merge( { :type => "graph" } ), &block).graph
53
+ # Create a new undirected graph
54
+ def graph(name, options = {}, &block)
55
+ GraphViz::DSL.new(name, options.merge( { :type => "graph" } ), &block).graph
50
56
  end
51
57
 
52
- def digraph(name, hOpts = {}, &block)
53
- GraphViz::DSL.new(name, hOpts.merge( { :type => "digraph" } ), &block).graph
58
+ # Create a new directed graph
59
+ def digraph(name, options = {}, &block)
60
+ GraphViz::DSL.new(name, options.merge( { :type => "digraph" } ), &block).graph
54
61
  end
55
62
 
56
- def strict(name, hOpts = {}, &block)
57
- GraphViz::DSL.new(name, hOpts.merge( { :type => "strict digraph" } ), &block).graph
63
+ # Create a new strict directed graph
64
+ def strict(name, options = {}, &block)
65
+ GraphViz::DSL.new(name, options.merge( { :type => "strict digraph" } ), &block).graph
58
66
  end
59
67
 
@@ -18,196 +18,176 @@ require 'graphviz/attrs'
18
18
  require 'graphviz/constants'
19
19
 
20
20
  class GraphViz
21
- class Edge
22
- include Constants
23
- @xNodeOne
24
- @xNodeOnePort
25
- @xNodeTwo
26
- @xNodeTwoPort
27
- @oAttrEdge
28
- @oGParrent
29
-
30
- #
31
- # Create a new edge
32
- #
33
- # In:
34
- # * vNodeOne : First node (can be a GraphViz::Node or a node ID)
35
- # * vNodeTwo : Second node (can be a GraphViz::Node or a node ID)
36
- # * oGParrent : Graph
37
- #
38
- def initialize( vNodeOne, vNodeTwo, oGParrent )
39
- @xNodeOne, @xNodeOnePort = getNodeNameAndPort( vNodeOne )
40
- # if vNodeOne.class == String
41
- # @xNodeOne = vNodeOne
42
- # else
43
- # @xNodeOne = vNodeOne.id
44
- # end
45
- @xNodeTwo, @xNodeTwoPort = getNodeNameAndPort( vNodeTwo )
46
- # if vNodeTwo.class == String
47
- # @xNodeTwo = vNodeTwo
48
- # else
49
- # @xNodeTwo = vNodeTwo.id
50
- # end
51
-
52
- @oGParrent = oGParrent
53
-
54
- @oAttrEdge = GraphViz::Attrs::new( nil, "edge", EDGESATTRS )
55
-
56
- @index = nil
57
- end
58
-
59
- # Return the node one as string (so with port if any)
60
- def node_one( with_port = true )
61
- if @xNodeOnePort.nil? or with_port == false
62
- GraphViz.escape(@xNodeOne)
63
- else
64
- GraphViz.escape(@xNodeOne, :force => true) + ":#{@xNodeOnePort}"
21
+ class Edge
22
+ include Constants
23
+
24
+ # Create a new edge
25
+ #
26
+ # In:
27
+ # * vNodeOne : First node (can be a GraphViz::Node or a node ID)
28
+ # * vNodeTwo : Second node (can be a GraphViz::Node or a node ID)
29
+ # * parent_graph : Graph
30
+ def initialize( vNodeOne, vNodeTwo, parent_graph )
31
+ @node_one_id, @node_one_port = getNodeNameAndPort( vNodeOne )
32
+ @node_two_id, @node_two_port = getNodeNameAndPort( vNodeTwo )
33
+
34
+ @parent_graph = parent_graph
35
+ @edge_attributs = GraphViz::Attrs::new( nil, "edge", EDGESATTRS )
36
+ @index = nil
37
+
38
+ unless @parent_graph.directed?
39
+ (@parent_graph.find_node(@node_one_id) || @parent_graph.add_node(@node_one_id)).incidents << (@parent_graph.find_node(@node_two_id) || @parent_graph.add_node(@node_two_id))
40
+ (@parent_graph.find_node(@node_two_id) || @parent_graph.add_node(@node_two_id)).neighbors << (@parent_graph.find_node(@node_one_id) || @parent_graph.add_node(@node_one_id))
41
+ end
42
+ (@parent_graph.find_node(@node_one_id) || @parent_graph.add_node(@node_one_id)).neighbors << (@parent_graph.find_node(@node_two_id) || @parent_graph.add_node(@node_two_id))
43
+ (@parent_graph.find_node(@node_two_id) || @parent_graph.add_node(@node_two_id)).incidents << (@parent_graph.find_node(@node_one_id) || @parent_graph.add_node(@node_one_id))
44
+ end
45
+
46
+ # Return the node one as string (so with port if any)
47
+ def node_one( with_port = true )
48
+ if @node_one_port.nil? or with_port == false
49
+ GraphViz.escape(@node_one_id)
50
+ else
51
+ GraphViz.escape(@node_one_id, :force => true) + ":#{@node_one_port}"
52
+ end
53
+ end
54
+ alias :tail_node :node_one
55
+
56
+ # Return the node two as string (so with port if any)
57
+ def node_two( with_port = true )
58
+ if @node_two_port.nil? or with_port == false
59
+ GraphViz.escape(@node_two_id)
60
+ else
61
+ GraphViz.escape(@node_two_id, :force => true) + ":#{@node_two_port}"
62
+ end
63
+ end
64
+ alias :head_node :node_two
65
+
66
+ # Return the index of the edge
67
+ def index
68
+ @index
69
+ end
70
+ def index=(i) #:nodoc:
71
+ @index = i if @index == nil
72
+ end
73
+
74
+ # Set value +attribut_value+ to the edge attribut +attribut_name+
75
+ def []=( attribut_name, attribut_value )
76
+ attribut_value = attribut_value.to_s if attribut_value.class == Symbol
77
+ @edge_attributs[attribut_name.to_s] = attribut_value
78
+ end
79
+
80
+ # Set values for edge attributs or
81
+ # get the value of the given edge attribut +attribut_name+
82
+ def []( attribut_name )
83
+ # Modification by axgle (http://github.com/axgle)
84
+ if Hash === attribut_name
85
+ attribut_name.each do |key, value|
86
+ self[key] = value
87
+ end
88
+ else
89
+ if @edge_attributs[attribut_name.to_s]
90
+ @edge_attributs[attribut_name.to_s].clone
91
+ else
92
+ nil
93
+ end
94
+ end
65
95
  end
66
- end
67
- alias :tail_node :node_one
68
-
69
- # Return the node two as string (so with port if any)
70
- def node_two( with_port = true )
71
- if @xNodeTwoPort.nil? or with_port == false
72
- GraphViz.escape(@xNodeTwo)
73
- else
74
- GraphViz.escape(@xNodeTwo, :force => true) + ":#{@xNodeTwoPort}"
96
+
97
+ #
98
+ # Calls block once for each attribut of the edge, passing the name and value to the
99
+ # block as a two-element array.
100
+ #
101
+ # If global is set to false, the block does not receive the attributs set globally
102
+ #
103
+ def each_attribut(global = true, &b)
104
+ attrs = @edge_attributs.to_h
105
+ if global
106
+ attrs = pg.edge.to_h.merge attrs
107
+ end
108
+ attrs.each do |k,v|
109
+ yield(k,v)
110
+ end
75
111
  end
76
- end
77
- alias :head_node :node_two
78
- #
79
- # Return the index of the edge
80
- #
81
- def index
82
- @index
83
- end
84
- def index=(i) #:nodoc:
85
- @index = i if @index == nil
86
- end
87
-
88
- #
89
- # Set value +xAttrValue+ to the edge attribut +xAttrName+
90
- #
91
- def []=( xAttrName, xAttrValue )
92
- xAttrValue = xAttrValue.to_s if xAttrValue.class == Symbol
93
- @oAttrEdge[xAttrName.to_s] = xAttrValue
94
- end
95
-
96
- #
97
- # Set values for edge attributs or
98
- # get the value of the given edge attribut +xAttrName+
99
- #
100
- def []( xAttrName )
101
- # Modification by axgle (http://github.com/axgle)
102
- if Hash === xAttrName
103
- xAttrName.each do |key, value|
104
- self[key] = value
105
- end
106
- else
107
- if @oAttrEdge[xAttrName.to_s]
108
- @oAttrEdge[xAttrName.to_s].clone
109
- else
110
- nil
111
- end
112
+
113
+ def <<( node ) #:nodoc:
114
+ n = @parent_graph.get_node(@node_two_id)
115
+
116
+ GraphViz::commonGraph( node, n ).add_edge( n, node )
112
117
  end
113
- end
114
-
115
- #
116
- # Calls block once for each attribut of the edge, passing the name and value to the
117
- # block as a two-element array.
118
- #
119
- # If global is set to false, the block does not receive the attributs set globally
120
- #
121
- def each_attribut(global = true, &b)
122
- attrs = @oAttrEdge.to_h
123
- if global
124
- attrs = pg.edge.to_h.merge attrs
118
+ alias :> :<< #:nodoc:
119
+ alias :- :<< #:nodoc:
120
+ alias :>> :<< #:nodoc:
121
+
122
+ #
123
+ # Return the root graph
124
+ #
125
+ def root_graph
126
+ return( (self.pg.nil?) ? nil : self.pg.root_graph )
125
127
  end
126
- attrs.each do |k,v|
127
- yield(k,v)
128
+
129
+ def pg #:nodoc:
130
+ @parent_graph
131
+ end
132
+
133
+ # Set edge attributs
134
+ #
135
+ # Example :
136
+ # e = graph.add_edge( ... )
137
+ # ...
138
+ # e.set { |_e|
139
+ # _e.color = "blue"
140
+ # _e.fontcolor = "red"
141
+ # }
142
+ def set( &b )
143
+ yield( self )
128
144
  end
129
- end
130
-
131
- def <<( oNode ) #:nodoc:
132
- n = @oGParrent.get_node(@xNodeTwo)
133
-
134
- GraphViz::commonGraph( oNode, n ).add_edge( n, oNode )
135
- end
136
- alias :> :<< #:nodoc:
137
- alias :- :<< #:nodoc:
138
- alias :>> :<< #:nodoc:
139
-
140
- #
141
- # Return the root graph
142
- #
143
- def root_graph
144
- return( (self.pg.nil?) ? nil : self.pg.root_graph )
145
- end
146
-
147
- def pg #:nodoc:
148
- @oGParrent
149
- end
150
-
151
- #
152
- # Set edge attributs
153
- #
154
- # Example :
155
- # e = graph.add_edge( ... )
156
- # ...
157
- # e.set { |_e|
158
- # _e.color = "blue"
159
- # _e.fontcolor = "red"
160
- # }
161
- #
162
- def set( &b )
163
- yield( self )
164
- end
165
-
166
- # Add edge options
167
- # use edge.<option>=<value> or edge.<option>( <value> )
168
- def method_missing( idName, *args, &block ) #:nodoc:
169
- return if idName == :to_ary # ruby 1.9.2 fix
170
- xName = idName.id2name
171
-
172
- self[xName.gsub( /=$/, "" )]=args[0]
173
- end
174
-
175
- def output( oGraphType ) #:nodoc:
176
- xLink = " -> "
177
- if oGraphType == "graph"
178
- xLink = " -- "
179
- end
180
-
181
- xOut = self.node_one + xLink + self.node_two
182
- xAttr = ""
183
- xSeparator = ""
184
- @oAttrEdge.data.each do |k, v|
185
- xAttr << xSeparator + k + " = " + v.to_gv
186
- xSeparator = ", "
145
+
146
+ # Add edge options
147
+ # use edge.<option>=<value> or edge.<option>( <value> )
148
+ def method_missing( idName, *args, &block ) #:nodoc:
149
+ return if idName == :to_ary # ruby 1.9.2 fix
150
+ xName = idName.id2name
151
+
152
+ self[xName.gsub( /=$/, "" )]=args[0]
187
153
  end
188
- if xAttr.length > 0
189
- xOut << " [" + xAttr + "]"
154
+
155
+ def output( oGraphType ) #:nodoc:
156
+ xLink = " -> "
157
+ if oGraphType == "graph"
158
+ xLink = " -- "
159
+ end
160
+
161
+ xOut = self.node_one + xLink + self.node_two
162
+ xAttr = ""
163
+ xSeparator = ""
164
+ @edge_attributs.data.each do |k, v|
165
+ xAttr << xSeparator + k + " = " + v.to_gv
166
+ xSeparator = ", "
167
+ end
168
+ if xAttr.length > 0
169
+ xOut << " [" + xAttr + "]"
170
+ end
171
+ xOut + ";"
172
+
173
+ return( xOut )
190
174
  end
191
- xOut + ";"
192
-
193
- return( xOut )
194
- end
195
-
196
- private
197
- def getNodeNameAndPort( node )
198
- name, port = nil, nil
199
- if node.class == Hash
200
- node.each do |k, v|
201
- name, port = getNodeNameAndPort(k)
202
- port = v
203
- end
204
- elsif node.class == String
205
- name = node
206
- else
207
- name = node.id
175
+
176
+ private
177
+ def getNodeNameAndPort( node )
178
+ name, port = nil, nil
179
+ if node.class == Hash
180
+ node.each do |k, v|
181
+ name, port = getNodeNameAndPort(k)
182
+ port = v
183
+ end
184
+ elsif node.class == String
185
+ name = node
186
+ else
187
+ name = node.id
188
+ end
189
+
190
+ return name, port
208
191
  end
209
-
210
- return name, port
211
- end
212
- end
192
+ end
213
193
  end