openwferu 0.9.10.653 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/README.txt +65 -33
  2. data/examples/README.txt +4 -0
  3. data/examples/flowtracing.rb +2 -0
  4. data/examples/homeworkreview.rb +2 -0
  5. data/examples/mano_tracker.rb +2 -0
  6. data/examples/openwferu.rb +3 -1
  7. data/examples/quotereporter.rb +2 -0
  8. data/examples/scheduler_cron_usage.rb +3 -1
  9. data/examples/scheduler_usage.rb +3 -1
  10. data/lib/openwfe/engine/engine.rb +15 -5
  11. data/lib/openwfe/expool/expressionpool.rb +30 -4
  12. data/lib/openwfe/expool/journal.rb +16 -18
  13. data/lib/openwfe/expool/journal_replay.rb +56 -8
  14. data/lib/openwfe/expool/wfidgen.rb +17 -8
  15. data/lib/openwfe/expressions/condition.rb +41 -26
  16. data/lib/openwfe/expressions/expressionmap.rb +7 -0
  17. data/lib/openwfe/expressions/fe_cancel.rb +1 -1
  18. data/lib/openwfe/expressions/fe_concurrence.rb +14 -5
  19. data/lib/openwfe/expressions/fe_cron.rb +3 -1
  20. data/lib/openwfe/expressions/fe_cursor.rb +1 -1
  21. data/lib/openwfe/expressions/fe_fqv.rb +58 -0
  22. data/lib/openwfe/expressions/fe_if.rb +1 -1
  23. data/lib/openwfe/expressions/fe_iterator.rb +5 -0
  24. data/lib/openwfe/expressions/fe_listen.rb +224 -0
  25. data/lib/openwfe/expressions/fe_misc.rb +32 -9
  26. data/lib/openwfe/expressions/fe_participant.rb +26 -6
  27. data/lib/openwfe/expressions/fe_sleep.rb +5 -7
  28. data/lib/openwfe/expressions/fe_timeout.rb +127 -0
  29. data/lib/openwfe/expressions/fe_when.rb +13 -1
  30. data/lib/openwfe/expressions/flowexpression.rb +4 -1
  31. data/lib/openwfe/expressions/time.rb +10 -27
  32. data/lib/openwfe/expressions/timeout.rb +23 -6
  33. data/lib/openwfe/flowexpressionid.rb +7 -6
  34. data/lib/openwfe/listeners/socketlisteners.rb +1 -1
  35. data/lib/openwfe/participants/enoparticipants.rb +103 -47
  36. data/lib/openwfe/participants/participant.rb +29 -3
  37. data/lib/openwfe/participants/participantmap.rb +10 -2
  38. data/lib/openwfe/participants/participants.rb +31 -19
  39. data/lib/openwfe/participants/socketparticipants.rb +3 -1
  40. data/lib/openwfe/rest/controlclient.rb +5 -18
  41. data/lib/openwfe/rest/oldrestservlet.rb +279 -0
  42. data/lib/openwfe/rest/restclient.rb +55 -25
  43. data/lib/openwfe/rest/worklistclient.rb +35 -44
  44. data/lib/openwfe/rest/xmlcodec.rb +79 -69
  45. data/lib/openwfe/rudefinitions.rb +15 -7
  46. data/lib/openwfe/storage/yamlextras.rb +3 -3
  47. data/lib/openwfe/util/observable.rb +64 -7
  48. data/lib/openwfe/util/scheduler.rb +107 -77
  49. data/lib/openwfe/util/workqueue.rb +5 -11
  50. data/lib/openwfe/utils.rb +3 -3
  51. data/lib/openwfe/version.rb +1 -2
  52. data/lib/openwfe/workitem.rb +3 -4
  53. data/lib/openwfe/worklist/oldrest.rb +244 -0
  54. data/lib/openwfe/worklist/storelocks.rb +288 -0
  55. data/lib/openwfe/worklist/storeparticipant.rb +4 -2
  56. data/lib/openwfe/worklist/worklist.rb +297 -0
  57. data/test/cron_test.rb +8 -9
  58. data/test/eno_test.rb +10 -13
  59. data/test/flowtestbase.rb +26 -17
  60. data/test/ft_15_iterator.rb +19 -0
  61. data/test/ft_23c_wait.rb +2 -2
  62. data/test/ft_2b_concurrence.rb +2 -2
  63. data/test/ft_30_socketlistener.rb +5 -1
  64. data/test/ft_32_journal.rb +1 -1
  65. data/test/ft_32c_journal.rb +102 -0
  66. data/test/ft_32d_journal.rb +85 -0
  67. data/test/ft_45_citerator.rb +25 -0
  68. data/test/ft_49_condition.rb +60 -2
  69. data/test/ft_4_misc.rb +15 -0
  70. data/test/ft_50_xml_attribute.rb +4 -4
  71. data/test/ft_53_null_noop_participant.rb +66 -0
  72. data/test/ft_54_listen.rb +223 -0
  73. data/test/ft_55_ptimeout.rb +64 -0
  74. data/test/ft_56_timeout.rb +55 -0
  75. data/test/ft_57_a.rb +109 -0
  76. data/test/ft_tests.rb +7 -0
  77. data/test/hparticipant_test.rb +3 -3
  78. data/test/obs_test.rb +115 -0
  79. data/test/orest_test.rb +224 -0
  80. data/test/pending.rb +24 -0
  81. data/test/rake_qtest.rb +5 -1
  82. data/test/rake_test.rb +4 -0
  83. data/test/scheduler_test.rb +31 -2
  84. data/test/sec_test.rb +7 -3
  85. data/test/slock_test.rb +82 -0
  86. metadata +19 -3
  87. data/test/ft_32b_journal.rb +0 -76
