openwferu-extras 0.9.16 → 0.9.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2007, John Mettraux OpenWFE.org
3
+ # Copyright (c) 2007-2008, John Mettraux, Tomaso Tosolini OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -37,11 +37,10 @@
37
37
  # John Mettraux at openwfe.org
38
38
  #
39
39
 
40
- require 'rubygems'
40
+ #require 'rubygems'
41
41
 
42
42
  #require_gem 'activerecord'
43
- gem 'activerecord'
44
- require 'active_record'
43
+ gem 'activerecord'; require 'active_record'
45
44
 
46
45
 
47
46
  require 'openwfe/workitem'
@@ -81,7 +80,12 @@ module Extras
81
80
  t.column :store_name, :string
82
81
  t.column :dispatch_time, :timestamp
83
82
  t.column :last_modified, :timestamp
83
+
84
+ t.column :yattributes, :text
85
+ # when using compact_workitems, attributes are stored here
86
+
84
87
  end
88
+ add_index :workitems, :fei, :unique => true
85
89
  add_index :workitems, :wfid
86
90
  add_index :workitems, :wf_name
87
91
  add_index :workitems, :wf_revision
@@ -90,12 +94,14 @@ module Extras
90
94
 
91
95
  create_table :fields do |t|
92
96
  t.column :fkey, :string, :null => false
97
+ t.column :vclass, :string, :null => false
93
98
  t.column :svalue, :string
94
99
  t.column :yvalue, :text
95
100
  t.column :workitem_id, :integer, :null => false
96
101
  end
97
102
  add_index :fields, [ :workitem_id, :fkey ], :unique => true
98
103
  add_index :fields, :fkey
104
+ add_index :fields, :vclass
99
105
  add_index :fields, :svalue
100
106
  end
101
107
 
@@ -109,7 +115,7 @@ module Extras
109
115
  #
110
116
  # Reopening InFlowWorkItem to add a 'db_id' attribute.
111
117
  #
112
- class InFlowWorkItem
118
+ class OpenWFE::InFlowWorkItem
113
119
 
114
120
  attr_accessor :db_id
115
121
  end
@@ -146,6 +152,9 @@ module Extras
146
152
 
147
153
  has_many :fields, :dependent => :destroy
148
154
 
155
+ serialize :yattributes
156
+
157
+
149
158
  #
150
159
  # Returns the flow expression id of this work (its unique OpenWFEru
151
160
  # identifier) as a FlowExpressionId instance.
@@ -182,8 +191,22 @@ module Extras
182
191
 
183
192
  i.store_name = store_name
184
193
 
185
- wi.attributes.each do |k, v|
186
- i.fields << Field.new_field(k, v)
194
+
195
+ # This is a field set by the active participant immediately
196
+ # before calling this method.
197
+ # the default behavior is "use field method"
198
+
199
+ if wi.attributes["compact_workitems"]
200
+
201
+ wi.attributes.delete("compact_workitems")
202
+ i.yattributes= wi.attributes
203
+ else
204
+
205
+ i.yattributes= nil
206
+
207
+ wi.attributes.each do |k, v|
208
+ i.fields << Field.new_field(k, v)
209
+ end
187
210
  end
188
211
 
189
212
  i.save!
@@ -217,11 +240,12 @@ module Extras
217
240
  #
218
241
  def fields_hash
219
242
 
220
- h = {}
221
- fields.each do |f|
222
- h[f.fkey] = f.value
243
+ return self.yattributes if self.yattributes
244
+
245
+ fields.inject({}) do |r, f|
246
+ r[f.fkey] = f.value
247
+ r
223
248
  end
224
- h
225
249
  end
226
250
 
227
251
  #
@@ -231,10 +255,17 @@ module Extras
231
255
  #
232
256
  def replace_fields (fhash)
233
257
 
234
- fields.delete_all
258
+ if self.yattributes
235
259
 
236
- fhash.each do |k, v|
237
- fields << Field.new_field(k, v)
260
+ self.yattributes = fhash
261
+
262
+ else
263
+
264
+ fields.delete_all
265
+
266
+ fhash.each do |k, v|
267
+ fields << Field.new_field(k, v)
268
+ end
238
269
  end
239
270
 
240
271
  #f = Field.new_field("___map_type", "smap")
@@ -253,8 +284,12 @@ module Extras
253
284
  # wi.field :customer_name
254
285
  #
255
286
  def field (key)
287
+
288
+ if self.yattributes
289
+ return self.yattributes[key.to_s]
290
+ end
256
291
 
257
- fields.find_by_fkey(key.to_s)
292
+ fields.find_by_fkey key.to_s
258
293
  end
259
294
 
260
295
  #
@@ -273,6 +308,15 @@ module Extras
273
308
  alias :forward :reply
274
309
  alias :proceed :reply
275
310
 
311
+ #
312
+ # Simply sets the 'last_modified' field to now.
313
+ # (Doesn't save the workitem though).
314
+ #
315
+ def touch
316
+
317
+ self.last_modified = Time.now
318
+ end
319
+
276
320
  #
