openwferu 0.9.9 → 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/examples/kotoba.rb +22 -0
  2. data/lib/openwfe/engine/engine.rb +46 -10
  3. data/lib/openwfe/expool/expressionpool.rb +84 -71
  4. data/lib/openwfe/expool/history.rb +6 -2
  5. data/lib/openwfe/expool/journal.rb +9 -3
  6. data/lib/openwfe/expool/journal_replay.rb +8 -5
  7. data/lib/openwfe/expressions/fe_participant.rb +32 -1
  8. data/lib/openwfe/filterdef.rb +1 -1
  9. data/lib/openwfe/omixins.rb +70 -0
  10. data/lib/openwfe/participants/participantmap.rb +14 -1
  11. data/lib/openwfe/rest/definitions.rb +2 -1
  12. data/lib/openwfe/rest/xmlcodec.rb +56 -27
  13. data/lib/openwfe/util/kotoba.rb +2 -2
  14. data/lib/openwfe/util/workqueue.rb +177 -0
  15. data/lib/openwfe/utils.rb +52 -13
  16. data/lib/openwfe/version.rb +1 -1
  17. data/lib/openwfe/worklist/storeparticipant.rb +7 -4
  18. data/test/fei_test.rb +12 -1
  19. data/test/flowtestbase.rb +21 -8
  20. data/test/ft_0b_sequence.rb +6 -4
  21. data/test/ft_10_loop.rb +10 -5
  22. data/test/ft_10b_loop2.rb +5 -2
  23. data/test/ft_11_ppd.rb +12 -5
  24. data/test/ft_1_unset.rb +22 -13
  25. data/test/ft_23c_wait.rb +10 -6
  26. data/test/ft_25_cancel.rb +11 -5
  27. data/test/ft_27_getflowpos.rb +21 -4
  28. data/test/ft_28_fileparticipant.rb +1 -1
  29. data/test/ft_2c_concurrence.rb +8 -4
  30. data/test/ft_30_socketlistener.rb +8 -0
  31. data/test/ft_32_journal.rb +11 -2
  32. data/test/ft_34_cancelwfid.rb +4 -0
  33. data/test/ft_36_subprocids.rb +2 -1
  34. data/test/ft_37_pnames.rb +1 -1
  35. data/test/ft_38_tag.rb +5 -5
  36. data/test/ft_39_reserve.rb +1 -41
  37. data/test/ft_39b_reserve.rb +70 -0
  38. data/test/ft_40_defined.rb +2 -1
  39. data/test/ft_42_environments.rb +1 -2
  40. data/test/ft_45_citerator.rb +16 -4
  41. data/test/ft_46_pparams.rb +3 -0
  42. data/test/ft_49_condition.rb +2 -1
  43. data/test/ft_50_xml_attribute.rb +72 -3
  44. data/test/ft_51_stack.rb +58 -0
  45. data/test/ft_52_obs_participant.rb +127 -0
  46. data/test/ft_7b_lose.rb +5 -4
  47. data/test/ft_tests.rb +3 -0
  48. data/test/hparticipant_test.rb +21 -18
  49. data/test/misc_test.rb +9 -0
  50. data/test/param_test.rb +6 -0
  51. data/test/rake_test.rb +1 -0
  52. data/test/scheduler_test.rb +21 -0
  53. data/test/sec_test.rb +14 -27
  54. data/test/timeout_test.rb +6 -2
  55. metadata +8 -2
@@ -0,0 +1,22 @@
1
+
2
+ require 'pp'
3
+ require 'rubygems'
4
+ require 'openwfe/util/kotoba'
5
+
6
+ 3.times do
7
+
8
+ i = (rand * 1000000).to_i
9
+ s = Kotoba::from_integer i
10
+
11
+ puts "#{i} => #{s}"
12
+ puts "#{s} => #{Kotoba::to_integer(s)}"
13
+ # forth and back
14
+
15
+ a = Kotoba::split s
16
+
17
+ print "#{s} => "; pp a
18
+ # showing how the 'word' is split
19
+
20
+ puts "."
21
+ end
22
+
@@ -128,13 +128,10 @@ module OpenWFE
128
128
  # either a String containing the URL of the process definition