@@ -81,9 +81,15 @@ module OpenWFE
81
81
  #
82
82
  # regenerator = Regenerator.new
83
83
  #
84
- # scheduler.schedule_in("4d", regenerator, :monthly)
84
+ # scheduler.schedule_in("4d", regenerator)
85
85
  # #
86
- # # will regenerate the monthly report in four days
86
+ # # will regenerate the report in four days
87
+ #
88
+ # scheduler.schedule_in(
89
+ # "5d",
90
+ # { :schedulable => regenerator, :scope => :month })
91
+ # #
92
+ # # will regenerate the monthly report in 5 days
87
93
  #
88
94
  # There is also schedule_every() :
89
95
  #
@@ -178,9 +184,11 @@ module OpenWFE
178
184
  # Schedules a job by specifying at which time it should trigger.
179
185
  # Returns the a job_id that can be used to unschedule the job.
180
186
  #
181
- def schedule_at (at, schedulable=nil, params=nil, &block)
187
+ def schedule_at (at, params={}, &block)
188
+
189
+ params = prepare_params(params)
182
190
 
183
- sschedule_at(false, at, nil, schedulable, params, &block)
191
+ sschedule_at(at, params, &block)
184
192
  end
185
193
 
186
194
 
@@ -188,12 +196,12 @@ module OpenWFE
188
196
  # Schedules a job by stating in how much time it should trigger.
189
197
  # Returns the a job_id that can be used to unschedule the job.
190
198
  #
191
- def schedule_in (duration, schedulable=nil, params=nil, &block)
199
+ def schedule_in (duration, params={}, &block)
192
200
 
193
201
  duration = duration_to_f(duration)
202
+ params = prepare_params(params)
194
203
 
195
- return schedule_at(
196
- Time.new.to_f + duration, schedulable, params, &block)
204
+ schedule_at(Time.new.to_f + duration, params, &block)
197
205
  end
198
206
 
199
207
  #
@@ -210,9 +218,29 @@ module OpenWFE
210
218
  # end
211
219
  # end
212
220
  #
213
- def schedule_every (freq, schedulable=nil, params=nil, &block)
221
+ def schedule_every (freq, params={}, &block)
222
+
223
+ f = duration_to_f freq
224
+
225
+ params = prepare_params params
226
+ schedulable = params[:schedulable]
227
+ params[:every] = true
214
228
 
215
- sschedule_every(freq, nil, schedulable, params, &block)
229
+ sschedule_at Time.new.to_f + f, params do |job_id, at|
230
+
231
+ params[:job_id] = job_id
232
+
233
+ if schedulable
234
+ schedulable.trigger(params)
235
+ else
236
+ block.call job_id, at
237
+ end
238
+
239
+ schedule_every(f, params, &block) \
240
+ unless @dont_reschedule_every
241
+
242
+ job_id
243
+ end
216
244
  end