277
321
  # Opening engine to update its reply method to accept these
278
322
  # active record workitems.
@@ -303,7 +347,7 @@ module Extras
303
347
  # The result is a Hash whose keys are the store names and whose
304
348
  # values are list of workitems.
305
349
  #
306
- def Workitem.find_in_stores (storename_list)
350
+ def self.find_in_stores (storename_list)
307
351
 
308
352
  workitems = find_all_by_store_name(storename_list)
309
353
 
@@ -319,7 +363,15 @@ module Extras
319
363
  #
320
364
  # A kind of 'google search' among workitems
321
365
  #
322
- def Workitem.search (search_string, storename_list=nil)
366
+ # == Note
367
+ #
368
+ # when this is used on compact_workitems, it will not be able to search
369
+ # info within the fields, because they aren't used by this kind of
370
+ # workitems. In this case the search will be limited to participant_name
371
+ #
372
+ def self.search (search_string, storename_list=nil)
373
+
374
+ #t = OpenWFE::Timer.new
323
375
 
324
376
  storename_list = Array(storename_list) if storename_list
325
377
 
@@ -334,49 +386,54 @@ module Extras
334
386
 
335
387
  ids = result.collect { |wi| wi.id }
336
388
 
337
- # svalue
338
-
339
- fields = Field.find(
340
- :all,
341
- :conditions => conditions(
342
- "svalue", search_string, storename_list),
343
- :include => :workitem)
344
-
345
- merge_search_results(ids, result, fields)
389
+ # search in fields
346
390
 
347
- # fkey
391
+ fields = Field.search search_string, storename_list
392
+ merge_search_results ids, result, fields
348
393
 
349
- fields = Field.find(
350
- :all,
351
- :conditions => conditions(
352
- "fkey", search_string, storename_list),
353
- :include => :workitem)
354
-
355
- merge_search_results(ids, result, fields)
394
+ #puts "... took #{t.duration} ms"
356
395
 
357
396
  # over.
358
397
 
359
398
  result
360
399
  end
361
400
 
401
+ #
402
+ # Not really about 'just launched', but rather about finding the first
403
+ # workitem for a given process instance (wfid) and a participant.
404
+ # It deserves its own method because the workitem could be in a
405
+ # subprocess, thus escaping the vanilla find_by_wfid_and_participant()
406
+ #
407
+ def self.find_just_launched (wfid, participant_name)
408
+
409
+ find(
410
+ :first,
411
+ :conditions => [
412
+ "wfid LIKE ? AND participant_name = ?",
413
+ "#{wfid}%",
414
+ participant_name ])
415
+ end
416
+
362
417
  protected
363
418
 
364
419
  #
365
420
  # builds the condition (the WHERE clause) for the
366
421
  # search.
367
422
  #
368
- def Workitem.conditions (keyname, search_string, storename_list)
423
+ def self.conditions (keyname, search_string, storename_list)
424
+
425
+ cs = [ "#{keyname} LIKE ?", search_string ]
369
426
 
370
427
  if storename_list
371
- [ "#{keyname} LIKE ? AND workitems.store_name IN (?)",
372
- search_string, storename_list ]
373
- else
374
- [ "#{keyname} LIKE ?",
375
- search_string ]
428
+
429
+ cs[0] = "#{cs[0]} AND workitems.store_name IN (?)"
430
+ cs << storename_list
376
431
  end
432
+
433
+ cs
377
434
  end
378
435
 
379
- def Workitem.merge_search_results (ids, wis, new_wis)
436
+ def self.merge_search_results (ids, wis, new_wis)
380
437
 
381
438
  return if new_wis.size < 1
382
439
 
@@ -414,13 +471,16 @@ module Extras
414
471
 
415
472
  f = Field.new
416
473
  f.fkey = key
474
+ f.vclass = value.class.to_s
417
475
  f.value = value
418
476
  f
419
477
  end
420
478
 
421
479
  def value= (v)
422
480
 
423
- if v.is_a?(String)
481
+ limit = connection.native_database_types[:string][:limit]
482
+
483
+ if v.is_a?(String) and v.length <= limit
424
484
  self.svalue = v
425
485
  else
426
486
  self.yvalue = v
@@ -429,9 +489,72 @@ module Extras
429
489
 
430
490
  def value
431
491
 
432
- return self.svalue if self.svalue
433
- self.yvalue
492
+ self.svalue || self.yvalue
493
+ end
494
+
495
+ #
496
+ # Will return all the fields that contain the given text.
497
+ #
498
+ # Looks in svalue and fkey. Looks as well in yvalue if it contains
499
+ # a string.
500
+ #
501
+ # This method is used by Workitem.search()
502
+ #
503
+ def self.search (text, storename_list=nil)
504
+
505
+ cs = build_search_conditions(text)
506
+
507
+ if storename_list
508
+
509
+ cs[0] = "(#{cs[0]}) AND workitems.store_name IN (?)"
510
+ cs << storename_list
511
+ end
512
+
513
+ find :all, :conditions => cs, :include => :workitem
434
514
  end
