rbpm 0.0.1 → 0.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.
@@ -7,6 +7,11 @@
7
7
  [ok] conditions
8
8
  [~ok] consistent and clean meta syntax
9
9
  [~ok] clean block support
10
- [pending] rbpm server
11
- [pending] rpbm server java/web service interface
10
+ [later] rbpm server
11
+ [later] rpbm server java/web service interface
12
12
  [ok] workflow support for exception handling
13
+ [later] tasks, roles and swimlanes
14
+ [pending] throw away prototype and re-implement *
15
+ [pending] improve test infrastructure (tests must be runnable from IDE, using rake, using gem installer)
16
+ [pending] workflow validation
17
+ [pending] persistence
@@ -1,590 +1,598 @@
1
- class WorkflowVersionManager
2
- def self.find_workflow_versions(workflow_name)
3
- versions = []
4
- ObjectSpace.each_object(Module) do |m|
5
- module_name = m.to_s
6
- if module_name =~ /#{workflow_name}Version([0-9]+)$/
7
- versions << $1.to_i
1
+ module Rbpm
2
+ class WorkflowVersionManager
3
+ def self.find_workflow_versions(workflow_name)
4
+ versions = []
5
+ ObjectSpace.each_object(Module) do |m|
6
+ module_name = m.to_s
7
+ if module_name =~ /#{workflow_name}Version([0-9]+)$/
8
+ versions << $1.to_i
9
+ end
8
10
  end
11
+ versions
9
12
  end
10
- versions
11
- end
12
13
 
13
- def self.create_workflow_instance(workflow_name, version = :latest)
14
- workflow_name = workflow_name.to_s if workflow_name.is_a? Symbol
15
- if :latest == version
16
- versions = find_workflow_versions(workflow_name)
17
- if versions.empty?
18
- #fallback to non-versionned wf
19
- return eval("#{workflow_name}.new")
20
- else
21
- version = versions.max
22
- end
14
+ def self.create_workflow_instance(workflow_name, version = :latest)
15
+ workflow_name = workflow_name.to_s if workflow_name.is_a? Symbol
16
+ if :latest == version
17
+ versions = find_workflow_versions(workflow_name)
18
+ if versions.empty?
19
+ #fallback to non-versionned wf
20
+ return eval("#{workflow_name}.new")
21
+ else
22
+ version = versions.max
23
+ end
24
+ end
25
+ return eval("#{workflow_name}Version#{version}::#{workflow_name}.new")
23
26
  end
24
- return eval("#{workflow_name}Version#{version}::#{workflow_name}.new")
25
27
  end
26
- end
27
28
 
28
- class Workflow
29
-
30
- ##WORKFLOW METADATA
31
-
32
- #@@meta will be a class attribute of a concrete Workflow
33
- def self.init_meta
34
- module_eval <<-end_eval
35
- unless defined? @@meta
36
- @@meta = {}
37
- def self.meta
38
- @@meta
29
+ class Workflow
30
+
31
+ ##WORKFLOW METADATA
32
+
33
+ #@@meta will be a class attribute of a concrete Workflow
34
+ def self.init_meta
35
+ module_eval <<-end_eval
36
+ unless defined? @@meta
37
+ @@meta = {}
38
+ def self.meta
39
+ @@meta
40
+ end
39
41
  end
40
- end
41
- end_eval
42
- end
42
+ end_eval
43
+ end
43
44
 
