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