ruote 2.3.0.1 → 2.3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -140,9 +140,9 @@ module Ruote
140
140
 
141
141
  return nil if @expressions.empty?
142
142
 
143
- @expressions.each_with_object({}) do |exp, h|
143
+ @expressions.each_with_object({}) { |exp, h|
144
144
  h[exp.fei] = exp.variables if exp.variables
145
- end
145
+ }
146
146
  end
147
147
 
148
148
  # Returns a hash tagname => fei of tags set at the root of the process
@@ -152,11 +152,7 @@ module Ruote
152
152
  #
153
153
  def tags
154
154
 
155
- if variables
156
- Hash[variables.select { |k, v| FlowExpressionId.is_a_fei?(v) }]
157
- else
158
- nil
159
- end
155
+ variables ? Hash[variables.select { |k, v| Ruote.is_a_fei?(v) }] : nil
160
156
  end
161
157
 
162
158
  # Returns a hash tagname => array of feis of all the tags set in the process
@@ -165,7 +161,7 @@ module Ruote
165
161
  def all_tags
166
162
 
167
163
  all_variables.remap do |(fei, vars), h|
168
- vars.each { |k, v| (h[k] ||= []) << v if FlowExpressionId.is_a_fei?(v) }
164
+ vars.each { |k, v| (h[k] ||= []) << v if Ruote.is_a_fei?(v) }
169
165
  end
170
166
  end
171
167
 
@@ -380,6 +376,7 @@ module Ruote
380
376
  vars = variables rescue nil
381
377
  avars = (all_variables || {}).remap { |(k, v), h| h[Ruote.sid(k)] = v }
382
378
 
379
+
383
380
  s = [ "== #{self.class} ==" ]
384
381
  s << ''
385
382
  s << " wfid: #{wfid}"
@@ -388,9 +385,15 @@ module Ruote
388
385
  s << " last_active: #{last_active}"
389
386
  s << " launched_time: #{launched_time}"
390
387
  s << ''
388
+
391
389
  s << " expressions: #{@expressions.size}"
392
390
  s << ''
393
391
  @expressions.each do |e|
392
+
393
+ eflags = %w[
394
+ flanking forgotten attached
395
+ ].each_with_object([]) { |f, a| a << f if e.h[f] }
396
+
394
397
  s << " #{e.fei.to_storage_id}"
395
398
  s << " | #{e.name}"
396
399
  s << " | _rev: #{e.h._rev.inspect}"
@@ -400,9 +403,11 @@ module Ruote
400
403
  s << " | . child-> #{Ruote.sid(ce)}"
401
404
  end if e.children.any?
402
405
  s << " | timers: #{e.h.timers.collect { |t| t[1] }}" if e.h.timers
403
- s << " | (flanking)" if e.h.flanking
406
+ s << " | tagname: #{e.h.tagname}" if e.h.tagname
407
+ s << " | (#{eflags.join(', ')})" if eflags.any?
404
408
  s << " `-parent--> #{e.h.parent_id ? e.parent_id.to_storage_id : 'nil'}"
405
409
  end
410
+
406
411
  s << ''
407
412
  s << " schedules: #{@schedules.size}"
408
413
  if @schedules.size > 0
@@ -414,6 +419,7 @@ module Ruote
414
419
  end
415
420
  s << ''
416
421
  end
422
+
417
423
  s << " stored workitems: #{@stored_workitems.size}"
418
424
 
419
425
  s << ''
@@ -494,32 +500,45 @@ module Ruote
494
500
  # Returns nil if there are no expressions (happens in the case of an
495
501
  # orphan workitem)
496
502
  #
497
- def current_tree
498
-
499
- return nil if @expressions.empty?
500
-
501
- h = Ruote.decompose_tree(original_tree)
502
-
503
- @expressions.sort { |e0, e1|
504
-
505
- e0.fei.expid <=> e1.fei.expid
506
-
507
- }.each { |e|
508
-
509
- trigger = e.tree[1]['_triggered']
510
-
511
- tree = if trigger && trigger != 'on_re_apply'
512
- t = original_tree_from_parent(e).dup
513
- t[1]['_triggered'] = trigger
514
- t
515
- else
516
- e.tree
517
- end
518
-
519
- h.merge!(Ruote.decompose_tree(tree, e.fei.expid))
520
- }
503
+ def current_tree(fexp=root_expression)
504
+
505
+ return nil unless fexp
506
+
507
+ t = Ruote.fulldup(fexp.tree)
508
+
509
+ fexp.children.each do |cfei|
510
+
511
+ cexp = fexp(cfei)
512
+ next unless cexp
513
+
514
+ ct = current_tree(cexp)
515
+
516
+ #trigger = ct[1]['_triggered']
517
+ #if trigger && trigger != 'on_re_apply'
518
+ # #
519
+ # # ignore any on_cancel / on_error / ...
520
+ # #
521
+ # #ct = t[2][cexp.child_id]
522
+ # # loses any change in the re_applied tree
523
+ # #
524
+ # # just flag the original tree as _triggered
525
+ # # loses any change in the re_applied tree
526
+ # #
527
+ # #ct = t[2][cexp.child_id]
528
+ # #ct[1]['_triggered'] = trigger
529
+ # #
530
+ # # extracts the new tree, discards the layers around it
531
+ # #
532
+ # ot = t[2][cexp.child_id]
533
+ # ct = ct[2][0][2][0]
534
+ # ct[1]['_triggered'] = [ trigger, ot[1][trigger] ].join('/')
535
+ #end
536
+ # return the real current tree, do not tweak with it!
537
+
538
+ t[2][cexp.child_id] = ct
539
+ end
521
540
 