217
245
 
218
246
  #
@@ -224,14 +252,12 @@ module OpenWFE
224
252
 
225
253
  for i in 0...@pending_jobs.length
226
254
  if @pending_jobs[i].eid == job_id
227
- @pending_jobs.delete_at(i)
255
+ @pending_jobs.delete_at i
228
256
  return true
229
257
  end
230
258
  end
231
259
 
232
- return true if unschedule_cron_job(job_id)
233
-
234
- return false
260
+ unschedule_cron_job job_id
235
261
  end
236
262
  end
237
263
 
@@ -241,10 +267,10 @@ module OpenWFE
241
267
  def unschedule_cron_job (job_id)
242
268
  synchronize do
243
269
  if @cron_entries.has_key?(job_id)
244
- @cron_entries.delete(job_id)
270
+ @cron_entries.delete job_id
245
271
  return true
246
272
  end
247
- return false
273
+ false
248
274
  end
249
275
  end
250
276
 
@@ -255,11 +281,11 @@ module OpenWFE
255
281
  #
256
282
  # For example :
257
283
  #
258
- # scheduler.schedule("5 0 * * *", nil, s, p)
259
- # # will trigger the schedulable s with params p every day
284
+ # scheduler.schedule("5 0 * * *", s)
285
+ # # will trigger the schedulable s every day
260
286
  # # five minutes after midnight
261
287
  #
262
- # scheduler.schedule("15 14 1 * *", nil, s, p)
288
+ # scheduler.schedule("15 14 1 * *", s)
263
289
  # # will trigger s at 14:15 on the first of every month
264
290
  #
265
291
  # scheduler.schedule("0 22 * * 1-5") do
@@ -270,29 +296,28 @@ module OpenWFE
270
296
  # Returns the job id attributed to this 'cron job', this id can
271
297
  # be used to unschedule the job.
272
298
  #
273
- def schedule (
274
- cron_line, cron_id=nil, schedulable=nil, params=nil, &block)
299
+ def schedule (cron_line, params={}, &block)
275
300
 
276
301
  synchronize do
302
+
303
+ params = prepare_params(params)
277
304
 
278
305
  #
279
306
  # is a job with the same id already scheduled ?
280
307
 
281
- if cron_id and unschedule(cron_id)
282
- ldebug do
283
- "schedule() unscheduled previous job "+
284
- "under same name '#{cron_id}'"
285
- end
286
- end
308
+ cron_id = params[:cron_id]
309
+ cron_id = params[:job_id] unless cron_id
310
+
311
+ unschedule(cron_id) if cron_id
287
312
 
288
313
  #
289
314
  # schedule
290
315
 
291
- b = to_block(schedulable, params, &block)
316
+ b = to_block(params, &block)
292
317
  entry = CronEntry.new(cron_id, cron_line, &b)
293
318
  @cron_entries[entry.eid] = entry
294
319
 
295
- return entry.eid
320
+ entry.eid
296
321
  end
297
322
  end
298
323
 
@@ -305,11 +330,9 @@ module OpenWFE
305
330
  entry = @cron_entries[job_id]
306
331
  return entry if entry
307
332
 
308
- @pending_jobs.each do |entry|
309
- return entry if entry.eid == job_id
333
+ @pending_jobs.find do |entry|
334
+ entry.eid == job_id
310
335
  end
311
-
312
- return nil
313
336
  end
314
337
 
315
338
  #
@@ -323,7 +346,8 @@ module OpenWFE
323
346
  j = get_job(job_id)
324
347
 
325
348
  return j.schedulable if j.respond_to? :schedulable
326
- return nil
349
+
350
+ nil
327
351
  end
328
352
 
329
353
  #
@@ -359,34 +383,49 @@ module OpenWFE
359
383
  # Returns true if the given string seems to be a cron string.
360
384
  #
361
385
  def Scheduler.is_cron_string (s)
362
- return s.match(".+ .+ .+ .+ .+")
386
+ s.match(".+ .+ .+ .+ .+")
363
387
  end
364
388
 
365
389
  protected
366
390
 
