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,87 @@
|
|
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
|
+
# Commands are understood by the cursor, loop and iterator expressions.
|
30
|
+
#
|
31
|
+
module CommandMixin
|
32
|
+
|
33
|
+
F_COMMAND = '__command__'
|
34
|
+
ATT_COMMANDS = %w[ break rewind reset over stop ]
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
# TODO : :ignore_workitem / :disallow => 'workitem' thing ?
|
39
|
+
|
40
|
+
def get_command(workitem)
|
41
|
+
|
42
|
+
command, step = workitem['fields'].delete(F_COMMAND)
|
43
|
+
command, step = lookup_attribute_command(workitem) unless command
|
44
|
+
command = 'break' if command == 'over' || command == 'stop'
|
45
|
+
|
46
|
+
step = 1 if step == ''
|
47
|
+
|
48
|
+
return nil if command == nil
|
49
|
+
|
50
|
+
if command == 'back'
|
51
|
+
command = 'skip'
|
52
|
+
step = step ? -step : -1
|
53
|
+
elsif command == 'skip'
|
54
|
+
step ||= 1
|
55
|
+
end
|
56
|
+
|
57
|
+
[ command, step ]
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_command(workitem, command, step=nil)
|
61
|
+
|
62
|
+
workitem['fields'][F_COMMAND] = [ command, step ]
|
63
|
+
end
|
64
|
+
|
65
|
+
def lookup_attribute_command(workitem)
|
66
|
+
|
67
|
+
lookup_att_com('if', workitem) || lookup_att_com('unless', workitem)
|
68
|
+
end
|
69
|
+
|
70
|
+
def lookup_att_com(dir, workitem)
|
71
|
+
|
72
|
+
ATT_COMMANDS.each do |com|
|
73
|
+
|
74
|
+
c = attribute("#{com}_#{dir}", workitem)
|
75
|
+
|
76
|
+
next unless c
|
77
|
+
|
78
|
+
c = Condition.true?(c)
|
79
|
+
|
80
|
+
return [ com, nil ] if (dir == 'if' && c) || (dir == 'unless' && ( ! c))
|
81
|
+
end
|
82
|
+
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
@@ -0,0 +1,69 @@
|
|
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
|
+
require 'ruote/exp/command'
|
27
|
+
require 'ruote/exp/iterator'
|
28
|
+
|
29
|
+
|
30
|
+
module Ruote::Exp
|
31
|
+
|
32
|
+
#
|
33
|
+
# A parent class for CursorExpression and IteratorExpression
|
34
|
+
#
|
35
|
+
class CommandedExpression < FlowExpression
|
36
|
+
|
37
|
+
include CommandMixin
|
38
|
+
|
39
|
+
def reply(workitem)
|
40
|
+
|
41
|
+
workitem = h.command_workitem || workitem
|
42
|
+
h.command_workitem = nil
|
43
|
+
|
44
|
+
# command/answer may come from
|
45
|
+
#
|
46
|
+
# a) a child, regular case, easy
|
47
|
+
# b) somewhere else, which means we have to cancel the current child
|
48
|
+
# and then make sure the comand is interpreted
|
49
|
+
|
50
|
+
# a)
|
51
|
+
|
52
|
+
if Ruote::FlowExpressionId.direct_child?(h.fei, workitem['fei'])
|
53
|
+
return move_on(workitem)
|
54
|
+
end
|
55
|
+
|
56
|
+
# b)
|
57
|
+
|
58
|
+
h.command_workitem = workitem
|
59
|
+
h.command_workitem['fei'] = h.children.first
|
60
|
+
|
61
|
+
do_persist || return
|
62
|
+
|
63
|
+
@context.storage.put_msg('cancel', 'fei' => h.children.first)
|
64
|
+
|
65
|
+
# iteration will be done at when cancelled child replies
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,227 @@
|
|
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
|
+
# A few helper methods for evaluating :if and :unless expression
|
30
|
+
# attributes in process definitions.
|
31
|
+
#
|
32
|
+
module Condition
|
33
|
+
|
34
|
+
#
|
35
|
+
# A runtime error for unusable comparison strings.
|
36
|
+
#
|
37
|
+
class ConditionError < RuntimeError
|
38
|
+
|
39
|
+
def initialize(code)
|
40
|
+
super(
|
41
|
+
"couldn't interpret >#{code}<, " +
|
42
|
+
"if it comes from a ${xx} construct, please use ${\"xx} or ${'yy}")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
REGEXES = {
|
47
|
+
'evl_set' => /^(.+?)( +is)?( +not)?( +set)$/,
|
48
|
+
'evl_null' => /^(.+?)( +is)?( +not)?( +null)$/,
|
49
|
+
'evl_empty' => /^(.+[\]}"'])( +is)?( +not)?( +empty)$/,
|
50
|
+
'evl_in' => /^(.+?)( +is)?( +not)?( +in +)(\[.*\]|\{.*\})$/
|
51
|
+
}
|
52
|
+
|
53
|
+
def self.apply?(sif, sunless)
|
54
|
+
|
55
|
+
return (true?(sif)) if sif
|
56
|
+
return ( ! true?(sunless)) if sunless
|
57
|
+
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns true if the given conditional string evaluates to true.
|
62
|
+
#
|
63
|
+
def self.true?(conditional)
|
64
|
+
|
65
|
+
conditional = unescape(conditional.to_s)
|
66
|
+
|
67
|
+
REGEXES.each do |method, regex|
|
68
|
+
if m = regex.match(conditional)
|
69
|
+
return self.send(method, m)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
evl(conditional) ? true : false
|
74
|
+
|
75
|
+
rescue ArgumentError => ae
|
76
|
+
|
77
|
+
raise ConditionError.new(conditional)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Evaluates the given [conditional] code string and returns the
|
81
|
+
# result.
|
82
|
+
#
|
83
|
+
# Note : this is not a full Ruby evaluation !
|
84
|
+
#
|
85
|
+
def self.eval(code)
|
86
|
+
|
87
|
+
evl(code)
|
88
|
+
|
89
|
+
rescue ArgumentError => ae
|
90
|
+
|
91
|
+
raise ConditionError.new(code)
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
def self.parse(conditional)
|
97
|
+
|
98
|
+
Rufus::TreeChecker.parse(conditional)
|
99
|
+
|
100
|
+
rescue NoMethodError => nme
|
101
|
+
|
102
|
+
raise NoMethodError.new(
|
103
|
+
"/!\\ please upgrade your rufus-treechecker gem /!\\"
|
104
|
+
)
|
105
|
+
|
106
|
+
rescue SyntaxError => se
|
107
|
+
|
108
|
+
[ :str, conditional ]
|
109
|
+
|
110
|
+
rescue Exception => e
|
111
|
+
|
112
|
+
[ :false ]
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.unescape(s)
|
116
|
+
|
117
|
+
s.gsub('&', '&').gsub('>', '>').gsub('<', '<')
|
118
|
+
end
|
119
|
+
|
120
|
+
COMPARATORS = %w[ == > < != >= <= ].collect { |c| c.to_sym }
|
121
|
+
|
122
|
+
def self.evl(tree)
|
123
|
+
|
124
|
+
return evl(parse(tree)) if tree.is_a?(String)
|
125
|
+
|
126
|
+
return nil if tree == []
|
127
|
+
|
128
|
+
return tree.last if tree.first == :str
|
129
|
+
return tree.last if tree.first == :lit
|
130
|
+
return tree.last.to_s if tree.first == :const
|
131
|
+
return nil if tree == [ :nil ]
|
132
|
+
return true if tree == [ :true ]
|
133
|
+
return false if tree == [ :false ]
|
134
|
+
|
135
|
+
return ( ! evl(tree.last)) if tree.first == :not
|
136
|
+
|
137
|
+
return evl(tree[1]) && evl(tree[2]) if tree[0] == :and
|
138
|
+
return evl(tree[1]) || evl(tree[2]) if tree[0] == :or
|
139
|
+
|
140
|
+
return tree[1..-1].collect { |e| evl(e) } if tree[0] == :array
|
141
|
+
return Hash.[](*tree[1..-1].collect { |e| evl(e) }) if tree[0] == :hash
|
142
|
+
|
143
|
+
if tree[0] == :match3
|
144
|
+
return evl(tree[2]) =~ evl(tree[1])
|
145
|
+
end
|
146
|
+
if tree[0] == :call && tree[2] == :=~
|
147
|
+
return evl(tree[1]) =~ Regexp.new(evl(tree.last.last).to_s)
|
148
|
+
end
|
149
|
+
|
150
|
+
if tree[0] == :call && COMPARATORS.include?(tree[2])
|
151
|
+
return evl(tree[1]).send(tree[2], evl(tree.last.last))
|
152
|
+
end
|
153
|
+
|
154
|
+
if (c = flatten_and_compare(tree)) != nil
|
155
|
+
return c
|
156
|
+
end
|
157
|
+
|
158
|
+
if tree[0] == :call
|
159
|
+
return flatten(tree)
|
160
|
+
end
|
161
|
+
|
162
|
+
raise ArgumentError
|
163
|
+
# TODO : consider returning false
|
164
|
+
|
165
|
+
#require 'ruby2ruby'
|
166
|
+
#Ruby2Ruby.new.process(Sexp.from_array(tree))
|
167
|
+
# returns the raw Ruby as a String
|
168
|
+
# it's nice but "Loan/Grant" becomes "(Loan / Grant)"
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.flatten_and_compare(tree)
|
172
|
+
|
173
|
+
ftree = tree.flatten
|
174
|
+
comparator = (ftree & COMPARATORS).first
|
175
|
+
|
176
|
+
return nil unless comparator
|
177
|
+
|
178
|
+
icomparator = ftree.index(comparator)
|
179
|
+
left = ftree[0..icomparator - 1]
|
180
|
+
right = ftree[icomparator + 1..-1]
|
181
|
+
|
182
|
+
evl("#{flatten(left).inspect} #{comparator} #{flatten(right).inspect}")
|
183
|
+
end
|
184
|
+
|
185
|
+
KEYWORDS = %w[ call const arglist str ].collect { |w| w.to_sym }
|
186
|
+
|
187
|
+
def self.flatten(tree)
|
188
|
+
|
189
|
+
(tree.flatten - KEYWORDS).collect { |e| e.nil? ? ' ' : e.to_s }.join.strip
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.evl_set(match)
|
193
|
+
|
194
|
+
set = evl(match[1])
|
195
|
+
set = set != nil && set != ''
|
196
|
+
set = false if match[1].match(/is$/) && match[2].nil?
|
197
|
+
|
198
|
+
match[3].nil? ? set : ( ! set)
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.evl_empty(match)
|
202
|
+
|
203
|
+
object = evl(match[1])
|
204
|
+
|
205
|
+
empty = if object.respond_to?(:empty?)
|
206
|
+
object.empty?
|
207
|
+
elsif object.nil?
|
208
|
+
true
|
209
|
+
else
|
210
|
+
false
|
211
|
+
end
|
212
|
+
|
213
|
+
( ! match[3].nil? ^ empty)
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.evl_null(match)
|
217
|
+
|
218
|
+
( ! match[3].nil? ^ evl(match[1]).nil?)
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.evl_in(match)
|
222
|
+
|
223
|
+
( ! match[3].nil? ^ evl(match[5]).include?(evl(match[1]))) rescue false
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
@@ -0,0 +1,138 @@
|
|
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 'ruote/exp/iterator'
|
26
|
+
|
27
|
+
|
28
|
+
module Ruote::Exp
|
29
|
+
|
30
|
+
#
|
31
|
+
# The 'add_branches'/'add_branch' expression can be used to add branches
|
32
|
+
# to a concurrent-iterator while it is running.
|
33
|
+
#
|
34
|
+
# concurrent_iterator :on => 'a, b, c' do
|
35
|
+
# sequence do
|
36
|
+
# participant :ref => 'worker_${v:i}'
|
37
|
+
# add_branches 'd, e', :if => '${v:/not_sufficient}'
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# In this example, if the process level variable 'not_sufficient' is set to
|
42
|
+
# true, workers d and e will be added to the iterated elements.
|
43
|
+
#
|
44
|
+
# 'add_branches' understand comma-separated list of values or direcltly
|
45
|
+
# array of values, like the concurrent_iterator does. The :sep or :separator
|
46
|
+
# attribute can be used for custom separators :
|
47
|
+
#
|
48
|
+
# add_branches 'd|e|f', :sep => '|'
|
49
|
+
#
|
50
|
+
#
|
51
|
+
# == :ref
|
52
|
+
#
|
53
|
+
# By default, add_branches looks up the first parent expression that is
|
54
|
+
# concurrent_iterator. This is all well, but what when you have nested
|
55
|
+
# concurrent_iterator and want to hit the enclosing one from inside the
|
56
|
+
# enclosed one ? Or when you want to add branches from somewhere else
|
57
|
+
# in the process instance, outside of the concurrent_iterator ?
|
58
|
+
#
|
59
|
+
# concurrence do
|
60
|
+
#
|
61
|
+
# concurrent_iterator :on => 'a, b, c', :tag => 'main' do
|
62
|
+
# subprocess :ref => 'perform_work'
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# sequence do
|
66
|
+
# subprocess :ref => 'supervise_work'
|
67
|
+
# add_branches 'd, e', :ref => 'main', :if => '${f:more_cowbell}'
|
68
|
+
# rewind :if => '${f:more_cowbell}'
|
69
|
+
# end
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# The add_branches expression refers to the 'main' concurrent_iterator via
|
73
|
+
# the :ref => 'main' attribute.
|
74
|
+
#
|
75
|
+
#
|
76
|
+
# == missing concurrent_iterator
|
77
|
+
#
|
78
|
+
# If :ref points to nothing or add_branch has no :ref and is not placed
|
79
|
+
# inside of a concurrent_iterator, the expression will silently have no
|
80
|
+
# effect.
|
81
|
+
#
|
82
|
+
class AddBranchesExpression < FlowExpression
|
83
|
+
|
84
|
+
include IteratorMixin
|
85
|
+
|
86
|
+
names :add_branches, :add_branch
|
87
|
+
|
88
|
+
def apply
|
89
|
+
|
90
|
+
list = split_list(lookup_val_prefix('on') || attribute_text)
|
91
|
+
it_fei = find_concurrent_iterator
|
92
|
+
|
93
|
+
if list && it_fei
|
94
|
+
|
95
|
+
wi = Ruote.fulldup(h.applied_workitem)
|
96
|
+
wi['fields'][ConcurrentIteratorExpression::ADD_BRANCHES_FIELD] = list
|
97
|
+
|
98
|
+
@context.storage.put_msg('reply', 'fei' => it_fei, 'workitem' => wi)
|
99
|
+
end
|
100
|
+
|
101
|
+
reply_to_parent(h.applied_workitem)
|
102
|
+
end
|
103
|
+
|
104
|
+
def reply(workitem)
|
105
|
+
|
106
|
+
# never called
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
def find_concurrent_iterator
|
112
|
+
|
113
|
+
#
|
114
|
+
# ref ?
|
115
|
+
|
116
|
+
if ref = attribute(:ref)
|
117
|
+
|
118
|
+
return lookup_variable(ref)
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# no :ref, lookup first parent that is a concurrent_iterator
|
123
|
+
|
124
|
+
exp = self.parent
|
125
|
+
|
126
|
+
loop do
|
127
|
+
|
128
|
+
break if exp.nil?
|
129
|
+
break if exp.is_a?(ConcurrentIteratorExpression)
|
130
|
+
|
131
|
+
exp = exp.parent
|
132
|
+
end
|
133
|
+
|
134
|
+
exp ? exp.h.fei : nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|