Class: T2Flow::Dot

Inherits:
Object
  • Object
show all
Defined in:
lib/t2flow/dot.rb

Overview

This class enables you to write the script will will be used by dot (which is part of GraphViz) to generate the image showing the structure of a given model. To get started quickly, you could try:

out_file = File.new("path/to/file/you/want/the/dot/script/to/be/written", "w+")
workflow = File.new("path/to/workflow/file", "r").read
model = T2Flow::Parser.new.parse(workflow)
T2Flow::Dot.new.write_dot(out_file, model)
`dot -Tpng -o"path/to/the/output/image" #{out_file.path}`

Constant Summary collapse

PROCESSOR_COLOURS =
{
    :apiconsumer =>  "#98fb98", #palegreen
    :beanshell =>  "#deb887", #burlywood2
    :biomart =>  "#d1eeee", #lightcyan2
    :localworker =>  "#d15fee",  #mediumorchid2
    :biomobywsdl =>  "#ffb90f", #darkgoldenrod1
    :biomoby =>  "#ffb90f",  #darkgoldenrod1
    :biomobyobject =>  "#ffd700",  #gold
    :biomobyparser =>  "#ffffff",  #white
    :inferno =>  "violetred1",
    :notification =>  "mediumorchid2",
    :rdfgenerator =>  "purple",
    :rserv =>  "lightgoldenrodyellow",
    :seqhound =>  "#836fff",
    :soaplabwsdl =>  "#fafad2",
    :soaplab =>  "#fafad2",
    :stringconstant =>  "#b0c4de",
    :talisman =>  "plum2",
    :bsf =>  "burlywood2",
    :abstractprocessor =>  "lightgoldenrodyellow",
    :xmlsplitter =>  "#ab92ea",
    :rshell =>  "#648faa",
    :arbitrarywsdl =>  "darkolivegreen3",
    :wsdl =>  "#a2cd5a",
    :workflow =>  "crimson",
    :rest =>  "#7aafff",
    :xpath =>  "#e6ff5e",
    :externaltool =>  "#f28c55",
    :spreadsheet =>  "#40e0d0",
    :dataflow =>  "#ffc0cb",
    :interaction =>  "#6aeb9f",
    :component =>  "#e693d2"
}
FILL_COLOURS =
%w{white aliceblue antiquewhite beige}
RANK_SEP =
'0.22'
NODE_SEP =
'0.05'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDot

Creates a new dot object for interaction.



63
64
65
66
# File 'lib/t2flow/dot.rb', line 63

def initialize
  # @port_style IS CURRENTLY UNUSED. IGNORE!!!
  @port_style = 'none' # 'all', 'bound' or 'none'
end

Class Method Details

.is_processor?(processor_name) ⇒ Boolean

Returns true if the given name is a processor; false otherwise

Returns:

  • (Boolean)


259
260
261
# File 'lib/t2flow/dot.rb', line 259

def Dot.is_processor?(processor_name)
  true if get_colour(processor_name)
end

Instance Method Details

#get_colour(processor_name) ⇒ Object

:nodoc:



249
250
251
252
253
254
255
256
# File 'lib/t2flow/dot.rb', line 249

def get_colour(processor_name) # :nodoc:
  colour = PROCESSOR_COLOURS[processor_name.to_sym]
  if colour
    colour
  else 
    'white'
  end  
end

#write_coordination(stream, coordination, dataflow, prefix) ⇒ Object

:nodoc:



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/t2flow/dot.rb', line 232

def write_coordination(stream, coordination, dataflow, prefix) # :nodoc:
  stream.write " \"#{prefix}#{coordination.control}" 
  processor = dataflow.processors.select{|p| p.name == coordination.control}[0]
  
  stream.write 'WORKFLOWINTERNALSINKCONTROL' if "#{processor.type}" == "workflow"
  stream.write '"->"'
  stream.write "#{prefix}#{coordination.target}"
  processor = dataflow.processors.select{|p| p.name == coordination.target}[0]
  stream.write 'WORKFLOWINTERNALSOURCECONTROL' if "#{processor.type}" == "workflow"
  stream.write "\""
  stream.puts ' ['
  stream.puts '  color="gray",'
  stream.puts '  arrowhead="odot",'
  stream.puts '  arrowtail="none"'
  stream.puts ' ];'