129
129
  # to launch (with an empty LaunchItem created on the fly).
130
130
  #
131
- # If async is set to true, the process will be launched asynchronously
132
- # (in his own thread).
131
+ # Returns the FlowExpressionId instance of the expression at the
132
+ # root of the newly launched process.
133
133
  #
134
- # Returns a FlowExpressionId instance or a tuple FlowExpressionId /
135
- # Thread object if async is set to true.
136
- #
137
- def launch (launch_object, async=false)
134
+ def launch (launch_object)
138
135
 
139
136
  launchitem = if launch_object.kind_of?(OpenWFE::LaunchItem)
140
137
 
@@ -158,7 +155,7 @@ module OpenWFE
158
155
  li
159
156
  end
160
157
 
161
- get_expression_pool.launch launchitem, async
158
+ get_expression_pool.launch launchitem
162
159
  end
163
160
 
164
161
  #
@@ -172,11 +169,11 @@ module OpenWFE
172
169
 
173
170
  if workitem.kind_of?(InFlowWorkItem)
174
171
 
175
- get_expression_pool.reply(workitem.flow_expression_id, workitem)
172
+ get_expression_pool.reply workitem.flow_expression_id, workitem
176
173
 
177
174
  elsif workitem.kind_of?(LaunchItem)
178
175
 
179
- get_expression_pool.launch(workitem, false)
176
+ get_expression_pool.launch workitem
180
177
 
181
178
  else
182
179
 
@@ -300,7 +297,7 @@ module OpenWFE
300
297
  OpenWFE::trap_int_irb(binding)
301
298
  end
302
299
 
303
- #
300
+ #--
304
301
  # Makes sure that hitting CTRL-C will actually kill the engine VM and
305
302
  # not open an IRB console.
306
303
  #
@@ -310,6 +307,7 @@ module OpenWFE
310
307
  # exit 0
311
308
  # end
312
309
  #end
310
+ #++
313
311
 
314
312
  #
315
313
  # Stopping the engine will stop all the services in the
@@ -398,6 +396,44 @@ module OpenWFE
398
396
  get_expression_pool.forget(exp_or_fei)
399
397
  end
400
398
 
399
+ #
400
+ # Waits for a given process instance to terminate.
401
+ # The method only exits when the flow terminates, but beware : if
402
+ # the process already terminated, the method will never exit.
403
+ #
404
+ # The parameter can be a FlowExpressionId instance, for example the
405
+ # one given back by a launch(), or directly a workflow instance id
406
+ # (String).
407
+ #
408
+ # This method is mainly used in utests.
409
+ #
410
+ def wait_for (fei_or_wfid)
411
+
412
+ wfid = if fei_or_wfid.kind_of?(FlowExpressionId)
413
+ fei_or_wfid.workflow_instance_id
414
+ else
415
+ fei_or_wfid
416
+ end
417
+
418
+ #Thread.pass
419
+ # #
420
+ # # let the flow 'stabilize' or progress before enquiring
421
+ #fexp = get_expression_pool.fetch_expression(fei)
422
+ #return unless fexp
423
+ #
424
+ # doesn't work well
425
+
426
+ t = Thread.new { Thread.stop }
427
+
428
+ get_expression_pool.add_observer(:terminate) do |channel, fe, wi|
429
+ t.wakeup if fe.fei.workflow_instance_id == wfid
430
+ end
431
+
432
+ ldebug { "wait_for() #{wfid}" }
433
+
434
+ t.join
435
+ end
436
+
401
437
  protected
402
438
 
403
439
  #
@@ -51,6 +51,7 @@ require 'openwfe/rudefinitions'
51
51
  require 'openwfe/flowexpressionid'
52
52
  require 'openwfe/util/lru'
53
53
  require 'openwfe/util/safe'
54
+ require 'openwfe/util/workqueue'
54
55
  require 'openwfe/util/observable'
55
56
  require 'openwfe/expressions/environment'
56
57
  require 'openwfe/expressions/raw_xml'
@@ -130,7 +131,8 @@ module OpenWFE
130
131
  ServiceMixin,
131
132
  MonitorMixin,
132
133
  OwfeServiceLocator,
133
- Observable
134
+ Observable,
135
+ WorkqueueMixin
134
136
 
