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,847 @@
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/logging'
42
+ require 'openwfe/contextual'
43
+ require 'openwfe/rudefinitions'
44
+ require 'openwfe/util/ometa'
45
+ require 'openwfe/util/dollar'
46
+
47
+
48
+ module OpenWFE
49
+
50
+ #
51
+ # When this variable is set to true (at the process root),
52
+ # it means the process is paused.
53
+ #
54
+ VAR_PAUSED = '/__paused__'
55
+
56
+ #
57
+ # FlowExpression
58
+ #
59
+ # The base class for all OpenWFE flow expression classes.
60
+ # It gathers all the methods for attributes and variable lookup.
61
+ #
62
+ class FlowExpression < ObjectWithMeta
63
+ include Contextual, Logging, OwfeServiceLocator
64
+
65
+ #
66
+ # The 'flow expression id' the unique identifier within a
67
+ # workflow instance for this expression instance.
68
+ #
69
+ attr_accessor :fei
70
+
71
+ #
72
+ # The 'flow expression id' of the parent expression.
73
+ # Will yield 'nil' if this expression is the root of its process
74
+ # instance.
75
+ #
76
+ attr_accessor :parent_id
77
+
78
+ #
79
+ # The 'flow expression id' of the environment this expression works
80
+ # with.
81
+ #
82
+ attr_accessor :environment_id
83
+
84
+ #
85
+ # The attributes of the expression, as found in the process definition.
86
+ #
87
+ # <participant ref='toto' timeout='1d10h' />
88
+ #
89
+ # The attributes will be ref => "toto" and timeout => "1d10h" (yes,
90
+ # 'attributes' contains a hash.
91
+ #
92
+ attr_accessor :attributes
93
+
94
+ #
95
+ # An array of 'flow expression id' instances. These are the ids of
96
+ # the expressions children to this one.
97
+ #
98
+ # <sequence>
99
+ # <participant ref="toto" />
100
+ # <participant ref="bert" />
101
+ # </sequence>
102
+ #
103
+ # The expression instance for 'sequence' will hold the feis of toto and
104
+ # bert in its children array.
105
+ #
106
+ attr_accessor :children
107
+
108
+ #
109
+ # When the FlowExpression instance is applied, this time stamp is set
110
+ # to the current date.
111
+ #
112
+ attr_accessor :apply_time
113
+
114
+ #
115
+ # Used by raw expressions to store the not yet interpreted branches
116
+ # of a process, used by other expressions to store their
117
+ # representation at 'eval time'.
118
+ #
119
+ attr_accessor :raw_representation
120
+
121
+ #
122
+ # Meant to contain a boolean value. If set to 'true' it means that
123
+ # this expression raw_representation has been modified after
124
+ # the expression instantiation.
125
+ #
126
+ # It's used to keep track effectively of in-flight modifications
127
+ # of process instances.
128
+ #
129
+ attr_accessor :raw_rep_updated
130
+
131
+
132
+ #
133
+ # The classical no-params constructors.
134
+ #
135
+ def initialize
136
+
137
+ super
138
+ #
139
+ # very necessary as this class includes the MonitorMixin
140
+ end
141
+
142
+ #
143
+ # Builds a new instance of an expression
144
+ #
145
+ def self.new_exp (fei, parent_id, env_id, app_context, attributes)
146
+
147
+ e = self.new
148
+
149
+ e.fei = fei
150
+ e.parent_id = parent_id
151
+ e.environment_id = env_id
152
+ e.application_context = app_context
153
+ e.attributes = attributes
154
+
155
+ e.children = []
156
+ e.apply_time = nil
157
+
158
+ e
159
+ end
160
+
161
+ #--
162
+ # the two most important methods for flow expressions
163
+ #++
164
+
165
+ #
166
+ # this default implementation immediately replies to the
167
+ # parent expression
168
+ #
169
+ def apply (workitem)
170
+
171
+ get_parent.reply(workitem) if @parent_id
172
+ end
173
+
174
+ #
175
+ # this default implementation immediately replies to the
176
+ # parent expression
177
+ #
178
+ def reply (workitem)
179
+
180
+ reply_to_parent workitem
181
+ end
182
+
183
+ #
184
+ # Triggers the reply to the parent expression (of course, via the
185
+ # expression pool).
186
+ # Expressions do call this method when their job is done and the flow
187
+ # should resume without them.
188
+ #
189
+ def reply_to_parent (workitem)
190
+
191
+ get_expression_pool.reply_to_parent self, workitem
192
+ end
193
+
194
+ #
195
+ # a default implementation for cancel :
196
+ # cancels all the children
197
+ # Attempts to return an InFlowWorkItem
198
+ #
199
+ def cancel
200
+
201
+ return nil unless @children
202
+
203
+ inflowitem = nil
204
+
205
+ @children.each do |child|
206
+
207
+ next if child.is_a?(String)
208
+
209
+ i = get_expression_pool.cancel child
210
+ inflowitem ||= i
211
+ end
212
+
213
+ inflowitem
214
+ end
215
+
216
+ #
217
+ # some convenience methods
218
+
219
+ #
220
+ # Returns the parent expression (not as a FlowExpressionId but directly
221
+ # as the FlowExpression instance it is).
222
+ #
223
+ def get_parent
224
+
225
+ get_expression_pool.fetch_expression @parent_id
226
+ end
227
+
228
+ #
229
+ # Stores itself in the expression pool.
230
+ # It's very important for expressions in persisted context to save
231
+ # themselves as soon as their state changed.
232
+ # Else this information would be lost at engine restart or
233
+ # simply if the expression got swapped out of memory and reloaded later.
234
+ #
235
+ def store_itself
236
+
237
+ ldebug { "store_itself() for #{@fei.to_debug_s}" }
238
+ #ldebug { "store_itself() \n#{OpenWFE::caller_to_s(0, 6)}" }
239
+
240
+ get_expression_pool.update self
241
+ end
242
+
243
+ #
244
+ # Returns the environment instance this expression uses.
245
+ # An environment is a container (a scope) for variables in the process
246
+ # definition.
247
+ # Environments themselves are FlowExpression instances.
248
+ #
249
+ def get_environment
250
+
251
+ fetch_environment || get_expression_pool.fetch_engine_environment
252
+ end
253
+
254
+ #
255
+ # A shortcut for fetch_environment.get_root_environment
256
+ #
257
+ # Returns the environment of the top process (the environement
258
+ # just before the engine environment in the hierarchy).
259
+ #
260
+ def get_root_environment
261
+
262
+ fetch_environment.get_root_environment
263
+ end
264
+
265
+ #
266
+ # Just fetches the environment for this expression.
267
+ #
268
+ def fetch_environment
269
+
270
+ get_expression_pool.fetch_expression @environment_id
271
+ end
272
+
273
+ #
274
+ # Returns true if the expression's environment was generated
275
+ # for itself (usually DefineExpression do have such envs)
276
+ #
277
+ def owns_its_environment?
278
+
279
+ #ldebug do
280
+ # "owns_its_environment?()\n" +
281
+ # " #{@fei.to_debug_s}\n" +
282
+ # " #{@environment_id.to_debug_s}"
283
+ #end
284
+
285
+ return false if not @environment_id
286
+
287
+ ei = @fei.dup
288
+ vi = @environment_id.dup
289
+
290
+ ei.expression_name = "neutral"
291
+ vi.expression_name = "neutral"
292
+
293
+ #ldebug do
294
+ # "owns_its_environment?()\n"+
295
+ # " exp #{ei.to_debug_s}\n"+
296
+ # " env #{vi.to_debug_s}"
297
+ #end
298
+
299
+ (ei == vi)
300
+ end
301
+
302
+ #
303
+ # Returns true if this expression belongs to a paused flow
304
+ #
305
+ def paused?
306
+
307
+ #(lookup_variable(VAR_PAUSED) == true)
308
+ get_expression_pool.is_paused?(self)
309
+ end
310
+
311
+ #
312
+ # Sets a variable in the current environment. Is usually
313
+ # called by the 'set' expression.
314
+ #
315
+ # The variable name may be prefixed by / to indicate process level scope
316
+ # or by // to indicate engine level (global) scope.
317
+ #
318
+ def set_variable (varname, value)
319
+
320
+ env, var = lookup_environment(varname)
321
+
322
+ ldebug do
323
+ "set_variable() '#{varname}' to '#{value}' " +
324
+ "in #{env.fei.to_debug_s}"
325
+ end
326
+
327
+ env[var] = value
328
+ end
329
+
330
+ #
331
+ # Looks up the value of a variable in the current environment.
332
+ # If not found locally will lookup at the process level and even
333
+ # further in the engine scope.
334
+ #
335
+ # The variable name may be prefixed by / to indicate process level scope
336
+ # or by // to indicate engine level (global) scope.
337
+ #
338
+ def lookup_variable (varname)
339
+
340
+ #puts "lv : #{varname}"
341
+ #puts OpenWFE.caller_to_s(0, 5)
342
+
343
+ env, var = lookup_environment(varname)
344
+ env[var]
345
+ end
346
+
347
+ #
348
+ # Unsets a variable in the current environment.
349
+ #
350
+ # The variable name may be prefixed by / to indicate process level scope
351
+ # or by // to indicate engine level (global) scope.
352
+ #
353
+ def delete_variable (varname)
354
+
355
+ env, var = lookup_environment(varname)
356
+ env.delete var
357
+ end
358
+
359
+ alias :unset_variable :delete_variable
360
+
361
+ #
362
+ # Looks up the value for an attribute of this expression.
363
+ #
364
+ # if the expression is
365
+ #
366
+ # <participant ref="toto" />
367
+ #
368
+ # then
369
+ #
370
+ # participant_expression.lookup_attribute("toto", wi)
371
+ #
372
+ # will yield "toto"
373
+ #
374
+ # The various methods for looking up attributes do perform dollar
375
+ # variable substitution.
376
+ # It's ok to pass a Symbol for the attribute name.
377
+ #
378
+ def lookup_attribute (attname, workitem, options={})
379
+
380
+ default = options[:default]
381
+ escape = options[:escape]
382
+ tostring = options[:to_s]
383
+
384
+ attname = OpenWFE::symbol_to_name(attname) \
385
+ if attname.kind_of?(Symbol)
386
+
387
+ #ldebug { "lookup_attribute() '#{attname}' in #{@fei.to_debug_s}" }
388
+
389
+ text = @attributes[attname]
390
+
391
+ text = if text == nil
392
+
393
+ default
394
+
395
+ elsif escape == true
396
+
397
+ text
398
+
399
+ else
400
+
401
+ OpenWFE::dosub text, self, workitem
402
+ end
403
+
404
+ text = text.to_s if text and tostring
405
+
406
+ text
407
+ end
408
+
409
+ #
410
+ # Returns the attribute value as a String (or nil if it's not found).
411
+ #
412
+ def lookup_string_attribute (attname, workitem, options={})
413
+
414
+ result = lookup_attribute attname, workitem, options
415
+ result = result.to_s if result
416
+ result
417
+ end
418
+
419
+ #
420
+ # Like lookup_attribute() but returns the value downcased [
421
+ # (and stripped).
422
+ # Returns nil if no such attribute was found.
423
+ #
424
+ def lookup_downcase_attribute (attname, workitem, options={})
425
+
426
+ result = lookup_string_attribute attname, workitem, options
427
+ result = result.strip.downcase if result
428
+ result
429
+ end
430
+
431
+ #
432
+ # Returns the value of the attribute as a Symbol.
433
+ # Returns nil if there is no attribute under the given name.
434
+ #
435
+ def lookup_sym_attribute (attname, workitem, options={})
436
+
437
+ result = lookup_downcase_attribute attname, workitem, options
438
+ result = result.to_sym if result
439
+ result
440
+ end
441
+
442
+ #
443
+ # A convenience method for looking up a boolean value.
444
+ # It's ok to pass a Symbol for the attribute name.
445
+ #
446
+ def lookup_boolean_attribute (attname, workitem, default=false)
447
+
448
+ result = lookup_downcase_attribute attname, workitem
449
+ return default if result == nil
450
+
451
+ (result == 'true')
452
+ end
453
+
454
+ #
455
+ # looks up an attribute, if it's an array, returns it. Else
456
+ # (probably a string) will split it (comma) and return it
457
+ # (each element trimmed).
458
+ #
459
+ def lookup_array_attribute (attname, workitem, options={})
460
+
461
+ tostring = options.delete :to_s
462
+
463
+ v = lookup_attribute attname, workitem, options
464
+
465
+ return nil unless v
466
+
467
+ v = v.to_s.split(",").collect { |e| e.strip } \
468
+ unless v.is_a?(Array)
469
+
470
+ v = v.collect { |e| e.to_s } \
471
+ if tostring
472
+
473
+ v
474
+ end
475
+
476
+ #
477
+ # Returns true if the expression has the given attribute.
478
+ # The attname parameter can be a String or a Symbol.
479
+ #
480
+ def has_attribute (attname)
481
+
482
+ attname = OpenWFE::symbol_to_name(attname) \
483
+ if attname.kind_of?(Symbol)
484
+
485
+ (@attributes[attname] != nil)
486
+ end
487
+
488
+ #
489
+ # Returns a hash of all the FlowExpression attributes with their
490
+ # values having undergone dollar variable substitution.
491
+ # If the _attributes parameter is set (to an Array instance) then
492
+ # only the attributes named in that list will be looked up.
493
+ #
494
+ # It's ok to pass an array of Symbol instances for the attributes
495
+ # parameter.
496
+ #
497
+ def lookup_attributes (workitem, _attributes=nil)
498
+
499
+ return {} unless @attributes
500
+
501
+ (_attributes || @attributes.keys).inject({}) do |r, k|
502
+
503
+ k = k.to_s
504
+ v = @attributes[k]
505
+
506
+ r[k] = OpenWFE::dosub v, self, workitem
507
+
508
+ r
509
+ end
510
+ end
511
+
512
+ #
513
+ # creates a new environment just for this expression
514
+ #
515
+ def new_environment (initial_vars=nil)
516
+
517
+ ldebug { "new_environment() for #{@fei.to_debug_s}" }
518
+
519
+ @environment_id = @fei.dup
520
+ @environment_id.expression_name = EN_ENVIRONMENT
521
+
522
+ parent_fei = nil
523
+ parent = nil
524
+
525
+ parent, _fei = get_expression_pool.fetch(@parent_id) \
526
+ if @parent_id
527
+
528
+ parent_fei = parent.environment_id if parent
529
+
530
+ env = Environment.new_env(
531
+ @environment_id, parent_fei, nil, @application_context, nil)
532
+
533
+ env.variables.merge! initial_vars if initial_vars
534
+
535
+ env[@fei.wfname] = self.raw_representation \
536
+ if (not @parent_id) and (self.is_a?(RawExpression))
537
+ #
538
+ # keeping track of the raw representation
539
+ # of the top expression (for top recursion)
540
+
541
+ ldebug { "new_environment() is #{env.fei.to_debug_s}" }
542
+
543
+ env.store_itself
544
+
545
+ env
546
+ end
547
+
548
+ #
549
+ # This method is called in expressionpool.forget(). It duplicates
550
+ # the expression's current environment (deep copy) and attaches
551
+ # it as the expression own environment.
552
+ # Returns the duplicated environment.
553
+ #
554
+ def dup_environment
555
+
556
+ env = fetch_environment
557
+ env = env.dup
558
+ env.fei = @fei.dup
559
+ env.fei.expression_name = EN_ENVIRONMENT
560
+ @environment_id = env.fei
561
+
562
+ env.store_itself
563
+ end
564
+
565
+ #
566
+ # Takes care of removing all the children of this expression, if any.
567
+ #
568
+ def clean_children
569
+
570
+ return unless @children
571
+
572
+ @children.each do |child_fei|
573
+ get_expression_pool.remove(child_fei) \
574
+ if child_fei.kind_of?(FlowExpressionId)
575
+ end
576
+ end
577
+
578
+ #
579
+ # Removes a child from the expression children list.
580
+ #
581
+ def remove_child (child_fei)
582
+
583
+ #fei = @children.delete child_fei
584
+ #store_itself if fei
585
+
586
+ i = @children.index child_fei
587
+
588
+ return unless i
589
+
590
+ @children.delete_at i
591
+ raw_children.delete_at i
592
+ @raw_rep_updated = true
593
+
594
+ store_itself
595
+ end
596
+
597
+ #
598
+ # Currently only used by dollar.rb and its ${r:some_ruby_code},
599
+ # returns the binding in this flow expression.
600
+ #
601
+ def get_binding
602
+
603
+ binding()
604
+ end
605
+
606
+ #--
607
+ # Used like the classical Ruby synchronize, but as the OpenWFE
608
+ # expression pool manages its own set of monitors, it's one of those
609
+ # monitors that is used. But the synchronize code looks like the class
610
+ # just included the MonitorMixin. No hassle.
611
+ #
612
+ #def synchronize
613
+ # #ldebug { "synchronize() ---in--- for #{@fei.to_debug_s}" }
614
+ # get_expression_pool.get_monitor(@fei).synchronize do
615
+ # yield
616
+ # end
617
+ # #ldebug { "synchronize() --out-- for #{@fei.to_debug_s}" }
618
+ #end
619
+ #++
620
+
621
+ #
622
+ # Returns the text stored as the children of the given expression
623
+ #
624
+ def fetch_text_content (workitem, escape=false)
625
+
626
+ text = ""
627
+
628
+ children.each do |child|
629
+
630
+ if child.is_a?(RawExpression)
631
+
632
+ text << child.fei.to_s
633
+
634
+ elsif child.is_a?(FlowExpressionId)
635
+
636
+ text << get_expression_pool\
637
+ .fetch_expression(child).raw_representation.to_s
638
+
639
+ else
640
+
641
+ text << child.to_s
642
+ end
643
+ end
644
+
645
+ return nil if text == ""
646
+
647
+ text = OpenWFE::dosub(text, self, workitem) \
648
+ unless escape
649
+
650
+ text
651
+ end
652
+
653
+ #
654
+ # looks up for 'value', 'variable-value' and then for 'field-value'
655
+ # if necessary.
656
+ #
657
+ def lookup_value (workitem, options={})
658
+
659
+ lookup_vf_attribute(workitem, 'value', options) ||
660
+ lookup_vf_attribute(workitem, 'val', options)
661
+ end
662
+
663
+ #
664
+ # looks up for 'ref', 'variable-ref' and then for 'field-ref'
665
+ # if necessary.
666
+ #
667
+ def lookup_ref (workitem, prefix='')
668
+
669
+ ref = lookup_vf_attribute workitem, 'ref', :prefix => prefix
670
+ return ref.to_s if ref
671
+ nil
672
+ end
673
+
674
+ #
675
+ # Looks up for value attributes like 'field-ref' or 'variable-value'
676
+ #
677
+ def lookup_vf_attribute (workitem, att_name, options={})
678
+
679
+ att_name = att_name.to_s
680
+
681
+ prefix = options[:prefix] || ''
682
+ prefix = prefix.to_s
683
+
684
+ dash = (att_name.size > 0 and prefix.size > 0) ? "-" : ""
685
+
686
+ v = lookup_attribute(
687
+ "#{prefix}#{dash}#{att_name}", workitem, options)
688
+
689
+ att_name = "-#{att_name}" if att_name.size > 0
690
+ prefix = "#{prefix}-" if prefix.size > 0
691
+
692
+ return v if v
693
+
694
+ v = lookup_attribute(
695
+ "#{prefix}variable#{att_name}", workitem, options) ||
696
+ lookup_attribute(
697
+ "#{prefix}var#{att_name}", workitem, options) ||
698
+ lookup_attribute(
699
+ "#{prefix}v#{att_name}", workitem, options)
700
+
701
+ return lookup_variable(v) if v
702
+
703
+ f = lookup_attribute(
704
+ "#{prefix}field#{att_name}", workitem, options) ||
705
+ lookup_attribute(
706
+ "#{prefix}f#{att_name}", workitem, options)
707
+
708
+ #return workitem.attributes[f] if f
709
+ return workitem.attributes[f.to_s] if f
710
+
711
+ nil
712
+ end
713
+
714
+ #
715
+ # Since OpenWFEru 0.9.17, each expression keeps his @raw_representation
716
+ # this is a shortcut for exp.raw_representation[2]
717
+ #
718
+ def raw_children
719
+
720
+ @raw_representation[2]
721
+ end
722
+
723
+ SUBIDMUTEX = Mutex.new
724
+
725
+ #
726
+ # Returns the next sub process id available (this counter
727
+ # is stored in the process environment under the key :next_sub_id)
728
+ #
729
+ def get_next_sub_id
730
+
731
+ #env = get_environment
732
+ env = get_root_environment
733
+
734
+ c = nil
735
+
736
+ #env.synchronize do
737
+
738
+ c = env.variables[:next_sub_id]
739
+ n = if c
740
+ c + 1
741
+ else
742
+ c = 0
743
+ 1
744
+ end
745
+ env.variables[:next_sub_id] = n
746
+ env.store_itself
747
+ #end
748
+
749
+ c
750
+ end
751
+
752
+ #
753
+ # Some eye candy
754
+ #
755
+ def to_s
756
+
757
+ s = "* #{@fei.to_debug_s} [#{self.class.name}]"
758
+
759
+ s << "\n `--p--> #{@parent_id.to_debug_s}" \
760
+ if @parent_id
761
+
762
+ s << "\n `--e--> #{@environment_id.to_debug_s}" \
763
+ if @environment_id
764
+
765
+ return s unless @children
766
+
767
+ @children.each do |c|
768
+ sc = if c.kind_of?(OpenWFE::FlowExpressionId)
769
+ c.to_debug_s
770
+ else
771
+ ">#{c.to_s}<"
772
+ end
773
+ s << "\n `--c--> #{sc}"
774
+ end
775
+
776
+ s
777
+ end
778
+
779
+ #
780
+ # a nice 'names' tag/method for registering the names of the
781
+ # Expression classes.
782
+ #
783
+ def self.names (*exp_names)
784
+
785
+ exp_names = exp_names.collect do |n|
786
+ n.to_s
787
+ end
788
+ meta_def :expression_names do
789
+ exp_names
790
+ end
791
+ end
792
+
793
+ #
794
+ # returns true if the expression class is a 'definition'.
795
+ #
796
+ def self.is_definition?
797
+ false
798
+ end
799
+ def self.is_definition
800
+ meta_def :is_definition? do
801
+ true
802
+ end
803
+ end
804
+
805
+ #
806
+ # returns true if the expression class 'uses a template'
807
+ # (children will not immediately get expanded at 'parse' time)
808
+ #
809
+ def self.uses_template?
810
+ false
811
+ end
812
+ def self.uses_template
813
+ meta_def :uses_template? do
814
+ true
815
+ end
816
+ end
817
+
818
+ protected
819
+
820
+ #
821
+ # If the varname starts with '//' will return the engine
822
+ # environment and the truncated varname...
823
+ # If the varname starts with '/' will return the root environment
824
+ # for the current process instance and the truncated varname...
825
+ #
826
+ def lookup_environment (varname)
827
+
828
+ if varname[0, 2] == '//'
829
+ return [
830
+ get_expression_pool.fetch_engine_environment,
831
+ varname[2..-1]
832
+ ]
833
+ end
834
+
835
+ if varname[0, 1] == '/'
836
+ return [
837
+ get_environment.get_root_environment,
838
+ varname[1..-1]
839
+ ]
840
+ end
841
+
842
+ [ get_environment, varname ]
843
+ end
844
+ end
845
+
846
+ end
847
+