44
- #insert generic node helper...
45
-
46
- def self.node(node_sym, options = {})
47
- self.init_meta
48
- self.nodes[node_sym] = {} unless self.nodes[node_sym]
49
- options.each do |key,value|
50
- case key.to_s
51
- when /(.*)_trans$|trans$/
52
- trans = $1.nil? ? "default" : $1
53
- transition(node_sym, trans.to_sym, value)
54
- when /(.*)_trans_action$|trans_action$/
55
- trans = $1.nil? ? "default" : $1
56
- transition_action(node_sym, trans.to_sym, value)
57
- when /(.*)_trans_cond$|trans_cond$/
58
- trans = $1.nil? ? "default" : $1
59
- transition_condition(node_sym, trans.to_sym, value)
60
- when "exception"
61
- exception_transition(node_sym, value)
62
- when "action"
63
- node_action(node_sym, value)
64
- when "on_enter"
65
- node_enter_action(node_sym, value)
66
- when "on_leave"
67
- node_leave_action(node_sym, value)
68
- when "action_singleton"
69
- node_action_singleton(node_sym, value)
45
+ #insert generic node helper...
46
+
47
+ def self.node(node_sym, options = {})
48
+ self.init_meta
49
+ self.nodes[node_sym] = {} unless self.nodes[node_sym]
50
+ options.each do |key,value|
51
+ case key.to_s
52
+ when /(.*)_trans$|trans$/
53
+ trans = $1.nil? ? "default" : $1
54
+ transition(node_sym, trans.to_sym, value)
55
+ when /(.*)_trans_action$|trans_action$/
56
+ trans = $1.nil? ? "default" : $1
57
+ transition_action(node_sym, trans.to_sym, value)
58
+ when /(.*)_trans_cond$|trans_cond$/
59
+ trans = $1.nil? ? "default" : $1
60
+ transition_condition(node_sym, trans.to_sym, value)
61
+ when "exception"
62
+ exception_transition(node_sym, value)
63
+ when "action"
64
+ node_action(node_sym, value)
65
+ when "on_enter"
66
+ node_enter_action(node_sym, value)
67
+ when "on_leave"
68
+ node_leave_action(node_sym, value)
69
+ when "action_singleton"
70
+ node_action_singleton(node_sym, value)
71
+ end
70
72
  end
71
73
  end
72
- end
73
74
 
74
- #insert special nodes helpers...
75
+ #insert special nodes helpers...
75
76
 
76
- def self.start_node(node_sym, options = {})
77
- node(node_sym, options)
78
- nodes[node_sym][:start] = true
79
- end
77
+ def self.start_node(node_sym, options = {})
78
+ node(node_sym, options)
79
+ nodes[node_sym][:start] = true
80
+ end
80
81
 
81
- def self.end_node(node_sym, options = {})
82
- node(node_sym, options)
83
- nodes[node_sym][:end] = true
84
- end
82
+ def self.end_node(node_sym, options = {})
83
+ node(node_sym, options)
84
+ nodes[node_sym][:end] = true
85
+ end
85
86
 
86
- def self.state_node(node_sym, options = {})
87
- node(node_sym, options)
88
- nodes[node_sym][:state] = true
89
- end
87
+ def self.state_node(node_sym, options = {})
88
+ node(node_sym, options)
89
+ nodes[node_sym][:state] = true
90
+ end
90
91
 
91
- def self.join_node(node_sym, options = {})
92
- options[:action_singleton] = JoinNode.new
93
- node(node_sym, options)
94
- end
92
+ def self.join_node(node_sym, options = {})
93
+ options[:action_singleton] = JoinNode.new
94
+ node(node_sym, options)
95
+ end
95
96
 
96
- def self.fork_node(node_sym, options = {})
97
- options[:action_singleton] = ForkNode.new(options[:children_ctx])
98
- node(node_sym, options)
99
- end
97
+ def self.fork_node(node_sym, options = {})
98
+ options[:action_singleton] = ForkNode.new(options[:children_ctx])
99
+ node(node_sym, options)
100
+ end
100
101
 
101
- def self.call_node(node_sym, options = {})
102
- options[:action_singleton] = CallNode.new(options[:workflow], options[:workflow_version], options[:call_in], options[:call_out])
103
- node(node_sym, options)
104
- end
102
+ def self.call_node(node_sym, options = {})
103
+ options[:action_singleton] = CallNode.new(options[:workflow], options[:workflow_version], options[:call_in], options[:call_out])
104
+ node(node_sym, options)
105
+ end
105
106
 
106
- #insert node action helpers...
107
+ #insert node action helpers...
107
108
 
108
- def self.enter(node_sym, &blk)
109
- node_enter_action(node_sym, blk)
110
- end
109
+ def self.enter(node_sym, &blk)
110
+ node_enter_action(node_sym, blk)
111
+ end
111
112
 
112
- def self.node_enter_action(node_sym, action)
113
- nodes[node_sym][:on_enter] = action
114
- end
113
+ def self.node_enter_action(node_sym, action)
114
+ nodes[node_sym][:on_enter] = action
115
+ end
115
116
 
116
- def self.action(node_sym, &blk)
117
- node_action(node_sym, blk)
118
- end
117
+ def self.action(node_sym, &blk)
118
+ node_action(node_sym, blk)
119
+ end
119
120
 
