ruote 2.3.0.1 → 2.3.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.
Files changed (148) hide show
  1. data/CHANGELOG.txt +23 -0
  2. data/CREDITS.txt +4 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/ruote.rb +2 -0
  5. data/lib/ruote/context.rb +2 -1
  6. data/lib/ruote/dashboard.rb +169 -13
  7. data/lib/ruote/dboard/mutation.rb +282 -0
  8. data/lib/ruote/dboard/process_error.rb +1 -1
  9. data/lib/ruote/dboard/process_status.rb +61 -48
  10. data/lib/ruote/engine.rb +1 -1
  11. data/lib/ruote/exp/command.rb +1 -1
  12. data/lib/ruote/exp/commanded.rb +1 -1
  13. data/lib/ruote/exp/condition.rb +2 -1
  14. data/lib/ruote/exp/fe_add_branches.rb +1 -1
  15. data/lib/ruote/exp/fe_apply.rb +1 -1
  16. data/lib/ruote/exp/fe_await.rb +97 -48
  17. data/lib/ruote/exp/fe_cancel_process.rb +1 -1
  18. data/lib/ruote/exp/fe_command.rb +2 -3
  19. data/lib/ruote/exp/fe_concurrence.rb +162 -66
  20. data/lib/ruote/exp/fe_concurrent_iterator.rb +25 -7
  21. data/lib/ruote/exp/fe_cron.rb +1 -1
  22. data/lib/ruote/exp/fe_cursor.rb +10 -11
  23. data/lib/ruote/exp/fe_define.rb +1 -1
  24. data/lib/ruote/exp/fe_echo.rb +1 -1
  25. data/lib/ruote/exp/fe_equals.rb +1 -1
  26. data/lib/ruote/exp/fe_error.rb +1 -1
  27. data/lib/ruote/exp/fe_filter.rb +1 -1
  28. data/lib/ruote/exp/fe_forget.rb +1 -1
  29. data/lib/ruote/exp/fe_given.rb +1 -1
  30. data/lib/ruote/exp/fe_if.rb +87 -7
  31. data/lib/ruote/exp/fe_inc.rb +1 -1
  32. data/lib/ruote/exp/fe_iterator.rb +1 -1
  33. data/lib/ruote/exp/fe_listen.rb +1 -1
  34. data/lib/ruote/exp/fe_lose.rb +1 -1
  35. data/lib/ruote/exp/fe_noop.rb +1 -1
  36. data/lib/ruote/exp/fe_on_error.rb +1 -1
  37. data/lib/ruote/exp/fe_once.rb +1 -1
  38. data/lib/ruote/exp/fe_participant.rb +49 -16
  39. data/lib/ruote/exp/fe_read.rb +1 -1
  40. data/lib/ruote/exp/fe_redo.rb +1 -1
  41. data/lib/ruote/exp/fe_ref.rb +1 -1
  42. data/lib/ruote/exp/fe_registerp.rb +1 -1
  43. data/lib/ruote/exp/fe_reserve.rb +1 -1
  44. data/lib/ruote/exp/fe_restore.rb +1 -7
  45. data/lib/ruote/exp/fe_save.rb +1 -1
  46. data/lib/ruote/exp/fe_sequence.rb +1 -1
  47. data/lib/ruote/exp/fe_set.rb +1 -1
  48. data/lib/ruote/exp/fe_stall.rb +1 -1
  49. data/lib/ruote/exp/fe_subprocess.rb +1 -1
  50. data/lib/ruote/exp/fe_that.rb +1 -1
  51. data/lib/ruote/exp/fe_undo.rb +1 -1
  52. data/lib/ruote/exp/fe_unregisterp.rb +1 -1
  53. data/lib/ruote/exp/fe_wait.rb +1 -1
  54. data/lib/ruote/exp/flow_expression.rb +117 -8
  55. data/lib/ruote/exp/iterator.rb +1 -1
  56. data/lib/ruote/exp/ro_attributes.rb +1 -1
  57. data/lib/ruote/exp/ro_filters.rb +1 -1
  58. data/lib/ruote/exp/ro_on_x.rb +4 -2
  59. data/lib/ruote/exp/ro_persist.rb +1 -1
  60. data/lib/ruote/exp/ro_timers.rb +1 -1
  61. data/lib/ruote/exp/ro_variables.rb +1 -1
  62. data/lib/ruote/extract.rb +125 -0
  63. data/lib/ruote/fei.rb +10 -73
  64. data/lib/ruote/id/mnemo_wfid_generator.rb +1 -1
  65. data/lib/ruote/id/wfid_generator.rb +1 -1
  66. data/lib/ruote/log/default_history.rb +17 -3
  67. data/lib/ruote/log/fancy_printing.rb +12 -32
  68. data/lib/ruote/log/storage_history.rb +1 -1
  69. data/lib/ruote/log/wait_logger.rb +15 -7
  70. data/lib/ruote/merge.rb +123 -0
  71. data/lib/ruote/observer.rb +1 -1
  72. data/lib/ruote/part/block_participant.rb +1 -1
  73. data/lib/ruote/part/code_participant.rb +1 -1
  74. data/lib/ruote/part/engine_participant.rb +1 -1
  75. data/lib/ruote/part/local_participant.rb +9 -1
  76. data/lib/ruote/part/no_op_participant.rb +1 -1
  77. data/lib/ruote/part/null_participant.rb +1 -1
  78. data/lib/ruote/part/participant.rb +1 -1
  79. data/lib/ruote/part/rev_participant.rb +1 -1
  80. data/lib/ruote/part/smtp_participant.rb +1 -1
  81. data/lib/ruote/part/storage_participant.rb +18 -1
  82. data/lib/ruote/part/template.rb +1 -1
  83. data/lib/ruote/reader.rb +1 -1
  84. data/lib/ruote/reader/json.rb +1 -1
  85. data/lib/ruote/reader/radial.rb +4 -4
  86. data/lib/ruote/reader/ruby_dsl.rb +1 -1
  87. data/lib/ruote/reader/xml.rb +1 -1
  88. data/lib/ruote/receiver/base.rb +13 -1
  89. data/lib/ruote/storage/base.rb +8 -14
  90. data/lib/ruote/storage/composite_storage.rb +1 -1
  91. data/lib/ruote/storage/fs_storage.rb +1 -1
  92. data/lib/ruote/storage/hash_storage.rb +2 -1
  93. data/lib/ruote/svc/dispatch_pool.rb +29 -18
  94. data/lib/ruote/svc/dollar_sub.rb +5 -8
  95. data/lib/ruote/svc/error_handler.rb +1 -1
  96. data/lib/ruote/svc/expression_map.rb +1 -1
  97. data/lib/ruote/svc/participant_list.rb +8 -5
  98. data/lib/ruote/svc/tracker.rb +154 -56
  99. data/lib/ruote/svc/treechecker.rb +1 -1
  100. data/lib/ruote/tree_dot.rb +1 -1
  101. data/lib/ruote/util/deep.rb +4 -2
  102. data/lib/ruote/util/filter.rb +1 -1
  103. data/lib/ruote/util/hashdot.rb +1 -1
  104. data/lib/ruote/util/look.rb +1 -1
  105. data/lib/ruote/util/lookup.rb +1 -1
  106. data/lib/ruote/util/misc.rb +51 -1
  107. data/lib/ruote/util/mpatch.rb +1 -1
  108. data/lib/ruote/util/ometa.rb +1 -1
  109. data/lib/ruote/util/subprocess.rb +1 -1
  110. data/lib/ruote/util/time.rb +3 -3
  111. data/lib/ruote/util/tree.rb +43 -4
  112. data/lib/ruote/version.rb +2 -2
  113. data/lib/ruote/worker.rb +30 -18
  114. data/lib/ruote/workitem.rb +1 -1
  115. data/ruote.gemspec +6 -2
  116. data/test/functional/base.rb +0 -1
  117. data/test/functional/concurrent_base.rb +1 -1
  118. data/test/functional/eft_14_cursor.rb +42 -52
  119. data/test/functional/eft_16_if.rb +24 -16
  120. data/test/functional/eft_18_concurrent_iterator.rb +31 -1
  121. data/test/functional/eft_6_concurrence.rb +149 -34
  122. data/test/functional/ft_10_dollar.rb +14 -30
  123. data/test/functional/ft_12_launchitem.rb +15 -0
  124. data/test/functional/ft_1_process_status.rb +62 -13
  125. data/test/functional/ft_20_storage_participant.rb +25 -0
  126. data/test/functional/ft_38_participant_more.rb +1 -1
  127. data/test/functional/ft_42_storage_copy.rb +1 -3
  128. data/test/functional/ft_43_participant_on_reply.rb +63 -5
  129. data/test/functional/ft_66_flank.rb +41 -0
  130. data/test/functional/ft_6_on_cancel.rb +9 -18
  131. data/test/functional/ft_71_retries.rb +25 -12
  132. data/test/functional/ft_79_attach.rb +138 -0
  133. data/test/functional/ft_7_tags.rb +27 -0
  134. data/test/functional/ft_80_pause_on_apply.rb +64 -0
  135. data/test/functional/ft_81_mutation.rb +417 -0
  136. data/test/functional/ft_82_await_attribute.rb +84 -0
  137. data/test/functional/ft_83_trackers.rb +79 -0
  138. data/test/functional/storage.rb +3 -4
  139. data/test/unit/ut_12_wait_logger.rb +41 -3
  140. data/test/unit/ut_15_util.rb +30 -0
  141. data/test/unit/ut_17_merge.rb +54 -53
  142. data/test/unit/ut_1_fei.rb +2 -2
  143. data/test/unit/ut_24_radial_reader.rb +7 -0
  144. data/test/unit/ut_26_deep.rb +14 -0
  145. data/test/unit/ut_5_tree.rb +38 -28
  146. metadata +206 -169
  147. data/couch_url.txt +0 -1
  148. data/lib/ruote/exp/merge.rb +0 -134
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -174,6 +174,14 @@ module Ruote::Exp
174
174
  nil
