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,186 @@
|
|
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 'sourcify'
|
26
|
+
require 'ruote/util/ometa'
|
27
|
+
|
28
|
+
|
29
|
+
module Ruote
|
30
|
+
|
31
|
+
# Not really a reader, more an AST builder.
|
32
|
+
#
|
33
|
+
# pdef = Ruote.define :name => 'take_out_garbage' do
|
34
|
+
# sequence do
|
35
|
+
# take_out_regular_garbage
|
36
|
+
# take_out_glass
|
37
|
+
# take_out_paper
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# engine.launch(pdef)
|
42
|
+
#
|
43
|
+
def self.define(*attributes, &block)
|
44
|
+
|
45
|
+
RubyDsl.create_branch('define', attributes, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Same as Ruote.define()
|
49
|
+
#
|
50
|
+
# pdef = Ruote.process_definition :name => 'take_out_garbage' do
|
51
|
+
# sequence do
|
52
|
+
# take_out_regular_garbage
|
53
|
+
# take_out_paper
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# engine.launch(pdef)
|
58
|
+
#
|
59
|
+
def self.process_definition(*attributes, &block)
|
60
|
+
|
61
|
+
define(*attributes, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Similar in purpose to Ruote.define and Ruote.process_definition but
|
65
|
+
# instead of returning a [process] definition, returns the tree.
|
66
|
+
#
|
67
|
+
# tree = Ruote.process_definition :name => 'take_out_garbage' do
|
68
|
+
# sequence do
|
69
|
+
# take_out_regular_garbage
|
70
|
+
# take_out_paper
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# p tree
|
75
|
+
# # => [ 'sequence', {}, [ [ 'take_out_regular_garbage', {}, [] ], [ 'take_out_paper', {}, [] ] ] ],
|
76
|
+
#
|
77
|
+
# This is useful when modifying a process instance via methods like re_apply :
|
78
|
+
#
|
79
|
+
# engine.re_apply(
|
80
|
+
# fei,
|
81
|
+
# :tree => Ruote.to_tree {
|
82
|
+
# sequence do
|
83
|
+
# participant 'alfred'
|
84
|
+
# participant 'bob'
|
85
|
+
# end
|
86
|
+
# })
|
87
|
+
# #
|
88
|
+
# # cancels the segment of process at fei and replaces it with
|
89
|
+
# # a simple alfred-bob sequence.
|
90
|
+
#
|
91
|
+
def self.to_tree(&block)
|
92
|
+
|
93
|
+
RubyDsl.create_branch('x', {}, &block).last.first
|
94
|
+
end
|
95
|
+
|
96
|
+
# :nodoc:
|
97
|
+
#
|
98
|
+
module RubyDsl
|
99
|
+
|
100
|
+
class BranchContext < Ruote::BlankSlate
|
101
|
+
|
102
|
+
def initialize(name, attributes)
|
103
|
+
|
104
|
+
@name = name
|
105
|
+
@attributes = attributes
|
106
|
+
@children = []
|
107
|
+
end
|
108
|
+
|
109
|
+
def method_missing(m, *args, &block)
|
110
|
+
|
111
|
+
@children.push(Ruote::RubyDsl.create_branch(m.to_s, args, &block))
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_a
|
115
|
+
|
116
|
+
[ @name, @attributes, @children ]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.create_branch(name, attributes, &block)
|
121
|
+
|
122
|
+
name = name[1..-1] while name[0, 1] == '_'
|
123
|
+
|
124
|
+
h = attributes.inject({}) { |h1, a|
|
125
|
+
|
126
|
+
a.is_a?(Hash) ? h1.merge!(a) : h1[a] = nil
|
127
|
+
|
128
|
+
h1
|
129
|
+
|
130
|
+
}.inject({}) { |h1, (k, v)|
|
131
|
+
|
132
|
+
k = k.is_a?(Regexp) ? k.inspect : k.to_s
|
133
|
+
h1[k] = to_json(v)
|
134
|
+
|
135
|
+
h1
|
136
|
+
}
|
137
|
+
|
138
|
+
c = BranchContext.new(name, h)
|
139
|
+
c.instance_eval(&block) if block
|
140
|
+
|
141
|
+
c.to_a
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.to_json(v)
|
145
|
+
|
146
|
+
case v
|
147
|
+
when Symbol; v.to_s
|
148
|
+
when Regexp; v.inspect
|
149
|
+
when Array; v.collect { |e| to_json(e) }
|
150
|
+
when Hash; v.inject({}) { |h, (k, v)| h[k.to_s] = to_json(v); h }
|
151
|
+
when Proc; v.to_raw_source + "\n"
|
152
|
+
else v
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# The same .read and .understands? method as the other readers are found here.
|
159
|
+
#
|
160
|
+
module RubyReader
|
161
|
+
|
162
|
+
# Returns true if s seems to contain a Ruby process definition
|
163
|
+
#
|
164
|
+
def self.understands?(s)
|
165
|
+
|
166
|
+
s.match(
|
167
|
+
/\bRuote\.(process_definition|workflow_definition|define)\b/
|
168
|
+
) != nil
|
169
|
+
end
|
170
|
+
|
171
|
+
# Evaluates the ruby string in the code, but at fist, thanks to the
|
172
|
+
# treechecker, makes sure it doesn't code malicious ruby code (at least
|
173
|
+
# tries very hard).
|
174
|
+
#
|
175
|
+
def self.read(s, treechecker)
|
176
|
+
|
177
|
+
treechecker.definition_check(s)
|
178
|
+
eval(s)
|
179
|
+
|
180
|
+
rescue SyntaxError => se
|
181
|
+
#p se
|
182
|
+
raise ArgumentError.new("Ruby syntax error : #{se.message}")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
@@ -0,0 +1,99 @@
|
|
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 'rexml/parsers/sax2parser'
|
26
|
+
require 'rexml/sax2listener'
|
27
|
+
|
28
|
+
|
29
|
+
module Ruote
|
30
|
+
|
31
|
+
#
|
32
|
+
# Turns an XML string into a process definition tree.
|
33
|
+
#
|
34
|
+
module XmlReader
|
35
|
+
|
36
|
+
# Returns true if the string seems to be an XML string.
|
37
|
+
#
|
38
|
+
def self.understands?(s)
|
39
|
+
|
40
|
+
s.match(/<[a-z]+>/) != nil
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# A helper class to store the temporary tree while it gets read.
|
45
|
+
#
|
46
|
+
class Node
|
47
|
+
|
48
|
+
attr_reader :parent, :attributes, :children
|
49
|
+
|
50
|
+
def initialize(parent, name, attributes)
|
51
|
+
|
52
|
+
@parent = parent
|
53
|
+
@name = name
|
54
|
+
@attributes = attributes.inject({}) { |h, (k, v)|
|
55
|
+
h[k.gsub(/-/, '_')] = v
|
56
|
+
h
|
57
|
+
}
|
58
|
+
@children = []
|
59
|
+
|
60
|
+
parent.children << self if parent
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_a
|
64
|
+
|
65
|
+
[ @name, @attributes, @children.collect { |c| c.to_a } ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Parses the XML string into a process definition tree (array of arrays).
|
70
|
+
#
|
71
|
+
def self.read(s, opt=nil)
|
72
|
+
|
73
|
+
parser = REXML::Parsers::SAX2Parser.new(s)
|
74
|
+
|
75
|
+
root = nil
|
76
|
+
current = nil
|
77
|
+
|
78
|
+
# u, l, q, a <=> url, local, qname, attributes
|
79
|
+
|
80
|
+
parser.listen(:start_element) do |u, l, q, a|
|
81
|
+
current = Node.new(current, l.gsub(/-/, '_'), a)
|
82
|
+
root ||= current
|
83
|
+
end
|
84
|
+
parser.listen(:end_element) do |u, l, q, a|
|
85
|
+
current = current.parent
|
86
|
+
end
|
87
|
+
|
88
|
+
parser.listen(:characters) do |text|
|
89
|
+
t = text.strip
|
90
|
+
current.attributes[t] = nil if t.size > 0
|
91
|
+
end
|
92
|
+
|
93
|
+
parser.parse
|
94
|
+
|
95
|
+
root.to_a
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,212 @@
|
|
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
|
27
|
+
|
28
|
+
#
|
29
|
+
# The core methods for the Receiver class (sometimes a Mixin is easier
|
30
|
+
# to integrate).
|
31
|
+
#
|
32
|
+
# (The engine itself includes this mixin, the LocalParticipant module
|
33
|
+
# includes it as well).
|
34
|
+
#
|
35
|
+
module ReceiverMixin
|
36
|
+
|
37
|
+
# This method pipes back a workitem into the engine, letting it resume
|
38
|
+
# in its flow, hopefully.
|
39
|
+
#
|
40
|
+
def receive(workitem)
|
41
|
+
|
42
|
+
workitem = workitem.to_h if workitem.respond_to?(:to_h)
|
43
|
+
|
44
|
+
@context.storage.put_msg(
|
45
|
+
'receive',
|
46
|
+
'fei' => workitem['fei'],
|
47
|
+
'workitem' => workitem,
|
48
|
+
'participant_name' => workitem['participant_name'],
|
49
|
+
'receiver' => sign)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Given a process definitions and optional initial fields and variables,
|
53
|
+
# launches a new process instance.
|
54
|
+
#
|
55
|
+
# This method is mostly used from the Ruote::Engine class (which includes
|
56
|
+
# this mixin).
|
57
|
+
#
|
58
|
+
# process_definition must be a result of Ruote.process_definition call
|
59
|
+
# or XML or JSON serialized process definition, as accepted by
|
60
|
+
# Ruote::Reader#read.
|
61
|
+
#
|
62
|
+
# fields are workflow parameters that will be placed in workitem.fields.
|
63
|
+
#
|
64
|
+
# variables contain engine variables.
|
65
|
+
#
|
66
|
+
def launch(process_definition, fields={}, variables={})
|
67
|
+
|
68
|
+
wfid = @context.wfidgen.generate
|
69
|
+
|
70
|
+
@context.storage.put_msg(
|
71
|
+
'launch',
|
72
|
+
'wfid' => wfid,
|
73
|
+
'tree' => @context.reader.read(process_definition),
|
74
|
+
'workitem' => { 'fields' => fields },
|
75
|
+
'variables' => variables)
|
76
|
+
|
77
|
+
wfid
|
78
|
+
end
|
79
|
+
|
80
|
+
# Wraps a call to receive(workitem)
|
81
|
+
#
|
82
|
+
# Not aliasing so that if someone changes the receive implementation,
|
83
|
+
# reply is affected as well.
|
84
|
+
#
|
85
|
+
def reply(workitem)
|
86
|
+
|
87
|
+
receive(workitem)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Wraps a call to receive(workitem)
|
91
|
+
#
|
92
|
+
# Not aliasing so that if someone changes the receive implementation,
|
93
|
+
# reply_to_engine is affected as well.
|
94
|
+
#
|
95
|
+
def reply_to_engine(workitem)
|
96
|
+
|
97
|
+
receive(workitem)
|
98
|
+
end
|
99
|
+
|
100
|
+
# A receiver signs a workitem when it comes back.
|
101
|
+
#
|
102
|
+
# Not used much as of now.
|
103
|
+
#
|
104
|
+
def sign
|
105
|
+
|
106
|
+
self.class.to_s
|
107
|
+
end
|
108
|
+
|
109
|
+
# Convenience method, given a workitem or a fei, returns the
|
110
|
+
# corresponding flow expession.
|
111
|
+
#
|
112
|
+
def fetch_flow_expression(workitem_or_fei)
|
113
|
+
|
114
|
+
Ruote::Exp::FlowExpression.fetch(
|
115
|
+
@context,
|
116
|
+
Ruote::FlowExpressionId.extract_h(workitem_or_fei))
|
117
|
+
end
|
118
|
+
|
119
|
+
# For example :
|
120
|
+
#
|
121
|
+
# fexp = engine.fexp(fei)
|
122
|
+
# # or
|
123
|
+
# fexp = engine.fexp(workitem)
|
124
|
+
#
|
125
|
+
alias fexp fetch_flow_expression
|
126
|
+
|
127
|
+
# A convenience methods for advanced users (like Oleg).
|
128
|
+
#
|
129
|
+
# Given a fei (flow expression id), fetches the workitem as stored in
|
130
|
+
# the expression with that fei.
|
131
|
+
# This is the "applied workitem", if the workitem is currently handed to
|
132
|
+
# a participant, this method will return the workitem as applied, not
|
133
|
+
# the workitem as saved by the participant/user in whatever worklist it
|
134
|
+
# uses. If you need that workitem, do the vanilla thing and ask it to
|
135
|
+
# the [storage] participant or its worklist.
|
136
|
+
#
|
137
|
+
# The fei might be a string fei (result of fei.to_storage_id), a
|
138
|
+
# FlowExpressionId instance or a hash.
|
139
|
+
#
|
140
|
+
# on_terminate processes are not triggered for on_error processes.
|
141
|
+
# on_error processes are triggered for on_terminate processes as well.
|
142
|
+
#
|
143
|
+
def applied_workitem(fei)
|
144
|
+
|
145
|
+
Ruote::Workitem.new(fexp(fei).h.applied_workitem)
|
146
|
+
end
|
147
|
+
alias workitem applied_workitem
|
148
|
+
|
149
|
+
protected
|
150
|
+
|
151
|
+
# Stashes values in the participant expression (in the storage).
|
152
|
+
#
|
153
|
+
# put(workitem.fei, 'key' => 'value', 'colour' => 'blue')
|
154
|
+
#
|
155
|
+
# Remember that keys/values must be serializable in JSON.
|
156
|
+
#
|
157
|
+
# put & get are useful for a participant that needs to communicate
|
158
|
+
# between its consume and its cancel.
|
159
|
+
#
|
160
|
+
# See the thread at
|
161
|
+
# http://groups.google.com/group/openwferu-users/t/2e6a95708c10847b for the
|
162
|
+
# justification.
|
163
|
+
#
|
164
|
+
def put(fei, hash)
|
165
|
+
|
166
|
+
fexp = Ruote::Exp::FlowExpression.fetch(@context, fei.to_h)
|
167
|
+
|
168
|
+
(fexp.h['stash'] ||= {}).merge!(hash)
|
169
|
+
|
170
|
+
fexp.persist_or_raise
|
171
|
+
end
|
172
|
+
|
173
|
+
# Fetches back a stashed value.
|
174
|
+
#
|
175
|
+
# get(fei, 'colour')
|
176
|
+
# # => 'blue'
|
177
|
+
#
|
178
|
+
# To return the whole stash
|
179
|
+
#
|
180
|
+
# get(fei)
|
181
|
+
# # => { 'colour' => 'blue' }
|
182
|
+
#
|
183
|
+
# put & get are useful for a participant that needs to communicate
|
184
|
+
# between its consume and its cancel.
|
185
|
+
#
|
186
|
+
def get(fei, key=nil)
|
187
|
+
|
188
|
+
fexp = Ruote::Exp::FlowExpression.fetch(@context, fei.to_h)
|
189
|
+
|
190
|
+
stash = fexp.h['stash'] rescue {}
|
191
|
+
|
192
|
+
key ? stash[key] : stash
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# A receiver is meant to receive workitems and feed them back into the
|
198
|
+
# engine (the storage actually).
|
199
|
+
#
|
200
|
+
class Receiver
|
201
|
+
include ReceiverMixin
|
202
|
+
|
203
|
+
# Accepts context, worker, engine or storage as first argument.
|
204
|
+
#
|
205
|
+
def initialize(cwes, options={})
|
206
|
+
|
207
|
+
@context = cwes.context
|
208
|
+
@options = options
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|