end

#write_dataflow(stream, dataflow, prefix = "", name = "", depth = 0) ⇒ Object

:nodoc:



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/t2flow/dot.rb', line 110

def write_dataflow(stream, dataflow, prefix="", name="", depth=0) # :nodoc:
  if name != ""
    stream.puts "subgraph cluster_#{prefix}#{name} {"
    stream.puts " label=\"#{name}\""
    stream.puts ' fontname="Helvetica"'
    stream.puts ' fontsize="10"'
    stream.puts ' fontcolor="black"'
    stream.puts ' clusterrank="local"'
    stream.puts " fillcolor=\"#{FILL_COLOURS[depth % FILL_COLOURS.length]}\""
    stream.puts ' style="filled"'
  end
  dataflow.processors.each {|processor| write_processor(stream, processor, prefix, depth)}
  write_source_cluster(stream, dataflow.sources, prefix)
  write_sink_cluster(stream, dataflow.sinks, prefix)
  dataflow.datalinks.each {|link| write_link(stream, link, dataflow, prefix)}
  dataflow.coordinations.each {|coordination| write_coordination(stream, coordination, dataflow, prefix)}
  if name != ""
    stream.puts '}'
  end
end

#write_dot(stream, model) ⇒ Object

Writes to the given stream (File, StringIO, etc) the script to generate the image showing the internals of the given workflow model.

Usage

stream = File.new("path/to/file/you/want/the/dot/script/to/be/written", "w+")
workflow = .......
model = T2Flow::Parser.new.parse(workflow)
T2Flow::Dot.new.write_dot(stream, model)


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/t2flow/dot.rb', line 75

def write_dot(stream, model)
  @t2flow_model = model
  stream.puts 'digraph t2flow_graph {'
  stream.puts ' graph ['
  stream.puts '  style=""'
  stream.puts '  labeljust="left"'
  stream.puts '  clusterrank="local"'
  stream.puts "  ranksep=\"#RANK_SEP\""
  stream.puts "  nodesep=\"#NODE_SEP\""
  stream.puts ' ]'
  stream.puts
  stream.puts ' node ['
  stream.puts '  fontname="Helvetica",'
  stream.puts '  fontsize="10",'
  stream.puts '  fontcolor="black", '
  stream.puts '  shape="box",'
  stream.puts '  height="0",'
  stream.puts '  width="0",'
  stream.puts '  color="black",'
  stream.puts '  fillcolor="lightgoldenrodyellow",'
  stream.puts '  style="filled"'
  stream.puts ' ];'
  stream.puts
  stream.puts ' edge ['
  stream.puts '  fontname="Helvetica",'
  stream.puts '  fontsize="8",'
  stream.puts '  fontcolor="black",'
  stream.puts '  color="black"'
  stream.puts ' ];'
  write_dataflow(stream, model.main)
  stream.puts '}'
  
  stream.flush
end

:nodoc:



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/t2flow/dot.rb', line 206

def write_link(stream, link, dataflow, prefix) # :nodoc:
  if dataflow.sources.select{|s| s.name == link.source} != []
    stream.write " \"#{prefix}WORKFLOWINTERNALSOURCE_#{link.source}\""
  else 
    processor = dataflow.processors.select{|p| p.name == link.source.split(':')[0]}[0]
    if "#{processor.type}" == "workflow"
      stream.write " \"#{prefix}#{processor.name}WORKFLOWINTERNALSINK_#{link.source.split(':')[1]}\""
    else
      stream.write " \"#{prefix}#{processor.name}\""
    end
  end
  stream.write '->'
  if dataflow.sinks.select{|s| s.name == link.sink} != []
    stream.write "\"#{prefix}WORKFLOWINTERNALSINK_#{link.sink}\""
  else 
    processor = dataflow.processors.select{|p| p.name == link.sink.split(':')[0]}[0]
    if "#{processor.type}" == "workflow"
      stream.write "\"#{prefix}#{processor.name}WORKFLOWINTERNALSOURCE_#{link.sink.split(':')[1]}\""
    else
      stream.write "\"#{prefix}#{processor.name}\""
    end
  end
  stream.puts ' ['
  stream.puts ' ];'