175
175
  end
176
176
 
177
+ # Returns the child_id for this expression. (The rightmost part of the
178
+ # fei.expid).
179
+ #
180
+ def child_id
181
+
182
+ fei.child_id
183
+ end
184
+
177
185
  # Fetches the parent expression, or returns nil if there is no parent
178
186
  # expression.
179
187
  #
@@ -227,6 +235,14 @@ module Ruote::Exp
227
235
  root(stubborn).fei
228
236
  end
229
237
 
238
+ # Concurrent expressions (expressions that apply more than one child
239
+ # at a time) are supposed to return true here.
240
+ #
241
+ def is_concurrent?
242
+
243
+ false
244
+ end
245
+
230
246
  # Turns this FlowExpression instance into a Hash (well, just hands back
231
247
  # the base hash behind it).
232
248
  #
@@ -242,6 +258,25 @@ module Ruote::Exp
242
258
  @awi ||= Ruote::Workitem.new(h.applied_workitem)
243
259
  end
244
260
 
261
+ # Given an index, returns the child fei (among the currently registered
262
+ # children feis) whose fei.expid ends with this index (whose child_id
263
+ # is equal to that index).
264
+ #
265
+ # Returns nil if not found or a child fei as a Hash.
266
+ #
267
+ def cfei_at(i)
268
+
269
+ children.find { |cfei| Ruote.extract_child_id(cfei) == i }
270
+ end
271
+
272
+ # Returns the list of child_ids (last part of the fei.expid) for the
273
+ # currently registered (active) children.
274
+ #
275
+ def child_ids
276
+
277
+ children.collect { |cfei| Ruote.extract_child_id(cfei) }
278
+ end
279
+
245
280
  # Instantiates expression back from hash.