367
- def sschedule_at (
368
- is_every, at, at_id, schedulable=nil, params=nil, &block)
391
+ #
392
+ # Making sure that params is a Hash.
393
+ #
394
+ def prepare_params (params)
395
+ params = { :schedulable => params } \
396
+ if params.is_a?(Schedulable)
397
+ params
398
+ end
399
+
400
+ def sschedule_at (at, params={}, &block)
369
401
 
370
402
  synchronize do
371
403
 
372
404
  #puts "0 at is '#{at.to_s}' (#{at.class})"
373
405
 
374
406
  at = OpenWFE::to_ruby_time(at) \
375
- if at.kind_of? String
407
+ if at.kind_of?(String)
376
408
 
377
409
  at = OpenWFE::to_gm_time(at) \
378
- if at.kind_of? DateTime
410
+ if at.kind_of?(DateTime)
379
411
 
380
412
  at = at.to_f \
381
- if at.kind_of? Time
413
+ if at.kind_of?(Time)
382
414
 
383
415
  #puts "1 at is '#{at.to_s}' (#{at.class})"}"
384
416
 
385
- jobClass = AtEntry
386
- jobClass = EveryEntry if is_every
417
+ jobClass = if params[:every]
418
+ EveryEntry
419
+ else
420
+ AtEntry
421
+ end
422
+
423
+ job_id = params[:job_id]
424
+
425
+ b = to_block(params, &block)
426
+ job = jobClass.new(at, job_id, &b)
387
427
 
388
- b = to_block(schedulable, params, &block)
389
- job = jobClass.new(at, at_id, &b)
428
+ unschedule(job_id) if job_id
390
429
 
391
430
  if at < (Time.new.to_f + @precision)
392
431
  job.trigger()
@@ -408,30 +447,10 @@ module OpenWFE
408
447
  end
409
448
  end
410
449
 
411
- return push(job)
450
+ push(job)
412
451
  end
413
452
  end
414
453
 
415
- def sschedule_every (freq, at_id, schedulable, params, &block)
416
-
417
- f = duration_to_f(freq)
418
-
419
- job_id = sschedule_at(
420
- true, Time.new.to_f + f, at_id) do |eid, at|
421
-
422
- if schedulable
423
- schedulable.trigger(params)
424
- else
425
- block.call eid, at
426
- end
427
-
428
- sschedule_every(f, eid, schedulable, params, &block) \
429
- unless @dont_reschedule_every
430
- end
431
-
432
- job_id
433
- end
434
-
435
454
  #
436
455
  # Ensures that a duration is a expressed as a Float instance.
437
456
  #
@@ -442,22 +461,33 @@ module OpenWFE
442
461
  def duration_to_f (s)
443
462
  return s if s.kind_of? Float
444
463
  return OpenWFE::parse_time_string(s) if s.kind_of? String
445
- return Float(s.to_s)
464
+ Float(s.to_s)
446
465
  end
447
466
 
448
- def to_block (schedulable, params, &block)
449
- if schedulable
450
- l = lambda do
451
- schedulable.trigger(params)
452
- end
453
- class << l
454
- attr_accessor :schedulable
455
- end
456
- l.schedulable = schedulable
457
- l
458
- else
459
- block
467
+ #
468
+ # Returns a block. If a block is passed, will return it, else,
469
+ # if a :schedulable is set in the params, will return a block
470
+ # wrapping a call to it.
471
+ #
472
+ def to_block (params, &block)
473
+
474
+ return block if block
475
+
476
+ schedulable = params[:schedulable]
477
+
478
+ return nil unless schedulable
479
+
480
+ params.delete :schedulable
481
+
482
+ l = lambda do
483
+ schedulable.trigger(params)
484
+ end
485
+ class << l
486
+ attr_accessor :schedulable
460
487
  end
488
+ l.schedulable = schedulable
489
+
490
+ l
461
491
  end
462
492
 
463
493
  #
@@ -60,8 +60,8 @@ module OpenWFE
60
60
 
61
61
  OpenWFE::call_in_thread "expression_pool", self do
62
62
  while true
63
- sleep @workqueue_frequency
64
63
  break if @workqueue_frequency == nil
64
+ sleep @workqueue_frequency
65
65
  do_process_workqueue