end

#write_processor(stream, processor, prefix, depth) ⇒ Object

:nodoc:



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/t2flow/dot.rb', line 131

def write_processor(stream, processor, prefix, depth) # :nodoc:
  # nested workflows
  if "#{processor.type}" == "workflow"
    dataflow = @t2flow_model.dataflow(processor.dataflow_id)
    write_dataflow(stream, dataflow, prefix + processor.name, processor.name, depth.next)
  else
    stream.puts " \"#{prefix}#{processor.name}\" ["
    stream.puts "  fillcolor=\"#{get_colour processor.type}\","
    stream.puts '  shape="box",'
    stream.puts '  style="filled",'
    stream.puts '  height="0",'
    stream.puts '  width="0",'
    stream.puts "  label=\"#{processor.name}\""
    stream.puts ' ];'
  end
end

#write_sink(stream, sink, prefix) ⇒ Object

:nodoc:



196
197
198
199
200
201
202
203
204
# File 'lib/t2flow/dot.rb', line 196

def write_sink(stream, sink, prefix) # :nodoc:
  stream.puts " \"#{prefix}WORKFLOWINTERNALSINK_#{sink.name}\" ["
  stream.puts '   shape="box",'
  stream.puts "   label=\"#{sink.name}\""
  stream.puts '   width="0",'
  stream.puts '   height="0",'
  stream.puts '   fillcolor="lightsteelblue2"'
  stream.puts ' ]'     
end

#write_sink_cluster(stream, sinks, prefix) ⇒ Object

:nodoc:



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/t2flow/dot.rb', line 177

def write_sink_cluster(stream, sinks, prefix) # :nodoc:
  stream.puts " subgraph cluster_#{prefix}sinks {"
  stream.puts '  style="dotted"'
  stream.puts '  label="Workflow Outputs"'
  stream.puts '  fontname="Helvetica"'
  stream.puts '  fontsize="10"'
  stream.puts '  fontcolor="black"'
  stream.puts '  rank="same"'
  stream.puts " \"#{prefix}WORKFLOWINTERNALSINKCONTROL\" ["
  stream.puts '  shape="invtriangle",'
  stream.puts '  width="0.2",'
  stream.puts '  height="0.2",'
  stream.puts '  fillcolor="chartreuse3"'
  stream.puts '  label=""'
  stream.puts ' ]'
  sinks.each {|sink| write_sink(stream, sink, prefix)}
  stream.puts ' }'
end

#write_source(stream, source, prefix) ⇒ Object

:nodoc:



167
168
169
170
171
172
173
174
175
# File 'lib/t2flow/dot.rb', line 167

def write_source(stream, source, prefix) # :nodoc:
  stream.puts " \"#{prefix}WORKFLOWINTERNALSOURCE_#{source.name}\" ["
  stream.puts '   shape="box",'
  stream.puts "   label=\"#{source.name}\""
  stream.puts '   width="0",'
  stream.puts '   height="0",'
  stream.puts '   fillcolor="skyblue"'
  stream.puts ' ]' 
end

#write_source_cluster(stream, sources, prefix) ⇒ Object

:nodoc:



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/t2flow/dot.rb', line 148

def write_source_cluster(stream, sources, prefix) # :nodoc:
  stream.puts " subgraph cluster_#{prefix}sources {"
  stream.puts '  style="dotted"'
  stream.puts '  label="Workflow Inputs"'
  stream.puts '  fontname="Helvetica"'
  stream.puts '  fontsize="10"'
  stream.puts '  fontcolor="black"'
  stream.puts '  rank="same"'
  stream.puts " \"#{prefix}WORKFLOWINTERNALSOURCECONTROL\" ["
  stream.puts '  shape="triangle",'
  stream.puts '  width="0.2",'
  stream.puts '  height="0.2",'
  stream.puts '  fillcolor="brown1"'
  stream.puts '  label=""'
  stream.puts ' ]'
  sources.each {|source| write_source(stream, source, prefix)}
  stream.puts ' }'
end