120
- def self.node_action(node_sym, action)
121
- nodes[node_sym][:action] = action
122
- end
121
+ def self.node_action(node_sym, action)
122
+ nodes[node_sym][:action] = action
123
+ end
123
124
 
124
- def self.leave(node_sym, &blk)
125
- node_leave_action(node_sym, blk)
126
- end
125
+ def self.leave(node_sym, &blk)
126
+ node_leave_action(node_sym, blk)
127
+ end
127
128
 
128
- def self.node_leave_action(node_sym, action)
129
- nodes[node_sym][:on_leave] = action
130
- end
129
+ def self.node_leave_action(node_sym, action)
130
+ nodes[node_sym][:on_leave] = action
131
+ end
131
132
 
132
- def self.node_action_singleton(node_sym, instance)
133
- nodes[node_sym][:action_singleton] = instance
134
- end
133
+ def self.node_action_singleton(node_sym, instance)
134
+ nodes[node_sym][:action_singleton] = instance
135
+ end
135
136
 
136
- #insert transition, transition action and transition condition helpers...
137
+ #insert transition, transition action and transition condition helpers...
137
138
 
138
- def self.transition(node_from_sym, trans_sym, node_to_sym)
139
- transitions(node_from_sym)[trans_sym] = node_to_sym
140
- end
139
+ def self.transition(node_from_sym, trans_sym, node_to_sym)
140
+ transitions(node_from_sym)[trans_sym] = node_to_sym
141
+ end
141
142
 
142
- def self.transition_action(node_from_sym, trans_sym, action)
143
- transition_actions(node_from_sym)[trans_sym] = action
144
- end
143
+ def self.transition_action(node_from_sym, trans_sym, action)
144
+ transition_actions(node_from_sym)[trans_sym] = action
145
+ end
145
146
 
146
- def self.transition_condition(node_from_sym, trans_sym, condition)
147
- transition_conditions(node_from_sym)[trans_sym] = condition
148
- end
147
+ def self.transit(node_from_sym, trans_sym, &blk)
148
+ transition_action(node_from_sym, trans_sym, blk)
149
+ end
149
150
 
150
- def self.exception_transition(node_from_sym, node_to_sym)
151
- transition(node_from_sym, :exception, node_to_sym)
152
- transition_condition(node_from_sym, :exception, "false") #only executed if "hardcoded" signalled
153
- end
151
+ def self.transition_condition(node_from_sym, trans_sym, condition)
152
+ transition_conditions(node_from_sym)[trans_sym] = condition
153
+ end
154
154
 
155
- #metadata access helpers...
155
+ def self.exception_transition(node_from_sym, node_to_sym)
156
+ transition(node_from_sym, :exception, node_to_sym)
157
+ transition_condition(node_from_sym, :exception, "false") #only executed if "hardcoded" signalled
158
+ end
159
+
160
+ #metadata access helpers...
156
161
 
157
- def self.nodes
158
- meta[:nodes] = {} unless meta[:nodes]
159
- meta[:nodes]
160
- end
161
-
162
- def self.node_option_values(node, option)
163
- nodes[node][option] = {} unless nodes[node][option]
164
- nodes[node][option]
165
- end
162
+ def self.nodes
163
+ meta[:nodes] = {} unless meta[:nodes]
164
+ meta[:nodes]
165
+ end
166
+
167
+ def self.node_option_values(node, option)
168
+ nodes[node][option] = {} unless nodes[node][option]
169
+ nodes[node][option]
170
+ end
166
171
 
167
- def self.transitions(node)
168
- node_option_values(node, :transitions)
169
- end
172
+ def self.transitions(node)
173
+ node_option_values(node, :transitions)
174
+ end
170
175
 
171
- def self.transition_actions(node)
172
- node_option_values(node, :transition_actions)
173
- end
176
+ def self.transition_actions(node)
177
+ node_option_values(node, :transition_actions)
178
+ end
174
179
 
175
- def self.transition_conditions(node)
176
- node_option_values(node, :transition_conditions)
177
- end
180
+ def self.transition_conditions(node)
181
+ node_option_values(node, :transition_conditions)
182
+ end
178
183
 
179
- def self.find_first_node_with_option(option)
180
- nodes.each do |node,options|
181
- return node if options[option]
184
+ def self.find_first_node_with_option(option)
185
+ nodes.each do |node,options|
186
+ return node if options[option]
187
+ end
188
+ nil
182
189
  end
183
- nil
184
- end
185
190
 
