ruote 2.1.11 → 2.2.0

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 (217) hide show
  1. data/CHANGELOG.txt +60 -0
  2. data/CREDITS.txt +22 -4
  3. data/LICENSE.txt +1 -1
  4. data/README.rdoc +6 -7
  5. data/Rakefile +58 -59
  6. data/TODO.txt +137 -65
  7. data/couch_url.txt +1 -0
  8. data/jruby_issue.txt +32 -0
  9. data/lib/ruote.rb +1 -1
  10. data/lib/ruote/context.rb +12 -10
  11. data/lib/ruote/engine.rb +280 -145
  12. data/lib/ruote/engine/process_error.rb +5 -5
  13. data/lib/ruote/engine/process_status.rb +47 -28
  14. data/lib/ruote/exp/command.rb +7 -10
  15. data/lib/ruote/exp/commanded.rb +2 -2
  16. data/lib/ruote/exp/condition.rb +130 -43
  17. data/lib/ruote/exp/fe_add_branches.rb +2 -2
  18. data/lib/ruote/exp/fe_apply.rb +1 -1
  19. data/lib/ruote/exp/fe_cancel_process.rb +3 -3
  20. data/lib/ruote/exp/fe_command.rb +3 -3
  21. data/lib/ruote/exp/fe_concurrence.rb +4 -4
  22. data/lib/ruote/exp/fe_concurrent_iterator.rb +17 -5
  23. data/lib/ruote/exp/fe_cron.rb +3 -3
  24. data/lib/ruote/exp/fe_cursor.rb +5 -5
  25. data/lib/ruote/exp/fe_define.rb +3 -3
  26. data/lib/ruote/exp/fe_echo.rb +3 -3
  27. data/lib/ruote/exp/fe_equals.rb +2 -2
  28. data/lib/ruote/exp/fe_error.rb +2 -2
  29. data/lib/ruote/exp/fe_filter.rb +519 -0
  30. data/lib/ruote/exp/fe_forget.rb +9 -2
  31. data/lib/ruote/exp/fe_given.rb +154 -0
  32. data/lib/ruote/exp/fe_if.rb +16 -13
  33. data/lib/ruote/exp/fe_inc.rb +3 -3
  34. data/lib/ruote/exp/fe_iterator.rb +4 -4
  35. data/lib/ruote/exp/fe_let.rb +75 -0
  36. data/lib/ruote/exp/fe_listen.rb +68 -12
  37. data/lib/ruote/exp/fe_lose.rb +110 -0
  38. data/lib/ruote/exp/fe_noop.rb +1 -1
  39. data/lib/ruote/exp/{fe_when.rb → fe_once.rb} +25 -21
  40. data/lib/ruote/exp/fe_participant.rb +14 -17
  41. data/lib/ruote/exp/fe_redo.rb +10 -6
  42. data/lib/ruote/exp/fe_ref.rb +1 -1
  43. data/lib/ruote/exp/fe_registerp.rb +112 -0
  44. data/lib/ruote/exp/fe_reserve.rb +3 -3
  45. data/lib/ruote/exp/fe_restore.rb +2 -2
  46. data/lib/ruote/exp/fe_save.rb +2 -2
  47. data/lib/ruote/exp/fe_sequence.rb +3 -4
  48. data/lib/ruote/exp/fe_set.rb +16 -7
  49. data/lib/ruote/exp/fe_subprocess.rb +23 -1
  50. data/lib/ruote/exp/fe_that.rb +92 -0
  51. data/lib/ruote/exp/fe_undo.rb +3 -3
  52. data/lib/ruote/exp/fe_unregisterp.rb +71 -0
  53. data/lib/ruote/exp/fe_wait.rb +2 -2
  54. data/lib/ruote/exp/flowexpression.rb +153 -78
  55. data/lib/ruote/exp/iterator.rb +2 -2
  56. data/lib/ruote/exp/merge.rb +2 -2
  57. data/lib/ruote/exp/ro_attributes.rb +14 -12
  58. data/lib/ruote/exp/ro_filters.rb +136 -0
  59. data/lib/ruote/exp/ro_persist.rb +51 -35
  60. data/lib/ruote/exp/ro_variables.rb +18 -27
  61. data/lib/ruote/fei.rb +73 -33
  62. data/lib/ruote/id/mnemo_wfid_generator.rb +1 -1
  63. data/lib/ruote/id/wfid_generator.rb +11 -4
  64. data/lib/ruote/log/default_history.rb +122 -0
  65. data/lib/ruote/log/pretty.rb +36 -8
  66. data/lib/ruote/log/storage_history.rb +37 -5
  67. data/lib/ruote/log/test_logger.rb +26 -24
  68. data/lib/ruote/log/wait_logger.rb +5 -3
  69. data/lib/ruote/part/block_participant.rb +22 -11
  70. data/lib/ruote/part/engine_participant.rb +6 -7
  71. data/lib/ruote/part/local_participant.rb +6 -12
  72. data/lib/ruote/part/no_op_participant.rb +4 -4
  73. data/lib/ruote/part/null_participant.rb +4 -4
  74. data/lib/ruote/part/smtp_participant.rb +4 -4
  75. data/lib/ruote/part/storage_participant.rb +40 -20
  76. data/lib/ruote/part/template.rb +4 -4
  77. data/lib/ruote/participant.rb +0 -1
  78. data/lib/ruote/{parser.rb → reader.rb} +30 -25
  79. data/lib/ruote/{parser → reader}/ruby_dsl.rb +28 -11
  80. data/lib/ruote/{parser → reader}/xml.rb +6 -5
  81. data/lib/ruote/receiver/base.rb +35 -13
  82. data/lib/ruote/storage/base.rb +20 -18
  83. data/lib/ruote/storage/composite_storage.rb +10 -10
  84. data/lib/ruote/storage/fs_storage.rb +17 -10
  85. data/lib/ruote/storage/hash_storage.rb +29 -18
  86. data/lib/ruote/svc/dispatch_pool.rb +41 -14
  87. data/lib/ruote/svc/dollar_sub.rb +50 -17
  88. data/lib/ruote/svc/error_handler.rb +19 -11
  89. data/lib/ruote/svc/expression_map.rb +4 -4
  90. data/lib/ruote/svc/participant_list.rb +105 -100
  91. data/lib/ruote/svc/tracker.rb +58 -18
  92. data/lib/ruote/svc/treechecker.rb +51 -24
  93. data/lib/ruote/tree_dot.rb +4 -4
  94. data/lib/ruote/util/filter.rb +440 -0
  95. data/lib/ruote/util/hashdot.rb +4 -4
  96. data/lib/ruote/util/look.rb +2 -6
  97. data/lib/ruote/util/lookup.rb +9 -7
  98. data/lib/ruote/util/misc.rb +40 -8
  99. data/lib/ruote/util/ometa.rb +1 -1
  100. data/lib/ruote/util/serializer.rb +4 -4
  101. data/lib/ruote/util/subprocess.rb +29 -9
  102. data/lib/ruote/util/time.rb +4 -4
  103. data/lib/ruote/util/tree.rb +3 -3
  104. data/lib/ruote/version.rb +2 -2
  105. data/lib/ruote/worker.rb +55 -32
  106. data/lib/ruote/workitem.rb +64 -11
  107. data/ruote.gemspec +31 -302
  108. data/test/bm/launch_bench.rb +37 -0
  109. data/test/functional/base.rb +60 -18
  110. data/test/functional/concurrent_base.rb +2 -2
  111. data/test/functional/ct_0_concurrence.rb +1 -1
  112. data/test/functional/ct_1_iterator.rb +1 -1
  113. data/test/functional/ct_2_cancel.rb +1 -1
  114. data/test/functional/eft_0_process_definition.rb +2 -2
  115. data/test/functional/eft_10_cancel_process.rb +1 -1
  116. data/test/functional/eft_11_wait.rb +19 -11
  117. data/test/functional/eft_12_listen.rb +79 -13
  118. data/test/functional/eft_13_iterator.rb +13 -10
  119. data/test/functional/eft_14_cursor.rb +98 -9
  120. data/test/functional/eft_15_loop.rb +6 -4
  121. data/test/functional/eft_16_if.rb +12 -0
  122. data/test/functional/eft_18_concurrent_iterator.rb +31 -32
  123. data/test/functional/eft_19_reserve.rb +4 -4
  124. data/test/functional/eft_1_echo.rb +9 -0
  125. data/test/functional/eft_20_save.rb +4 -4
  126. data/test/functional/{eft_28_when.rb → eft_28_once.rb} +33 -7
  127. data/test/functional/eft_30_ref.rb +17 -2
  128. data/test/functional/eft_31_registerp.rb +130 -0
  129. data/test/functional/eft_32_lose.rb +93 -0
  130. data/test/functional/eft_33_let.rb +31 -0
  131. data/test/functional/eft_34_given.rb +123 -0
  132. data/test/functional/eft_35_filter.rb +269 -0
  133. data/test/functional/eft_3_participant.rb +4 -6
  134. data/test/functional/eft_4_set.rb +16 -2
  135. data/test/functional/eft_5_subprocess.rb +2 -4
  136. data/test/functional/eft_6_concurrence.rb +29 -29
  137. data/test/functional/eft_8_undo.rb +39 -3
  138. data/test/functional/eft_9_redo.rb +94 -2
  139. data/test/functional/ft_10_dollar.rb +81 -2
  140. data/test/functional/ft_11_recursion.rb +13 -17
  141. data/test/functional/ft_12_launchitem.rb +9 -5
  142. data/test/functional/ft_13_variables.rb +7 -9
  143. data/test/functional/ft_14_re_apply.rb +6 -9
  144. data/test/functional/ft_15_timeout.rb +18 -18
  145. data/test/functional/ft_16_participant_params.rb +1 -3
  146. data/test/functional/ft_17_conditional.rb +25 -2
  147. data/test/functional/ft_18_kill.rb +65 -12
  148. data/test/functional/ft_1_process_status.rb +147 -71
  149. data/test/functional/ft_20_storage_participant.rb +0 -1
  150. data/test/functional/ft_21_forget.rb +82 -1
  151. data/test/functional/{ft_24_block_participants.rb → ft_24_block_participant.rb} +42 -11
  152. data/test/functional/ft_25_receiver.rb +47 -17
  153. data/test/functional/{ft_26_participant_timeout.rb → ft_26_participant_rtimeout.rb} +56 -19
  154. data/test/functional/ft_29_part_template.rb +6 -5
  155. data/test/functional/ft_2_errors.rb +21 -37
  156. data/test/functional/ft_30_smtp_participant.rb +1 -1
  157. data/test/functional/ft_31_part_blocking.rb +8 -6
  158. data/test/functional/ft_34_cursor_rewind.rb +13 -10
  159. data/test/functional/ft_35_add_service.rb +1 -1
  160. data/test/functional/ft_36_storage_history.rb +24 -1
  161. data/test/functional/ft_37_default_history.rb +109 -0
  162. data/test/functional/ft_38_participant_more.rb +10 -10
  163. data/test/functional/ft_39_wait_for.rb +12 -9
  164. data/test/functional/ft_3_participant_registration.rb +111 -32
  165. data/test/functional/ft_40_wait_logger.rb +2 -1
  166. data/test/functional/ft_41_participants.rb +30 -4
  167. data/test/functional/ft_43_participant_on_reply.rb +6 -23
  168. data/test/functional/ft_45_participant_accept.rb +4 -4
  169. data/test/functional/ft_46_launch_single.rb +36 -2
  170. data/test/functional/ft_47_wfid_generator.rb +54 -0
  171. data/test/functional/ft_48_lose.rb +112 -0
  172. data/test/functional/ft_49_engine_on_error.rb +201 -0
  173. data/test/functional/ft_4_cancel.rb +66 -6
  174. data/test/functional/ft_50_engine_config.rb +22 -0
  175. data/test/functional/ft_51_misc.rb +67 -0
  176. data/test/functional/ft_52_case.rb +134 -0
  177. data/test/functional/ft_53_engine_on_terminate.rb +95 -0
  178. data/test/functional/ft_54_patterns.rb +104 -0
  179. data/test/functional/{ft_37_engine_participant.rb → ft_55_engine_participant.rb} +4 -5
  180. data/test/functional/ft_56_filter_attribute.rb +259 -0
  181. data/test/functional/ft_5_on_error.rb +77 -30
  182. data/test/functional/ft_6_on_cancel.rb +66 -11
  183. data/test/functional/ft_7_tags.rb +94 -5
  184. data/test/functional/ft_8_participant_consumption.rb +36 -5
  185. data/test/functional/ft_9_subprocesses.rb +10 -10
  186. data/test/functional/rt_1_listen.rb +3 -3
  187. data/test/functional/{rt_3_when.rb → rt_3_once.rb} +4 -4
  188. data/test/functional/storage_helper.rb +15 -13
  189. data/test/functional/test.rb +1 -3
  190. data/test/test_helper.rb +0 -8
  191. data/test/unit/storage.rb +154 -10
  192. data/test/unit/{ut_0_ruby_parser.rb → ut_0_ruby_reader.rb} +61 -11
  193. data/test/unit/ut_11_lookup.rb +7 -0
  194. data/test/unit/ut_13_serializer.rb +1 -1
  195. data/test/unit/ut_15_util.rb +23 -0
  196. data/test/unit/{ut_16_parser.rb → ut_16_reader.rb} +11 -13
  197. data/test/unit/ut_1_fei.rb +57 -10
  198. data/test/unit/ut_20_composite_storage.rb +25 -11
  199. data/test/unit/ut_21_participant_list.rb +47 -0
  200. data/test/unit/ut_22_filter.rb +903 -0
  201. data/test/unit/ut_3_wait_logger.rb +2 -6
  202. data/test/unit/ut_6_condition.rb +164 -17
  203. data/test/unit/ut_7_workitem.rb +28 -0
  204. data/test/unit/ut_8_tree_to_dot.rb +1 -1
  205. data/test/unit/{ut_9_xml_parser.rb → ut_9_xml_reader.rb} +5 -5
  206. metadata +108 -84
  207. data/.gitignore +0 -4
  208. data/examples/barley.rb +0 -391
  209. data/examples/flickr_report.rb +0 -107
  210. data/examples/pong.rb +0 -37
  211. data/examples/ruote_quickstart.rb +0 -43
  212. data/examples/web_first_page.rb +0 -68
  213. data/lib/ruote/part/hash_participant.rb +0 -91
  214. data/test/README.rdoc +0 -15
  215. data/test/functional/crunner.sh +0 -19
  216. data/test/pdef.xml +0 -7
  217. data/test/unit/ut_2_wfidgen.rb +0 -21
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -59,6 +59,13 @@ module Ruote::Exp
59
59
  #
