openwferu 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/{README → README.txt} +16 -13
  2. data/bin/validate-workflow.rb +46 -22
  3. data/examples/README.txt +8 -0
  4. data/examples/homeworkreview.rb +66 -0
  5. data/examples/quotereporter.rb +154 -0
  6. data/lib/{openwferu.rb → openwfe.rb} +6 -8
  7. data/lib/{ru → openwfe}/contextual.rb +11 -3
  8. data/lib/{ru → openwfe/engine}/engine.rb +50 -36
  9. data/lib/{ru/participant.rb → openwfe/engine/file_persisted_engine.rb} +21 -22
  10. data/lib/openwfe/expool/expressionpool.rb +534 -0
  11. data/lib/openwfe/expool/expstorage.rb +184 -0
  12. data/lib/openwfe/expool/journalexpstorage.rb +312 -0
  13. data/lib/openwfe/expool/yamlexpstorage.rb +127 -0
  14. data/lib/{ru → openwfe/expressions}/environment.rb +19 -14
  15. data/lib/{ru → openwfe/expressions}/expressionmap.rb +48 -21
  16. data/lib/{ru → openwfe/expressions}/fe_concurrence.rb +111 -35
  17. data/lib/openwfe/expressions/fe_cursor.rb +236 -0
  18. data/lib/{ru → openwfe/expressions}/fe_define.rb +5 -5
  19. data/lib/openwfe/expressions/fe_fqv.rb +99 -0
  20. data/lib/openwfe/expressions/fe_iterator.rb +182 -0
  21. data/lib/{ru/fe_misc.rb → openwfe/expressions/fe_losfor.rb} +14 -56
  22. data/lib/openwfe/expressions/fe_misc.rb +102 -0
  23. data/lib/{ru → openwfe/expressions}/fe_participant.rb +25 -14
  24. data/lib/{ru → openwfe/expressions}/fe_raw.rb +39 -75
  25. data/lib/{ru/fe_base.rb → openwfe/expressions/fe_sequence.rb} +40 -35
  26. data/lib/{ru → openwfe/expressions}/fe_subprocess.rb +30 -14
  27. data/lib/{ru → openwfe/expressions}/fe_time.rb +59 -31
  28. data/lib/{ru → openwfe/expressions}/fe_utils.rb +42 -26
  29. data/lib/{ru → openwfe/expressions}/fe_value.rb +20 -14
  30. data/lib/openwfe/expressions/flowexpression.rb +434 -0
  31. data/lib/openwfe/expressions/raw_prog.rb +391 -0
  32. data/lib/openwfe/expressions/raw_xml.rb +128 -0
  33. data/lib/openwfe/flowexpressionid.rb +148 -0
  34. data/lib/{ru → openwfe}/logging.rb +10 -6
  35. data/lib/{osocket.rb → openwfe/osocket.rb} +36 -35
  36. data/lib/{otime.rb → openwfe/otime.rb} +71 -21
  37. data/lib/openwfe/participants/atomparticipants.rb +144 -0
  38. data/lib/openwfe/participants/enoparticipant.rb +73 -0
  39. data/lib/openwfe/participants/participant.rb +85 -0
  40. data/lib/{ru → openwfe/participants}/participantmap.rb +40 -12
  41. data/lib/{ru → openwfe/participants}/participants.rb +41 -12
  42. data/lib/openwfe/participants/soapparticipants.rb +96 -0
  43. data/lib/{controlclient.rb → openwfe/rest/controlclient.rb} +12 -13
  44. data/lib/{definitions.rb → openwfe/rest/definitions.rb} +3 -3
  45. data/lib/{exception.rb → openwfe/rest/exception.rb} +3 -3
  46. data/lib/{restclient.rb → openwfe/rest/restclient.rb} +13 -22
  47. data/lib/{worklistclient.rb → openwfe/rest/worklistclient.rb} +33 -46
  48. data/lib/openwfe/rest/xmlcodec.rb +575 -0
  49. data/lib/{ru → openwfe}/rudefinitions.rb +32 -4
  50. data/lib/{ru → openwfe}/service.rb +20 -8
  51. data/lib/openwfe/storage/yamlfilestorage.rb +159 -0
  52. data/lib/{ru → openwfe/util}/dollar.rb +10 -8
  53. data/lib/openwfe/util/lru_cache.rb +149 -0
  54. data/lib/{ru → openwfe/util}/scheduler.rb +18 -10
  55. data/lib/{ru → openwfe/util}/schedulers.rb +7 -7
  56. data/lib/{utils.rb → openwfe/utils.rb} +93 -9
  57. data/lib/openwfe/workitem.rb +366 -0
  58. data/lib/openwfe/worklist/worklists.rb +175 -0
  59. data/test/README.txt +27 -0
  60. data/test/atomtest.rb +99 -0
  61. data/test/crontest.rb +58 -0
  62. data/test/dollartest.rb +3 -3
  63. data/test/feitest.rb +42 -14
  64. data/test/file_persistence_test.rb +93 -0
  65. data/test/flowtestbase.rb +72 -26
  66. data/test/ft_0.rb +1 -97
  67. data/test/ft_0b_sequence.rb +33 -0
  68. data/test/ft_0c_testname.rb +29 -0
  69. data/test/ft_10_loop.rb +48 -0
  70. data/test/ft_11_ppd.rb +292 -0
  71. data/test/ft_12_blockparticipant.rb +45 -0
  72. data/test/ft_13_eno.rb +51 -0
  73. data/test/ft_14_subprocess.rb +90 -0
  74. data/test/ft_14b_subprocess.rb +40 -0
  75. data/test/ft_15_iterator.rb +70 -0
  76. data/test/ft_16_fqv.rb +57 -0
  77. data/test/ft_1_unset.rb +25 -1
  78. data/test/ft_2_concurrence.rb +10 -5
  79. data/test/ft_3_equals.rb +35 -1
  80. data/test/ft_4_misc.rb +16 -1
  81. data/test/ft_5_time.rb +26 -1
  82. data/test/ft_6_lambda.rb +2 -1
  83. data/test/{ft_7_losfor.rb → ft_7_lose.rb} +41 -35
  84. data/test/ft_8_forget.rb +46 -0
  85. data/test/ft_9_cursor.rb +94 -0
  86. data/test/journal_persistence_test.rb +147 -0
  87. data/test/misctest.rb +13 -9
  88. data/test/rake_ptest.rb +18 -0
  89. data/test/rake_qtest.rb +43 -0
  90. data/test/{fulltest.rb → rake_test.rb} +2 -2
  91. data/test/raw_prog_test.rb +236 -0
  92. data/test/rest_test.rb +189 -0
  93. data/test/rutest_utils.rb +1 -1
  94. data/test/timetest.rb +42 -34
  95. metadata +125 -82
  96. data/lib/codec.rb +0 -573
  97. data/lib/flowexpressionid.rb +0 -139
  98. data/lib/ru/expressionpool.rb +0 -382
  99. data/lib/ru/expressionstorage.rb +0 -99
  100. data/lib/ru/flowexpression.rb +0 -272
  101. data/lib/ru/ruutils.rb +0 -70
  102. data/lib/test.rb +0 -222
  103. data/lib/workitem.rb +0 -249
  104. 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 'ru/rudefinitions'
