ruote 0.9.18

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 (291) hide show
  1. data/README.txt +24 -0
  2. data/bin/validate-workflow.rb +89 -0
  3. data/examples/about_state.rb +81 -0
  4. data/examples/bigflow.rb +19 -0
  5. data/examples/csv_weather.rb +23 -0
  6. data/examples/engine_template.rb +247 -0
  7. data/examples/flowtracing.rb +24 -0
  8. data/examples/homeworkreview.rb +68 -0
  9. data/examples/kotoba.rb +22 -0
  10. data/examples/mano_tracker.rb +172 -0
  11. data/examples/openwferu.rb +58 -0
  12. data/examples/quotereporter.rb +157 -0
  13. data/examples/scheduler_cron_usage.rb +48 -0
  14. data/examples/scheduler_usage.rb +56 -0
  15. data/lib/openwfe.rb +41 -0
  16. data/lib/openwfe/contextual.rb +111 -0
  17. data/lib/openwfe/def.rb +46 -0
  18. data/lib/openwfe/engine.rb +37 -0
  19. data/lib/openwfe/engine/engine.rb +756 -0
  20. data/lib/openwfe/engine/expool_methods.rb +172 -0
  21. data/lib/openwfe/engine/file_persisted_engine.rb +105 -0
  22. data/lib/openwfe/engine/participant_methods.rb +133 -0
  23. data/lib/openwfe/engine/status_methods.rb +353 -0
  24. data/lib/openwfe/engine/update_exp_methods.rb +112 -0
  25. data/lib/openwfe/exceptions.rb +51 -0
  26. data/lib/openwfe/expool/errorjournal.rb +476 -0
  27. data/lib/openwfe/expool/expressionpool.rb +1144 -0
  28. data/lib/openwfe/expool/expstorage.rb +403 -0
  29. data/lib/openwfe/expool/history.rb +174 -0
  30. data/lib/openwfe/expool/journal.rb +224 -0
  31. data/lib/openwfe/expool/journal_replay.rb +321 -0
  32. data/lib/openwfe/expool/parser.rb +242 -0
  33. data/lib/openwfe/expool/representation.rb +121 -0
  34. data/lib/openwfe/expool/threadedexpstorage.rb +188 -0
  35. data/lib/openwfe/expool/wfidgen.rb +388 -0
  36. data/lib/openwfe/expool/yamlexpstorage.rb +224 -0
  37. data/lib/openwfe/expressions/condition.rb +244 -0
  38. data/lib/openwfe/expressions/environment.rb +246 -0
  39. data/lib/openwfe/expressions/expressionmap.rb +258 -0
  40. data/lib/openwfe/expressions/fe_cancel.rb +109 -0
  41. data/lib/openwfe/expressions/fe_command.rb +241 -0
  42. data/lib/openwfe/expressions/fe_concurrence.rb +662 -0
  43. data/lib/openwfe/expressions/fe_cron.rb +259 -0
  44. data/lib/openwfe/expressions/fe_cursor.rb +259 -0
  45. data/lib/openwfe/expressions/fe_define.rb +192 -0
  46. data/lib/openwfe/expressions/fe_do.rb +168 -0
  47. data/lib/openwfe/expressions/fe_equals.rb +291 -0
  48. data/lib/openwfe/expressions/fe_filter.rb +129 -0
  49. data/lib/openwfe/expressions/fe_filter_definition.rb +168 -0
  50. data/lib/openwfe/expressions/fe_fqv.rb +250 -0
  51. data/lib/openwfe/expressions/fe_if.rb +303 -0
  52. data/lib/openwfe/expressions/fe_iterator.rb +145 -0
  53. data/lib/openwfe/expressions/fe_listen.rb +371 -0
  54. data/lib/openwfe/expressions/fe_losfor.rb +111 -0
  55. data/lib/openwfe/expressions/fe_misc.rb +421 -0
  56. data/lib/openwfe/expressions/fe_participant.rb +269 -0
  57. data/lib/openwfe/expressions/fe_reserve.rb +212 -0
  58. data/lib/openwfe/expressions/fe_save.rb +274 -0
  59. data/lib/openwfe/expressions/fe_sequence.rb +117 -0
  60. data/lib/openwfe/expressions/fe_set.rb +139 -0
  61. data/lib/openwfe/expressions/fe_sleep.rb +166 -0
  62. data/lib/openwfe/expressions/fe_step.rb +159 -0
  63. data/lib/openwfe/expressions/fe_subprocess.rb +168 -0
  64. data/lib/openwfe/expressions/fe_timeout.rb +127 -0
  65. data/lib/openwfe/expressions/fe_wait.rb +78 -0
  66. data/lib/openwfe/expressions/fe_when.rb +142 -0
  67. data/lib/openwfe/expressions/filter.rb +104 -0
  68. data/lib/openwfe/expressions/flowexpression.rb +847 -0
  69. data/lib/openwfe/expressions/iterator.rb +221 -0
  70. data/lib/openwfe/expressions/merge.rb +84 -0
  71. data/lib/openwfe/expressions/raw.rb +547 -0
  72. data/lib/openwfe/expressions/rprocdef.rb +375 -0
  73. data/lib/openwfe/expressions/time.rb +333 -0
  74. data/lib/openwfe/expressions/timeout.rb +178 -0
  75. data/lib/openwfe/expressions/value.rb +126 -0
  76. data/lib/openwfe/filterdef.rb +259 -0
  77. data/lib/openwfe/flowexpressionid.rb +357 -0
  78. data/lib/openwfe/listeners/listener.rb +97 -0
  79. data/lib/openwfe/listeners/listeners.rb +139 -0
  80. data/lib/openwfe/listeners/socketlisteners.rb +272 -0
  81. data/lib/openwfe/logging.rb +122 -0
  82. data/lib/openwfe/omixins.rb +95 -0
  83. data/lib/openwfe/orest/controlclient.rb +119 -0
  84. data/lib/openwfe/orest/definitions.rb +113 -0
  85. data/lib/openwfe/orest/exception.rb +60 -0
  86. data/lib/openwfe/orest/oldrestservlet.rb +279 -0
  87. data/lib/openwfe/orest/osocket.rb +148 -0
  88. data/lib/openwfe/orest/restclient.rb +176 -0
  89. data/lib/openwfe/orest/workitem.rb +206 -0
  90. data/lib/openwfe/orest/worklistclient.rb +272 -0
  91. data/lib/openwfe/orest/xmlcodec.rb +670 -0
  92. data/lib/openwfe/participants.rb +38 -0
  93. data/lib/openwfe/participants/enoparticipants.rb +230 -0
  94. data/lib/openwfe/participants/participant.rb +141 -0
  95. data/lib/openwfe/participants/participantmap.rb +249 -0
  96. data/lib/openwfe/participants/participants.rb +407 -0
  97. data/lib/openwfe/participants/soapparticipants.rb +135 -0
  98. data/lib/openwfe/participants/socketparticipants.rb +202 -0
  99. data/lib/openwfe/participants/storeparticipants.rb +254 -0
  100. data/lib/openwfe/rudefinitions.rb +130 -0
  101. data/lib/openwfe/service.rb +103 -0
  102. data/lib/openwfe/storage/yamlcustom.rb +106 -0
  103. data/lib/openwfe/storage/yamlfilestorage.rb +245 -0
  104. data/lib/openwfe/tools/flowtracer.rb +81 -0
  105. data/lib/openwfe/util/dollar.rb +217 -0
  106. data/lib/openwfe/util/irb.rb +86 -0
  107. data/lib/openwfe/util/observable.rb +144 -0
  108. data/lib/openwfe/util/ometa.rb +62 -0
  109. data/lib/openwfe/util/workqueue.rb +124 -0
  110. data/lib/openwfe/util/xml.rb +418 -0
  111. data/lib/openwfe/utils.rb +554 -0
  112. data/lib/openwfe/version.rb +37 -0
  113. data/lib/openwfe/workitem.rb +499 -0
  114. data/lib/openwfe/worklist/oldrest.rb +244 -0
  115. data/lib/openwfe/worklist/storelocks.rb +293 -0
  116. data/lib/openwfe/worklist/storeparticipant.rb +44 -0
  117. data/lib/openwfe/worklist/worklist.rb +297 -0
  118. data/test/README.txt +27 -0
  119. data/test/back_0916_test.rb +111 -0
  120. data/test/bm/bm_1_xml_vs_prog.rb +56 -0
  121. data/test/bm/bm_2_step.rb +109 -0
  122. data/test/bm/ft_0f_5ms.rb +35 -0
  123. data/test/bm/ft_26_load.rb +210 -0
  124. data/test/bm/ft_26b_load.rb +86 -0
  125. data/test/bm/ft_26c_load.rb +97 -0
  126. data/test/bm/ft_26d_load.rb +97 -0
  127. data/test/bm/ft_recu.rb +71 -0
  128. data/test/clone_test.rb +122 -0
  129. data/test/concurrence_test.rb +77 -0
  130. data/test/condition_test.rb +155 -0
  131. data/test/console_test.rb +12 -0
  132. data/test/cron_ltest.rb +15 -0
  133. data/test/description_test.rb +87 -0
  134. data/test/eno_test.rb +76 -0
  135. data/test/expmap_test.rb +54 -0
  136. data/test/expool_20031219_0916.tgz +0 -0
  137. data/test/fe_lookup_att_test.rb +62 -0
  138. data/test/fei_test.rb +181 -0
  139. data/test/file_persisted_engine_test.rb +64 -0
  140. data/test/file_persistence_test.rb +134 -0
  141. data/test/filep_cancel_test.rb +123 -0
  142. data/test/filter_test.rb +109 -0
  143. data/test/flowtestbase.rb +351 -0
  144. data/test/ft_0.rb +68 -0
  145. data/test/ft_0b_sequence.rb +36 -0
  146. data/test/ft_0c_testname.rb +33 -0
  147. data/test/ft_0d_participant.rb +30 -0
  148. data/test/ft_0e_multibody.rb +34 -0
  149. data/test/ft_10_loop.rb +134 -0
  150. data/test/ft_11_ppd.rb +415 -0
  151. data/test/ft_11b_ppd.rb +54 -0
  152. data/test/ft_12_blockparticipant.rb +97 -0
  153. data/test/ft_13_eno.rb +52 -0
  154. data/test/ft_14_subprocess.rb +88 -0
  155. data/test/ft_14b_subprocess.rb +192 -0
  156. data/test/ft_14c_subprocess.rb +68 -0
  157. data/test/ft_15_iterator.rb +216 -0
  158. data/test/ft_15b_iterator.rb +74 -0
  159. data/test/ft_16_fqv.rb +73 -0
  160. data/test/ft_17_condition.rb +84 -0
  161. data/test/ft_18_pname.rb +56 -0
  162. data/test/ft_1_unset.rb +175 -0
  163. data/test/ft_1b_unset.rb +39 -0
  164. data/test/ft_20_cron.rb +53 -0
  165. data/test/ft_21_cron.rb +87 -0
  166. data/test/ft_21b_cron_pause.rb +82 -0
  167. data/test/ft_22_history.rb +74 -0
  168. data/test/ft_23_when.rb +77 -0
  169. data/test/ft_23b_when.rb +70 -0
  170. data/test/ft_23c_wait.rb +80 -0
  171. data/test/ft_23d_cww.rb +58 -0
  172. data/test/ft_24_def.rb +44 -0
  173. data/test/ft_25_cancel.rb +89 -0
  174. data/test/ft_27_getflowpos.rb +147 -0
  175. data/test/ft_28_fileparticipant.rb +63 -0
  176. data/test/ft_29_httprb.rb +106 -0
  177. data/test/ft_2_concurrence.rb +135 -0
  178. data/test/ft_2b_concurrence.rb +188 -0
  179. data/test/ft_2c_concurrence.rb +64 -0
  180. data/test/ft_30_socketlistener.rb +203 -0
  181. data/test/ft_31_flowname.rb +40 -0
  182. data/test/ft_32_journal.rb +91 -0
  183. data/test/ft_32c_journal.rb +102 -0
  184. data/test/ft_32d_journal.rb +84 -0
  185. data/test/ft_33_description.rb +107 -0
  186. data/test/ft_34_cancelwfid.rb +80 -0
  187. data/test/ft_35_localdefs.rb +75 -0
  188. data/test/ft_36_subprocids.rb +97 -0
  189. data/test/ft_37_pnames.rb +70 -0
  190. data/test/ft_38_tag.rb +127 -0
  191. data/test/ft_38b_tag.rb +161 -0
  192. data/test/ft_38c_tag.rb +100 -0
  193. data/test/ft_39_reserve.rb +63 -0
  194. data/test/ft_39b_reserve.rb +84 -0
  195. data/test/ft_3_equals.rb +170 -0
  196. data/test/ft_3b_lookup_vf.rb +83 -0
  197. data/test/ft_40_defined.rb +61 -0
  198. data/test/ft_41_case.rb +110 -0
  199. data/test/ft_42_environments.rb +75 -0
  200. data/test/ft_43_pat10.rb +85 -0
  201. data/test/ft_44_save.rb +70 -0
  202. data/test/ft_44b_restore.rb +212 -0
  203. data/test/ft_45_citerator.rb +214 -0
  204. data/test/ft_46_pparams.rb +62 -0
  205. data/test/ft_47_filter.rb +160 -0
  206. data/test/ft_48_fe_filter.rb +88 -0
  207. data/test/ft_49_condition.rb +126 -0
  208. data/test/ft_4_misc.rb +237 -0
  209. data/test/ft_50_xml_attribute.rb +155 -0
  210. data/test/ft_51_stack.rb +55 -0
  211. data/test/ft_52_obs_participant.rb +123 -0
  212. data/test/ft_53_null_noop_participant.rb +62 -0
  213. data/test/ft_54_listen.rb +288 -0
  214. data/test/ft_54b_listen.rb +66 -0
  215. data/test/ft_54c_listen.rb +99 -0
  216. data/test/ft_55_ptimeout.rb +59 -0
  217. data/test/ft_56_timeout.rb +59 -0
  218. data/test/ft_57_a.rb +145 -0
  219. data/test/ft_58_ejournal.rb +151 -0
  220. data/test/ft_59_ps.rb +150 -0
  221. data/test/ft_59b_ps_for_pat.rb +58 -0
  222. data/test/ft_5_time.rb +118 -0
  223. data/test/ft_60_ecancel.rb +161 -0
  224. data/test/ft_61_elsub.rb +51 -0
  225. data/test/ft_62_procparticipant.rb +71 -0
  226. data/test/ft_63_pause.rb +124 -0
  227. data/test/ft_64_alias.rb +102 -0
  228. data/test/ft_64_clone.rb +69 -0
  229. data/test/ft_65_stringlaunch.rb +59 -0
  230. data/test/ft_66_subforget.rb +70 -0
  231. data/test/ft_67_schedlaunch.rb +116 -0
  232. data/test/ft_68_ifparticipant.rb +70 -0
  233. data/test/ft_69_cancelmissing.rb +51 -0
  234. data/test/ft_6_lambda.rb +64 -0
  235. data/test/ft_70_lookupvar.rb +55 -0
  236. data/test/ft_71_log.rb +60 -0
  237. data/test/ft_72_lookup_processes.rb +76 -0
  238. data/test/ft_73_cancel_sub.rb +139 -0
  239. data/test/ft_74_block_and_workitem_dup.rb +63 -0
  240. data/test/ft_75_ruby_attributes.rb +87 -0
  241. data/test/ft_76_merge_isolate.rb +88 -0
  242. data/test/ft_77_segments.rb +35 -0
  243. data/test/ft_78_eval.rb +150 -0
  244. data/test/ft_79_tticket.rb +187 -0
  245. data/test/ft_79b_tticket.rb +172 -0
  246. data/test/ft_79c_outcome.rb +56 -0
  247. data/test/ft_7_lose.rb +104 -0
  248. data/test/ft_7b_lose.rb +78 -0
  249. data/test/ft_80_spname.rb +91 -0
  250. data/test/ft_81_exp.rb +60 -0
  251. data/test/ft_82_trecu.rb +46 -0
  252. data/test/ft_83_badpause.rb +58 -0
  253. data/test/ft_84_updateexp.rb +198 -0
  254. data/test/ft_85_dolhash.rb +43 -0
  255. data/test/ft_86_dollar_fv.rb +68 -0
  256. data/test/ft_87_define.rb +74 -0
  257. data/test/ft_8_forget.rb +44 -0
  258. data/test/ft_9_cursor.rb +145 -0
  259. data/test/ft_9b_cursor.rb +105 -0
  260. data/test/ft_tests.rb +124 -0
  261. data/test/hash_test.rb +75 -0
  262. data/test/hparticipant_test.rb +164 -0
  263. data/test/lookup_att_test.rb +90 -0
  264. data/test/lookup_vf_test.rb +94 -0
  265. data/test/misc_test.rb +90 -0
  266. data/test/nut_0_irb.rb +20 -0
  267. data/test/obs_test.rb +142 -0
  268. data/test/orest_test.rb +251 -0
  269. data/test/param_test.rb +290 -0
  270. data/test/participant_test.rb +101 -0
  271. data/test/pending.rb +23 -0
  272. data/test/ps_representation.rb +133 -0
  273. data/test/rake_ltest.rb +38 -0
  274. data/test/rake_qtest.rb +68 -0
  275. data/test/raw_prog_test.rb +412 -0
  276. data/test/restart_cron_test.rb +136 -0
  277. data/test/restart_paused_test.rb +98 -0
  278. data/test/restart_sleep_test.rb +140 -0
  279. data/test/restart_tests.rb +18 -0
  280. data/test/restart_when_test.rb +112 -0
  281. data/test/ruby_procdef_test.rb +132 -0
  282. data/test/rutest_utils.rb +63 -0
  283. data/test/sec_test.rb +205 -0
  284. data/test/slock_test.rb +80 -0
  285. data/test/storage_test.rb +44 -0
  286. data/test/test.rb +3 -0
  287. data/test/timeout_test.rb +105 -0
  288. data/test/util_xml_test.rb +112 -0
  289. data/test/wfid_test.rb +175 -0
  290. data/test/wi_test.rb +75 -0
  291. metadata +433 -0
