myGrid-taverna-scufl 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|