60
60
  # This expression can be useful for fire-and-forget parallelism in processes.
61
61
  #
62
+ # == forget vs lose
63
+ #
64
+ # forget : replies to parent expression immediately, is not cancellable
65
+ # (not reachable).
66
+ #
67
+ # lose : never replies to parent expression, is cancellable.
68
+ #
62
69
  class ForgetExpression < FlowExpression
63
70
 
64
71
  names :forget
@@ -72,7 +79,7 @@ module Ruote::Exp
72
79
  reply_to_parent(h.applied_workitem)
73
80
  end
74
81
 
75
- def reply (workitem)
82
+ def reply(workitem)
76
83
 
77
84
  # never gets called
78
85
  end
@@ -0,0 +1,154 @@
1
+ #--
2
+ # Copyright (c) 2005-2011, 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
+ require 'ruote/exp/fe_sequence'
26
+
27
+
28
+ module Ruote::Exp
29
+
30
+ #
31
+ # This expressions corresponds to a "case" statement in Ruby or a "switch"
32
+ # in other languages.
33
+ #
34
+ # It accepts two variants "given that" and "given an x of".
35
+ #
36
+ # 'given' works in conjunction with the 'that' / 'of' expression.
37
+ #
38
+ #
39
+ # == "given that"
40
+ #
41
+ # given do
42
+ # that "${location} == paris" do
43
+ # subprocess "notify_and_wait_for_pickup"
44
+ # end
45
+ # that "${state} == ready" do
46
+ # subprocess "deliver"
47
+ # end
48
+ # # else...
49
+ # subprocess "do_something_else"
50
+ # end
51
+ #
52
+ #
53
+ # == "given an x of"
54
+ #
55
+ # given "${status}" do
56
+ # of "ordered" do
57
+ # participant "alpha"
58
+ # end
59
+ # of "delivered" do
60
+ # participant "alpha"
61
+ # end
62
+ # # else...
63
+ # subprocess "do_something_else"
64
+ # end
65
+ #
66
+ # This variant also accepts regular expressions :
67
+ #
68
+ # given "${target}" do
69
+ # of "/-manager$/" do
70
+ # # ...
71
+ # end
72
+ # of /^user-/ do
73
+ # # ...
74
+ # end
75
+ # end
76
+ #
77
+ # == mixing 'that' and 'of'
78
+ #
79
+ # It's OK to use a "that" inside a "given an x" :
80
+ #
81
+ # given '${target}' do
82
+ # that "${location} == paris" do
83
+ # subprocess "notify_and_wait_for_pickup"
84
+ # end
85
+ # of "home" do
86
+ # subprocess "return_procedure"
87
+ # end
88
+ # end
89
+ #
90
+ #
91
+ # == the else part
92
+ #
93
+ # Anything that comes after the serie of 'that' and 'of' is considered in
94
+ # the 'else' zone and is executed if none of the 'that' or 'of' triggered.
95
+ #
96
+ # given '${target}' do
97
+ # that "${location} == paris" do
98
+ # subprocess "notify_and_wait_for_pickup"
99
+ # end
100
+ # of "home" do
101
+ # subprocess "return_procedure"
102
+ # end
103
+ # subprocess "do_this"
104
+ # subprocess "and_then_that"
105
+ # end
106
+ #
107
+ # Yes, two 'else' subprocesses will get executed one after the other (the
108
+ # 'given' acting like a 'sequence' for them.
109
+ #
110
+ # Interestingly :
111
+ #
112
+ # given '${target}' do
113
+ # of "home" do
114
+ # subprocess "return_procedure"
115
+ # end
116
+ # subprocess "do_this"
117
+ # of "office" do
118
+ # subprocess "go_to_work"
119
+ # end
120
+ # subprocess "and_then_that"
121
+ # end
122
+ #
123
+ # If the workitem field 'target' is set to 'home' only the 'return_procedure'
124
+ # subprocess will get called.
125
+ #
126
+ # If the workitem field 'target' is set to 'office', the 'do_this'
127
+ # subprocess, then the 'go_to_work' one will get called.
128
+ #
129
+ class GivenExpression < SequenceExpression
130
+
131
+ names :given
132
+
133
+ def reply(workitem)
134
+
135
+ if given = attribute(:t) || attribute_text
136
+ workitem['fields']['__given__'] = given
137
+ end
138
+
139
+ # as soon as one child says true, reply to the parent expression
140
+
141
+ if workitem['fields']['__result__'].to_s == 'true'
142
+
143
+ workitem['fields'].delete('__given__')
144
+ workitem['fields'].delete('__result__')
145
+ reply_to_parent(workitem)
146
+
147
+ else
148
+
149
+ super
150
+ end
151
+ end
152
+ end
153
+ end
154
+
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -61,7 +61,14 @@ module Ruote::Exp
61
61
  #
