openwferu 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{README → README.txt} +16 -13
- data/bin/validate-workflow.rb +46 -22
- data/examples/README.txt +8 -0
- data/examples/homeworkreview.rb +66 -0
- data/examples/quotereporter.rb +154 -0
- data/lib/{openwferu.rb → openwfe.rb} +6 -8
- data/lib/{ru → openwfe}/contextual.rb +11 -3
- data/lib/{ru → openwfe/engine}/engine.rb +50 -36
- data/lib/{ru/participant.rb → openwfe/engine/file_persisted_engine.rb} +21 -22
- data/lib/openwfe/expool/expressionpool.rb +534 -0
- data/lib/openwfe/expool/expstorage.rb +184 -0
- data/lib/openwfe/expool/journalexpstorage.rb +312 -0
- data/lib/openwfe/expool/yamlexpstorage.rb +127 -0
- data/lib/{ru → openwfe/expressions}/environment.rb +19 -14
- data/lib/{ru → openwfe/expressions}/expressionmap.rb +48 -21
- data/lib/{ru → openwfe/expressions}/fe_concurrence.rb +111 -35
- data/lib/openwfe/expressions/fe_cursor.rb +236 -0
- data/lib/{ru → openwfe/expressions}/fe_define.rb +5 -5
- data/lib/openwfe/expressions/fe_fqv.rb +99 -0
- data/lib/openwfe/expressions/fe_iterator.rb +182 -0
- data/lib/{ru/fe_misc.rb → openwfe/expressions/fe_losfor.rb} +14 -56
- data/lib/openwfe/expressions/fe_misc.rb +102 -0
- data/lib/{ru → openwfe/expressions}/fe_participant.rb +25 -14
- data/lib/{ru → openwfe/expressions}/fe_raw.rb +39 -75
- data/lib/{ru/fe_base.rb → openwfe/expressions/fe_sequence.rb} +40 -35
- data/lib/{ru → openwfe/expressions}/fe_subprocess.rb +30 -14
- data/lib/{ru → openwfe/expressions}/fe_time.rb +59 -31
- data/lib/{ru → openwfe/expressions}/fe_utils.rb +42 -26
- data/lib/{ru → openwfe/expressions}/fe_value.rb +20 -14
- data/lib/openwfe/expressions/flowexpression.rb +434 -0
- data/lib/openwfe/expressions/raw_prog.rb +391 -0
- data/lib/openwfe/expressions/raw_xml.rb +128 -0
- data/lib/openwfe/flowexpressionid.rb +148 -0
- data/lib/{ru → openwfe}/logging.rb +10 -6
- data/lib/{osocket.rb → openwfe/osocket.rb} +36 -35
- data/lib/{otime.rb → openwfe/otime.rb} +71 -21
- data/lib/openwfe/participants/atomparticipants.rb +144 -0
- data/lib/openwfe/participants/enoparticipant.rb +73 -0
- data/lib/openwfe/participants/participant.rb +85 -0
- data/lib/{ru → openwfe/participants}/participantmap.rb +40 -12
- data/lib/{ru → openwfe/participants}/participants.rb +41 -12
- data/lib/openwfe/participants/soapparticipants.rb +96 -0
- data/lib/{controlclient.rb → openwfe/rest/controlclient.rb} +12 -13
- data/lib/{definitions.rb → openwfe/rest/definitions.rb} +3 -3
- data/lib/{exception.rb → openwfe/rest/exception.rb} +3 -3
- data/lib/{restclient.rb → openwfe/rest/restclient.rb} +13 -22
- data/lib/{worklistclient.rb → openwfe/rest/worklistclient.rb} +33 -46
- data/lib/openwfe/rest/xmlcodec.rb +575 -0
- data/lib/{ru → openwfe}/rudefinitions.rb +32 -4
- data/lib/{ru → openwfe}/service.rb +20 -8
- data/lib/openwfe/storage/yamlfilestorage.rb +159 -0
- data/lib/{ru → openwfe/util}/dollar.rb +10 -8
- data/lib/openwfe/util/lru_cache.rb +149 -0
- data/lib/{ru → openwfe/util}/scheduler.rb +18 -10
- data/lib/{ru → openwfe/util}/schedulers.rb +7 -7
- data/lib/{utils.rb → openwfe/utils.rb} +93 -9
- data/lib/openwfe/workitem.rb +366 -0
- data/lib/openwfe/worklist/worklists.rb +175 -0
- data/test/README.txt +27 -0
- data/test/atomtest.rb +99 -0
- data/test/crontest.rb +58 -0
- data/test/dollartest.rb +3 -3
- data/test/feitest.rb +42 -14
- data/test/file_persistence_test.rb +93 -0
- data/test/flowtestbase.rb +72 -26
- data/test/ft_0.rb +1 -97
- data/test/ft_0b_sequence.rb +33 -0
- data/test/ft_0c_testname.rb +29 -0
- data/test/ft_10_loop.rb +48 -0
- data/test/ft_11_ppd.rb +292 -0
- data/test/ft_12_blockparticipant.rb +45 -0
- data/test/ft_13_eno.rb +51 -0
- data/test/ft_14_subprocess.rb +90 -0
- data/test/ft_14b_subprocess.rb +40 -0
- data/test/ft_15_iterator.rb +70 -0
- data/test/ft_16_fqv.rb +57 -0
- data/test/ft_1_unset.rb +25 -1
- data/test/ft_2_concurrence.rb +10 -5
- data/test/ft_3_equals.rb +35 -1
- data/test/ft_4_misc.rb +16 -1
- data/test/ft_5_time.rb +26 -1
- data/test/ft_6_lambda.rb +2 -1
- data/test/{ft_7_losfor.rb → ft_7_lose.rb} +41 -35
- data/test/ft_8_forget.rb +46 -0
- data/test/ft_9_cursor.rb +94 -0
- data/test/journal_persistence_test.rb +147 -0
- data/test/misctest.rb +13 -9
- data/test/rake_ptest.rb +18 -0
- data/test/rake_qtest.rb +43 -0
- data/test/{fulltest.rb → rake_test.rb} +2 -2
- data/test/raw_prog_test.rb +236 -0
- data/test/rest_test.rb +189 -0
- data/test/rutest_utils.rb +1 -1
- data/test/timetest.rb +42 -34
- metadata +125 -82
- data/lib/codec.rb +0 -573
- data/lib/flowexpressionid.rb +0 -139
- data/lib/ru/expressionpool.rb +0 -382
- data/lib/ru/expressionstorage.rb +0 -99
- data/lib/ru/flowexpression.rb +0 -272
- data/lib/ru/ruutils.rb +0 -70
- data/lib/test.rb +0 -222
- data/lib/workitem.rb +0 -249
- data/test/quicktest.rb +0 -21
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#
|
|
2
2
|
#--
|
|
3
|
-
# Copyright (c) 2006, John Mettraux, OpenWFE.org
|
|
3
|
+
# Copyright (c) 2006-2007, John Mettraux, Nicolas Modrzyk OpenWFE.org
|
|
4
4
|
# All rights reserved.
|
|
5
5
|
#
|
|
6
6
|
# Redistribution and use in source and binary forms, with or without
|
|
@@ -37,45 +37,50 @@
|
|
|
37
37
|
# "made in Japan"
|
|
38
38
|
#
|
|
39
39
|
# John Mettraux at openwfe.org
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
require 'rexml/document'
|
|
40
|
+
# Nicolas Modrzyk at openwfe.org
|
|
41
|
+
#
|
|
43
42
|
|
|
44
|
-
require 'workitem'
|
|
45
|
-
require '
|
|
46
|
-
require '
|
|
47
|
-
require '
|
|
48
|
-
require '
|
|
49
|
-
require '
|
|
50
|
-
require '
|
|
51
|
-
require '
|
|
43
|
+
require 'openwfe/workitem'
|
|
44
|
+
require 'openwfe/rudefinitions'
|
|
45
|
+
require 'openwfe/service'
|
|
46
|
+
require 'openwfe/util/schedulers'
|
|
47
|
+
require 'openwfe/expool/expressionpool'
|
|
48
|
+
require 'openwfe/expool/expstorage'
|
|
49
|
+
require 'openwfe/expressions/expressionmap'
|
|
50
|
+
require 'openwfe/participants/participantmap'
|
|
52
51
|
|
|
53
52
|
|
|
54
|
-
module
|
|
53
|
+
module OpenWFE
|
|
55
54
|
|
|
55
|
+
#
|
|
56
|
+
# The simplest implementation of the OpenWFE workflow engine.
|
|
57
|
+
# No persistence is used, everything is stored in memory.
|
|
58
|
+
#
|
|
56
59
|
class Engine < Service
|
|
60
|
+
include OwfeServiceLocator
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
# :application_context
|
|
62
|
+
def initialize ()
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
super('engine', {})
|
|
64
|
+
super(S_ENGINE, {})
|
|
64
65
|
|
|
65
66
|
@application_context[@service_name] = self
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@application_context[S_SCHEDULER] = \
|
|
73
|
-
SchedulerService.new(S_SCHEDULER, @application_context)
|
|
68
|
+
build_expression_map()
|
|
69
|
+
build_expression_pool()
|
|
70
|
+
build_expression_storage()
|
|
71
|
+
build_participant_map()
|
|
72
|
+
build_scheduler()
|
|
74
73
|
|
|
75
74
|
init_default_logging('engine.log')
|
|
76
75
|
end
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
#
|
|
78
|
+
# Launches a [business] process.
|
|
79
|
+
# The 'object' param may contain either a LaunchItem instance,
|
|
80
|
+
# either a String containing the URL of the process definition
|
|
81
|
+
# to launch (with an empty LaunchItem created on the fly).
|
|
82
|
+
#
|
|
83
|
+
def launch (object)
|
|
79
84
|
|
|
80
85
|
launchitem = nil
|
|
81
86
|
|
|
@@ -95,35 +100,44 @@ module OpenWFEru
|
|
|
95
100
|
end
|
|
96
101
|
end
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
get_expression_pool.launch(launchitem)
|
|
99
104
|
end
|
|
100
105
|
|
|
101
106
|
#
|
|
102
|
-
#
|
|
107
|
+
# Registers a participant in this [embedded] engine.
|
|
108
|
+
# This method is a shortcut to the ParticipantMap method
|
|
109
|
+
# with the same name.
|
|
103
110
|
#
|
|
104
|
-
def register_participant (regex, participant)
|
|
111
|
+
def register_participant (regex, participant=nil, &block)
|
|
105
112
|
|
|
106
|
-
|
|
107
|
-
.register_participant(regex, participant)
|
|
113
|
+
get_participant_map.register_participant(regex, participant, &block)
|
|
108
114
|
end
|
|
109
115
|
|
|
110
116
|
protected
|
|
111
117
|
|
|
118
|
+
#
|
|
119
|
+
# the following methods may get overridden upon extension
|
|
120
|
+
# see for example file_persisted_engine.rb
|
|
121
|
+
#
|
|
122
|
+
|
|
112
123
|
def build_expression_map ()
|
|
113
|
-
|
|
124
|
+
init_service(S_EXPRESSION_MAP, ExpressionMap)
|
|
114
125
|
end
|
|
115
126
|
|
|
116
127
|
def build_expression_pool ()
|
|
117
|
-
|
|
128
|
+
init_service(S_EXPRESSION_POOL, ExpressionPool)
|
|
118
129
|
end
|
|
119
130
|
|
|
120
131
|
def build_expression_storage ()
|
|
121
|
-
InMemoryExpressionStorage
|
|
122
|
-
.new(S_EXPRESSION_STORAGE, @application_context)
|
|
132
|
+
init_service(S_EXPRESSION_STORAGE, InMemoryExpressionStorage)
|
|
123
133
|
end
|
|
124
134
|
|
|
125
135
|
def build_participant_map ()
|
|
126
|
-
|
|
136
|
+
init_service(S_PARTICIPANT_MAP, ParticipantMap)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def build_scheduler ()
|
|
140
|
+
init_service(S_SCHEDULER, SchedulerService)
|
|
127
141
|
end
|
|
128
142
|
|
|
129
143
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2006,
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (c) 2006-2007, Nicolas Modryzk, OpenWFE.org
|
|
4
4
|
# All rights reserved.
|
|
5
5
|
#
|
|
6
6
|
# Redistribution and use in source and binary forms, with or without
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
29
29
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
30
30
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
31
|
-
|
|
31
|
+
#++
|
|
32
32
|
#
|
|
33
33
|
# $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
|
|
34
34
|
#
|
|
@@ -36,34 +36,33 @@
|
|
|
36
36
|
#
|
|
37
37
|
# "made in Japan"
|
|
38
38
|
#
|
|
39
|
+
# Nicolas Modrzyk at openwfe.org
|
|
39
40
|
# John Mettraux at openwfe.org
|
|
40
41
|
#
|
|
41
42
|
|
|
42
|
-
require '
|
|
43
|
+
require 'openwfe/engine/engine'
|
|
44
|
+
require 'openwfe/expool/yamlexpstorage'
|
|
43
45
|
|
|
44
46
|
|
|
45
|
-
module
|
|
47
|
+
module OpenWFE
|
|
46
48
|
|
|
47
49
|
#
|
|
48
|
-
#
|
|
49
|
-
# other pieces of code may easily 'mix it in'.
|
|
50
|
+
# An engine persisted to a tree of yaml files
|
|
50
51
|
#
|
|
51
|
-
|
|
52
|
-
include Contextual
|
|
52
|
+
class FilePersistedEngine < Engine
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
#
|
|
55
|
+
# overrides the method already found in Engine with a persisted
|
|
56
|
+
# expression storage
|
|
57
|
+
#
|
|
58
|
+
def build_expression_storage ()
|
|
59
|
+
#FileExpressionStorage \
|
|
60
|
+
# .new(S_EXPRESSION_STORAGE, @application_context, ENV['HOME'])
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
# when the workflow engine is cancelling a workflow branch, the
|
|
62
|
-
# already activated participants are notified via this method
|
|
63
|
-
#
|
|
64
|
-
def cancel (cancelitem)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
62
|
+
@application_context[:file_expression_storage_path] = "./work"
|
|
67
63
|
|
|
64
|
+
init_service(S_EXPRESSION_STORAGE, YamlFileExpressionStorage)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
68
|
end
|
|
69
|
-
|
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
#
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (c) 2006-2007, John Mettraux, OpenWFE.org
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
|
8
|
+
#
|
|
9
|
+
# . Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
# list of conditions and the following disclaimer.
|
|
11
|
+
#
|
|
12
|
+
# . Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
# and/or other materials provided with the distribution.
|
|
15
|
+
#
|
|
16
|
+
# . Neither the name of the "OpenWFE" nor the names of its contributors may be
|
|
17
|
+
# used to endorse or promote products derived from this software without
|
|
18
|
+
# specific prior written permission.
|
|
19
|
+
#
|
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
31
|
+
#++
|
|
32
|
+
#
|
|
33
|
+
# $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
|
|
34
|
+
#
|
|
35
|
+
|
|
36
|
+
#
|
|
37
|
+
# "made in Japan"
|
|
38
|
+
#
|
|
39
|
+
# John Mettraux at openwfe.org
|
|
40
|
+
#
|
|
41
|
+
|
|
42
|
+
require 'uri'
|
|
43
|
+
require 'monitor'
|
|
44
|
+
require 'net/http'
|
|
45
|
+
require 'rexml/document'
|
|
46
|
+
|
|
47
|
+
require 'openwfe/utils'
|
|
48
|
+
require 'openwfe/service'
|
|
49
|
+
require 'openwfe/logging'
|
|
50
|
+
require 'openwfe/rudefinitions'
|
|
51
|
+
require 'openwfe/flowexpressionid'
|
|
52
|
+
require 'openwfe/util/lru_cache'
|
|
53
|
+
require 'openwfe/expressions/environment'
|
|
54
|
+
require 'openwfe/expressions/raw_xml'
|
|
55
|
+
|
|
56
|
+
include OpenWFE
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
module OpenWFE
|
|
60
|
+
|
|
61
|
+
#
|
|
62
|
+
# a small help class for storing monitors provided on demand
|
|
63
|
+
# to expressions that need them
|
|
64
|
+
#
|
|
65
|
+
class MonitorProvider
|
|
66
|
+
include MonitorMixin, Logging
|
|
67
|
+
|
|
68
|
+
MAX_MONITORS = 10000
|
|
69
|
+
|
|
70
|
+
def initialize (application_context=nil)
|
|
71
|
+
super()
|
|
72
|
+
@application_context = application_context
|
|
73
|
+
@monitors = LRUCache.new(MAX_MONITORS)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def [] (key)
|
|
77
|
+
synchronize do
|
|
78
|
+
#ldebug { "[] caller :\n" + OpenWFE::caller_to_s(8) }
|
|
79
|
+
mon = @monitors[key]
|
|
80
|
+
if not mon
|
|
81
|
+
#ldebug { "[] creating new Monitor for #{key}" }
|
|
82
|
+
mon = Monitor.new
|
|
83
|
+
@monitors[key] = mon
|
|
84
|
+
else
|
|
85
|
+
#ldebug { "[] already had Monitor for #{key}" }
|
|
86
|
+
end
|
|
87
|
+
return mon
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def delete (key)
|
|
92
|
+
synchronize do
|
|
93
|
+
#ldebug { "delete() removing Monitor for #{key}" }
|
|
94
|
+
@monitors.delete(key)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
GONE = "gone"
|
|
100
|
+
|
|
101
|
+
#
|
|
102
|
+
# This special flow expression id is used by the forget() method
|
|
103
|
+
# (which is used by the forget expression and the concurrence
|
|
104
|
+
# synchronization expressions)
|
|
105
|
+
#
|
|
106
|
+
GONE_PARENT_ID = FlowExpressionId.new
|
|
107
|
+
GONE_PARENT_ID.engine_id = GONE
|
|
108
|
+
GONE_PARENT_ID.initial_engine_id = GONE
|
|
109
|
+
GONE_PARENT_ID.workflow_definition_url = GONE
|
|
110
|
+
GONE_PARENT_ID.workflow_definition_name = GONE
|
|
111
|
+
GONE_PARENT_ID.workflow_definition_revision = GONE
|
|
112
|
+
GONE_PARENT_ID.workflow_instance_id = "-1"
|
|
113
|
+
GONE_PARENT_ID.expression_name = GONE
|
|
114
|
+
GONE_PARENT_ID.expression_id = "-1"
|
|
115
|
+
GONE_PARENT_ID.freeze
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# The ExpressionPool stores expressions (pieces of workflow instance).
|
|
119
|
+
# It's the core of the workflow engine.
|
|
120
|
+
# It relies on an expression storage for actual persistence of the
|
|
121
|
+
# expressions.
|
|
122
|
+
#
|
|
123
|
+
class ExpressionPool < Service
|
|
124
|
+
include MonitorMixin, OwfeServiceLocator
|
|
125
|
+
|
|
126
|
+
@@last_given_instance_id = -1
|
|
127
|
+
#
|
|
128
|
+
# storing at class level the last workflow instance id given
|
|
129
|
+
|
|
130
|
+
def initialize (serviceName, applicationContext)
|
|
131
|
+
super(serviceName, applicationContext)
|
|
132
|
+
@monitors = MonitorProvider.new(application_context)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
#
|
|
136
|
+
# Obtains a unique monitor for an expression.
|
|
137
|
+
# It avoids the need for the FlowExpression instances to include
|
|
138
|
+
# the monitor mixin by themselves
|
|
139
|
+
#
|
|
140
|
+
def get_monitor (fei)
|
|
141
|
+
return @monitors[fei]
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
#
|
|
145
|
+
# Instantiates a workflow definition and launches it.
|
|
146
|
+
#
|
|
147
|
+
def launch (launchitem)
|
|
148
|
+
|
|
149
|
+
rawExpression = buildRawExpression(launchitem)
|
|
150
|
+
|
|
151
|
+
wi = build_workitem(launchitem)
|
|
152
|
+
|
|
153
|
+
rawExpression.apply(wi)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
#
|
|
157
|
+
# launches a subprocess
|
|
158
|
+
#
|
|
159
|
+
def launch_template \
|
|
160
|
+
(requesting_expression, template_fei, workitem, params=nil)
|
|
161
|
+
|
|
162
|
+
ldebug { "launch() request for #{template_fei.to_debug_s}" }
|
|
163
|
+
|
|
164
|
+
rawexp, fei = fetch(template_fei)
|
|
165
|
+
rawexp = rawexp.dup()
|
|
166
|
+
rawexp.fei = rawexp.fei.dup()
|
|
167
|
+
|
|
168
|
+
if requesting_expression.kind_of? FlowExpressionId
|
|
169
|
+
rawexp.parent_id = requesting_expression
|
|
170
|
+
rawexp.fei.workflow_instance_id = \
|
|
171
|
+
"#{requesting_expression.workflow_instance_id}.0"
|
|
172
|
+
elsif requesting_expression.kind_of? String
|
|
173
|
+
rawexp.parent_id = nil
|
|
174
|
+
rawexp.fei.workflow_instance_id = \
|
|
175
|
+
"#{requesting_expression}.0"
|
|
176
|
+
else # kind is FlowExpression
|
|
177
|
+
rawexp.parent_id = requesting_expression.fei
|
|
178
|
+
rawexp.fei.workflow_instance_id = \
|
|
179
|
+
"#{requesting_expression.fei.workflow_instance_id}.0"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
#ldebug do
|
|
183
|
+
# "launch_template() spawning wfid " +
|
|
184
|
+
# "#{rawexp.fei.workflow_instance_id.to_s}"
|
|
185
|
+
#end
|
|
186
|
+
|
|
187
|
+
env = rawexp.new_environment()
|
|
188
|
+
|
|
189
|
+
params.each { |k, v| env[k] = v } if params
|
|
190
|
+
#
|
|
191
|
+
# the new scope gets its own environment
|
|
192
|
+
|
|
193
|
+
rawexp.store_itself()
|
|
194
|
+
|
|
195
|
+
rawexp.apply(workitem)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
#
|
|
199
|
+
# Evaluates a raw definition expression and
|
|
200
|
+
# returns its body fei
|
|
201
|
+
#
|
|
202
|
+
def evaluate (rawExpression, workitem)
|
|
203
|
+
exp = rawExpression.instantiate_real_expression(workitem)
|
|
204
|
+
fei = exp.evaluate(workitem)
|
|
205
|
+
remove(rawExpression)
|
|
206
|
+
return fei
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
#
|
|
210
|
+
# Applies a given expression (id or expression)
|
|
211
|
+
#
|
|
212
|
+
def apply (exp, workitem)
|
|
213
|
+
|
|
214
|
+
exp, fei = fetch(exp)
|
|
215
|
+
|
|
216
|
+
ldebug { "apply() '#{fei}' (#{fei.class})" }
|
|
217
|
+
|
|
218
|
+
if not exp
|
|
219
|
+
lwarn { "apply() cannot apply missing #{fei.to_debug_s}" }
|
|
220
|
+
return
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
ldebug { "apply() #{fei.to_debug_s}" }
|
|
224
|
+
|
|
225
|
+
workitem.last_expression_id = exp.fei
|
|
226
|
+
|
|
227
|
+
exp.apply(workitem)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
#
|
|
231
|
+
# Cancels the given expression
|
|
232
|
+
#
|
|
233
|
+
def cancel (exp)
|
|
234
|
+
|
|
235
|
+
exp, fei = fetch(exp)
|
|
236
|
+
|
|
237
|
+
if not exp
|
|
238
|
+
ldebug { "cancel() cannot cancel missing #{fei.to_debug_s}" }
|
|
239
|
+
return nil
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
ldebug { "cancel() for #{fei.to_debug_s}" }
|
|
243
|
+
|
|
244
|
+
inflowitem = exp.cancel()
|
|
245
|
+
remove(exp)
|
|
246
|
+
|
|
247
|
+
return inflowitem
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
#
|
|
251
|
+
# Forgets the given expression (makes sure to substitute its
|
|
252
|
+
# parent_id with the GONE_PARENT_ID constant)
|
|
253
|
+
#
|
|
254
|
+
def forget (exp)
|
|
255
|
+
|
|
256
|
+
exp, fei = fetch(exp)
|
|
257
|
+
|
|
258
|
+
return if not exp
|
|
259
|
+
|
|
260
|
+
exp.parent_id = GONE_PARENT_ID
|
|
261
|
+
exp.store_itself()
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
#
|
|
265
|
+
# Replies to the parent of the given expression.
|
|
266
|
+
#
|
|
267
|
+
def reply_to_parent (exp, workitem)
|
|
268
|
+
|
|
269
|
+
exp, fei = fetch(exp)
|
|
270
|
+
|
|
271
|
+
workitem.last_expression_id = fei
|
|
272
|
+
|
|
273
|
+
remove(exp, workitem)
|
|
274
|
+
|
|
275
|
+
if not exp.parent_id
|
|
276
|
+
ldebug do
|
|
277
|
+
"reply_to_parent() process " +
|
|
278
|
+
"#{exp.fei.workflow_instance_id} terminated"
|
|
279
|
+
end
|
|
280
|
+
else
|
|
281
|
+
if exp.parent_id == GONE_PARENT_ID
|
|
282
|
+
ldebug do
|
|
283
|
+
"reply_to_parent() parent is gone for " +
|
|
284
|
+
exp.fei.to_debug_s
|
|
285
|
+
end
|
|
286
|
+
else
|
|
287
|
+
reply(exp.parent_id, workitem)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
#
|
|
293
|
+
# Triggers the reply expression of the expression given by its id.
|
|
294
|
+
#
|
|
295
|
+
def reply (exp, workitem)
|
|
296
|
+
|
|
297
|
+
exp, fei = fetch(exp)
|
|
298
|
+
|
|
299
|
+
ldebug { "reply() to #{fei.to_debug_s}" }
|
|
300
|
+
ldebug { "reply() from #{workitem.last_expression_id}" }
|
|
301
|
+
|
|
302
|
+
if not exp
|
|
303
|
+
#raise "cannot reply to missing #{fei.to_debug_s}"
|
|
304
|
+
lwarn { "reply() cannot reply to missing #{fei.to_debug_s}" }
|
|
305
|
+
return
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
exp.reply(workitem)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
#
|
|
312
|
+
# Adds or updates a flow expression in this pool
|
|
313
|
+
#
|
|
314
|
+
def update (flowExpression)
|
|
315
|
+
|
|
316
|
+
get_expression_storage()[flowExpression.fei] = flowExpression
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
#
|
|
320
|
+
# Fetches a FlowExpression from the pool.
|
|
321
|
+
# Returns a tuple : the FlowExpression plus its FlowExpressionId.
|
|
322
|
+
#
|
|
323
|
+
# The param 'exp' may be a FlowExpressionId or a FlowExpression that
|
|
324
|
+
# has to be reloaded.
|
|
325
|
+
#
|
|
326
|
+
def fetch (exp)
|
|
327
|
+
synchronize do
|
|
328
|
+
fei = exp
|
|
329
|
+
if exp.kind_of? FlowExpression
|
|
330
|
+
fei = exp.fei
|
|
331
|
+
elsif not exp.kind_of? FlowExpressionId
|
|
332
|
+
raise \
|
|
333
|
+
"Cannot fetch expression with key : "+
|
|
334
|
+
"'#{fei}' (#{fei.class})"
|
|
335
|
+
end
|
|
336
|
+
return get_expression_storage()[fei], fei
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
#
|
|
341
|
+
# Fetches a FlowExpression (returns only the FlowExpression instance)
|
|
342
|
+
#
|
|
343
|
+
# The param 'exp' may be a FlowExpressionId or a FlowExpression that
|
|
344
|
+
# has to be reloaded.
|
|
345
|
+
#
|
|
346
|
+
def fetch_expression (exp)
|
|
347
|
+
exp, _fei = fetch(exp)
|
|
348
|
+
return exp
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def fetch_engine_environment ()
|
|
352
|
+
synchronize do
|
|
353
|
+
|
|
354
|
+
eei = engine_environment_id
|
|
355
|
+
ee, fei = fetch(eei)
|
|
356
|
+
|
|
357
|
+
if not ee
|
|
358
|
+
ee = Environment\
|
|
359
|
+
.new(eei, nil, nil, @application_context, nil)
|
|
360
|
+
ee.store_itself()
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
ldebug { "fetch_engine_environment() stored new ee" }
|
|
364
|
+
|
|
365
|
+
return ee
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
#
|
|
370
|
+
# Removes a flow expression from the pool
|
|
371
|
+
# (This method is mainly called from the pool itself)
|
|
372
|
+
#
|
|
373
|
+
def remove (exp, workitem=nil)
|
|
374
|
+
|
|
375
|
+
exp, fei = fetch(exp)
|
|
376
|
+
|
|
377
|
+
return if not exp
|
|
378
|
+
|
|
379
|
+
ldebug { "remove() fe #{fei.to_debug_s}" }
|
|
380
|
+
|
|
381
|
+
synchronize do
|
|
382
|
+
|
|
383
|
+
@monitors.delete(fei)
|
|
384
|
+
|
|
385
|
+
#get_expression_storage().delete(fei)
|
|
386
|
+
get_expression_storage().remove(fei, workitem)
|
|
387
|
+
|
|
388
|
+
if exp.owns_its_environment?
|
|
389
|
+
remove_environment(exp.environment_id)
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def engine_environment_id ()
|
|
396
|
+
synchronize do
|
|
397
|
+
return @eei if @eei
|
|
398
|
+
@eei = FlowExpressionId.new
|
|
399
|
+
@eei.owfe_version = OPENWFE_VERSION
|
|
400
|
+
@eei.engine_id = get_engine.service_name
|
|
401
|
+
@eei.initial_engine_id = @eei.engine_id
|
|
402
|
+
@eei.workflow_definition_url = 'ee'
|
|
403
|
+
@eei.workflow_definition_name = 'ee'
|
|
404
|
+
@eei.workflow_definition_revision = '0'
|
|
405
|
+
@eei.workflow_instance_id = '0'
|
|
406
|
+
@eei.expression_name = EN_ENVIRONMENT
|
|
407
|
+
@eei.expression_id = '0'
|
|
408
|
+
return @eei
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
protected
|
|
413
|
+
|
|
414
|
+
def evaluate_definition (raw_definition, workitem)
|
|
415
|
+
expression = raw_definition.instantiate(workitem)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def remove_environment (environment_id)
|
|
419
|
+
env, fei = fetch(environment_id)
|
|
420
|
+
env.unbind()
|
|
421
|
+
get_expression_storage().remove(environment_id, nil)
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def build_workitem (launchitem)
|
|
425
|
+
|
|
426
|
+
wi = InFlowWorkItem.new()
|
|
427
|
+
|
|
428
|
+
wi.attributes = launchitem.attributes.dup()
|
|
429
|
+
|
|
430
|
+
return wi
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def fetch_definition (launchitem)
|
|
434
|
+
|
|
435
|
+
wfdUrl = launchitem.workflow_definition_url
|
|
436
|
+
|
|
437
|
+
#ldebug { "wfdUrl is '#{wfdUrl}'" }
|
|
438
|
+
|
|
439
|
+
sDefinition = nil
|
|
440
|
+
wfdField = nil
|
|
441
|
+
|
|
442
|
+
if wfdUrl[0..5] == 'field:'
|
|
443
|
+
wfdField = wfdUrl[6..-1]
|
|
444
|
+
sDefinition = launchitem.attributes[wfdField]
|
|
445
|
+
else
|
|
446
|
+
sDefinition = NET::HTTP.get(URI.parse(wfdUrl))
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
#ldebug { "sDefinition is \n#{sDefinition}" }
|
|
450
|
+
|
|
451
|
+
launchitem.attributes.delete(wfdField) if wfdField
|
|
452
|
+
|
|
453
|
+
if sDefinition.kind_of? String
|
|
454
|
+
|
|
455
|
+
xmlRoot = REXML::Document.new(sDefinition).root
|
|
456
|
+
class << xmlRoot
|
|
457
|
+
def rawExpressionClass
|
|
458
|
+
XmlRawExpression
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
return xmlRoot
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
if sDefinition.kind_of? ProgExpRepresentation
|
|
465
|
+
|
|
466
|
+
return sDefinition
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
if sDefinition.kind_of? ProcessDefinition
|
|
470
|
+
|
|
471
|
+
return sDefinition.make()
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
if sDefinition.kind_of? Class
|
|
475
|
+
|
|
476
|
+
return sDefinition.do_make(get_expression_map)
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
raise \
|
|
480
|
+
"Cannot deduce process definition " +
|
|
481
|
+
"out of instance of class #{sDefinition.class}"
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def new_fei (flow_url, flow_name, flow_revision, exp_name)
|
|
485
|
+
|
|
486
|
+
fei = FlowExpressionId.new
|
|
487
|
+
|
|
488
|
+
fei.owfe_version = OPENWFE_VERSION
|
|
489
|
+
fei.engine_id = get_engine.service_name
|
|
490
|
+
fei.initial_engine_id = fei.engine_id
|
|
491
|
+
fei.workflow_definition_url = flow_url
|
|
492
|
+
fei.workflow_definition_name = flow_name
|
|
493
|
+
fei.workflow_definition_revision = flow_revision
|
|
494
|
+
fei.workflow_instance_id = new_workflow_instance_id()
|
|
495
|
+
fei.expression_id = "0"
|
|
496
|
+
fei.expression_name = exp_name
|
|
497
|
+
return fei
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def new_workflow_instance_id ()
|
|
501
|
+
synchronize do
|
|
502
|
+
wfid = OpenWFE::current_time_millis()
|
|
503
|
+
wfid = wfid + 1 if wfid == @@last_given_instance_id
|
|
504
|
+
@@last_given_instance_id = wfid
|
|
505
|
+
return wfid.to_s
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
#
|
|
510
|
+
# Builds the RawExpression instance at the root of the flow
|
|
511
|
+
# being launched.
|
|
512
|
+
#
|
|
513
|
+
def buildRawExpression (launchitem)
|
|
514
|
+
|
|
515
|
+
procdef = fetch_definition(launchitem)
|
|
516
|
+
|
|
517
|
+
flow_url = launchitem.workflow_definition_url
|
|
518
|
+
flow_name = procdef.attributes['name']
|
|
519
|
+
flow_revision = procdef.attributes['revision']
|
|
520
|
+
exp_name = procdef.name
|
|
521
|
+
|
|
522
|
+
fei = new_fei(flow_url, flow_name, flow_revision, exp_name)
|
|
523
|
+
|
|
524
|
+
#puts procdef.rawExpressionClass
|
|
525
|
+
#puts procdef.rawExpressionClass.public_methods
|
|
526
|
+
|
|
527
|
+
return procdef.rawExpressionClass\
|
|
528
|
+
.new(fei, nil, nil, @application_context, procdef)
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
end
|
|
534
|
+
|