1 package body WF_STANDARD as
2 /* $Header: wfstdb.pls 120.11.12010000.2 2008/12/05 15:57:09 alsosa ship $ */
3
4
5
6 -------------------------------------------------------------------------------
7 ------------------------------- PRIVATE API DECLARATIONS ----------------------
8 -------------------------------------------------------------------------------
9 -- ContinueMasterFlow
10 -- Signal Master Flow to continue if all Detail flows have executed
11 -- Continuation Activity
12 -- OUT
13 -- result - 'NULL'
14 procedure ContinueMasterFlow( itemtype in varchar2,
15 itemkey in varchar2,
16 actid in number,
17 waiting_activity in varchar2,
18 resultout in out nocopy varchar2);
19
20 -- ContinueDetailFlow
21 -- Signal Detail Flows to continue
22 -- IN
23 -- waiting_activity - The Name of the activity that is waiting
24 -- OUT
25 -- resultout - 'NULL'
26 procedure ContinueDetailFlow( itemtype in varchar2,
27 itemkey in varchar2,
28 actid in number,
29 waiting_activity in varchar2,
30 resultout out nocopy varchar2
31 );
32
33 -- WaitForDetailFlow
34 -- Wait for all detail flows to complete continuation activity
35 -- IN
36 -- continuation_activity - The Name of the activity that in waiting
37 -- OUT
38 -- result - 'NULL'
39 procedure WaitForDetailFlow( itemtype in varchar2,
40 itemkey in varchar2,
41 actid in number,
42 continuation_activity in varchar2,
43 resultout out nocopy varchar2);
44
45 -- WaitForMasterFlow
46 -- Wait for Master flows to complete continuation activity
47 -- IN
48 -- itemtype - item type
49 -- itemkey - item key
50 -- actid - process activity instance id
51 -- funcmode - execution mode
52 -- OUT
53 -- result - 'NULL'
54 procedure WaitForMasterFlow( itemtype in varchar2,
55 itemkey in varchar2,
56 actid in number,
57 continuation_activity in varchar2,
58 resultout out nocopy varchar2 );
59
60 -------------------------------------------------------------------------------
61 ------------------------------- PUBLIC APIs -----------------------------------
62 -------------------------------------------------------------------------------
63
64
65 -- AbortProcess
66 -- cover to wf_engine abort process used in error process.
67 procedure AbortProcess(itemtype in varchar2,
68 itemkey in varchar2,
69 actid in number,
70 funcmode in varchar2,
71 resultout in out nocopy varchar2) is
72
73 l_error_itemtype varchar2(8);
74 l_error_itemkey varchar2(240);
75
76 begin
77 -- Do nothing in cancel or timeout mode
78 if (funcmode <> wf_engine.eng_run) then
79 resultout := wf_engine.eng_null;
80 return;
81 end if;
82
83 --
84 -- Get the type and the key of the process that errored out
85 -- these were set in the erroring out process by Execute_Error_Process
86 --
87 l_error_itemkey := WF_ENGINE.GetItemAttrText(
88 itemtype => itemtype,
89 itemkey => itemkey,
90 aname => 'ERROR_ITEM_KEY' );
91 l_error_itemtype := WF_ENGINE.GetItemAttrText(
92 itemtype => itemtype,
93 itemkey => itemkey,
94 aname => 'ERROR_ITEM_TYPE' );
95
96 -- now abort the process: dont specify the process so it defaults to the root
97 Wf_Engine.AbortProcess(itemtype => l_error_itemtype, itemkey=>l_error_itemkey);
98 resultout := wf_engine.eng_null;
99
100 exception
101 when others then
102 Wf_Core.Context('Wf_Standard', 'AbortProcess', itemtype,
103 itemkey, to_char(actid), funcmode);
104 raise;
105 end AbortProcess;
106
107 -- OrJoin
108 -- Parallel Or Join.
109 -- Always returns 'NULL' result immediately, since an 'Or' succeeds
110 -- as soon as first in-transition activity completes.
111 -- OUT
112 -- result - 'NULL'
113 procedure OrJoin(itemtype in varchar2,
114 itemkey in varchar2,
115 actid in number,
116 funcmode in varchar2,
117 resultout in out nocopy varchar2)
118 is
119 begin
120 resultout := wf_engine.eng_null;
121 exception
122 when others then
123 Wf_Core.Context('Wf_Standard', 'OrJoin', itemtype, itemkey,
124 to_char(actid), funcmode);
125 raise;
126 end OrJoin;
127
128
129 -- AndJoin
130 -- Parallel And Join
131 -- Returns 'NULL' if all in-transition activities have completed.
132 -- Returns 'WAITING' if at least one in-transition activity is not
133 -- complete, or is complete with the wrong result.
134 -- OUT
135 -- result - 'WAITING' | 'NULL'
136 procedure AndJoin(itemtype in varchar2,
137 itemkey in varchar2,
138 actid in number,
139 funcmode in varchar2,
140 resultout in out nocopy varchar2)
141 is
142 cnt pls_integer;
143 begin
144 -- Do nothing in cancel or timeout mode
145 if (funcmode <> wf_engine.eng_run) then
146 resultout := wf_engine.eng_null;
147 return;
148 end if;
149
150 -- SYNCHMODE: Not allowed
151 if (itemkey = wf_engine.eng_synch) then
152 Wf_Core.Token('OPERATION', 'Wf_Standard.AndJoin');
153 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
154 end if;
155
156 -- The And fails if there is at least one in-transition which is either
157 -- incomplete or complete with the wrong result.
158 SELECT count(1)
159 into cnt
160 FROM WF_ACTIVITY_TRANSITIONS WAT
161 WHERE WAT.TO_PROCESS_ACTIVITY = actid
162 AND NOT EXISTS
163 (SELECT NULL
164 FROM WF_ITEM_ACTIVITY_STATUSES WIAS
165 WHERE WIAS.PROCESS_ACTIVITY = WAT.FROM_PROCESS_ACTIVITY
166 AND WIAS.ITEM_TYPE = itemtype
167 AND WIAS.ITEM_KEY = itemkey
168 AND WIAS.ACTIVITY_STATUS = 'COMPLETE'
169 AND (WAT.RESULT_CODE in (WIAS.ACTIVITY_RESULT_CODE,
170 wf_engine.eng_trans_any)
171 OR (WAT.RESULT_CODE = wf_engine.eng_trans_default
172 AND NOT EXISTS
173 (SELECT NULL
174 FROM WF_ACTIVITY_TRANSITIONS WAT2
175 WHERE WAT2.FROM_PROCESS_ACTIVITY =
176 WAT.FROM_PROCESS_ACTIVITY
177 AND WAT2.RESULT_CODE = WIAS.ACTIVITY_RESULT_CODE)
178 )
179 )
180 );
181
182 if (cnt > 0) then
183 -- This means there is at least one in-transition either incomplete
184 -- or complete with the wrong result.
185 -- The LogicalAnd fails, return a result of 'WAITING'.
186 resultout := wf_engine.eng_waiting;
187 else
188 -- This means there are no in-transition activities that are either
189 -- incomplete or complete with the wrong result.
190 -- The LogicalAnd succeeds, return a result of 'NULL' to continue.
191 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
192 end if;
193 return;
194 exception
195 when others then
196 Wf_Core.Context('Wf_Standard', 'AndJoin', itemtype,
197 itemkey, to_char(actid), funcmode);
198 raise;
199 end AndJoin;
200
201
202 -- Assign
203 -- Assign a value to an item attribute
204 -- OUT
205 -- result - null
206 -- ACTIVITY ATTRIBUTES REFERENCED
207 -- ATTR - Item attribute
208 -- DATE_VALUE - date value
209 -- NUMBER_VALUE - number value
210 -- TEXT_VALUE - text value
211 procedure Assign(itemtype in varchar2,
212 itemkey in varchar2,
213 actid in number,
214 funcmode in varchar2,
215 resultout in out nocopy varchar2)
216 is
217 atype varchar2(8);
218 asubtype varchar2(8);
219 aformat varchar2(240);
220 aname varchar2(30);
221 begin
222 -- Do nothing in cancel or timeout mode
223 if (funcmode <> wf_engine.eng_run) then
224 resultout := wf_engine.eng_null;
225 return;
226 end if;
227
228 -- Get attribute info
229 aname := wf_engine.GetActivityAttrText(itemtype, itemkey, actid, 'ATTR');
230 wf_engine.GetItemAttrInfo(itemtype, aname, atype, asubtype, aformat);
231
232 -- NUMBER value
233 if (atype = 'NUMBER') then
234 wf_engine.SetItemAttrNumber(itemtype,itemkey,aname,
235 wf_engine.GetActivityAttrNumber(itemtype,itemkey,actid, 'NUMBER_VALUE'));
236
237 -- DATE value
238 elsif (atype = 'DATE') then
239 wf_engine.SetItemAttrDate(itemtype,itemkey,aname,
240 wf_engine.GetActivityAttrDate(itemtype,itemkey,actid, 'DATE_VALUE'));
241
242 -- TEXT value (VARCHAR2, LOOKUP, FORM, URL, DOCUMENT, etc)
243 else
244 wf_engine.SetItemAttrText(itemtype,itemkey,aname,
245 wf_engine.GetActivityAttrText(itemtype,itemkey,actid, 'TEXT_VALUE'));
246 end if;
247
248 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
249 exception
250 when others then
251 Wf_Core.Context('Wf_Standard', 'Assign', itemtype,
252 itemkey, to_char(actid), funcmode);
253 raise;
254 end Assign;
255
256
257 -- GetURL
258 -- Get monitor URL, store in item attribute
259 -- OUT
260 -- result - 'NULL'
261 -- ACTIVITY ATTRIBUTES REFERENCED
262 -- ATTR - Item attribute to set
263 -- ADMIN_MODE - administration mode (Y / N)
264 procedure GetURL(itemtype in varchar2,
265 itemkey in varchar2,
266 actid in number,
267 funcmode in varchar2,
268 resultout in out nocopy varchar2)
269 is
270 aname varchar2(30);
271 admin varchar2(8);
272 begin
273 -- Do nothing in cancel or timeout mode
274 if (funcmode <> wf_engine.eng_run) then
275 resultout := wf_engine.eng_null;
276 return;
277 end if;
278
279 -- SYNCHMODE: Not allowed
280 if (itemkey = wf_engine.eng_synch) then
281 Wf_Core.Token('OPERATION', 'Wf_Standard.GetUrl');
282 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
283 end if;
284
285 -- Get item attribute name
286 aname := wf_engine.GetActivityAttrText(itemtype,itemkey,actid, 'ATTR');
287
288 -- Get admin mode
289 admin := wf_engine.GetActivityAttrText(itemtype,itemkey,actid, 'ADMIN_MODE');
290
291 -- Set item attribute
292 wf_engine.SetItemAttrText(itemtype, itemkey, aname,
293 wf_monitor.geturl(
294 wf_core.translate('WF_WEB_AGENT'), itemtype, itemkey, admin));
295
296 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
297 exception
298 when others then
299 Wf_Core.Context('Wf_Standard', 'GetUrl', itemtype,
300 itemkey, to_char(actid), funcmode);
301 raise;
302 end GetURL;
303
304
305 -- Compare
306 -- Standard Compare function.
307 -- OUT
308 -- comparison value (LT, EQ, GT, NULL)
309 -- ACTIVITY ATTRIBUTES REFERENCED
310 -- VALUE1 - Test value
311 -- VALUE2 - Reference value
312 procedure Compare(itemtype in varchar2,
313 itemkey in varchar2,
314 actid in number,
315 funcmode in varchar2,
316 resultout in out nocopy varchar2)
317 is
318 atype varchar2(8);
319 asubtype varchar2(8);
320 aformat varchar2(240);
321 aname varchar2(30);
322 nval1 number;
323 nval2 number;
324 dval1 date;
325 dval2 date;
326 tval1 varchar2(4000);
327 tval2 varchar2(4000);
328 begin
329 -- Do nothing in cancel or timeout mode
330 if (funcmode <> wf_engine.eng_run) then
331 resultout := wf_engine.eng_null;
332 return;
333 end if;
334
335 -- Get comparison data type
336 Wf_Engine.GetActivityAttrInfo(itemtype, itemkey, actid, 'VALUE1',
337 atype, asubtype, aformat);
338
339 tval1 := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'VALUE1');
340
341
342 --
343 -- NUMBER value
344 --
345 if (atype = 'NUMBER') then
346 -- Get the two number values
347 nval1 := Wf_Engine.GetActivityAttrNumber(itemtype,itemkey,actid, 'VALUE1');
348 nval2 := Wf_Engine.GetActivityAttrNumber(itemtype,itemkey,actid, 'VALUE2');
349
350 -- Compare
351 if (nval1 is null or nval2 is null) then
352 resultout := wf_engine.eng_completed||':NULL';
353 elsif (nval1 < nval2) then
354 resultout := wf_engine.eng_completed||':LT';
355 elsif (nval1 > nval2) then
356 resultout := wf_engine.eng_completed||':GT';
357 elsif (nval1 = nval2) then
358 resultout := wf_engine.eng_completed||':EQ';
359 end if;
360
361 --
362 -- DATE value
363 --
364 elsif (atype = 'DATE') then
365 -- Get the two date values
366 dval1 := Wf_Engine.GetActivityAttrDate(itemtype,itemkey,actid, 'VALUE1');
367 dval2 := Wf_Engine.GetActivityAttrDate(itemtype,itemkey,actid, 'VALUE2');
368
369 -- Compare
370 if (dval1 is null or dval2 is null) then
371 resultout := wf_engine.eng_completed||':NULL';
372 elsif (dval1 < dval2) then
373 resultout := wf_engine.eng_completed||':LT';
374 elsif (dval1 > dval2) then
375 resultout := wf_engine.eng_completed||':GT';
376 elsif (dval1 = dval2) then
377 resultout := wf_engine.eng_completed||':EQ';
378 end if;
379
380 --
381 -- TEXT value (VARCHAR2, LOOKUP, FORM, URL, DOCUMENT, etc)
382 --
383 else
384 -- Get the two text values
385 tval1 := Wf_Engine.GetActivityAttrText(itemtype,itemkey,actid, 'VALUE1');
386 tval2 := Wf_Engine.GetActivityAttrText(itemtype,itemkey,actid, 'VALUE2');
387
388 -- Compare
389 if (tval1 is null or tval2 is null) then
390 resultout := wf_engine.eng_completed||':NULL';
391 elsif (tval1 < tval2) then
392 resultout := wf_engine.eng_completed||':LT';
393 elsif (tval1 > tval2) then
394 resultout := wf_engine.eng_completed||':GT';
395 elsif (tval1 = tval2) then
396 resultout := wf_engine.eng_completed||':EQ';
397 end if;
398 end if;
399
400 exception
401 when others then
402 Wf_Core.Context('Wf_Standard', 'Compare', itemtype,
403 itemkey, to_char(actid), funcmode);
404 raise;
405 end Compare;
406
407
408 -- CompareExecutionTime
409 -- Compare Execution Time function.
410 -- OUT
411 -- comparison value (LT, EQ, GT, NULL)
412 -- ACTIVITY ATTRIBUTES REFERENCED
413 -- EXECUTIONTIME - Execution time Test value in seconds
414 -- PARENTTYPE - Either ROOT or SUBPROCESS
415 procedure CompareExecutionTime(itemtype in varchar2,
416 itemkey in varchar2,
417 actid in number,
418 funcmode in varchar2,
419 resultout in out nocopy varchar2)
420 is
421 etime number;
422 delta number;
423 processid number;
424 ptype varchar2(30);
425
426 cursor GetRunningTime (itemtype in varchar2,
427 itemkey in varchar2, actid in number) is
428 select (sysdate - nvl(begin_date,sysdate))*86400
429 from wf_item_activity_statuses
430 where item_type = itemtype
431 and item_key = itemkey
432 and process_activity = actid;
433
434 cursor GetExecutionTime (itemtype in varchar2,
435 itemkey in varchar2) is
436 select (sysdate - begin_date)*86400
437 from wf_items
438 where item_type = itemtype
439 and item_key = itemkey;
440
441 begin
442 -- Do nothing in cancel or timeout mode
443 if (funcmode <> wf_engine.eng_run) then
444 resultout := wf_engine.eng_null;
445 return;
446 end if;
447
448 Ptype := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'PARENTTYPE');
449
450 if Ptype = 'ROOT' then
451 -- calculate the execution time
452 open GetExecutionTime(itemtype, itemkey);
453 fetch GetExecutionTime into delta;
454 close GetExecutionTime;
455 else
456 processid := WF_ENGINE_UTIL.activity_parent_process(itemtype, itemkey, actid);
457
458 -- calculate the execution time
459 open GetRunningTime(itemtype, itemkey, processid);
460 fetch GetRunningTime into delta;
461 close GetRunningTime;
462 end if;
463
464 -- look up the test value for execution time
465 Etime := Wf_Engine.GetActivityAttrNumber(itemtype, itemkey, actid, 'EXECUTIONTIME');
466
467 -- execute comparison
468 if (delta is null or etime is null) then
469 resultout := wf_engine.eng_completed||':NULL';
470 elsif (delta < etime) then
471 resultout := wf_engine.eng_completed||':LT';
472 elsif (delta > etime) then
473 resultout := wf_engine.eng_completed||':GT';
474 elsif (delta = etime) then
475 resultout := wf_engine.eng_completed||':EQ';
476 end if;
477
478 exception
479 when others then
480 Wf_Core.Context('Wf_Standard', 'CompareExecutionTime', itemtype,
481 itemkey, to_char(actid), funcmode);
482 raise;
483 end CompareExecutionTime;
484
485
486 -- CompareEventProperty
487 -- Compare a property on an event
488 -- IN
489 -- itemtype - item type
490 -- itemkey - item key
491 -- actid - process activity instance id
492 -- funcmode - execution mode
493 -- OUT
494 -- comparison result (WFSTD_COMPARISON lookup code)
495 -- GT LT EQ NULL
496 -- ACTIVITY ATTRIBUTES REFERENCED
497 -- EVENT - Event whose property is to be compared
498 -- PROPERTY - Event Property Reference (Based on the lookup of EVENTPROPERTY
499 -- PARAMETER - Parameter Name if Lookup type = Parameter
500 -- VALUE - Constant value of correct type
501 procedure CompareEventProperty(itemtype in varchar2,
502 itemkey in varchar2,
503 actid in number,
504 funcmode in varchar2,
505 resultout in out nocopy varchar2)
506 is
507 lEvent WF_EVENT_T;
508 lAgent WF_AGENT_T;
509 lNVal NUMBER;
510 lDVal DATE;
511 lTVal VARCHAR2 (4000);
512 lProperty VARCHAR2 (20);
513 lParameter VARCHAR2(200);
514 lType VARCHAR2 (20);
515 lSubType VARCHAR2 (20);
516 lFormat VARCHAR2 (20);
517
518 begin
519 lEvent := wf_engine.getActivityAttrEvent(itemtype, itemkey,
520 actid, 'EVENT');
521 lProperty := wf_engine.getActivityAttrText(itemtype, itemkey,
522 actid, 'PROPERTY');
523
524 if (lProperty = 'PRIORITY') then
525 lNVal := wf_engine.getActivityAttrNumber(itemtype, itemkey,
526 actid, 'NUMBER_VALUE');
527 if (lEvent.priority is NULL or lNVal is NULL) then
528 resultout := wf_engine.eng_completed||':NULL';
529 elsif (lEvent.priority < lNVal) then
530 resultout := wf_engine.eng_completed||':LT';
531 elsif (lEvent.priority > lNVal) then
532 resultout := wf_engine.eng_completed||':GT';
533 elsif (lEvent.priority = lNVal) then
534 resultout := wf_engine.eng_completed||':EQ';
535 end if;
536
537 elsif (lProperty = 'SEND_DATE') then
538 lDVal := wf_engine.getActivityAttrDate(itemtype, itemkey,
539 actid, 'DATE_VALUE');
540 if (lEvent.send_date is NULL or lDVal is null) then
541 resultout := wf_engine.eng_completed||':NULL';
542 elsif (lEvent.send_date < lDVal) then
543 resultout := wf_engine.eng_completed||':LT';
544 elsif (lEvent.send_date > lDVal) then
545 resultout := wf_engine.eng_completed||':GT';
546 elsif (lEvent.send_date = lDVal) then
547 resultout := wf_engine.eng_completed||':EQ';
548 end if;
549 elsif (lProperty = 'RECEIVE_DATE') then
550 lDVal := wf_engine.getActivityAttrDate(itemtype, itemkey,
551 actid, 'DATE_VALUE');
552 if (lEvent.receive_date is NULL or lDVal is null) then
553 resultout := wf_engine.eng_completed||':NULL';
554 elsif (lEvent.receive_date < lDVal) then
555 resultout := wf_engine.eng_completed||':LT';
556 elsif (lEvent.receive_date > lDVal) then
557 resultout := wf_engine.eng_completed||':GT';
558 elsif (lEvent.receive_date = lDVal) then
559 resultout := wf_engine.eng_completed||':EQ';
560 end if;
561 elsif (lProperty = 'CORRELATION_ID') then
562 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
563 actid, 'TEXT_VALUE');
564 if (LEvent.correlation_id is NULL or lTVal is NULL) then
565 resultout := wf_engine.eng_completed||':NULL';
566 elsif (LEvent.correlation_id < lTVal) then
567 resultout := wf_engine.eng_completed||':LT';
568 elsif (LEvent.correlation_id > lTVal) then
569 resultout := wf_engine.eng_completed||':GT';
570 elsif (LEvent.correlation_id = lTVal) then
571 resultout := wf_engine.eng_completed||':EQ';
572 end if;
573 elsif (lProperty = 'EVENT_NAME') then
574 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
575 actid, 'TEXT_VALUE');
576 if (LEvent.event_name is NULL or lTVal is NULL) then
577 resultout := wf_engine.eng_completed||':NULL';
578 elsif (LEvent.event_name < lTVal) then
579 resultout := wf_engine.eng_completed||':LT';
580 elsif (LEvent.event_name > lTVal) then
581 resultout := wf_engine.eng_completed||':GT';
582 elsif (LEvent.event_name = lTVal) then
583 resultout := wf_engine.eng_completed||':EQ';
584 end if;
585 elsif (lProperty = 'EVENT_KEY') then
586 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
587 actid, 'TEXT_VALUE');
588 if (LEvent.event_key is NULL or lTVal is NULL) then
589 resultout := wf_engine.eng_completed||':NULL';
590 elsif (LEvent.event_key < lTVal) then
591 resultout := wf_engine.eng_completed||':LT';
592 elsif (LEvent.event_key > lTVal) then
593 resultout := wf_engine.eng_completed||':GT';
594 elsif (LEvent.event_key = lTVal) then
595 resultout := wf_engine.eng_completed||':EQ';
596 end if;
597 elsif (lProperty = 'FROM_AGENT_NAME') then
598 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
599 actid, 'TEXT_VALUE');
600 if (LEvent.From_Agent.Name is NULL or lTVal is NULL) then
601 resultout := wf_engine.eng_completed||':NULL';
602 elsif (LEvent.From_Agent.Name < lTVal) then
603 resultout := wf_engine.eng_completed||':LT';
604 elsif (LEvent.From_Agent.Name > lTVal) then
605 resultout := wf_engine.eng_completed||':GT';
606 elsif (LEvent.From_Agent.Name = lTVal) then
607 resultout := wf_engine.eng_completed||':EQ';
608 end if;
609 elsif (lProperty = 'FROM_AGENT_SYSTEM') then
610 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
611 actid, 'TEXT_VALUE');
612 if (LEvent.From_Agent.System is NULL or lTVal is NULL) then
613 resultout := wf_engine.eng_completed||':NULL';
614 elsif (LEvent.From_Agent.System < lTVal) then
615 resultout := wf_engine.eng_completed||':LT';
616 elsif (LEvent.From_Agent.System > lTVal) then
617 resultout := wf_engine.eng_completed||':GT';
618 elsif (LEvent.From_Agent.System = lTVal) then
619 resultout := wf_engine.eng_completed||':EQ';
620 end if;
621 elsif (lProperty = 'TO_AGENT_NAME') then
622 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
623 actid, 'TEXT_VALUE');
624 if (LEvent.To_Agent.Name is NULL or lTVal is NULL) then
625 resultout := wf_engine.eng_completed||':NULL';
626 elsif (LEvent.To_Agent.Name < lTVal) then
627 resultout := wf_engine.eng_completed||':LT';
628 elsif (LEvent.To_Agent.Name > lTVal) then
629 resultout := wf_engine.eng_completed||':GT';
630 elsif (LEvent.To_Agent.Name = lTVal) then
631 resultout := wf_engine.eng_completed||':EQ';
632 end if;
633 elsif (lProperty = 'TO_AGENT_SYSTEM') then
634 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
635 actid, 'TEXT_VALUE');
636 if (LEvent.To_Agent.System is NULL or lTVal is NULL) then
637 resultout := wf_engine.eng_completed||':NULL';
638 elsif (LEvent.To_Agent.System < lTVal) then
639 resultout := wf_engine.eng_completed||':LT';
640 elsif (LEvent.To_Agent.System > lTVal) then
641 resultout := wf_engine.eng_completed||':GT';
642 elsif (LEvent.To_Agent.System = lTVal) then
643 resultout := wf_engine.eng_completed||':EQ';
644 end if;
645 elsif (lProperty = 'FROM_AGENT') then
646 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
647 actid, 'TEXT_VALUE');
648 if (LEvent.From_Agent.Name is NULL
649 or LEvent.From_Agent.System is NULL or lTVal is NULL) then
650 resultout := wf_engine.eng_completed||':NULL';
651 elsif (LEvent.From_Agent.Name||'@'||LEvent.From_Agent.System < lTVal) then
652 resultout := wf_engine.eng_completed||':LT';
653 elsif (LEvent.From_Agent.Name||'@'||LEvent.From_Agent.System > lTVal) then
654 resultout := wf_engine.eng_completed||':GT';
655 elsif (LEvent.From_Agent.Name||'@'||LEvent.From_Agent.System = lTVal) then
656 resultout := wf_engine.eng_completed||':EQ';
657 end if;
658 elsif (lProperty = 'TO_AGENT') then
659 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
660 actid, 'TEXT_VALUE');
661 if (LEvent.To_Agent.Name is NULL
662 or LEvent.To_Agent.System is NULL or lTVal is NULL) then
663 resultout := wf_engine.eng_completed||':NULL';
664 elsif (LEvent.To_Agent.Name||'@'||LEvent.To_Agent.System < lTVal) then
665 resultout := wf_engine.eng_completed||':LT';
666 elsif (LEvent.To_Agent.Name||'@'||LEvent.To_Agent.System > lTVal) then
667 resultout := wf_engine.eng_completed||':GT';
668 elsif (LEvent.To_Agent.Name||'@'||LEvent.To_Agent.System = lTVal) then
669 resultout := wf_engine.eng_completed||':EQ';
670 end if;
671 elsif (lProperty = 'PARAMETER') then
672 lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
673 actid, 'TEXT_VALUE');
674 lParameter := wf_engine.getActivityAttrText(itemtype => itemtype,
675 itemkey => itemkey,
676 actid => actid,
677 aname => 'PARAMETER');
678 if (LEvent.GetValueForParameter(lParameter)) is NULL then
679 resultout := wf_engine.eng_completed||':NULL';
680 elsif (LEvent.GetValueForParameter(lParameter) < lTVal) then
681 resultout := wf_engine.eng_completed||':LT';
682 elsif (LEvent.GetValueForParameter(lParameter) > lTVal) then
683 resultout := wf_engine.eng_completed||':GT';
684 elsif (LEvent.GetValueForParameter(lParameter) = lTVal) then
685 resultout := wf_engine.eng_completed||':EQ';
686 end if;
687 else
688 -- Unhandled property. Return NULL
689 resultout := wf_engine.eng_completed||':NULL';
690 end if;
691
692 exception
693 when others then
694 Wf_Core.Context('Wf_Standard', 'CompareEventProperty', itemtype,
695 itemkey, to_char(actid), funcmode);
696 raise;
697 end CompareEventProperty;
698
699 -- SetEventProperty
700 -- Set the property in an Event to a given value
701 -- IN
702 -- itemtype - item type
703 -- itemkey - item key
704 -- actid - process activity instance id
705 -- funcmode - execution mode
706 -- OUT
707 -- NONE
708 -- ACTIVITY ATTRIBUTES REFERENCED
709 -- EVENT - Event whose property is to be compared
710 -- PROPERTY - Event Property Reference (Based on the lookup of EVENTPROPERTY
711 -- PARAMETER - Parameter name
712 -- VALUE - Constant value of correct type
713 procedure SetEventProperty(itemtype in varchar2,
714 itemkey in varchar2,
715 actid in number,
716 funcmode in varchar2,
717 resultout in out nocopy varchar2)
718 is
719 lEvent WF_EVENT_T;
720 lNVal NUMBER;
721 lDVal DATE;
722 lTVal VARCHAR2 (4000);
723 lAName VARCHAR2(30);
724 lProperty VARCHAR2 (20);
725 lParameter VARCHAR2(200);
726 lType VARCHAR2 (20);
727 lSubType VARCHAR2 (20);
728 lFormat VARCHAR2 (20);
729 lRefFlag VARCHAR2(8);
730 lAtSign PLS_INTEGER;
731 lFromAgent WF_AGENT_T := WF_AGENT_T(NULL, NULL);
732 lToAgent WF_AGENT_T := WF_AGENT_T(NULL, NULL);
733
734 begin
735 if (funcmode = 'RUN') then
736
737 -- First get the name of the Item Attribute that EVENT points to
738 select WAAV.VALUE_TYPE, substrb(WAAV.TEXT_VALUE, 1, 30)
739 into LRefflag, LAName
740 from WF_ACTIVITY_ATTR_VALUES WAAV
741 where WAAV.PROCESS_ACTIVITY_ID = actid
742 and WAAV.NAME = 'EVENT';
743
744 /* Should be able to use the GetActivityAttrEvent to do this
745 lEvent := wf_engine.getItemAttrEvent(itemtype => itemtype,
746 itemkey => itemkey,
747 name => LAName);
748 */
749
750
751 lEvent := wf_engine.getActivityAttrEvent(itemtype, itemkey,
752 actid, 'EVENT');
753
754 lProperty := wf_engine.getActivityAttrText(itemtype => itemtype,
755 itemkey => itemkey,
756 actid => actid,
757 aname => 'PROPERTY');
758 if (lProperty = 'PRIORITY') then
759 lNVal := wf_engine.getActivityAttrNumber(itemtype => itemtype,
760 itemkey => itemkey,
761 actid => actid,
762 aname => 'NUMBER_VALUE');
763 lEvent.setPriority(lNVal);
764 elsif (lProperty = 'SEND_DATE') then
765 lDVal := wf_engine.getActivityAttrDate(itemtype => itemtype,
766 itemkey => itemkey,
767 actid => actid,
768 aname => 'DATE_VALUE');
769 lEvent.setSendDate(lDVal);
770 elsif (lProperty = 'RECEIVE_DATE') then
771 lDVal := wf_engine.getActivityAttrDate(itemtype => itemtype,
772 itemkey => itemkey,
773 actid => actid,
774 aname => 'DATE_VALUE');
775 lEvent.setReceiveDate(lDVal);
776 elsif (lProperty = 'CORRELATION_ID') then
777 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
778 itemkey => itemkey,
779 actid => actid,
780 aname => 'TEXT_VALUE');
781 lEvent.setCorrelationID(lTVal);
782 elsif (lProperty = 'EVENT_NAME') then
783 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
784 itemkey => itemkey,
785 actid => actid,
786 aname => 'TEXT_VALUE');
787 lEvent.setEventName(lTVal);
788 elsif (lProperty = 'EVENT_KEY') then
789 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
790 itemkey => itemkey,
791 actid => actid,
792 aname => 'TEXT_VALUE');
793 lEvent.setEventKey(lTVal);
794 elsif (lProperty = 'FROM_AGENT_NAME') then
795 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
796 itemkey => itemkey,
797 actid => actid,
798 aname => 'TEXT_VALUE');
799 if lEvent.GetFromAgent() is not null then
800 lFromAgent := lEvent.GetFromAgent();
801 end if;
802 lFromAgent.SetName(lTVal);
803 lEvent.SetFromAgent(lFromAgent);
804 elsif (lProperty = 'FROM_AGENT_SYSTEM') then
805 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
806 itemkey => itemkey,
807 actid => actid,
808 aname => 'TEXT_VALUE');
809 if lEvent.GetFromAgent() is not null then
810 lFromAgent := lEvent.GetFromAgent();
811 end if;
812 lFromAgent.SetSystem(lTVal);
813 lEvent.SetFromAgent(lFromAgent);
814 elsif (lProperty = 'TO_AGENT_NAME') then
815 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
816 itemkey => itemkey,
817 actid => actid,
818 aname => 'TEXT_VALUE');
819 if lEvent.GetToAgent() is not null then
820 lToAgent := lEvent.GetToAgent();
821 end if;
822 lToAgent.SetName(lTVal);
823 lEvent.SetToAgent(lToAgent);
824 elsif (lProperty = 'TO_AGENT_SYSTEM') then
825 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
826 itemkey => itemkey,
827 actid => actid,
828 aname => 'TEXT_VALUE');
829 if lEvent.GetToAgent() is not null then
830 lToAgent := lEvent.GetToAgent();
831 end if;
832 lToAgent.SetSystem(lTVal);
833 lEvent.SetToAgent(lToAgent);
834 elsif (lProperty = 'FROM_AGENT') then
835 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
836 itemkey => itemkey,
837 actid => actid,
838 aname => 'TEXT_VALUE');
839 lAtSign := instr(lTVal, '@');
840 lFromAgent.SetName(substr(lTVal, 1, lAtSign-1));
841 lFromAgent.SetSystem(substr(lTVal, lAtSign+1));
842 lEvent.SetFromAgent(lFromAgent);
843 elsif (lProperty = 'TO_AGENT') then
844 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
845 itemkey => itemkey,
846 actid => actid,
847 aname => 'TEXT_VALUE');
848 lAtSign := instr(lTVal, '@');
849 lToAgent.SetName(substr(lTVal, 1, lAtSign-1));
850 lToAgent.SetSystem(substr(lTVal, lAtSign+1));
851 lEvent.SetToAgent(lToAgent);
852 elsif (lProperty = 'PARAMETER') then
853 lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
854 itemkey => itemkey,
855 actid => actid,
856 aname => 'TEXT_VALUE');
857 lParameter := wf_engine.getActivityAttrText(itemtype => itemtype,
858 itemkey => itemkey,
859 actid => actid,
860 aname => 'PARAMETER');
861 lEvent.AddParameterToList(lParameter, lTVal);
862 end if;
863
864 wf_engine.setItemAttrEvent(itemtype => itemtype,
865 itemkey => itemkey,
866 name => lAName,
867 event => lEvent);
868 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
869 end if; -- RUN
870
871 exception
872 when others then
873 Wf_Core.Context('Wf_Standard', 'SetEventProperty', itemtype,
874 itemkey, to_char(actid), funcmode);
875 raise;
876 end SetEventProperty;
877
878
879 -- GetEventProperty
880 -- Get a property of an Event and assign it to an Item Attribute
881 -- IN
882 -- itemtype - item type
883 -- itemkey - item key
884 -- actid - process activity instance id
885 -- funcmode - execution mode
886 -- OUT
887 -- NONE
888 -- ACTIVITY ATTRIBUTES REFERENCED
889 -- EVENT - Event whose property is to be compared
890 -- PROPERTY - Event Property Reference (Based on the lookup of EVENTPROPERTY
891 -- PARAMETER - Event Parameter Name
892 -- VALUE - Constant value of correct type
893 procedure GetEventProperty(itemtype in varchar2,
894 itemkey in varchar2,
895 actid in number,
896 funcmode in varchar2,
897 resultout in out nocopy varchar2)
898 is
899 lEvent WF_EVENT_T;
900 lNVal NUMBER;
901 lDVal DATE;
902 lTVal VARCHAR2 (4000);
903 lAName VARCHAR2(30);
904 lProperty VARCHAR2 (20);
905 lParameter VARCHAR2(200);
906 lType VARCHAR2 (20);
907 lSubType VARCHAR2 (20);
908 lFormat VARCHAR2 (20);
909 lRefFlag VARCHAR2(8);
910
911 begin
912 if (funcmode = 'RUN') then
913
914
915 lEvent := wf_engine.getActivityAttrEvent(itemtype => itemtype,
916 itemkey => itemkey,
917 actid => actid,
918 name => 'EVENT');
919
920 lProperty := wf_engine.getActivityAttrText(itemtype => itemtype,
921 itemkey => itemkey,
922 actid => actid,
923 aname => 'PROPERTY');
924
925
926 lAName := wf_engine.getActivityAttrText(itemtype => itemtype,
927 itemkey => itemkey,
928 actid => actid,
929 aname => 'ATTR');
930 if (lProperty = 'PRIORITY') then
931 wf_engine.SetItemAttrNumber(itemtype => itemtype,
932 itemkey => itemkey,
933 aname => LAName,
934 avalue => lEvent.getPriority());
935 lEvent.setPriority(lNVal);
936 elsif (lProperty = 'SEND_DATE') then
937 wf_engine.SetItemAttrDate(itemtype => itemtype,
938 itemkey => itemkey,
939 aname => LAName,
940 avalue => lEvent.getSendDate());
941 elsif (lProperty = 'RECEIVE_DATE') then
942 wf_engine.SetItemAttrDate(itemtype => itemtype,
943 itemkey => itemkey,
944 aname => LAName,
945 avalue => lEvent.getReceiveDate());
946 elsif (lProperty = 'CORRELATION_ID') then
947 wf_engine.SetItemAttrText(itemtype => itemtype,
948 itemkey => itemkey,
949 aname => LAName,
950 avalue => lEvent.getCorrelationID());
951 elsif (lProperty = 'EVENT_NAME') then
952 wf_engine.SetItemAttrText(itemtype => itemtype,
953 itemkey => itemkey,
954 aname => LAName,
955 avalue => lEvent.getEventName());
956 elsif (lProperty = 'EVENT_KEY') then
957 wf_engine.SetItemAttrText(itemtype => itemtype,
958 itemkey => itemkey,
959 aname => LAName,
960 avalue => lEvent.getEventKey());
961 elsif (lProperty = 'FROM_AGENT_NAME') then
962 wf_engine.SetItemAttrText(itemtype => itemtype,
963 itemkey => itemkey,
964 aname => LAName,
965 avalue => lEvent.getFromAgent().getName());
966 elsif (lProperty = 'FROM_AGENT_SYSTEM') then
967 wf_engine.SetItemAttrText(itemtype => itemtype,
968 itemkey => itemkey,
969 aname => LAName,
970 avalue => lEvent.getFromAgent().getSystem());
971 elsif (lProperty = 'TO_AGENT_NAME') then
972 wf_engine.SetItemAttrText(itemtype => itemtype,
973 itemkey => itemkey,
974 aname => LAName,
975 avalue => lEvent.getToAgent().getName());
976 elsif (lProperty = 'TO_AGENT_SYSTEM') then
977 wf_engine.SetItemAttrText(itemtype => itemtype,
978 itemkey => itemkey,
979 aname => LAName,
980 avalue => lEvent.getToAgent().getSystem());
981 elsif (lProperty = 'FROM_AGENT') then
982 wf_engine.SetItemAttrText(itemtype => itemtype,
983 itemkey => itemkey,
984 aname => LAName,
985 avalue =>
986 lEvent.getFromAgent().getName()||
987 '@'||lEvent.getFromAgent().getSystem());
988 elsif (lProperty = 'TO_AGENT') then
989 wf_engine.SetItemAttrText(itemtype => itemtype,
990 itemkey => itemkey,
991 aname => LAName,
992 avalue =>
993 lEvent.getToAgent().getName()||
994 '@'||lEvent.getToAgent().getSystem());
995 elsif (lProperty = 'PARAMETER') then
996 lParameter := wf_engine.getActivityAttrText(itemtype => itemtype,
997 itemkey => itemkey,
998 actid => actid,
999 aname => 'PARAMETER');
1000
1001 wf_engine.SetItemAttrText(itemtype => itemtype,
1002 itemkey => itemkey,
1003 aname => LAName,
1004 avalue =>
1005 lEvent.GetValueForParameter(lParameter));
1006 end if;
1007 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
1008 end if; -- RUN
1009
1010 exception
1011 when others then
1012 Wf_Core.Context('Wf_Standard', 'GetEventProperty', itemtype,
1013 itemkey, to_char(actid), funcmode);
1014 raise;
1015 end GetEventProperty;
1016
1017
1018 -- LaunchProcess
1019 -- launches a process
1020 -- IN
1021 -- itemtype - item type
1022 -- itemkey - item key
1023 -- actid - process activity instance id
1024 -- funcmode - execution mode
1025 -- OUT
1026 -- result - NULL
1027 -- ACTIVITY ATTRIBUTES REFERENCED
1028 -- START_ITEMTYPE,START_ITEMKEY,START_PROCESS,START_USER_KEY,START_OWNER
1029 procedure LaunchProcess
1030 (itemtype in varchar2,
1031 itemkey in varchar2,
1032 actid in number,
1033 funcmode in varchar2,
1034 resultout in out nocopy varchar2) is
1035 SItemtype varchar2(8);
1036 SItemKey varchar2(30);
1037 SProcess varchar2(30);
1038 SUserKey varchar2(320);
1039 SOwner varchar2(320);
1040 Deferit varchar2(2);
1041 Launch_count number;
1042 status varchar2(8);
1043 result varchar2(30);
1044
1045 loop_flag BOOLEAN;
1046 begin
1047 -- Do nothing in cancel or timeout mode
1048 if (funcmode <> wf_engine.eng_run) then
1049 resultout := wf_engine.eng_null;
1050 return;
1051 end if;
1052
1053
1054 SItemtype := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'ITEMTYPE'));
1055 Deferit := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'DEFER');
1056
1057 if SItemtype is null then
1058 wf_core.token('ITEMTYPE','NULL');
1059 wf_core.raise('WFSQL_ARGS');
1060 end if;
1061
1062 if deferit = 'Y' then
1063 -- Check if this is the first or second execution of this activity.
1064 -- First -> result_code will be null (really null).
1065 -- Second -> result_code will be '#NULL' (set that way by execution 1).
1066 Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
1067
1068 if (result = wf_engine.eng_null) then
1069 -- Second execution.
1070 -- Defer must have been picked up by the background engine,
1071 -- so return complete result.
1072 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
1073 else
1074 -- Return deferred result
1075 resultout := wf_engine.eng_deferred;
1076 return;
1077 end if;
1078 end if;
1079
1080 -- if we have got this far, go ahead and launch the process.
1081 SItemkey := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'ITEMKEY');
1082 SProcess := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'PROCESS_NAME'));
1083 SUserkey := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'USER_KEY');
1084 SOwner := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'OWNER');
1085 if sItemkey is not null then
1086 wf_engine.LaunchProcess(SItemtype, SItemkey, SProcess, SUserkey, SOwner);
1087
1088 else
1089 begin
1090 launch_count := wf_engine.GetItemAttrNumber(
1091 itemtype, itemkey, 'LAUNCH_COUNT');
1092 exception
1093 when others then
1094 --
1095 -- If item attribute does not exist then create it;
1096 --
1097 if ( wf_core.error_name = 'WFENG_ITEM_ATTR' ) then
1098 wf_engine.AddItemAttr(itemtype,itemkey, 'LAUNCH_COUNT');
1099 launch_count := 0;
1100 else
1101 raise;
1102 end if;
1103 end;
1104
1105 loop_flag:=TRUE;
1106 while loop_flag loop
1107 begin
1108 launch_count:=launch_count+1;
1109 -- imtetype:itemkey is unique so the new itemkey should be unique
1110 sItemkey := itemtype||':'||itemkey||'-'||to_char(launch_count);
1111 wf_engine.LaunchProcess(SItemtype, SItemkey, SProcess,
1112 SUserkey, SOwner);
1113 loop_flag:=FALSE;
1114 exception
1115 when others then
1116 --
1117 -- Dont raise error if its a dup name: instead we will loop
1118 -- around and increment the counter.
1119 if ( wf_core.error_name <> 'WFENG_ITEM_UNIQUE' ) then
1120 raise;
1121 end if;
1122 end;
1123 end loop;
1124
1125 wf_engine.SetItemAttrNumber(
1126 itemtype, itemkey, 'LAUNCH_COUNT',launch_count);
1127
1128 end if;
1129
1130
1131 resultout := wf_engine.eng_completed;
1132
1133 exception
1134 when others then
1135 Wf_Core.Context('Wf_Standard', 'LaunchProcess', itemtype,
1136 itemkey, to_char(actid), Sitemtype||':'||Sitemkey||SProcess);
1137 raise;
1138 end LaunchProcess;
1139
1140 -- LaunchProcess
1141 -- Forks the item by creating a duplicate item with the same history.
1142 -- The new forked item will be identical up to the point of this activity.
1143 -- However this activity will be marked as NOTIFIED. It will be upto the user
1144 -- to push it forward using CompleteActivity.
1145 -- NOTE: this is not permitted for #SYNCH items.
1146 -- IN
1147 -- itemtype - item type
1148 -- itemkey - item key
1149 -- actid - process activity instance id
1150 -- funcmode - execution mode
1151 -- OUT
1152 -- result - NULL
1153 -- ACTIVITY ATTRIBUTES REFERENCED
1154 -- NEW_ITEMKEY - the itemkey for the new item (required)
1155 -- SAME_VERSION - TRUE creates a duplicate, FALSE uses the latest version
1156 procedure ForkItem(itemtype in varchar2,
1157 itemkey in varchar2,
1158 actid in number,
1159 funcmode in varchar2,
1160 resultout in out nocopy varchar2) is
1161
1162 sitemkey varchar2(30);
1163 sameversion boolean;
1164 sameversionFlag varchar2(1);
1165
1166 begin
1167
1168 -- Do nothing in cancel or timeout mode
1169 if (funcmode <> wf_engine.eng_run) then
1170 resultout := wf_engine.eng_null;
1171 return;
1172 end if;
1173
1174 if (itemkey = wf_engine.eng_synch) then
1175 Wf_Core.Token('OPERATION', 'Wf_Standard.ForkItem');
1176 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
1177 end if;
1178
1179
1180
1181 SItemkey := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'NEW_ITEMKEY'));
1182 SameVersionFlag := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'SAME_VERSION');
1183
1184 if SItemkey is null
1185 or SameVersionFlag is null then
1186 wf_core.token('ITEMKEY',Sitemkey);
1187 wf_core.token('SAME_VERSION',SameVersionFlag);
1188 wf_core.raise('WFSQL_ARGS');
1189 end if;
1190
1191 if SameVersionFlag = 'T' then
1192 sameversion := TRUE;
1193 else
1194 sameversion := FALSE;
1195 end if;
1196
1197 -- go ahead and create the new process.
1198 wf_engine.CreateForkProcess(Itemtype, Itemkey, SItemkey, SameVersion);
1199
1200 -- start the new process
1201 wf_engine.StartForkProcess(Itemtype, SItemkey);
1202
1203 resultout := wf_engine.eng_completed;
1204
1205 exception
1206 when others then
1207 Wf_Core.Context('Wf_Standard', 'ForkItem', itemtype,
1208 itemkey, to_char(actid), Sitemkey);
1209 raise;
1210 end ForkItem;
1211
1212 -- Noop
1213 -- Does nothing
1214 -- OUT
1215 -- result - NULL
1216 procedure Noop(itemtype in varchar2,
1217 itemkey in varchar2,
1218 actid in number,
1219 funcmode in varchar2,
1220 resultout in out nocopy varchar2)
1221 is
1222 begin
1223 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
1224 exception
1225 when others then
1226 Wf_Core.Context('Wf_Standard', 'Noop', itemtype,
1227 itemkey, to_char(actid), funcmode);
1228 raise;
1229 end Noop;
1230
1231 -- Notify
1232 -- Public wrapper to engine notification call
1233 -- the engine notification package will retrieve the activity attributes.
1234 -- OUT
1235 -- result - NULL
1236 procedure Notify(itemtype in varchar2,
1237 itemkey in varchar2,
1238 actid in number,
1239 funcmode in varchar2,
1240 resultout in out nocopy varchar2)
1241 is
1242 msg varchar2(30);
1243 msgtype varchar2(8);
1244 prole varchar2(320);
1245 expand_role varchar2(1);
1246
1247 colon pls_integer;
1248 avalue varchar2(240);
1249
1250 begin
1251 -- Do nothing in cancel or timeout mode
1252 if (funcmode <> wf_engine.eng_run) then
1253 resultout := wf_engine.eng_null;
1254 return;
1255 end if;
1256
1257
1258 -- lookup notification base info
1259 Wf_Activity.Notification_Info(itemtype, itemkey, actid, msg, msgtype,
1260 expand_role);
1261
1262 -- see if this activity is already assigned to a role
1263 prole := Wf_Activity.Perform_Role(itemtype, itemkey, actid);
1264
1265 -- if it isnt then use the value from activity attribute
1266 if prole is null then
1267 prole := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'PERFORMER');
1268 end if;
1269
1270 if prole is null then
1271 Wf_Core.Token('TYPE', itemtype);
1272 Wf_Core.Token('ACTID', to_char(actid));
1273 Wf_Core.Raise('WFENG_NOTIFICATION_PERFORMER');
1274 end if;
1275
1276 -- message name and expand roles will be null. Get these from attributes
1277 avalue := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey,
1278 actid, 'MESSAGE'));
1279
1280 -- let notification_send catch a missing message name.
1281 expand_role := nvl(Wf_Engine.GetActivityAttrText(itemtype, itemkey,
1282 actid, 'EXPANDROLES'),'N');
1283
1284 -- parse out the message type if given
1285 colon := instr(avalue, ':');
1286 if colon = 0 then
1287 msgtype := itemtype;
1288 msg := avalue;
1289 else
1290 msgtype := substr(avalue, 1, colon - 1);
1291 msg := substr(avalue, colon + 1);
1292 end if;
1293
1294
1295 -- Actually send the notification
1296 Wf_Engine_Util.Notification_Send(itemtype, itemkey, actid,
1297 msg, msgtype, prole, expand_role,
1298 resultout);
1299
1300
1301 --resultout is determined by Notification_Send as either
1302 --NULL if notification is FYI
1303 --NOTIFIED:notid:role if notification requires responce
1304
1305
1306 exception
1307 when others then
1308 Wf_Core.Context('Wf_Standard', 'Notify', itemtype,
1309 itemkey, to_char(actid), funcmode);
1310 raise;
1311 end Notify;
1312
1313
1314 -- Block
1315 -- Stop and wait for external completion
1316 -- OUT
1317 -- result - NOTIFIED
1318 procedure Block(itemtype in varchar2,
1319 itemkey in varchar2,
1320 actid in number,
1321 funcmode in varchar2,
1322 resultout in out nocopy varchar2)
1323 is
1324 begin
1325 -- Do nothing in cancel or timeout mode
1326 if (funcmode <> wf_engine.eng_run) then
1327 resultout := wf_engine.eng_null;
1328 return;
1329 end if;
1330
1331 resultout := wf_engine.eng_notified||':'||wf_engine.eng_null||
1332 ':'||wf_engine.eng_null;
1333 exception
1334 when others then
1335 Wf_Core.Context('Wf_Standard', 'Block', itemtype,
1336 itemkey, to_char(actid), funcmode);
1337 raise;
1338 end Block;
1339
1340
1341 -- Block
1342 -- Defers the thread by requesting a wait of zero seconds
1343 -- OUT
1344 -- result - DEFERRED
1345 --
1346 procedure Defer(itemtype in varchar2,
1347 itemkey in varchar2,
1348 actid in number,
1349 funcmode in varchar2,
1350 resultout in out nocopy varchar2)
1351 is
1352 status varchar2(8);
1353 result varchar2(30);
1354 begin
1355 -- Do nothing in cancel or timeout mode
1356 if (funcmode <> wf_engine.eng_run) then
1357 resultout := wf_engine.eng_null;
1358 return;
1359 end if;
1360
1361 -- Check if this is the first or second execution of this activity.
1362 -- First -> result_code will be null (really null).
1363 -- Second -> result_code will be '#NULL' (set that way by execution 1).
1364 Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
1365
1366 if (result = wf_engine.eng_null) then
1367 -- Second execution.
1368 -- Defer must have been picked up by the background engine,
1369 -- so return complete result.
1370 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
1371 else
1372 -- Return deferred result
1373 resultout := wf_engine.eng_deferred;
1374 end if;
1375
1376 exception
1377 when others then
1378 Wf_Core.Context('Wf_Standard', 'Defer', itemtype, itemkey,
1379 to_char(actid), funcmode);
1380 raise;
1381 end Defer;
1382
1383 -- Wait
1384 -- Wait until given date and time.
1385 -- OUT
1386 -- result - 'DEFERRED' or 'NULL'
1387 -- 'DEFERRED' if this is the first call and wait is beginning
1388 -- 'NULL' if this is the second call and wait period has completed
1389 -- ACTIVITY ATTRIBUTES REFERENCED
1390 -- WAIT_MODE - Lookup
1391 -- 'ABSOLUTE' - Wait until date in WAIT_ABSOLUTE_DATE
1392 -- 'RELATIVE' - Wait until time WAIT_RELATIVE_TIME after current date
1393 -- 'DAY_OF_WEEK' - Wait until next occurrence of day of week
1394 -- 'DAY_OF_MONTH' - Wait until next occurrence of day of month
1395 -- WAIT_ABSOLUTE_DATE - Date
1396 -- Date to wait until if WAIT_MODE = 'ABSOLUTE'
1397 -- (Ignored if mode <> 'ABSOLUTE')
1398 -- WAIT_RELATIVE_TIME - Number (expressed in <days>.<fraction of days>)
1399 -- Time to wait after current date if WAIT_MODE = 'RELATIVE'
1400 -- (Ignored if mode <> 'RELATIVE')
1401 -- WAIT_DAY_OF_WEEK - Lookup
1402 -- Next day of week (SUNDAY, MONDAY, etc) after current date
1403 -- (Ignored if mode <> 'DAY_OF_WEEK')
1404 -- WAIT_DAY_OF_MONTH - Lookup
1405 -- Next day of month (1, 2, ..., 31, LAST) after current date
1406 -- (Ignored if mode <> 'DAY_OF_MONTH')
1407 -- WAIT_TIME - Date (format HH24:MI)
1408 -- Time of day to complete activity. Valid for all wait modes.
1409 -- If null default time to 00:00 (midnight), except RELATIVE mode.
1410 -- For RELATIVE mode, if time is null then complete relative to current
1411 -- date and time.
1412 -- NOTE:
1413 -- For all WAIT_MODEs, the completion day is determined by the attribute
1414 -- associated with the mode, and the completion time by the WAIT_TIME
1415 -- attribute.
1416 -- For all modes except RELATIVE, the completion time is WAIT_TIME on
1417 -- the day selected by the mode's attribute. If WAIT_TIME is null, the
1418 -- default is 00:00 (midnight).
1419 -- For RELATIVE mode, if WAIT_TIME is null the completion time is
1420 -- figured relative to the current date and time. If WAIT_TIME is not
1421 -- null the completion time is WAIT_TIME on the day selected regardless
1422 -- of the current time.
1423 procedure Wait(itemtype in varchar2,
1424 itemkey in varchar2,
1425 actid in number,
1426 funcmode in varchar2,
1427 resultout in out nocopy varchar2)
1428 is
1429 status varchar2(8);
1430 result varchar2(30);
1431 wait_mode varchar2(30);
1432 wait_date date;
1433 wakeup date;
1434 daybuf varchar2(30);
1435 time date;
1436 wf_invalid_mode exception;
1437 begin
1438 -- Do nothing in cancel or timeout mode
1439 if (funcmode <> wf_engine.eng_run) then
1440 resultout := wf_engine.eng_null;
1441 return;
1442 end if;
1443
1444 -- SYNCHMODE: Not allowed
1445 if (itemkey = wf_engine.eng_synch) then
1446 Wf_Core.Token('OPERATION', 'Wf_Standard.Wait');
1447 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
1448 end if;
1449
1450 -- Check if this is the first or second execution of this activity.
1451 -- First -> result_code will be null (really null).
1452 -- Second -> result_code will be '#NULL' (set that way by execution 1).
1453 Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
1454
1455 if (result = wf_engine.eng_null) then
1456 -- Second execution.
1457 -- Wait is completed, return complete result.
1458 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
1459 else
1460 -- First execution.
1461 wait_mode := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
1462 'WAIT_MODE');
1463
1464 if (wait_mode = 'ABSOLUTE') then
1465 -- Absolute date
1466 wakeup := Wf_Engine.GetActivityAttrDate(itemtype, itemkey, actid,
1467 'WAIT_ABSOLUTE_DATE');
1468
1469 elsif (wait_mode = 'RELATIVE') then
1470 -- Relative date. Figure offset from sysdate.
1471 wakeup := Wf_Engine.GetActivityAttrNumber(itemtype, itemkey, actid,
1472 'WAIT_RELATIVE_TIME') + sysdate;
1473
1474 elsif (wait_mode = 'DAY_OF_WEEK') then
1475 -- Day of week.
1476 daybuf := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
1477 'WAIT_DAY_OF_WEEK');
1478 wakeup := next_day(trunc(sysdate), daybuf);
1479
1480 elsif (wait_mode = 'DAY_OF_MONTH') then
1481 daybuf := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
1482 'WAIT_DAY_OF_MONTH');
1483
1484 -- Figure wakeup time as offset from beginning of current month
1485 if (daybuf = 'LAST') then
1486 -- Set to last day of current month
1487 wakeup := last_day(to_date('01/'||to_char(sysdate, 'MM/YYYY'),
1488 'DD/MM/YYYY'));
1489 else
1490 -- Set to day x of current month
1491 wakeup := to_date('01/'||to_char(sysdate, 'MM/YYYY'),
1492 'DD/MM/YYYY') + to_number(daybuf) - 1;
1493 end if;
1494
1495 -- If wakeup is before current date, then shift to next month
1496 if (wakeup <= sysdate) then
1497 if (daybuf = 'LAST') then
1498 -- Set to last day of following month
1499 wakeup := last_day(add_months(to_date('01/'||to_char(sysdate,
1500 'MM/YYYY'),
1501 'DD/MM/YYYY'), 1));
1502 else
1503 -- Set to day x of the following month
1504 wakeup := add_months(to_date('01/'||to_char(sysdate, 'MM/YYYY'),
1505 'DD/MM/YYYY'), 1)
1506 + to_number(daybuf) - 1;
1507
1508 end if;
1509 end if;
1510 else
1511 raise wf_invalid_mode;
1512 end if;
1513
1514 -- Add the WAIT_TIME to the wakeup if specified
1515 time := Wf_Engine.GetActivityAttrDate(itemtype, itemkey, actid,
1516 'WAIT_TIME');
1517 if (time is not null) then
1518 wakeup := to_date(to_char(wakeup, 'DD/MM/YYYY')||
1519 to_char(time, ' HH24:MI'), 'DD/MM/YYYY HH24:MI');
1520 end if;
1521
1522 -- Return deferred result with wakeup time appended
1523 resultout := wf_engine.eng_deferred||':'||
1524 to_char(wakeup, wf_engine.date_format);
1525 end if;
1526
1527 exception
1528 when wf_invalid_mode then
1529 Wf_Core.Context('Wf_Standard', 'Wait', itemtype, itemkey,
1530 to_char(actid), funcmode);
1531 Wf_Core.Token('COMMAND', wait_mode);
1532 Wf_Core.Raise('WFSQL_COMMAND');
1533 when others then
1534 Wf_Core.Context('Wf_Standard', 'Wait', itemtype, itemkey,
1535 to_char(actid), funcmode);
1536 raise;
1537 end Wait;
1538
1539
1540 -- ResetError
1541 -- Reset the status of an errored activity in an WFERROR process.
1542 -- OUT
1543 -- result - 'NULL'
1544 -- ACTIVITY ATTRIBUTES REFERENCED
1545 -- COMMAND - 'SKIP' or 'RETRY'
1546 -- 'SKIP' marks the errored activity complete and continues processing
1547 -- 'RETRY' clears the errored activity and runs it again
1548 -- RESULT - Result code to complete the activity with if COMMAND = 'SKIP'
1549 procedure ResetError(itemtype in varchar2,
1550 itemkey in varchar2,
1551 actid in number,
1552 funcmode in varchar2,
1553 resultout in out nocopy varchar2)
1554 is
1555 cmd varchar2(8);
1556 result varchar2(30);
1557 err_itemtype varchar2(8);
1558 err_itemkey varchar2(240);
1559 err_actlabel varchar2(62);
1560 wf_invalid_command exception;
1561 begin
1562 -- Do nothing in cancel or timeout mode
1563 if (funcmode <> wf_engine.eng_run) then
1564 resultout := wf_engine.eng_null;
1565 return;
1566 end if;
1567
1568 -- SYNCHMODE: Not allowed
1569 if (itemkey = wf_engine.eng_synch) then
1570 Wf_Core.Token('OPERATION', 'Wf_Standard.ResetError');
1571 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
1572 end if;
1573
1574 -- Get RETRY or SKIP command
1575 cmd := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'COMMAND');
1576
1577 -- Get original errored activity info
1578 err_itemtype := Wf_Engine.GetItemAttrText(itemtype, itemkey,
1579 'ERROR_ITEM_TYPE');
1580 err_itemkey := Wf_Engine.GetItemAttrText(itemtype, itemkey,
1581 'ERROR_ITEM_KEY');
1582 err_actlabel := Wf_Engine.GetItemAttrText(itemtype, itemkey,
1583 'ERROR_ACTIVITY_LABEL');
1584
1585 if (cmd = wf_engine.eng_retry) then
1586 -- Rerun activity
1587 Wf_Engine.HandleError(err_itemtype, err_itemkey, err_actlabel,
1588 cmd, '');
1589
1590 /* Disallow skip mode because it is too difficult to
1591 assign and validate the RESULT value
1592 elsif (cmd = wf_engine.eng_skip) then
1593 -- Get result code
1594 result := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
1595 'RESULT');
1596 -- Mark activity complete and continue processing
1597 Wf_Engine.HandleError(err_itemtype, err_itemkey, err_actlabel,
1598 cmd, result);
1599 */
1600 else
1601 raise wf_invalid_command;
1602 end if;
1603
1604 resultout := wf_engine.eng_null;
1605 exception
1606 when wf_invalid_command then
1607 Wf_Core.Context('Wf_Standard', 'ResetError', itemtype,
1608 itemkey, to_char(actid), funcmode);
1609 Wf_Core.Token('COMMAND', cmd);
1610 Wf_Core.Raise('WFSQL_COMMAND');
1611 when others then
1612 Wf_Core.Context('Wf_Standard', 'ResetError', itemtype,
1613 itemkey, to_char(actid), funcmode);
1614 raise;
1615 end ResetError;
1616
1617
1618 -- RoleResolution
1619 -- Resolve A Role which comprises a group to an individual
1620 -- OUT
1621 -- result - 'NULL'
1622 -- ACTIVITY ATTRIBUTES REFERENCED
1623 -- COMMAND - 'LOAD_BALANCE' or 'ROUND_ROBIN'
1624 -- 'LOAD_BALANCE' Assigns to user with least open notifications
1625 -- 'ROUND_ROBIN' Assigns notification to users sequencially
1626 procedure RoleResolution(itemtype in varchar2,
1627 itemkey in varchar2,
1628 actid in number,
1629 funcmode in varchar2,
1630 resultout in out nocopy varchar2) is
1631 cmd varchar2(30);
1632 wf_invalid_command exception;
1633 actdate date;
1634 label varchar2(30);
1635 prole varchar2(320);
1636 --
1637 -- select all out-transitions of RoleResolution Activity
1638 --
1639 cursor out_transitions is
1640 SELECT wat.to_process_activity,
1641 wpa.activity_name,
1642 wpa.perform_role,
1643 wpa.perform_role_type
1644 FROM wf_activity_transitions wat,
1645 wf_process_activities wpa
1646 WHERE wat.from_process_activity = actid
1647 AND wat.result_code = wf_engine.eng_trans_default
1648 AND wat.to_process_activity = wpa.instance_id;
1649 --
1650 -- select number of activities the user currently has in worklist
1651 --
1652 cursor load_balance(user in varchar2, act_name varchar2 ) is
1653 select count(1)
1654 from wf_item_activity_statuses wias,
1655 wf_process_activities wpa
1656 where wias.item_type = itemtype
1657 and wias.activity_status = 'NOTIFIED'
1658 and wias.process_activity = wpa.instance_id
1659 and wpa.activity_name = act_name
1660 and assigned_user = user;
1661 --
1662 -- select the date of the last time the user was notified
1663 --
1664 cursor round_robin(user in varchar2, act_name varchar2 ) is
1665 select max(begin_date)
1666 from wf_item_activity_statuses wias,
1667 wf_process_activities wpa
1668 where wias.item_type = itemtype
1669 and wias.process_activity = wpa.instance_id
1670 and wpa.activity_name = act_name
1671 and wias.assigned_user = user;
1672 --
1673 begin
1674 --
1675 -- Do nothing in cancel mode
1676 --
1677 if (funcmode <> wf_engine.eng_run ) then
1678 resultout := wf_engine.eng_null;
1679 return;
1680 end if;
1681
1682 -- SYNCHMODE: Not allowed
1683 if (itemkey = wf_engine.eng_synch) then
1684 Wf_Core.Token('OPERATION', 'Wf_Standard.AndJoin');
1685 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
1686 end if;
1687
1688 actdate := wf_item.active_date(itemtype, itemkey);
1689 cmd := Wf_Engine.GetActivityAttrText(itemtype,itemkey,actid,'METHOD');
1690
1691 -- loop thru all out-transiations of role resolution activity
1692 for trans_rec in out_transitions loop
1693 declare
1694 usertab wf_directory.UserTable;
1695 min_assigned_activities number := -1;
1696 min_begin_date date;
1697 assigned_performer varchar2(320);
1698 begin
1699 --
1700 if (Wf_Activity.Type(itemtype, trans_rec.activity_name, actdate) =
1701 wf_engine.eng_notification) then
1702 -- Get perform_role from constant or itemattr value
1703 if (trans_rec.perform_role_type = 'CONSTANT') then
1704 prole := trans_rec.perform_role;
1705 else
1706 prole := Wf_Engine.GetItemAttrText(itemtype, itemkey,
1707 trans_rec.perform_role);
1708 end if;
1709 wf_directory.GetRoleUsers(prole,usertab);
1710 if ( cmd = 'LOAD_BALANCE' ) then
1711 declare
1712 assigned_activities number := 0;
1713 indx number := 1;
1714 begin
1715 loop -- loop until NO_DATA_FOUND
1716 open load_balance(usertab(indx),
1717 trans_rec.activity_name);
1718 fetch load_balance into assigned_activities;
1719 close load_balance;
1720
1721 if ((assigned_activities < min_assigned_activities or
1722 min_assigned_activities = -1) and
1723 wf_directory.UserActive(usertab(indx))) then
1724 min_assigned_activities := assigned_activities;
1725 assigned_performer := usertab(indx);
1726 end if;
1727
1728 indx := indx + 1;
1729 end loop;
1730 exception
1731 when NO_DATA_FOUND then
1732 null;
1733 end;
1734 elsif ( cmd = 'ROUND_ROBIN' ) then
1735 declare
1736 begin_date date;
1737 indx number :=1;
1738 begin
1739 loop -- until access of usertab raises NO_DATA_FOUND
1740 open round_robin(usertab(indx),
1741 trans_rec.activity_name);
1742 fetch round_robin into begin_date;
1743 close round_robin;
1744
1745 if (begin_date is null) then
1746 begin_date := to_date('01/01/0001','DD/MM/YYYY');
1747 end if;
1748
1749 if ((begin_date < min_begin_date or
1750 min_begin_date is null) and
1751 wf_directory.UserActive(usertab(indx))) then
1752 min_begin_date := begin_date;
1753 assigned_performer := usertab(indx);
1754 end if;
1755
1756 indx := indx + 1;
1757 end loop;
1758 exception
1759 when NO_DATA_FOUND then
1760 null;
1761 end;
1762 else
1763 raise wf_invalid_command;
1764 end if;
1765
1766 if ( assigned_performer is not null ) then
1767 --
1768 -- Retreieve instance_label for activity
1769 --
1770 select wpa.instance_label
1771 into label
1772 from wf_process_activities wpa
1773 where wpa.instance_id = trans_rec.to_process_activity;
1774
1775 wf_engine.AssignActivity(itemtype,itemkey,label,
1776 assigned_performer);
1777
1778 end if;
1779
1780 resultout := wf_engine.eng_null;
1781 end if;
1782 end;
1783 end loop;
1784 exception
1785 when wf_invalid_command then
1786 wf_core.context('Wf_Standard', 'RoleResoluion',
1787 itemtype, itemkey, to_char(actid), funcmode);
1788 wf_core.token('COMMAND', cmd);
1789 wf_core.raise('WFSQL_COMMAND');
1790 when others then
1791 wf_core.Context('Wf_Standard', 'RoleResolution',
1792 itemtype, itemkey, to_char(actid), funcmode);
1793 raise;
1794 end RoleResolution;
1795
1796
1797 -- ContinueFlow
1798 -- Signal Flow to continue
1799 -- OUT
1800 -- result - 'NULL'
1801 -- ACTIVITY ATTRIBUTES REFERENCED
1802 -- WAITING_ACTIVITY
1803 -- WAITING_FLOW
1804 procedure ContinueFlow( itemtype in varchar2,
1805 itemkey in varchar2,
1806 actid in number,
1807 funcmode in varchar2,
1808 resultout in out nocopy varchar2 ) is
1809 l_waiting_activity varchar2(30);
1810 l_waiting_flow varchar2(30);
1811 wf_invalid_command exception;
1812 begin
1813 if (funcmode <> wf_engine.eng_run) then
1814 resultout := wf_engine.eng_null;
1815 return;
1816 end if;
1817
1818 -- SYNCHMODE: Not allowed
1819 if (itemkey = wf_engine.eng_synch) then
1820 Wf_Core.Token('OPERATION', 'Wf_Standard.AndJoin');
1821 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
1822 end if;
1823
1824 l_waiting_activity := upper(Wf_Engine.GetActivityAttrText(
1825 itemtype, itemkey, actid,'WAITING_ACTIVITY'));
1826 l_waiting_flow := Wf_Engine.GetActivityAttrText(
1827 itemtype, itemkey, actid,'WAITING_FLOW');
1828
1829 if ( l_waiting_flow = 'MASTER' ) then
1830 ContinueMasterFlow(itemtype,itemkey,actid,l_waiting_activity,resultout);
1831 elsif ( l_waiting_flow = 'DETAIL' ) then
1832 ContinueDetailFlow(itemtype,itemkey,actid,l_waiting_activity,resultout);
1833 else
1834 raise wf_invalid_command;
1835 end if;
1836
1837 exception
1838 when wf_invalid_command then
1839 Wf_Core.Context('Wf_Standard', 'ContinueFlow',
1840 itemtype,itemkey, to_char(actid), funcmode);
1841 Wf_Core.Token('COMMAND', l_waiting_flow );
1842 Wf_Core.Raise('WFSQL_COMMAND');
1843 when others then
1844 Wf_Core.Context('Wf_Standard', 'ContinueFlow',
1845 itemtype,itemkey, to_char(actid), funcmode);
1846 raise;
1847 end continueflow;
1848
1849
1850 -- WaitForFlow
1851 -- Wait for flow to complete
1852 -- OUT
1853 -- result - 'NULL'
1854 -- ACTIVITY ATTRIBUTES REFERENCED
1855 -- CONTINUATION_ACTIVITY
1856 -- CONTINUATION_FLOW
1857 procedure WaitForFlow( itemtype in varchar2,
1858 itemkey in varchar2,
1859 actid in number,
1860 funcmode in varchar2,
1861 resultout in out nocopy varchar2) is
1862 l_continuation_activity varchar2(30);
1863 l_continuation_flow varchar2(30);
1864 wf_invalid_command exception;
1865 begin
1866 if (funcmode <> wf_engine.eng_run) then
1867 resultout := wf_engine.eng_null;
1868 return;
1869 end if;
1870
1871 -- SYNCHMODE: Not allowed
1872 if (itemkey = wf_engine.eng_synch) then
1873 Wf_Core.Token('OPERATION', 'Wf_Standard.WaitForFlow');
1874 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
1875 end if;
1876
1877 l_continuation_activity := upper(Wf_Engine.GetActivityAttrText(
1878 itemtype, itemkey, actid,
1879 'CONTINUATION_ACTIVITY'));
1880 l_continuation_flow := Wf_Engine.GetActivityAttrText(
1881 itemtype,itemkey,actid,'CONTINUATION_FLOW');
1882
1883 if ( l_continuation_flow = 'MASTER' ) then
1884 WaitForMasterFlow(itemtype,itemkey,actid,
1885 l_continuation_activity,resultout);
1886 elsif ( l_continuation_flow = 'DETAIL' ) then
1887 WaitForDetailFlow(itemtype,itemkey,actid,
1888 l_continuation_activity,resultout);
1889 else
1890 raise wf_invalid_command;
1891 end if;
1892
1893 exception
1894 when wf_invalid_command then
1895 Wf_Core.Context('Wf_Standard', 'WaitForFlow',
1896 itemtype,itemkey, to_char(actid), funcmode);
1897 Wf_Core.Token('COMMAND', l_continuation_flow );
1898 Wf_Core.Raise('WFSQL_COMMAND');
1899 when others then
1900 Wf_Core.Context('Wf_Standard', 'WaitForFlow',
1901 itemtype,itemkey, to_char(actid), funcmode);
1902 raise;
1903 end WaitForFlow;
1904
1905
1906 -- LoopCounter
1907 -- Count the number of times the activity has been visited.
1908 -- OUT
1909 -- result -
1910 -- ACTIVITY ATTRIBUTES REFERENCED
1911 -- MAX_TIMES
1912 procedure LoopCounter( itemtype in varchar2,
1913 itemkey in varchar2,
1914 actid in number,
1915 funcmode in varchar2,
1916 resultout in out nocopy varchar2) is
1917 max_times pls_integer;
1918 loop_count pls_integer;
1919 begin
1920 --
1921 -- Do nothing in cancel mode
1922 --
1923 if (funcmode <> wf_engine.eng_run) then
1924 resultout := wf_engine.eng_null;
1925 return;
1926 end if;
1927
1928 -- Get maximum times activity can be executed.
1929 max_times := wf_engine.GetActivityAttrNumber(
1930 itemtype, itemkey, actid, 'MAX_TIMES');
1931 if ( max_times is null ) then
1932 wf_core.token('MAX_TIMES',max_times);
1933 wf_core.raise('WFSQL_ARGS');
1934 end if;
1935
1936 begin
1937 loop_count := wf_engine.GetItemAttrNumber(
1938 itemtype, itemkey, 'LOOP_COUNT'||':'||actid);
1939 exception
1940 when others then
1941 --
1942 -- If item attribute does not exist then create it;
1943 --
1944 if ( wf_core.error_name = 'WFENG_ITEM_ATTR' ) then
1945 wf_engine.AddItemAttr(
1946 itemtype,itemkey, 'LOOP_COUNT'||':'||actid);
1947 loop_count := 0;
1948 else
1949 raise;
1950 end if;
1951 end;
1952
1953 if ( loop_count >= max_times ) then
1954 loop_count := 0;
1955 resultout := 'EXIT';
1956 else
1957 loop_count := loop_count +1;
1958 resultout := 'LOOP';
1959 end if;
1960
1961 wf_engine.SetItemAttrNumber(
1962 itemtype, itemkey, 'LOOP_COUNT'||':'||actid,loop_count);
1963 exception
1964 when others then
1965 wf_core.context('Wf_Standard','LoopCount',
1966 itemtype, itemkey, to_char(actid), funcmode);
1967 raise;
1968 end loopcounter;
1969
1970
1971 -- VoteForResultType
1972 -- Standard Voting Function
1973 -- IN
1974 -- itemtype - A valid item type from (WF_ITEM_TYPES table).
1975 -- itemkey - A string generated from the application object's primary key.
1976 -- actid - The process activity(instance id).
1977 -- funcmode - Run/Cancel
1978 -- OUT
1979 -- result -
1980 --
1981 -- USED BY ACTIVITIES
1982 --
1983 -- WFSTD.VoteForResultType
1984 --
1985 -- ACTIVITY ATTRIBUTES REFERENCED
1986 -- VOTING_OPTION
1987 -- - WAIT_FOR_ALL_VOTES - Evaluate voting after all votes are cast
1988 -- - or a Timeout condition closes the voting
1989 -- - polls. When a Timeout occurs the
1990 -- - voting percentages are calculated as a
1991 -- - percentage ofvotes cast.
1992 --
1993 -- - REQUIRE_ALL_VOTES - Evaluate voting after all votes are cast.
1994 -- - If a Timeout occurs and all votes have not
1995 -- - been cast then the standard timeout
1996 -- - transition is taken. Votes are calculated
1997 -- - as a percenatage of users notified to vote.
1998 --
1999 -- - TALLY_ON_EVERY_VOTE - Evaluate voting after every vote or a
2000 -- - Timeout condition closes the voting polls.
2001 -- - After every vote voting percentages are
2002 -- - calculated as a percentage of user notified
2003 -- - to vote. After a timeout voting
2004 -- - percentages are calculated as a percentage
2005 -- - of votes cast.
2006 --
2007 -- "One attribute for each of the activities result type codes"
2008 --
2009 -- - The standard Activity VOTEFORRESULTTYPE has the WFSTD_YES_NO
2010 -- - result type assigned.
2011 -- - Thefore activity has two activity attributes.
2012 --
2013 -- Y - Percenatage required for Yes transition
2014 -- N - Percentage required for No transition
2015 --
2016 procedure VoteForResultType( itemtype in varchar2,
2017 itemkey in varchar2,
2018 actid in number,
2019 funcmode in varchar2,
2020 resultout in out nocopy varchar2)
2021 is
2022 -- Select all lookup codes for an activities result type
2023 cursor result_codes is
2024 select wfl.lookup_code result_code
2025 from wf_lookups wfl,
2026 wf_activities wfa,
2027 wf_process_activities wfpa,
2028 wf_items wfi
2029 where wfl.lookup_type = wfa.result_type
2030 and wfa.name = wfpa.activity_name
2031 and wfi.begin_date >= wfa.begin_date
2032 and wfi.begin_date < nvl(wfa.end_date,wfi.begin_date+1)
2033 and wfpa.activity_item_type = wfa.item_type
2034 and wfpa.instance_id = actid
2035 and wfi.item_key = itemkey
2036 and wfi.item_type = itemtype;
2037
2038 l_code_count pls_integer;
2039 l_group_id pls_integer;
2040 l_user varchar2(320);
2041 l_voting_option varchar2(30);
2042 l_per_of_total number;
2043 l_per_of_vote number;
2044 l_per_code number;
2045 per_success number;
2046 max_default pls_integer := 0;
2047 default_result varchar2(30) := '';
2048 result varchar2(30) := '';
2049 wf_invalid_command exception;
2050 begin
2051 -- Do nothing unless in RUN or TIMEOUT modes
2052 if (funcmode <> wf_engine.eng_run)
2053 and (funcmode <> wf_engine.eng_timeout) then
2054 resultout := wf_engine.eng_null;
2055 return;
2056 end if;
2057
2058 -- SYNCHMODE: Not allowed
2059 if (itemkey = wf_engine.eng_synch) then
2060 Wf_Core.Token('OPERATION', 'Wf_Standard.VotForResultType');
2061 Wf_Core.Raise('WFENG_SYNCH_DISABLED');
2062 end if;
2063
2064 -- Get Notifications group_id for activity
2065 Wf_Item_Activity_Status.Notification_Status(itemtype,itemkey,actid,
2066 l_group_id,l_user);
2067 l_voting_option := Wf_Engine.GetActivityAttrText(itemtype,itemkey,
2068 actid,'VOTING_OPTION');
2069 if (l_voting_option not in ('REQUIRE_ALL_VOTES', 'WAIT_FOR_ALL_VOTES',
2070 'TALLY_ON_EVERY_VOTE')) then
2071 raise wf_invalid_command;
2072 end if;
2073
2074 -- If the mode is one of:
2075 -- a. REQUIRE_ALL_VOTES
2076 -- b. WAIT_FOR_ALL_VOTES and no timeout has occurred
2077 -- and there are still open notifications, then return WAITING to
2078 -- either continue voting (in run mode) or trigger timeout processing
2079 -- (in timeout mode).
2080 if ((l_voting_option = 'REQUIRE_ALL_VOTES') or
2081 ((funcmode = wf_engine.eng_run) and
2082 (l_voting_option = 'WAIT_FOR_ALL_VOTES'))) then
2083 if (wf_notification.OpenNotificationsExist(l_group_id)) then
2084 resultout := wf_engine.eng_waiting;
2085 return;
2086 end if;
2087 end if;
2088
2089 -- If here, then the mode is one of:
2090 -- a. TALLY_ON_ALL_VOTES
2091 -- b. WAIT_FOR_ALL_VOTES and timeout has occurred
2092 -- c. WAIT_FOR_ALL_VOTES and all votes are cast
2093 -- d. REQUIRE_ALL_VOTES and all votes are cast
2094 -- Tally votes.
2095 for result_rec in result_codes loop
2096 -- Tally Vote Count for this result code
2097 Wf_Notification.VoteCount(l_group_id,result_rec.result_code,
2098 l_code_count,l_per_of_total,l_per_of_vote);
2099
2100 -- If this is timeout mode, then use the percent of votes cast so far.
2101 -- If this is run mode, then use the percent of total votes possible.
2102 if (funcmode = wf_engine.eng_timeout) then
2103 l_per_code := l_per_of_vote;
2104 else
2105 l_per_code := l_per_of_total;
2106 end if;
2107
2108 -- Get percent vote needed for this result to succeed
2109 per_success := Wf_Engine.GetActivityAttrNumber(itemtype,itemkey,
2110 actid,result_rec.result_code);
2111
2112 if (per_success is null) then
2113 -- Null value means this is a default result.
2114 -- Save the default result with max code_count.
2115 if (l_code_count > max_default) then
2116 max_default := l_code_count;
2117 default_result := result_rec.result_code;
2118 elsif (l_code_count = max_default) then
2119 -- Tie for default result.
2120 default_result := wf_engine.eng_tie;
2121 end if;
2122 else
2123 -- If:
2124 -- a. % vote for this result > % needed for success OR
2125 -- b. % vote is 100% AND
2126 -- c. at least 1 vote for this result
2127 -- then this result succeeds.
2128 if (((l_per_code > per_success) or (l_per_code = 100)) and
2129 (l_code_count > 0))
2130 then
2131 if (result is null) then
2132 -- Save satisfied result.
2133 result := result_rec.result_code;
2134 else
2135 -- This is the second result to be satisfied. Return a tie.
2136 resultout := wf_engine.eng_completed||':'||wf_engine.eng_tie;
2137 return;
2138 end if;
2139 end if;
2140 end if;
2141 end loop;
2142
2143 if (result is not null) then
2144 -- Return the satisfied result code.
2145 resultout := wf_engine.eng_completed||':'||result;
2146 else
2147 -- If we get here no non-default results were satisfied.
2148 if (funcmode = wf_engine.eng_run and
2149 wf_notification.OpenNotificationsExist(l_group_id)) then
2150 -- Not timed out and still open notifications.
2151 -- Return waiting to continue voting.
2152 resultout := wf_engine.eng_waiting;
2153 elsif (default_result is not null) then
2154 -- Either timeout or all notifications closed
2155 -- Return default result if one found.
2156 resultout := wf_engine.eng_completed||':'||default_result;
2157 elsif (funcmode = wf_engine.eng_timeout) then
2158 -- If Timeout has occured then return result Timeout so the Timeout
2159 -- transition will occur - BUG2885157
2160 resultout := wf_engine.eng_completed||':'||wf_engine.eng_timedout;
2161 else
2162 -- All notifications closed, and no default.
2163 -- Return nomatch
2164 resultout := wf_engine.eng_completed||':'||wf_engine.eng_nomatch;
2165 end if;
2166 end if;
2167 return;
2168 exception
2169 when wf_invalid_command then
2170 Wf_Core.Context('Wf_Standard', 'VoteForResultType', itemtype,
2171 itemkey, to_char(actid), funcmode);
2172 Wf_Core.Token('COMMAND', l_voting_option);
2173 Wf_Core.Raise('WFSQL_COMMAND');
2174 when others then
2175 Wf_Core.Context('Wf_Standard', 'VoteForResultType',itemtype,
2176 itemkey, to_char(actid), funcmode);
2177 raise;
2178 end VoteForResultType;
2179
2180
2181 -------------------------------------------------------------------------------
2182 ------------------------------- PRIVATE APIs ----------------------------------
2183 -------------------------------------------------------------------------------
2184
2185 --
2186 -- WaitForMasterFlow
2187 -- Wait for Master flow to complete continuation activity
2188 -- OUT
2189 -- result - 'NULL'
2190 procedure WaitForMasterFlow( itemtype in varchar2,
2191 itemkey in varchar2,
2192 actid in number,
2193 continuation_activity in varchar2,
2194 resultout out nocopy varchar2 )
2195 is
2196 l_parent_itemtype varchar2(8);
2197 l_parent_itemkey varchar2(240);
2198 l_activity_status varchar2(30);
2199
2200 colon pls_integer;
2201 process varchar2(30);
2202 label varchar2(30);
2203 instid pls_integer;
2204 dummy varchar2(50);
2205 begin
2206
2207 -- Parse activity arg into <process_name> and <instance_label> components.
2208 colon := instr(continuation_activity, ':');
2209 if (colon <> 0) then
2210 -- Activity arg is <process name>:<instance label>
2211 process := substr(continuation_activity, 1, colon-1);
2212 label := substr(continuation_activity, colon+1);
2213 else
2214 -- Activity arg is just instance label
2215 process := '';
2216 label := continuation_activity;
2217 end if;
2218
2219 select parent_item_type, parent_item_key
2220 into l_parent_itemtype, l_parent_itemkey
2221 from wf_items
2222 where item_type = WaitForMasterFlow.itemtype
2223 and item_key = WaitForMasterFlow.itemkey;
2224
2225
2226 begin
2227 select 'master activity not complete'
2228 into dummy
2229 from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA
2230 where WIAS.ITEM_TYPE = l_parent_itemtype
2231 and WIAS.ITEM_KEY = l_parent_itemkey
2232 and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
2233 and WPA.INSTANCE_LABEL = label
2234 and WPA.PROCESS_NAME = nvl(process, WPA.PROCESS_NAME)
2235 and wias.activity_status in (wf_engine.eng_completed, wf_engine.eng_active);
2236 exception
2237 -- When not complete return NOTIFIED to cause engine to stall
2238 when NO_DATA_FOUND then
2239 resultout := wf_engine.eng_notified||':'||wf_engine.eng_null|| ':'||wf_engine.eng_null;
2240 return;
2241 end;
2242 resultout := wf_engine.eng_null;
2243 exception
2244 when others then
2245 wf_core.context('Wf_Standard', 'WaitForMasterFlow',
2246 itemtype,itemkey,to_char(actid),continuation_activity);
2247 raise;
2248 end WaitForMasterFlow;
2249
2250
2251 -- WaitForDetailFlow
2252 -- Wait for detail flows to complete continuation activity
2253 -- OUT
2254 -- result - 'NULL'
2255 procedure WaitForDetailFlow( itemtype in varchar2,
2256 itemkey in varchar2,
2257 actid in number,
2258 continuation_activity in varchar2,
2259 resultout out nocopy varchar2) is
2260 cursor child_flows is
2261 -- select all active children of parent flow
2262 select count(1)
2263 from wf_items
2264 where parent_item_type = itemtype
2265 and parent_item_key = itemkey
2266 and end_date is null;
2267
2268 cursor child_activities (itemtype varchar2, itemkey varchar2,
2269 pname varchar2, plabel varchar2) is
2270 select count(1)
2271 from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA
2272 where (WIAS.ITEM_TYPE, WIAS.ITEM_KEY) in (select item_type,item_key
2273 from wf_items
2274 where parent_item_type =itemtype
2275 and parent_item_key =itemkey
2276 and end_date is null)
2277 and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
2278 and WPA.INSTANCE_LABEL = plabel
2279 and WPA.PROCESS_NAME = nvl(pname, WPA.PROCESS_NAME)
2280 and wias.activity_status in (wf_engine.eng_completed, wf_engine.eng_active);
2281
2282 cursor current_process (p_actid number) is
2283 select instance_label
2284 from wf_process_activities
2285 where instance_id = p_actid;
2286
2287 colon pls_integer;
2288 process varchar2(30);
2289 label varchar2(30);
2290 instid pls_integer;
2291 number_active pls_integer;
2292 number_complete pls_integer;
2293 l_childCount number;
2294 l_labelCount number;
2295 l_waitLabel varchar2(30);
2296
2297 begin
2298 -- Parse activity arg into <process_name> and <instance_label> components.
2299 colon := instr(continuation_activity, ':');
2300 if (colon <> 0) then
2301 -- Activity arg is <process name>:<instance label>
2302 process := substr(continuation_activity, 1, colon-1);
2303 label := substr(continuation_activity, colon+1);
2304 else
2305 -- Activity arg is just instance label
2306 process := '';
2307 label := continuation_activity;
2308 end if;
2309
2310 --Retrieve the label for the WaitForFlow activity.
2311 open current_process(actid);
2312 fetch current_process into l_waitLabel;
2313 close current_process;
2314
2315 l_labelCount := WF_ENGINE.GetItemAttrNumber(itemType, itemKey,
2316 '#CNT_'||l_waitLabel, TRUE);
2317 if (l_labelCount is NULL) then
2318 l_childCount := WF_ENGINE.GetItemAttrNumber(itemType, itemKey,
2319 '#WAITFORDETAIL', TRUE);
2320 if (l_childCount is NULL) then --Fall back to the old path.
2321 open child_flows;
2322 fetch child_flows into number_active;
2323 close child_flows;
2324
2325 if (number_active < 1) then
2326 resultout := wf_engine.eng_null;
2327 else
2328 open child_activities(itemtype, itemkey, process, label);
2329 fetch child_activities into number_complete;
2330 close child_activities;
2331
2332 if number_active > number_complete then
2333 resultout := wf_engine.eng_notified||':'||
2334 wf_engine.eng_null||':'||wf_engine.eng_null;
2335 else
2336 resultout := wf_engine.eng_null;
2337 end if;
2338
2339 end if; --There are no children
2340 else --#WAITFORDETAIL exists
2341 WF_ENGINE.AddItemAttr(itemtype=>WaitForDetailFlow.itemtype,
2342 itemkey=>WaitForDetailFlow.itemkey,
2343 aname=>'#CNT_'||l_waitLabel,
2344 number_value=>l_childCount);
2345 if (l_childCount > 0) then
2346 resultout := wf_engine.eng_notified||':'||
2347 wf_engine.eng_null||':'||wf_engine.eng_null;
2348 else
2349 resultout := wf_engine.eng_null;
2350 end if; --l_childCount > 0
2351 end if; -- #WAITFORDETAIL
2352 elsif (l_labelCount > 0) then
2353 --The #CNT_ attribute exists and is 1 or greater so this will remain
2354 --notified.
2355 resultout := wf_engine.eng_notified||':'||wf_engine.eng_null||
2356 ':'||wf_engine.eng_null;
2357
2358 else --The labelcount exists and is < 1 so we can continue.
2359 resultout := wf_engine.eng_null;
2360 end if;
2361
2362
2363 exception
2364 when others then
2365 wf_core.context('Wf_Standard', 'WaitForDetailFlow',
2366 itemtype,itemkey,to_char(actid),continuation_activity);
2367 raise;
2368 end WaitForDetailFlow;
2369
2370
2371 -- ContinueDetailFlow
2372 -- Signal Detail Flows to continue
2373 -- IN
2374 -- itemtype - A valid item type from (WF_ITEM_TYPES table).
2375 -- itemkey - A string generated from the application object's primary key.
2376 -- actid - The process activity(instance id).
2377 -- waiting_activity - The Name of the activity that in waiting
2378 -- OUT
2379 -- resultout - 'NULL'
2380 procedure ContinueDetailFlow( itemtype in varchar2,
2381 itemkey in varchar2,
2382 actid in number,
2383 waiting_activity in varchar2,
2384 resultout out nocopy varchar2
2385 ) is
2386 --
2387 cursor child_flows is
2388 --
2389 -- select all active children of parent flow
2390 --
2391 select item_type, item_key
2392 from wf_items
2393 where parent_item_type = itemtype
2394 and parent_item_key = itemkey
2395 and end_date is null;
2396 --
2397 begin
2398 for child_flows_rec in child_flows loop
2399 --
2400 -- Complete Waiting Activity in All Detail Flows
2401 --
2402 begin
2403 wf_engine.CompleteActivity(child_flows_rec.item_type,
2404 child_flows_rec.item_key, waiting_activity,wf_engine.eng_null);
2405 exception
2406 when others then
2407 -- If call to CompleteActivity cannot find activity, return null
2408 -- As either the detail flows does not have a waiting activity OR
2409 -- the detail flow has not reach the waiting activity
2410 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2411 wf_core.clear;
2412 else
2413 raise;
2414 end if;
2415 end;
2416 end loop;
2417
2418 ContinueDetailFlow.resultout := wf_engine.eng_null;
2419
2420 exception
2421 when others then
2422 wf_core.context('Wf_Standard','ContinueDetailFlow',
2423 itemtype, itemkey, to_char(actid),waiting_activity);
2424 raise;
2425 end ContinueDetailFlow;
2426
2427
2428 -- ContinueMasterFlow
2429 -- Signal Master Flow to continue if all Detail flows have
2430 -- executed Continuation Activity
2431 -- OUT
2432 -- result - 'NULL'
2433 procedure ContinueMasterFlow( itemtype in varchar2,
2434 itemkey in varchar2,
2435 actid in number,
2436 waiting_activity in varchar2,
2437 resultout in out nocopy varchar2) is
2438
2439
2440 l_activity_status varchar2(8);
2441 l_parent_itemtype varchar2(8);
2442 l_parent_itemkey varchar2(240);
2443 label varchar2(30);
2444 number_active pls_integer;
2445 number_complete pls_integer;
2446
2447 -- CTILLEY bug 1941013
2448 l_parent_context varchar2(2000);
2449
2450 cursor child_flows_mwf is
2451 -- This cursor is used if there are multiple WaitForFlow Activities in the
2452 -- parent flow (the parent_context must be set). CTILLEY bug 1941013
2453 -- select all active children of parent flow excluding current work item
2454 select count(1)
2455 from wf_items
2456 where parent_item_type = l_parent_itemtype
2457 and parent_item_key = l_parent_itemkey
2458 and parent_context = l_parent_context
2459 and (item_type <> ContinueMasterFlow.itemtype
2460 or item_key <> ContinueMasterFlow.itemkey)
2461 and end_date is null;
2462
2463 cursor child_flows2 is
2464 -- select all active children of parent flow excluding current work item
2465 select count(1)
2466 from wf_items
2467 where parent_item_type = l_parent_itemtype
2468 and parent_item_key = l_parent_itemkey
2469 and (item_type <> ContinueMasterFlow.itemtype
2470 or item_key <> ContinueMasterFlow.itemkey)
2471 and end_date is null;
2472
2473 cursor child_activities2 is
2474 select count(1)
2475 from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA,
2476 WF_ITEMS WI
2477 where WIAS.ITEM_TYPE = itemtype
2478 and WIAS.ITEM_KEY = WI.item_key
2479 and WI.parent_item_type = l_parent_itemtype
2480 and WI.parent_item_key = l_parent_itemkey
2481 and (WI.item_type <> itemtype OR WI.item_key <> itemkey )
2482 and WI.end_date is null
2483 and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
2484 and WPA.INSTANCE_LABEL = label
2485 and wias.activity_status in (wf_engine.eng_completed,
2486 wf_engine.eng_active);
2487
2488 dummy varchar2(240);
2489 status varchar2(8);
2490 result varchar2(30);
2491 l_count number;
2492 l_defer varchar2(4000);
2493 l_childwaiting number;
2494 begin
2495 --
2496 -- select parent details
2497 --
2498 select parent_item_type, parent_item_key, parent_context
2499 into l_parent_itemtype, l_parent_itemkey, l_parent_context
2500 from wf_items
2501 where item_type = ContinueMasterFlow.itemtype
2502 and item_key = ContinueMasterFlow.itemkey;
2503
2504 select instance_label
2505 into label
2506 from wf_process_activities
2507 where instance_id = actid;
2508
2509 -- Check if this is the first or second execution of this activity.
2510 -- First -> result_code will be null (really null).
2511 -- Second -> result_code will be '#NULL' (set that way by execution 1).
2512 Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
2513
2514 if (result = wf_engine.eng_null) then
2515 -- Second execution.
2516 -- ContinueFlow() completed and was deferred.
2517 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
2518 return;
2519 else
2520 --First execution.
2521
2522 -- lock the parent item, so only one child can execute this at the time.
2523 select item_key
2524 into dummy
2525 from wf_items
2526 where item_type = l_parent_itemtype
2527 and item_key = l_parent_itemkey
2528 for update;
2529
2530 --Nulling out the #LBL_ attribute, if it does not exist, we will check the
2531 --parent flow for #WAITFORDETAIL to see if we can create the #LBL_
2532 --attribute.
2533 if NOT (WF_ENGINE.SetItemAttrText2(ContinueMasterFlow.itemtype,
2534 ContinueMasterFlow.itemkey,
2535 '#LBL_'||waiting_activity,
2536 NULL)) then
2537 l_childwaiting := WF_ENGINE.GetItemAttrNumber(
2538 l_parent_itemtype, l_parent_itemkey,
2539 '#WAITFORDETAIL', TRUE);
2540 if (l_childwaiting is NOT NULL) then
2541 --The parent has #WAITFORDETAIL, so we can create the #LBL_ attribute
2542 WF_ENGINE.AddItemAttr(ContinueMasterFlow.itemtype,
2543 ContinueMasterFlow.itemkey,
2544 '#LBL_'||waiting_activity, NULL);
2545
2546 else --#WAITFORDETAIL does not exist in the parent, so we will fall back
2547 --to old code path.
2548 -- If parent_context is not set then there is one WaitForFlow Activity
2549 -- use original cursor.
2550
2551 if (l_parent_context is null) then
2552 open child_flows2;
2553 fetch child_flows2 into number_active;
2554 close child_flows2;
2555 else
2556 open child_flows_mwf;
2557 fetch child_flows_mwf into number_active;
2558 close child_flows_mwf;
2559 end if;
2560
2561 if (number_active < 1) then
2562 begin
2563 wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
2564 waiting_activity,wf_engine.eng_null);
2565 resultout := wf_engine.eng_null;
2566 exception
2567 when OTHERS then
2568 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2569 wf_core.clear;
2570 ContinueMasterFlow.resultout := wf_engine.eng_null;
2571 else
2572 raise;
2573 end if;
2574 end;
2575 else
2576 open child_activities2;
2577 fetch child_activities2 into number_complete;
2578 close child_activities2;
2579
2580 begin
2581 if number_active = number_complete then
2582 wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
2583 waiting_activity,wf_engine.eng_null);
2584 end if;
2585 resultout := wf_engine.eng_null;
2586
2587 exception
2588 when others then
2589 --
2590 -- If call to CompleteActivity cannot find activity, return
2591 -- null and wait for master flow
2592 --
2593 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2594 wf_core.clear;
2595 ContinueMasterFlow.resultout := wf_engine.eng_null;
2596 else
2597 raise;
2598 end if;
2599 end;
2600 end if; -- number_active was more than 0
2601 return; -- done with old code path
2602
2603 end if; --#WAITFORDETAIL exists in the parent
2604 end if; --#LBL_ is not null
2605
2606 -- If we come to here, we must be progressing in the new code path.
2607 --Now we will try to decrement the corresponding #CNT_ attribute if it
2608 --exists, and will create it with a value of 0 if it does not yet exist.
2609 l_count := WF_ENGINE.AddToItemAttrNumber(l_parent_itemtype,
2610 l_parent_itemkey,
2611 '#CNT_'||waiting_activity, -1);
2612
2613 if (l_count is NULL) then
2614 WF_ENGINE.AddItemAttr(itemtype=>l_parent_itemtype,
2615 itemkey=>l_parent_itemkey,
2616 aname=>'#CNT_'||waiting_activity,
2617 number_value=>l_childwaiting - 1);
2618 elsif (l_count < 1) then
2619 begin
2620 wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
2621 waiting_activity,wf_engine.eng_null);
2622 exception
2623 when OTHERS then
2624 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2625 wf_core.clear;
2626 ContinueMasterFlow.resultout := wf_engine.eng_null;
2627 else
2628 raise;
2629 end if;
2630 end;
2631 end if;
2632
2633 l_defer := WF_ENGINE.GetActivityAttrText(itemtype, itemkey, actid,
2634 '#HINT', TRUE);
2635
2636 --If #HINT is not set to 'NO_DEFER', or is null we will set the
2637 --threshold to cause the next activity to defer.
2638 if ((l_defer is null) or (l_defer <> 'NO_DEFER')) then
2639 resultout := wf_engine.eng_deferred;
2640 else
2641 resultout := wf_engine.eng_null;
2642 end if;
2643
2644 end if; --First execution
2645
2646 exception
2647 when others then
2648 wf_core.context('Wf_Standard', 'ContinueMasterFlow',
2649 itemtype, itemkey, to_char(actid), waiting_activity);
2650 raise;
2651 end ContinueMasterFlow;
2652
2653
2654
2655
2656 -- -------------------------------------------------------------------
2657 -- InitializeErrors
2658 -- checks if an item attribute for Workflow administrator exists in
2659 -- the item that just errored out. If it does, then it uses this
2660 -- role to send notifications to, overriding the default role
2661 -- in this item.
2662 -- NOTE: the item attibute in the workflow-in-error must have an
2663 -- internal name of WF_ADMINISTRATOR.
2664 --
2665 -- Called by default error process.
2666 -- -------------------------------------------------------------------
2667 PROCEDURE InitializeErrors( itemtype VARCHAR2,
2668 itemkey VARCHAR2,
2669 actid NUMBER,
2670 funcmode VARCHAR2,
2671 result OUT NOCOPY VARCHAR2 ) IS
2672
2673 l_error_itemtype VARCHAR2(8);
2674 l_error_itemkey VARCHAR2(240);
2675 l_error_name VARCHAR2(30);
2676 l_error_msg VARCHAR2(2000);
2677 l_timeout PLS_INTEGER;
2678 l_administrator VARCHAR2(100);
2679
2680 BEGIN
2681
2682 IF (funcmode = 'RUN') THEN
2683
2684 --
2685 -- Get the type and the key of the process that errored out
2686 -- these were set in the erroring out process by Execute_Error_Process
2687 --
2688 l_error_itemkey := WF_ENGINE.GetItemAttrText(
2689 itemtype => itemtype,
2690 itemkey => itemkey,
2691 aname => 'ERROR_ITEM_KEY' );
2692 l_error_itemtype := WF_ENGINE.GetItemAttrText(
2693 itemtype => itemtype,
2694 itemkey => itemkey,
2695 aname => 'ERROR_ITEM_TYPE' );
2696
2697 --
2698 -- Check if the workflow administrator exists
2699 -- If it does, then assign the notification to this role
2700 --
2701
2702 begin
2703 --if this item type doesnt exist an exception is raised.
2704 l_administrator := WF_ENGINE.GetItemAttrText(
2705 itemtype => l_error_itemtype,
2706 itemkey => l_error_itemkey,
2707 aname => 'WF_ADMINISTRATOR' );
2708
2709 --<rwunderl:2775132> Put first assignemt in their own block
2710 --in case DEFAULT_RESET_ERROR_NTF does not exist.
2711 begin
2712 wf_engine.AssignActivity(itemtype,itemkey,
2713 'DEFAULT_RESET_ERROR_NTF',
2714 l_administrator);
2715 exception
2716 when OTHERS then
2717 null; --We only null this exception because the parent
2718 --block nulls the expeption.
2719 end;
2720
2721 wf_engine.AssignActivity(itemtype,itemkey,'RETRY_ONLY_NTF',
2722 l_administrator);
2723
2724 exception
2725 when others then null;
2726 end;
2727
2728 --
2729 -- Check if a timeout value exists
2730 -- If it does, then set the error timeout
2731 --
2732
2733 begin
2734 --if this item type doesnt exist an exception is raised.
2735 l_timeout := WF_ENGINE.GetItemAttrNumber(
2736 itemtype => l_error_itemtype,
2737 itemkey => l_error_itemkey,
2738 aname => 'ERROR_TIMEOUT' );
2739 wf_engine.SetItemAttrNumber(itemtype,itemkey,'TIMEOUT_VALUE',l_timeout);
2740 exception
2741 when others then null;
2742 end;
2743
2744 result := wf_engine.eng_completed;
2745 ELSIF (funcmode = 'CANCEL') THEN
2746 result := wf_engine.eng_completed;
2747 END IF;
2748 EXCEPTION
2749 WHEN OTHERS THEN
2750 WF_CORE.Context('WF_STANDARD', 'InitializeErrors',
2751 itemtype, itemkey, actid, funcmode);
2752 RAISE;
2753 END InitializeErrors;
2754
2755 -- -------------------------------------------------------------------
2756 -- CheckErrorActive
2757 -- checks if an error is still active and returns TRUE/FALSE.
2758 -- Use this in an error process to exit out of a timeout loop
2759 -- Called by default error process.
2760 -- -------------------------------------------------------------------
2761 PROCEDURE CheckErrorActive( itemtype IN VARCHAR2,
2762 itemkey IN VARCHAR2,
2763 actid IN NUMBER,
2764 funcmode IN VARCHAR2,
2765 result OUT NOCOPY VARCHAR2 ) IS
2766
2767 l_error_itemtype VARCHAR2(8);
2768 l_error_itemkey VARCHAR2(240);
2769 l_error_actid NUMBER;
2770 status VARCHAR2(30);
2771
2772 cursor activity_status (litemtype varchar2, litemkey varchar2, lactid number ) is
2773 select WIAS.ACTIVITY_STATUS
2774 from WF_ITEM_ACTIVITY_STATUSES WIAS
2775 where WIAS.ITEM_TYPE = litemtype
2776 and WIAS.ITEM_KEY = litemkey
2777 and WIAS.PROCESS_ACTIVITY = lactid;
2778
2779
2780 BEGIN
2781
2782 IF (funcmode = 'RUN') THEN
2783
2784 --
2785 -- Get the type and the key of the process that errored out
2786 -- these were set in the erroring out process by Execute_Error_Process
2787 --
2788 l_error_itemkey := WF_ENGINE.GetItemAttrText(
2789 itemtype => itemtype,
2790 itemkey => itemkey,
2791 aname => 'ERROR_ITEM_KEY' );
2792 l_error_itemtype := WF_ENGINE.GetItemAttrText(
2793 itemtype => itemtype,
2794 itemkey => itemkey,
2795 aname => 'ERROR_ITEM_TYPE' );
2796
2797 l_error_actid := WF_ENGINE.GetItemAttrText(
2798 itemtype => itemtype,
2799 itemkey => itemkey,
2800 aname => 'ERROR_ACTIVITY_ID' );
2801
2802 open activity_status(l_error_itemtype, l_error_itemkey, l_error_actid);
2803 fetch activity_status into status;
2804 close activity_status;
2805
2806 if status = 'ERROR' then
2807 result:='T';
2808 else
2809 result:='F';
2810 end if;
2811
2812 END IF;
2813
2814 EXCEPTION
2815 WHEN OTHERS THEN
2816 WF_CORE.Context('WF_STANDARD', 'CheckErrorActive',
2817 itemtype, itemkey, actid, funcmode);
2818 RAISE;
2819 END CheckErrorActive;
2820 -- -------------------------------------------------------------------
2821 -- InitializeEventError
2822 -- Called by the Error Process, this sets up various
2823 -- item attributes.
2824 -- -------------------------------------------------------------------
2825 PROCEDURE InitializeEventError( itemtype VARCHAR2,
2826 itemkey VARCHAR2,
2827 actid NUMBER,
2828 funcmode VARCHAR2,
2829 resultout OUT NOCOPY VARCHAR2 ) IS
2830 l_event_t wf_event_t;
2831 l_error_name varchar2(240);
2832 l_error_type varchar2(240);
2833 l_error_message varchar2(2000);
2834 l_error_stack varchar2(2000);
2835 l_subscription RAW(16);
2836 l_url varchar2(4000);
2837 l_eventdataurl varchar2(4000);
2838 l_source varchar2(8);
2839
2840
2841 begin
2842
2843 IF (funcmode = 'RUN') THEN
2844 --
2845 -- Get the Event Item Attribute
2846 --
2847
2848 l_event_t := WF_ENGINE.GetItemAttrEvent(
2849 itemtype => itemtype,
2850 itemkey => itemkey,
2851 name => 'EVENT_MESSAGE' );
2852 --
2853 -- Get the Errored Subscription GUID
2854 --
2855 l_subscription := l_event_t.GetErrorSubscription();
2856
2857 --
2858 -- Get the Error Type from the Item Attribute - set by Engine
2859 --
2860 l_error_type := WF_ENGINE.GetItemAttrText(
2861 itemtype => itemtype,
2862 itemkey => itemkey,
2863 aname => 'ERROR_TYPE');
2864 --
2865 -- If the error type is null, this must be an UNEXPECTED event
2866 --
2867 IF l_error_type IS NULL THEN
2868 l_error_type := 'UNEXPECTED';
2869 wf_engine.SetItemAttrText(itemtype => itemtype,
2870 itemkey => itemkey,
2871 aname => 'ERROR_TYPE',
2872 avalue => l_error_type);
2873 END IF;
2874
2875 --
2876 -- Determine if this event is LOCAL or EXTERNAL
2877 --
2878 if l_subscription is not null then
2879 -- If a subscription found, look at its source
2880 select source_type into l_source
2881 from wf_event_subscriptions
2882 where guid = l_subscription;
2883
2884 if l_source = 'ERROR' then
2885 l_source := 'LOCAL';
2886 end if;
2887 else
2888 -- Since no subscription found, look at from agent details
2889 begin
2890 select 'LOCAL' into l_source
2891 from wf_systems ws
2892 where ws.guid = hextoraw(wf_core.translate('WF_SYSTEM_GUID'))
2893 and ws.name = nvl(l_event_t.GetFromAgent().GetSystem(),ws.name);
2894 exception
2895 when no_data_found then
2896 l_source := 'EXTERNAL';
2897 end;
2898 end if;
2899
2900 --
2901 -- Get the Error Message, or set it if UNEXPECTED
2902 --
2903 l_error_message := substr(l_event_t.GetErrorMessage(),1,2000);
2904 IF (l_error_message is null) THEN
2905 l_error_message := wf_core.translate('NO_MATCHING_SUBSCRIPTIONS');
2906 END IF;
2907
2908 -- Get the Error Stack
2909 l_error_stack := substr(l_event_t.GetErrorStack(),1,2000);
2910
2911 -- Get the Errored Subscription GUID
2912 l_subscription := l_event_t.GetErrorSubscription();
2913
2914 -- Generate the URL
2915 wf_event_html.GetFWKEvtSubscriptionUrl(l_subscription, l_url);
2916 l_eventdataurl := wf_oam_util.GetViewXMLURL(p_eventattribute => 'EVENT_MESSAGE',
2917 p_itemtype => itemtype,
2918 p_itemkey => itemkey);
2919
2920 -- Set the Item Attributes
2921
2922 wf_engine.SetItemAttrText(itemtype => itemtype,
2923 itemkey => itemkey,
2924 aname => 'ERROR_MESSAGE',
2925 avalue => l_error_message);
2926
2927 wf_engine.SetItemAttrText(itemtype => itemtype,
2928 itemkey => itemkey,
2929 aname => 'ERROR_STACK',
2930 avalue => l_error_stack);
2931
2932 -- Set the PL/SQL Document for the Event Details
2933 wf_engine.SetItemAttrText(itemtype => itemtype,
2934 itemkey => itemkey,
2935 aname => 'EVENT_DETAILS',
2936 avalue => 'PLSQL:WF_STANDARD.EVENTDETAILS/'||ItemType||':'||ItemKey);
2937
2938 wf_engine.SetItemAttrText(itemtype => itemtype,
2939 itemkey => itemkey,
2940 aname => 'ERROR_DETAILS',
2941 avalue => 'PLSQL:WF_STANDARD.ErrorDetails/'||ItemType||':'||ItemKey);
2942
2943 wf_engine.SetItemAttrText(itemtype => itemtype,
2944 itemkey => itemkey,
2945 aname => 'SUBSCRIPTION_DETAILS',
2946 avalue => 'PLSQL:WF_STANDARD.SubscriptionDetails/'||ItemType||':'||ItemKey);
2947
2948 -- Set the Value for the Error Subscription URL
2949 wf_engine.SetItemAttrText(itemtype => itemtype,
2950 itemkey => itemkey,
2951 aname => 'EVENT_SUBSCRIPTION',
2952 avalue => l_url);
2953 -- Set the Value for the Event Data URL
2954 wf_engine.SetItemAttrText(itemtype => itemtype,
2955 itemkey => itemkey,
2956 aname => 'EVENT_DATA_URL',
2957 avalue => l_eventdataurl);
2958
2959 IF l_error_type IN ('ERROR','UNEXPECTED') THEN
2960 IF l_source = 'LOCAL' THEN
2961 resultout := 'EVENT_ERROR';
2962 ELSE
2963 resultout := 'EVENT_EXTERNAL_ERROR';
2964 END IF;
2965 ELSE
2966 resultout := 'EVENT_WARNING';
2967 END IF;
2968
2969 ELSIF (funcmode = 'CANCEL') THEN
2970 resultout := wf_engine.eng_completed;
2971 END IF;
2972 EXCEPTION
2973 WHEN OTHERS THEN
2974 WF_CORE.Context('WF_STANDARD', 'InitializeEventError',
2975 itemtype, itemkey, actid, funcmode);
2976 RAISE;
2977 END InitializeEventError;
2978 -- --------------------------------------------------------------------
2979 -- EventDetails
2980 -- PL/SQL Document for Event Attributes
2981 -- --------------------------------------------------------------------
2982 procedure EventDetails ( document_id in varchar2,
2983 display_type in varchar2,
2984 document in out nocopy varchar2,
2985 document_type in out nocopy varchar2) IS
2986
2987 ItemType varchar2(30);
2988 ItemKey varchar2(30);
2989
2990 l_to_agent varchar2(60);
2991 l_to_system varchar2(60);
2992 l_from_agent varchar2(60);
2993 l_from_system varchar2(60);
2994 l_priority varchar2(10);
2995 l_send_date date;
2996 l_send_date_text varchar2(60);
2997 l_receive_date date;
2998 l_receive_date_text varchar2(60);
2999
3000 i pls_integer;
3001
3002 l_event_t wf_event_t;
3003 l_parmlist_t wf_parameter_list_t;
3004 l_cells wf_notification.tdType;
3005 j number;
3006 l_result varchar2(32000);
3007
3008 begin
3009
3010 -- parse document_id for the ':' dividing item type name from item key value
3011 -- document_id value will take the form <ITEMTYPE>:<ITEMKEY> starting with
3012 -- release 2.5
3013 ItemType := nvl(substr(document_id, 1, instr(document_id,':')-1),'WFERROR');
3014 ItemKey := substr(document_id
3015 , instr(document_id,':')+1);
3016
3017
3018
3019 l_event_t := wf_engine.GetItemAttrEvent(
3020 itemtype => itemtype,
3021 itemkey => itemkey,
3022 name => 'EVENT_MESSAGE' );
3023
3024 --
3025 -- Get the Agent Details, we don't want any errors if the Agent
3026 -- didn't get populated with anything
3027 --
3028 if l_event_t.To_Agent is not null then
3029 l_to_agent := l_event_t.GetToAgent().GetName();
3030 l_to_system := l_event_t.GetToAgent().GetSystem();
3031 end if;
3032
3033 if l_event_t.From_Agent is not null then
3034 l_from_agent := l_event_t.GetFromAgent().GetName();
3035 l_from_system := l_event_t.GetFromAgent().GetSystem();
3036 end if;
3037
3038 --
3039 -- Get any date values and format if required
3040 --
3041 l_send_date := l_event_t.GetSendDate();
3042
3043 IF l_send_date IS NOT NULL THEN
3044 l_send_date_text := WF_NOTIFICATION_UTIL.GetCalendarDate(-1, l_send_date, null, true);
3045 END IF;
3046
3047 l_receive_date := l_event_t.GetReceiveDate();
3048
3049 IF l_receive_date IS NOT NULL THEN
3050 l_receive_date_text := WF_NOTIFICATION_UTIL.GetCalendarDate(-1, l_receive_date, null, true);
3051 END IF;
3052
3053 --
3054 -- Get the Priority
3055 --
3056 l_priority := l_event_t.GetPriority();
3057
3058 --
3059 -- Build up the PL/SQL Document depending on the User Mail Preference
3060 --
3061 -- bug 6955474
3062 -- Using WF_NOTIFICATION.NTF_Table API to maintain consistency with BLAF
3063 --
3064 -- Build the Table
3065 if (display_type = wf_notification.doc_html) then
3066 i := 1;
3067 l_cells(i) := wf_core.translate('WF_EVENT_HEADING');
3068 l_cells(i) := 'S30%:'||l_cells(i);
3069
3070 i := i + 1;
3071 l_cells(i) := wf_core.translate('WF_VALUE');
3072 l_cells(i) := 'S70%:'||l_cells(i);
3073
3074 i := i + 1;
3075 l_cells(i) := 'S:'||wf_core.translate('WF_EVENT_NAME');
3076 i := i + 1;
3077 l_cells(i) := 'S:'||nvl(l_event_t.GetEventName(),'&'||'nbsp');
3078
3079 i := i + 1;
3080 l_cells(i) := 'S:'||wf_core.translate('WF_EVENT_KEY');
3081 i := i + 1;
3082 l_cells(i) := 'S:'||nvl(l_event_t.GetEventKey(),'&'||'nbsp');
3083
3084 i := i + 1;
3085 l_cells(i) := 'S:'||wf_core.translate('WF_TO_AGENT_NAME');
3086 i := i + 1;
3087 l_cells(i) := 'S:'||l_to_agent;
3088 i := i + 1;
3089 l_cells(i) := 'S:'||wf_core.translate('WF_TO_AGENT_SYSTEM');
3090 i := i + 1;
3091 l_cells(i) := 'S:'||l_to_system;
3092
3093 i := i + 1;
3094 l_cells(i) := 'S:'||wf_core.translate('WF_FROM_AGENT_NAME');
3095 i := i + 1;
3096 l_cells(i) := 'S:'||l_from_agent;
3097 i := i + 1;
3098 l_cells(i) := 'S:'||wf_core.translate('WF_FROM_AGENT_SYSTEM');
3099 i := i + 1;
3100 l_cells(i) := 'S:'||l_from_system;
3101
3102 i := i + 1;
3103 l_cells(i) := 'S:'||wf_core.translate('WF_SEND_DATE');
3104 i := i + 1;
3105 l_cells(i) := 'S:<BDO DIR="LTR">'||l_send_date_text||'</BDO>';
3106
3107 i := i + 1;
3108 l_cells(i) := 'S:'||wf_core.translate('WF_RECEIVE_DATE');
3109 i := i + 1;
3110 l_cells(i) := 'S:<BDO DIR="LTR">'||l_receive_date_text||'</BDO>';
3111
3112 i := i + 1;
3113 l_cells(i) := 'S:'||wf_core.translate('WF_PRIORITY');
3114 i := i + 1;
3115 l_cells(i) := 'S:'||l_priority;
3116
3117 i := i + 1;
3118 l_cells(i) := 'S:'||wf_core.translate('WF_CORRELATION');
3119 i := i + 1;
3120 l_cells(i) := 'S:'||nvl(l_event_t.GetCorrelationId(),'&'||'nbsp');
3121
3122 else
3123 l_result := Wf_Core.Newline||rpad(wf_core.translate('WF_EVENT_HEADING'),40)
3124 ||wf_core.translate('WF_VALUE')||Wf_Core.Newline;
3125
3126 l_result := l_result||rpad(wf_core.translate('WF_EVENT_NAME'),40)||
3127 l_event_t.GetEventName()||Wf_Core.Newline||
3128 rpad(wf_core.translate('WF_EVENT_KEY'),40)||
3129 l_event_t.GetEventKey()||Wf_Core.Newline||
3130 rpad(wf_core.translate('WF_FROM_AGENT_NAME'),40)||
3131 l_From_Agent||Wf_Core.Newline||
3132 rpad(wf_core.translate('WF_FROM_AGENT_SYSTEM'),40)||
3133 l_From_System||Wf_Core.Newline||
3134 rpad(wf_core.translate('WF_TO_AGENT_NAME'),40)||
3135 l_To_Agent||Wf_Core.Newline||
3136 rpad(wf_core.translate('WF_TO_AGENT_SYSTEM'),40)||
3137 l_To_System||Wf_Core.Newline||
3138 rpad(wf_core.translate('WF_PRIORITY'),40)||
3139 l_Priority||Wf_Core.Newline||
3140 rpad(wf_core.translate('WF_SEND_DATE'),40)||
3141 l_send_date_text||Wf_Core.Newline||
3142 rpad(wf_core.translate('WF_RECEIVE_DATE'),40)||
3143 l_receive_date_text||Wf_Core.Newline||
3144 rpad(wf_core.translate('WF_CORRELATION'),40)||
3145 l_event_t.GetCorrelationId()||Wf_Core.Newline;
3146
3147 end if;
3148
3149 -- Display the Parameter List
3150 l_parmlist_t := l_event_t.getParameterList();
3151 if (l_parmlist_t is not null) then
3152 j := l_parmlist_t.FIRST;
3153 while (j <= l_parmlist_t.LAST) loop
3154 if (display_type = wf_notification.doc_html) then
3155 i := i + 1;
3156 l_cells(i) := 'S:'||wf_core.translate('WF_PARAMETER')||' : '||l_parmlist_t(j).getName();
3157
3158 i := i + 1;
3159 l_cells(i) :=
3160 'S:'||substr(nvl(l_parmlist_t(j).getValue(),'&'||'nbsp'),1,20);
3161 else
3162 l_result := l_result||rpad(wf_core.translate('WF_PARAMETER')
3163 ||l_parmlist_t(j).getName(),40)
3164 ||substr(l_parmlist_t(j).getValue(),1,20)||Wf_Core.Newline;
3165 end if;
3166 j := l_parmlist_t.NEXT(j);
3167 end loop;
3168 end if;
3169
3170 if (display_type = wf_notification.doc_html) then
3171 document_type := wf_notification.doc_html;
3172 wf_notification.NTF_Table(cells => l_cells,
3173 col => 2,
3174 type => 'H',
3175 rs => l_result);
3176 -- Display title
3177 l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1">' ||
3178 '<tr><td class="x3w">'||wf_core.Translate('WFITD_EVENT_DETAILS')||
3179 '</td></tr>'||'<tr><td>'||l_result||'</td></tr></table>';
3180
3181 else
3182 document_type := wf_notification.doc_text;
3183 end if;
3184 document := l_result;
3185
3186 exception
3187 when others then
3188 wf_core.context('WF_STANDARD','EventDetails',document_id, display_type);
3189 raise;
3190 end EventDetails;
3191 -- --------------------------------------------------------------------
3192 -- Retry Raise
3193 -- Executes command depending on notification response
3194 -- --------------------------------------------------------------------
3195 PROCEDURE RetryRaise ( itemtype in varchar2,
3196 itemkey in varchar2,
3197 actid in number,
3198 funcmode in varchar2,
3199 resultout out nocopy varchar2 ) IS
3200
3201 aname varchar2(100);
3202 l_event_t wf_event_t;
3203 l_toagent wf_agent_t;
3204 l_skip_sub varchar2(300) := null;
3205 l_parameterList wf_parameter_list_t := null;
3206
3207 begin
3208
3209 IF (funcmode = 'RUN') THEN
3210
3211 l_event_t := wf_engine.GetItemAttrEvent(
3212 itemtype => itemtype,
3213 itemkey => itemkey,
3214 name => 'EVENT_MESSAGE' );
3215
3216 aname := wf_engine.GetActivityAttrText(itemtype,
3217 itemkey,
3218 actid,
3219 'COMMAND');
3220
3221 -- Bug 4198975
3222 -- If the SKIP_ERROR_SUB is not null, then this parameber will
3223 -- be passed over to raise in all the cases.
3224 l_skip_sub := l_event_t.GETVALUEFORPARAMETER('SKIP_ERROR_SUB');
3225 if (l_skip_sub is not null) then
3226 l_parameterList := wf_parameter_list_t();
3227 wf_event.addParameterToList('SKIP_ERROR_SUB', l_skip_sub, l_parameterList);
3228 end if;
3229
3230 IF aname = 'RAISE_KEY' THEN
3231 wf_event.raise(p_event_name => l_event_t.GetEventName(),
3232 p_event_key => l_event_t.GetEventKey(),
3233 p_parameters => l_parameterList);
3234
3235 ELSIF aname = 'RAISE_KEY_DATA' THEN
3236 wf_event.raise(p_event_name => l_event_t.GetEventName(),
3237 p_event_key => l_event_t.GetEventKey(),
3238 p_event_data => l_event_t.GetEventData(),
3239 p_parameters => l_parameterList);
3240
3241 ELSIF aname = 'RAISE_KEY_DATA_PARAM' THEN
3242 wf_event.raise(l_event_t.GetEventName(),
3243 l_event_t.GetEventKey(),
3244 l_event_t.GetEventData(),
3245 l_event_t.GetParameterList());
3246 ELSIF aname = 'ENQUEUE' THEN
3247 l_toagent := l_event_t.GetToAgent();
3248 l_event_t.SetPriority(-1); -- want this dequeued ASAP
3249 wf_event.enqueue(l_event_t, l_toagent);
3250 ELSE
3251 wf_core.raise('WFSQL_ARGS');
3252
3253 END IF;
3254
3255 resultout := wf_engine.eng_completed;
3256
3257 ELSIF (funcmode = 'CANCEL') THEN
3258 resultout := wf_engine.eng_completed;
3259 END IF;
3260
3261 EXCEPTION
3262 WHEN OTHERS THEN
3263 WF_CORE.Context('WF_STANDARD', 'RetryRaise',
3264 itemtype, itemkey, actid, funcmode);
3265 RAISE;
3266 end RetryRaise;
3267 -- --------------------------------------------------------------------
3268 -- GetAgents
3269 -- Gets the Event Subscription Out and To Agent
3270 -- --------------------------------------------------------------------
3271 procedure GetAgents ( itemtype in varchar2,
3272 itemkey in varchar2,
3273 actid in number,
3274 funcmode in varchar2,
3275 resultout out nocopy varchar2)
3276 is
3277
3278 --l_subguid raw(16);
3279 l_subguid varchar2(100);
3280 l_outagentattr varchar2(100);
3281 l_toagentattr varchar2(100);
3282 l_outagentguid raw(16);
3283 l_toagentguid raw(16);
3284 l_outagent varchar2(100);
3285 l_toagent varchar2(100);
3286
3287 cursor c_agents is
3288 select out_agent_guid, to_agent_guid
3289 from wf_event_subscriptions
3290 where guid = l_subguid;
3291
3292 begin
3293
3294 IF (funcmode = 'RUN') THEN
3295
3296 l_subguid := wf_engine.GetActivityAttrText(itemtype,
3297 itemkey,
3298 actid,
3299 'SUB_GUID');
3300
3301 l_outagentattr := wf_engine.GetActivityAttrText(itemtype,
3302 itemkey,
3303 actid,
3304 'FROMAGENT');
3305
3306 l_toagentattr := wf_engine.GetActivityAttrText(itemtype,
3307 itemkey,
3308 actid,
3309 'TOAGENT');
3310
3311 -- Get the Agent Guids
3312 open c_agents;
3313 fetch c_agents into l_outagentguid, l_toagentguid;
3314 close c_agents;
3315
3316 if l_toagentguid is not null then
3317 -- Get the Out Agent in the agent@system format
3318 if l_outagentguid is not null then
3319 select wfa.name||'@'||wfs.name
3320 into l_outagent
3321 from wf_agents wfa, wf_systems wfs
3322 where wfa.guid = l_outagentguid
3323 and wfa.system_guid = wfs.guid;
3324 end if;
3325
3326 -- Get the To Agent in the agent@system format
3327 select wfa.name||'@'||wfs.name
3328 into l_toagent
3329 from wf_agents wfa, wf_systems wfs
3330 where wfa.guid = l_toagentguid
3331 and wfa.system_guid = wfs.guid;
3332
3333 -- Update the agent item attributes
3334 wf_engine.SetItemAttrText(itemtype => itemtype,
3335 itemkey => itemkey,
3336 aname => l_outagentattr,
3337 avalue => l_outagent);
3338
3339 wf_engine.SetItemAttrText(itemtype => itemtype,
3340 itemkey => itemkey,
3341 aname => l_toagentattr,
3342 avalue => l_toagent);
3343 resultout := 'T';
3344 else
3345 resultout := 'F';
3346 end if;
3347 ELSIF (funcmode = 'CANCEL') THEN
3348 resultout := wf_engine.eng_completed;
3349 END IF;
3350
3351 EXCEPTION
3352 WHEN OTHERS THEN
3353 WF_CORE.Context('WF_STANDARD', 'GetAgents',
3354 itemtype, itemkey, actid, funcmode);
3355 RAISE;
3356 end GetAgents;
3357 -- --------------------------------------------------------------------
3358 -- GetAckAgent
3359 -- Gets the Acknowledge To Agent based on the Event Message
3360 -- --------------------------------------------------------------------
3361 procedure GetAckAgent ( itemtype in varchar2,
3362 itemkey in varchar2,
3363 actid in number,
3364 funcmode in varchar2,
3365 resultout out nocopy varchar2)
3366 is
3367
3368 l_event_t wf_event_t;
3369 l_toagentattr varchar2(100);
3370 l_system varchar2(30);
3371 l_agent varchar2(30);
3372
3373 cursor c_return_agent is
3374 select wfa.name agent
3375 from wf_systems wfs,
3376 wf_agents wfa
3377 where wfs.name = l_system
3378 and wfa.status = 'ENABLED'
3379 and wfa.direction = 'IN'
3380 and wfa.name not in ('WF_ERROR','WF_DEFERRED');
3381
3382 begin
3383
3384 IF (funcmode = 'RUN') THEN
3385
3386 l_event_t := wf_engine.GetActivityAttrEvent(
3387 itemtype => itemtype,
3388 itemkey => itemkey,
3389 actid => actid,
3390 name => 'EVENTMESSAGE');
3391
3392 l_toagentattr := wf_engine.GetActivityAttrText(itemtype,
3393 itemkey,
3394 actid,
3395 'ACKTOAGENT');
3396
3397 l_system := l_event_t.GetFromAgent().GetSystem();
3398
3399 open c_return_agent;
3400 fetch c_return_agent into l_agent;
3401 close c_return_agent;
3402
3403 if l_agent is not null then
3404 wf_engine.SetItemAttrText(itemtype => itemtype,
3405 itemkey => itemkey,
3406 aname => l_toagentattr,
3407 avalue => l_agent||'@'||l_system);
3408 end if;
3409
3410 resultout := wf_engine.eng_completed;
3411
3412 ELSIF (funcmode = 'CANCEL') THEN
3413 resultout := wf_engine.eng_completed;
3414 END IF;
3415
3416 EXCEPTION
3417 WHEN OTHERS THEN
3418 WF_CORE.Context('WF_STANDARD', 'GetAckAgent',
3419 itemtype, itemkey, actid, funcmode);
3420 RAISE;
3421 end GetAckAgent;
3422
3423 -- SubscriptionDetails
3424 -- PL/SQL Document to display subscription parameter details
3425 -- IN
3426 -- document_id
3427 -- display_type
3428 -- document
3429 -- document_type
3430 procedure SubscriptionDetails (document_id in varchar2,
3431 display_type in varchar2,
3432 document in out nocopy varchar2,
3433 document_type in out nocopy varchar2)
3434 is
3435 l_item_type varchar2(10);
3436 l_item_key varchar2(240);
3437 l_subscription raw(16);
3438 l_params varchar2(4000);
3439 l_rule_func varchar2(240);
3440 l_cells wf_notification.tdType;
3441 l_cells2 wf_notification.tdType;
3442 i pls_integer;
3443 j pls_integer;
3444 l_document varchar2(32000);
3445 l_sub_param_list wf_parameter_list_t;
3446 l_event_t wf_event_t;
3447 l_result varchar2(22000);
3448 l_result2 varchar2(10000);
3449 l_url varchar2(500);
3450 l_sub_url varchar2(1000);
3451 l_evt_url varchar2(1000);
3452 begin
3453 l_item_type := nvl(substr(document_id, 1,
3454 instr(document_id,':')-1),'WFERROR');
3455 l_item_key := substr(document_id, instr(document_id,':')+1);
3456
3457 l_event_t := wf_engine.GetItemAttrEvent(itemtype => l_item_type,
3458 itemkey => l_item_key,
3459 name => 'EVENT_MESSAGE');
3460 l_subscription := l_event_t.GetErrorSubscription();
3461
3462 if (l_subscription is not null) then
3463
3464 SELECT parameters, java_rule_func
3465 INTO l_params, l_rule_func
3466 FROM wf_event_subscriptions
3467 WHERE guid = l_subscription;
3468
3469 l_sub_param_list := wf_event.GetParamListFromString(l_params);
3470
3471 if (display_type = wf_notification.doc_html) then
3472 i := 1;
3473 l_cells(i) := 'S30%:'||wf_core.Translate('WF_PARAMETER');
3474
3475 i := i + 1;
3476 l_cells(i) := 'S70%:'||wf_core.Translate('WF_VALUE');
3477 else
3478 l_result := Wf_Core.Newline||rpad(wf_core.Translate('WF_PARAMETER'), 40)
3479 ||wf_core.translate('WF_VALUE')||Wf_Core.Newline;
3480 end if;
3481
3482 -- Show all Subscription Parameters that are currently used as
3483 -- meta-data store for WS definition
3484 if (l_sub_param_list is not null) then
3485 j := l_sub_param_list.FIRST;
3486 while (j is not null) loop
3487 if (display_type = wf_notification.doc_html) then
3488 i := i + 1;
3489 l_cells(i) := 'S:'||l_sub_param_list(j).getName();
3490
3491 i := i + 1;
3492 l_cells(i) := 'S:'||l_sub_param_list(j).getValue();
3493 else
3494 l_result := l_result||rpad(l_sub_param_list(j).getName(),40)||
3495 rpad(l_sub_param_list(j).getValue(),40)||wf_core.newline;
3496 end if;
3497 j := l_sub_param_list.NEXT(j);
3498 end loop;
3499 end if;
3500
3501 -- Show Invoker Rule Function since it may be a Custom one extended from
3502 -- seeded. Also the Event Payload is WS input message
3503 l_evt_url := wf_engine.GetItemAttrText(itemtype => l_item_type,
3504 itemkey => l_item_key,
3505 aname => 'EVENT_DATA_URL');
3506 l_sub_url := wf_engine.GetItemAttrText(itemtype => l_item_type,
3507 itemkey => l_item_key,
3508 aname => 'EVENT_SUBSCRIPTION');
3509
3510 if (display_type = wf_notification.doc_html) then
3511 i := i + 1;
3512 l_cells(i) := 'S:'||wf_core.Translate('WF_INOKER_RULE_FUNC');
3513 i := i + 1;
3514 l_cells(i) := 'S:'||l_rule_func;
3515
3516 i := i + 1;
3517 l_cells(i) := 'S:'||wf_core.Translate('WF_WS_INPUT_MESG');
3518 i := i + 1;
3519 l_url := '<a href="'||l_evt_url||'" class="xd">'||wf_core.Translate('WF_CLICK_HERE')||'</a>';
3520 l_cells(i) := 'S:'||l_url;
3521
3522 i := i + 1;
3523 l_cells(i) := 'S:'||wf_core.Translate('WF_SUBSCRIPTION_PAGE');
3524 i := i + 1;
3525 l_url := '<a href="'||l_sub_url||'" class="xd">'||wf_core.Translate('WF_CLICK_HERE')||'</a>';
3526 l_cells(i) := 'S:'||l_url;
3527
3528 wf_notification.Ntf_Table(l_cells, 2, 'H', l_result);
3529
3530 -- Display title "Web Service Details"
3531 l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1">' ||
3532 '<tr><td class="x3w">'||wf_core.Translate('WF_WEBSERVICE_DETAILS')||'</td></tr>'||
3533 '<tr><td>'||l_result||'</td></tr></table>';
3534
3535 else
3536 l_result := l_result||rpad(wf_core.Translate('WF_INOKER_RULE_FUNC'),40)||
3537 rpad(l_rule_func,40)||wf_core.newline||
3538 rpad(wf_core.Translate('WF_WS_INPUT_MESG'),40)||
3539 rpad(l_evt_url,40)||wf_core.newline||
3540 rpad(wf_core.Translate('WF_SUBSCRIPTION_PAGE'),40)||
3541 rpad(l_sub_url,40)||wf_core.newline;
3542
3543 end if;
3544 end if;
3545 document := l_result;
3546 exception
3547 when others then
3548 wf_core.context('WF_STANDARD', 'SubscriptionDetails', document_id);
3549 raise;
3550 end SubscriptionDetails;
3551
3552 -- ErrorDetails
3553 -- PL/SQL Document to display event error details
3554 -- IN
3555 -- document_id
3556 -- display_type
3557 -- document
3558 -- document_type
3559 procedure ErrorDetails (document_id in varchar2,
3560 display_type in varchar2,
3561 document in out nocopy varchar2,
3562 document_type in out nocopy varchar2)
3563 is
3564 l_result varchar2(32000);
3565 l_error_name varchar2(240);
3566 l_item_type varchar2(30);
3567 l_item_key varchar2(240);
3568 l_error_message varchar2(2000);
3569 l_error_stack varchar2(2000);
3570 l_cells wf_notification.tdType;
3571 i pls_integer;
3572 begin
3573
3574 l_item_type := nvl(substr(document_id, 1, instr(document_id,':')-1),'WFERROR');
3575 l_item_key := substr(document_id, instr(document_id,':')+1);
3576
3577 l_error_name := wf_engine.GetItemAttrText(itemtype => l_item_type,
3578 itemkey => l_item_key,
3579 aname => 'ERROR_NAME');
3580 l_error_message := wf_engine.GetItemAttrText(itemtype => l_item_type,
3581 itemkey => l_item_key,
3582 aname => 'ERROR_MESSAGE');
3583 l_error_stack := wf_engine.GetItemAttrText(itemtype => l_item_type,
3584 itemkey => l_item_key,
3585 aname => 'ERROR_STACK');
3586
3587 if (display_type = wf_notification.doc_html) then
3588 document_type := wf_notification.doc_html;
3589
3590 i := 1;
3591 if (l_error_name is not null) then
3592 l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_NAME');
3593 i := i + 1;
3594 l_cells(i) := 'S:'||l_error_name;
3595 i := i + 1;
3596 end if;
3597
3598 l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_MESSAGE');
3599 i := i + 1;
3600 l_cells(i) := 'S:'||l_error_message;
3601
3602 i := i + 1;
3603 l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_STACK');
3604 i := i + 1;
3605 l_cells(i) := 'S:'||l_error_stack;
3606
3607 wf_notification.NTF_Table(cells => l_cells,
3608 col => 2,
3609 type => 'V',
3610 rs => l_result);
3611
3612 -- Display title
3613 l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1">' ||
3614 '<tr><td class="x3w">'||wf_core.Translate('WF_ERROR_DETAILS') ||
3615 '</td></tr>'||'<tr><td>'||l_result||'</td></tr></table>';
3616 else
3617 document_type := wf_notification.doc_text;
3618 l_result := rpad(wf_core.Translate('WFMON_ERROR_NAME'),40)||' : '||l_error_name||wf_core.newline||
3619 rpad(wf_core.Translate('WFMON_ERROR_MESSAGE'),40)||' : '||l_error_message||wf_core.newline||
3620 rpad(wf_core.Translate('WFMON_ERROR_STACK'),40)||' : '||l_error_stack||wf_core.newline;
3621 end if;
3622 document := l_result;
3623 exception
3624 when others then
3625 wf_core.context('WF_STANDARD', 'ErrorDetails', document_id);
3626 raise;
3627 end ErrorDetails;
3628
3629 -- SubscriptionAction
3630 -- Returns Subscription's Action Code based on which a specific notification
3631 -- could be sent
3632 procedure SubscriptionAction(itemtype in varchar2,
3633 itemkey in varchar2,
3634 actid in number,
3635 funcmode in varchar2,
3636 resultout in out nocopy varchar2)
3637 is
3638 l_event_t wf_event_t;
3639 l_subscription raw(16);
3640 l_action_code varchar2(30);
3641 begin
3642
3643 if (funcmode = 'RUN') then
3644 l_event_t := wf_engine.GetItemAttrEvent(itemtype => itemtype,
3645 itemkey => itemkey,
3646 name => 'EVENT_MESSAGE');
3647 l_subscription := l_event_t.GetErrorSubscription();
3648
3649 SELECT action_code
3650 INTO l_action_code
3651 FROM wf_event_subscriptions
3652 WHERE guid = l_subscription;
3653
3654 if (l_action_code is not null) then
3655 resultout := wf_engine.eng_completed||':'||l_action_code;
3656 else
3657 resultout := wf_engine.eng_completed||':CUSTOM_RG';
3658 end if;
3659 elsif (funcmode = 'CANCEL') then
3660 resultout := wf_engine.eng_completed;
3661 end if;
3662
3663 end SubscriptionAction;
3664
3665 END WF_STANDARD;