135
137
  SAFETY_LEVEL = 2
136
138
  #
@@ -148,6 +150,8 @@ module OpenWFE
148
150
  @observers = {}
149
151
 
150
152
  @stopped = false
153
+
154
+ start_workqueue
151
155
  end
152
156
 
153
157
  #
@@ -155,6 +159,7 @@ module OpenWFE
155
159
  #
156
160
  def stop
157
161
  @stopped = true
162
+ stop_workqueue
158
163
  onotify :stop
159
164
  end
160
165
 
@@ -204,16 +209,15 @@ module OpenWFE
204
209
  #
205
210
  # Instantiates a workflow definition and launches it.
206
211
  #
207
- # If async is set to true, the launch will occur in its own thread.
212
+ # This method call will return immediately, it could even return
213
+ # before the actual launch is completely over.
208
214
  #
209
215
  # Returns the FlowExpressionId instance of the root expression of
210
216
  # the newly launched flow.
211
- # If async is set to true, returns a tuple FlowExpressionId /
212
- # Thread instance used.
213
217
  #
214
- def launch (launchitem, async=false)
218
+ def launch (launchitem)
215
219
 
216
- raw_expression = prepare_raw_expression(launchitem)
220
+ raw_expression = prepare_raw_expression launchitem
217
221
  #
218
222
  # will raise an exception if there are requirements
219
223
  # and one of them is not met
@@ -224,25 +228,15 @@ module OpenWFE
224
228
  # it has to have an environment for all the variables of
225
229
  # the process instance
226
230
 
227
- wi = build_workitem(launchitem)
231
+ wi = build_workitem launchitem
228
232
 
229
233
  fei = raw_expression.fei
230
234
 
231
- onotify :launch, launchitem.workflow_definition_url
232
-
233
- if async
234
-
235
- t = OpenWFE::call_in_thread "launch()", self do
236
- apply(raw_expression, wi)
237
- end
238
-
239
- return fei, t
240
- end
235
+ onotify :launch, fei, launchitem
241
236
 
242
- apply(raw_expression, wi)
237
+ apply raw_expression, wi
243
238
 
244
- return fei
245
- #return fei, Thread.current
239
+ fei
246
240
  end
247
241
 
248
242
  #
@@ -266,10 +260,6 @@ module OpenWFE
266
260
  #raise "did not find expression at #{template.to_s}" \
267
261
  # unless rawexp
268
262
 
269
- ldebug { "launch_template() request for #{rawexp.fei.to_debug_s}" }
270
-
271
- onotify :launch_template, rawexp.fei
272
-
273
263
  rawexp = rawexp.dup()
274
264
  rawexp.fei = rawexp.fei.dup()
275
265
 
@@ -322,6 +312,8 @@ module OpenWFE
322
312
 
323
313
  workitem.flow_expression_id = rawexp.fei
324
314
 
315
+ onotify :launch_template, rawexp.fei, workitem
316
+
325
317
  apply rawexp, workitem
326
318
 
327
319
  rawexp.fei
@@ -349,26 +341,17 @@ module OpenWFE
349
341
  #
350
342
  def apply (exp, workitem)
351
343
 
352
- exp, fei = fetch(exp) if exp.kind_of? FlowExpressionId
353
-
354
- #ldebug { "apply() '#{fei}' (#{fei.class})" }
355
-
356
- if not exp
357
- lwarn { "apply() cannot apply missing #{fei.to_debug_s}" }
358
- return
359
- end
360
-
361
- #ldebug { "apply() #{fei.to_debug_s}" }
362
-
363
- #exp.apply_time = OpenWFE::now()
364
- #
365
- # this is done in RawExpression
366
-
367
- workitem.flow_expression_id = exp.fei
344
+ #do_apply exp, workitem
345
+ queue_work :do_apply, exp, workitem
346
+ end
368
347
 
369
- onotify :apply, exp.fei, workitem
348
+ #
349
+ # Replies to a given expression
350
+ #
351
+ def reply (exp, workitem)
370
352
 
371
- exp.apply(workitem)
353
+ #do_reply exp, workitem
354
+ queue_work :do_reply, exp, workitem
372
355
  end
373
356
 
374
357
  #
