ruote-maestrodev 2.2.1
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/CHANGELOG.txt +290 -0
- data/CREDITS.txt +99 -0
- data/LICENSE.txt +21 -0
- data/README.rdoc +88 -0
- data/Rakefile +108 -0
- data/TODO.txt +488 -0
- data/lib/ruote.rb +7 -0
- data/lib/ruote/context.rb +194 -0
- data/lib/ruote/engine.rb +1062 -0
- data/lib/ruote/engine/process_error.rb +122 -0
- data/lib/ruote/engine/process_status.rb +448 -0
- data/lib/ruote/exp/command.rb +87 -0
- data/lib/ruote/exp/commanded.rb +69 -0
- data/lib/ruote/exp/condition.rb +227 -0
- data/lib/ruote/exp/fe_add_branches.rb +138 -0
- data/lib/ruote/exp/fe_apply.rb +154 -0
- data/lib/ruote/exp/fe_cancel_process.rb +78 -0
- data/lib/ruote/exp/fe_command.rb +156 -0
- data/lib/ruote/exp/fe_concurrence.rb +321 -0
- data/lib/ruote/exp/fe_concurrent_iterator.rb +219 -0
- data/lib/ruote/exp/fe_cron.rb +141 -0
- data/lib/ruote/exp/fe_cursor.rb +324 -0
- data/lib/ruote/exp/fe_define.rb +112 -0
- data/lib/ruote/exp/fe_echo.rb +60 -0
- data/lib/ruote/exp/fe_equals.rb +115 -0
- data/lib/ruote/exp/fe_error.rb +82 -0
- data/lib/ruote/exp/fe_filter.rb +648 -0
- data/lib/ruote/exp/fe_forget.rb +88 -0
- data/lib/ruote/exp/fe_given.rb +154 -0
- data/lib/ruote/exp/fe_if.rb +127 -0
- data/lib/ruote/exp/fe_inc.rb +205 -0
- data/lib/ruote/exp/fe_iterator.rb +234 -0
- data/lib/ruote/exp/fe_let.rb +75 -0
- data/lib/ruote/exp/fe_listen.rb +304 -0
- data/lib/ruote/exp/fe_lose.rb +110 -0
- data/lib/ruote/exp/fe_noop.rb +45 -0
- data/lib/ruote/exp/fe_once.rb +215 -0
- data/lib/ruote/exp/fe_participant.rb +287 -0
- data/lib/ruote/exp/fe_read.rb +69 -0
- data/lib/ruote/exp/fe_redo.rb +82 -0
- data/lib/ruote/exp/fe_ref.rb +152 -0
- data/lib/ruote/exp/fe_registerp.rb +110 -0
- data/lib/ruote/exp/fe_reserve.rb +126 -0
- data/lib/ruote/exp/fe_restore.rb +102 -0
- data/lib/ruote/exp/fe_save.rb +72 -0
- data/lib/ruote/exp/fe_sequence.rb +59 -0
- data/lib/ruote/exp/fe_set.rb +154 -0
- data/lib/ruote/exp/fe_subprocess.rb +211 -0
- data/lib/ruote/exp/fe_that.rb +92 -0
- data/lib/ruote/exp/fe_undo.rb +67 -0
- data/lib/ruote/exp/fe_unregisterp.rb +69 -0
- data/lib/ruote/exp/fe_wait.rb +95 -0
- data/lib/ruote/exp/flowexpression.rb +886 -0
- data/lib/ruote/exp/iterator.rb +81 -0
- data/lib/ruote/exp/merge.rb +118 -0
- data/lib/ruote/exp/ro_attributes.rb +212 -0
- data/lib/ruote/exp/ro_filters.rb +136 -0
- data/lib/ruote/exp/ro_persist.rb +154 -0
- data/lib/ruote/exp/ro_variables.rb +189 -0
- data/lib/ruote/exp/ro_vf.rb +68 -0
- data/lib/ruote/fei.rb +260 -0
- data/lib/ruote/id/mnemo_wfid_generator.rb +43 -0
- data/lib/ruote/id/wfid_generator.rb +81 -0
- data/lib/ruote/log/default_history.rb +122 -0
- data/lib/ruote/log/pretty.rb +176 -0
- data/lib/ruote/log/storage_history.rb +159 -0
- data/lib/ruote/log/test_logger.rb +208 -0
- data/lib/ruote/log/wait_logger.rb +64 -0
- data/lib/ruote/part/block_participant.rb +137 -0
- data/lib/ruote/part/code_participant.rb +81 -0
- data/lib/ruote/part/engine_participant.rb +189 -0
- data/lib/ruote/part/local_participant.rb +138 -0
- data/lib/ruote/part/no_op_participant.rb +60 -0
- data/lib/ruote/part/null_participant.rb +54 -0
- data/lib/ruote/part/rev_participant.rb +169 -0
- data/lib/ruote/part/smtp_participant.rb +116 -0
- data/lib/ruote/part/storage_participant.rb +392 -0
- data/lib/ruote/part/template.rb +84 -0
- data/lib/ruote/participant.rb +7 -0
- data/lib/ruote/reader.rb +278 -0
- data/lib/ruote/reader/json.rb +49 -0
- data/lib/ruote/reader/radial.rb +290 -0
- data/lib/ruote/reader/ruby_dsl.rb +186 -0
- data/lib/ruote/reader/xml.rb +99 -0
- data/lib/ruote/receiver/base.rb +212 -0
- data/lib/ruote/storage/base.rb +364 -0
- data/lib/ruote/storage/composite_storage.rb +121 -0
- data/lib/ruote/storage/fs_storage.rb +139 -0
- data/lib/ruote/storage/hash_storage.rb +211 -0
- data/lib/ruote/svc/dispatch_pool.rb +158 -0
- data/lib/ruote/svc/dollar_sub.rb +298 -0
- data/lib/ruote/svc/error_handler.rb +138 -0
- data/lib/ruote/svc/expression_map.rb +97 -0
- data/lib/ruote/svc/participant_list.rb +397 -0
- data/lib/ruote/svc/tracker.rb +172 -0
- data/lib/ruote/svc/treechecker.rb +141 -0
- data/lib/ruote/tree_dot.rb +85 -0
- data/lib/ruote/util/filter.rb +525 -0
- data/lib/ruote/util/hashdot.rb +79 -0
- data/lib/ruote/util/look.rb +128 -0
- data/lib/ruote/util/lookup.rb +127 -0
- data/lib/ruote/util/misc.rb +167 -0
- data/lib/ruote/util/ometa.rb +71 -0
- data/lib/ruote/util/serializer.rb +103 -0
- data/lib/ruote/util/subprocess.rb +88 -0
- data/lib/ruote/util/time.rb +100 -0
- data/lib/ruote/util/tree.rb +58 -0
- data/lib/ruote/version.rb +29 -0
- data/lib/ruote/worker.rb +386 -0
- data/lib/ruote/workitem.rb +394 -0
- data/phil.txt +14 -0
- data/ruote.gemspec +44 -0
- data/test/bm/ci.rb +55 -0
- data/test/bm/ici.rb +71 -0
- data/test/bm/juuman.rb +54 -0
- data/test/bm/launch_bench.rb +37 -0
- data/test/bm/load_26c.rb +97 -0
- data/test/bm/mega.rb +64 -0
- data/test/bm/seq_thousand.rb +31 -0
- data/test/bm/t.rb +35 -0
- data/test/functional/base.rb +247 -0
- data/test/functional/concurrent_base.rb +98 -0
- data/test/functional/crunner.rb +31 -0
- data/test/functional/ct_0_concurrence.rb +65 -0
- data/test/functional/ct_1_iterator.rb +67 -0
- data/test/functional/ct_2_cancel.rb +81 -0
- data/test/functional/eft_0_process_definition.rb +65 -0
- data/test/functional/eft_10_cancel_process.rb +46 -0
- data/test/functional/eft_11_wait.rb +109 -0
- data/test/functional/eft_12_listen.rb +500 -0
- data/test/functional/eft_13_iterator.rb +342 -0
- data/test/functional/eft_14_cursor.rb +456 -0
- data/test/functional/eft_15_loop.rb +69 -0
- data/test/functional/eft_16_if.rb +183 -0
- data/test/functional/eft_17_equals.rb +55 -0
- data/test/functional/eft_18_concurrent_iterator.rb +410 -0
- data/test/functional/eft_19_reserve.rb +136 -0
- data/test/functional/eft_1_echo.rb +68 -0
- data/test/functional/eft_20_save.rb +116 -0
- data/test/functional/eft_21_restore.rb +61 -0
- data/test/functional/eft_22_noop.rb +28 -0
- data/test/functional/eft_23_apply.rb +168 -0
- data/test/functional/eft_24_add_branches.rb +98 -0
- data/test/functional/eft_25_command.rb +28 -0
- data/test/functional/eft_26_error.rb +77 -0
- data/test/functional/eft_27_inc.rb +280 -0
- data/test/functional/eft_28_once.rb +135 -0
- data/test/functional/eft_29_cron.rb +64 -0
- data/test/functional/eft_2_sequence.rb +58 -0
- data/test/functional/eft_30_ref.rb +155 -0
- data/test/functional/eft_31_registerp.rb +130 -0
- data/test/functional/eft_32_lose.rb +93 -0
- data/test/functional/eft_33_let.rb +31 -0
- data/test/functional/eft_34_given.rb +123 -0
- data/test/functional/eft_35_filter.rb +375 -0
- data/test/functional/eft_36_read.rb +95 -0
- data/test/functional/eft_3_participant.rb +149 -0
- data/test/functional/eft_4_set.rb +296 -0
- data/test/functional/eft_5_subprocess.rb +163 -0
- data/test/functional/eft_6_concurrence.rb +304 -0
- data/test/functional/eft_7_forget.rb +61 -0
- data/test/functional/eft_8_undo.rb +114 -0
- data/test/functional/eft_9_redo.rb +138 -0
- data/test/functional/ft_0_worker.rb +65 -0
- data/test/functional/ft_10_dollar.rb +304 -0
- data/test/functional/ft_11_recursion.rb +109 -0
- data/test/functional/ft_12_launchitem.rb +43 -0
- data/test/functional/ft_13_variables.rb +151 -0
- data/test/functional/ft_14_re_apply.rb +324 -0
- data/test/functional/ft_15_timeout.rb +226 -0
- data/test/functional/ft_16_participant_params.rb +98 -0
- data/test/functional/ft_17_conditional.rb +102 -0
- data/test/functional/ft_18_kill.rb +138 -0
- data/test/functional/ft_19_participant_code.rb +67 -0
- data/test/functional/ft_1_process_status.rb +796 -0
- data/test/functional/ft_20_storage_participant.rb +543 -0
- data/test/functional/ft_21_forget.rb +153 -0
- data/test/functional/ft_22_process_definitions.rb +90 -0
- data/test/functional/ft_23_load_defs.rb +79 -0
- data/test/functional/ft_24_block_participant.rb +235 -0
- data/test/functional/ft_25_receiver.rb +207 -0
- data/test/functional/ft_26_participant_rtimeout.rb +179 -0
- data/test/functional/ft_27_var_indirection.rb +128 -0
- data/test/functional/ft_28_null_noop_participants.rb +51 -0
- data/test/functional/ft_29_part_template.rb +60 -0
- data/test/functional/ft_2_errors.rb +380 -0
- data/test/functional/ft_30_smtp_participant.rb +122 -0
- data/test/functional/ft_31_part_blocking.rb +72 -0
- data/test/functional/ft_33_participant_subprocess_priority.rb +32 -0
- data/test/functional/ft_34_cursor_rewind.rb +101 -0
- data/test/functional/ft_35_add_service.rb +56 -0
- data/test/functional/ft_36_storage_history.rb +150 -0
- data/test/functional/ft_37_default_history.rb +109 -0
- data/test/functional/ft_38_participant_more.rb +193 -0
- data/test/functional/ft_39_wait_for.rb +136 -0
- data/test/functional/ft_3_participant_registration.rb +574 -0
- data/test/functional/ft_40_wait_logger.rb +62 -0
- data/test/functional/ft_41_participants.rb +91 -0
- data/test/functional/ft_42_storage_copy.rb +71 -0
- data/test/functional/ft_43_participant_on_reply.rb +87 -0
- data/test/functional/ft_44_var_participant.rb +35 -0
- data/test/functional/ft_45_participant_accept.rb +64 -0
- data/test/functional/ft_46_launch_single.rb +83 -0
- data/test/functional/ft_47_wfid_generator.rb +54 -0
- data/test/functional/ft_48_lose.rb +112 -0
- data/test/functional/ft_49_engine_on_error.rb +201 -0
- data/test/functional/ft_4_cancel.rb +132 -0
- data/test/functional/ft_50_engine_config.rb +22 -0
- data/test/functional/ft_51_misc.rb +67 -0
- data/test/functional/ft_52_case.rb +134 -0
- data/test/functional/ft_53_engine_on_terminate.rb +95 -0
- data/test/functional/ft_54_patterns.rb +104 -0
- data/test/functional/ft_55_engine_participant.rb +303 -0
- data/test/functional/ft_56_filter_attribute.rb +259 -0
- data/test/functional/ft_57_rev_participant.rb +252 -0
- data/test/functional/ft_58_workitem.rb +69 -0
- data/test/functional/ft_59_pause.rb +343 -0
- data/test/functional/ft_5_on_error.rb +384 -0
- data/test/functional/ft_60_code_participant.rb +45 -0
- data/test/functional/ft_61_trailing_fields.rb +34 -0
- data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
- data/test/functional/ft_6_on_cancel.rb +221 -0
- data/test/functional/ft_7_tags.rb +177 -0
- data/test/functional/ft_8_participant_consumption.rb +124 -0
- data/test/functional/ft_9_subprocesses.rb +146 -0
- data/test/functional/restart_base.rb +34 -0
- data/test/functional/rt_0_wait.rb +55 -0
- data/test/functional/rt_1_listen.rb +56 -0
- data/test/functional/rt_2_errors.rb +56 -0
- data/test/functional/rt_3_once.rb +70 -0
- data/test/functional/rt_4_cron.rb +64 -0
- data/test/functional/rt_5_timeout.rb +60 -0
- data/test/functional/rtest.rb +8 -0
- data/test/functional/storage_helper.rb +93 -0
- data/test/functional/test.rb +44 -0
- data/test/functional/vertical.rb +46 -0
- data/test/path_helper.rb +15 -0
- data/test/test.rb +13 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/storage.rb +428 -0
- data/test/unit/storages.rb +37 -0
- data/test/unit/test.rb +28 -0
- data/test/unit/ut_0_ruby_reader.rb +223 -0
- data/test/unit/ut_11_lookup.rb +122 -0
- data/test/unit/ut_13_serializer.rb +65 -0
- data/test/unit/ut_14_is_uri.rb +28 -0
- data/test/unit/ut_15_util.rb +57 -0
- data/test/unit/ut_16_reader.rb +225 -0
- data/test/unit/ut_18_engine.rb +47 -0
- data/test/unit/ut_19_part_template.rb +86 -0
- data/test/unit/ut_1_fei.rb +165 -0
- data/test/unit/ut_20_composite_storage.rb +74 -0
- data/test/unit/ut_21_svc_participant_list.rb +46 -0
- data/test/unit/ut_22_filter.rb +1094 -0
- data/test/unit/ut_23_svc_tracker.rb +48 -0
- data/test/unit/ut_24_radial_reader.rb +332 -0
- data/test/unit/ut_25_merge.rb +113 -0
- data/test/unit/ut_3_wait_logger.rb +39 -0
- data/test/unit/ut_4_expmap.rb +20 -0
- data/test/unit/ut_5_tree.rb +54 -0
- data/test/unit/ut_6_condition.rb +303 -0
- data/test/unit/ut_7_workitem.rb +99 -0
- data/test/unit/ut_8_tree_to_dot.rb +72 -0
- data/test/unit/ut_9_xml_reader.rb +61 -0
- metadata +504 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
module Ruote::Exp
|
27
|
+
|
28
|
+
#
|
29
|
+
# Reopening the FlowExpression class to add [un]persist methods.
|
30
|
+
#
|
31
|
+
class FlowExpression
|
32
|
+
|
33
|
+
#--
|
34
|
+
# PERSISTENCE
|
35
|
+
#++
|
36
|
+
|
37
|
+
# Persists and fetches the _rev identifier from the storage.
|
38
|
+
#
|
39
|
+
# Only used by the worker when creating the expression.
|
40
|
+
#
|
41
|
+
def initial_persist
|
42
|
+
|
43
|
+
r = @context.storage.put(@h, :update_rev => true)
|
44
|
+
|
45
|
+
#t = Thread.current.object_id.to_s[-3..-1]
|
46
|
+
#puts "+ per #{h.fei['expid']} #{tree[0]} r#{h._rev} t#{t} -> #{r.class}"
|
47
|
+
#Ruote.p_caller('+ per')
|
48
|
+
|
49
|
+
raise_or_return('initial_persist failed', r)
|
50
|
+
end
|
51
|
+
|
52
|
+
def try_persist
|
53
|
+
|
54
|
+
r = @context.storage.put(@h)
|
55
|
+
|
56
|
+
#t = Thread.current.object_id.to_s[-3..-1]
|
57
|
+
#puts "+ per #{h.fei['expid']} #{tree[0]} r#{h._rev} t#{t} -> #{r.class}"
|
58
|
+
#Ruote.p_caller('+ per')
|
59
|
+
|
60
|
+
r
|
61
|
+
end
|
62
|
+
|
63
|
+
def try_unpersist
|
64
|
+
|
65
|
+
r = @context.storage.delete(@h)
|
66
|
+
|
67
|
+
#t = Thread.current.object_id.to_s[-3..-1]
|
68
|
+
#puts "- unp #{h.fei['expid']} #{tree[0]} r#{h._rev} t#{t} -> #{r.class}"
|
69
|
+
#Ruote.p_caller('- unp')
|
70
|
+
|
71
|
+
return r if r
|
72
|
+
|
73
|
+
#if h.has_error
|
74
|
+
err = @context.storage.get('errors', "err_#{Ruote.to_storage_id(h.fei)}")
|
75
|
+
@context.storage.delete(err) if err
|
76
|
+
#end
|
77
|
+
# removes any error in the journal for this expression
|
78
|
+
# since it will now be gone, no need to keep track of its errors
|
79
|
+
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def persist_or_raise
|
84
|
+
|
85
|
+
p_or_raise(true)
|
86
|
+
end
|
87
|
+
|
88
|
+
def unpersist_or_raise
|
89
|
+
|
90
|
+
p_or_raise(false)
|
91
|
+
end
|
92
|
+
|
93
|
+
alias persist persist_or_raise
|
94
|
+
alias unpersist unpersist_or_raise
|
95
|
+
|
96
|
+
def do_persist
|
97
|
+
|
98
|
+
do_p(true)
|
99
|
+
end
|
100
|
+
|
101
|
+
def do_unpersist
|
102
|
+
|
103
|
+
do_p(false)
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
def raise_or_return(msg, r)
|
109
|
+
|
110
|
+
msg = msg.is_a?(String) ?
|
111
|
+
msg : (msg ? 'persist' : 'unpersist') + ' failed'
|
112
|
+
|
113
|
+
raise(
|
114
|
+
"#{msg} for " +
|
115
|
+
"#{Ruote.to_storage_id(h.fei)} #{tree[0]} #{tree[1].inspect} " +
|
116
|
+
'r(' + (r == true ? 'gone' : "rev : #{r['_rev']}") + ')'
|
117
|
+
) if r
|
118
|
+
|
119
|
+
r
|
120
|
+
end
|
121
|
+
|
122
|
+
# Does persist or unpersist, returns nothing in particular.
|
123
|
+
#
|
124
|
+
# Will raise a runtime error if it fails (ie if it happens, there
|
125
|
+
# is something wrong with the storage implementation or the engine).
|
126
|
+
#
|
127
|
+
def p_or_raise(pers)
|
128
|
+
|
129
|
+
r = pers ? try_persist : try_unpersist
|
130
|
+
|
131
|
+
raise_or_return(pers, r)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Does persist or unpersist, if successful then return true. If the
|
135
|
+
# expression is gone, return false.
|
136
|
+
# If there is a 'fresher' version of the expression, re-attempt and return
|
137
|
+
# false.
|
138
|
+
#
|
139
|
+
def do_p(pers)
|
140
|
+
|
141
|
+
case r = pers ? try_persist : try_unpersist
|
142
|
+
when true
|
143
|
+
false # do not go on
|
144
|
+
when Hash
|
145
|
+
self.h = r
|
146
|
+
self.send("do_#{@msg['action']}", @msg)
|
147
|
+
false # do not go on
|
148
|
+
else
|
149
|
+
true # success, do go on
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
@@ -0,0 +1,189 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
module Ruote::Exp
|
27
|
+
|
28
|
+
#
|
29
|
+
# 're-opening' the FlowExpression class to add the methods about variables.
|
30
|
+
#
|
31
|
+
class FlowExpression
|
32
|
+
|
33
|
+
# A shortcut to the variables held in the expression (nil if none held).
|
34
|
+
#
|
35
|
+
def variables
|
36
|
+
|
37
|
+
@h['variables']
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a fresh hash of all the variables visible from this expression.
|
41
|
+
#
|
42
|
+
# This is used mainly when forgetting an expression.
|
43
|
+
#
|
44
|
+
def compile_variables
|
45
|
+
|
46
|
+
vars = h.parent_id ? parent.compile_variables : {}
|
47
|
+
vars.merge!(h.variables) if h.variables
|
48
|
+
|
49
|
+
vars
|
50
|
+
end
|
51
|
+
|
52
|
+
# Looks up the value of a variable in expression tree
|
53
|
+
# (seen from a leaf, it looks more like a stack than a tree)
|
54
|
+
#
|
55
|
+
def lookup_variable(var, prefix=nil)
|
56
|
+
|
57
|
+
var, prefix = split_prefix(var, prefix)
|
58
|
+
|
59
|
+
return @context.storage.get_engine_variable(var) \
|
60
|
+
if prefix.length >= 2
|
61
|
+
|
62
|
+
return parent.lookup_variable(var, prefix) \
|
63
|
+
if h.parent_id && prefix.length >= 1
|
64
|
+
|
65
|
+
if h.variables
|
66
|
+
|
67
|
+
val = Ruote.lookup(h.variables, var)
|
68
|
+
|
69
|
+
return val if val != nil
|
70
|
+
end
|
71
|
+
|
72
|
+
if h.parent_id && h.parent_id['engine_id'] == @context.engine_id
|
73
|
+
#
|
74
|
+
# do not lookup variables in a remote engine ...
|
75
|
+
|
76
|
+
(return parent.lookup_variable(var, prefix)) rescue nil
|
77
|
+
# if the lookup fails (parent gone) then rescue and let go
|
78
|
+
end
|
79
|
+
|
80
|
+
@context.storage.get_engine_variable(var)
|
81
|
+
end
|
82
|
+
|
83
|
+
# A shortcut for #lookup_variable
|
84
|
+
#
|
85
|
+
alias :v :lookup_variable
|
86
|
+
|
87
|
+
# A shortcut for #lookup_variable
|
88
|
+
#
|
89
|
+
alias :lv :lookup_variable
|
90
|
+
|
91
|
+
# Sets a variable to a given value.
|
92
|
+
# (will set at the appropriate level).
|
93
|
+
#
|
94
|
+
def set_variable(var, val)
|
95
|
+
|
96
|
+
fexp, v = locate_var(var)
|
97
|
+
|
98
|
+
fexp.un_set_variable(:set, v, val, (fexp.h.fei != h.fei)) if fexp
|
99
|
+
end
|
100
|
+
|
101
|
+
# Unbinds a variables.
|
102
|
+
#
|
103
|
+
def unset_variable(var)
|
104
|
+
|
105
|
+
fexp, v = locate_var(var)
|
106
|
+
|
107
|
+
fexp.un_set_variable(:unset, v, nil, (fexp.h.fei != h.fei)) if fexp
|
108
|
+
end
|
109
|
+
|
110
|
+
# TODO : redoc rewrite needed
|
111
|
+
#
|
112
|
+
# This method is mostly used by the worker when looking up
|
113
|
+
# a process name or participant name bound under a variable.
|
114
|
+
#
|
115
|
+
def iterative_var_lookup(k)
|
116
|
+
|
117
|
+
v = lookup_variable(k)
|
118
|
+
|
119
|
+
return [ k, v ] unless (v.is_a?(String) or v.is_a?(Symbol))
|
120
|
+
|
121
|
+
iterative_var_lookup(v)
|
122
|
+
end
|
123
|
+
|
124
|
+
protected
|
125
|
+
|
126
|
+
# Sets (or unsets) the value of a local variable
|
127
|
+
#
|
128
|
+
# val should be nil in case of 'unset'.
|
129
|
+
#
|
130
|
+
def un_set_variable(op, var, val, should_persist)
|
131
|
+
|
132
|
+
if op == :set
|
133
|
+
Ruote.set(h.variables, var, val)
|
134
|
+
else # op == :unset
|
135
|
+
Ruote.unset(h.variables, var)
|
136
|
+
end
|
137
|
+
|
138
|
+
if should_persist && r = try_persist # persist failed, have to retry
|
139
|
+
|
140
|
+
@h = r
|
141
|
+
un_set_variable(op, var, val, true)
|
142
|
+
|
143
|
+
else # success (even when should_persist == false)
|
144
|
+
|
145
|
+
@context.storage.put_msg("variable_#{op}", 'var' => var, 'fei' => h.fei)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
VAR_PREFIX_REGEX = /^(\/*)/
|
150
|
+
|
151
|
+
# Used by lookup_variable and set_variable to extract the
|
152
|
+
# prefix in a variable name
|
153
|
+
#
|
154
|
+
def split_prefix(var, prefix)
|
155
|
+
|
156
|
+
if prefix.nil?
|
157
|
+
var = var.to_s
|
158
|
+
m = VAR_PREFIX_REGEX.match(var)
|
159
|
+
prefix = m ? m[1][0, 2] : ''
|
160
|
+
var = var[prefix.length..-1]
|
161
|
+
end
|
162
|
+
|
163
|
+
[ var, prefix ]
|
164
|
+
end
|
165
|
+
|
166
|
+
# Returns the flow expression that owns a variable (or the one
|
167
|
+
# that should own it) and the var without its potential / prefixes.
|
168
|
+
#
|
169
|
+
def locate_var(var, prefix=nil)
|
170
|
+
|
171
|
+
var, prefix = split_prefix(var, prefix)
|
172
|
+
|
173
|
+
return nil if prefix.length >= 2 # engine variable
|
174
|
+
return parent.locate_var(var, prefix) if prefix.length == 1 && h.parent_id
|
175
|
+
|
176
|
+
# no prefix...
|
177
|
+
|
178
|
+
return [ self, var ] if h.variables
|
179
|
+
|
180
|
+
if par = parent
|
181
|
+
return parent.locate_var(var, prefix) rescue nil
|
182
|
+
end
|
183
|
+
|
184
|
+
#raise "uprooted var lookup, something went wrong"
|
185
|
+
[ nil, nil ]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
module Ruote::Exp
|
27
|
+
|
28
|
+
#
|
29
|
+
# 're-opening' the FlowExpression class to add methods like set_vf and co.
|
30
|
+
#
|
31
|
+
class FlowExpression
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def set_v(key, value, unset=false)
|
36
|
+
|
37
|
+
if unset
|
38
|
+
unset_variable(key)
|
39
|
+
else
|
40
|
+
set_variable(key, value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_f(key, value, unset=false)
|
45
|
+
|
46
|
+
if unset
|
47
|
+
h.applied_workitem['fields'].delete(key)
|
48
|
+
else
|
49
|
+
Ruote.set(h.applied_workitem['fields'], key, value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
PREFIX_REGEX = /^([^:]+):(.+)$/
|
54
|
+
F_PREFIX_REGEX = /^f/
|
55
|
+
|
56
|
+
def set_vf(key, value, unset=false)
|
57
|
+
|
58
|
+
field, key = if m = PREFIX_REGEX.match(key)
|
59
|
+
[ F_PREFIX_REGEX.match(m[1]), m[2] ]
|
60
|
+
else
|
61
|
+
[ true, key ]
|
62
|
+
end
|
63
|
+
|
64
|
+
field ? set_f(key, value, unset) : set_v(key, value, unset)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
data/lib/ruote/fei.rb
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'digest/md5'
|
26
|
+
|
27
|
+
require 'ruote/version'
|
28
|
+
require 'ruote/workitem'
|
29
|
+
require 'ruote/util/misc'
|
30
|
+
require 'ruote/util/hashdot'
|
31
|
+
|
32
|
+
|
33
|
+
module Ruote
|
34
|
+
|
35
|
+
# A shortcut for
|
36
|
+
#
|
37
|
+
# Ruote::FlowExpressionId.to_storage_id(fei)
|
38
|
+
#
|
39
|
+
def self.to_storage_id(fei)
|
40
|
+
|
41
|
+
Ruote::FlowExpressionId.to_storage_id(fei)
|
42
|
+
end
|
43
|
+
|
44
|
+
# A shorter shortcut for
|
45
|
+
#
|
46
|
+
# Ruote::FlowExpressionId.to_storage_id(fei)
|
47
|
+
#
|
48
|
+
def self.sid(fei)
|
49
|
+
|
50
|
+
Ruote::FlowExpressionId.to_storage_id(fei)
|
51
|
+
end
|
52
|
+
|
53
|
+
# A shortcut for
|
54
|
+
#
|
55
|
+
# Ruote::FlowExpressionId.is_a_fei?(o)
|
56
|
+
#
|
57
|
+
def self.is_a_fei?(o)
|
58
|
+
|
59
|
+
Ruote::FlowExpressionId.is_a_fei?(o)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Will do its best to return a wfid (String) or a fei (Hash instance)
|
63
|
+
# extract from the given o argument.
|
64
|
+
#
|
65
|
+
def self.extract_id(o)
|
66
|
+
|
67
|
+
return o if o.is_a?(String) and o.index('!').nil? # wfid
|
68
|
+
|
69
|
+
Ruote::FlowExpressionId.extract_h(o)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Given something, tries to return the fei (Ruote::FlowExpressionId) in it.
|
73
|
+
#
|
74
|
+
def self.extract_fei(o)
|
75
|
+
|
76
|
+
Ruote::FlowExpressionId.extract(o)
|
77
|
+
end
|
78
|
+
|
79
|
+
# This function is used to generate the subids. Each flow
|
80
|
+
# expression receives such an id (it's useful for cursors, loops and
|
81
|
+
# forgotten branches).
|
82
|
+
#
|
83
|
+
def self.generate_subid(salt)
|
84
|
+
|
85
|
+
Digest::MD5.hexdigest(
|
86
|
+
"#{rand}-#{salt}-#{$$}-#{Thread.current.object_id}#{Time.now.to_f}")
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# The FlowExpressionId (fei for short) is an process expression identifier.
|
91
|
+
# Each expression when instantiated gets a unique fei.
|
92
|
+
#
|
93
|
+
# Feis are also used in workitems, where the fei is the fei of the
|
94
|
+
# [participant] expression that emitted the workitem.
|
95
|
+
#
|
96
|
+
# Feis can thus indicate the position of a workitem in a process tree.
|
97
|
+
#
|
98
|
+
# Feis contain four pieces of information :
|
99
|
+
#
|
100
|
+
# * wfid : workflow instance id, the identifier for the process instance
|
101
|
+
# * subid : a unique identifier for expressions (useful in loops)
|
102
|
+
# * expid : the expression id, where in the process tree
|
103
|
+
# * engine_id : only relevant in multi engine scenarii (defaults to 'engine')
|
104
|
+
#
|
105
|
+
class FlowExpressionId
|
106
|
+
|
107
|
+
CHILD_SEP = '_'
|
108
|
+
|
109
|
+
attr_reader :h
|
110
|
+
|
111
|
+
def initialize(h)
|
112
|
+
|
113
|
+
@h = h
|
114
|
+
class << h; include Ruote::HashDot; end
|
115
|
+
|
116
|
+
@h['subid'] = @h.delete('sub_wfid') if @h['sub_wfid']
|
117
|
+
# TODO : for 2.1.13, remove this
|
118
|
+
end
|
119
|
+
|
120
|
+
def expid; @h['expid']; end
|
121
|
+
def wfid; @h['wfid']; end
|
122
|
+
def engine_id; @h['engine_id']; end
|
123
|
+
def subid; @h['subid']; end
|
124
|
+
|
125
|
+
alias sub_wfid subid
|
126
|
+
|
127
|
+
def to_storage_id
|
128
|
+
|
129
|
+
"#{@h['expid']}!#{@h['subid']}!#{@h['wfid']}"
|
130
|
+
end
|
131
|
+
alias sid to_storage_id
|
132
|
+
|
133
|
+
def to_sortable_id
|
134
|
+
|
135
|
+
"#{@h['wfid']}!!#{@h['expid']}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.to_storage_id(hfei)
|
139
|
+
|
140
|
+
hfei.respond_to?(:to_storage_id) ?
|
141
|
+
hfei.to_storage_id :
|
142
|
+
"#{hfei['expid']}!#{hfei['subid'] || hfei['sub_wfid']}!#{hfei['wfid']}"
|
143
|
+
|
144
|
+
# TODO : for 2.1.13, remove the subid || sub_wfid trick
|
145
|
+
end
|
146
|
+
|
147
|
+
# Turns the result of to_storage_id back to a FlowExpressionId instance.
|
148
|
+
#
|
149
|
+
def self.from_id(s, engine_id='engine')
|
150
|
+
|
151
|
+
extract("#{engine_id}!#{s}")
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns the last number in the expid. For instance, if the expid is
|
155
|
+
# '0_5_7', the child_id will be '7'.
|
156
|
+
#
|
157
|
+
def child_id
|
158
|
+
|
159
|
+
h.expid.split(CHILD_SEP).last.to_i
|
160
|
+
end
|
161
|
+
|
162
|
+
def hash
|
163
|
+
|
164
|
+
to_storage_id.hash
|
165
|
+
end
|
166
|
+
|
167
|
+
def <=>(other)
|
168
|
+
|
169
|
+
self.to_sortable_id <=> other.to_sortable_id
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns true if the other is a FlowExpressionId instance and it
|
173
|
+
# points to the same expression as this one.
|
174
|
+
#
|
175
|
+
def ==(other)
|
176
|
+
|
177
|
+
return false unless other.is_a?(Ruote::FlowExpressionId)
|
178
|
+
|
179
|
+
(hash == other.hash)
|
180
|
+
end
|
181
|
+
|
182
|
+
alias eql? ==
|
183
|
+
|
184
|
+
SUBS = %w[ subid sub_wfid ]
|
185
|
+
IDS = %w[ engine_id expid wfid ]
|
186
|
+
|
187
|
+
# Returns true if the h is a representation of a FlowExpressionId instance.
|
188
|
+
#
|
189
|
+
def self.is_a_fei?(h)
|
190
|
+
|
191
|
+
h.respond_to?(:keys) && (h.keys - SUBS).sort == IDS
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns child_id... For an expid of '0_1_4', this will be 4.
|
195
|
+
#
|
196
|
+
def self.child_id(h)
|
197
|
+
|
198
|
+
h['expid'].split(CHILD_SEP).last.to_i
|
199
|
+
end
|
200
|
+
|
201
|
+
def to_h
|
202
|
+
|
203
|
+
@h
|
204
|
+
end
|
205
|
+
|
206
|
+
# Returns true if other_fei is the fei of a child expression of
|
207
|
+
# parent_fei.
|
208
|
+
#
|
209
|
+
def self.direct_child?(parent_fei, other_fei)
|
210
|
+
|
211
|
+
%w[ wfid engine_id ].each do |k|
|
212
|
+
return false if parent_fei[k] != other_fei[k]
|
213
|
+
end
|
214
|
+
|
215
|
+
pei = other_fei['expid'].split(CHILD_SEP)[0..-2].join(CHILD_SEP)
|
216
|
+
|
217
|
+
(pei == parent_fei['expid'])
|
218
|
+
end
|
219
|
+
|
220
|
+
# Attempts at extracting a FlowExpressionId from the given argument
|
221
|
+
# (workitem, string, ...)
|
222
|
+
#
|
223
|
+
# Uses .extract_h
|
224
|
+
#
|
225
|
+
def self.extract(arg)
|
226
|
+
|
227
|
+
FlowExpressionId.new(extract_h(arg))
|
228
|
+
end
|
229
|
+
|
230
|
+
# Attempts at extracting a FlowExpressionId (as a Hash instance) from the
|
231
|
+
# given argument (workitem, string, ...)
|
232
|
+
#
|
233
|
+
def self.extract_h(arg)
|
234
|
+
|
235
|
+
if arg.is_a?(Hash)
|
236
|
+
return arg if arg['expid']
|
237
|
+
return arg['fei'] if arg['fei']
|
238
|
+
end
|
239
|
+
|
240
|
+
return extract_h(arg.fei) if arg.respond_to?(:fei)
|
241
|
+
return arg.h if arg.is_a?(Ruote::FlowExpressionId)
|
242
|
+
return arg.h['fei'] if arg.is_a?(Ruote::Workitem)
|
243
|
+
|
244
|
+
if arg.is_a?(String)
|
245
|
+
|
246
|
+
ss = arg.split('!')
|
247
|
+
|
248
|
+
return {
|
249
|
+
'engine_id' => ss[-4] || 'engine',
|
250
|
+
'expid' => ss[-3],
|
251
|
+
'subid' => ss[-2],
|
252
|
+
'wfid' => ss[-1] }
|
253
|
+
end
|
254
|
+
|
255
|
+
raise ArgumentError.new(
|
256
|
+
"couldn't extract fei out of instance of #{arg.class}")
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|