246
281
  #
247
282
  def self.from_h(context, h)
@@ -336,6 +371,16 @@ module Ruote::Exp
336
371
  #
337
372
  def do_apply(msg)
338
373
 
374
+ if msg['state'] == 'paused'
375
+
376
+ return pause_on_apply(msg)
377
+ end
378
+
379
+ if msg['flavour'].nil? && (aw = attribute(:await))
380
+
381
+ return await(aw, msg)
382
+ end
383
+
339
384
  unless Condition.apply?(attribute(:if), attribute(:unless))
340
385
 
341
386
  return do_reply_to_parent(h.applied_workitem)
@@ -385,6 +430,52 @@ module Ruote::Exp
385
430
  apply
386
431
  end
387
432
 
433
+ # Called by #do_apply when msg['state'] == 'paused'. Covers the
434
+ # "apply/launch it but it's immediately paused" case. Freezes the
435
+ # apply message in h.paused_apply and saves the expression.
436
+ #
437
+ def pause_on_apply(msg)
438
+
439
+ msg['state'] = nil
440
+
441
+ h.state = 'paused'
442
+ h.paused_apply = msg
443
+
444
+ persist_or_raise
445
+ end
446
+
447
+ # If the expression has an :await attribute, the expression gets
448
+ # into a special "awaiting" state until the condition in the value
449
+ # of :await gets triggered and the trigger calls resume on the
450
+ # expression.
451
+ #
452
+ def await(att, msg)
453
+
454
+ action, condition =
455
+ Ruote::Exp::AwaitExpression.extract_await_ac(:await => att)
456
+
457
+ raise ::ArgumentError.new(
458
+ ":await does not understand #{att.inspect}"
459
+ ) if action == nil
460
+
461
+ msg.merge!('flavour' => 'awaiting')
462
+
463
+ h.state = 'awaiting'
464
+ h.paused_apply = msg
465
+
466
+ persist_or_raise
467
+
468
+ @context.tracker.add_tracker(
469
+ h.fei['wfid'],
470
+ action,
471
+ Ruote.to_storage_id(h.fei),
472
+ condition,
473
+ { '_auto_remove' => true,
474
+ 'action' => 'resume',
475
+ 'fei' => h.fei,
476
+ 'flavour' => 'awaiting' })
477
+ end
478
+
388
479
  # FlowExpression call this method when they're done and they want their