186
- def self.find_nodes_with_option(option)
187
- found = nodes.collect do |node,options|
188
- options[option] ? node : nil
191
+ def self.find_nodes_with_option(option)
192
+ found = nodes.collect do |node,options|
193
+ options[option] ? node : nil
194
+ end
195
+ found.compact
189
196
  end
190
- found.compact
191
- end
192
197
 
193
- def self.find_node_with_name(name)
194
- nodes[name.to_sym]
195
- end
198
+ def self.find_node_with_name(name)
199
+ nodes[name.to_sym]
200
+ end
196
201
 
197
- def self.find_start_node
198
- find_first_node_with_option :start
199
- end
202
+ def self.find_start_node
203
+ find_first_node_with_option :start
204
+ end
200
205
 
201
- def self.find_end_nodes
202
- find_nodes_with_option :end
203
- end
206
+ def self.find_end_nodes
207
+ find_nodes_with_option :end
208
+ end
204
209
 
205
- def self.end_node?(node)
206
- nodes[node][:end]
207
- end
210
+ def self.end_node?(node)
211
+ nodes[node][:end]
212
+ end
208
213
 
209
- @@next_token_id = 1
214
+ @@next_token_id = 1
210
215
 
211
- def self.generate_token_id
212
- @@next_token_id += 1
213
- end
216
+ def self.generate_token_id
217
+ @@next_token_id += 1
218
+ end
214
219
 
215
- ##WORKFLOW INSTANCE
220
+ ##WORKFLOW INSTANCE
216
221
 
217
- attr_writer :token_id_generator
218
- attr_reader :tokens, :result, :token_id_generator
222
+ attr_writer :token_id_generator
223
+ attr_reader :tokens, :result, :token_id_generator
219
224
 
220
- def initialize
221
- @tokens = []
222
- @result = nil
223
- end
225
+ def initialize
226
+ @tokens = []
227
+ @result = nil
228
+ end
224
229
 
225
- def clazz
226
- self.class
227
- end
230
+ def clazz
231
+ self.class
232
+ end
228
233
 
229
- #token management...
234
+ #token management...
230
235
 
231
- def generate_token_id
232
- if token_id_generator
233
- token_id_generator.generate_token_id
234
- else
235
- clazz.generate_token_id
236
+ def generate_token_id
237
+ if token_id_generator
238
+ token_id_generator.generate_token_id
239
+ else
240
+ clazz.generate_token_id
241
+ end
236
242
  end
237
- end
238
-
239
- def create_root_token(ctx_vars = {})
240
- create_token(nil, ctx_vars)
241
- end
242
243
 
243
- def create_token(parent = nil, ctx_vars = {})
244
- token = Token.new(self, parent, ctx_vars, generate_token_id)
245
- @tokens << token
246
- token
247
- end
244
+ def create_root_token(ctx_vars = {})
245
+ create_token(nil, ctx_vars)
246
+ end
248
247
 
249
- def token_done(token)
250
- unless token.parent
251
- @result = token.all_ctx_vars
248
+ def create_token(parent = nil, ctx_vars = {})
249
+ token = Token.new(self, parent, ctx_vars, generate_token_id)
250
+ @tokens << token
251
+ token
252
252
  end
253
+
254
+ def token_done(token)
255
+ unless token.parent
256
+ @result = token.all_ctx_vars
257
+ end
253
258
 
254
- @tokens.delete token
255
- end
259
+ @tokens.delete token
260
+ end
256
261
 
257
- def find_root_token
258
- @tokens.each do |token|
259
- return token unless token.parent
262
+ def find_root_token
263
+ @tokens.each do |token|
264
+ return token unless token.parent
265
+ end
266
+ nil?
260
267
  end
261
- nil?
262
- end
263
268
 
264
- def [](key)
265
- if @result
266
- @result[key]
267
- else
268
- find_root_token[key]
269
+ def [](key)
270
+ if @result
271
+ @result[key]
272
+ else
273
+ find_root_token[key]
274
+ end
269
275
  end
270
- end
271
276
 
272
- #(metadata-driven) reflection helpers...
277
+ #(metadata-driven) reflection helpers...
273
278
 
274
- def find_method(method_name)
275
- action = method(method_name) if methods.include? method_name
279
+ def find_method(method_name)
280
+ action = method(method_name) if methods.include? method_name
276
281
 
277
- unless action
278
- action = clazz.method(method_name) if clazz.methods.include? method_name
279
- end
282
+ unless action
283
+ action = clazz.method(method_name) if clazz.methods.include? method_name
284
+ end
280
285
 