62
62
  # == shorter
63
63
  #
64
- # It's ok to shortcircuit the _if expression like this :
64
+ # The :test can be shortened to a :t :
65
+ #
66
+ # _if :t => '${f:customer.name} == Fred' do
67
+ # subprocess 'premium_course'
68
+ # subprocess 'regular_course'
69
+ # end
70
+ #
71
+ # When using Ruby to generate the process definition tree, you can simply do :
65
72
  #
66
73
  # _if '${f:customer.name} == Fred' do
67
74
  # subprocess 'premium_course'
@@ -79,21 +86,18 @@ module Ruote::Exp
79
86
 
80
87
  # called by 'else', 'then' or perhaps 'equals'
81
88
  #
82
- def reply (workitem)
89
+ def reply(workitem)
83
90
 
84
91
  if workitem['fei'] == h.fei # apply --> reply
85
92
 
86
93
  h.test = attribute(:test)
94
+ h.test = attribute(:t) if h.test.nil?
87
95
  h.test = attribute_text if h.test.nil?
88
96
  h.test = nil if h.test == ''
89
97
 
90
- offset = if h.test != nil
91
- Condition.true?(h.test) ? 0 : 1
92
- else
93
- 0
94
- end
98
+ offset = (h.test.nil? || Condition.true?(h.test)) ? 0 : 1
95
99
 