389
480
  # parent expression to take over (it will end up calling the #reply of
390
481
  # the parent expression).
@@ -456,7 +547,13 @@ module Ruote::Exp
456
547
 
457
548
  trigger('on_reply', workitem)
458
549
 
459
- elsif (h.lost || h.flanking) && h.state.nil?
550
+ elsif h.flanking && h.state.nil?
551
+ #
552
+ # do vanish
553
+
554
+ do_unpersist
555
+
556
+ elsif h.lost && h.state.nil?
460
557
  #
461
558
  # do not reply, sit here (and wait for cancellation probably)
462
559
 
@@ -483,7 +580,7 @@ module Ruote::Exp
483
580
  (do_unpersist || return) if delete
484
581
  # remove expression from storage
485
582
 
486
- if h.parent_id
583
+ if h.parent_id && ! h.attached
487
584
 
488
585
  @context.storage.put_msg(
489
586
  'reply',
@@ -495,15 +592,18 @@ module Ruote::Exp
495
592
  else
496
593
 
497
594
  @context.storage.put_msg(
498
- h.forgotten ? 'ceased' : 'terminated',
595
+ (h.forgotten || h.attached) ? 'ceased' : 'terminated',
499
596
  'wfid' => h.fei['wfid'],
500
597
  'fei' => h.fei,
501
598
  'workitem' => workitem,
502
599
  'variables' => h.variables,
503
600
  'flavour' => flavour)
504
601
 
505
- if h.state.nil? && h.on_terminate == 'regenerate' && ! h.forgotten
506
-
602
+ if
603
+ h.state.nil? &&
604
+ h.on_terminate == 'regenerate' &&
605
+ ! (h.forgotten || h.attached)
606
+ then
507
607
  @context.storage.put_msg(
508
608
  'regenerate',
509
609
  'wfid' => h.fei['wfid'],
@@ -717,9 +817,14 @@ module Ruote::Exp
717
817
  #
718
818
  def do_resume(msg)
719
819
 
720
- return if h.state != 'paused'
820
+ return unless h.state == 'paused' || h.state == 'awaiting'
721
821
 
722
822
  h['state'] = nil
823
+
824
+ m = h.delete('paused_apply')
825
+ return do_apply(m) if m
826
+ # if it's a paused apply, pipe it directly to #do_apply
827
+
723
828
  replies = h.delete('paused_replies') || []
724
829
 
725
830
  do_persist || return
@@ -744,6 +849,10 @@ module Ruote::Exp
744
849
  'subid' => Ruote.generate_subid(h.fei.inspect),
745
850
  'expid' => pos)
746
851
 
852
+ if ci = opts[:child_id]
853
+ i['subid'] = "#{i['subid']}k#{ci}"
854
+ end
855
+
747
856
  #p '=== launch_sub ==='
748
857
  #p [ :launcher, h.fei['expid'], h.fei['subid'], h.fei['wfid'] ]
749
858
  #p [ :launched, i['expid'], i['subid'], i['wfid'] ]
@@ -916,7 +1025,7 @@ module Ruote::Exp
916
1025
 
917
1026
  tag = attribute(:tag)
918
1027
 
919
- return unless tag
1028
+ return unless tag && tag.strip.size > 0
920
1029
 
921
1030
  h.tagname = tag
922
1031
  h.full_tagname = applied_workitem.tags.join('/')
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -205,7 +205,9 @@ module Ruote::Exp
205
205
  def schedule_retries(handler, err)
206
206
 
207
207
  retries = handler.split(/\s*,\s*/)
208
+
208
209
  after, action = retries.shift.split(/:/)
210
+ (after, action = '0', after) if action.nil?
209
211
 
210
212
  # deal with "* 3"
211
213
 
@@ -299,7 +301,7 @@ module Ruote::Exp
299
301
  workitem = h.supplanted['applied_workitem']
300
302
  end
301
303
 
302
- if on == 'on_error' && handler.respond_to?(:match) && handler.match(/:/)
304
+ if on == 'on_error' && handler.respond_to?(:match) && handler.match(/[,:\*]/)
303
305
  return schedule_retries(handler, err)
304
306
  end
305
307
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,125 @@
1
+ #--
2
+ # Copyright (c) 2005-2013, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ #--
27
+ #
28
+ # Various Ruote.xxx methods.
29
+ #
30
+ #++
31
+ module Ruote
32
+
33
+ # A shortcut for
34
+ #
35
+ # Ruote::FlowExpressionId.to_storage_id(fei)
36
+ #
37
+ def self.to_storage_id(fei)
38
+
39
+ Ruote::FlowExpressionId.to_storage_id(fei)
40
+ end
41
+
42
+ # A shorter shortcut for
43
+ #
44
+ # Ruote::FlowExpressionId.to_storage_id(fei)
45
+ #
46
+ def self.sid(fei)
47
+
48
+ Ruote::FlowExpressionId.to_storage_id(fei)
49
+ end
50
+
51
+ SUBS = %w[ subid sub_wfid ]
52
+ IDS = %w[ engine_id expid wfid ]
53
+
54
+ # Returns true if the h is a representation of a FlowExpressionId instance.
55
+ #
56
+ def self.is_a_fei?(o)
57
+
58
+ return true if o.is_a?(Ruote::FlowExpressionId)
59
+ return false unless o.is_a?(Hash)
60
+
61
+ (o.keys - SUBS).sort == IDS
62
+ end
63
+
64
+ # Will do its best to return a wfid (String) or a fei (Hash instance)
65
+ # extract from the given o argument.
66
+ #
67
+ def self.extract_id(o)
68
+
69
+ return o if o.is_a?(String) and o.index('!').nil? # wfid
70
+
71
+ Ruote::FlowExpressionId.extract_h(o)
72
+ end
73
+
74
+ # Given something, tries to return the fei (Ruote::FlowExpressionId) in it.
75
+ #
76
+ def self.extract_fei(o)
77
+
78
+ Ruote::FlowExpressionId.extract(o)
79
+ end
80
+
81
+ # Given something that might be a fei, extract the child_id (the last
82
+ # portion of the expid in the fei).
83
+ #
84
+ def self.extract_child_id(o)
85
+
86
+ fei = Ruote::FlowExpressionId.extract(o)
87
+
88
+ fei ? fei.child_id : nil
89
+ end
90
+
91
+ # Given an object, will return the wfid (workflow instance id) nested into
92
+ # it (or nil if it can't find or doesn't know how to find).
93
+ #
94
+ # The wfid is a String instance.
95
+ #
96
+ def self.extract_wfid(o)
97
+
98
+ return o.strip == '' ? nil : o if o.is_a?(String)
99
+ return o.wfid if o.respond_to?(:wfid)
100
+ return o['wfid'] || o.fetch('fei', {})['wfid'] if o.respond_to?(:[])
101
+ nil
102
+ end
103
+
104
+ # Given a context and a fei (FlowExpressionId or Hash) or a flow expression
105
+ # (Ruote::Exp::FlowExpression or Hash) return the desired
106
+ # Ruote::Exp::FlowExpression instance.
107
+ #
108
+ def self.extract_fexp(context, fei_or_fexp)
109
+
110
+ return fei_or_fexp if fei_or_fexp.is_a?(Ruote::Exp::FlowExpression)
111
+
112
+ fei = case fei_or_fexp
113
+ when Ruote::FlowExpressionId then fei_or_fexp
114
+ when Hash, String then extract_fei(fei_or_fexp)
115
+ else nil
116
+ end
117
+
118
+ raise ArgumentError.new(
119
+ "failed to extract flow expression out of #{fei_or_fexp.class} instance"
120
+ ) unless fei
121
+
122
+ Ruote::Exp::FlowExpression.fetch(context, fei)
123
+ end
124
+ end
125
+