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,375 @@
|
|
|
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 'rufus/eval' # gem 'rufus-eval'
|
|
41
|
+
|
|
42
|
+
require 'openwfe/utils'
|
|
43
|
+
require 'openwfe/expressions/raw'
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
module OpenWFE
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Extend this class to create a programmatic process definition.
|
|
50
|
+
#
|
|
51
|
+
# A short example :
|
|
52
|
+
#
|
|
53
|
+
# class MyProcessDefinition < OpenWFE::ProcessDefinition
|
|
54
|
+
# def make
|
|
55
|
+
# process_definition :name => "test1", :revision => "0" do
|
|
56
|
+
# sequence do
|
|
57
|
+
# set :variable => "toto", :value => "nada"
|
|
58
|
+
# print "toto:${toto}"
|
|
59
|
+
# end
|
|
60
|
+
# end
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# li = OpenWFE::LaunchItem.new(MyProcessDefinition)
|
|
65
|
+
# engine.launch(li)
|
|
66
|
+
#
|
|
67
|
+
#
|
|
68
|
+
class ProcessDefinition
|
|
69
|
+
|
|
70
|
+
def self.metaclass; class << self; self; end; end
|
|
71
|
+
|
|
72
|
+
attr_reader :context
|
|
73
|
+
|
|
74
|
+
def initialize
|
|
75
|
+
|
|
76
|
+
super()
|
|
77
|
+
@context = Context.new
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def method_missing (m, *args, &block)
|
|
81
|
+
|
|
82
|
+
#puts "__i_method_missing >>>#{m}<<<<"
|
|
83
|
+
|
|
84
|
+
ProcessDefinition.make_expression(
|
|
85
|
+
@context,
|
|
86
|
+
OpenWFE::to_expression_name(m),
|
|
87
|
+
ProcessDefinition.pack_args(args),
|
|
88
|
+
&block)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.method_missing (m, *args, &block)
|
|
92
|
+
|
|
93
|
+
@ccontext = Context.new \
|
|
94
|
+
if (not @ccontext) or @ccontext.discarded?
|
|
95
|
+
|
|
96
|
+
ProcessDefinition.make_expression(
|
|
97
|
+
@ccontext,
|
|
98
|
+
OpenWFE::to_expression_name(m),
|
|
99
|
+
ProcessDefinition.pack_args(args),
|
|
100
|
+
&block)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#
|
|
104
|
+
# builds an actual expression representation (a node in the
|
|
105
|
+
# process definition tree).
|
|
106
|
+
#
|
|
107
|
+
def self.make_expression (context, exp_name, params, &block)
|
|
108
|
+
|
|
109
|
+
string_child = nil
|
|
110
|
+
#attributes = OpenWFE::SymbolHash.new
|
|
111
|
+
attributes = Hash.new
|
|
112
|
+
|
|
113
|
+
#puts " ... params.class is #{params.class}"
|
|
114
|
+
|
|
115
|
+
if params.kind_of?(Hash)
|
|
116
|
+
|
|
117
|
+
params.each do |k, v|
|
|
118
|
+
|
|
119
|
+
if k == '0'
|
|
120
|
+
string_child = v.to_s
|
|
121
|
+
else
|
|
122
|
+
#attributes[OpenWFE::symbol_to_name(k.to_s)] = v.to_s
|
|
123
|
+
attributes[OpenWFE::symbol_to_name(k.to_s)] = v
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
elsif params
|
|
128
|
+
|
|
129
|
+
string_child = params.to_s
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
exp = [ exp_name, attributes, [] ]
|
|
133
|
+
|
|
134
|
+
exp.last << string_child \
|
|
135
|
+
if string_child
|
|
136
|
+
|
|
137
|
+
if context.parent_expression
|
|
138
|
+
#
|
|
139
|
+
# adding this new expression to its parent
|
|
140
|
+
#
|
|
141
|
+
context.parent_expression.last << exp
|
|
142
|
+
else
|
|
143
|
+
#
|
|
144
|
+
# an orphan, a top expression
|
|
145
|
+
#
|
|
146
|
+
context.top_expressions << exp
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
return exp unless block
|
|
150
|
+
|
|
151
|
+
context.push_parent_expression exp
|
|
152
|
+
|
|
153
|
+
result = block.call
|
|
154
|
+
|
|
155
|
+
exp.last << result \
|
|
156
|
+
if result and result.kind_of?(String)
|
|
157
|
+
|
|
158
|
+
context.pop_parent_expression
|
|
159
|
+
|
|
160
|
+
exp
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def do_make
|
|
164
|
+
|
|
165
|
+
ProcessDefinition.do_make self
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
#
|
|
169
|
+
# A class method for actually "making" the process
|
|
170
|
+
# segment raw representation
|
|
171
|
+
#
|
|
172
|
+
def self.do_make (instance=nil)
|
|
173
|
+
|
|
174
|
+
context = if @ccontext
|
|
175
|
+
|
|
176
|
+
@ccontext.discard
|
|
177
|
+
# preventing further additions in case of reevaluation
|
|
178
|
+
@ccontext
|
|
179
|
+
|
|
180
|
+
elsif instance
|
|
181
|
+
|
|
182
|
+
instance.make
|
|
183
|
+
instance.context
|
|
184
|
+
else
|
|
185
|
+
|
|
186
|
+
pdef = self.new
|
|
187
|
+
pdef.make
|
|
188
|
+
pdef.context
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
return context.top_expression if context.top_expression
|
|
192
|
+
|
|
193
|
+
name, revision =
|
|
194
|
+
extract_name_and_revision(self.metaclass.to_s[8..-2])
|
|
195
|
+
|
|
196
|
+
top_expression = [
|
|
197
|
+
"process-definition",
|
|
198
|
+
{ "name" => name, "revision" => revision },
|
|
199
|
+
context.top_expressions
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
top_expression
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
#
|
|
206
|
+
# Parses the string to find the class name of the process definition
|
|
207
|
+
# and returns that class (instance).
|
|
208
|
+
#
|
|
209
|
+
def self.extract_class (ruby_proc_def_string)
|
|
210
|
+
|
|
211
|
+
ruby_proc_def_string.each_line do |l|
|
|
212
|
+
|
|
213
|
+
m = ClassNameRex.match l
|
|
214
|
+
|
|
215
|
+
return eval(m[1]) if m
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
nil
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
#
|
|
222
|
+
# Turns a String containing a ProcessDefinition ...
|
|
223
|
+
#
|
|
224
|
+
def self.eval_ruby_process_definition (code, safety_level=2)
|
|
225
|
+
|
|
226
|
+
# TODO : insert tree check
|
|
227
|
+
|
|
228
|
+
#puts "\nin:\n#{code}\n"
|
|
229
|
+
|
|
230
|
+
code, is_wrapped = wrap_code code
|
|
231
|
+
|
|
232
|
+
o = Rufus::eval_safely code, safety_level, binding()
|
|
233
|
+
|
|
234
|
+
o = extract_class(code) \
|
|
235
|
+
if (o == nil) or o.is_a?(Array)
|
|
236
|
+
#if (o == nil) or o.is_a?(SimpleExpRepresentation)
|
|
237
|
+
#
|
|
238
|
+
# grab the first process definition class found
|
|
239
|
+
# in the given code
|
|
240
|
+
|
|
241
|
+
#return o.do_make \
|
|
242
|
+
# if o.is_a?(ProcessDefinition) or o.is_a?(Class)
|
|
243
|
+
#o
|
|
244
|
+
|
|
245
|
+
result = o.do_make
|
|
246
|
+
|
|
247
|
+
#return result.first_child if is_wrapped
|
|
248
|
+
return result.last.first if is_wrapped
|
|
249
|
+
|
|
250
|
+
result
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
protected
|
|
254
|
+
|
|
255
|
+
ClassNameRex = Regexp.compile(
|
|
256
|
+
" *class *([a-zA-Z0-9]*) *< .*ProcessDefinition")
|
|
257
|
+
ProcessDefinitionRex = Regexp.compile(
|
|
258
|
+
"^class *[a-zA-Z0-9]* *< .*ProcessDefinition")
|
|
259
|
+
ProcessNameAndDefRex = Regexp.compile(
|
|
260
|
+
"([^0-9_]*)_*([0-9].*)$")
|
|
261
|
+
ProcessNameRex = Regexp.compile(
|
|
262
|
+
"(.*$)")
|
|
263
|
+
EndsInDefinitionRex = Regexp.compile(
|
|
264
|
+
".*Definition$")
|
|
265
|
+
|
|
266
|
+
def self.wrap_code (code)
|
|
267
|
+
|
|
268
|
+
return [ code, false ] if ProcessDefinitionRex.match(code)
|
|
269
|
+
|
|
270
|
+
s = "class NoName0 < ProcessDefinition"
|
|
271
|
+
s << "\n"
|
|
272
|
+
s << code
|
|
273
|
+
s << "\nend"
|
|
274
|
+
|
|
275
|
+
[ s, true ]
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def self.pack_args (args)
|
|
279
|
+
|
|
280
|
+
return args[0] if args.length == 1
|
|
281
|
+
|
|
282
|
+
a = {}
|
|
283
|
+
args.each_with_index do |arg, index|
|
|
284
|
+
if arg.is_a?(Hash)
|
|
285
|
+
a = a.merge(arg)
|
|
286
|
+
break
|
|
287
|
+
end
|
|
288
|
+
a[index.to_s] = arg
|
|
289
|
+
end
|
|
290
|
+
a
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def self.extract_name_and_revision (s)
|
|
294
|
+
|
|
295
|
+
i = s.rindex("::")
|
|
296
|
+
s = s[i+2..-1] if i
|
|
297
|
+
|
|
298
|
+
m = ProcessNameAndDefRex.match s
|
|
299
|
+
return [ as_name(m[1]), as_revision(m[2]) ] if m
|
|
300
|
+
|
|
301
|
+
m = ProcessNameRex.match s
|
|
302
|
+
return [ as_name(m[1]), '0' ] if m
|
|
303
|
+
|
|
304
|
+
[ as_name(s), '0' ]
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def self.as_name (s)
|
|
308
|
+
|
|
309
|
+
return s[0..-11] if EndsInDefinitionRex.match(s)
|
|
310
|
+
s
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def self.as_revision (s)
|
|
314
|
+
|
|
315
|
+
s.gsub("_", ".")
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
class Context
|
|
319
|
+
|
|
320
|
+
attr_accessor :parent_expression, :top_expressions
|
|
321
|
+
attr_reader :previous_parent_expressions
|
|
322
|
+
|
|
323
|
+
def initialize
|
|
324
|
+
@parent_expression = nil
|
|
325
|
+
@top_expressions = []
|
|
326
|
+
@previous_parent_expressions = []
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def discard
|
|
330
|
+
@discarded = true
|
|
331
|
+
end
|
|
332
|
+
def discarded?
|
|
333
|
+
(@discarded == true)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
#
|
|
337
|
+
# puts the current parent expression on top of the 'previous
|
|
338
|
+
# parent expressions' stack, the current parent expression
|
|
339
|
+
# is replaced with the supplied parent expression.
|
|
340
|
+
#
|
|
341
|
+
def push_parent_expression (exp)
|
|
342
|
+
|
|
343
|
+
@previous_parent_expressions.push(@parent_expression) \
|
|
344
|
+
if @parent_expression
|
|
345
|
+
|
|
346
|
+
@parent_expression = exp
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
#
|
|
350
|
+
# Replaces the current parent expression with the one found
|
|
351
|
+
# on the top of the previous parent expression stack (pop).
|
|
352
|
+
#
|
|
353
|
+
def pop_parent_expression
|
|
354
|
+
|
|
355
|
+
@parent_expression = @previous_parent_expressions.pop
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
#
|
|
359
|
+
# This method returns the top expression among the
|
|
360
|
+
# top expressions...
|
|
361
|
+
#
|
|
362
|
+
def top_expression
|
|
363
|
+
|
|
364
|
+
return nil if @top_expressions.size > 1
|
|
365
|
+
|
|
366
|
+
exp = @top_expressions.first
|
|
367
|
+
|
|
368
|
+
return exp if exp.first == "process-definition"
|
|
369
|
+
nil
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
end
|
|
375
|
+
|
|
@@ -0,0 +1,333 @@
|
|
|
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 'rufus/otime'
|
|
41
|
+
require 'openwfe/expressions/timeout'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
module OpenWFE
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# A parent class for CronExpression and SleepExpression, is never
|
|
48
|
+
# used directly.
|
|
49
|
+
# It contains a simple get_scheduler() method simplifying the scheduler
|
|
50
|
+
# localization for <sleep/> and <cron/>.
|
|
51
|
+
#
|
|
52
|
+
class TimeExpression < FlowExpression
|
|
53
|
+
include Rufus::Schedulable
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# The workitem received at apply time
|
|
57
|
+
#
|
|
58
|
+
attr_accessor :applied_workitem
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# The job_id in the scheduler for this expression
|
|
62
|
+
#
|
|
63
|
+
attr_accessor :scheduler_job_id
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# The tags (if any) for the job in the scheduler
|
|
67
|
+
#
|
|
68
|
+
attr_accessor :scheduler_tags
|
|
69
|
+
|
|
70
|
+
#
|
|
71
|
+
# Makes sure to cancel any scheduler job associated with this
|
|
72
|
+
# expression
|
|
73
|
+
#
|
|
74
|
+
def cancel
|
|
75
|
+
#synchronize do
|
|
76
|
+
|
|
77
|
+
ldebug { "cancel()..." }
|
|
78
|
+
|
|
79
|
+
unschedule
|
|
80
|
+
|
|
81
|
+
super()
|
|
82
|
+
|
|
83
|
+
@applied_workitem
|
|
84
|
+
#end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# If the expression has been scheduled, a call to this method
|
|
89
|
+
# will make sure it's unscheduled (removed from the scheduler).
|
|
90
|
+
#
|
|
91
|
+
def unschedule
|
|
92
|
+
|
|
93
|
+
ldebug { "unschedule() @scheduler_job_id is #{@scheduler_job_id}" }
|
|
94
|
+
|
|
95
|
+
sleep get_scheduler.precision + 0.001
|
|
96
|
+
#
|
|
97
|
+
# make sure not to unschedule before the actual scheduling
|
|
98
|
+
# got done.
|
|
99
|
+
|
|
100
|
+
get_scheduler.unschedule(@scheduler_job_id) \
|
|
101
|
+
if @scheduler_job_id
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
protected
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
# looks up potential scheduler tags in the expression
|
|
108
|
+
# attributes
|
|
109
|
+
#
|
|
110
|
+
def determine_scheduler_tags
|
|
111
|
+
|
|
112
|
+
@scheduler_tags = lookup_array_attribute(
|
|
113
|
+
:scheduler_tags, @applied_workitem) || []
|
|
114
|
+
|
|
115
|
+
@scheduler_tags << self.class.name
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
#
|
|
120
|
+
# A parent class for WhenExpression and WaitExpression.
|
|
121
|
+
#
|
|
122
|
+
# All the code for managing waiting for something to occur is
|
|
123
|
+
# concentrated here.
|
|
124
|
+
#
|
|
125
|
+
class WaitingExpression < TimeExpression
|
|
126
|
+
include ConditionMixin
|
|
127
|
+
include TimeoutMixin
|
|
128
|
+
|
|
129
|
+
attr_accessor :frequency
|
|
130
|
+
|
|
131
|
+
uses_template
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# By default, classes extending this class do poll for their
|
|
135
|
+
# condition every 10 seconds.
|
|
136
|
+
#
|
|
137
|
+
DEFAULT_FREQUENCY = "10s"
|
|
138
|
+
|
|
139
|
+
#
|
|
140
|
+
# Don't go under 300 milliseconds.
|
|
141
|
+
#
|
|
142
|
+
MIN_FREQUENCY = 0.300
|
|
143
|
+
|
|
144
|
+
#
|
|
145
|
+
# Classes extending this WaitingExpression have a 'conditions' class
|
|
146
|
+
# method (like 'attr_accessor').
|
|
147
|
+
#
|
|
148
|
+
def self.conditions (*attnames)
|
|
149
|
+
|
|
150
|
+
attnames = attnames.collect do |n|
|
|
151
|
+
n.to_s.to_sym
|
|
152
|
+
end
|
|
153
|
+
meta_def :condition_attributes do
|
|
154
|
+
attnames
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def apply (workitem)
|
|
159
|
+
|
|
160
|
+
remove_timedout_flag workitem
|
|
161
|
+
|
|
162
|
+
@applied_workitem = workitem.dup
|
|
163
|
+
|
|
164
|
+
@frequency = lookup_attribute(
|
|
165
|
+
:frequency, workitem, :default => DEFAULT_FREQUENCY)
|
|
166
|
+
@frequency = Rufus::parse_time_string(
|
|
167
|
+
@frequency)
|
|
168
|
+
@frequency = MIN_FREQUENCY \
|
|
169
|
+
if @frequency < MIN_FREQUENCY
|
|
170
|
+
|
|
171
|
+
determine_timeout
|
|
172
|
+
determine_scheduler_tags
|
|
173
|
+
|
|
174
|
+
condition_attribute = determine_condition_attribute(
|
|
175
|
+
self.class.condition_attributes)
|
|
176
|
+
|
|
177
|
+
#
|
|
178
|
+
# register consequence
|
|
179
|
+
|
|
180
|
+
consequence = condition_attribute ?
|
|
181
|
+
raw_children[0] : raw_children[1]
|
|
182
|
+
|
|
183
|
+
get_expression_pool.tprepare_child(
|
|
184
|
+
self,
|
|
185
|
+
consequence,
|
|
186
|
+
0,
|
|
187
|
+
true, # please register child
|
|
188
|
+
nil # no vars
|
|
189
|
+
) if consequence
|
|
190
|
+
|
|
191
|
+
#
|
|
192
|
+
# go east...
|
|
193
|
+
|
|
194
|
+
store_itself
|
|
195
|
+
|
|
196
|
+
trigger
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def reply (workitem)
|
|
200
|
+
|
|
201
|
+
result = workitem.get_result
|
|
202
|
+
|
|
203
|
+
if result
|
|
204
|
+
apply_consequence workitem
|
|
205
|
+
else
|
|
206
|
+
reschedule get_scheduler
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
#
|
|
211
|
+
# Cancels this expression (takes care of unscheduling a timeout
|
|
212
|
+
# if there is one).
|
|
213
|
+
#
|
|
214
|
+
def cancel
|
|
215
|
+
|
|
216
|
+
unschedule_timeout
|
|
217
|
+
super()
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def trigger (params={})
|
|
221
|
+
|
|
222
|
+
ldebug { "trigger() #{@fei.to_debug_s} params : #{params.inspect}" }
|
|
223
|
+
|
|
224
|
+
if params[:do_timeout!]
|
|
225
|
+
#
|
|
226
|
+
# do timeout...
|
|
227
|
+
#
|
|
228
|
+
set_timedout_flag @applied_workitem
|
|
229
|
+
reply_to_parent @applied_workitem
|
|
230
|
+
return
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
@scheduler_job_id = nil
|
|
234
|
+
|
|
235
|
+
evaluate_condition
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def reschedule (scheduler)
|
|
239
|
+
|
|
240
|
+
@scheduler_job_id = "waiting_#{fei.to_s}"
|
|
241
|
+
|
|
242
|
+
scheduler.schedule_in(
|
|
243
|
+
@frequency,
|
|
244
|
+
{
|
|
245
|
+
:schedulable => self,
|
|
246
|
+
:job_id => @scheduler_job_id,
|
|
247
|
+
:tags => @scheduler_tags })
|
|
248
|
+
|
|
249
|
+
ldebug { "reschedule() @scheduler_job_id is #{@scheduler_job_id}" }
|
|
250
|
+
|
|
251
|
+
to_reschedule scheduler
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def reply_to_parent (workitem)
|
|
255
|
+
|
|
256
|
+
unschedule
|
|
257
|
+
unschedule_timeout
|
|
258
|
+
|
|
259
|
+
super workitem
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
protected
|
|
263
|
+
|
|
264
|
+
#
|
|
265
|
+
# The code for the condition evalution is here.
|
|
266
|
+
#
|
|
267
|
+
# This method is overriden by the WhenExpression.
|
|
268
|
+
#
|
|
269
|
+
def evaluate_condition
|
|
270
|
+
|
|
271
|
+
condition_attribute = determine_condition_attribute(
|
|
272
|
+
self.class.condition_attributes)
|
|
273
|
+
|
|
274
|
+
if condition_attribute
|
|
275
|
+
|
|
276
|
+
c = eval_condition condition_attribute, @applied_workitem
|
|
277
|
+
|
|
278
|
+
do_reply c
|
|
279
|
+
return
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# else, condition is nested as a child
|
|
283
|
+
|
|
284
|
+
#if @children.size < 1
|
|
285
|
+
if raw_children.size < 1
|
|
286
|
+
#
|
|
287
|
+
# no condition attribute and no child attribute,
|
|
288
|
+
# simply reply to parent
|
|
289
|
+
#
|
|
290
|
+
reply_to_parent @applied_workitem
|
|
291
|
+
return
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# trigger the first child (the condition child)
|
|
295
|
+
|
|
296
|
+
#get_expression_pool.launch_template(
|
|
297
|
+
# self,
|
|
298
|
+
# @environment_id,
|
|
299
|
+
# @condition_sub_id,
|
|
300
|
+
# @children[0],
|
|
301
|
+
# @applied_workitem)
|
|
302
|
+
get_expression_pool.tlaunch_child(
|
|
303
|
+
self,
|
|
304
|
+
raw_children.first,
|
|
305
|
+
(Time.new.to_f * 1000).to_i,
|
|
306
|
+
@applied_workitem.dup,
|
|
307
|
+
false) # not registering as a child
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
#
|
|
311
|
+
# Used when replying to self after an attribute condition
|
|
312
|
+
# got evaluated
|
|
313
|
+
#
|
|
314
|
+
def do_reply (result)
|
|
315
|
+
|
|
316
|
+
@applied_workitem.set_result result
|
|
317
|
+
reply @applied_workitem
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
#
|
|
321
|
+
# This method is overriden by WhenExpression. WaitExpression
|
|
322
|
+
# doesn't override it.
|
|
323
|
+
# This default implementation simply directly replies to
|
|
324
|
+
# the parent expression.
|
|
325
|
+
#
|
|
326
|
+
def apply_consequence (workitem)
|
|
327
|
+
|
|
328
|
+
reply_to_parent workitem
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
end
|
|
333
|
+
|