openwferu 0.9.9 → 0.9.10

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.
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
+