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
@@ -0,0 +1,184 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2006-2007, Nicolas Modryzk and 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
+ # Nicolas Modrzyk at openwfe.org
40
+ # John Mettraux at openwfe.org
41
+ #
42
+
43
+ require 'fileutils'
44
+
45
+ require 'openwfe/service'
46
+ require 'openwfe/util/lru_cache'
47
+ require 'openwfe/flowexpressionid'
48
+
49
+ module OpenWFE
50
+
51
+ #
52
+ # Create a composite expression storage.
53
+ # This will take parameters from the application context to create
54
+ # the resulting composite storage
55
+ class CompositeExpressionStorage
56
+ include ServiceMixin
57
+
58
+ attr_accessor \
59
+ :persistence, \
60
+ :cache, \
61
+ :journal
62
+
63
+ def initialize (serviceName, applicationContext)
64
+
65
+ service_init(serviceName, applicationContext)
66
+
67
+ @cache = @application_context[:cached_expression_storage]
68
+ @journal = @application_context[:journalized_expression_storage]
69
+ @persistence = @application_context[:file_expression_storage]
70
+ end
71
+
72
+ #
73
+ # call the add method for each registered storage
74
+ def []= (fei, flowExpression)
75
+ @journal[fei] = flowExpression if @journal
76
+ @cache[fei] = flowExpression if @cache
77
+ @persistence[fei] = flowExpression
78
+ end
79
+
80
+ #
81
+ # remove the expressionid from each registered storage
82
+ def remove (fei, workitem)
83
+ @journal.remove(fei, workitem) if @journal
84
+ @cache.remove(fei, workitem) if @cache
85
+ @persistence.remove(fei,workitem)
86
+ end
87
+
88
+ #
89
+ # slightly different method. Try to get the value from the cache storage if one
90
+ # if not retrieve it, and then add it to the cache.
91
+ def [] (fei)
92
+ return @cache[fei] if @cache
93
+ flow_expression = @persistence[fei]
94
+ @cache[fei] = flow_expression if @cache
95
+ return flow_expression
96
+ end
97
+ end
98
+
99
+ #
100
+ # implementation of a LRU caching storage.
101
+ class LruCachedExpressionStorage
102
+ include ServiceMixin
103
+
104
+ DEFAULT_LRU_SIZE = 10
105
+
106
+ def initialize (service_name, application_context)
107
+ service_init(service_name, application_context)
108
+ size = if (@application_context)
109
+ @application_context[:lru_storage_size]
110
+ else
111
+ DEFAULT_LRU_SIZE
112
+ end
113
+ @cache = LRUCache.new(size)
114
+ end
115
+
116
+ def []= (fei, flowExpression)
117
+ @cache[fei]=flowExpression
118
+ end
119
+
120
+ #
121
+ # interface method to remove an entry for the given expression_id
122
+ def remove (fei, workitem)
123
+ @cache.delete(fei)
124
+ end
125
+
126
+ #
127
+ # check if the value is in the cache
128
+ def is_in_cache?(fei)
129
+ @cache.include?(fei)
130
+ end
131
+ alias has_key? is_in_cache?
132
+
133
+ #
134
+ # interface method, return the value associated with the given id,
135
+ # or nil if not in cache.
136
+ def [] (fei)
137
+ if(@cache.include?(fei))
138
+ return @cache[fei]
139
+ else
140
+ return nil
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+ #
147
+ # Memory consuming in-memory storage.
148
+ # No memory limit, puts everything in a Hash
149
+ #
150
+ class InMemoryExpressionStorage < Hash
151
+ include ServiceMixin
152
+
153
+ def initialize (service_name, application_context)
154
+ @service_name = service_name
155
+ @application_context = application_context
156
+ end
157
+
158
+ def remove (fei, workitem)
159
+ delete(fei)
160
+ end
161
+
162
+ def purge
163
+ self.clear
164
+ end
165
+
166
+ def to_s
167
+ s = "\n\n==== #{self.class} ===="
168
+ each do |k, v|
169
+ s << "\n"
170
+ if v.kind_of?(RawExpression)
171
+ s << "*raw"
172
+ else
173
+ s << " "
174
+ end
175
+ s << v.to_s
176
+ s << " key/value mismatch !" if k != v.fei
177
+ end
178
+ s << "\n==== . ====\n"
179
+ return s
180
+ end
181
+
182
+ end
183
+
184
+ end
@@ -0,0 +1,312 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2006-2007, Nicolas Modryzk and 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
+ # Nicolas Modrzyk at openwfe.org
40
+ # John Mettraux at openwfe.org
41
+ #
42
+
43
+ require 'fileutils'
44
+ require 'base64'
45
+
46
+ require 'openwfe/service'
47
+ require 'openwfe/workitem'
48
+ require 'openwfe/flowexpressionid'
49
+ require 'openwfe/expressions/expressionmap'
50
+
51
+
52
+ module OpenWFE
53
+
54
+ #
55
+ # by default the journals are stored into "work/journal"
56
+ #
57
+ DEFAULT_STORAGE_PATH = "work/"
58
+
59
+ #
60
+ # this is the container class for storing entries in the the journal
61
+ #
62
+ class JournalEntry
63
+
64
+ # reused for
65
+ ENTRY_DELIM = ' -- '
66
+
67
+ attr_reader :fei, :action, :fe, :time
68
+
69
+
70
+ def initialize (action, fei, fe, stime=nil)
71
+ @action = action
72
+ @fei = fei
73
+ @fe = fe
74
+ @time = if stime
75
+ stime
76
+ else
77
+ Time.new
78
+ end
79
+ end
80
+
81
+ #
82
+ # parse the entry from a line read from a log file
83
+ def JournalEntry.parse_from_string (line)
84
+ # offset includes iso formatting and delim
85
+ time_offset = line.index(ENTRY_DELIM)
86
+
87
+ time = Time.iso8601(line.slice(0..time_offset))
88
+
89
+ line = line.slice(time_offset+ ENTRY_DELIM.length..line.length)
90
+ action = line[0..2]
91
+
92
+ index = line.index(ENTRY_DELIM,7)
93
+ fei = OpenWFE::FlowExpressionId.to_fei(line[8..index-1])
94
+
95
+ if action == :put.to_s
96
+ fe_64_yaml = line[index+ENTRY_DELIM.length,line.length].rstrip
97
+ fe_yaml = Base64.decode64(fe_64_yaml.gsub("**","\n"))
98
+ fe = YAML.load(fe_yaml)
99
+ return JournalEntry.new(:put, fei, fe, time)
100
+ else
101
+ return JournalEntry.new(action, fei, nil, time)
102
+ end
103
+ end
104
+
105
+ #
106
+ # this is directly used to store the entry in the journal.
107
+ # This is using base64 encoding to wrap the encoded object, and is not readable. Use to_human_s to decrypt
108
+ def to_s
109
+ if @action == :put
110
+ base64 = Base64.encode64(YAML.dump(@fe)).gsub("\n","**") + "\n"
111
+ @time.iso8601 + ENTRY_DELIM + @action.to_s + ENTRY_DELIM + @fei.to_s + ENTRY_DELIM + base64
112
+ else
113
+ @time.iso8601 + ENTRY_DELIM + @action.to_s + ENTRY_DELIM + @fei.to_s + ENTRY_DELIM + "\n"
114
+ end
115
+ end
116
+
117
+ #
118
+ # same as above,except the encoded object is fully expanded. The return value cannot be processed.
119
+ def to_human_s
120
+ if @action == :put
121
+ @time.iso8601 + ENTRY_DELIM + @action.to_s + ENTRY_DELIM + @fei.to_s + ENTRY_DELIM + "\n" + YAML.dump(@fe).to_s + "---\n"
122
+ else
123
+ to_s
124
+ end
125
+ end
126
+ end
127
+
128
+ #
129
+ # the class responsible for handling replay of a log file
130
+ class JournalReplay
131
+
132
+ def initialize(storage=nil)
133
+ if not storage
134
+ @storage = @application_context[S_EXPRESSION_STORAGE]
135
+ else
136
+ @storage = storage
137
+ end
138
+ end
139
+
140
+ #
141
+ # from the content of path_to_journal, will replay all the entries one by one on the given storage
142
+ def replay(path_to_journal)
143
+ datalines = IO.readlines(path_to_journal)
144
+ datalines.each {
145
+ |line_read|
146
+ entry = (JournalEntry.parse_from_string(line_read))
147
+ if(entry.action == :put)
148
+ @storage[entry.fei]=entry.fe
149
+ else
150
+ #TODO: implement delete
151
+ #@storage.delete(entry.fei)
152
+ @storage.remove(entry.fei)
153
+ end
154
+ }
155
+ end
156
+
157
+ end
158
+
159
+ #
160
+ # this is the main class for journalized storage
161
+ class JournalizedExpressionStorage
162
+ include ServiceMixin
163
+
164
+ attr_accessor :basepath
165
+
166
+ def initialize (serviceName, applicationContext)
167
+ service_init(serviceName, applicationContext)
168
+ path = if (@application_context)
169
+ @application_context[:file_expression_storage_path]
170
+ else
171
+ DEFAULT_STORAGE_PATH
172
+ end
173
+ @basepath = path + "/journal"
174
+ FileUtils.makedirs @basepath
175
+ end
176
+
177
+ #
178
+ # remove the file corresponding to the journal of this workflow instance
179
+ def clean (workflow_id)
180
+ fei_path = compute_file_path_id(workflow_id)
181
+ if (File.exist?(fei_path))
182
+ File.delete(fei_path)
183
+ end
184
+ end
185
+
186
+ #
187
+ # backup the journal file corresponding to the give workflow instance
188
+ # by default, deletes the original journal file.
189
+ def backup (workflow_id, delete_original = true, backup_path = nil)
190
+ path_to_journal = compute_file_path_id(workflow_id)
191
+ temporary_journal = if not backup_path
192
+ path_to_journal+".0"
193
+ else
194
+ backup_path
195
+ end
196
+ FileUtils.copy_file(path_to_journal, temporary_journal)
197
+ File.delete(path_to_journal) if delete_original
198
+ return temporary_journal
199
+ end
200
+
201
+ #
202
+ # truncate the content of the log file:
203
+ # - number of lines
204
+ # - before a given date
205
+ def truncate! (workflow_id, number_of_lines=nil, after_date=nil)
206
+ return 0 if not number_of_lines and not after_date
207
+
208
+ fei_path = compute_file_path_id(workflow_id)
209
+ datalines = IO.readlines(fei_path)
210
+ entries = Array.new
211
+
212
+ datalines.each { |line_read|
213
+ entry = JournalEntry.parse_from_string(line_read)
214
+ break if after_date and entry.time >= after_date
215
+ break if number_of_lines and entries.length >= number_of_lines
216
+ entries.push entry
217
+ }
218
+
219
+ backup(workflow_id)
220
+
221
+ fd = IO.sysopen(fei_path, File::WRONLY|File::CREAT, 0666)
222
+ io = IO.open(fd , "w")
223
+
224
+ entries.each{ |entry|
225
+ io.write(entry.to_s)
226
+ }
227
+ io.close
228
+
229
+ return entries.length
230
+ end
231
+
232
+ #
233
+ # create a human readable log file for the given workflow instance.
234
+ # Note that this will override any existing previously created file
235
+ def to_human_s(workflow_id)
236
+ fei_path = compute_file_path_id(workflow_id)
237
+ if (File.exist?(fei_path))
238
+ fei_new_path = fei_path[0,fei_path.length-5] + ".txt"
239
+ File.delete(fei_new_path) if (File.exist?(fei_new_path))
240
+
241
+ fd = IO.sysopen(fei_new_path, File::WRONLY|File::CREAT, 0666)
242
+ io = IO.open(fd , "w")
243
+
244
+ datalines = IO.readlines(fei_path)
245
+ datalines.each { |line_read| human = (JournalEntry.parse_from_string(line_read)).to_human_s ; io.write(human) }
246
+
247
+ io.close
248
+ else
249
+ raise "workflow journal does not exist for given id:"+workflow_id
250
+ end
251
+ end
252
+
253
+ #
254
+ # interface method for the persistence. add a flow expression to the storage
255
+ def []= (fei, flow_expression)
256
+ write_to_journal(JournalEntry.new(:put, fei, flow_expression))
257
+ end
258
+
259
+ #
260
+ # interface method: remove the expressionid and persist the related workitem
261
+ def remove (fei, workitem=nil)
262
+ write_to_journal(JournalEntry.new(:del, fei, nil))
263
+ end
264
+
265
+ #
266
+ # compute the size of the journal (number of entries) in the journal for the
267
+ # given workflow id
268
+ def size (workflow_instance_id)
269
+ fei_path = compute_file_path_id(workflow_instance_id)
270
+ return 0 if not File.exist?(fei_path)
271
+
272
+ datalines = IO.readlines(fei_path)
273
+ return datalines.length
274
+ end
275
+
276
+ #
277
+ # alias for the protected compute_file_path with a better name.
278
+ # Return the path of the log for the given workflow instance
279
+ def where_is_journal_for (workflow_instance_id)
280
+ compute_file_path(workflow_instance_id)
281
+ end
282
+
283
+ #
284
+ # write an entry to the journal. This call the to_s method of the entry
285
+ # and append the resulting line to the log file
286
+ def write_to_journal (journal_entry)
287
+ fei_path = compute_file_path(journal_entry.fei)
288
+ fei_parent_path = File.dirname(fei_path)
289
+
290
+ FileUtils.makedirs fei_parent_path if not (File.exist?(fei_parent_path))
291
+
292
+ fd = IO.sysopen(fei_path, File::WRONLY|File::APPEND|File::CREAT, 0666)
293
+ io = IO.open(fd , "w")
294
+
295
+ io.write(journal_entry.to_s)
296
+
297
+ io.close
298
+ end
299
+
300
+ protected
301
+
302
+ def compute_file_path (fei)
303
+ compute_file_path_id(fei.parent_workflow_instance_id)
304
+ end
305
+
306
+ def compute_file_path_id (parent_workflow_instance_id)
307
+ @basepath + "/" + parent_workflow_instance_id.to_s + ".yaml"
308
+ end
309
+
310
+ end
311
+
312
+ end