96
- apply_child_if_present(offset, workitem)
100
+ apply_child(offset, workitem)
97
101
 
98
102
  else # reply from a child
99
103
 
@@ -103,18 +107,17 @@ module Ruote::Exp
103
107
 
104
108
  else
105
109
 
106
- apply_child_if_present(
107
- workitem['fields']['__result__'] == true ? 1 : 2, workitem)
110
+ apply_child(workitem['fields']['__result__'] == true ? 1 : 2, workitem)
108
111
  end
109
112
  end
110
113
  end
111
114
 
112
115
  protected
113
116
 
114
- def apply_child_if_present (index, workitem)
117
+ def apply_child(index, workitem)
115
118
 
116
119
  if tree_children[index]
117
- apply_child(index, workitem)
120
+ super
118
121
  else
119
122
  reply_to_parent(workitem)
120
123
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -151,14 +151,14 @@ module Ruote::Exp
151
151
  reply_to_parent(h.applied_workitem)
152
152
  end
153
153
 
154
- def reply (workitem)
154
+ def reply(workitem)
155
155
 
156
156
  # never called
157
157
  end
158
158
 
159
159
  protected
160
160
 
161
- def new_value (type, key)
161
+ def new_value(type, key)
162
162
 
163
163
  dec = name.match(/^dec/)