66
66
  end
67
67
  end
@@ -141,17 +141,11 @@ module OpenWFE
141
141
  #ldebug { "do_process_workqueue() #{q.size} items to process" }
142
142
 
143
143
  q.each do |elt|
144
- begin
145
-
146
- do_process_workelement elt
147
144
 
148
- rescue Exception => e
149
-
150
- lwarn do
151
- "#{self.service_name} caught an exception\n" +
152
- OpenWFE::exception_to_s(e)
153
- end
154
- end
145
+ do_process_workelement elt
146
+ #
147
+ # exception management is now done in the
148
+ # do_process_workelement method
155
149
  end
156
150
  end
157
151
 
data/lib/openwfe/utils.rb CHANGED
@@ -232,10 +232,10 @@ module OpenWFE
232
232
  # Attempts at displaying a nice stack trace
233
233
  #
234
234
  def OpenWFE.exception_to_s (exception)
235
- s = ""
235
+ s = "exception : "
236
236
  s << "#{exception}\n"
237
237
  s << exception.backtrace.join("\n")
238
- return s
238
+ s
239
239
  end
240
240
 
241
241
  #
@@ -247,7 +247,7 @@ module OpenWFE
247
247
  break if max_lines and index >= max_lines
248
248
  s << " #{line}\n"
249
249
  end
250
- return s
250
+ s
251
251
  end
252
252
 
253
253
  #
@@ -34,6 +34,5 @@
34
34
  #
35
35
 
36
36
  module OpenWFE
37
- #OPENWFERU_VERSION = '0.9.10'
38
- OPENWFERU_VERSION = '0.9.10.653'
37
+ OPENWFERU_VERSION = '0.9.11'
39
38
  end
@@ -472,12 +472,11 @@ module OpenWFE
472
472
 
473
473
  #
474
474
  # A header is a summary of a workitem, returned by the getHeader
475
- # worklist method
475
+ # worklist method.
476
476
  #
477
- class Header
477
+ class Header < InFlowWorkItem
478
478
 
479
- attr_accessor \
480
- :last_modified, :locked, :flow_expression_id, :attributes
479
+ attr_accessor :locked
481
480
  end
482
481
 
483
482
 
