openwferu-extras 0.9.15 → 0.9.16

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.
@@ -0,0 +1,275 @@
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
+ #
41
+ # this participant requires atom-tools from
42
+ #
43
+ # http://code.necronomicorp.com/trac/atom-tools
44
+ #
45
+ # atom-tools' license is X11/MIT
46
+ #
47
+
48
+ #require 'monitor'
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
67
+
68
+ require 'openwfe/service'
69
+
70
+
71
+
72
+ module OpenWFE::Extras
73
+
74
+ #
75
+ # A workitem event as kept
76
+ #
77
+ class Entry
78
+
79
+ attr_accessor :id
80
+ attr_accessor :updated
81
+
82
+ attr_accessor :participant_name
83
+ attr_accessor :upon
84
+ attr_accessor :workitem
85
+
86
+ def initialize
87
+
88
+ @update = Time.now
89
+ end
90
+
91
+ def as_atom_entry
92
+
93
+ e = Atom::Entry.new
94
+
95
+ e.id = @id
96
+ e.updated = @updated
97
+
98
+ e
99
+ end
100
+ end
101
+
102
+ #
103
+ # This feed registers as an observer to the ParticipantMap.
104
+ # Each time a workitem is delivered to a participant or comes back from/for
105
+ # it, an AtomEntry is generated.
106
+ # The get_feed() method produces an atom feed of participant activity.
107
+ #
108
+ class ActivityFeedService
109
+ #include MonitorMixin
110
+ include ServiceMixin
111
+ include OwfeServiceLocator
112
+
113
+
114
+ attr_accessor :max_item_count
115
+
116
+
117
+ #
118
+ # This service is generally tied to an engine by doing :
119
+ #
120
+ # engine.init_service 'activityFeed', ActivityFeedService
121
+ #
122
+ # The init_service() will take care of calling the constructor
123
+ # implemented here.
124
+ #
125
+ def initialize (service_name, application_context)
126
+
127
+ super()
128
+
129
+ service_init service_name, application_context
130
+
131
+ @entries = []
132
+ @max_item_count = 100
133
+
134
+ get_participant_map.add_observer ".*", self
135
+ end
136
+
137
+ #
138
+ # This is the method call by the expression pool each time a
139
+ # workitem reaches a participant.
140
+ #
141
+ def call (channel, *args)
142
+
143
+ e = Entry.new
144
+
145
+ e.participant_name = channel
146
+ e.upon = args[0]
147
+ e.workitem = args[1].dup
148
+
149
+ e.id = \
150
+ "#{e.workitem.participant_name} - #{e.upon} " +
151
+ "#{e.workitem.fei.workflow_instance_id}--" +
152
+ "#{e.workitem.fei.expression_id}"
153
+
154
+ @entries << e
155
+
156
+ @entries = @entries[0, @max_item_count] \
157
+ if @entries.length > @max_item_count
158
+ end
159
+
160
+ #
161
+ # Returns an Atom feed of all the workitem activity for the
162
+ # participants whose name matches the given regular expression.
163
+ #
164
+ # Options :
165
+ #
166
+ # [:upon] can be set to either nil, :apply, :reply. :apply states
167
+ # that the returned feed should only contain entries about
168
+ # participant getting applied, :reply only about
169
+ # participant replying.
170
+ # [:feed_uri] the URI for the feed. Defaults to
171
+ # 'http://localhost/feed'
172
+ # [:feed_title] the title for the feed. Defaults to
173
+ # 'OpenWFEru engine activity feed'
174
+ # [:format] yaml|text|json
175
+ #
176
+ #
177
+ def get_feed (participant_regex, options={})
178
+
179
+ participant_regex = Regexp.compile(participant_regex) \
180
+ if participant_regex.is_a?(String)
181
+
182
+ upon = options[:upon]
183
+ feed_uri = options[:feed_uri] || "http://localhost/feed"
184
+ title = options[:feed_title] || "OpenWFEru engine activity feed"
185
+
186
+ feed = Atom::Collection.new feed_uri
187
+ feed.title = title
188
+
189
+ format = options[:format]
190
+ format = validate_format(format)
191
+
192
+ @entries.each do |e|
193
+
194
+ next unless participant_regex.match(e.participant_name)
195
+ next if upon and upon != e.upon
196
+
197
+ feed.updated = e.updated \
198
+ if feed.updated == nil or e.updated > feed.updated
199
+
200
+ feed << as_atom_entry(format, e)
201
+ end
202
+
203
+ feed
204
+ end
205
+
206
+ protected
207
+
208
+ #
209
+ # Makes sure the required 'render' is valid. Returns it
210
+ # as a Symbol.
211
+ #
212
+ def validate_format (f)
213
+
214
+ f = "as_#{f}"
215
+ return :as_yaml unless methods.include?(f)
216
+ f.to_sym
217
+ end
218
+
219
+ def as_atom_entry (render, entry)
220
+
221
+ send(
222
+ render,
223
+ entry.as_atom_entry,
224
+ entry.participant_name,
225
+ entry.upon,
226
+ entry.workitem)
227
+ end
228
+
229
+ #
230
+ # A basic rendition of a workitem as a YAML string
231
+ #
232
+ def as_yaml (atom_entry, participant_name, upon, workitem)
233
+
234
+ atom_entry.title = "#{participant_name} - #{upon}"
235
+ atom_entry.content = workitem.to_yaml
236
+ atom_entry.content['type'] = "text/plain"
237
+
238
+ atom_entry
239
+ end
240
+
241
+ #class Atom::Content
242
+ # def convert_contents e
243
+ # REXML::CData.new(@content.to_s)
244
+ # end
245
+ #end
246
+
247
+ #
248
+ # A basic rendition of a workitem as text.
249
+ #
250
+ def as_text (atom_entry, participant_name, upon, workitem)
251
+
252
+ atom_entry.title = "#{participant_name} - #{upon}"
253
+
254
+ atom_entry.content = workitem.to_s
255
+ atom_entry.content['type'] = "text/plain"
256
+
257
+ atom_entry
258
+ end
259
+
260
+ #
261
+ # Renders the workitem as a JSON string.
262
+ #
263
+ def as_json (atom_entry, participant_name, upon, workitem)
264
+
265
+ atom_entry.title = "#{participant_name} - #{upon}"
266
+
267
+ atom_entry.content = workitem.to_json
268
+ atom_entry.content['type'] = "text/plain"
269
+
270
+ atom_entry
271
+ end
272
+ end
273
+
274
+ end
275
+
@@ -68,7 +68,7 @@ module Extras
68
68
  # in the same source file. It should be quite easy for the Rails hackers