164
164
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -126,11 +126,11 @@ module Ruote::Exp
126
126
  #
127
127
  # class Adjust
128
128
  # include Ruote::LocalParticipant
129
- # def consume (workitem)
129
+ # def consume(workitem)
130
130
  # workitem.command = 'break' if workitem.fields['amount'] > 10_000
131
131
  # reply_to_engine(workitem)
132
132
  # end
133
- # def cancel (fei, flavour)
133
+ # def cancel(fei, flavour)
134
134
  # end
135
135
  # end
136
136
  #
@@ -197,7 +197,7 @@ module Ruote::Exp
197
197
 
198
198
  protected
199
199
 
200
- def move_on (workitem=h.applied_workitem)
200
+ def move_on(workitem=h.applied_workitem)
201
201
 
202
202
  h.position += 1
203
203
 
@@ -0,0 +1,75 @@
1
+ #--
2
+ # Copyright (c) 2005-2011, 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
+ require 'ruote/exp/fe_sequence'
26
+
27
+
28
+ module Ruote::Exp
29
+
30
+ #
31
+ # Behaves like a sequence, but the children have their own variable
32
+ # scope.
33
+ #
34
+ # pdef = Ruote.process_definition do
35
+ # set 'v:var' => 'val'
36
+ # echo "out:${v:var}"
37
+ # let do
38
+ # set 'v:var' => 'val1'
39
+ # echo "in:${v:var}"
40
+ # end
41
+ # echo "out:${v:var}"
42
+ # end
43
+ #
44
+ # # => out:val, in:val1, out:val
45
+ #
46
+ #
47
+ # == as a 'case' statement
48
+ #
49
+ # let do
50
+ # define 'published' do
51
+ # do_this
52
+ # end
53
+ # define 'reviewed' do
54
+ # do_that
55
+ # end
56
+ # subprocess '${case}'
57
+ # end
58
+ #
59
+ # Subprocesses 'published' and 'reviewed' are bound in a local scope,
60
+ # that gets discarded when the let exits.
61
+ #
62
+ class LetExpression < SequenceExpression
63
+
64
+ names :let
65
+
66
+ def apply
67
+
68
+ h.variables = {}
69
+ # the blank local scope
70
+
71
+ reply(h.applied_workitem)
72
+ end
73
+ end
74
+ end
75
+
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -43,7 +43,7 @@ module Ruote::Exp
43
43
  #