281
- action
282
- end
286
+ action
287
+ end
283
288
 
284
- def find_node_event_action(node, default_method_suffix, action_option)
285
- default_method_name = "#{node.to_s}#{default_method_suffix}"
289
+ def find_node_event_action(node, default_method_suffix, action_option)
290
+ default_method_name = "#{node.to_s}#{default_method_suffix}"
286
291
 
287
- action_singleton = clazz.nodes[node][:action_singleton]
288
- action = action_singleton.method(action_option) if action_singleton && action_singleton.methods.include?(action_option.to_s)
292
+ action_singleton = clazz.nodes[node][:action_singleton]
293
+ action = action_singleton.method(action_option) if action_singleton && action_singleton.methods.include?(action_option.to_s)
289
294
 
290
- unless action
291
- action = find_method(default_method_name)
292
- end
295
+ unless action
296
+ action = find_method(default_method_name)
297
+ end
293
298
 
294
- unless action
295
- action_or_name = clazz.nodes[node][action_option]
299
+ unless action
300
+ action_or_name = clazz.nodes[node][action_option]
296
301
 
297
- if action_or_name.is_a? Symbol
298
- action_name = action_or_name.to_s
299
- action = find_method(action_name)
302
+ if action_or_name.is_a? Symbol
303
+ action_name = action_or_name.to_s
304
+ action = find_method(action_name)
300
305
 
301
- raise "unknown custom action #{action_name}" unless action
302
- else
303
- action = action_or_name
306
+ raise "unknown custom action #{action_name}" unless action
307
+ else
308
+ action = action_or_name
309
+ end
304
310
  end
305
- end
306
311
 
307
- action
308
- end
312
+ action
313
+ end
309
314
 
310
- def find_enter_action(node)
311
- find_node_event_action(node, "_on_enter", :on_enter)
312
- end
315
+ def find_enter_action(node)
316
+ find_node_event_action(node, "_on_enter", :on_enter)
317
+ end
313
318
 
314
- def find_leave_action(node)
315
- find_node_event_action(node, "_on_leave", :on_leave)
316
- end
319
+ def find_leave_action(node)
320
+ find_node_event_action(node, "_on_leave", :on_leave)
321
+ end
317
322
 
318
- def find_node_action(node)
319
- find_node_event_action(node, "_action", :action)
320
- end
323
+ def find_node_action(node)
324
+ find_node_event_action(node, "_action", :action)
325
+ end
321
326
 
322
- def find_transit_action(node, transition)
323
- default_method_name = "#{node.to_s}_#{transition.to_s}_trans_action"
324
- action = find_method(default_method_name)
327
+ def find_transit_action(node, transition)
328
+ default_method_name = "#{node.to_s}_#{transition.to_s}_trans_action"
329
+ action = find_method(default_method_name)
325
330
 
326
- unless action
327
- action_or_name = clazz.transition_actions(node)[transition]
331
+ unless action
332
+ action_or_name = clazz.transition_actions(node)[transition]
328
333
 
329
- if action_or_name.is_a? Symbol
330
- action_name = action_or_name.to_s
331
- action = find_method(action_name)
334
+ if action_or_name.is_a? Symbol
335
+ action_name = action_or_name.to_s
336
+ action = find_method(action_name)
332
337
 
333
- raise "unknown custom action #{action_name}" unless action
334
- else
335
- action = action_or_name
338
+ raise "unknown custom action #{action_name}" unless action
339
+ else
340
+ action = action_or_name
341
+ end
336
342
  end
337
- end
338
343
 
339
- action
340
- end
344
+ action
345
+ end
341
346
 
342
- def find_transit_target(node, transition)
343
- clazz.transitions(node)[transition]
344
- end
347
+ def find_transit_target(node, transition)
348
+ clazz.transitions(node)[transition]
349
+ end
345
350
 
346
- #flow management...
351
+ #flow management...
347
352
 
348
- def start(ctx_vars = {})
349
- token = create_root_token(ctx_vars)
350
- token.enter(clazz.find_start_node)
351
- token
352
- end
353
+ def start(ctx_vars = {})
354
+ token = create_root_token(ctx_vars)
355
+ token.enter(clazz.find_start_node)
356
+ token
357
+ end
353
358
 
