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,122 @@
|
|
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
|
+
# Encapsulating all the information about an error in a process instance.
|
30
|
+
#
|
31
|
+
class ProcessError
|
32
|
+
|
33
|
+
# When this instance was returned by Ruote::Engine#ps or
|
34
|
+
# Ruote::Engine#process, this attribute will point to the flow expression
|
35
|
+
# where the error occurred.
|
36
|
+
#
|
37
|
+
attr_accessor :flow_expression
|
38
|
+
|
39
|
+
def initialize(h)
|
40
|
+
@h = h
|
41
|
+
end
|
42
|
+
|
43
|
+
def message
|
44
|
+
@h['message']
|
45
|
+
end
|
46
|
+
|
47
|
+
def trace
|
48
|
+
@h['trace']
|
49
|
+
end
|
50
|
+
|
51
|
+
def msg
|
52
|
+
@h['msg']
|
53
|
+
end
|
54
|
+
|
55
|
+
def fei
|
56
|
+
Ruote::FlowExpressionId.new(msg['fei'])
|
57
|
+
end
|
58
|
+
|
59
|
+
def wfid
|
60
|
+
msg['fei']['wfid']
|
61
|
+
end
|
62
|
+
|
63
|
+
def tree
|
64
|
+
@h['msg']['tree']
|
65
|
+
end
|
66
|
+
|
67
|
+
def at
|
68
|
+
@h['msg']['put_at']
|
69
|
+
end
|
70
|
+
|
71
|
+
# A shortcut for modifying the tree of an expression when it has had
|
72
|
+
# an error upon being applied.
|
73
|
+
#
|
74
|
+
def tree=(t)
|
75
|
+
@h['msg']['tree'] = t
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_h
|
79
|
+
@h
|
80
|
+
end
|
81
|
+
|
82
|
+
# 'apply', 'reply', 'receive', ... Indicates in which "direction" the
|
83
|
+
# error occured.
|
84
|
+
#
|
85
|
+
def action
|
86
|
+
@h['msg']['action']
|
87
|
+
end
|
88
|
+
|
89
|
+
# Exposes the workitem fields directly.
|
90
|
+
#
|
91
|
+
def fields
|
92
|
+
@h['msg']['workitem'] && @h['msg']['workitem']['fields']
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns an instance of Ruote::Workitem
|
96
|
+
#
|
97
|
+
def workitem
|
98
|
+
Ruote::Workitem.new(msg['workitem'])
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns an array of deviations (see the 'filter' expression) if the
|
102
|
+
# error is a Ruote::ValidationError.
|
103
|
+
#
|
104
|
+
def deviations
|
105
|
+
@h['deviations']
|
106
|
+
end
|
107
|
+
|
108
|
+
protected
|
109
|
+
|
110
|
+
def to_dot(opts)
|
111
|
+
|
112
|
+
i = fei.to_storage_id
|
113
|
+
label = "error : #{message.gsub(/"/, "'")}"
|
114
|
+
|
115
|
+
[
|
116
|
+
"\"err_#{i}\" [ label = \"#{label}\" ];",
|
117
|
+
"\"err_#{i}\" -> \"#{i}\" [ style = \"dotted\" ];"
|
118
|
+
]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
@@ -0,0 +1,448 @@
|
|
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/engine/process_error'
|
26
|
+
|
27
|
+
|
28
|
+
module Ruote
|
29
|
+
|
30
|
+
#
|
31
|
+
# A 'view' on the status of a process instance.
|
32
|
+
#
|
33
|
+
# Returned by the #process and the #processes methods of the Engine.
|
34
|
+
#
|
35
|
+
class ProcessStatus
|
36
|
+
|
37
|
+
# The expressions that compose the process instance.
|
38
|
+
#
|
39
|
+
attr_reader :expressions
|
40
|
+
|
41
|
+
# Returns the expression at the root of the process instance.
|
42
|
+
#
|
43
|
+
attr_reader :root_expression
|
44
|
+
|
45
|
+
# An array of the workitems currently in the storage participant for this
|
46
|
+
# process instance.
|
47
|
+
#
|
48
|
+
# Do not confuse with #workitems
|
49
|
+
#
|
50
|
+
attr_reader :stored_workitems
|
51
|
+
|
52
|
+
# An array of errors currently plaguing the process instance. Hopefully,
|
53
|
+
# this array is empty.
|
54
|
+
#
|
55
|
+
attr_reader :errors
|
56
|
+
|
57
|
+
# An array of schedules (open structs yielding information about the
|
58
|
+
# schedules of this process)
|
59
|
+
#
|
60
|
+
attr_reader :schedules
|
61
|
+
|
62
|
+
# Called by Ruote::Engine#processes or Ruote::Engine#process.
|
63
|
+
#
|
64
|
+
def initialize(context, expressions, stored_workitems, errors, schedules)
|
65
|
+
|
66
|
+
#
|
67
|
+
# preparing data
|
68
|
+
|
69
|
+
@expressions = expressions.collect { |e|
|
70
|
+
Ruote::Exp::FlowExpression.from_h(context, e) }
|
71
|
+
@expressions.sort! { |a, b| a.fei.expid <=> b.fei.expid }
|
72
|
+
|
73
|
+
@stored_workitems = stored_workitems.collect { |h|
|
74
|
+
Ruote::Workitem.new(h)
|
75
|
+
}
|
76
|
+
|
77
|
+
@errors = errors.sort! { |a, b| a.fei.expid <=> b.fei.expid }
|
78
|
+
@schedules = schedules.sort! { |a, b| a['owner'].sid <=> b['owner'].sid }
|
79
|
+
|
80
|
+
@root_expression = root_expressions.first
|
81
|
+
|
82
|
+
#
|
83
|
+
# linking errors and expressions for easy navigation
|
84
|
+
|
85
|
+
@errors.each do |err|
|
86
|
+
err.flow_expression = @expressions.find { |fexp| fexp.fei == err.fei }
|
87
|
+
err.flow_expression.error = err if err.flow_expression
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a list of all the expressions that have no parent expression.
|
92
|
+
# The list is sorted with the deeper (closer to the original root) first.
|
93
|
+
#
|
94
|
+
def root_expressions
|
95
|
+
|
96
|
+
roots = @expressions.select { |e| e.h.parent_id == nil }
|
97
|
+
|
98
|
+
roots = roots.inject({}) { |h, e|
|
99
|
+
h["#{e.h.fei['expid']}__#{e.h.fei['subid']}"] = e; h
|
100
|
+
}
|
101
|
+
|
102
|
+
roots.keys.sort.collect { |k| roots[k] }
|
103
|
+
end
|
104
|
+
|
105
|
+
# Given an expression id, returns the root (top ancestor) for its
|
106
|
+
# expression.
|
107
|
+
#
|
108
|
+
def root_expression_for(fei)
|
109
|
+
|
110
|
+
sfei = Ruote.sid(fei)
|
111
|
+
|
112
|
+
exp = @expressions.find { |fe| sfei == Ruote.sid(fe.fei) }
|
113
|
+
|
114
|
+
return nil unless exp
|
115
|
+
return exp if exp.parent_id.nil?
|
116
|
+
|
117
|
+
root_expression_for(exp.parent_id)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns the process variables set for this process instance.
|
121
|
+
#
|
122
|
+
def variables
|
123
|
+
|
124
|
+
@root_expression && @root_expression.variables
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns a hash fei => variable_hash containing all the variable bindings
|
128
|
+
# (expression by expression) of the process instance.
|
129
|
+
#
|
130
|
+
def all_variables
|
131
|
+
|
132
|
+
@expressions.inject({}) do |h, exp|
|
133
|
+
h[exp.fei] = exp.variables if exp.variables
|
134
|
+
h
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns a hash tagname => fei of tags set at the root of the process
|
139
|
+
# instance.
|
140
|
+
#
|
141
|
+
def tags
|
142
|
+
|
143
|
+
Hash[variables.select { |k, v| FlowExpressionId.is_a_fei?(v) }]
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns a hash tagname => array of feis of all the tags set in the process
|
147
|
+
# instance.
|
148
|
+
#
|
149
|
+
def all_tags
|
150
|
+
|
151
|
+
all_variables.inject({}) do |h, (fei, vars)|
|
152
|
+
vars.each { |k, v| (h[k] ||= []) << v if FlowExpressionId.is_a_fei?(v) }
|
153
|
+
h
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns the unique identifier for this process instance.
|
158
|
+
#
|
159
|
+
def wfid
|
160
|
+
|
161
|
+
@expressions.any? ? @expressions.first.fei.wfid : @errors.first.fei.wfid
|
162
|
+
end
|
163
|
+
|
164
|
+
# For a process
|
165
|
+
#
|
166
|
+
# Ruote.process_definition :name => 'review', :revision => '0.1' do
|
167
|
+
# author
|
168
|
+
# reviewer
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# will yield 'review'.
|
172
|
+
#
|
173
|
+
def definition_name
|
174
|
+
|
175
|
+
@root_expression && (
|
176
|
+
@root_expression.attribute('name') ||
|
177
|
+
@root_expression.attribute_text)
|
178
|
+
end
|
179
|
+
|
180
|
+
# For a process
|
181
|
+
#
|
182
|
+
# Ruote.process_definition :name => 'review', :revision => '0.1' do
|
183
|
+
# author
|
184
|
+
# reviewer
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# will yield '0.1'.
|
188
|
+
#
|
189
|
+
def definition_revision
|
190
|
+
|
191
|
+
@root_expression && (
|
192
|
+
@root_expression.attribute('revision') ||
|
193
|
+
@root_expression.attribute('rev'))
|
194
|
+
end
|
195
|
+
|
196
|
+
# Returns the 'position' of the process.
|
197
|
+
#
|
198
|
+
# pdef = Ruote.process_definition do
|
199
|
+
# alpha :task => 'clean car'
|
200
|
+
# end
|
201
|
+
# wfid = engine.launch(pdef)
|
202
|
+
#
|
203
|
+
# sleep 0.500
|
204
|
+
#
|
205
|
+
# engine.process(wfid) # => [["0_0", "alpha", {"task"=>"clean car"}]]
|
206
|
+
#
|
207
|
+
# A process with concurrent branches will yield multiple 'positions'.
|
208
|
+
#
|
209
|
+
# It uses #workitems underneath.
|
210
|
+
#
|
211
|
+
# If you want to list all the expressions where the "flow currently is"
|
212
|
+
# regardless they are participant expressions or errors, look at the
|
213
|
+
# #leaves method.
|
214
|
+
#
|
215
|
+
def position
|
216
|
+
|
217
|
+
workitems.collect { |wi|
|
218
|
+
|
219
|
+
r = [ wi.fei.sid, wi.participant_name ]
|
220
|
+
|
221
|
+
params = (wi.fields['params'] || {}).dup
|
222
|
+
params.delete('ref')
|
223
|
+
|
224
|
+
if err = errors.find { |e| e.fei == wi.fei }
|
225
|
+
params['error'] = err.message
|
226
|
+
end
|
227
|
+
|
228
|
+
r << params
|
229
|
+
r
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
# Returns the expressions where the flow is currently, ak the leaves
|
234
|
+
# of the execution tree.
|
235
|
+
#
|
236
|
+
# Whereas #position only looks at participant expressions (and errors),
|
237
|
+
# #leaves looks at any expressions that is a leave (which has no
|
238
|
+
# child at this point).
|
239
|
+
#
|
240
|
+
# Returns an array of FlowExpression instances. (Note that they may
|
241
|
+
# have their attribute #error set).
|
242
|
+
#
|
243
|
+
def leaves
|
244
|
+
|
245
|
+
expressions.inject([]) { |a, exp|
|
246
|
+
a.select { |e| ! exp.ancestor?(e.fei) } + [ exp ]
|
247
|
+
}
|
248
|
+
end
|
249
|
+
|
250
|
+
# Returns the workitem as was applied at the root expression.
|
251
|
+
#
|
252
|
+
def root_workitem
|
253
|
+
|
254
|
+
Ruote::Workitem.new(root_expression.h.applied_workitem)
|
255
|
+
end
|
256
|
+
|
257
|
+
# Returns a list of the workitems currently 'out' to participants
|
258
|
+
#
|
259
|
+
# For example, with an instance of
|
260
|
+
#
|
261
|
+
# Ruote.process_definition do
|
262
|
+
# concurrence do
|
263
|
+
# alpha :task => 'clean car'
|
264
|
+
# bravo :task => 'sell car'
|
265
|
+
# end
|
266
|
+
# end
|
267
|
+
#
|
268
|
+
# calling engine.process(wfid).workitems will yield two workitems
|
269
|
+
# (alpha and bravo).
|
270
|
+
#
|
271
|
+
# Warning : do not confuse the workitems here with the workitems held
|
272
|
+
# in a storage participant or equivalent.
|
273
|
+
#
|
274
|
+
def workitems
|
275
|
+
|
276
|
+
@expressions.select { |fexp|
|
277
|
+
fexp.is_a?(Ruote::Exp::ParticipantExpression)
|
278
|
+
}.collect { |fexp|
|
279
|
+
Ruote::Workitem.new(fexp.h.applied_workitem)
|
280
|
+
}
|
281
|
+
end
|
282
|
+
|
283
|
+
# Returns a parseable UTC datetime string which indicates when the process
|
284
|
+
# was last active.
|
285
|
+
#
|
286
|
+
def last_active
|
287
|
+
|
288
|
+
@expressions.collect { |fexp| fexp.h.put_at }.max
|
289
|
+
end
|
290
|
+
|
291
|
+
# Returns the process definition tree as it was when this process instance
|
292
|
+
# was launched.
|
293
|
+
#
|
294
|
+
def original_tree
|
295
|
+
|
296
|
+
@root_expression && @root_expression.original_tree
|
297
|
+
end
|
298
|
+
|
299
|
+
# Returns a Time instance indicating when the process instance was launched.
|
300
|
+
#
|
301
|
+
def launched_time
|
302
|
+
|
303
|
+
@root_expression && @root_expression.created_time
|
304
|
+
end
|
305
|
+
|
306
|
+
def to_s
|
307
|
+
|
308
|
+
"(process_status wfid '#{wfid}', " +
|
309
|
+
"expressions #{@expressions.size}, " +
|
310
|
+
"stored_workitems #{@stored_workitems.size}, " +
|
311
|
+
"errors #{@errors.size}, " +
|
312
|
+
"schedules #{@schedules.size}, " +
|
313
|
+
")"
|
314
|
+
end
|
315
|
+
|
316
|
+
def inspect
|
317
|
+
|
318
|
+
vars = variables rescue nil
|
319
|
+
avars = all_variables.inject({}) { |h, (k, v)| h[Ruote.sid(k)] = v; h }
|
320
|
+
|
321
|
+
s = [ "== #{self.class} ==" ]
|
322
|
+
s << " expressions : #{@expressions.size}"
|
323
|
+
@expressions.each do |e|
|
324
|
+
s << " #{e.fei.to_storage_id}"
|
325
|
+
s << " | #{e.name}"
|
326
|
+
s << " | * #{e.state} *" if e.state
|
327
|
+
s << " | #{e.attributes.inspect}"
|
328
|
+
s << " `-parent--> #{e.h.parent_id ? e.parent_id.to_storage_id : 'nil'}"
|
329
|
+
end
|
330
|
+
s << " schedules : #{@schedules.size}"
|
331
|
+
s << " stored workitems : #{@stored_workitems.size}"
|
332
|
+
s << " variables : #{vars.inspect}"
|
333
|
+
s << " all_variables : #{avars.inspect}"
|
334
|
+
s << " errors : #{@errors.size}"
|
335
|
+
@errors.each do |e|
|
336
|
+
s << " ***"
|
337
|
+
s << " #{e.fei.to_storage_id} :" if e.fei
|
338
|
+
s << " action : #{e.action}"
|
339
|
+
s << " message : #{e.message}"
|
340
|
+
s << " trace :"
|
341
|
+
e.trace.split("\n").each do |line|
|
342
|
+
s << " #{line}"
|
343
|
+
end
|
344
|
+
s << " fields : #{e.fields.inspect}"
|
345
|
+
end
|
346
|
+
|
347
|
+
s.join("\n") + "\n"
|
348
|
+
end
|
349
|
+
|
350
|
+
# Returns a 'dot' representation of the process. A graph describing
|
351
|
+
# the tree of flow expressions that compose the process.
|
352
|
+
#
|
353
|
+
def to_dot(opts={})
|
354
|
+
|
355
|
+
s = [ "digraph \"process wfid #{wfid}\" {" ]
|
356
|
+
@expressions.each { |e| s.push(*e.send(:to_dot, opts)) }
|
357
|
+
@errors.each { |e| s.push(*e.send(:to_dot, opts)) }
|
358
|
+
s << "}"
|
359
|
+
|
360
|
+
s.join("\n")
|
361
|
+
end
|
362
|
+
|
363
|
+
#--
|
364
|
+
#def to_h
|
365
|
+
# h = {}
|
366
|
+
# %w[
|
367
|
+
# wfid
|
368
|
+
# definition_name definition_revision
|
369
|
+
# original_tree current_tree
|
370
|
+
# variables tags
|
371
|
+
# ].each { |m| h[m] = self.send(m) }
|
372
|
+
# h['launched_time'] = launched_time
|
373
|
+
# h['last_active'] = last_active
|
374
|
+
# # all_variables and all_tags ?
|
375
|
+
# h['root_expression'] = nil
|
376
|
+
# h['expressions'] = @expressions.collect { |e| e.fei.to_h }
|
377
|
+
# h['errors'] = @errors.collect { |e| e.to_h }
|
378
|
+
# h
|
379
|
+
#end
|
380
|
+
#++
|
381
|
+
|
382
|
+
# Returns the current version of the process definition tree. If no
|
383
|
+
# manipulation (gardening) was performed on the tree, this method yields
|
384
|
+
# the same result as the #original_tree method.
|
385
|
+
#
|
386
|
+
def current_tree
|
387
|
+
|
388
|
+
h = Ruote.decompose_tree(original_tree)
|
389
|
+
|
390
|
+
@expressions.sort { |e0, e1|
|
391
|
+
|
392
|
+
e0.fei.expid <=> e1.fei.expid
|
393
|
+
|
394
|
+
}.each { |e|
|
395
|
+
|
396
|
+
trigger = e.tree[1]['_triggered']
|
397
|
+
|
398
|
+
tree = if trigger && trigger != 'on_re_apply'
|
399
|
+
t = original_tree_from_parent(e).dup
|
400
|
+
t[1]['_triggered'] = trigger
|
401
|
+
t
|
402
|
+
else
|
403
|
+
e.tree
|
404
|
+
end
|
405
|
+
|
406
|
+
h.merge!(Ruote.decompose_tree(tree, e.fei.expid))
|
407
|
+
}
|
408
|
+
|
409
|
+
Ruote.recompose_tree(h)
|
410
|
+
end
|
411
|
+
|
412
|
+
protected
|
413
|
+
|
414
|
+
def original_tree_from_parent(e)
|
415
|
+
|
416
|
+
parent = @expressions.find { |exp| exp.fei == e.parent_id }
|
417
|
+
|
418
|
+
parent ? parent.tree[2][e.fei.child_id] : e.tree
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
def self.decompose_tree(t, pos='0', h={})
|
423
|
+
|
424
|
+
h[pos] = t[0, 2]
|
425
|
+
t[2].each_with_index { |c, i| decompose_tree(c, "#{pos}_#{i}", h) }
|
426
|
+
h
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.recompose_tree(h, pos='0')
|
430
|
+
|
431
|
+
t = h[pos]
|
432
|
+
|
433
|
+
return nil unless t
|
434
|
+
|
435
|
+
t << []
|
436
|
+
i = 0
|
437
|
+
|
438
|
+
loop do
|
439
|
+
tt = recompose_tree(h, "#{pos}_#{i}")
|
440
|
+
break unless tt
|
441
|
+
t.last << tt
|
442
|
+
i = i + 1
|
443
|
+
end
|
444
|
+
|
445
|
+
t
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|