@@ -0,0 +1,244 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 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
+
34
+ #
35
+ # "made in Japan"
36
+ #
37
+ # John Mettraux at openwfe.org
38
+ #
39
+
40
+ require 'rexml/element'
41
+ require 'openwfe/rest/xmlcodec'
42
+ require 'openwfe/rest/oldrestservlet'
43
+
44
+
45
+ module OpenWFE
46
+
47
+ #
48
+ # This webrick servlet provides a REST interface for an old style
49
+ # OpenWFE worklist.
50
+ #
51
+ class OldRestWorklistServlet < OldRestServlet
52
+
53
+ def initialize (server, params)
54
+ super
55
+ @worklist = params[:Worklist]
56
+ end
57
+
58
+ #
59
+ # The realm for HTTP authentication.
60
+ #
61
+ def get_realm_name
62
+ "worklist"
63
+ end
64
+
65
+ #
66
+ # Lists the stores in the worklist
67
+ #
68
+ def do__getstorenames (req, res)
69
+
70
+ e = REXML::Element.new 'stores'
71
+
72
+ @worklist.each_store do |regex, store_name, store|
73
+
74
+ perms = @worklist.get_permissions(
75
+ req.attributes['username'], store_name)
76
+
77
+ es = REXML::Element.new 'store'
78
+ es.add_attribute 'name', store_name
79
+ es.add_attribute 'workitem-count', store.size
80
+ es.add_attribute 'permissions', perms
81
+ e << es
82
+ end
83
+
84
+ reply_with_xml res, 200, e
85
+ end
86
+
87
+ alias :do__liststores :do__getstorenames
88
+
89
+ #
90
+ # This implementation simply encodes the workitem, no transformation
91
+ # into headers at all.
92
+ #
93
+ def do__getheaders (req, res)
94
+
95
+ limit = req.query['limit']
96
+ limit = limit.to_s.to_i if limit
97
+ limit = nil if limit and limit < 1
98
+
99
+ hs = @worklist.get_headers(
100
+ req.attributes['username'],
101
+ get_store_name(req),
102
+ limit)
103
+
104
+ # TODO raise "404 no store named '#{store_name}'" unless store
105
+ # TODO raise "403 forbidden"
106
+
107
+ e = REXML::Element.new 'headers'
108
+
109
+ hs.each do |h|
110
+
111
+ workitem, locked = h
112
+
113
+ e << OpenWFE::XmlCodec::encode_workitem_as_header(
114
+ workitem, locked)
115
+ end
116
+
117
+ reply_with_xml res, 200, e
118
+ end
119
+
120
+ #
121
+ # Launches a new process instance.
122
+ #
123
+ def do__launchflow (req, res)
124
+
125
+ engine_name = req.query['engineid']
126
+ engine_name = "__nil__" unless engine_name
127
+
128
+ launch_item = OpenWFE::XmlCodec::decode req.body
129
+
130
+ r = @worklist.launch_flow engine_name, launch_item
131
+
132
+ e = REXML::Element.new 'ok'
133
+
134
+ e.add_attribute 'flow-id', r.to_s
135
+
136
+ reply_with_xml res, 200, e
137
+ end
138
+
139
+ #
140
+ # Retrieves a workitem from the worklist
141
+ #
142
+ def do__getworkitem (req, res)
143
+
144
+ execute_wi_get :get, req, res
145
+ end
146
+
147
+ #
148
+ # Retrieves a workitem from the worklist, locks it and returns it
149
+ #
150
+ def do__getandlockworkitem (req, res)
151
+
152
+ execute_wi_get :get_and_lock, req, res
153
+ end
154
+
155
+ #
156
+ # Returns the flow expression ids of the workitems with a given
157
+ # workflow instance id in a store.
158
+ #
159
+ def do__findflowinstance (req, res)
160
+
161
+ store_name = get_store_name req
162
+
163
+ wfid = req.query['id']
164
+ raise "404 'id' not specified" unless wfid
165
+
166
+ wis = @worklist.list_workitems(
167
+ req.attributes['username'], store_name, wfid)
168
+
169
+ e = REXML::Element.new 'stores'
170
+
171
+ wis.each do |wi|
172
+ e << OpenWFE::XmlCodec::encode(wi.fei)
173
+ end
174
+
175
+ reply_with_xml res, 200, e
176
+ end
177
+
178
+ #
179
+ # Releases a workitem (unlocks it).
180
+ #
181
+ def do__releaseworkitem (req, res)
182
+
183
+ execute_wi_post :release, req, res
184
+ end
185
+
186
+ #
187
+ # Simply saves the workitem and the modifications done to it.
188
+ #
189
+ def do__saveworkitem (req, res)
190
+
191
+ execute_wi_post :save, req, res
192
+ end
193
+
194
+ #
195
+ # Forwards the workitem (makes the worklist reply to the engine
196
+ # with the modified workitem)
197
+ #
198
+ def do__forwardworkitem (req, res)
199
+
200
+ execute_wi_post :forward, req, res
201
+ end
202
+
203
+ protected
204
+
205
+ def execute_wi_post (method, req, res)
206
+
207
+ store_name = get_store_name req
208
+
209
+ wi = OpenWFE::XmlCodec::decode req.body
210
+
211
+ @worklist.send(
212
+ method,
213
+ req.attributes['username'],
214
+ store_name,
215
+ wi)
216
+ end
217
+
218
+ def execute_wi_get (method, req, res)
219
+
220
+ store_name = get_store_name req
221
+ fei = OpenWFE::XmlCodec::decode req.body
222
+
223
+ wi = @worklist.send(
224
+ method, req.attributes['username'], store_name, fei)
225
+
226
+ raise "404 no workitem found for #{fei.to_s}" unless wi
227
+
228
+ reply_with_wi res, wi
229
+ end
230
+
231
+ def reply_with_wi (res, wi)
232
+
233
+ reply_with_xml res, 200, OpenWFE::XmlCodec::encode(wi)
234
+ end
235
+
236
+ def get_store_name (req)
237
+
238
+ ss = req.path.split("/")
239
+ raise "404 'store' not specified" if ss.length != 3
240
+ ss[-1]
241
+ end
242
+ end
243
+ end
244
+