354
- def call_event_action(action, token, node)
355
- begin
356
- action.call(token, node)
357
- rescue Exception => exception
358
- if clazz.transitions(node)[:exception]
359
- token[:exception] = exception
360
- return :exception
361
- else
362
- raise
359
+ def call_event_action(action, token, node)
360
+ begin
361
+ action.call(token, node)
362
+ rescue Exception => exception
363
+ if clazz.transitions(node)[:exception]
364
+ token[:exception] = exception
365
+ return :exception
366
+ else
367
+ raise
368
+ end
363
369
  end
370
+ return nil
364
371
  end
365
- return nil
366
- end
367
372
 
368
- def enter_node(token, node)
369
- token.entered(node)
373
+ def enter_node(token, node)
374
+ token.entered(node)
370
375
 
371
- hardcoded_transition = call_event_action(find_enter_action(node), token, node) if find_enter_action(node)
376
+ hardcoded_transition = call_event_action(find_enter_action(node), token, node) if find_enter_action(node)
372
377
 
373
- if hardcoded_transition || (not (clazz.end_node?(node) || clazz.nodes[node][:state]))
374
- signal_node(token, node, hardcoded_transition)
378
+ if hardcoded_transition || (not (clazz.end_node?(node) || clazz.nodes[node][:state]))
379
+ signal_node(token, node, hardcoded_transition)
380
+ end
375
381
  end
376
- end
377
382
 
378
- def signal_node(token, node, hardcoded_transition = nil)
379
- if hardcoded_transition
380
- transitions = [[hardcoded_transition, token]]
381
- elsif find_node_action(node)
382
- transitions = find_node_action(node).call(token, node)
383
- else
384
- clazz.transitions(node).each do |transition,target|
385
- if (clazz.transition_conditions(node)[transition].nil? || token.eval_expr(clazz.transition_conditions(node)[transition]))
386
- transitions = [[transition, token]]
387
- break
383
+ def signal_node(token, node, hardcoded_transition = nil)
384
+ if hardcoded_transition
385
+ transitions = [[hardcoded_transition, token]]
386
+ elsif find_node_action(node)
387
+ transitions = find_node_action(node).call(token, node)
388
+ else
389
+ clazz.transitions(node).each do |transition,target|
390
+ if (clazz.transition_conditions(node)[transition].nil? || token.eval_expr(clazz.transition_conditions(node)[transition]))
391
+ transitions = [[transition, token]]
392
+ break
393
+ end
388
394
  end
389
395
  end
390
- end
391
396
 
392
- if not clazz.nodes[node][:end] and transitions
393
- transitions.each do |transition_token|
394
- transition,token = transition_token
395
- token.transit(transition)
397
+ if not clazz.nodes[node][:end] and transitions
398
+ transitions.each do |transition_token|
399
+ transition,token = transition_token
400
+ token.transit(transition)
401
+ end
396
402
  end
397
403
  end
398
- end
399
404
 
400
- def leave_node(token, node)
401
- call_event_action(find_leave_action(node), token, node) if find_leave_action(node)
402
- end
405
+ def leave_node(token, node)
406
+ call_event_action(find_leave_action(node), token, node) if find_leave_action(node)
407
+ end
403
408
 
404
- def transit(token, node, transition)
405
- hardcoded_transition = call_event_action(find_transit_action(node, transition), token, node) if find_transit_action(node, transition)
409
+ def transit(token, node, transition)
410
+ hardcoded_transition = call_event_action(find_transit_action(node, transition), token, node) if find_transit_action(node, transition)
406
411
 
407
- if hardcoded_transition
408
- enter_node(token, find_transit_target(node, hardcoded_transition))
409
- else
410
- enter_node(token, find_transit_target(node, transition))
412
+ if hardcoded_transition
413
+ enter_node(token, find_transit_target(node, hardcoded_transition))
414
+ else
415
+ enter_node(token, find_transit_target(node, transition))
416
+ end
411
417
  end
412
418
  end
413
- end
414
419
 