@@ -387,7 +370,7 @@ module OpenWFE
387
370
 
388
371
  ldebug { "cancel() for #{fei.to_debug_s}" }
389
372
 
390
- onotify :cancel, fei
373
+ onotify :cancel, exp
391
374
 
392
375
  inflowitem = exp.cancel()
393
376
  remove(exp)
@@ -401,7 +384,7 @@ module OpenWFE
401
384
  #
402
385
  def cancel_flow (exp_or_wfid)
403
386
 
404
- ldebug { "cancel_flow() from #{exp_or_wfid}" }
387
+ #ldebug { "cancel_flow() from #{exp_or_wfid}" }
405
388
 
406
389
  root = fetch_root(exp_or_wfid)
407
390
  cancel(root)
@@ -420,7 +403,7 @@ module OpenWFE
420
403
 
421
404
  return if not exp
422
405
 
423
- onotify :forget, fei
406
+ onotify :forget, exp
424
407
 
425
408
  parent_exp.children.delete(fei)
426
409
 
@@ -440,7 +423,7 @@ module OpenWFE
440
423
 
441
424
  workitem.last_expression_id = exp.fei
442
425
 
443
- onotify :reply_to_parent, exp.fei, workitem
426
+ onotify :reply_to_parent, exp, workitem
444
427
 
445
428
  if remove
446
429
 
@@ -465,12 +448,13 @@ module OpenWFE
465
448
  # flow terminated ?
466
449
 
467
450
  if not exp.parent_id
451
+
468
452
  ldebug do
469
453
  "reply_to_parent() process " +
470
454
  "#{exp.fei.workflow_instance_id} terminated"
471
455
  end
472
456
 
473
- onotify :terminate, exp.fei
457
+ onotify :terminate, exp, workitem
474
458
 
475
459
  return
476
460
  end
@@ -493,27 +477,6 @@ module OpenWFE
493
477
  reply exp.parent_id, workitem
494
478
  end
495
479
 
496
- #
497
- # Triggers the reply expression of the expression given by its id.
498
- #
499
- def reply (exp, workitem)
500
-
501
- exp, fei = fetch(exp)
502
-
503
- ldebug { "reply() to #{fei.to_debug_s}" }
504
- ldebug { "reply() from #{workitem.last_expression_id.to_debug_s}" }
505
-
506
- if not exp
507
- #raise "cannot reply to missing #{fei.to_debug_s}"
508
- lwarn { "reply() cannot reply to missing #{fei.to_debug_s}" }
509
- return
510
- end
511
-
512
- onotify :reply, fei, workitem
513
-
514
- exp.reply(workitem)
515
- end
516
-
517
480
  #
518
481
  # Adds or updates a flow expression in this pool
519
482
  #
@@ -754,9 +717,59 @@ module OpenWFE
754
717
 
755
718
  protected
756
719
 
757
- #def evaluate_definition (raw_definition, workitem)
758
- # expression = raw_definition.instantiate(workitem)
759
- #end
720
+ def do_process_workelement elt
721
+
722
+ message, fei, workitem = elt
723
+ send message, fei, workitem
724
+ end
725
+
726
+ #
727
+ # The real apply work.
728
+ #
729
+ def do_apply (exp, workitem)
730
+
731
+ exp, fei = fetch(exp) if exp.kind_of? FlowExpressionId
732
+
733
+ #ldebug { "apply() '#{fei}' (#{fei.class})" }
734
+
735
+ if not exp
736
+ lwarn { "apply() cannot apply missing #{fei.to_debug_s}" }
737
+ return
738
+ end
739
+
740
+ #ldebug { "apply() #{fei.to_debug_s}" }
741
+
742
+ #exp.apply_time = OpenWFE::now()
743
+ #
744
+ # this is done in RawExpression
745
+
746
+ workitem.flow_expression_id = exp.fei
747
+
748
+ onotify :apply, exp, workitem
749
+
750
+ exp.apply(workitem)
751
+ end
752
+
753
+ #
754
+ # The real reply work is done here
755
+ #
756
+ def do_reply (exp, workitem)
757
+
758
+ exp, fei = fetch(exp)
759
+
760
+ ldebug { "reply() to #{fei.to_debug_s}" }
761
+ ldebug { "reply() from #{workitem.last_expression_id.to_debug_s}" }
762
+
763
+ if not exp
764
+ #raise "cannot reply to missing #{fei.to_debug_s}"
765
+ lwarn { "reply() cannot reply to missing #{fei.to_debug_s}" }
766
+ return
767
+ end
768
+
769
+ onotify :reply, exp, workitem
770
+
771
+ exp.reply(workitem)
772
+ end
760
773
 