69
69
  # among you to sort that out for a Rails based usage.
70
70
  #
71
- class OwfeTables < ActiveRecord::Migration
71
+ class WorkitemTables < ActiveRecord::Migration
72
72
 
73
73
  def self.up
74
74
 
@@ -106,6 +106,14 @@ module Extras
106
106
  end
107
107
  end
108
108
 
109
+ #
110
+ # Reopening InFlowWorkItem to add a 'db_id' attribute.
111
+ #
112
+ class InFlowWorkItem
113
+
114
+ attr_accessor :db_id
115
+ end
116
+
109
117
  #
110
118
  # The ActiveRecord version of an OpenWFEru workitem (InFlowWorkItem).
111
119
  #
@@ -179,7 +187,7 @@ module Extras
179
187
  end
180
188
 
181
189
  i.save!
182
-
190
+ # making sure to throw an exception in case of trouble
183
191
  end
184
192
 
185
193
  i
@@ -191,10 +199,14 @@ module Extras
191
199
  def as_owfe_workitem
192
200
 
193
201
  wi = OpenWFE::InFlowWorkItem.new
202
+
194
203
  wi.fei = full_fei
195
204
  wi.participant_name = participant_name
196
205
  wi.attributes = fields_hash
197
206
  # don't care about dispatch_time and last_modified
207
+
208
+ wi.db_id = self.id
209
+
198
210
  wi
199
211
  end
200
212
 
@@ -230,6 +242,7 @@ module Extras
230
242
  # an old trick for backward compatibility with OpenWFEja
231
243
 
232
244
  save!
245
+ # making sure to throw an exception in case of trouble
233
246
  end
234
247
 
235
248
  #
@@ -302,6 +315,78 @@ module Extras
302
315
 
303
316
  result
304
317
  end