415
- class Token
416
-
417
- attr_writer :sub_process, :parent_process
418
- attr_reader :workflow, :node, :parent, :sub_process, :parent_process, :ref
419
-
420
- def initialize(workflow, parent = nil, ctx_vars = {}, ref = -1)
421
- @workflow = workflow
422
- @parent = parent
423
- @ctx_vars = ctx_vars
424
- @ref = ref
425
- @childs = []
426
- @sub_process = nil
427
- @parent_process = nil
428
- @done = false
429
- if parent
430
- @node = parent.node
431
- @parent.add_child(self)
432
- else
433
- @node = nil
420
+ class Token
421
+
422
+ attr_writer :sub_process, :parent_process
423
+ attr_reader :workflow, :node, :parent, :sub_process, :parent_process, :ref
424
+
425
+ def initialize(workflow, parent = nil, ctx_vars = {}, ref = -1)
426
+ @workflow = workflow
427
+ @parent = parent
428
+ @ctx_vars = ctx_vars
429
+ @ref = ref
430
+ @childs = []
431
+ @sub_process = nil
432
+ @parent_process = nil
433
+ @done = false
434
+ if parent
435
+ @node = parent.node
436
+ @parent.add_child(self)
437
+ else
438
+ @node = nil
439
+ end
434
440
  end
435
- end
436
441
 
437
- def all_ctx_vars
438
- @ctx_vars
439
- end
442
+ def all_ctx_vars
443
+ @ctx_vars
444
+ end
440
445
 
441
- def token
442
- self
443
- end
446
+ #transition condition expressions are evaluated using token's binding()
447
+ #and this method is here to support expressions like "token[:var_name] == ..."
448
+ def token
449
+ self
450
+ end
444
451
 
445
- def []=(key, value)
446
- @ctx_vars[key] = value
447
- end
452
+ def []=(key, value)
453
+ @ctx_vars[key] = value
454
+ end
448
455
 
449
- def [](key)
450
- @ctx_vars[key]
451
- end
456
+ def [](key)
457
+ @ctx_vars[key]
458
+ end
452
459
 
453
- def add_child(token)
454
- @childs << token
455
- end
460
+ def add_child(token)
461
+ @childs << token
462
+ end
456
463
 
457
- def remove_child(token)
458
- @childs.delete(token)
459
- end
464
+ def remove_child(token)
465
+ @childs.delete(token)
466
+ end
460
467
 
461
- def childs?
462
- not @childs.empty?
463
- end
468
+ def childs?
469
+ not @childs.empty?
470
+ end
464
471
 
465
- def signal
466
- @workflow.signal_node(self, node)
472
+ def signal
473
+ @workflow.signal_node(self, node)
467
474
 
468
- if end? && @parent_process
469
- @parent_process.signal
470
- @parent_process = nil
475
+ if end? && @parent_process
476
+ @parent_process.signal
477
+ @parent_process = nil
478
+ end
471
479
  end
472
- end
473
480
 
474
- def enter(node)
475
- @workflow.enter_node(self, node)
476
- end
481
+ def enter(node)
482
+ @workflow.enter_node(self, node)
483
+ end
477
484
 
478
- def entered(node)
479
- @node = node
485
+ def entered(node)
486
+ @node = node
480
487
 
481
- if @workflow.clazz.end_node?(@node) and not @parent
482
- @workflow.token_done(self)
488
+ if @workflow.clazz.end_node?(@node) and not @parent
489
+ @workflow.token_done(self)
490
+ end
483
491
  end
484
- end
485
492
 
486
- def transit(transition)
487
- hardcoded_transition = @workflow.leave_node(self, @node)
488
- if hardcoded_transition
489
- @workflow.transit(self, @node, hardcoded_transition)
490
- else
491
- @workflow.transit(self, @node, transition)
493
+ def transit(transition)
494
+ hardcoded_transition = @workflow.leave_node(self, @node)
495
+ if hardcoded_transition
496
+ @workflow.transit(self, @node, hardcoded_transition)
497
+ else
498
+ @workflow.transit(self, @node, transition)
499
+ end
492
500
  end
493
- end
494
501
 
495
- def jump(child)
496
- @node = child.node
497
- end
502
+ def jump(child)
503
+ @node = child.node
504
+ end
498
505
 
499
- def done
500
- @parent.remove_child(self) if @parent
501
- @parent.jump(self) if @parent
502
- @workflow.token_done(self)
503
- @done = true
504
- end
506
+ def done
507
+ @parent.remove_child(self) if @parent
508
+ @parent.jump(self) if @parent
509
+ @workflow.token_done(self)
510
+ @done = true
511
+ end
505
512
 
506
- def end?
507
- @done || @workflow.clazz.end_node?(@node)
508
- end
513
+ def end?
514
+ @done || @workflow.clazz.end_node?(@node)
515
+ end
509
516
 
