mannie-taverna-scufl 0.6.0
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.
- data/LICENCE +165 -0
- data/README +133 -0
- data/lib/baclava/reader.rb +61 -0
- data/lib/baclava/writer.rb +82 -0
- data/lib/document/data.rb +24 -0
- data/lib/document/report.rb +91 -0
- data/lib/enactor/client.rb +673 -0
- data/lib/scufl/dot.rb +248 -0
- data/lib/scufl/model.rb +153 -0
- data/lib/scufl/parser.rb +162 -0
- data/test/fixtures/animal.xml +10 -0
- data/test/fixtures/colouranimal.xml +14 -0
- data/test/tc_client.rb +191 -0
- data/test/ts_taverna.rb +4 -0
- metadata +95 -0
data/lib/scufl/dot.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
module Scufl
|
2
|
+
|
3
|
+
# This class enables you to write the script will will be used by dot
|
4
|
+
# (which is part of GraphViz[http://www.graphviz.org/Download.php])
|
5
|
+
# to generate the image showing the structure of a given model.
|
6
|
+
# To get started quickly, you could try:
|
7
|
+
# out_file = File.new("path/to/file/you/want/the/dot/script/to/be/written", "w+")
|
8
|
+
# workflow = File.new("path/to/workflow/file", "r").read
|
9
|
+
# model = Scufl::Parser.new.parse(workflow)
|
10
|
+
# Scufl::Dot.new.write_dot(out_file, model)
|
11
|
+
# `dot -Tpng -o"path/to/the/output/image" #{out_file.path}`
|
12
|
+
class Dot
|
13
|
+
|
14
|
+
@@processor_colours = {
|
15
|
+
'apiconsumer' => 'palegreen',
|
16
|
+
'beanshell' => 'burlywood2',
|
17
|
+
'biomart' => 'lightcyan2',
|
18
|
+
'local' => 'mediumorchid2',
|
19
|
+
'biomobywsdl' => 'darkgoldenrod1',
|
20
|
+
'biomobyobject' => 'gold',
|
21
|
+
'biomobyparser' => 'white',
|
22
|
+
'inferno' => 'violetred1',
|
23
|
+
'notification' => 'mediumorchid2',
|
24
|
+
'rdfgenerator' => 'purple',
|
25
|
+
'rserv' => 'lightgoldenrodyellow',
|
26
|
+
'seqhound' => '#836fff',
|
27
|
+
'soaplabwsdl' => 'lightgoldenrodyellow',
|
28
|
+
'stringconstant' => 'lightsteelblue',
|
29
|
+
'talisman' => 'plum2',
|
30
|
+
'bsf' => 'burlywood2',
|
31
|
+
'abstractprocessor' => 'lightgoldenrodyellow',
|
32
|
+
'rshell' => 'lightgoldenrodyellow',
|
33
|
+
'arbitrarywsdl' => 'darkolivegreen3',
|
34
|
+
'workflow' => 'crimson'}
|
35
|
+
|
36
|
+
@@fill_colours = %w{white aliceblue antiquewhite beige}
|
37
|
+
|
38
|
+
@@ranksep = '0.22'
|
39
|
+
@@nodesep = '0.05'
|
40
|
+
|
41
|
+
# Creates a new dot object for interaction.
|
42
|
+
def initialize
|
43
|
+
# @port_style IS CURRENTLY UNUSED. IGNORE!!!
|
44
|
+
@port_style = 'none' # 'all', 'bound' or 'none'
|
45
|
+
end
|
46
|
+
|
47
|
+
# Writes to the given stream (File, StringIO, etc) the script to generate
|
48
|
+
# the image showing the internals of the given workflow model.
|
49
|
+
# === Usage
|
50
|
+
# stream = File.new("path/to/file/you/want/the/dot/script/to/be/written", "w+")
|
51
|
+
# workflow = .......
|
52
|
+
# model = Scufl::Parser.new.parse(workflow)
|
53
|
+
# Scufl::Dot.new.write_dot(stream, model)
|
54
|
+
def write_dot(stream, model)
|
55
|
+
stream.puts 'digraph scufl_graph {'
|
56
|
+
stream.puts ' graph ['
|
57
|
+
stream.puts ' style=""'
|
58
|
+
stream.puts ' labeljust="left"'
|
59
|
+
stream.puts ' clusterrank="local"'
|
60
|
+
stream.puts " ranksep=\"#@@ranksep\""
|
61
|
+
stream.puts " nodesep=\"#@@nodesep\""
|
62
|
+
stream.puts ' ]'
|
63
|
+
stream.puts
|
64
|
+
stream.puts ' node ['
|
65
|
+
stream.puts ' fontname="Helvetica",'
|
66
|
+
stream.puts ' fontsize="10",'
|
67
|
+
stream.puts ' fontcolor="black", '
|
68
|
+
stream.puts ' shape="box",'
|
69
|
+
stream.puts ' height="0",'
|
70
|
+
stream.puts ' width="0",'
|
71
|
+
stream.puts ' color="black",'
|
72
|
+
stream.puts ' fillcolor="lightgoldenrodyellow",'
|
73
|
+
stream.puts ' style="filled"'
|
74
|
+
stream.puts ' ];'
|
75
|
+
stream.puts
|
76
|
+
stream.puts ' edge ['
|
77
|
+
stream.puts ' fontname="Helvetica",'
|
78
|
+
stream.puts ' fontsize="8",'
|
79
|
+
stream.puts ' fontcolor="black",'
|
80
|
+
stream.puts ' color="black"'
|
81
|
+
stream.puts ' ];'
|
82
|
+
write_workflow(stream, model)
|
83
|
+
stream.puts '}'
|
84
|
+
|
85
|
+
stream.flush
|
86
|
+
end
|
87
|
+
|
88
|
+
def write_workflow(stream, model, prefix="", name="", depth=0) # :nodoc:
|
89
|
+
if name != ""
|
90
|
+
stream.puts "subgraph cluster_#{prefix}#{name} {"
|
91
|
+
stream.puts " label=\"#{name}\""
|
92
|
+
stream.puts ' fontname="Helvetica"'
|
93
|
+
stream.puts ' fontsize="10"'
|
94
|
+
stream.puts ' fontcolor="black"'
|
95
|
+
stream.puts ' clusterrank="local"'
|
96
|
+
stream.puts " fillcolor=\"#{@@fill_colours[depth % @@fill_colours.length]}\""
|
97
|
+
stream.puts ' style="filled"'
|
98
|
+
end
|
99
|
+
model.processors.each {|processor| write_processor(stream, processor, prefix, depth)}
|
100
|
+
write_source_cluster(stream, model.sources, prefix)
|
101
|
+
write_sink_cluster(stream, model.sinks, prefix)
|
102
|
+
model.links.each {|link| write_link(stream, link, model, prefix)}
|
103
|
+
model.coordinations.each {|coordination| write_coordination(stream, coordination, model, prefix)}
|
104
|
+
if name != ""
|
105
|
+
stream.puts '}'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def write_processor(stream, processor, prefix, depth) # :nodoc:
|
110
|
+
# nested workflows
|
111
|
+
if processor.model
|
112
|
+
write_workflow(stream, processor.model, prefix + processor.name, processor.name, depth.next)
|
113
|
+
else
|
114
|
+
stream.puts " \"#{prefix}#{processor.name}\" ["
|
115
|
+
stream.puts " fillcolor=\"#{get_colour processor.type}\","
|
116
|
+
stream.puts ' shape="box",'
|
117
|
+
stream.puts ' style="filled",'
|
118
|
+
stream.puts ' height="0",'
|
119
|
+
stream.puts ' width="0",'
|
120
|
+
stream.puts " label=\"#{processor.name}\""
|
121
|
+
stream.puts ' ];'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def write_source_cluster(stream, sources, prefix) # :nodoc:
|
126
|
+
if sources.length > 0
|
127
|
+
stream.puts " subgraph cluster_#{prefix}sources {"
|
128
|
+
stream.puts ' style="dotted"'
|
129
|
+
stream.puts ' label="Workflow Inputs"'
|
130
|
+
stream.puts ' fontname="Helvetica"'
|
131
|
+
stream.puts ' fontsize="10"'
|
132
|
+
stream.puts ' fontcolor="black"'
|
133
|
+
stream.puts ' rank="same"'
|
134
|
+
stream.puts " \"#{prefix}WORKFLOWINTERNALSOURCECONTROL\" ["
|
135
|
+
stream.puts ' shape="triangle",'
|
136
|
+
stream.puts ' width="0.2",'
|
137
|
+
stream.puts ' height="0.2",'
|
138
|
+
stream.puts ' fillcolor="brown1"'
|
139
|
+
stream.puts ' label=""'
|
140
|
+
stream.puts ' ]'
|
141
|
+
sources.each {|source| write_source(stream, source, prefix)}
|
142
|
+
stream.puts ' }'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def write_source(stream, source, prefix) # :nodoc:
|
147
|
+
stream.puts " \"#{prefix}WORKFLOWINTERNALSOURCE_#{source.name}\" ["
|
148
|
+
stream.puts ' shape="box",'
|
149
|
+
stream.puts " label=\"#{source.name}\""
|
150
|
+
stream.puts ' width="0",'
|
151
|
+
stream.puts ' height="0",'
|
152
|
+
stream.puts ' fillcolor="skyblue"'
|
153
|
+
stream.puts ' ]'
|
154
|
+
end
|
155
|
+
|
156
|
+
def write_sink_cluster(stream, sinks, prefix) # :nodoc:
|
157
|
+
if sinks.length > 0
|
158
|
+
stream.puts " subgraph cluster_#{prefix}sinks {"
|
159
|
+
stream.puts ' style="dotted"'
|
160
|
+
stream.puts ' label="Workflow Outputs"'
|
161
|
+
stream.puts ' fontname="Helvetica"'
|
162
|
+
stream.puts ' fontsize="10"'
|
163
|
+
stream.puts ' fontcolor="black"'
|
164
|
+
stream.puts ' rank="same"'
|
165
|
+
stream.puts " \"#{prefix}WORKFLOWINTERNALSINKCONTROL\" ["
|
166
|
+
stream.puts ' shape="invtriangle",'
|
167
|
+
stream.puts ' width="0.2",'
|
168
|
+
stream.puts ' height="0.2",'
|
169
|
+
stream.puts ' fillcolor="chartreuse3"'
|
170
|
+
stream.puts ' label=""'
|
171
|
+
stream.puts ' ]'
|
172
|
+
sinks.each {|sink| write_sink(stream, sink, prefix)}
|
173
|
+
stream.puts ' }'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def write_sink(stream, sink, prefix) # :nodoc:
|
178
|
+
stream.puts " \"#{prefix}WORKFLOWINTERNALSINK_#{sink.name}\" ["
|
179
|
+
stream.puts ' shape="box",'
|
180
|
+
stream.puts " label=\"#{sink.name}\""
|
181
|
+
stream.puts ' width="0",'
|
182
|
+
stream.puts ' height="0",'
|
183
|
+
stream.puts ' fillcolor="lightsteelblue2"'
|
184
|
+
stream.puts ' ]'
|
185
|
+
end
|
186
|
+
|
187
|
+
def write_link(stream, link, model, prefix) # :nodoc:
|
188
|
+
if model.sources.select{|s| s.name == link.source} != []
|
189
|
+
stream.write " \"#{prefix}WORKFLOWINTERNALSOURCE_#{link.source}\""
|
190
|
+
else
|
191
|
+
processor = model.processors.select{|p| p.name == link.source.split(':')[0]}[0]
|
192
|
+
if processor.model
|
193
|
+
stream.write " \"#{prefix}#{processor.name}WORKFLOWINTERNALSINK_#{link.source.split(':')[1]}\""
|
194
|
+
else
|
195
|
+
stream.write " \"#{prefix}#{processor.name}\""
|
196
|
+
end
|
197
|
+
end
|
198
|
+
stream.write '->'
|
199
|
+
if model.sinks.select{|s| s.name == link.sink} != []
|
200
|
+
stream.write "\"#{prefix}WORKFLOWINTERNALSINK_#{link.sink}\""
|
201
|
+
else
|
202
|
+
processor = model.processors.select{|p| p.name == link.sink.split(':')[0]}[0]
|
203
|
+
if processor.model
|
204
|
+
stream.write "\"#{prefix}#{processor.name}WORKFLOWINTERNALSOURCE_#{link.sink.split(':')[1]}\""
|
205
|
+
else
|
206
|
+
stream.write "\"#{prefix}#{processor.name}\""
|
207
|
+
end
|
208
|
+
end
|
209
|
+
stream.puts ' ['
|
210
|
+
stream.puts ' ];'
|
211
|
+
end
|
212
|
+
|
213
|
+
def write_coordination(stream, coordination, model, prefix) # :nodoc:
|
214
|
+
stream.write " \"#{prefix}#{coordination.controller}"
|
215
|
+
processor = model.processors.select{|p| p.name == coordination.controller}[0]
|
216
|
+
if processor.model
|
217
|
+
stream.write 'WORKFLOWINTERNALSINKCONTROL'
|
218
|
+
end
|
219
|
+
stream.write '"->"'
|
220
|
+
stream.write "#{prefix}#{coordination.target}\""
|
221
|
+
processor = model.processors.select{|p| p.name == coordination.target}[0]
|
222
|
+
if processor.model
|
223
|
+
stream.write 'WORKFLOWINTERNALSOURCECONTROL'
|
224
|
+
end
|
225
|
+
stream.puts ' ['
|
226
|
+
stream.puts ' color="gray",'
|
227
|
+
stream.puts ' arrowhead="odot",'
|
228
|
+
stream.puts ' arrowtail="none"'
|
229
|
+
stream.puts ' ];'
|
230
|
+
end
|
231
|
+
|
232
|
+
def get_colour(processor_name) # :nodoc:
|
233
|
+
colour = @@processor_colours[processor_name]
|
234
|
+
if colour
|
235
|
+
colour
|
236
|
+
else
|
237
|
+
'white'
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Returns true if the given name is a processor; false otherwise
|
242
|
+
def Dot.is_processor?(processor_name)
|
243
|
+
true if @@processor_colours[processor_name]
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
data/lib/scufl/model.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# This is the module containing the Scufl model implementation i.e. the model structure/definition and all its internals.
|
2
|
+
|
3
|
+
module Scufl # :nodoc:
|
4
|
+
|
5
|
+
# The model for a given Taverna 1 workflow.
|
6
|
+
class Model
|
7
|
+
# This returns a WorkflowDescription object.
|
8
|
+
attr_reader :description
|
9
|
+
|
10
|
+
# Retrieve the list of processors specific to the workflow.
|
11
|
+
# Does not include those from nested workflows.
|
12
|
+
attr_reader :processors
|
13
|
+
|
14
|
+
# Retrieve the list of datalinks specific to the workflow.
|
15
|
+
# Does not include those from nested workflows.
|
16
|
+
attr_reader :links
|
17
|
+
|
18
|
+
# Retrieve the list of sources specific to the workflow.
|
19
|
+
# Does not include those from nested workflows.
|
20
|
+
attr_reader :sources
|
21
|
+
|
22
|
+
# Retrieve the list of sinks specific to the workflow.
|
23
|
+
# Does not include those from nested workflows.
|
24
|
+
attr_reader :sinks
|
25
|
+
|
26
|
+
# Retrieve the list of coordinations specific to the workflow.
|
27
|
+
# Does not include those from nested workflows.
|
28
|
+
attr_reader :coordinations
|
29
|
+
|
30
|
+
# The list of any dependencies that have been found inside the workflow.
|
31
|
+
# Does not include those from nested workflows.
|
32
|
+
attr_accessor :dependencies
|
33
|
+
|
34
|
+
# Creates an empty model for a Taverna 1 workflow.
|
35
|
+
def initialize
|
36
|
+
@description = WorkflowDescription.new
|
37
|
+
@processors = Array.new
|
38
|
+
@links = Array.new
|
39
|
+
@sources = Array.new
|
40
|
+
@sinks = Array.new
|
41
|
+
@coordinations = Array.new
|
42
|
+
end
|
43
|
+
|
44
|
+
# Retrieve ALL the beanshell processors within the workflow.
|
45
|
+
def beanshells
|
46
|
+
return get_beanshells(self, [])
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def get_beanshells(given_model, beans_collected) # :nodoc:
|
52
|
+
wf_procs = given_model.processors.select { |x| x.type == "workflow" }
|
53
|
+
wf_procs.each { |x| get_beanshells(x.model, beans_collected) }
|
54
|
+
|
55
|
+
bean_procs = given_model.processors.select { |b| b.type == "beanshell" }
|
56
|
+
bean_procs.each { |a| beans_collected << a }
|
57
|
+
|
58
|
+
return beans_collected
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
# This is the (shim) object within the workflow. This can be a beanshell,
|
65
|
+
# a webservice, a workflow, etc...
|
66
|
+
class Processor
|
67
|
+
# A string containing name of the processor.
|
68
|
+
attr_accessor :name
|
69
|
+
|
70
|
+
# A string containing the description of the processor if available.
|
71
|
+
# Returns nil otherwise.
|
72
|
+
attr_accessor :description
|
73
|
+
|
74
|
+
# A string for the type of processor, e.g. beanshell, workflow, webservice, etc...
|
75
|
+
attr_accessor :type
|
76
|
+
|
77
|
+
# For processors that have type == "workflow", model is the the workflow
|
78
|
+
# definition. For all other processor types, model is nil.
|
79
|
+
attr_accessor :model
|
80
|
+
|
81
|
+
# This only has a value in beanshell processors. This is the actual script
|
82
|
+
# embedded with the processor which does all the "work"
|
83
|
+
attr_accessor :script
|
84
|
+
|
85
|
+
# This is a list of inputs that the processor can take in.
|
86
|
+
attr_accessor :inputs
|
87
|
+
|
88
|
+
# This is a list of outputs that the processor can produce.
|
89
|
+
attr_accessor :outputs
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
# This contains basic descriptive information about the workflow model.
|
95
|
+
class WorkflowDescription
|
96
|
+
# The author of the workflow.
|
97
|
+
attr_accessor :author
|
98
|
+
|
99
|
+
# The name/title of the workflow.
|
100
|
+
attr_accessor :title
|
101
|
+
|
102
|
+
# A small piece of descriptive text for the workflow.
|
103
|
+
attr_accessor :description
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
# This represents a connection between any of the following pair of entities:
|
109
|
+
# {processor -> processor}, {workflow -> workflow}, {workflow -> processor},
|
110
|
+
# and {processor -> workflow}.
|
111
|
+
class Link
|
112
|
+
# The name of the source (the starting point of the connection).
|
113
|
+
attr_accessor :source
|
114
|
+
|
115
|
+
# The name of the sink (the endpoint of the connection).
|
116
|
+
attr_accessor :sink
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
# This is a representation of the 'Run after...' function in Taverna
|
122
|
+
# where the selected processor or workflow is set to run after another.
|
123
|
+
class Coordination
|
124
|
+
# The name of the processor/workflow which is to run first.
|
125
|
+
attr_accessor :controller
|
126
|
+
|
127
|
+
# The name of the processor/workflow which is to run after the controller.
|
128
|
+
attr_accessor :target
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
# This is the start node of a Link. Each source has a name and a port
|
134
|
+
# which is seperated by a colon; ":".
|
135
|
+
# This is represented as "source of a processor:port_name".
|
136
|
+
# A string that does not contain a colon can often be returned, signifiying
|
137
|
+
# a workflow source as opposed to that of a processor.
|
138
|
+
class Source
|
139
|
+
attr_accessor :name, :description
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
# This is the start node of a Link. Each sink has a name and a port
|
145
|
+
# which is seperated by a colon; ":".
|
146
|
+
# This is represented as "sink of a processor:port_name".
|
147
|
+
# A string that does not contain a colon can often be returned, signifiying
|
148
|
+
# a workflow sink as opposed to that of a processor.
|
149
|
+
class Sink
|
150
|
+
attr_accessor :name, :description
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
data/lib/scufl/parser.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require "rexml/document"
|
2
|
+
|
3
|
+
module Scufl
|
4
|
+
|
5
|
+
class Parser
|
6
|
+
# Returns the model for the given t2flow_file.
|
7
|
+
# The method accepts objects of classes File and String only.
|
8
|
+
# ===Usage
|
9
|
+
# foo = ... # stuff to initialize foo here
|
10
|
+
# bar = Scufl::Parser.new.parse(foo)
|
11
|
+
def parse(scufl)
|
12
|
+
document = REXML::Document.new(scufl)
|
13
|
+
|
14
|
+
root = document.root
|
15
|
+
raise "Doesn't appear to be a workflow!" if root.name != "scufl"
|
16
|
+
version = root.attribute('version').value
|
17
|
+
|
18
|
+
create_model(root, version)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_model(element, version) # :nodoc:
|
22
|
+
model = Model.new
|
23
|
+
|
24
|
+
element.each_element('s:workflowdescription') { |description| set_description(model, description, version)}
|
25
|
+
element.each_element('s:processor') { |processor| add_processor(model, processor, version)}
|
26
|
+
element.each_element('s:link') { |link| add_link(model, link, version)}
|
27
|
+
element.each_element('s:source') { |source| add_source(model, source, version)}
|
28
|
+
element.each_element('s:sink') { |sink| add_sink(model, sink, version)}
|
29
|
+
element.each_element('s:coordination') { |coordination| add_coordination(model, coordination, version)}
|
30
|
+
|
31
|
+
return model
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_coordination(model, element, version) # :nodoc:
|
35
|
+
coordination = Coordination.new
|
36
|
+
|
37
|
+
element.each_element('s:condition') do |condition|
|
38
|
+
condition.each_element('s:target') {|target| coordination.controller = target.text}
|
39
|
+
end
|
40
|
+
element.each_element('s:action') do |action|
|
41
|
+
action.each_element('s:target') {|target| coordination.target = target.text}
|
42
|
+
end
|
43
|
+
|
44
|
+
model.coordinations.push coordination
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_link(model, element, version) # :nodoc:
|
48
|
+
link = Link.new
|
49
|
+
|
50
|
+
if version == '0.1'
|
51
|
+
element.each_element('s:input') { |input| link.sink = input.text}
|
52
|
+
element.each_element('s:output') { |output| link.source = output.text}
|
53
|
+
else
|
54
|
+
source = element.attribute('source')
|
55
|
+
link.source = source.value if source
|
56
|
+
|
57
|
+
sink = element.attribute('sink')
|
58
|
+
link.sink = sink.value if sink
|
59
|
+
end
|
60
|
+
|
61
|
+
model.links.push link
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_source(model, element, version) # :nodoc:
|
65
|
+
source = Source.new
|
66
|
+
|
67
|
+
if version == '0.1'
|
68
|
+
name = element.text
|
69
|
+
source.name = name.value if name
|
70
|
+
else
|
71
|
+
name = element.attribute('name')
|
72
|
+
source.name = name.value if name
|
73
|
+
element.each_element('s:metadata') { |metadata|
|
74
|
+
metadata.each_element('s:description') {|description| source.description = description.text}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
model.sources.push source
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_sink(model, element, version) # :nodoc:
|
82
|
+
sink = Sink.new
|
83
|
+
|
84
|
+
if version == '0.1'
|
85
|
+
name = element.text
|
86
|
+
sink.name = name.value if name
|
87
|
+
else
|
88
|
+
name = element.attribute('name')
|
89
|
+
sink.name = name.value if name
|
90
|
+
element.each_element('s:metadata') { |metadata|
|
91
|
+
metadata.each_element('s:description') {|description| sink.description = description.text}
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
model.sinks.push sink
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_processor(model, element, version) # :nodoc:
|
99
|
+
processor = Processor.new
|
100
|
+
|
101
|
+
name = element.attribute('name')
|
102
|
+
processor.name = name.value if name
|
103
|
+
|
104
|
+
element.each_element() do |e|
|
105
|
+
case e.name
|
106
|
+
when 'description'
|
107
|
+
processor.description = e.text
|
108
|
+
when'beanshell'
|
109
|
+
processor.type = e.name
|
110
|
+
e.each_element do |bean|
|
111
|
+
case bean.name
|
112
|
+
when "scriptvalue"
|
113
|
+
processor.script = bean.text
|
114
|
+
when "beanshellinputlist"
|
115
|
+
bean.each_element do |input|
|
116
|
+
if input.name == "beanshellinput"
|
117
|
+
processor.inputs = [] if processor.inputs.nil?
|
118
|
+
processor.inputs << input.text
|
119
|
+
end # if
|
120
|
+
end # bean.each_element
|
121
|
+
when "beanshelloutputlist"
|
122
|
+
bean.each_element do |output|
|
123
|
+
if output.name == "beanshelloutput"
|
124
|
+
processor.outputs = [] if processor.outputs.nil?
|
125
|
+
processor.outputs << output.text
|
126
|
+
end # if
|
127
|
+
end # bean.each_element
|
128
|
+
when "dependencies"
|
129
|
+
bean.each_element do |dep|
|
130
|
+
model.dependencies = [] if model.dependencies.nil?
|
131
|
+
model.dependencies << dep.text unless dep.text =~ /^\s*$/
|
132
|
+
end # bean.each_element
|
133
|
+
end # case bean.name
|
134
|
+
end # e.each_element
|
135
|
+
when 'mergemode'
|
136
|
+
when 'defaults'
|
137
|
+
when 'iterationstrategy'
|
138
|
+
else
|
139
|
+
if Dot.is_processor? e.name
|
140
|
+
processor.type = e.name
|
141
|
+
if processor.type == 'workflow'
|
142
|
+
e.each_element('s:scufl') {|e| processor.model = create_model(e, version)}
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
model.processors.push processor
|
149
|
+
end
|
150
|
+
|
151
|
+
def set_description(model, element, version) # :nodoc:
|
152
|
+
author = element.attribute('author')
|
153
|
+
title = element.attribute('title')
|
154
|
+
|
155
|
+
model.description.author = author.value if author
|
156
|
+
model.description.title = title.value if title
|
157
|
+
model.description.description = element.text
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|