ruote 0.9.18

Sign up to get free protection for your applications and to get access to all the features.
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,1144 @@
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 'uri'
41
+
42
+ require 'openwfe/utils'
43
+ require 'openwfe/service'
44
+ require 'openwfe/logging'
45
+ require 'openwfe/omixins'
46
+ require 'openwfe/rudefinitions'
47
+ require 'openwfe/flowexpressionid'
48
+ require 'openwfe/util/observable'
49
+ require 'openwfe/expool/parser'
50
+ require 'openwfe/expool/representation'
51
+ require 'openwfe/expressions/environment'
52
+ require 'openwfe/expressions/raw'
53
+
54
+ require 'rufus/lru' # gem 'rufus-lru'
55
+ require 'rufus/verbs' # gem 'rufus-lru'
56
+
57
+
58
+ module OpenWFE
59
+
60
+ #
61
+ # The ExpressionPool stores expressions (pieces of workflow instance).
62
+ # It's the core of the workflow engine.
63
+ # It relies on an expression storage for actual persistence of the
64
+ # expressions.
65
+ #
66
+ class ExpressionPool
67
+ include ServiceMixin
68
+ include OwfeServiceLocator
69
+ include OwfeObservable
70
+ include FeiMixin
71
+
72
+ #
73
+ # The hash containing the wfid of the process instances currently
74
+ # paused.
75
+ #
76
+ attr_reader :paused_instances
77
+
78
+ #
79
+ # The constructor for the expression pool.
80
+ #
81
+ def initialize (service_name, application_context)
82
+
83
+ super()
84
+
85
+ service_init service_name, application_context
86
+
87
+ @paused_instances = {}
88
+
89
+ #@monitors = MonitorProvider.new(application_context)
90
+
91
+ @observers = {}
92
+
93
+ @stopped = false
94
+
95
+ engine_environment_id
96
+ # makes sure it's called now
97
+ end
98
+
99
+ #
100
+ # Stops this expression pool (especially its workqueue).
101
+ #
102
+ def stop
103
+
104
+ @stopped = true
105
+
106
+ onotify :stop
107
+ end
108
+
109
+ #--
110
+ # Obtains a unique monitor for an expression.
111
+ # It avoids the need for the FlowExpression instances to include
112
+ # the monitor mixin by themselves
113
+ #
114
+ #def get_monitor (fei)
115
+ # @monitors[fei]
116
+ #end
117
+ #++
118
+
119
+ #
120
+ # This method is called by the launch method. It's actually the first
121
+ # stage of that method.
122
+ # It may be interessant to use to 'validate' a launchitem and its
123
+ # process definition, as it will raise an exception in case
124
+ # of 'parameter' mismatch.
125
+ #
126
+ # There is a 'pre_launch_check' alias for this method in the
127
+ # Engine class.
128
+ #
129
+ def prepare_raw_expression (launchitem)
130
+
131
+ wfdurl = launchitem.workflow_definition_url
132
+
133
+ raise "launchitem.workflow_definition_url not set, cannot launch" \
134
+ unless wfdurl
135
+
136
+ definition = if wfdurl.match "^field:"
137
+
138
+ raise(
139
+ ":definition_in_launchitem_allowed not set to true, "+
140
+ "cannot launch"
141
+ ) if ac[:definition_in_launchitem_allowed] != true
142
+
143
+ wfdfield = wfdurl[6..-1]
144
+ launchitem.attributes.delete wfdfield
145
+ else
146
+
147
+ read_uri wfdurl
148
+ end
149
+
150
+ raise "didn't find process definition at '#{wfdurl}'" \
151
+ unless definition
152
+
153
+ raw_expression = build_raw_expression launchitem, definition
154
+
155
+ raw_expression.check_parameters launchitem
156
+ #
157
+ # will raise an exception if there are requirements
158
+ # and one of them is not met
159
+
160
+ raw_expression
161
+ end
162
+
163
+ #
164
+ # Instantiates a workflow definition and launches it.
165
+ #
166
+ # This method call will return immediately, it could even return
167
+ # before the actual launch is completely over.
168
+ #
169
+ # Returns the FlowExpressionId instance of the root expression of
170
+ # the newly launched flow.
171
+ #
172
+ def launch (launchitem, options={})
173
+
174
+ #
175
+ # prepare raw expression
176
+
177
+ raw_expression = prepare_raw_expression launchitem
178
+ #
179
+ # will raise an exception if there are requirements
180
+ # and one of them is not met
181
+
182
+ raw_expression = wrap_in_schedule(raw_expression, options) \
183
+ if options.size > 0
184
+
185
+ raw_expression.new_environment
186
+ #
187
+ # as this expression is the root of a new process instance,
188
+ # it has to have an environment for all the variables of
189
+ # the process instance
190
+
191
+ fei = raw_expression.fei
192
+
193
+ #
194
+ # apply prepared raw expression
195
+
196
+ wi = build_workitem launchitem
197
+
198
+ onotify :launch, fei, launchitem
199
+
200
+ apply raw_expression, wi
201
+
202
+ fei
203
+ end
204
+
205
+ #
206
+ # This is the first stage of the tlaunch_child() method.
207
+ #
208
+ # (it's used by the concurrent iterator when preparing all its
209
+ # iteration children)
210
+ #
211
+ def tprepare_child (
212
+ parent_exp, template, sub_id, register_child, vars)
213
+
214
+ return fetch_expression(template) \
215
+ if template.is_a?(FlowExpressionId)
216
+
217
+ fei = parent_exp.fei.dup
218
+ fei.expression_name = template.first
219
+ fei.expression_id = "#{fei.expid}.#{sub_id}"
220
+
221
+ raw_exp = RawExpression.new_raw(
222
+ fei, nil, nil, @application_context, template)
223
+
224
+ raw_exp.parent_id = parent_exp.fei
225
+
226
+ if vars
227
+ raw_exp.new_environment vars
228
+ else
229
+ raw_exp.environment_id = parent_exp.environment_id
230
+ end
231
+
232
+ #workitem.fei = raw_exp.fei
233
+ # done in do_apply...
234
+
235
+ if register_child
236
+ (parent_exp.children ||= []) << raw_exp.fei
237
+ update raw_exp
238
+ end
239
+
240
+ raw_exp
241
+ end
242
+
243
+ #
244
+ # Launches the given template (sexp) as the child of its
245
+ # parent expression.
246
+ #
247
+ # If the last, register_child, is set to true, this method will
248
+ # take care of adding the new child to the parent expression.
249
+ #
250
+ # (used by 'cron' and more)
251
+ #
252
+ def tlaunch_child (
253
+ parent_exp, template, sub_id, workitem, register_child, vars=nil)
254
+
255
+ raw_exp = tprepare_child(
256
+ parent_exp, template, sub_id, register_child, vars)
257
+
258
+ onotify :tlaunch_child, raw_exp.fei, workitem
259
+
260
+ apply raw_exp, workitem
261
+
262
+ raw_exp.fei
263
+ end
264
+
265
+ #
266
+ # Launches a template, but makes sure the new expression has no
267
+ # parent.
268
+ #
269
+ # (used by 'listen')
270
+ #
271
+ def tlaunch_orphan (
272
+ firing_exp, template, sub_id, workitem, register_child)
273
+
274
+ fei = firing_exp.fei.dup
275
+ fei.expression_id = "#{fei.expid}.#{sub_id}"
276
+ fei.expression_name = template.first
277
+
278
+ raw_exp = RawExpression.new_raw(
279
+ fei, nil, nil, @application_context, template)
280
+
281
+ #raw_exp.parent_id = GONE_PARENT_ID
282
+ raw_exp.parent_id = nil
283
+ # it's an orphan, no parent
284
+
285
+ raw_exp.environment_id = firing_exp.environment_id
286
+ # tapping anyway into the firer's environment
287
+
288
+ (firing_exp.children ||= []) << raw_exp.fei \
289
+ if register_child
290
+
291
+ onotify :tlaunch_orphan, raw_exp.fei, workitem
292
+
293
+ apply raw_exp, workitem
294
+
295
+ raw_exp.fei
296
+ end
297
+
298
+ #
299
+ # Launches a subprocess.
300
+ # The resulting wfid is a subid for the wfid of the firing expression.
301
+ #
302
+ # (used by 'subprocess')
303
+ #
304
+ def launch_subprocess (
305
+ firing_exp, template, forget, workitem, params)
306
+
307
+ raw_exp = if template.is_a?(FlowExpressionId)
308
+
309
+ fetch_expression template
310
+
311
+ elsif template.is_a?(RawExpression)
312
+
313
+ template.application_context = @application_context
314
+ template
315
+
316
+ else # probably an URI
317
+
318
+ build_raw_expression nil, template
319
+ end
320
+
321
+ raw_exp = raw_exp.dup
322
+ raw_exp.fei = raw_exp.fei.dup
323
+
324
+ if forget
325
+ raw_exp.parent_id = nil
326
+ else
327
+ raw_exp.parent_id = firing_exp.fei
328
+ end
329
+
330
+ #raw_exp.fei.wfid = get_wfid_generator.generate
331
+ #raw_exp.fei.wfid =
332
+ # "#{firing_exp.fei.wfid}.#{firing_exp.get_next_sub_id}"
333
+ raw_exp.fei.wfid =
334
+ "#{firing_exp.fei.parent_wfid}.#{firing_exp.get_next_sub_id}"
335
+
336
+ raw_exp.new_environment params
337
+
338
+ raw_exp.store_itself
339
+
340
+ apply raw_exp, workitem
341
+
342
+ raw_exp.fei
343
+ end
344
+
345
+ #
346
+ # Replaces the flow expression with a raw expression that has
347
+ # the same fei, same parent and points to the same env.
348
+ # The raw_representation will be the template.
349
+ # Stores and then apply the "cuckoo" expression.
350
+ #
351
+ def substitute_and_apply (fexp, template, workitem)
352
+
353
+ re = RawExpression.new_raw(
354
+ fexp.fei,
355
+ fexp.parent_id,
356
+ fexp.environment_id,
357
+ application_context,
358
+ template)
359
+
360
+ update re
361
+
362
+ apply re, workitem
363
+ end
364
+
365
+ #
366
+ # Applies a given expression (id or expression)
367
+ #
368
+ def apply (exp_or_fei, workitem)
369
+
370
+ get_workqueue.push(
371
+ self, :do_apply_reply, :apply, exp_or_fei, workitem)
372
+ end
373
+
374
+ #
375
+ # Replies to a given expression
376
+ #
377
+ def reply (exp_or_fei, workitem)
378
+
379
+ get_workqueue.push(
380
+ self, :do_apply_reply, :reply, exp_or_fei, workitem)
381
+ end
382
+
383
+ #
384
+ # Cancels the given expression.
385
+ # The param might be an expression instance or a FlowExpressionId
386
+ # instance.
387
+ #
388
+ def cancel (exp)
389
+
390
+ exp, fei = fetch exp
391
+
392
+ unless exp
393
+ linfo { "cancel() cannot cancel missing #{fei.to_debug_s}" }
394
+ return nil
395
+ end
396
+
397
+ ldebug { "cancel() for #{fei.to_debug_s}" }
398
+
399
+ onotify :cancel, exp
400
+
401
+ wi = exp.cancel
402
+
403
+ remove exp
404
+
405
+ wi
406
+ end
407
+
408
+ #
409
+ # Cancels the given expression and makes sure to resume the flow
410
+ # if the expression or one of its children were active.
411
+ #
412
+ # If the cancelled branch was not active, this method will take
413
+ # care of removing the cancelled expression from the parent
414
+ # expression.
415
+ #
416
+ def cancel_expression (exp)
417
+
418
+ exp = fetch_expression exp
419
+
420
+ wi = cancel exp
421
+
422
+ # ( remember that in case of error, no wi could get returned...)
423
+
424
+ if wi
425
+
426
+ reply_to_parent exp, wi, false
427
+
428
+ elsif exp.parent_id
429
+
430
+ parent_exp = fetch_expression exp.parent_id
431
+ parent_exp.remove_child(exp.fei) if parent_exp
432
+ end
433
+ end
434
+
435
+ #
436
+ # Given any expression of a process, cancels the complete process
437
+ # instance.
438
+ #
439
+ def cancel_process (exp_or_wfid)
440
+
441
+ wfid = extract_wfid exp_or_wfid, false
442
+
443
+ ldebug { "cancel_process() '#{wfid}'" }
444
+
445
+ root = fetch_root wfid
446
+
447
+ raise "no process to cancel '#{wfid}'" unless root
448
+
449
+ cancel root
450
+ end
451
+ alias :cancel_flow :cancel_process
452
+ #
453
+ # Forgets the given expression (make it an orphan).
454
+ #
455
+ def forget (parent_exp, exp)
456
+
457
+ exp, fei = fetch exp
458
+
459
+ #ldebug { "forget() forgetting #{fei}" }
460
+
461
+ return if not exp
462
+
463
+ onotify :forget, exp
464
+
465
+ parent_exp.children.delete(fei)
466
+
467
+ #exp.parent_id = GONE_PARENT_ID
468
+ exp.parent_id = nil
469
+
470
+ exp.dup_environment
471
+ exp.store_itself()
472
+
473
+ ldebug { "forget() forgot #{fei}" }
474
+ end
475
+
476
+ #
477
+ # Replies to the parent of the given expression.
478
+ #
479
+ def reply_to_parent (exp, workitem, remove=true)
480
+
481
+ ldebug { "reply_to_parent() for #{exp.fei.to_debug_s}" }
482
+
483
+ workitem.last_expression_id = exp.fei
484
+
485
+ onotify :reply_to_parent, exp, workitem
486
+
487
+ if remove
488
+
489
+ remove exp
490
+ #
491
+ # remove the expression itself
492
+
493
+ exp.clean_children
494
+ #
495
+ # remove all the children of the expression
496
+ end
497
+
498
+ #
499
+ # manage tag, have to remove it so it can get 'redone' or 'undone'
500
+ # (preventing abuse)
501
+
502
+ tagname = exp.attributes["tag"] if exp.attributes
503
+
504
+ exp.delete_variable(tagname) if tagname
505
+
506
+ #
507
+ # has raw_expression been updated ?
508
+
509
+ track_child_raw_representation exp
510
+
511
+ #
512
+ # flow terminated ?
513
+
514
+ #if not exp.parent_id
515
+ if (not exp.parent_id) and (exp.fei.expid == '0')
516
+
517
+ ldebug do
518
+ "reply_to_parent() process " +
519
+ "#{exp.fei.workflow_instance_id} terminated"
520
+ end
521
+
522
+ onotify :terminate, exp, workitem
523
+
524
+ return
525
+ end
526
+
527
+ #
528
+ # else, gone parent ?
529
+
530
+ #if exp.parent_id == GONE_PARENT_ID
531
+ if (not exp.parent_id) or (exp.parent_id.expname == 'gone')
532
+ # this 'gone' is kept for some level of 'backward compatibility'
533
+
534
+ ldebug do
535
+ "reply_to_parent() parent is gone for " +
536
+ exp.fei.to_debug_s
537
+ end
538
+
539
+ return
540
+ end
541
+
542
+ #
543
+ # parent still present, reply to it
544
+
545
+ reply exp.parent_id, workitem
546
+ end
547
+
548
+ #
549
+ # Adds or updates a flow expression in this pool
550
+ #
551
+ def update (flow_expression)
552
+
553
+ ldebug { "update() for #{flow_expression.fei.to_debug_s}" }
554
+
555
+ #t = Timer.new
556
+
557
+ onotify :update, flow_expression.fei, flow_expression
558
+
559
+ #ldebug do
560
+ # "update() took #{t.duration} ms " +
561
+ # "#{flow_expression.fei.to_debug_s}"
562
+ #end
563
+
564
+ flow_expression
565
+ end
566
+
567
+ #
568
+ # Fetches a FlowExpression from the pool.
569
+ # Returns a tuple : the FlowExpression plus its FlowExpressionId.
570
+ #
571
+ # The param 'exp' may be a FlowExpressionId or a FlowExpression that
572
+ # has to be reloaded.
573
+ #
574
+ def fetch (exp)
575
+ #synchronize do
576
+
577
+ #ldebug { "fetch() exp is of kind #{exp.class}" }
578
+
579
+ fei = if exp.is_a?(FlowExpression)
580
+
581
+ exp.fei
582
+
583
+ elsif not exp.is_a?(FlowExpressionId)
584
+
585
+ raise \
586
+ "Cannot fetch expression with key : "+
587
+ "'#{fei}' (#{fei.class})"
588
+
589
+ else
590
+
591
+ exp
592
+ end
593
+
594
+ #ldebug { "fetch() for #{fei.to_debug_s}" }
595
+
596
+ [ get_expression_storage[fei], fei ]
597
+ #end
598
+ end
599
+
600
+ #
601
+ # Fetches a FlowExpression (returns only the FlowExpression instance)
602
+ #
603
+ # The param 'exp' may be a FlowExpressionId or a FlowExpression that
604
+ # has to be reloaded.
605
+ #
606
+ def fetch_expression (exp)
607
+
608
+ exp, fei = fetch exp
609
+ exp
610
+ end
611
+
612
+ #
613
+ # Returns the engine environment (the top level environment)
614
+ #
615
+ def fetch_engine_environment
616
+ #synchronize do
617
+ #
618
+ # synchronize to ensure that there's 1! engine env
619
+
620
+ eei = engine_environment_id
621
+ ee, fei = fetch eei
622
+
623
+ return ee if ee
624
+
625
+ ee = Environment.new_env(
626
+ eei, nil, nil, @application_context, nil)
627
+
628
+ ee.store_itself
629
+
630
+ ee
631
+ #end
632
+ end
633
+
634
+ #
635
+ # Fetches the root expression of a process (or a subprocess).
636
+ #
637
+ def fetch_root (wfid)
638
+
639
+ get_expression_storage.fetch_root wfid
640
+ end
641
+
642
+ #
643
+ # Removes a flow expression from the pool
644
+ # (This method is mainly called from the pool itself)
645
+ #
646
+ def remove (exp)
647
+
648
+ exp, _fei = fetch(exp) \
649
+ if exp.is_a?(FlowExpressionId)
650
+
651
+ return unless exp
652
+
653
+ ldebug { "remove() fe #{exp.fei.to_debug_s}" }
654
+
655
+ onotify :remove, exp.fei
656
+
657
+ #synchronize do
658
+ #@monitors.delete(exp.fei)
659
+
660
+ remove_environment(exp.environment_id) \
661
+ if exp.owns_its_environment?
662
+ #end
663
+ end
664
+
665
+ #
666
+ # This method is called at each expool (engine) [re]start.
667
+ # It roams through the previously saved (persisted) expressions
668
+ # to reschedule ones like 'sleep' or 'cron'.
669
+ #
670
+ def reschedule
671
+
672
+ return if @stopped
673
+
674
+ #synchronize do
675
+
676
+ t = OpenWFE::Timer.new
677
+
678
+ linfo { "reschedule() initiating..." }
679
+
680
+ options = { :include_classes => Rufus::Schedulable }
681
+
682
+ get_expression_storage.find_expressions(options).each do |fexp|
683
+
684
+ linfo { "reschedule() for #{fexp.fei.to_s}..." }
685
+
686
+ onotify :reschedule, fexp.fei
687
+
688
+ fexp.reschedule get_scheduler
689
+ end
690
+
691
+ linfo { "reschedule() done. (took #{t.duration} ms)" }
692
+ #end
693
+ end
694
+
695
+ #
696
+ # Returns the unique engine_environment FlowExpressionId instance.
697
+ # There is only one such environment in an engine, hence this
698
+ # 'singleton' method.
699
+ #
700
+ def engine_environment_id
701
+ #synchronize do
702
+ # no need, it's been already called at initialization
703
+
704
+ return @eei if @eei
705
+
706
+ @eei = FlowExpressionId.new
707
+ @eei.owfe_version = OPENWFERU_VERSION
708
+ @eei.engine_id = get_engine.engine_name
709
+ @eei.initial_engine_id = @eei.engine_id
710
+ @eei.workflow_definition_url = 'ee'
711
+ @eei.workflow_definition_name = 'ee'
712
+ @eei.workflow_definition_revision = '0'
713
+ @eei.workflow_instance_id = '0'
714
+ @eei.expression_name = EN_ENVIRONMENT
715
+ @eei.expression_id = '0'
716
+ @eei
717
+ #end
718
+ end
719
+
720
+ #
721
+ # Returns the list of applied expressions belonging to a given
722
+ # workflow instance.
723
+ #
724
+ # If the unapplied optional parameter is set to true, all the
725
+ # expressions (even those not yet applied) that compose the process
726
+ # instance will be returned. Environments will be returned as well.
727
+ #
728
+ def process_stack (wfid, unapplied=false)
729
+
730
+ #raise "please provide a non-nil workflow instance id" \
731
+ # unless wfid
732
+
733
+ wfid = extract_wfid wfid, true
734
+
735
+ params = {
736
+ #:exclude_classes => [ Environment, RawExpression ],
737
+ #:exclude_classes => [ Environment ],
738
+ :parent_wfid => wfid
739
+ }
740
+ params[:applied] = true if (not unapplied)
741
+
742
+ stack = get_expression_storage.find_expressions params
743
+
744
+ stack.extend(RepresentationMixin) if unapplied
745
+
746
+ stack
747
+ end
748
+
749
+ #
750
+ # Lists all workflows (processes) currently in the expool (in
751
+ # the engine).
752
+ # This method will return a list of "process-definition" expressions
753
+ # (root of flows).
754
+ #
755
+ def list_processes (options={})
756
+
757
+ options[:include_classes] = DefineExpression
758
+ #
759
+ # Maybe it would be better to list root expressions instead
760
+ # so that expressions like 'sequence' can be used
761
+ # as root expressions. Later...
762
+
763
+ get_expression_storage.find_expressions options
764
+ end
765
+
766
+ #
767
+ # This method is called when apply() or reply() failed for
768
+ # an expression.
769
+ # There are currently only two 'users', the ParticipantExpression
770
+ # class and the do_process_workelement method of this ExpressionPool
771
+ # class.
772
+ #
773
+ def notify_error (error, fei, message, workitem)
774
+
775
+ fei = extract_fei fei
776
+ # densha requires that... :(
777
+
778
+ se = OpenWFE::exception_to_s error
779
+
780
+ onotify :error, fei, message, workitem, error.class.name, se
781
+
782
+ #fei = extract_fei fei
783
+
784
+ if error.is_a?(PausedError)
785
+ lwarn do
786
+ "#{self.service_name} " +
787
+ "operation :#{message.to_s} on #{fei.to_s} " +
788
+ "delayed because process '#{fei.wfid}' is in pause"
789
+ end
790
+ else
791
+ lwarn do
792
+ "#{self.service_name} " +
793
+ "operation :#{message.to_s} on #{fei.to_s} " +
794
+ "failed with\n" + se
795
+ end
796
+ end
797
+ end
798
+
799
+ #
800
+ # Gets the process definition (if necessary) and turns into
801
+ # into an expression tree (for storing into a RawExpression).
802
+ #
803
+ def determine_rep (param)
804
+
805
+ param = read_uri(param) if param.is_a?(URI)
806
+
807
+ DefParser.parse param
808
+ end
809
+
810
+ #
811
+ # Returns true if the process instance to which the expression
812
+ # belongs is currently paused.
813
+ #
814
+ def is_paused? (expression)
815
+
816
+ (@paused_instances[expression.fei.parent_wfid] != nil)
817
+ end
818
+
819
+ protected
820
+
821
+ #
822
+ # This is the only point in the expression pool where an URI
823
+ # is read, so this is where the :remote_definitions_allowed
824
+ # security check is enforced.
825
+ #
826
+ def read_uri (uri)
827
+
828
+ uri = URI.parse uri.to_s
829
+
830
+ raise ":remote_definitions_allowed is set to false" \
831
+ if (ac[:remote_definitions_allowed] != true and
832
+ uri.scheme and
833
+ uri.scheme != 'file')
834
+
835
+ #open(uri.to_s).read
836
+
837
+ f = Rufus::Verbs.fopen uri
838
+ result = f.read
839
+ f.close if f.respond_to?(:close)
840
+
841
+ result
842
+ end
843
+
844
+ #
845
+ # This is the method called [asynchronously] by the WorkQueue
846
+ # upon apply/reply.
847
+ #
848
+ def do_apply_reply (direction, exp_or_fei, workitem)
849
+
850
+ fei = nil
851
+
852
+ begin
853
+
854
+ exp, fei = if exp_or_fei.is_a?(FlowExpressionId)
855
+ fetch exp_or_fei
856
+ else
857
+ [ exp_or_fei, exp_or_fei.fei ]
858
+ end
859
+
860
+ #p [ direction, fei.wfid, fei.expid, fei.expname ]
861
+ #
862
+ # I uncomment that sometimes to see how the stack
863
+ # grows (wfids and expids)
864
+
865
+ ldebug {
866
+ ":#{direction} "+
867
+ "target #{fei.to_debug_s}" }
868
+
869
+ if not exp
870
+
871
+ #raise "apply() cannot apply missing #{_fei.to_debug_s}"
872
+ # not very helpful anyway
873
+
874
+ lwarn { "do_apply_reply() cannot find >#{fei}" }
875
+
876
+ return
877
+ end
878
+
879
+ check_if_paused exp
880
+
881
+ workitem.fei = exp.fei if direction == :apply
882
+
883
+ onotify direction, exp, workitem
884
+
885
+ exp.send direction, workitem
886
+
887
+ rescue Exception => e
888
+
889
+ notify_error e, fei, direction, workitem
890
+ end
891
+ end
892
+
893
+ #
894
+ # Will raise an exception if the expression belongs to a paused
895
+ # process.
896
+ #
897
+ def check_if_paused (expression)
898
+
899
+ wfid = expression.fei.parent_wfid
900
+
901
+ raise PausedError.new(wfid) if @paused_instances[wfid]
902
+ end
903
+
904
+ #
905
+ # if the launch method is called with a schedule option
906
+ # (like :at, :in, :cron and :every), this method takes care of
907
+ # wrapping the process with a sleep or a cron.
908
+ #
909
+ def wrap_in_schedule (raw_expression, options)
910
+
911
+ oat = options[:at]
912
+ oin = options[:in]
913
+ ocron = options[:cron]
914
+ oevery = options[:every]
915
+
916
+ fei = new_fei nil, "schedlaunch", "0", "sequence"
917
+
918
+ # not very happy with this code, it builds custom
919
+ # wrapping processes manually, maybe there is
920
+ # a more elegant way, but for now, it's ok.
921
+
922
+ template = if oat or oin
923
+
924
+ sleep_atts = if oat
925
+ { "until" => oat }
926
+ else #oin
927
+ { "for" => oin }
928
+ end
929
+ sleep_atts["scheduler-tags"] = "scheduled-launch"
930
+
931
+ raw_expression.new_environment
932
+ raw_expression.store_itself
933
+
934
+ [
935
+ "sequence", {}, [
936
+ [ "sleep", sleep_atts, [] ],
937
+ raw_expression.fei
938
+ ]
939
+ ]
940
+
941
+ elsif ocron or oevery
942
+
943
+ fei.expression_name = "cron"
944
+
945
+ cron_atts = if ocron
946
+ { "tab" => ocron }
947
+ else #oevery
948
+ { "every" => oevery }
949
+ end
950
+ cron_atts["name"] = "//cron_launch__#{fei.wfid}"
951
+ cron_atts["scheduler-tags"] = "scheduled-launch"
952
+
953
+ template = raw_expression.raw_representation
954
+ remove raw_expression
955
+
956
+ [ "cron", cron_atts, [ template ] ]
957
+
958
+ else
959
+
960
+ nil # don't schedule at all
961
+ end
962
+
963
+ if template
964
+
965
+ raw_exp = RawExpression.new_raw(
966
+ fei, nil, nil, @application_context, template)
967
+
968
+ raw_exp.store_itself
969
+
970
+ raw_exp
971
+ else
972
+
973
+ raw_expression
974
+ end
975
+ end
976
+
977
+ #
978
+ # Removes an environment, especially takes care of unbinding
979
+ # any special value it may contain.
980
+ #
981
+ def remove_environment (environment_id)
982
+
983
+ ldebug { "remove_environment() #{environment_id.to_debug_s}" }
984
+
985
+ env, fei = fetch(environment_id)
986
+
987
+ return unless env
988
+ #
989
+ # env already unbound and removed
990
+
991
+ env.unbind
992
+
993
+ #get_expression_storage().delete(environment_id)
994
+
995
+ onotify :remove, environment_id
996
+ end
997
+
998
+ #
999
+ # Prepares a new instance of InFlowWorkItem from a LaunchItem
1000
+ # instance.
1001
+ #
1002
+ def build_workitem (launchitem)
1003
+
1004
+ wi = InFlowWorkItem.new
1005
+
1006
+ wi.attributes = launchitem.attributes.dup
1007
+
1008
+ wi
1009
+ end
1010
+
1011
+ #
1012
+ # Builds a FlowExpressionId instance for a process being
1013
+ # launched.
1014
+ #
1015
+ def new_fei (launchitem, flow_name, flow_revision, exp_name)
1016
+
1017
+ url = if launchitem
1018
+ launchitem.workflow_definition_url
1019
+ else
1020
+ "no-url"
1021
+ end
1022
+
1023
+ fei = FlowExpressionId.new
1024
+
1025
+ fei.owfe_version = OPENWFERU_VERSION
1026
+ fei.engine_id = OpenWFE::stu get_engine.service_name
1027
+ fei.initial_engine_id = OpenWFE::stu fei.engine_id
1028
+ fei.workflow_definition_url = OpenWFE::stu url
1029
+ fei.workflow_definition_name = OpenWFE::stu flow_name
1030
+ fei.workflow_definition_revision = OpenWFE::stu flow_revision
1031
+ fei.wfid = get_wfid_generator.generate launchitem
1032
+ fei.expression_id = "0"
1033
+ fei.expression_name = exp_name
1034
+
1035
+ fei
1036
+ end
1037
+
1038
+ #
1039
+ # Builds the RawExpression instance at the root of the flow
1040
+ # being launched.
1041
+ #
1042
+ # The param can be a template or a definition (anything
1043
+ # accepted by the determine_representation() method).
1044
+ #
1045
+ def build_raw_expression (launchitem, param)
1046
+
1047
+ procdef = determine_rep param
1048
+
1049
+ atts = procdef[1]
1050
+ flow_name = atts['name'] || "noname"
1051
+ flow_revision = atts['revision'] || "0"
1052
+ exp_name = procdef.first
1053
+
1054
+ fei = new_fei launchitem, flow_name, flow_revision, exp_name
1055
+
1056
+ RawExpression.new_raw(
1057
+ fei, nil, nil, @application_context, procdef)
1058
+ end
1059
+
1060
+ #
1061
+ # Given a [replying] child flow expression, will update its parent
1062
+ # raw expression if the child raw_expression changed.
1063
+ #
1064
+ # This is used to keep track of in-flight modification to running
1065
+ # process instances.
1066
+ #
1067
+ def track_child_raw_representation (fexp)
1068
+
1069
+ return unless fexp.raw_rep_updated == true
1070
+
1071
+ parent = fetch_expression fexp.parent_id
1072
+
1073
+ return if parent.class.uses_template?
1074
+
1075
+ parent.raw_children[fexp.fei.child_id.to_i] =
1076
+ fexp.raw_representation
1077
+
1078
+ parent.store_itself
1079
+ end
1080
+ end
1081
+
1082
+ #
1083
+ # This error is raised when an expression belonging to a paused
1084
+ # process is applied or replied to.
1085
+ #
1086
+ class PausedError < RuntimeError
1087
+
1088
+ attr_reader :wfid
1089
+
1090
+ def initialize (wfid)
1091
+
1092
+ super "process '#{wfid}' is paused"
1093
+ @wfid = wfid
1094
+ end
1095
+
1096
+ #
1097
+ # Returns a hash for this PausedError instance.
1098
+ # (simply returns the hash of the paused process' wfid).
1099
+ #
1100
+ def hash
1101
+
1102
+ @wfid.hash
1103
+ end
1104
+
1105
+ #
1106
+ # Returns true if the other is a PausedError issued for the
1107
+ # same process instance (wfid).
1108
+ #
1109
+ def == (other)
1110
+
1111
+ return false unless other.is_a?(PausedError)
1112
+
1113
+ (@wfid == other.wfid)
1114
+ end
1115
+ end
1116
+
1117
+ #--
1118
+ # a small help class for storing monitors provided on demand
1119
+ # to expressions that need them
1120
+ #
1121
+ #class MonitorProvider
1122
+ # include MonitorMixin, Logging
1123
+ # MAX_MONITORS = 10000
1124
+ # def initialize (application_context=nil)
1125
+ # super()
1126
+ # @application_context = application_context
1127
+ # @monitors = LruHash.new(MAX_MONITORS)
1128
+ # end
1129
+ # def [] (key)
1130
+ # synchronize do
1131
+ # (@monitors[key] ||= Monitor.new)
1132
+ # end
1133
+ # end
1134
+ # def delete (key)
1135
+ # synchronize do
1136
+ # #ldebug { "delete() removing Monitor for #{key}" }
1137
+ # @monitors.delete(key)
1138
+ # end
1139
+ # end
1140
+ #end
1141
+ #++
1142
+
1143
+ end
1144
+