522
- Ruote.recompose_tree(h)
541
+ t
523
542
  end
524
543
 
525
544
  # Used by Ruote::Dashboard#process and #processes
@@ -566,21 +585,15 @@ module Ruote
566
585
  }.compact
567
586
  end
568
587
 
569
- #--
570
- #def self.from_h(h)
571
- # self.new(
572
- # nil,
573
- # *%w[ expressions workitems errors schedules trackers ].map { |k| h[k] })
574
- #end
575
- #++
576
-
577
- protected
578
-
579
- def original_tree_from_parent(e)
588
+ # Given a fei, returns the flow expression with that fei (only looks
589
+ # in the expressions stored here, in this ProcessStatus instance, doesn't
590
+ # query the storage).
591
+ #
592
+ def fexp(fei)
580
593
 
581
- parent = @expressions.find { |exp| exp.fei == e.parent_id }
594
+ fei = Ruote.extract_fei(fei)
582
595
 
583
- parent ? parent.tree[2][e.fei.child_id] : e.tree
596
+ @expressions.find { |e| e.fei == fei }
584
597
  end
585
598
  end
586
599
  end
data/lib/ruote/engine.rb CHANGED
@@ -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
@@ -37,6 +37,7 @@ module Ruote::Exp
37
37
  class ConditionError < RuntimeError
38
38
 
39
39
  def initialize(code)
40
+
40
41
  super(
41
42
  "couldn't interpret >#{code}<, " +
42
43
  "if it comes from a ${xx} construct, please use ${\"xx} or ${'yy}")
@@ -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
@@ -212,49 +212,59 @@ module Ruote::Exp
212
212
  # Note: the :where guard is always about the event's workitem (not the
213
213
  # workitem as it reached the 'await' expression).
214
214
  #
215
+ #
216
+ # == note: the "await" attribute
217
+ #
218
+ # (since ruote 3.2.1)
219
+ #
220
+ # "listen" and "await" are both ruote expressions. There is also an
221
+ # attribute common to all the expressions: :await.
222
+ #
223
+ # concurrence do
224
+ # sequence do
225
+ # alice
226
+ # sequence :tag => 'stage2' do
227
+ # bob
228
+ # end
229
+ # end
230
+ # sequence do
231
+ # charly
232
+ # diana :await => 'left_tag:stage2'
233
+ # eliza
234
+ # end
235
+ # frank
236
+ # end
237
+ #
238
+ # The expressions with an await attribute suspends its application until
239
+ # the awaited event happens.
240
+ #
241
+ # This await attribute, defaults to "left_tag:", so
242
+ #
243
+ # diana :await => 'stage2'
244
+ # # is equivalent to
245
+ # diana :await => 'left_tag:stage2'
246
+ #
215
247
  class AwaitExpression < FlowExpression
216
248
 
217
249
  names :await
218
250
 
219
- INS = %w[ in entered reached]
220
- OUTS = %w[ out left ]
221
-
222
- SPLIT_R = /^(#{(INS + OUTS).join('|')})_(tag|participant)s?$/
223
- SINGLE_R = /^(tag)s|(participant|error)s?$/ # not 'tag' alone
224
-
225
251
  def apply
226
252
 
227
253
  #
228
254
  # gathering info
229
255
 
230
- direction, type, value = attributes.collect { |k, v|
231
- if m = SPLIT_R.match(k)
232
- [ m[1], m[2], v ]
233
- elsif m = SINGLE_R.match(k)
234
- [ 'in', m[1] || m[2], v ]
235
- else
236
- nil
237
- end
238
- }.compact.first
256
+ action, condition = self.class.extract_await_ac(attributes)
239
257
 
240
258
  raise ArgumentError.new(
241
259
  "couldn't determine which event to listen to from: " +
242
260
  attributes.inspect
243
- ) unless direction
261
+ ) unless action
244
262
 
245
263
  global = (attribute(:global).to_s == 'true')
246
- global = false if type == 'error'
264
+ global = false if action == 'error_intercepted'
247
265
 
248
266
  h.amerge = attribute(:merge).to_s
249
267
 
250
- action = if type == 'tag'
251
- INS.include?(direction) ? 'entered_tag' : 'left_tag'
252
- elsif type == 'participant'
253
- INS.include?(direction) ? 'dispatch' : 'receive'
254
- else # error
255
- 'error_intercepted'
256
- end
257
-
258
268
  persist_or_raise