510
- def fork(ctx_vars = {})
511
- @workflow.create_token(self, ctx_vars)
512
- end
517
+ def fork(ctx_vars = {})
518
+ @workflow.create_token(self, ctx_vars)
519
+ end
513
520
 
514
- def eval_expr(expr)
515
- eval(expr, binding())
521
+ def eval_expr(expr)
522
+ eval(expr, binding())
523
+ end
516
524
  end
517
- end
518
525
 
519
- class ForkNode
520
- def initialize(children_ctx_var)
521
- @children_ctx_var = children_ctx_var
522
- end
526
+ class ForkNode
527
+ def initialize(children_ctx_var)
528
+ @children_ctx_var = children_ctx_var
529
+ end
523
530
 
524
- def action(token, caller)
525
- exits = []
526
- token[@children_ctx_var].each do |ctx_vars|
527
- exits << [:default, token.fork(ctx_vars)]
531
+ def action(token, caller)
532
+ exits = []
533
+ token[@children_ctx_var].each do |ctx_vars|
534
+ exits << [:default, token.fork(ctx_vars)]
535
+ end
536
+ return exits
528
537
  end
529
- return exits
530
538
  end
531
- end
532
539
 
533
- class JoinNode
534
- def action(token, caller)
535
- parent_token = token.parent
536
- token.done
537
- parent_token.childs? ? nil : [[:default, parent_token]]
540
+ class JoinNode
541
+ def action(token, caller)
542
+ parent_token = token.parent
543
+ token.done
544
+ parent_token.childs? ? nil : [[:default, parent_token]]
545
+ end
538
546
  end
539
- end
540
547
 
541
- class CallNode
542
- def initialize(workflow, workflow_version, call_in, call_out)
543
- @workflow = workflow
544
- @workflow_version = workflow_version
545
- @call_in = call_in
546
- @call_out = call_out
547
- end
548
+ class CallNode
549
+ def initialize(workflow, workflow_version, call_in, call_out)
550
+ @workflow = workflow
551
+ @workflow_version = workflow_version
552
+ @call_in = call_in
553
+ @call_out = call_out
554
+ end
548
555
 
549
- def action(token, caller)
550
- if token.sub_process
551
- #sub process has been finished...
556
+ def action(token, caller)
557
+ if token.sub_process
558
+ #sub process has been finished...
552
559
 
553
- @call_out.each do |remote,local|
554
- token[local] = token.sub_process[remote]
555
- end
560
+ @call_out.each do |remote,local|
561
+ token[local] = token.sub_process[remote]
562
+ end
556
563
 
557
- token.sub_process = nil
564
+ token.sub_process = nil
558
565
 
559
- return [[:default, token]]
560
- else
561
- #let's start a sub process...
562
-
563
- if (@workflow.is_a? Symbol)
564
- sub_wf = WorkflowVersionManager.create_workflow_instance(@workflow, @workflow_version.nil? ? :latest : @workflow_version)
566
+ return [[:default, token]]
565
567
  else
566
- sub_wf = @workflow.new
567
- end
568
-
569
- params = {}
570
- @call_in.each do |local,remote|
571
- params[remote] = token[local]
572
- end
568
+ #let's start a sub process...
573
569
 
574
- sub_t = sub_wf.start(params)
570
+ if (@workflow.is_a? Symbol)
571
+ sub_wf = WorkflowVersionManager.create_workflow_instance(@workflow, @workflow_version.nil? ? :latest : @workflow_version)
572
+ else
573
+ sub_wf = @workflow.new
574
+ end
575
575
 
576
- if (sub_t.end?)
577
- @call_out.each do |remote,local|
578
- token[local] = sub_t[remote]
576
+ params = {}
577
+ @call_in.each do |local,remote|
578
+ params[remote] = token[local]
579
579
  end
580
580
 
581
- return [[:default, token]]
582
- else
583
- sub_t.parent_process = token
584
- token.sub_process = sub_t
581
+ sub_t = sub_wf.start(params)
582
+
583
+ if (sub_t.end?)
584
+ @call_out.each do |remote,local|
585
+ token[local] = sub_t[remote]
586
+ end
587
+
588
+ return [[:default, token]]
589
+ else
590
+ sub_t.parent_process = token
591
+ token.sub_process = sub_t
585
592
 
586
- return nil #stop wf execution... we'll be called later...
593
+ return nil #stop wf execution... we'll be called later...
594
+ end
587
595
  end
588
596
  end
589
597
  end
590
- end
598
+ end