44
44
  # It can be used in two ways : 'blocking' or 'triggering'. In both cases
45
45
  # the listen expression 'reacts' upon activity (incoming or outgoing workitem)
46
- # happening on a channel (a participant name).
46
+ # happening on a channel (a participant name or a tag name).
47
47
  #
48
48
  # == blocking
49
49
  #
@@ -99,14 +99,42 @@ module Ruote::Exp
99
99
  # Can be set to 'reply', to react on workitems being handed back to the
100
100
  # engine by the participant.
101
101
  #
102
+ # Setting :upon to 'entering' or 'leaving' tells the listen to focus on
103
+ # tag events.
104
+ #
105
+ # sequence do
106
+ # sequence :tag => 'phase_one' do
107
+ # alpha
108
+ # end
109
+ # sequence :tag => 'phase_two' do
110
+ # bravo
111
+ # end
112
+ # end
113
+ #
114
+ # In this dummy process definition, there are four tag events :
115
+ #
116
+ # * 'entering' 'phase_one'
117
+ # * 'leaving' 'phase_one'
118
+ # * 'entering' 'phase_two'
119
+ # * 'leaving' 'phase_two'
120
+ #
121
+ #
102
122
  # == :to and :on
103
123
  #
104
124
  # The :to attribute has already been seen, it can be replaced by the :on one.