46
- require 'ru/service'
47
- require 'ru/expressionmap'
48
- require 'ru/expressionpool'
49
- require 'ru/expressionstorage'
50
- require 'ru/participantmap'
51
- require 'ru/schedulers'
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 OpenWFEru
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
- #attr_accessor \
59
- # :application_context
62
+ def initialize ()
60
63
 
61
- def initialize()
62
-
63
- super('engine', {})
64
+ super(S_ENGINE, {})
64
65
 
65
66
  @application_context[@service_name] = self
66
67
 
67
- @application_context[S_EXPRESSION_MAP] = build_expression_map()
68
- @application_context[S_EXPRESSION_POOL] = build_expression_pool()
69
- @application_context[S_EXPRESSION_STORAGE] = build_expression_storage()
70
- @application_context[S_PARTICIPANT_MAP] = build_participant_map()
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
- def launch(object)
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
- return @application_context[S_EXPRESSION_POOL].launch(launchitem)
103
+ get_expression_pool.launch(launchitem)
99
104
  end
100
105
 
101
106
  #
102
- # registers a participant in this [embedded] engine
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
- @application_context[S_PARTICIPANT_MAP]\
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
- ExpressionMap.new(S_EXPRESSION_MAP, @application_context)
124
+ init_service(S_EXPRESSION_MAP, ExpressionMap)
114
125
  end
115
126
 
116
127
  def build_expression_pool ()
117
- ExpressionPool.new(S_EXPRESSION_POOL, @application_context)
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
- ParticipantMap.new(S_PARTICIPANT_MAP, @application_context)
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
- #<tt>
3
- # Copyright (c) 2006, John Mettraux, OpenWFE.org
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
- #</tt>
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 'ru/contextual'
43
+ require 'openwfe/engine/engine'
44
+ require 'openwfe/expool/yamlexpstorage'
43
45
 
44
46
 
45
- module OpenWFEru
47
+ module OpenWFE
46
48
 
47
49
  #
48
- # The 'participant' concept is displayed as a module, so that
49
- # other pieces of code may easily 'mix it in'.
50
+ # An engine persisted to a tree of yaml files
50
51
  #
51
- module Participant
52
- include Contextual
52
+ class FilePersistedEngine < Engine
53
53
 
54
- #
55
- # a participant will be receiving workitems via this method
56
- #
57
- def consume (workitem)
58
- end
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
+