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,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
+