105
125
  #
106
- # Those two attributes are expected to hold regular expressions, so it's OK to
107
- # write things like :
126
+ # listen :to => 'alpha'
127
+ #
128
+ # is equivalent to
129
+ #
130
+ # listen :on => 'alpha'
131
+ #
132
+ #
133
+ # == :to (:on) and regular expressions
108
134
  #
109
- # listen :to => "^user\_.+"
135
+ # It's OK to write things like :
136
+ #
137
+ # listen :to => "/^user\_.+/"
110
138
  #
111
139
  # or
112
140
  #
@@ -115,6 +143,7 @@ module Ruote::Exp
115
143
  # To listen for workitems for all the participant whose name start with
116
144
  # "user_".
117
145
  #
146
+ #
118
147
  # == :wfid
119
148
  #
120
149
  # By default, a listen expression listens for any workitem/participant event
@@ -122,16 +151,34 @@ module Ruote::Exp
122
151
  # will make the listen expression only care for events belonging to the
123
152
  # same process instance (same wfid).
124
153
  #
154
+ #
155
+ # == :where
156
+ #
157
+ # The :wfid can be considered a 'guard'. Another tool for guarding listen
158
+ # is to use the :where attribute.
159
+ #
160
+ # listen :to => 'alpha', :where => '${customer.state} == CA'
161
+ #
162
+ # The listen will trigger only if the workitem has a customer field with
163
+ # a subfield state containing the value "CA".
164
+ #
165
+ # The documentation about the dollar notation and the one about common
166
+ # attributes :if and :unless applies for the :where attribute.
167
+ #
125
168
  class ListenExpression < FlowExpression
126
169
 
127
170
  names :listen, :receive, :intercept
128
171
 
172
+ UPONS = {
173
+ 'apply' => 'dispatch', 'reply' => 'receive',
174
+ 'entering' => 'entered_tag', 'leaving' => 'left_tag'
175
+ }
176
+
129
177
  def apply
130
178
 
131
179
  h.to = attribute(:to) || attribute(:on)
132
180
 
133
- upon = attribute(:upon) || 'apply'
134
- h.upon = (upon == 'reply') ? 'receive' : 'dispatch'
181
+ h.upon = UPONS[attribute(:upon) || 'apply']
135
182
 
136
183
  h.lmerge = attribute(:merge).to_s
137
184
  h.lmerge = 'true' if h.lmerge == ''
@@ -141,15 +188,24 @@ module Ruote::Exp
141
188
 
142
189
  persist_or_raise
143
190
 
191
+ condition = if h.upon == 'dispatch' || h.upon == 'receive'
192
+ { 'participant_name' => h.to }
193
+ else
194
+ { 'tag' => h.to }
195
+ end
196
+
144
197
  @context.tracker.add_tracker(
145
198
  h.lwfid ? h.fei['wfid'] : nil,
146
199
  h.upon,
147
- h.fei,
148
- { 'participant_name' => h.to },
149
- { 'action' => 'reply', 'fei' => h.fei, 'flavour' => 'listen' })
200
+ Ruote.to_storage_id(h.fei),
201
+ condition,
202
+ { 'action' => 'reply',
203
+ 'fei' => h.fei,
204
+ 'workitem' => 'replace',
205
+ 'flavour' => 'listen' })
150
206
  end
151
207
 
152
- def reply (workitem)
208
+ def reply(workitem)
153
209
 
154
210
  #
155
211
  # :where guard
@@ -181,7 +237,7 @@ module Ruote::Exp
181
237
 
182
238
  protected
183
239
 
184
- def reply_to_parent (workitem)
240
+ def reply_to_parent(workitem)
185
241
 
186
242
  @context.tracker.remove_tracker(h.fei)
187
243