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,662 @@
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/utils'
41
+ require 'openwfe/rudefinitions'
42
+ require 'openwfe/expressions/merge'
43
+ require 'openwfe/expressions/condition'
44
+ require 'openwfe/expressions/flowexpression'
45
+ require 'openwfe/expressions/iterator'
46
+
47
+
48
+ #
49
+ # base expressions like 'sequence' and 'concurrence'
50
+ #
51
+
52
+ module OpenWFE
53
+
54
+ #
55
+ # The concurrence expression will execute each of its (direct) children
56
+ # in parallel threads.
57
+ #
58
+ # Thus,
59
+ #
60
+ # <concurrence>
61
+ # <participant ref="pa" />
62
+ # <participant ref="pb" />
63
+ # </concurrence>
64
+ #
65
+ # Participants pa and pb will be 'treated' in parallel (quasi
66
+ # simultaneously).
67
+ #
68
+ # The concurrence expressions accept many attributes, that can get
69
+ # combined. By default, the concurrence waits for all its children to
70
+ # reply and returns the workitem of the first child that replied.
71
+ # The attributes tune this behaviour.
72
+ #
73
+ # <em>count</em>
74
+ #
75
+ # <concurrence count="1">
76
+ # <participant ref="pa" />
77
+ # <participant ref="pb" />
78
+ # </concurrence>
79
+ #
80
+ # The concurrence will be over as soon as 'pa' or 'pb' replied, i.e.
81
+ # as soon as "1" child replied.
82
+ #
83
+ # <em>remaining</em>
84
+ #
85
+ # The attribute 'remaining' can take two values 'cancel' (the default) and
86
+ # 'forget'.
87
+ # Cancelled children are completely wiped away, forgotten ones continue
88
+ # to operate but their reply will simply get discarded.
89
+ #
90
+ # <em>over-if</em>
91
+ #
92
+ # 'over-if' accepts a 'boolean expression' (something replying 'true' or
93
+ # 'false'), if the expression evaluates to true, the concurrence will be
94
+ # over and the remaining children will get cancelled (the default) or
95
+ # forgotten.
96
+ #
97
+ # <em>merge</em>
98
+ #
99
+ # By default, the first child to reply to its parent 'concurrence'
100
+ # expression 'wins', i.e. its workitem is used for resuming the flow (after
101
+ # the concurrence).
102
+ #
103
+ # [first] The default : the first child to reply wins
104
+ # [last] The last child to reply wins
105
+ # [highest] The first 'defined' child (in the list of children) will win
106
+ # [lowest] The last 'defined' child (in the list of children) will win
107
+ #
108
+ # Thus, in that example
109
+ #
110
+ # <concurrence merge="lowest">
111
+ # <participant ref="pa" />
112
+ # <participant ref="pb" />
113
+ # </concurrence>
114
+ #
115
+ # when the concurrence is done, the workitem of 'pb' is used to resume the
116
+ # flow after the concurrence.
117
+ #
118
+ # <em>merge-type</em>
119
+ #
120
+ # [override] The default : no mix of values between the workitems do occur
121
+ # [mix] Priority is given to the 'winning' workitem but their values
122
+ # get mixed
123
+ # [isolate] the attributes of the workitem of each branch is placed
124
+ # in a field in the resulting workitem. For example, the
125
+ # attributes of the first branch will be stored under the
126
+ # field named '0' of the resulting workitem.
127
+ #
128
+ # The merge occurs are the top level of workitem attributes.
129
+ #
130
+ # More complex merge behaviour can be obtained by extending the
131
+ # GenericSyncExpression class. But the default sync options are already
132
+ # numerous and powerful by their combinations.
133
+ #
134
+ class ConcurrenceExpression < SequenceExpression
135
+ include ConditionMixin
136
+
137
+ names :concurrence
138
+
139
+ attr_accessor \
140
+ :sync_expression
141
+
142
+
143
+ def apply (workitem)
144
+
145
+ sync = lookup_sym_attribute(
146
+ :sync, workitem, :default => :generic)
147
+
148
+ @sync_expression =
149
+ get_expression_map.get_sync_class(sync).new(self, workitem)
150
+
151
+ @children.each do |child|
152
+ @sync_expression.add_child child
153
+ end
154
+
155
+ store_itself
156
+
157
+ #concurrence = self
158
+
159
+ @children.each_with_index do |child, index|
160
+
161
+ get_expression_pool.apply(
162
+ child,
163
+ get_workitem(workitem, index))
164
+
165
+ #Thread.new do
166
+ # begin
167
+ # #ldebug { "apply() child : #{child.to_debug_s}" }
168
+ # concurrence.synchronize do
169
+ # get_expression_pool().apply(
170
+ # child,
171
+ # #workitem.dup)
172
+ # get_workitem(workitem, index))
173
+ # end
174
+ # rescue Exception => e
175
+ # lwarn do
176
+ # "apply() " +
177
+ # "caught exception in concurrent child " +
178
+ # child.to_debug_s + "\n" +
179
+ # OpenWFE::exception_to_s(e)
180
+ # end
181
+ # end
182
+ #end
183
+ end
184
+
185
+ #@sync_expression.ready(self)
186
+ #
187
+ # this is insufficient, have to do that :
188
+
189
+ #synchronize do
190
+ #
191
+ # Making sure the freshest version of the concurrence
192
+ # expression is used.
193
+ # This is especially important when using pure persistence.
194
+ #
195
+ reloaded_self, _fei = get_expression_pool.fetch @fei
196
+ reloaded_self.sync_expression.ready reloaded_self
197
+ #end
198
+ end
199
+
200
+ def reply (workitem)
201
+ @sync_expression.reply(self, workitem)
202
+ end
203
+
204
+ protected
205
+
206
+ def get_workitem (workitem, index)
207
+ workitem.dup
208
+ end
209
+ end
210
+
211
+ #
212
+ # This expression is a mix between a 'concurrence' and an 'iterator'.
213
+ # It understands the same attributes and behaves as an interator that
214
+ # forks its children concurrently.
215
+ #
216
+ # Some examples :
217
+ #
218
+ # <concurrent-iterator on-value="sales, logistics, lob2" to-field="p">
219
+ # <participant field-ref="p" />
220
+ # </concurrent-iterator>
221
+ #
222
+ # Within a Ruby process definition :
223
+ #
224
+ # sequence do
225
+ # set :field => f, :value => %w{ Alan, Bob, Clarence }
226
+ # #...
227
+ # concurrent_iterator :on_field => "f", :to_field => "p" do
228
+ # participant "${p}"
229
+ # end
230
+ # end
231
+ #
232
+ class ConcurrentIteratorExpression < ConcurrenceExpression
233
+
234
+ names :concurrent_iterator
235
+
236
+ #attr_accessor :template
237
+
238
+ uses_template
239
+
240
+
241
+ def apply (workitem)
242
+
243
+ return reply_to_parent(workitem) \
244
+ if raw_children.length < 1
245
+
246
+ @workitems = []
247
+
248
+ iterator = Iterator.new self, workitem
249
+
250
+ return reply_to_parent(workitem) \
251
+ unless iterator.has_next?
252
+
253
+ while iterator.has_next?
254
+
255
+ wi = workitem.dup
256
+
257
+ @workitems << wi
258
+
259
+ vars = iterator.next wi
260
+
261
+ #rawexp = get_expression_pool.prepare_from_template(
262
+ # self, nil, iterator.index, template, vars)
263
+ #@children << rawexp.fei
264
+
265
+ get_expression_pool.tprepare_child(
266
+ self,
267
+ raw_children.first,
268
+ iterator.index,
269
+ true, # register child
270
+ vars)
271
+ end
272
+
273
+ super
274
+ end
275
+
276
+ protected
277
+
278
+ def get_workitem (workitem, index)
279
+
280
+ @workitems[index]
281
+ end
282
+ end
283
+
284
+ #
285
+ # A base for sync expressions, currently empty.
286
+ # That may change.
287
+ #
288
+ class SyncExpression < ObjectWithMeta
289
+
290
+ def initialize
291
+
292
+ super
293
+ end
294
+
295
+ def self.names (*exp_names)
296
+
297
+ exp_names = exp_names.collect do |n|
298
+ n.to_s
299
+ end
300
+ meta_def :expression_names do
301
+ exp_names
302
+ end
303
+ end
304
+ end
305
+
306
+ #
307
+ # The classical OpenWFE sync expression.
308
+ # Used by 'concurrence' and 'concurrent-iterator'
309
+ #
310
+ class GenericSyncExpression < SyncExpression
311
+
312
+ names :generic
313
+
314
+ attr_accessor \
315
+ :remaining_children,
316
+ :count,
317
+ :reply_count,
318
+ :cancel_remaining,
319
+ :unready_queue
320
+
321
+ def initialize (synchable, workitem)
322
+
323
+ super()
324
+
325
+ @remaining_children = []
326
+ @reply_count = 0
327
+
328
+ @count = determine_count(synchable, workitem)
329
+ @cancel_remaining = cancel_remaining?(synchable, workitem)
330
+
331
+ merge = synchable.lookup_sym_attribute(
332
+ :merge, workitem, :default => :first)
333
+
334
+ merge_type = synchable.lookup_sym_attribute(
335
+ :merge_type, workitem, :default => :mix)
336
+
337
+ synchable.ldebug { "new() merge_type is '#{merge_type}'" }
338
+
339
+ @merge_array = MergeArray.new synchable.fei, merge, merge_type
340
+
341
+ @unready_queue = []
342
+ end
343
+
344
+ #
345
+ # when all the children got applied concurrently, the concurrence
346
+ # calls this method to notify the sync expression that replies
347
+ # can be processed
348
+ #
349
+ def ready (synchable)
350
+ #synchable.synchronize do
351
+
352
+ synchable.ldebug do
353
+ "ready() called by #{synchable.fei.to_debug_s} " +
354
+ "#{@unready_queue.length} wi waiting"
355
+ end
356
+
357
+ queue = @unready_queue
358
+ @unready_queue = nil
359
+ synchable.store_itself
360
+
361
+ queue.each do |workitem|
362
+ break if do_reply(synchable, workitem)
363
+ #
364
+ # do_reply() will return 'true' as soon as the
365
+ # concurrence is over, if this is the case, the
366
+ # queue should not be treated anymore
367
+ end
368
+ #end
369
+ end
370
+
371
+ def add_child (child)
372
+ @remaining_children << child
373
+ end
374
+
375
+ def reply (synchable, workitem)
376
+ #synchable.synchronize do
377
+
378
+ if @unready_queue
379
+
380
+ @unready_queue << workitem
381
+
382
+ synchable.store_itself
383
+
384
+ synchable.ldebug do
385
+ "#{self.class}.reply() "+
386
+ "#{@unready_queue.length} wi waiting..."
387
+ end
388
+
389
+ else
390
+ do_reply synchable, workitem
391
+ end
392
+ #end
393
+ end
394
+
395
+ protected
396
+
397
+ def do_reply (synchable, workitem)
398
+
399
+ synchable.ldebug do
400
+ "#{self.class}.do_reply() from " +
401
+ "#{workitem.last_expression_id.to_debug_s}"
402
+ end
403
+
404
+ @merge_array.push(synchable, workitem)
405
+
406
+ @reply_count = @reply_count + 1
407
+
408
+ @remaining_children.delete(workitem.last_expression_id)
409
+
410
+ #synchable.ldebug do
411
+ # "#{self.class}.do_reply() "+
412
+ # "remaining children : #{@remaining_children.length}"
413
+ #end
414
+
415
+ if @remaining_children.length <= 0
416
+ reply_to_parent(synchable)
417
+ return true
418
+ end
419
+
420
+ if @count > 0 and @reply_count >= @count
421
+ treat_remaining_children(synchable)
422
+ reply_to_parent(synchable)
423
+ return true
424
+ end
425
+
426
+ #
427
+ # over-if
428
+
429
+ conditional =
430
+ synchable.eval_condition("over-if", workitem, "over-unless")
431
+
432
+ if conditional
433
+ treat_remaining_children(synchable)
434
+ reply_to_parent(synchable)
435
+ return true
436
+ end
437
+
438
+ #
439
+ # not over, resuming
440
+
441
+ synchable.store_itself()
442
+
443
+ #synchable.ldebug do
444
+ # "#{self.class}.do_reply() not replying to parent "+
445
+ # "#{workitem.last_expression_id.to_debug_s}"
446
+ #end
447
+
448
+ false
449
+ end
450
+
451
+ def reply_to_parent (synchable)
452
+
453
+ workitem = @merge_array.do_merge
454
+
455
+ synchable.reply_to_parent workitem
456
+ end
457
+
458
+ def treat_remaining_children (synchable)
459
+
460
+ expool = synchable.get_expression_pool
461
+
462
+ @remaining_children.each do |child|
463
+
464
+ synchable.ldebug do
465
+ "#{self.class}.treat_remainining_children() " +
466
+ "#{child.to_debug_s} " +
467
+ "(cancel ? #{@cancel_remaining})"
468
+ end
469
+
470
+ if @cancel_remaining
471
+ expool.cancel(child)
472
+ else
473
+ expool.forget(synchable, child)
474
+ end
475
+ end
476
+ end
477
+
478
+ def cancel_remaining? (synchable_expression, workitem)
479
+
480
+ s = synchable_expression.lookup_sym_attribute(
481
+ :remaining, workitem, :default => :cancel)
482
+
483
+ (s == :cancel)
484
+ end
485
+
486
+ def determine_count (synchable_expression, workitem)
487
+
488
+ c = synchable_expression.lookup_attribute :count, workitem
489
+ return -1 if not c
490
+ i = c.to_i
491
+ return -1 if i < 1
492
+ i
493
+ end
494
+
495
+ #
496
+ # This inner class is used to gather workitems (via push()) before
497
+ # the final merge
498
+ # This final merge is triggered by calling the do_merge() method
499
+ # which will return the resulting, merged workitem.
500
+ #
501
+ class MergeArray
502
+ include MergeMixin
503
+
504
+ attr_accessor \
505
+ :synchable_fei,
506
+ :workitem,
507
+ :workitems_by_arrival,
508
+ :workitems_by_altitude,
509
+ :merge,
510
+ :merge_type
511
+
512
+ def initialize (synchable_fei, merge, merge_type)
513
+
514
+ @synchable_fei = synchable_fei
515
+
516
+ @merge = merge
517
+ @merge_type = merge_type
518
+
519
+ ensure_merge_settings
520
+
521
+ @workitem = nil
522
+
523
+ if highest? or lowest?
524
+ @workitems_by_arrival = []
525
+ @workitems_by_altitude = []
526
+ end
527
+ end
528
+
529
+ def push (synchable, wi)
530
+
531
+ #synchable.ldebug do
532
+ # "push() isolate? #{isolate?}"
533
+ #end
534
+
535
+ if isolate?
536
+ push_in_isolation wi
537
+ elsif last? or first?
538
+ push_by_position wi
539
+ else
540
+ push_by_arrival wi
541
+ end
542
+ end
543
+
544
+ def push_by_position (wi)
545
+
546
+ source, target = if first?
547
+ [ @workitem, wi ]
548
+ else
549
+ [ wi, @workitem ]
550
+ end
551
+ @workitem = merge_workitems target, source, override?
552
+ end
553
+
554
+ def push_in_isolation (wi)
555
+
556
+ unless @workitem
557
+ @workitem = wi.dup
558
+ att = @workitem.attributes
559
+ @workitem.attributes = {}
560
+ end
561
+
562
+ #key = synchable.children.index wi.last_expression_id
563
+ #key = wi.last_expression_id.child_id
564
+ key = get_child_id wi
565
+
566
+ @workitem.attributes[key.to_s] =
567
+ OpenWFE::fulldup(wi.attributes)
568
+ end
569
+
570
+ def push_by_arrival (wi)
571
+
572
+ #index = synchable.children.index wi.last_expression_id
573
+ #index = Integer(wi.last_expression_id.child_id)
574
+ index = Integer(get_child_id(wi))
575
+
576
+ @workitems_by_arrival << wi
577
+ @workitems_by_altitude[index] = wi
578
+ end
579
+
580
+ #
581
+ # merges the workitems stored here
582
+ #
583
+ def do_merge
584
+
585
+ return @workitem if @workitem
586
+
587
+ list = if first?
588
+ @workitems_by_arrival.reverse
589
+ elsif last?
590
+ @workitems_by_arrival
591
+ elsif highest?
592
+ @workitems_by_altitude.reverse
593
+ elsif lowest?
594
+ @workitems_by_altitude
595
+ end
596
+
597
+ result = nil
598
+
599
+ list.each do |wi|
600
+ next unless wi
601
+ result = merge_workitems result, wi, override?
602
+ end
603
+
604
+ #puts "___ result :"
605
+ #puts result.to_s
606
+ #puts
607
+
608
+ result
609
+ end
610
+
611
+ protected
612
+
613
+ def first?
614
+ @merge == :first
615
+ end
616
+ def last?
617
+ @merge == :last
618
+ end
619
+ def highest?
620
+ @merge == :highest
621
+ end
622
+ def lowest?
623
+ @merge == :lowest
624
+ end
625
+
626
+ def mix?
627
+ @merge_type == :mix
628
+ end
629
+ def override?
630
+ @merge_type == :override
631
+ end
632
+ def isolate?
633
+ @merge_type == :isolate
634
+ end
635
+
636
+ #
637
+ # Returns the child id of the expression that just
638
+ # replied with the given workitem.
639
+ #
640
+ def get_child_id (workitem)
641
+
642
+ return workitem.fei.child_id \
643
+ if workitem.fei.wfid == @synchable_fei.wfid
644
+
645
+ workitem.fei.last_sub_instance_id
646
+ end
647
+
648
+ #
649
+ # Making sure @merge and @merge_type are set to
650
+ # appropriate values.
651
+ #
652
+ def ensure_merge_settings
653
+
654
+ @merge_type = :mix unless override? or isolate?
655
+ @merge = :first unless last? or highest? or lowest?
656
+ end
657
+ end
658
+
659
+ end
660
+
661
+ end
662
+