259
269
 
260
270
  #
@@ -264,7 +274,7 @@ module Ruote::Exp
264
274
  global ? nil : h.fei['wfid'],
265
275
  action,
266
276
  Ruote.to_storage_id(h.fei),
267
- determine_condition(type, value),
277
+ condition,
268
278
  { 'action' => 'reply',
269
279
  'fei' => h.fei,
270
280
  'workitem' => 'replace',
@@ -284,12 +294,13 @@ module Ruote::Exp
284
294
 
285
295
  wi = h.applied_workitem.dup
286
296
 
287
- wi['fields'] = case h.amerge
288
- when 'ignore', 'drop' then wi['fields']
289
- when 'incoming' then wi['fields'].merge(workitem['fields'])
290
- when 'awaiting' then workitem['fields'].merge(wi['fields'])
291
- else workitem['fields'] # 'override'
292
- end
297
+ wi['fields'] =
298
+ case h.amerge
299
+ when 'ignore', 'drop' then wi['fields']
300
+ when 'incoming' then wi['fields'].merge(workitem['fields'])
301
+ when 'awaiting' then workitem['fields'].merge(wi['fields'])
302
+ else workitem['fields'] # 'override'
303
+ end
293
304
 
294
305
  #
295
306
  # actual trigger
@@ -323,34 +334,72 @@ module Ruote::Exp
323
334
  super(workitem)
324
335
  end
325
336
 
326
- # Matches Ruby class names, like "Ruote::ForcedError" or "::ArgumentError"
327
- #
328
- KLASS_R = /^(::)?([A-Z][a-z]+)+(::([A-Z][a-z]+)+)*$/
337
+ INS = %w[ in entered reached ]
338
+ OUTS = %w[ out left ]
339
+
340
+ SPLIT_R =
341
+ /^(?:(#{(INS + OUTS).join('|')})_)?(tag|participant|error)s?$/
342
+
343
+ # attribute wait regex
344
+ AAWAIT_R =
345
+ /^(?:(#{(INS + OUTS).join('|')})_)?(tag|participant)s?\s*:\s*(.+)$/
346
+
347
+ # matches Ruby class names, like "Ruote::ForcedError" or "::ArgumentError"
348
+ KLASS_R =
349
+ /^(::)?([A-Z][a-z]+)+(::([A-Z][a-z]+)+)*$/
329
350
 
330
- # Builds the condition used by the tracker service to filter msgs.
351
+ # Made into a class method, so that the :await common attribute can
352
+ # use it when parsing :await...
331
353
  #
332
- def determine_condition(type, value)
354
+ def self.extract_await_ac(atts)
355
+
356
+ direction, type, value =
357
+ atts.collect { |k, v|
358
+ if k == :await && m = AAWAIT_R.match(v)
359
+ [ m[1] || 'in', m[2], m[3] ]
360
+ elsif k == :await && v.index(':').nil?
361
+ [ 'left', 'tag', v ]
362
+ elsif m = SPLIT_R.match(k)
363
+ [ m[1] || 'in', m[2], v ]
364
+ else
365
+ nil
366
+ end
367
+ }.compact.first
368
+
369
+ return nil if direction == nil
370
+
371
+ action =
372
+ if type == 'tag'
373
+ INS.include?(direction) ? 'entered_tag' : 'left_tag'
374
+ elsif type == 'participant'
375
+ INS.include?(direction) ? 'dispatch' : 'receive'
376
+ else # error
377
+ 'error_intercepted'
378
+ end
333
379
 
334
380
  value = Ruote.comma_split(value)
335
381
 
336
- if type == 'participant'
382
+ condition =
383
+ if type == 'participant'
337
384
 
338
- { 'participant_name' => value }
385
+ { 'participant_name' => value }
339
386
 
340
- elsif type == 'error'
387
+ elsif type == 'error'
341
388
 
342
- # array or comma string or string ?
389
+ # array or comma string or string ?
343
390
 
344
- h = { 'class' => [], 'message' => [] }
391
+ h = { 'class' => [], 'message' => [] }
345
392
 
346
- value.each { |e| (KLASS_R.match(e) ? h['class'] : h['message']) << e }
393
+ value.each { |e| (KLASS_R.match(e) ? h['class'] : h['message']) << e }
347
394
 
348
- h.delete_if { |k, v| v == nil or v == [] }
395
+ h.delete_if { |k, v| v == nil or v == [] }
349
396
 
350
- else # 'tag'
397
+ else # 'tag'
351
398
 
352
- { (value.first.to_s.match(/\//) ? 'full_tag' : 'tag') => value }
353
- end
399
+ { (value.first.to_s.match(/\//) ? 'full_tag' : 'tag') => value }
400
+ end
401
+
402
+ [ action, condition ]
354
403
  end
355
404
  end
356
405
  end