318
+
319
+ #
320
+ # A kind of 'google search' among workitems
321
+ #
322
+ def Workitem.search (search_string, storename_list=nil)
323
+
324
+ storename_list = Array(storename_list) if storename_list
325
+
326
+ # participant_name
327
+
328
+ result = find(
329
+ :all,
330
+ :conditions => conditions(
331
+ "participant_name", search_string, storename_list),
332
+ :order => "participant_name")
333
+ # :limit => 10)
334
+
335
+ ids = result.collect { |wi| wi.id }
336
+
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)
346
+
347
+ # fkey
348
+
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)
356
+
357
+ # over.
358
+
359
+ result
360
+ end
361
+
362
+ protected
363
+
364
+ #
365
+ # builds the condition (the WHERE clause) for the
366
+ # search.
367
+ #
368
+ def Workitem.conditions (keyname, search_string, storename_list)
369
+
370
+ if storename_list
371
+ [ "#{keyname} LIKE ? AND workitems.store_name IN (?)",
372
+ search_string, storename_list ]
373
+ else
374
+ [ "#{keyname} LIKE ?",
375
+ search_string ]
376
+ end
377
+ end
378
+
379
+ def Workitem.merge_search_results (ids, wis, new_wis)
380
+
381
+ return if new_wis.size < 1
382
+
383
+ new_wis.each do |wi|
384
+ wi = wi.workitem if wi.kind_of?(Field)
385
+ next if ids.include? wi.id
386
+ ids << wi.id
387
+ wis << wi
388
+ end
389
+ end
305
390
  end
306
391
 
307
392
  #
@@ -30,8 +30,6 @@
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
31
  #++
32
32
  #
33
- # $Id$
34
- #
35
33
 
36
34
  #
37
35
  # "made in Japan"
@@ -70,15 +68,14 @@ end
70
68
  require 'openwfe/participants/participant'
71
69
 
72
70
 
73
- module OpenWFE
74
- module Extras
71
+ module OpenWFE::Extras
75
72
 
76
73
  #
77
74
  # Stores the incoming workitem into an 'atom feed'
78
75
  #
79
76
  # An example :
80
77
  #
81
- # feed0 = AtomParticipant.new(
78
+ # feed0 = AtomFeedParticipant.new(
82
79
  # 20, # no more than 20 entries are kept
83
80
  # """
84
81
  # <p>
@@ -89,13 +86,13 @@ module Extras
89
86
  # The 'template' parameter may contain an instance of File instead of
90
87
  # an instance of String.
91
88
  #
92
- # feed0 = AtomParticipant.new(
89
+ # feed0 = AtomFeedParticipant.new(
93
90
  # 20, File.new("path/to/my/atom/template.txt")
94
91
  #
95
92
  # The template can be passed as the second parameter (after the max entry
96
93
  # count) or as a block :
97
94
  #
98
- # feed1 = AtomParticipant.new(20) do |flow_expression, atom_participant, workitem|
95
+ # feed1 = AtomFeedParticipant.new(20) do |flow_expression, atom_participant, workitem|
99
96
  # #
100
97
  # # usually only the workitem parameter is used
101
98
  # # but the other two allow for advanced tricks...
@@ -117,15 +114,19 @@ module Extras
117
114
  # "atom-tools" from http://code.necronomicorp.com/trac/atom-tools
118
115
  #
119
116
  #
120
- class AtomParticipant
121
- include LocalParticipant, MonitorMixin
117
+ class AtomFeedParticipant
118
+ include MonitorMixin
119
+ include LocalParticipant
120
+ include TemplateMixin
122
121
 
123
- attr_accessor \
124
- :content_type # blocks may manipulate them
122
+ #
123
+ # Made accessible so that blocks may set it.
124
+ #
125
+ attr_accessor :content_type
125
126
 
126
127
  def initialize (max_item_count, template=nil, &block)
127
128
 
128
- super()
129
+ super() # very important as this class includes MonitorMixin
129
130
 
130
131
  @template = template
131
132
  @max_item_count = max_item_count
@@ -160,24 +161,15 @@ module Extras
160
161
 
161
162
  protected
162
163
 
164
+ #
165
+ # This base implementation simply calls the eval_template()
166
+ # method of the TemplateMixin.
167
+ # Feel free to override this render() method for custom
168
+ # representations.
169
+ #
163
170
  def render (workitem)
164
171
 
165
- fe = get_flow_expression(workitem)
166
-
167
- template = if @block_template
168
- #@block_template.call(fe, self, workitem)
169
- call_block @block_template, workitem
170
- elsif @template
171
- if @template.kind_of? File
172
- @template.readlines
173
- else
174
- @template.to_s
175
- end
176
- else
177
- "(no template given)"
178
- end
179
-
180
- OpenWFE::dosub(template, fe, workitem)
172
+ eval_template workitem
181
173
  end
182
174
 
183
175
  #
@@ -194,5 +186,4 @@ module Extras
194
186
  end
195
187
 
196
188
  end
197
- end
198
189