515
+
516
+ protected
517
+
518
+ #
519
+ # The search operates on the content of these columns
520
+ #
521
+ FIELDS_TO_SEARCH = %w{ svalue fkey yvalue }
522
+
523
+ #
524
+ # Builds the condition array for a pseudo text search
525
+ #
526
+ def self.build_search_conditions (text)
527
+
528
+ has_percent = (text.index("%") != nil)
529
+
530
+ conds = []
531
+
532
+ conds << FIELDS_TO_SEARCH.collect { |key|
533
+
534
+ count = has_percent ? 1 : 4
535
+
536
+ s = ([ "#{key} LIKE ?" ] * count).join(" OR ")
537
+
538
+ s = "(vclass = ? AND (#{s}))" if key == 'yvalue'
539
+
540
+ s
541
+ }.join(" OR ")
542
+
543
+ FIELDS_TO_SEARCH.each do |key|
544
+
545
+ conds << 'String' if key == 'yvalue'
546
+
547
+ conds << text
548
+
549
+ unless has_percent
550
+ conds << "% #{text} %"
551
+ conds << "% #{text}"
552
+ conds << "#{text} %"
553
+ end
554
+ end
555
+
556
+ conds
557
+ end
435
558
  end
436
559
 
437
560
 
@@ -469,16 +592,46 @@ module Extras
469
592
  # # ...
470
593
  # end
471
594
  #
595
+ # == Compact workitems
596
+ #
597
+ # It is possible to save all the workitem data into a single table,
598
+ # the workitems table, without
599
+ # splitting info between workitems and fields tables.
600
+ #
601
+ # You can configure the "compact_workitems" behavior by adding to the
602
+ # previous lines:
603
+ #
604
+ # active0 = engine.register_participant(
605
+ # :active0, OpenWFE::Extras::ActiveParticipant)
606
+ #
607
+ # active0.compact_workitems = true
608
+ #
609
+ # This behaviour is determined participant per participant, it's ok to
610
+ # have a participant instance that compacts will there is another that
611
+ # doesn't compact.
612
+ #
472
613
  class ActiveParticipant
473
614
  include OpenWFE::LocalParticipant
474
615
 
616
+ #
617
+ # when compact_workitems is set to true, the attributes of a workitem
618
+ # are stored in the yattributes column (they are not expanded into
619
+ # the Fields table).
620
+ # By default, workitem attributes are expanded.
621
+ #
622
+ attr :compact_workitems, true
623
+
475
624
  #
476
625
  # This is the method called by the OpenWFEru engine to hand a
477
626
  # workitem to this participant.
478
627
  #
479
628
  def consume (workitem)
480
629
 
481
- Workitem.from_owfe_workitem(workitem)
630
+ if compact_workitems
631
+ workitem.attributes["compact_workitems"] = true
632
+ end
633
+
634
+ Workitem.from_owfe_workitem workitem
482
635
  end
483
636
 
484
637
  #
@@ -533,6 +686,10 @@ module Extras
533
686
  #
534
687
  def consume (workitem)
535
688
 
689
+ if compact_workitems
690
+ workitem.attributes["compact_workitems"] = true
691
+ end
692
+
536
693
  Workitem.from_owfe_workitem(workitem, @store_name)
537
694
  end
538
695
 
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2007, John Mettraux, OpenWFE.org
3
+ # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -47,23 +47,8 @@
47
47
 
48
48
  require 'monitor'
49
49
 
50
- require 'rubygems'
51
-
52
- begin
53
- require 'atom/collection'
54
- rescue LoadError
55
- #
56
- # soft dependency on 'atom-tools'
57
- #
58
- puts
59
- puts
60
- puts "'atom/collection' is missing. You can install with :"
61
- puts
62
- puts " [sudo] gem install atom-tools"
63
- puts
64
- puts
65
- exit 1
66
- end
50
+ #require 'rubygems'
51
+ require 'atom/collection' # gem 'atom-tools'
67
52
 
68
53
  require 'openwfe/participants/participant'
69
54
 
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2007, John Mettraux, OpenWFE.org
3
+ # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -50,27 +50,9 @@ require 'rexml/document'
50
50
 
51
51
  require 'openwfe/participants/participants'
52
52
 
53
- require 'rubygems'
54
-
55
- begin
56
- require 'atom/entry'
57
- require 'atom/collection'
58
- rescue LoadError
59
- #
60
- # soft dependency on 'atom-tools'
61
- #
62
- puts
63
- puts
64
- puts "'atom/collection' is missing. You can install with :"
65
- puts
66
- puts " [sudo] gem install atom-tools"
67
- puts
68
- puts
69
- exit 1
70
- end
71
-
72
- require 'openwfe/participants/participant'
73
- require 'openwfe/participants/participants'
53
+ #require 'rubygems'
54
+ require 'atom/entry' # gem 'atom-tools'
55
+ require 'atom/collection'
74
56
 
75
57
 
76
58
  module OpenWFE::Extras