761
774
  #
762
775
  # Removes an environment, especially takes care of unbinding
@@ -42,6 +42,7 @@
42
42
  #require 'date'
43
43
 
44
44
  require 'openwfe/service'
45
+ require 'openwfe/omixins'
45
46
  require 'openwfe/rudefinitions'
46
47
 
47
48
 
@@ -73,6 +74,7 @@ module OpenWFE
73
74
  #
74
75
  class BaseHistory
75
76
  include HistoryMixin
77
+ include FeiMixin
76
78
 
77
79
  attr_reader :entries
78
80
 
@@ -93,8 +95,10 @@ module OpenWFE
93
95
 
94
96
  msg << event.to_s
95
97
 
96
- msg << " #{args[0].to_s}" \
97
- if args.length > 0
98
+ if args.length > 0
99
+ fei = extract_fei args[0]
100
+ msg << " #{fei.to_s}"
101
+ end
98
102
 
99
103
  #msg << " #{args[1].to_s}" \
100
104
  # if args.length > 1
@@ -43,6 +43,7 @@ require 'monitor'
43
43
  require 'fileutils'
44
44
 
45
45
  require 'openwfe/service'
46
+ require 'openwfe/omixins'
46
47
  require 'openwfe/rudefinitions'
47
48
  require 'openwfe/flowexpressionid'
48
49
  require 'openwfe/util/otime'
@@ -58,6 +59,7 @@ module OpenWFE
58
59
  class Journal < Service
59
60
  include MonitorMixin, OwfeServiceLocator
60
61
  include JournalReplay
62
+ include FeiMixin
61
63
 
62
64
  attr_reader :workdir, :donedir
63
65
 
@@ -77,7 +79,7 @@ module OpenWFE
77
79
  FileUtils.makedirs(@donedir) unless File.exist?(@donedir)
78
80
 
79
81
  get_expression_pool.add_observer(:all) do |event, *args|
80
- #ldebug { ":#{event} for #{args[0].to_debug_s}" }
82
+ #ldebug { ":#{event} for #{args[0].class.name}" }
81
83
  queue_event(event, *args)
82
84
  end
83
85
 
@@ -109,8 +111,12 @@ module OpenWFE
109
111
  return if event == :launch
110
112
  return if event == :reschedule
111
113
 
112
- wfid = args[0].parent_wfid
113
- #puts "__#{wfid} : #{event}"
114
+ #wfid = args[0].parent_wfid
115
+ wfid = extract_fei(args[0]).parent_wfid
116
+ #
117
+ # maybe args[0] could be a FlowExpression instead
118
+ # of a FlowExpressionId instance
119
+ #puts "___#{event}__wfid : #{wfid}"
114
120
 
115
121
  e = serialize_event(event, *args)
116
122
 
@@ -47,7 +47,7 @@ module OpenWFE
47
47
  #
48
48
  # The code decicated to replay and reconstitute journal.
49
49
  #
50
- module JournalReplay
50
+ module JournalReplay
51
51
 
52
52
  #
53
53
  # Replays a given journal file.
@@ -83,10 +83,12 @@ module OpenWFE
83
83
 
84
84
  return unless trigger_action
85
85
 
86
+ #puts "sds : #{state.dynamic.size}"
87
+
86
88
  state.dynamic.each do |ply|
87
89
 
88
90
  message = ply[0]
89
- fei = ply[2]
91
+ fei = extract_fei(ply[2])
90
92
  wi = ply[3]
91
93
 
92
94
  if wi
@@ -203,7 +205,7 @@ module OpenWFE
203
205
  dynamic = []
204
206
  events.reverse.each do |e|
205
207
  etype = e[0]
206
- fei = e[2]
208
+ fei = extract_fei e[2]
207
209
  next if etype == :update