@@ -0,0 +1,303 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2006-2008, 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
+
34
+ #
35
+ # "made in Japan"
36
+ #
37
+ # John Mettraux at openwfe.org
38
+ #
39
+
40
+ require 'openwfe/workitem'
41
+ require 'openwfe/flowexpressionid'
42
+ require 'openwfe/expressions/condition'
43
+ require 'openwfe/expressions/flowexpression'
44
+
45
+
46
+ #
47
+ # expressions like 'set' and 'unset' and their utility methods
48
+ #
49
+
50
+ module OpenWFE
51
+
52
+ #
53
+ # The 'if' expression.
54
+ #
55
+ # <if>
56
+ # <equals field-value="f0" other-value="true" />
57
+ # <participant ref="alpha" />
58
+ # </if>
59
+ #
60
+ # It accepts an 'else' clause :
61
+ #
62
+ # <if>
63
+ # <equals field-value="f0" other-value="true" />
64
+ # <participant ref="alpha" />
65
+ # <participant ref="bravo" />
66
+ # </if>
67
+ #
68
+ # The 'test' attribute can be used instead of a condition child :
69
+ #
70
+ # <if test="${f:f0}">
71
+ # <participant ref="alpha" />
72
+ # </if>
73
+ #
74
+ # The 'rtest' attribute can be used to embed a condition expressed directly
75
+ # in Ruby :
76
+ #
77
+ # <if rtest="5 * 12 == 61">
78
+ # <participant ref="alpha" />
79
+ # </if>
80
+ #
81
+ # (Note that 'rtest' may only be used if the <tt>:ruby_eval_allowed</tt>
82
+ # parameter has been set in the engine's application_context :
83
+ #
84
+ # engine.application_context[:ruby_eval_allowed] = true
85
+ #
86
+ # but this is dangerous if the origin of the process defintions to run
87
+ # are not trusted)
88
+ #
89
+ # Used alone with 'test' or 'rtest', the 'if' expression simply sets the
90
+ # the __result__ field of its workitem to the result of its attribute
91
+ # evaluation :
92
+ #
93
+ # <if test="5 == 6"/>
94
+ #
95
+ # will set the __result__ field of the workitem to 'false'.
96
+ #
97
+ class IfExpression < FlowExpression
98
+ include ConditionMixin
99
+
100
+ names :if
101
+
102
+ #
103
+ # This boolean is set to true when the conditional claused has
104
+ # been evaluated and the 'if' is waiting for the consequence's
105
+ # reply.
106
+ #
107
+ attr_accessor :condition_replied
108
+
109
+
110
+ def apply (workitem)
111
+
112
+ #workitem.unset_result
113
+ #
114
+ # since OpenWFEru 0.9.16 previous __result__ values
115
+ # are not erased before an 'if'.
116
+
117
+ test = eval_condition :test, workitem, :not
118
+
119
+ if @children.length < 1
120
+ #workitem.set_result test if test
121
+ workitem.set_result((test != nil and test != false))
122
+ reply_to_parent workitem
123
+ return
124
+ end
125
+
126
+ @condition_replied = (test != nil)
127
+ #
128
+ # if the "test" attribute is not used, test will be null
129
+
130
+ store_itself
131
+
132
+ # a warning
133
+
134
+ maxchildren = (test == nil) ? 3 : 2
135
+
136
+ lwarn {
137
+ "apply() 'if' with more than #{maxchildren} children"
138
+ } if @children.size > maxchildren
139
+
140
+ # apply next step
141
+
142
+ if test != nil
143
+ #
144
+ # apply then or else (condition result known)
145
+ #
146
+ apply_consequence test, workitem, 0
147
+ else
148
+ #
149
+ # apply condition
150
+ #
151
+ get_expression_pool.apply @children.first, workitem
152
+ end
153
+ end
154
+
155
+ def reply (workitem)
156
+
157
+ return reply_to_parent(workitem) \
158
+ if @condition_replied
159
+
160
+ result = workitem.attributes[FIELD_RESULT]
161
+
162
+ @condition_replied = true
163
+
164
+ store_itself
165
+
166
+ apply_consequence result, workitem
167
+ end
168
+
169
+ #
170
+ # This reply_to_parent takes care of cleaning all the children
171
+ # before replying to the parent expression, this is important
172
+ # because only the 'then' or the 'else' child got evaluated, the
173
+ # remaining one has to be cleaned out here.
174
+ #
175
+ def reply_to_parent (workitem)
176
+
177
+ clean_children
178
+ super workitem
179
+ end
180
+
181
+ protected
182
+
183
+ def apply_consequence (index, workitem, offset=1)
184
+
185
+ if index == true
186
+ index = 0
187
+ elsif index == false
188
+ index = 1
189
+ elsif index == nil
190
+ index = 1
191
+ elsif not index.integer?
192
+ index = 0
193
+ end
194
+
195
+ index = index + offset
196
+
197
+ if index >= @children.length
198
+ reply_to_parent workitem
199
+ else
200
+ get_expression_pool.apply @children[index], workitem
201
+ end
202
+ end
203
+ end
204
+
205
+ #
206
+ # The 'case' expression.
207
+ #
208
+ # <case>
209
+ #
210
+ # <equals field="f0" other-value="ready" />
211
+ # <participant ref="alpha" />
212
+ #
213
+ # <if test="${supply_level} == ${field:supply_request}" />
214
+ # <participant ref="bravo" />
215
+ #
216
+ # <participant ref="charly" />
217
+ #
218
+ # </case>
219
+ #
220
+ # A generalized 'if'. Will evaluate its children, expecting the order :
221
+ #
222
+ # - condition
223
+ # - consequence
224
+ # - condition
225
+ # - consequence
226
+ # ...
227
+ # - else consequence (optional)
228
+ #
229
+ # The 'switch' nickname can be used for 'case'.
230
+ #
231
+ class CaseExpression < FlowExpression
232
+
233
+ names :case, :switch
234
+
235
+ #
236
+ # keeping track of where we are in the case iteration
237
+ #
238
+ attr_accessor :offset
239
+
240
+ #
241
+ # set to 'true' when the case expression is actually evaluating
242
+ # a condition (ie not triggering a consequence).
243
+ #
244
+ attr_accessor :evaluating_condition
245
+
246
+
247
+ def apply (workitem)
248
+
249
+ #workitem.unset_result
250
+ #
251
+ # since OpenWFEru 0.9.16 previous __result__ values
252
+ # are not erased before a 'case'.
253
+
254
+ @offset = nil
255
+
256
+ trigger_child workitem, true
257
+ end
258
+
259
+ def reply (workitem)
260
+
261
+ if @evaluating_condition
262
+
263
+ result = workitem.get_boolean_result
264
+
265
+ #ldebug { "reply() result : '#{result.to_s}' (#{result.class})" }
266
+
267
+ trigger_child workitem, !result
268
+ else
269
+
270
+ reply_to_parent workitem
271
+ end
272
+ end
273
+
274
+ protected
275
+
276
+ def trigger_child (workitem, is_condition)
277
+
278
+ @offset = if !@offset
279
+ 0
280
+ elsif is_condition
281
+ @offset + 2
282
+ else
283
+ @offset + 1
284
+ end
285
+
286
+ #ldebug { "trigger_child() is_condition ? #{is_condition}" }
287
+ #ldebug { "trigger_child() next offset is #{@offset}" }
288
+
289
+ unless @children[@offset]
290
+ reply_to_parent workitem
291
+ return
292
+ end
293
+
294
+ @evaluating_condition = is_condition
295
+
296
+ store_itself
297
+
298
+ get_expression_pool.apply(@children[@offset], workitem)
299
+ end
300
+ end
301
+
302
+ end
303
+
@@ -0,0 +1,145 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007-2008, 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
+
34
+ #
35
+ # "made in Japan"
36
+ #
37
+ # John Mettraux at openwfe.org
38
+ #
39
+
40
+ require 'openwfe/expressions/flowexpression'
41
+ require 'openwfe/expressions/iterator'
42
+ require 'openwfe/expressions/fe_command'
43
+
44
+
45
+ module OpenWFE
46
+
47
+ #
48
+ # The 'iterator' expression can be used like that for example :
49
+ #
50
+ # <iterator
51
+ # on-value="alice, bob, charles"
52
+ # to-variable="user-name"
53
+ # >
54
+ # <set
55
+ # field="${user-name} comment"
56
+ # value="(please fill this field)"
57
+ # />
58
+ # </iterator>
59
+ #
60
+ # Within the iteration, the workitem field "\_\_ic__" contains the number
61
+ # of elements in the iteration and the field "\_\_ip__" the index of the
62
+ # current iteration.
63
+ #
64
+ # The 'iterator' expression understands the same cursor commands as the
65
+ # CursorExpression. One can thus exit an iterator or skip steps in it.
66
+ #
67
+ # iterator :on_value => "alice, bob, charles, doug", to_variable => "v" do
68
+ # sequence do
69
+ # participant :variable_ref => "v"
70
+ # skip 1, :if => "${f:reply} == 'skip next'"
71
+ # end
72
+ # end
73
+ #
74
+ # For more information about those commands, see CursorCommandExpression.
75
+ #
76
+ class IteratorExpression < FlowExpression
77
+ include CommandMixin
78
+
79
+ names :iterator
80
+
81
+ uses_template
82
+
83
+ #
84
+ # an Iterator instance that holds the list of values being iterated
85
+ # upon.
86
+ #
87
+ attr_accessor :iterator
88
+
89
+ def apply (workitem)
90
+
91
+ return reply_to_parent(workitem) \
92
+ if raw_children.length < 1
93
+
94
+ @iterator = Iterator.new(self, workitem)
95
+
96
+ return reply_to_parent(workitem) \
97
+ if @iterator.size < 1
98
+
99
+ reply workitem
100
+ end
101
+
102
+ def reply (workitem)
103
+
104
+ command, step = determine_command_and_step workitem
105
+
106
+ vars = if not command
107
+
108
+ @iterator.next workitem
109
+
110
+ elsif command == C_BREAK or command == C_CANCEL
111
+
112
+ nil
113
+
114
+ elsif command == C_REWIND or command == C_CONTINUE
115
+
116
+ @iterator.rewind workitem
117
+
118
+ elsif command.match "^#{C_JUMP}"
119
+
120
+ @iterator.jump workitem, step
121
+
122
+ else # C_SKIP or C_BACK
123
+
124
+ @iterator.skip workitem, step
125
+ end
126
+
127
+ return reply_to_parent(workitem) \
128
+ unless vars
129
+
130
+ @children = []
131
+
132
+ get_expression_pool.tlaunch_child(
133
+ self,
134
+ raw_children.first,
135
+ @iterator.index,
136
+ workitem,
137
+ true, # registering child
138
+ vars)
139
+
140
+ store_itself
141
+ end
142
+ end
143
+
144
+ end
145
+
@@ -0,0 +1,371 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007-2008, 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
+
34
+ #
35
+ # "made in Japan"
36
+ #
37
+ # John Mettraux at openwfe.org
38
+ #
39
+
40
+ require 'openwfe/expressions/merge'
41
+ require 'openwfe/expressions/timeout'
42
+ require 'openwfe/expressions/condition'
43
+ require 'openwfe/expressions/flowexpression'
44
+
45
+
46
+ module OpenWFE
47
+
48
+ #
49
+ # The "listen" expression can be viewed in two ways :
50
+ #
51
+ # 1)
52
+ # It's a hook into the participant map to intercept apply or reply
53
+ # operations on participants.
54
+ #
55
+ # 2)
56
+ # It allows OpenWFE[ru] to be a bit closer to the 'ideal' process-calculus
57
+ # world (http://en.wikipedia.org/wiki/Process_calculi)
58
+ #
59
+ # Anyway...
60
+ #
61
+ # <listen to="alice">
62
+ # <subprocess ref="notify_bob" />
63
+ # </listen>
64
+ #
65
+ # Whenever a workitem is dispatched (applied) to the participant
66
+ # named "alice", the subprocess named "notify_bob" is triggered (once).
67
+ #
68
+ # listen :to => "^channel_.*", :upon => "reply" do
69
+ # sequence do
70
+ # participant :ref => "delta"
71
+ # participant :ref => "echo"
72
+ # end
73
+ # end
74
+ #
75
+ # After the listen has been applied, the first workitem coming back from
76
+ # a participant whose named starts with "channel_" will trigger a sequence
77
+ # with the participants 'delta' and 'echo'.
78
+ #
79
+ # listen :to => "alpha", :where => "${f:color} == red" do
80
+ # participant :ref => "echo"
81
+ # end
82
+ #
83
+ # Will send a copy of the first workitem meant for participant "alpha" to
84
+ # participant "echo" if this workitem's color field is set to 'red'.
85
+ #
86
+ # listen :to => "alpha", :once => "false" do
87
+ # send_email_to_stakeholders
88
+ # end
89
+ #
90
+ # This is some kind of a server : each time a workitem is dispatched to
91
+ # participant "alpha", the subprocess (or participant) named
92
+ # 'send_email_to_stakeholders') will receive a copy of that workitem.
93
+ # Use with care.
94
+ #
95
+ # listen :to => "alpha", :once => "false", :timeout => "1M2w" do
96
+ # send_email_to_stakeholders
97
+ # end
98
+ #
99
+ # The 'listen' expression understands the 'timeout' attribute. It can thus
100
+ # be instructed to stop listening after a certain amount of time (here,
101
+ # after one month and two weeks).
102
+ #
103
+ # The listen expression can be used without a
104
+ # child expression. It blocks until a valid messages comes in the
105
+ # channel, at which point it resumes the process, with workitem that came
106
+ # as the message (not with the workitem at apply time).
107
+ # (no merge implemented for now).
108
+ #
109
+ # sequence do
110
+ # listen :to => "channel_z", :upon => :reply
111
+ # participant :the_rest_of_the_process
112
+ # end
113
+ #
114
+ # In this example, the process will block until a workitem comes for
115
+ # a participant named 'channel_z'.
116
+ #
117
+ # The engine accept (in its reply()
118
+ # method) workitems that don't belong to a process intance (ie workitems
119
+ # that have a nil flow_expression_id). So it's entirely feasible to
120
+ # send 'notifications only' workitems to the OpenWFEru engine.
121
+ # (see http://openwferu.rubyforge.org/svn/trunk/openwfe-ruby/test/ft_54b_listen.rb)
122
+ #
123
+ # This expression has been aliased 'intercept'
124
+ # and 'receive'. It also accepts the 'on' parameter as an alias parameter
125
+ # to the 'to' parameter. Think "listen to" and "receive on".
126
+ #
127
+ # A 'merge' attribute can be set to true (the
128
+ # default value being false), the incoming workitem will then be merged
129
+ # with a copy of the workitem that 'applied' (activated) the listen
130
+ # expression.
131
+ #
132
+ class ListenExpression < FlowExpression
133
+ include TimeoutMixin
134
+ include ConditionMixin
135
+ include MergeMixin
136
+
137
+ names :listen, :intercept, :receive
138
+
139
+ uses_template
140
+
141
+ #
142
+ # the channel on which this expression 'listens'
143
+ #
144
+ attr_accessor :participant_regex
145
+
146
+ #
147
+ # is set to true if the expression listen to 1! workitem and
148
+ # then replies to its parent.
149
+ # When set to true, it listens until the process it belongs to
150
+ # terminates.
151
+ # The default value is true.
152
+ #
153
+ attr_accessor :once
154
+
155
+ #
156
+ # can take :apply or :reply as a value, if not set (nil), will listen
157
+ # on both 'directions'.
158
+ #
159
+ attr_accessor :upon
160
+
161
+ #
162
+ # 'listen' accepts a :merge attribute, when set to true, this
163
+ # field will contain a copy of the workitem that activated the
164
+ # listen activity. This copy will be merged with incoming (listened
165
+ # for) workitems when triggering the listen child.
166
+ #
167
+ attr_accessor :applied_workitem
168
+
169
+ #
170
+ # how many messages were received (can more than 0 or 1 if 'once'
171
+ # is set to false).
172
+ #
173
+ attr_accessor :call_count
174
+
175
+
176
+ def apply (workitem)
177
+
178
+ #if @children.size < 1
179
+ # reply_to_parent workitem
180
+ # return
181
+ #end
182
+ #
183
+ # 'listen' now blocks if there is no children
184
+
185
+ @participant_regex = lookup_string_attribute(:to, workitem)
186
+
187
+ @participant_regex = lookup_string_attribute(:on, workitem) \
188
+ unless @participant_regex
189
+
190
+ raise "attribute 'to' is missing for expression 'listen'" \
191
+ unless @participant_regex
192
+
193
+ ldebug { "apply() listening to '#{@participant_regex}'" }
194
+
195
+ #
196
+ # once
197
+
198
+ @once = lookup_boolean_attribute :once, workitem, true
199
+
200
+ @once = true if raw_children.size < 1
201
+ # a 'blocking listen' can only get triggered once.
202
+
203
+ ldebug { "apply() @once is #{@once}" }
204
+
205
+ #
206
+ # merge
207
+
208
+ merge = lookup_boolean_attribute :merge, workitem, false
209
+
210
+ ldebug { "apply() merge is #{@merge}" }
211
+
212
+ @applied_workitem = workitem.dup if merge
213
+
214
+ #
215
+ # upon
216
+
217
+ @upon = lookup_sym_attribute(
218
+ :upon, workitem, :default => :apply)
219
+
220
+ @upon = (@upon == :reply) ? :reply : :apply
221
+
222
+ ldebug { "apply() @upon is #{@upon}" }
223
+
224
+ @call_count = 0
225
+
226
+ determine_timeout
227
+ reschedule get_scheduler
228
+
229
+ store_itself
230
+ end
231
+
232
+ def cancel
233
+
234
+ stop_observing
235
+ super
236
+ end
237
+
238
+ def reply_to_parent (workitem)
239
+
240
+ ldebug { "reply_to_parent() 'listen' done." }
241
+
242
+ stop_observing
243
+ super
244
+ end
245
+
246
+ #
247
+ # Only called in case of timeout.
248
+ #
249
+ def trigger (params)
250
+
251
+ reply_to_parent workitem
252
+ end
253
+
254
+ #
255
+ # This is the method called when a 'listenable' workitem comes in
256
+ #
257
+ def call (channel, *args)
258
+ #synchronize do
259
+
260
+ upon = args[0]
261
+
262
+ ldebug { "call() channel : '#{channel}' upon '#{upon}'" }
263
+
264
+ return if upon != @upon
265
+
266
+ workitem = args[1].dup
267
+
268
+ conditional = eval_condition :where, workitem
269
+ #
270
+ # note that the values if the incoming workitem (not the
271
+ # workitem at apply time) are used for the evaluation
272
+ # of the condition (if necessary).
273
+
274
+ return if conditional == false
275
+
276
+ return if @once and @call_count > 0
277
+
278
+ #
279
+ # workitem does match...
280
+
281
+ ldebug do
282
+ "call() "+
283
+ "through for fei #{workitem.fei} / "+
284
+ "'#{workitem.participant_name}'"
285
+ end
286
+
287
+ @call_count += 1
288
+
289
+ #ldebug { "call() @call_count is #{@call_count}" }
290
+
291
+ #
292
+ # eventual merge
293
+
294
+ workitem = merge_workitems @applied_workitem.dup, workitem \
295
+ if @applied_workitem
296
+
297
+ #
298
+ # reply or launch nested child expression
299
+
300
+ return reply_to_parent(workitem) \
301
+ if raw_children.size < 1
302
+ #
303
+ # was just a "blocking listen"
304
+
305
+ #parent = @once ? self : nil
306
+ #get_expression_pool.launch_template(
307
+ # parent,
308
+ # nil,
309
+ # @call_count - 1,
310
+ # @children[0],
311
+ # workitem,
312
+ # nil)
313
+
314
+ if @once
315
+
316
+ # triggering just once
317
+
318
+ get_expression_pool.tlaunch_child(
319
+ self,
320
+ raw_children.first,
321
+ @call_count - 1,
322
+ workitem,
323
+ true) # registering child
324
+
325
+ else
326
+
327
+ # triggering multiple times
328
+
329
+ get_expression_pool.tlaunch_orphan(
330
+ self,
331
+ raw_children.first,
332
+ @call_count - 1,
333
+ workitem,
334
+ true) # registering child (in case of cancel)
335
+ end
336
+
337
+ store_itself
338
+ #end
339
+ end
340
+
341
+ #
342
+ # Registers for timeout and start observing the participant
343
+ # activity.
344
+ #
345
+ def reschedule (scheduler)
346
+
347
+ to_reschedule(scheduler)
348
+ start_observing
349
+ end
350
+
351
+ protected
352
+
353
+ #
354
+ # Start observing a [participant name] channel.
355
+ #
356
+ def start_observing
357
+
358
+ get_participant_map.add_observer @participant_regex, self
359
+ end
360
+
361
+ #
362
+ # Expression's job is over, deregister.
363
+ #
364
+ def stop_observing
365
+
366
+ get_participant_map.remove_observer self
367
+ end
368
+ end
369
+
370
+ end
371
+