208
210
  next if etype == :remove
209
211
  #next if etype == :reply_to_parent
@@ -217,6 +219,7 @@ module OpenWFE
217
219
  end
218
220
 
219
221
  class ExpoolState
222
+ include FeiMixin
220
223
 
221
224
  attr_accessor \
222
225
  :offset,
@@ -241,13 +244,13 @@ module OpenWFE
241
244
  s << "\n"
242
245
  s << "static :\n"
243
246
  @static.each do |e|
244
- s << " - #{e[0]} #{e[2].to_short_s}\n"
247
+ s << " - #{e[0]} #{extract_fei(e[2]).to_short_s}\n"
245
248
  end
246
249
 
247
250
  s << "\n"
248
251
  s << "dynamic :\n"
249
252
  @dynamic.each do |e|
250
- s << " - #{e[0]} #{e[2].to_short_s}\n"
253
+ s << " - #{e[0]} #{extract_fei(e[2]).to_short_s}\n"
251
254
  end
252
255
 
253
256
  #s << "\n"
@@ -57,9 +57,40 @@ module OpenWFE
57
57
  # to it to the Participant instance it looks up in the participant map
58
58
  # tied to the engine.
59
59
  #
60
+ # <participant ref="alpha" />
61
+ # <!-- direct reference to participant alpha -->
62
+ #
63
+ # <participant field-ref="target" />
64
+ # <participant ref="${f:target}" />
65
+ # <!-- the name of the participant is the value found in
66
+ # the field 'target' -->
67
+ #
68
+ # <participant variable-ref="target" />
69
+ # <participant ref="${target}" />
70
+ # <!-- the name of the participant is the value found in
71
+ # the variable 'target' -->
72
+ #
73
+ # <alpha />
74
+ # <!-- direct reference to participant 'alpha'
75
+ # if a subprocess named 'alpha' has been defined, the
76
+ # subprocess will be called instead -->
77
+ #
60
78
  # The Participant expressions includes the FilterMixin and thus
61
79
  # understands and applies the "filter" attribute.
62
80
  #
81
+ # Since OpenWFE 0.9.9, the attributes of the participant expression are
82
+ # set inside a hash field named 'params' just available to the participant.
83
+ # Thus in
84
+ #
85
+ # <participant ref="toto" task="play golf" location="Minami Center" />
86
+ #
87
+ # participant 'toto' will receive a workitem with a field named 'params'
88
+ # containing the hash
89
+ # { "ref"=>"toto", "task"=>"play golf", "location"=>"Minami Center" }.
90
+ #
91
+ # When the workitem gets back from the participant, the field 'params' is
92
+ # deleted.
93
+ #
63
94
  class ParticipantExpression < FlowExpression
64
95
  include FilterMixin
65
96
  include TimeoutMixin
@@ -91,7 +122,7 @@ module OpenWFE
91
122
 
92
123
  workitem.params = lookup_attributes workitem
93
124
 
94
- get_participant_map.dispatch(@participant_name, workitem)
125
+ get_participant_map.dispatch @participant_name, workitem
95
126
  end
96
127
 
97
128
  def reply_to_parent (workitem)
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2007, John Mettraux, Nicolas Modrzyk OpenWFE.org
3
+ # Copyright (c) 2007, John Mettraux OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -0,0 +1,70 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+ # $Id: utils.rb 3454 2006-10-08 16:51:00Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # john.mettraux@openwfe.org
40
+ #
41
+
42
+ require 'openwfe/flowexpressionid'
43
+
44
+
45
+ module OpenWFE
46
+
47
+ #
48
+ # A few methods about FlowExpressionIds
49
+ #
50
+ module FeiMixin
51
+
52
+ #
53
+ # Makes sure to return a FlowExpressionId instance.
54
+ #
55
+ def extract_fei (object)
56
+
57
+ if object.kind_of?(FlowExpressionId)
58
+ object
59
+ elsif object.kind_of?(FlowExpression) or object.kind_of?(InFlowItem)
60
+ object.fei
61
+ elsif object.kind_of?(String)
62
+ FlowExpressionId.to_fei object
63
+ else
64
+ raise "cannot extract FlowExpressionId out of #{object.inspect}"
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+