1 package body WF_STANDARD as
2 /* $Header: wfstdb.pls 120.17.12020000.2 2012/11/13 19:39:29 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 --Bug 14784055. Need to validate the activity LABEL is not too large
2297 ValTooLarge EXCEPTION;
2298 pragma exception_init(ValTooLarge, -01401);
2299 ValTooLargeNew EXCEPTION;
2300 pragma exception_init(ValTooLargeNew, -12899);
2301 l_module varchar2(20) := 'WaitForDetailFlow';
2302
2303 begin
2304 -- Parse activity arg into <process_name> and <instance_label> components.
2305 colon := instr(continuation_activity, ':');
2306 if (colon <> 0) then
2307 -- Activity arg is <process name>:<instance label>
2308 process := substr(continuation_activity, 1, colon-1);
2309 label := substr(continuation_activity, colon+1);
2310 else
2311 -- Activity arg is just instance label
2312 process := '';
2313 label := continuation_activity;
2314 end if;
2315
2316 --Retrieve the label for the WaitForFlow activity.
2317 open current_process(actid);
2318 fetch current_process into l_waitLabel;
2319 close current_process;
2320
2321 l_labelCount := WF_ENGINE.GetItemAttrNumber(itemType, itemKey,
2322 '#CNT_'||l_waitLabel, TRUE);
2323 if (l_labelCount is NULL) then
2324 l_childCount := WF_ENGINE.GetItemAttrNumber(itemType, itemKey,
2325 '#WAITFORDETAIL', TRUE);
2326 if (l_childCount is NULL) then --Fall back to the old path.
2327 open child_flows;
2328 fetch child_flows into number_active;
2329 close child_flows;
2330
2331 if (number_active < 1) then
2332 resultout := wf_engine.eng_null;
2333 else
2334 open child_activities(itemtype, itemkey, process, label);
2335 fetch child_activities into number_complete;
2336 close child_activities;
2337
2338 if number_active > number_complete then
2339 resultout := wf_engine.eng_notified||':'||
2340 wf_engine.eng_null||':'||wf_engine.eng_null;
2341 else
2342 resultout := wf_engine.eng_null;
2343 end if;
2344
2345 end if; --There are no children
2346 else --#WAITFORDETAIL exists
2347 begin
2348 WF_ENGINE.AddItemAttr(itemtype=>WaitForDetailFlow.itemtype,
2349 itemkey=>WaitForDetailFlow.itemkey,
2350 aname=>'#CNT_'||l_waitLabel,
2351 number_value=>l_childCount);
2352 exception
2353 when ValTooLarge OR ValTooLargeNew then
2354 Wf_Core.Context('WF_ENGINE', l_module, WaitForDetailFlow.itemtype,
2355 WaitForDetailFlow.itemkey);
2356 WF_CORE.Token('LABEL', '#CNT_'||l_waitLabel);
2357 WF_CORE.Token('LENGTH', 30);
2358 WF_CORE.Raise('WFENG_LABEL_TOO_LARGE');
2359 end;
2360 if (l_childCount > 0) then
2361 resultout := wf_engine.eng_notified||':'||
2362 wf_engine.eng_null||':'||wf_engine.eng_null;
2363 else
2364 resultout := wf_engine.eng_null;
2365 end if; --l_childCount > 0
2366 end if; -- #WAITFORDETAIL
2367 elsif (l_labelCount > 0) then
2368 --The #CNT_ attribute exists and is 1 or greater so this will remain
2369 --notified.
2370 resultout := wf_engine.eng_notified||':'||wf_engine.eng_null||
2371 ':'||wf_engine.eng_null;
2372
2373 else --The labelcount exists and is < 1 so we can continue.
2374 resultout := wf_engine.eng_null;
2375 end if;
2376
2377
2378 exception
2379 when others then
2380 wf_core.context('Wf_Standard', 'WaitForDetailFlow',
2381 itemtype,itemkey,to_char(actid),continuation_activity);
2382 raise;
2383 end WaitForDetailFlow;
2384
2385
2386 -- ContinueDetailFlow
2387 -- Signal Detail Flows to continue
2388 -- IN
2389 -- itemtype - A valid item type from (WF_ITEM_TYPES table).
2390 -- itemkey - A string generated from the application object's primary key.
2391 -- actid - The process activity(instance id).
2392 -- waiting_activity - The Name of the activity that in waiting
2393 -- OUT
2394 -- resultout - 'NULL'
2395 procedure ContinueDetailFlow( itemtype in varchar2,
2396 itemkey in varchar2,
2397 actid in number,
2398 waiting_activity in varchar2,
2399 resultout out nocopy varchar2
2400 ) is
2401 --
2402 cursor child_flows is
2403 --
2404 -- select all active children of parent flow
2405 --
2406 select item_type, item_key
2407 from wf_items
2408 where parent_item_type = itemtype
2409 and parent_item_key = itemkey
2410 and end_date is null;
2411 --
2412 begin
2413 for child_flows_rec in child_flows loop
2414 --
2415 -- Complete Waiting Activity in All Detail Flows
2416 --
2417 begin
2418 wf_engine.CompleteActivity(child_flows_rec.item_type,
2419 child_flows_rec.item_key, waiting_activity,wf_engine.eng_null);
2420 exception
2421 when others then
2422 -- If call to CompleteActivity cannot find activity, return null
2423 -- As either the detail flows does not have a waiting activity OR
2424 -- the detail flow has not reach the waiting activity
2425 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2426 wf_core.clear;
2427 else
2428 raise;
2429 end if;
2430 end;
2431 end loop;
2432
2433 ContinueDetailFlow.resultout := wf_engine.eng_null;
2434
2435 exception
2436 when others then
2437 wf_core.context('Wf_Standard','ContinueDetailFlow',
2438 itemtype, itemkey, to_char(actid),waiting_activity);
2439 raise;
2440 end ContinueDetailFlow;
2441
2442
2443 -- ContinueMasterFlow
2444 -- Signal Master Flow to continue if all Detail flows have
2445 -- executed Continuation Activity
2446 -- OUT
2447 -- result - 'NULL'
2448 procedure ContinueMasterFlow( itemtype in varchar2,
2449 itemkey in varchar2,
2450 actid in number,
2451 waiting_activity in varchar2,
2452 resultout in out nocopy varchar2) is
2453
2454
2455 l_activity_status varchar2(8);
2456 l_parent_itemtype varchar2(8);
2457 l_parent_itemkey varchar2(240);
2458 label varchar2(30);
2459 number_active pls_integer;
2460 number_complete pls_integer;
2461
2462 -- CTILLEY bug 1941013
2463 l_parent_context varchar2(2000);
2464
2465 cursor child_flows_mwf is
2466 -- This cursor is used if there are multiple WaitForFlow Activities in the
2467 -- parent flow (the parent_context must be set). CTILLEY bug 1941013
2468 -- select all active children of parent flow excluding current work item
2469 select count(1)
2470 from wf_items
2471 where parent_item_type = l_parent_itemtype
2472 and parent_item_key = l_parent_itemkey
2473 and parent_context = l_parent_context
2474 and (item_type <> ContinueMasterFlow.itemtype
2475 or item_key <> ContinueMasterFlow.itemkey)
2476 and end_date is null;
2477
2478 cursor child_flows2 is
2479 -- select all active children of parent flow excluding current work item
2480 select count(1)
2481 from wf_items
2482 where parent_item_type = l_parent_itemtype
2483 and parent_item_key = l_parent_itemkey
2484 and (item_type <> ContinueMasterFlow.itemtype
2485 or item_key <> ContinueMasterFlow.itemkey)
2486 and end_date is null;
2487
2488 cursor child_activities2 is
2489 select count(1)
2490 from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA,
2491 WF_ITEMS WI
2492 where WIAS.ITEM_TYPE = itemtype
2493 and WIAS.ITEM_KEY = WI.item_key
2494 and WI.parent_item_type = l_parent_itemtype
2495 and WI.parent_item_key = l_parent_itemkey
2496 and (WI.item_type <> itemtype OR WI.item_key <> itemkey )
2497 and WI.end_date is null
2498 and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
2499 and WPA.INSTANCE_LABEL = label
2500 and wias.activity_status in (wf_engine.eng_completed,
2501 wf_engine.eng_active);
2502
2503 dummy varchar2(240);
2504 status varchar2(8);
2505 result varchar2(30);
2506 l_count number;
2507 l_defer varchar2(4000);
2508 l_childwaiting number;
2509 --Bug 14784055. Need to validate the activity LABEL is not too large
2510 ValTooLarge EXCEPTION;
2511 pragma exception_init(ValTooLarge, -01401);
2512 ValTooLargeNew EXCEPTION;
2513 pragma exception_init(ValTooLargeNew, -12899);
2514 l_module varchar2(20) := 'ContinueMasterFlow';
2515 l_activity_label varchar2(50);
2516
2517 begin
2518 --
2519 -- select parent details
2520 --
2521 select parent_item_type, parent_item_key, parent_context
2522 into l_parent_itemtype, l_parent_itemkey, l_parent_context
2523 from wf_items
2524 where item_type = ContinueMasterFlow.itemtype
2525 and item_key = ContinueMasterFlow.itemkey;
2526
2527 select instance_label
2528 into label
2529 from wf_process_activities
2530 where instance_id = actid;
2531
2532 -- Check if this is the first or second execution of this activity.
2533 -- First -> result_code will be null (really null).
2534 -- Second -> result_code will be '#NULL' (set that way by execution 1).
2535 Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
2536
2537 if (result = wf_engine.eng_null) then
2538 -- Second execution.
2539 -- ContinueFlow() completed and was deferred.
2540 resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
2541 return;
2542 else
2543 --First execution.
2544
2545 -- lock the parent item, so only one child can execute this at the time.
2546 select item_key
2547 into dummy
2548 from wf_items
2549 where item_type = l_parent_itemtype
2550 and item_key = l_parent_itemkey
2551 for update;
2552
2553 --Nulling out the #LBL_ attribute, if it does not exist, we will check the
2554 --parent flow for #WAITFORDETAIL to see if we can create the #LBL_
2555 --attribute.
2556 l_activity_label := '#LBL_'||waiting_activity;
2557 if NOT (WF_ENGINE.SetItemAttrText2(ContinueMasterFlow.itemtype,
2558 ContinueMasterFlow.itemkey,
2559 l_activity_label,
2560 NULL)) then
2561 l_childwaiting := WF_ENGINE.GetItemAttrNumber(
2562 l_parent_itemtype, l_parent_itemkey,
2563 '#WAITFORDETAIL', TRUE);
2564 if (l_childwaiting is NOT NULL) then
2565 --The parent has #WAITFORDETAIL, so we can create the #LBL_ attribute
2566 WF_ENGINE.AddItemAttr(ContinueMasterFlow.itemtype,
2567 ContinueMasterFlow.itemkey,
2568 l_activity_label, NULL);
2569 else --#WAITFORDETAIL does not exist in the parent, so we will fall back
2570 --to old code path.
2571 -- If parent_context is not set then there is one WaitForFlow Activity
2572 -- use original cursor.
2573
2574 if (l_parent_context is null) then
2575 open child_flows2;
2576 fetch child_flows2 into number_active;
2577 close child_flows2;
2578 else
2579 open child_flows_mwf;
2580 fetch child_flows_mwf into number_active;
2581 close child_flows_mwf;
2582 end if;
2583
2584 if (number_active < 1) then
2585 begin
2586 wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
2587 waiting_activity,wf_engine.eng_null);
2588 resultout := wf_engine.eng_null;
2589 exception
2590 when OTHERS then
2591 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2592 wf_core.clear;
2593 ContinueMasterFlow.resultout := wf_engine.eng_null;
2594 else
2595 raise;
2596 end if;
2597 end;
2598 else
2599 open child_activities2;
2600 fetch child_activities2 into number_complete;
2601 close child_activities2;
2602
2603 begin
2604 if number_active = number_complete then
2605 wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
2606 waiting_activity,wf_engine.eng_null);
2607 end if;
2608 resultout := wf_engine.eng_null;
2609
2610 exception
2611 when others then
2612 --
2613 -- If call to CompleteActivity cannot find activity, return
2614 -- null and wait for master flow
2615 --
2616 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2617 wf_core.clear;
2618 ContinueMasterFlow.resultout := wf_engine.eng_null;
2619 else
2620 raise;
2621 end if;
2622 end;
2623 end if; -- number_active was more than 0
2624 return; -- done with old code path
2625
2626 end if; --#WAITFORDETAIL exists in the parent
2627 end if; --#LBL_ is not null
2628
2629 -- If we come to here, we must be progressing in the new code path.
2630 --Now we will try to decrement the corresponding #CNT_ attribute if it
2631 --exists, and will create it with a value of 0 if it does not yet exist.
2632 l_activity_label := '#CNT_'||waiting_activity;
2633 l_count := WF_ENGINE.AddToItemAttrNumber(l_parent_itemtype,
2634 l_parent_itemkey,
2635 l_activity_label, -1);
2636
2637 if (l_count is NULL) then
2638 WF_ENGINE.AddItemAttr(itemtype=>l_parent_itemtype,
2639 itemkey=>l_parent_itemkey,
2640 aname=>l_activity_label,
2641 number_value=>l_childwaiting - 1);
2642 elsif (l_count < 1) then
2643 begin
2644 wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
2645 waiting_activity,wf_engine.eng_null);
2646 exception
2647 when OTHERS then
2648 if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
2649 wf_core.clear;
2650 ContinueMasterFlow.resultout := wf_engine.eng_null;
2651 else
2652 raise;
2653 end if;
2654 end;
2655 end if;
2656
2657 l_defer := WF_ENGINE.GetActivityAttrText(itemtype, itemkey, actid,
2658 '#HINT', TRUE);
2659
2660 --If #HINT is not set to 'NO_DEFER', or is null we will set the
2661 --threshold to cause the next activity to defer.
2662 if ((l_defer is null) or (l_defer <> 'NO_DEFER')) then
2663 resultout := wf_engine.eng_deferred;
2664 else
2665 resultout := wf_engine.eng_null;
2666 end if;
2667
2668 end if; --First execution
2669
2670 exception
2671 when ValTooLarge OR ValTooLargeNew then
2672 Wf_Core.Context('WF_ENGINE', l_module, ContinueMasterFlow.itemtype,
2673 ContinueMasterFlow.itemkey);
2674 WF_CORE.Token('LABEL', l_activity_label);
2675 WF_CORE.Token('LENGTH', 30);
2676 WF_CORE.Raise('WFENG_LABEL_TOO_LARGE');
2677
2678 when others then
2679 wf_core.context('Wf_Standard', 'ContinueMasterFlow',
2680 itemtype, itemkey, to_char(actid), waiting_activity);
2681 raise;
2682 end ContinueMasterFlow;
2683
2684
2685
2686
2687 -- -------------------------------------------------------------------
2688 -- InitializeErrors
2689 -- checks if an item attribute for Workflow administrator exists in
2690 -- the item that just errored out. If it does, then it uses this
2691 -- role to send notifications to, overriding the default role
2692 -- in this item.
2693 -- NOTE: the item attibute in the workflow-in-error must have an
2694 -- internal name of WF_ADMINISTRATOR.
2695 --
2696 -- Called by default error process.
2697 -- -------------------------------------------------------------------
2698 PROCEDURE InitializeErrors( itemtype VARCHAR2,
2699 itemkey VARCHAR2,
2700 actid NUMBER,
2701 funcmode VARCHAR2,
2702 result OUT NOCOPY VARCHAR2 ) IS
2703
2704 l_error_itemtype VARCHAR2(8);
2705 l_error_itemkey VARCHAR2(240);
2706 l_error_name VARCHAR2(30);
2707 l_error_msg VARCHAR2(2000);
2708 l_timeout PLS_INTEGER;
2709 l_administrator VARCHAR2(100);
2710
2711 BEGIN
2712
2713 IF (funcmode = 'RUN') THEN
2714
2715 --
2716 -- Get the type and the key of the process that errored out
2717 -- these were set in the erroring out process by Execute_Error_Process
2718 --
2719 l_error_itemkey := WF_ENGINE.GetItemAttrText(
2720 itemtype => itemtype,
2721 itemkey => itemkey,
2722 aname => 'ERROR_ITEM_KEY' );
2723 l_error_itemtype := WF_ENGINE.GetItemAttrText(
2724 itemtype => itemtype,
2725 itemkey => itemkey,
2726 aname => 'ERROR_ITEM_TYPE' );
2727
2728 --
2729 -- Check if the workflow administrator exists
2730 -- If it does, then assign the notification to this role
2731 --
2732
2733 begin
2734 --if this item type doesnt exist an exception is raised.
2735 l_administrator := WF_ENGINE.GetItemAttrText(
2736 itemtype => l_error_itemtype,
2737 itemkey => l_error_itemkey,
2738 aname => 'WF_ADMINISTRATOR' );
2739
2740 --<rwunderl:2775132> Put first assignemt in their own block
2741 --in case DEFAULT_RESET_ERROR_NTF does not exist.
2742 begin
2743 wf_engine.AssignActivity(itemtype,itemkey,
2744 'DEFAULT_RESET_ERROR_NTF',
2745 l_administrator);
2746 exception
2747 when OTHERS then
2748 null; --We only null this exception because the parent
2749 --block nulls the expeption.
2750 end;
2751
2752 wf_engine.AssignActivity(itemtype,itemkey,'RETRY_ONLY_NTF',
2753 l_administrator);
2754
2755 exception
2756 when others then null;
2757 end;
2758
2759 --
2760 -- Check if a timeout value exists
2761 -- If it does, then set the error timeout
2762 --
2763
2764 begin
2765 --if this item type doesnt exist an exception is raised.
2766 l_timeout := WF_ENGINE.GetItemAttrNumber(
2767 itemtype => l_error_itemtype,
2768 itemkey => l_error_itemkey,
2769 aname => 'ERROR_TIMEOUT' );
2770 wf_engine.SetItemAttrNumber(itemtype,itemkey,'TIMEOUT_VALUE',l_timeout);
2771 exception
2772 when others then null;
2773 end;
2774
2775 result := wf_engine.eng_completed;
2776 ELSIF (funcmode = 'CANCEL') THEN
2777 result := wf_engine.eng_completed;
2778 END IF;
2779 EXCEPTION
2780 WHEN OTHERS THEN
2781 WF_CORE.Context('WF_STANDARD', 'InitializeErrors',
2782 itemtype, itemkey, actid, funcmode);
2783 RAISE;
2784 END InitializeErrors;
2785
2786 -- -------------------------------------------------------------------
2787 -- CheckErrorActive
2788 -- checks if an error is still active and returns TRUE/FALSE.
2789 -- Use this in an error process to exit out of a timeout loop
2790 -- Called by default error process.
2791 -- -------------------------------------------------------------------
2792 PROCEDURE CheckErrorActive( itemtype IN VARCHAR2,
2793 itemkey IN VARCHAR2,
2794 actid IN NUMBER,
2795 funcmode IN VARCHAR2,
2796 result OUT NOCOPY VARCHAR2 ) IS
2797
2798 l_error_itemtype VARCHAR2(8);
2799 l_error_itemkey VARCHAR2(240);
2800 l_error_actid NUMBER;
2801 status VARCHAR2(30);
2802
2803 cursor activity_status (litemtype varchar2, litemkey varchar2, lactid number ) is
2804 select WIAS.ACTIVITY_STATUS
2805 from WF_ITEM_ACTIVITY_STATUSES WIAS
2806 where WIAS.ITEM_TYPE = litemtype
2807 and WIAS.ITEM_KEY = litemkey
2808 and WIAS.PROCESS_ACTIVITY = lactid;
2809
2810
2811 BEGIN
2812
2813 IF (funcmode = 'RUN') THEN
2814
2815 --
2816 -- Get the type and the key of the process that errored out
2817 -- these were set in the erroring out process by Execute_Error_Process
2818 --
2819 l_error_itemkey := WF_ENGINE.GetItemAttrText(
2820 itemtype => itemtype,
2821 itemkey => itemkey,
2822 aname => 'ERROR_ITEM_KEY' );
2823 l_error_itemtype := WF_ENGINE.GetItemAttrText(
2824 itemtype => itemtype,
2825 itemkey => itemkey,
2826 aname => 'ERROR_ITEM_TYPE' );
2827
2828 l_error_actid := WF_ENGINE.GetItemAttrText(
2829 itemtype => itemtype,
2830 itemkey => itemkey,
2831 aname => 'ERROR_ACTIVITY_ID' );
2832
2833 open activity_status(l_error_itemtype, l_error_itemkey, l_error_actid);
2834 fetch activity_status into status;
2835 close activity_status;
2836
2837 if status = 'ERROR' then
2838 result:='T';
2839 else
2840 result:='F';
2841 end if;
2842
2843 END IF;
2844
2845 EXCEPTION
2846 WHEN OTHERS THEN
2847 WF_CORE.Context('WF_STANDARD', 'CheckErrorActive',
2848 itemtype, itemkey, actid, funcmode);
2849 RAISE;
2850 END CheckErrorActive;
2851 -- -------------------------------------------------------------------
2852 -- InitializeEventError
2853 -- Called by the Error Process, this sets up various
2854 -- item attributes.
2855 -- -------------------------------------------------------------------
2856 PROCEDURE InitializeEventError( itemtype VARCHAR2,
2857 itemkey VARCHAR2,
2858 actid NUMBER,
2859 funcmode VARCHAR2,
2860 resultout OUT NOCOPY VARCHAR2 ) IS
2861 l_event_t wf_event_t;
2862 l_error_name varchar2(240);
2863 l_error_type varchar2(240);
2864 l_error_message varchar2(2000);
2865 l_error_stack varchar2(2000);
2866 l_subscription RAW(16);
2867 l_url varchar2(4000);
2868 l_eventdataurl varchar2(4000);
2869 l_source varchar2(8);
2870
2871
2872 begin
2873
2874 IF (funcmode = 'RUN') THEN
2875 --
2876 -- Get the Event Item Attribute
2877 --
2878
2879 l_event_t := WF_ENGINE.GetItemAttrEvent(
2880 itemtype => itemtype,
2881 itemkey => itemkey,
2882 name => 'EVENT_MESSAGE' );
2883 --
2884 -- Get the Errored Subscription GUID
2885 --
2886 l_subscription := l_event_t.GetErrorSubscription();
2887
2888 --
2889 -- Get the Error Type from the Item Attribute - set by Engine
2890 --
2891 l_error_type := WF_ENGINE.GetItemAttrText(
2892 itemtype => itemtype,
2893 itemkey => itemkey,
2894 aname => 'ERROR_TYPE');
2895 --
2896 -- If the error type is null, this must be an UNEXPECTED event
2897 --
2898 IF l_error_type IS NULL THEN
2899 l_error_type := 'UNEXPECTED';
2900 wf_engine.SetItemAttrText(itemtype => itemtype,
2901 itemkey => itemkey,
2902 aname => 'ERROR_TYPE',
2903 avalue => l_error_type);
2904 END IF;
2905
2906 --
2907 -- Determine if this event is LOCAL or EXTERNAL
2908 --
2909 if l_subscription is not null then
2910 -- If a subscription found, look at its source
2911 select source_type into l_source
2912 from wf_event_subscriptions
2913 where guid = l_subscription;
2914
2915 if l_source = 'ERROR' then
2916 l_source := 'LOCAL';
2917 end if;
2918 else
2919 -- Since no subscription found, look at from agent details
2920 begin
2921 select 'LOCAL' into l_source
2922 from wf_systems ws
2923 where ws.guid = hextoraw(wf_core.translate('WF_SYSTEM_GUID'))
2924 and ws.name = nvl(l_event_t.GetFromAgent().GetSystem(),ws.name);
2925 exception
2926 when no_data_found then
2927 l_source := 'EXTERNAL';
2928 end;
2929 end if;
2930
2931 --
2932 -- Get the Error Message, or set it if UNEXPECTED
2933 --
2934 l_error_message := substr(l_event_t.GetErrorMessage(),1,2000);
2935 IF (l_error_message is null) THEN
2936 -- Bug 10126673: Show 'NO_ERROR_MESSAGE' message token when error message is null
2937 l_error_message := wf_core.translate('NO_ERROR_MESSAGE');
2938 END IF;
2939
2940 -- Get the Error Stack
2941 l_error_stack := substr(l_event_t.GetErrorStack(),1,2000);
2942
2943 -- Get the Errored Subscription GUID
2944 l_subscription := l_event_t.GetErrorSubscription();
2945
2946 -- Generate the URL
2947 wf_event_html.GetFWKEvtSubscriptionUrl(l_subscription, l_url);
2948 l_eventdataurl := wf_oam_util.GetViewXMLURL(p_eventattribute => 'EVENT_MESSAGE',
2949 p_itemtype => itemtype,
2950 p_itemkey => itemkey);
2951
2952 -- Set the Item Attributes
2953
2954 wf_engine.SetItemAttrText(itemtype => itemtype,
2955 itemkey => itemkey,
2956 aname => 'ERROR_MESSAGE',
2957 avalue => l_error_message);
2958
2959 wf_engine.SetItemAttrText(itemtype => itemtype,
2960 itemkey => itemkey,
2961 aname => 'ERROR_STACK',
2962 avalue => l_error_stack);
2963
2964 -- Set the PL/SQL Document for the Event Details
2965 wf_engine.SetItemAttrText(itemtype => itemtype,
2966 itemkey => itemkey,
2967 aname => 'EVENT_DETAILS',
2968 avalue => 'PLSQL:WF_STANDARD.EVENTDETAILS/'||ItemType||':'||ItemKey);
2969
2970 wf_engine.SetItemAttrText(itemtype => itemtype,
2971 itemkey => itemkey,
2972 aname => 'ERROR_DETAILS',
2973 avalue => 'PLSQL:WF_STANDARD.ErrorDetails/'||ItemType||':'||ItemKey);
2974
2975 wf_engine.SetItemAttrText(itemtype => itemtype,
2976 itemkey => itemkey,
2977 aname => 'SUBSCRIPTION_DETAILS',
2978 avalue => 'PLSQL:WF_STANDARD.SubscriptionDetails/'||ItemType||':'||ItemKey);
2979
2980 -- Set the Value for the Error Subscription URL
2981 wf_engine.SetItemAttrText(itemtype => itemtype,
2982 itemkey => itemkey,
2983 aname => 'EVENT_SUBSCRIPTION',
2984 avalue => l_url);
2985 -- Set the Value for the Event Data URL
2986 wf_engine.SetItemAttrText(itemtype => itemtype,
2987 itemkey => itemkey,
2988 aname => 'EVENT_DATA_URL',
2989 avalue => l_eventdataurl);
2990
2991 IF l_error_type IN ('ERROR','UNEXPECTED') THEN
2992 IF l_source = 'LOCAL' THEN
2993 resultout := 'EVENT_ERROR';
2994 ELSE
2995 resultout := 'EVENT_EXTERNAL_ERROR';
2996 END IF;
2997 ELSE
2998 resultout := 'EVENT_WARNING';
2999 END IF;
3000
3001 ELSIF (funcmode = 'CANCEL') THEN
3002 resultout := wf_engine.eng_completed;
3003 END IF;
3004 EXCEPTION
3005 WHEN OTHERS THEN
3006 WF_CORE.Context('WF_STANDARD', 'InitializeEventError',
3007 itemtype, itemkey, actid, funcmode);
3008 RAISE;
3009 END InitializeEventError;
3010 -- --------------------------------------------------------------------
3011 -- EventDetails
3012 -- PL/SQL Document for Event Attributes
3013 -- --------------------------------------------------------------------
3014 procedure EventDetails ( document_id in varchar2,
3015 display_type in varchar2,
3016 document in out nocopy varchar2,
3017 document_type in out nocopy varchar2) IS
3018
3019 ItemType varchar2(30);
3020 ItemKey varchar2(30);
3021
3022 l_to_agent varchar2(60);
3023 l_to_system varchar2(60);
3024 l_from_agent varchar2(60);
3025 l_from_system varchar2(60);
3026 l_priority varchar2(10);
3027 l_send_date date;
3028 l_send_date_text varchar2(60);
3029 l_receive_date date;
3030 l_receive_date_text varchar2(60);
3031
3032 i pls_integer;
3033
3034 l_event_t wf_event_t;
3035 l_parmlist_t wf_parameter_list_t;
3036 l_cells wf_notification.tdType;
3037 j number;
3038 l_result varchar2(32000);
3039
3040 begin
3041
3042 -- parse document_id for the ':' dividing item type name from item key value
3043 -- document_id value will take the form <ITEMTYPE>:<ITEMKEY> starting with
3044 -- release 2.5
3045 ItemType := nvl(substr(document_id, 1, instr(document_id,':')-1),'WFERROR');
3046 ItemKey := substr(document_id
3047 , instr(document_id,':')+1);
3048
3049
3050
3051 l_event_t := wf_engine.GetItemAttrEvent(
3052 itemtype => itemtype,
3053 itemkey => itemkey,
3054 name => 'EVENT_MESSAGE' );
3055
3056 --
3057 -- Get the Agent Details, we don't want any errors if the Agent
3058 -- didn't get populated with anything
3059 --
3060 if l_event_t.To_Agent is not null then
3061 l_to_agent := l_event_t.GetToAgent().GetName();
3062 l_to_system := l_event_t.GetToAgent().GetSystem();
3063 end if;
3064
3065 if l_event_t.From_Agent is not null then
3066 l_from_agent := l_event_t.GetFromAgent().GetName();
3067 l_from_system := l_event_t.GetFromAgent().GetSystem();
3068 end if;
3069
3070 --
3071 -- Get any date values and format if required
3072 --
3073 l_send_date := l_event_t.GetSendDate();
3074
3075 IF l_send_date IS NOT NULL THEN
3076 l_send_date_text := WF_NOTIFICATION_UTIL.GetCalendarDate(-1, l_send_date, null, true);
3077 END IF;
3078
3079 l_receive_date := l_event_t.GetReceiveDate();
3080
3081 IF l_receive_date IS NOT NULL THEN
3082 l_receive_date_text := WF_NOTIFICATION_UTIL.GetCalendarDate(-1, l_receive_date, null, true);
3083 END IF;
3084
3085 --
3086 -- Get the Priority
3087 --
3088 l_priority := l_event_t.GetPriority();
3089
3090 --
3091 -- Build up the PL/SQL Document depending on the User Mail Preference
3092 --
3093 -- bug 6955474
3094 -- Using WF_NOTIFICATION.NTF_Table API to maintain consistency with BLAF
3095 --
3096 -- Build the Table
3097 if (display_type = wf_notification.doc_html) then
3098 i := 1;
3099 l_cells(i) := wf_core.translate('WF_EVENT_HEADING');
3100 l_cells(i) := 'S30%:'||l_cells(i);
3101
3102 i := i + 1;
3103 l_cells(i) := wf_core.translate('WF_VALUE');
3104 l_cells(i) := 'S70%:'||l_cells(i);
3105
3106 i := i + 1;
3107 l_cells(i) := 'S:'||wf_core.translate('WF_EVENT_NAME');
3108 i := i + 1;
3109 l_cells(i) := 'S:'||nvl(l_event_t.GetEventName(),'&'||'nbsp');
3110
3111 i := i + 1;
3112 l_cells(i) := 'S:'||wf_core.translate('WF_EVENT_KEY');
3113 i := i + 1;
3114 l_cells(i) := 'S:'||nvl(l_event_t.GetEventKey(),'&'||'nbsp');
3115
3116 i := i + 1;
3117 l_cells(i) := 'S:'||wf_core.translate('WF_TO_AGENT_NAME');
3118 i := i + 1;
3119 l_cells(i) := 'S:'||l_to_agent;
3120 i := i + 1;
3121 l_cells(i) := 'S:'||wf_core.translate('WF_TO_AGENT_SYSTEM');
3122 i := i + 1;
3123 l_cells(i) := 'S:'||l_to_system;
3124
3125 i := i + 1;
3126 l_cells(i) := 'S:'||wf_core.translate('WF_FROM_AGENT_NAME');
3127 i := i + 1;
3128 l_cells(i) := 'S:'||l_from_agent;
3129 i := i + 1;
3130 l_cells(i) := 'S:'||wf_core.translate('WF_FROM_AGENT_SYSTEM');
3131 i := i + 1;
3132 l_cells(i) := 'S:'||l_from_system;
3133
3134 i := i + 1;
3135 l_cells(i) := 'S:'||wf_core.translate('WF_SEND_DATE');
3136 i := i + 1;
3137 l_cells(i) := 'S:<BDO DIR="LTR">'||l_send_date_text||'</BDO>';
3138
3139 i := i + 1;
3140 l_cells(i) := 'S:'||wf_core.translate('WF_RECEIVE_DATE');
3141 i := i + 1;
3142 l_cells(i) := 'S:<BDO DIR="LTR">'||l_receive_date_text||'</BDO>';
3143
3144 i := i + 1;
3145 l_cells(i) := 'S:'||wf_core.translate('WF_PRIORITY');
3146 i := i + 1;
3147 l_cells(i) := 'S:'||l_priority;
3148
3149 i := i + 1;
3150 l_cells(i) := 'S:'||wf_core.translate('WF_CORRELATION');
3151 i := i + 1;
3152 l_cells(i) := 'S:'||nvl(l_event_t.GetCorrelationId(),'&'||'nbsp');
3153
3154 else
3155 l_result := Wf_Core.Newline||rpad(wf_core.translate('WF_EVENT_HEADING'),40)
3156 ||wf_core.translate('WF_VALUE')||Wf_Core.Newline;
3157
3158 l_result := l_result||rpad(wf_core.translate('WF_EVENT_NAME'),40)||
3159 l_event_t.GetEventName()||Wf_Core.Newline||
3160 rpad(wf_core.translate('WF_EVENT_KEY'),40)||
3161 l_event_t.GetEventKey()||Wf_Core.Newline||
3162 rpad(wf_core.translate('WF_FROM_AGENT_NAME'),40)||
3163 l_From_Agent||Wf_Core.Newline||
3164 rpad(wf_core.translate('WF_FROM_AGENT_SYSTEM'),40)||
3165 l_From_System||Wf_Core.Newline||
3166 rpad(wf_core.translate('WF_TO_AGENT_NAME'),40)||
3167 l_To_Agent||Wf_Core.Newline||
3168 rpad(wf_core.translate('WF_TO_AGENT_SYSTEM'),40)||
3169 l_To_System||Wf_Core.Newline||
3170 rpad(wf_core.translate('WF_PRIORITY'),40)||
3171 l_Priority||Wf_Core.Newline||
3172 rpad(wf_core.translate('WF_SEND_DATE'),40)||
3173 l_send_date_text||Wf_Core.Newline||
3174 rpad(wf_core.translate('WF_RECEIVE_DATE'),40)||
3175 l_receive_date_text||Wf_Core.Newline||
3176 rpad(wf_core.translate('WF_CORRELATION'),40)||
3177 l_event_t.GetCorrelationId()||Wf_Core.Newline;
3178
3179 end if;
3180
3181 -- Display the Parameter List
3182 l_parmlist_t := l_event_t.getParameterList();
3183 if (l_parmlist_t is not null) then
3184 j := l_parmlist_t.FIRST;
3185 while (j <= l_parmlist_t.LAST) loop
3186 if (display_type = wf_notification.doc_html) then
3187 i := i + 1;
3188 l_cells(i) := 'S:'||wf_core.translate('WF_PARAMETER')||' : '||l_parmlist_t(j).getName();
3189
3190 i := i + 1;
3191 l_cells(i) :=
3192 'S:'||substr(nvl(l_parmlist_t(j).getValue(),'&'||'nbsp'),1,20);
3193 else
3194 l_result := l_result||rpad(wf_core.translate('WF_PARAMETER')
3195 ||l_parmlist_t(j).getName(),40)
3196 ||substr(l_parmlist_t(j).getValue(),1,20)||Wf_Core.Newline;
3197 end if;
3198 j := l_parmlist_t.NEXT(j);
3199 end loop;
3200 end if;
3201
3202 if (display_type = wf_notification.doc_html) then
3203 document_type := wf_notification.doc_html;
3204 wf_notification.NTF_Table(cells => l_cells,
3205 col => 2,
3206 type => 'H',
3207 rs => l_result);
3208 -- Display title
3209 l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1">' ||
3210 '<tr><td class="x3w">'||wf_core.Translate('WFITD_EVENT_DETAILS')||
3211 '</td></tr>'||'<tr><td>'||l_result||'</td></tr></table>';
3212
3213 else
3214 document_type := wf_notification.doc_text;
3215 end if;
3216 document := l_result;
3217
3218 exception
3219 when others then
3220 wf_core.context('WF_STANDARD','EventDetails',document_id, display_type);
3221 raise;
3222 end EventDetails;
3223 -- --------------------------------------------------------------------
3224 -- Retry Raise
3225 -- Executes command depending on notification response
3226 -- --------------------------------------------------------------------
3227 PROCEDURE RetryRaise ( itemtype in varchar2,
3228 itemkey in varchar2,
3229 actid in number,
3230 funcmode in varchar2,
3231 resultout out nocopy varchar2 ) IS
3232
3233 aname varchar2(100);
3234 l_event_t wf_event_t;
3235 l_toagent wf_agent_t;
3236 l_skip_sub varchar2(300) := null;
3237 l_parameterList wf_parameter_list_t := null;
3238
3239 begin
3240
3241 IF (funcmode = 'RUN') THEN
3242
3243 l_event_t := wf_engine.GetItemAttrEvent(
3244 itemtype => itemtype,
3245 itemkey => itemkey,
3246 name => 'EVENT_MESSAGE' );
3247
3248 aname := wf_engine.GetActivityAttrText(itemtype,
3249 itemkey,
3250 actid,
3251 'COMMAND');
3252
3253 -- Bug 4198975
3254 -- If the SKIP_ERROR_SUB is not null, then this parameber will
3255 -- be passed over to raise in all the cases.
3256 l_skip_sub := l_event_t.GETVALUEFORPARAMETER('SKIP_ERROR_SUB');
3257 if (l_skip_sub is not null) then
3258 l_parameterList := wf_parameter_list_t();
3259 wf_event.addParameterToList('SKIP_ERROR_SUB', l_skip_sub, l_parameterList);
3260 end if;
3261
3262 IF aname = 'RAISE_KEY' THEN
3263 wf_event.raise(p_event_name => l_event_t.GetEventName(),
3264 p_event_key => l_event_t.GetEventKey(),
3265 p_parameters => l_parameterList);
3266
3267 ELSIF aname = 'RAISE_KEY_DATA' THEN
3268 wf_event.raise(p_event_name => l_event_t.GetEventName(),
3269 p_event_key => l_event_t.GetEventKey(),
3270 p_event_data => l_event_t.GetEventData(),
3271 p_parameters => l_parameterList);
3272
3273 ELSIF aname = 'RAISE_KEY_DATA_PARAM' THEN
3274 wf_event.raise(l_event_t.GetEventName(),
3275 l_event_t.GetEventKey(),
3276 l_event_t.GetEventData(),
3277 l_event_t.GetParameterList());
3278 ELSIF aname = 'ENQUEUE' THEN
3279 l_toagent := l_event_t.GetToAgent();
3280 l_event_t.SetPriority(-1); -- want this dequeued ASAP
3281 wf_event.enqueue(l_event_t, l_toagent);
3282 ELSE
3283 wf_core.raise('WFSQL_ARGS');
3284
3285 END IF;
3286
3287 resultout := wf_engine.eng_completed;
3288
3289 ELSIF (funcmode = 'CANCEL') THEN
3290 resultout := wf_engine.eng_completed;
3291 END IF;
3292
3293 EXCEPTION
3294 WHEN OTHERS THEN
3295 WF_CORE.Context('WF_STANDARD', 'RetryRaise',
3296 itemtype, itemkey, actid, funcmode);
3297 RAISE;
3298 end RetryRaise;
3299 -- --------------------------------------------------------------------
3300 -- GetAgents
3301 -- Gets the Event Subscription Out and To Agent
3302 -- --------------------------------------------------------------------
3303 procedure GetAgents ( itemtype in varchar2,
3304 itemkey in varchar2,
3305 actid in number,
3306 funcmode in varchar2,
3307 resultout out nocopy varchar2)
3308 is
3309
3310 --l_subguid raw(16);
3311 l_subguid varchar2(100);
3312 l_outagentattr varchar2(100);
3313 l_toagentattr varchar2(100);
3314 l_outagentguid raw(16);
3315 l_toagentguid raw(16);
3316 l_outagent varchar2(100);
3317 l_toagent varchar2(100);
3318
3319 cursor c_agents is
3320 select out_agent_guid, to_agent_guid
3321 from wf_event_subscriptions
3322 where guid = l_subguid;
3323
3324 begin
3325
3326 IF (funcmode = 'RUN') THEN
3327
3328 l_subguid := wf_engine.GetActivityAttrText(itemtype,
3329 itemkey,
3330 actid,
3331 'SUB_GUID');
3332
3333 l_outagentattr := wf_engine.GetActivityAttrText(itemtype,
3334 itemkey,
3335 actid,
3336 'FROMAGENT');
3337
3338 l_toagentattr := wf_engine.GetActivityAttrText(itemtype,
3339 itemkey,
3340 actid,
3341 'TOAGENT');
3342
3343 -- Get the Agent Guids
3344 open c_agents;
3345 fetch c_agents into l_outagentguid, l_toagentguid;
3346 close c_agents;
3347
3348 if l_toagentguid is not null then
3349 -- Get the Out Agent in the agent@system format
3350 if l_outagentguid is not null then
3351 select wfa.name||'@'||wfs.name
3352 into l_outagent
3353 from wf_agents wfa, wf_systems wfs
3354 where wfa.guid = l_outagentguid
3355 and wfa.system_guid = wfs.guid;
3356 end if;
3357
3358 -- Get the To Agent in the agent@system format
3359 select wfa.name||'@'||wfs.name
3360 into l_toagent
3361 from wf_agents wfa, wf_systems wfs
3362 where wfa.guid = l_toagentguid
3363 and wfa.system_guid = wfs.guid;
3364
3365 -- Update the agent item attributes
3366 wf_engine.SetItemAttrText(itemtype => itemtype,
3367 itemkey => itemkey,
3368 aname => l_outagentattr,
3369 avalue => l_outagent);
3370
3371 wf_engine.SetItemAttrText(itemtype => itemtype,
3372 itemkey => itemkey,
3373 aname => l_toagentattr,
3374 avalue => l_toagent);
3375 resultout := 'T';
3376 else
3377 resultout := 'F';
3378 end if;
3379 ELSIF (funcmode = 'CANCEL') THEN
3380 resultout := wf_engine.eng_completed;
3381 END IF;
3382
3383 EXCEPTION
3384 WHEN OTHERS THEN
3385 WF_CORE.Context('WF_STANDARD', 'GetAgents',
3386 itemtype, itemkey, actid, funcmode);
3387 RAISE;
3388 end GetAgents;
3389 -- --------------------------------------------------------------------
3390 -- GetAckAgent
3391 -- Gets the Acknowledge To Agent based on the Event Message
3392 -- --------------------------------------------------------------------
3393 procedure GetAckAgent ( itemtype in varchar2,
3394 itemkey in varchar2,
3395 actid in number,
3396 funcmode in varchar2,
3397 resultout out nocopy varchar2)
3398 is
3399
3400 l_event_t wf_event_t;
3401 l_toagentattr varchar2(100);
3402 l_system varchar2(30);
3403 l_agent varchar2(30);
3404
3405 cursor c_return_agent is
3406 select wfa.name agent
3407 from wf_systems wfs,
3408 wf_agents wfa
3409 where wfs.name = l_system
3410 and wfa.status = 'ENABLED'
3411 and wfa.direction = 'IN'
3412 and wfa.name not in ('WF_ERROR','WF_DEFERRED');
3413
3414 begin
3415
3416 IF (funcmode = 'RUN') THEN
3417
3418 l_event_t := wf_engine.GetActivityAttrEvent(
3419 itemtype => itemtype,
3420 itemkey => itemkey,
3421 actid => actid,
3422 name => 'EVENTMESSAGE');
3423
3424 l_toagentattr := wf_engine.GetActivityAttrText(itemtype,
3425 itemkey,
3426 actid,
3427 'ACKTOAGENT');
3428
3429 l_system := l_event_t.GetFromAgent().GetSystem();
3430
3431 open c_return_agent;
3432 fetch c_return_agent into l_agent;
3433 close c_return_agent;
3434
3435 if l_agent is not null then
3436 wf_engine.SetItemAttrText(itemtype => itemtype,
3437 itemkey => itemkey,
3438 aname => l_toagentattr,
3439 avalue => l_agent||'@'||l_system);
3440 end if;
3441
3442 resultout := wf_engine.eng_completed;
3443
3444 ELSIF (funcmode = 'CANCEL') THEN
3445 resultout := wf_engine.eng_completed;
3446 END IF;
3447
3448 EXCEPTION
3449 WHEN OTHERS THEN
3450 WF_CORE.Context('WF_STANDARD', 'GetAckAgent',
3451 itemtype, itemkey, actid, funcmode);
3452 RAISE;
3453 end GetAckAgent;
3454
3455 -- SubscriptionDetails
3456 -- PL/SQL Document to display subscription parameter details
3457 -- IN
3458 -- document_id
3459 -- display_type
3460 -- document
3461 -- document_type
3462 procedure SubscriptionDetails (document_id in varchar2,
3463 display_type in varchar2,
3464 document in out nocopy varchar2,
3465 document_type in out nocopy varchar2)
3466 is
3467 l_item_type varchar2(10);
3468 l_item_key varchar2(240);
3469 l_subscription raw(16);
3470 l_params varchar2(4000);
3471 l_rule_func varchar2(240);
3472 l_cells wf_notification.tdType;
3473 l_cells2 wf_notification.tdType;
3474 i pls_integer;
3475 j pls_integer;
3476 l_document varchar2(32000);
3477 l_sub_param_list wf_parameter_list_t;
3478 l_event_t wf_event_t;
3479 l_result varchar2(22000);
3480 l_result2 varchar2(10000);
3481 l_url varchar2(500);
3482 l_sub_url varchar2(1000);
3483 l_evt_url varchar2(1000);
3484 begin
3485 l_item_type := nvl(substr(document_id, 1,
3486 instr(document_id,':')-1),'WFERROR');
3487 l_item_key := substr(document_id, instr(document_id,':')+1);
3488
3489 l_event_t := wf_engine.GetItemAttrEvent(itemtype => l_item_type,
3490 itemkey => l_item_key,
3491 name => 'EVENT_MESSAGE');
3492 l_subscription := l_event_t.GetErrorSubscription();
3493
3494 if (l_subscription is not null) then
3495
3496 SELECT parameters, java_rule_func
3497 INTO l_params, l_rule_func
3498 FROM wf_event_subscriptions
3499 WHERE guid = l_subscription;
3500
3501 l_sub_param_list := wf_event.GetParamListFromString(l_params);
3502
3503 if (display_type = wf_notification.doc_html) then
3504 i := 1;
3505 l_cells(i) := 'S30%:'||wf_core.Translate('WF_PARAMETER');
3506
3507 i := i + 1;
3508 l_cells(i) := 'S70%:'||wf_core.Translate('WF_VALUE');
3509 else
3510 l_result := Wf_Core.Newline||rpad(wf_core.Translate('WF_PARAMETER'), 40)
3511 ||wf_core.translate('WF_VALUE')||Wf_Core.Newline;
3512 end if;
3513
3514 -- Show all Subscription Parameters that are currently used as
3515 -- meta-data store for WS definition
3516 if (l_sub_param_list is not null) then
3517 j := l_sub_param_list.FIRST;
3518 while (j is not null) loop
3519 if (display_type = wf_notification.doc_html) then
3520 i := i + 1;
3521 l_cells(i) := 'S:'||l_sub_param_list(j).getName();
3522
3523 i := i + 1;
3524 l_cells(i) := 'S:'||l_sub_param_list(j).getValue();
3525 else
3526 l_result := l_result||rpad(l_sub_param_list(j).getName(),40)||
3527 rpad(l_sub_param_list(j).getValue(),40)||wf_core.newline;
3528 end if;
3529 j := l_sub_param_list.NEXT(j);
3530 end loop;
3531 end if;
3532
3533 -- Show Invoker Rule Function since it may be a Custom one extended from
3534 -- seeded. Also the Event Payload is WS input message
3535 l_evt_url := wf_engine.GetItemAttrText(itemtype => l_item_type,
3536 itemkey => l_item_key,
3537 aname => 'EVENT_DATA_URL');
3538 l_sub_url := wf_engine.GetItemAttrText(itemtype => l_item_type,
3539 itemkey => l_item_key,
3540 aname => 'EVENT_SUBSCRIPTION');
3541
3542 if (display_type = wf_notification.doc_html) then
3543 i := i + 1;
3544 l_cells(i) := 'S:'||wf_core.Translate('WF_INOKER_RULE_FUNC');
3545 i := i + 1;
3546 l_cells(i) := 'S:'||l_rule_func;
3547
3548 i := i + 1;
3549 l_cells(i) := 'S:'||wf_core.Translate('WF_WS_INPUT_MESG');
3550 i := i + 1;
3551 l_url := '<a href="'||l_evt_url||'" class="xd">'||wf_core.Translate('WF_CLICK_HERE')||'</a>';
3552 l_cells(i) := 'S:'||l_url;
3553
3554 i := i + 1;
3555 l_cells(i) := 'S:'||wf_core.Translate('WF_SUBSCRIPTION_PAGE');
3556 i := i + 1;
3557 l_url := '<a href="'||l_sub_url||'" class="xd">'||wf_core.Translate('WF_CLICK_HERE')||'</a>';
3558 l_cells(i) := 'S:'||l_url;
3559
3560 wf_notification.Ntf_Table(l_cells, 2, 'H', l_result);
3561
3562 -- Display title "Web Service Details"
3563 l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1">' ||
3564 '<tr><td class="x3w">'||wf_core.Translate('WF_WEBSERVICE_DETAILS')||'</td></tr>'||
3565 '<tr><td>'||l_result||'</td></tr></table>';
3566
3567 else
3568 l_result := l_result||rpad(wf_core.Translate('WF_INOKER_RULE_FUNC'),40)||
3569 rpad(l_rule_func,40)||wf_core.newline||
3570 rpad(wf_core.Translate('WF_WS_INPUT_MESG'),40)||
3571 rpad(l_evt_url,40)||wf_core.newline||
3572 rpad(wf_core.Translate('WF_SUBSCRIPTION_PAGE'),40)||
3573 rpad(l_sub_url,40)||wf_core.newline;
3574
3575 end if;
3576 end if;
3577 document := l_result;
3578 exception
3579 when others then
3580 wf_core.context('WF_STANDARD', 'SubscriptionDetails', document_id);
3581 raise;
3582 end SubscriptionDetails;
3583
3584 -- ErrorDetails
3585 -- PL/SQL Document to display event error details
3586 -- IN
3587 -- document_id
3588 -- display_type
3589 -- document
3590 -- document_type
3591 procedure ErrorDetails (document_id in varchar2,
3592 display_type in varchar2,
3593 document in out nocopy varchar2,
3594 document_type in out nocopy varchar2)
3595 is
3596 l_result varchar2(32000);
3597 l_error_name varchar2(240);
3598 l_item_type varchar2(30);
3599 l_item_key varchar2(240);
3600 l_error_message varchar2(2000);
3601 l_error_stack varchar2(2000);
3602 l_cells wf_notification.tdType;
3603 i pls_integer;
3604 begin
3605
3606 l_item_type := nvl(substr(document_id, 1, instr(document_id,':')-1),'WFERROR');
3607 l_item_key := substr(document_id, instr(document_id,':')+1);
3608
3609 l_error_name := wf_engine.GetItemAttrText(itemtype => l_item_type,
3610 itemkey => l_item_key,
3611 aname => 'ERROR_NAME');
3612 l_error_message := wf_engine.GetItemAttrText(itemtype => l_item_type,
3613 itemkey => l_item_key,
3614 aname => 'ERROR_MESSAGE');
3615 l_error_stack := wf_engine.GetItemAttrText(itemtype => l_item_type,
3616 itemkey => l_item_key,
3617 aname => 'ERROR_STACK');
3618
3619 if (display_type = wf_notification.doc_html) then
3620 document_type := wf_notification.doc_html;
3621
3622 i := 1;
3623 if (l_error_name is not null) then
3624 l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_NAME');
3625 i := i + 1;
3626 l_cells(i) := 'S:'||l_error_name;
3627 i := i + 1;
3628 end if;
3629
3630 l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_MESSAGE');
3631 i := i + 1;
3632 l_cells(i) := 'S:'||l_error_message;
3633
3634 i := i + 1;
3635 l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_STACK');
3636 i := i + 1;
3637 l_cells(i) := 'S:'||l_error_stack;
3638
3639 wf_notification.NTF_Table(cells => l_cells,
3640 col => 2,
3641 type => 'V',
3642 rs => l_result);
3643
3644 -- Display title
3645 l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1">' ||
3646 '<tr><td class="x3w">'||wf_core.Translate('WF_ERROR_DETAILS') ||
3647 '</td></tr>'||'<tr><td>'||l_result||'</td></tr></table>';
3648 else
3649 document_type := wf_notification.doc_text;
3650 l_result := rpad(wf_core.Translate('WFMON_ERROR_NAME'),40)||' : '||l_error_name||wf_core.newline||
3651 rpad(wf_core.Translate('WFMON_ERROR_MESSAGE'),40)||' : '||l_error_message||wf_core.newline||
3652 rpad(wf_core.Translate('WFMON_ERROR_STACK'),40)||' : '||l_error_stack||wf_core.newline;
3653 end if;
3654 document := l_result;
3655 exception
3656 when others then
3657 wf_core.context('WF_STANDARD', 'ErrorDetails', document_id);
3658 raise;
3659 end ErrorDetails;
3660
3661 -- SubscriptionAction
3662 -- Returns Subscription's Action Code based on which a specific notification
3663 -- could be sent
3664 procedure SubscriptionAction(itemtype in varchar2,
3665 itemkey in varchar2,
3666 actid in number,
3667 funcmode in varchar2,
3668 resultout in out nocopy varchar2)
3669 is
3670 l_event_t wf_event_t;
3671 l_subscription raw(16);
3672 l_action_code varchar2(30);
3673 begin
3674
3675 if (funcmode = 'RUN') then
3676 l_event_t := wf_engine.GetItemAttrEvent(itemtype => itemtype,
3677 itemkey => itemkey,
3678 name => 'EVENT_MESSAGE');
3679 l_subscription := l_event_t.GetErrorSubscription();
3680
3681 SELECT action_code
3682 INTO l_action_code
3683 FROM wf_event_subscriptions
3684 WHERE guid = l_subscription;
3685
3686 if (l_action_code is not null) then
3687 resultout := wf_engine.eng_completed||':'||l_action_code;
3688 else
3689 resultout := wf_engine.eng_completed||':CUSTOM_RG';
3690 end if;
3691 elsif (funcmode = 'CANCEL') then
3692 resultout := wf_engine.eng_completed;
3693 end if;
3694
3695 end SubscriptionAction;
3696
3697 --
3698 -- InitializeErrorInfo
3699 -- ER 10177347: Called by the Error Process in the deferred notification
3700 -- response processing mode, this sets up various item attributes.
3701 -- IN
3702 -- itemtype - item type
3703 -- itemkey - item key
3704 -- actid - process activity instance id
3705 -- funcmode - execution mode
3706 -- OUT
3707 -- result - 'NULL'
3708 procedure InitializeErrorInfo (itemtype in varchar2,
3709 itemkey in varchar2,
3710 actid in number,
3711 funcmode in varchar2,
3712 resultout out nocopy varchar2)
3713 is
3714
3715 l_event_t wf_event_t;
3716 l_error_type varchar2(240);
3717 l_error_message varchar2(2000);
3718 l_error_stack varchar2(2000);
3719 l_parmlist_t wf_parameter_list_t;
3720
3721
3722 l_nid number;
3723 l_subject WF_NOTIFICATIONS.SUBJECT%TYPE;
3724 l_messageType WF_NOTIFICATIONS.MESSAGE_TYPE%TYPE;
3725 l_messageName WF_NOTIFICATIONS.MESSAGE_NAME%TYPE;
3726 l_recipient WF_LOCAL_ROLES.NAME%TYPE;
3727 l_recipient_dispname WF_LOCAL_ROLES.DISPLAY_NAME%TYPE;
3728 l_responder WF_LOCAL_ROLES.NAME%TYPE;
3729 l_responder_dispname WF_LOCAL_ROLES.DISPLAY_NAME%TYPE;
3730 l_error_recipient WF_LOCAL_ROLES.NAME%TYPE;
3731 l_subscription RAW(16);
3732 l_url varchar2(4000);
3733
3734
3735 begin
3736
3737 IF (funcmode = 'RUN') THEN
3738
3739 -- Get the Event Item Attribute
3740 l_event_t := WF_ENGINE.GetItemAttrEvent(itemtype => itemtype,
3741 itemkey => itemkey,
3742 name => 'EVENT_MESSAGE' );
3743
3744 -- Get the Error Type from the Item Attribute - set by Engine
3745 l_error_type := WF_ENGINE.GetItemAttrText(itemtype => itemtype,
3746 itemkey => itemkey,
3747 aname => 'ERROR_TYPE');
3748
3749 -- If the error type is null, this must be an UNEXPECTED event
3750 IF l_error_type IS NULL THEN
3751 l_error_type := 'UNEXPECTED';
3752 wf_engine.SetItemAttrText(itemtype => itemtype,
3753 itemkey => itemkey,
3754 aname => 'ERROR_TYPE',
3755 avalue => l_error_type);
3756 END IF;
3757
3758 l_error_message := substr(l_event_t.GetErrorMessage(),1,2000);
3759 IF (l_error_message is null) THEN
3760 l_error_message := wf_core.translate('NO_ERROR_MESSAGE');
3761 END IF;
3762
3763 -- Get the Error Stack
3764 l_error_stack := substr(l_event_t.GetErrorStack(),1,2000);
3765
3766 -- Get the Errored Subscription GUID
3767 l_subscription := l_event_t.GetErrorSubscription();
3768
3769 -- Generate the URL
3770 wf_event_html.GetFWKEvtSubscriptionUrl(l_subscription, l_url);
3771
3772
3773 -- Set the Item Attributes
3774
3775 wf_engine.SetItemAttrText(itemtype => itemtype,
3776 itemkey => itemkey,
3777 aname => 'ERROR_MESSAGE',
3778 avalue => l_error_message);
3779
3780 wf_engine.SetItemAttrText(itemtype => itemtype,
3781 itemkey => itemkey,
3782 aname => 'ERROR_STACK',
3783 avalue => l_error_stack);
3784
3785
3786 -- Set the Value for the Error Subscription URL
3787 wf_engine.SetItemAttrText(itemtype => itemtype,
3788 itemkey => itemkey,
3789 aname => 'EVENT_SUBSCRIPTION',
3790 avalue => l_url);
3791
3792
3793 --- Get notification id
3794 l_nid := l_event_t.getValueForParameter('NOTIFICATION_ID');
3795
3796 select message_type, message_name, subject, recipient_role, responder
3797 into l_messageType, l_messageName, l_subject, l_recipient, l_responder
3798 from wf_notifications
3799 where notification_id = l_nid;
3800
3801 l_responder_dispname := WF_DIRECTORY.GetRoleDisplayName(l_responder);
3802 l_recipient_dispname := WF_DIRECTORY.GetRoleDisplayName(l_recipient);
3803
3804 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_ID', l_nid);
3805 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_SUBJECT', l_subject);
3806 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_MSG_TYPE', l_messageType);
3807 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_MSG_NAME', l_messageName);
3808 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_RECIPIENT_ROLE', l_recipient);
3809 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_RECIPIENT_DISPNAME', l_recipient_dispname);
3810 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_RESPONDER_ROLE', l_responder);
3811 wf_engine.SetItemAttrText(itemtype, itemkey, 'PARENT_NTF_RESPONDER_DISPNAME', l_responder_dispname);
3812
3813
3814 -- Get WF Admin Role to receive error notification
3815 select text
3816 into l_error_recipient
3817 from wf_resources
3818 where name = 'WF_ADMIN_ROLE'
3819 and language = userenv('LANG');
3820
3821 -- If WF Admini Role is '*', then set the recipient as SYSADMIN
3822 if(l_error_recipient = '*') then
3823 l_error_recipient := 'SYSADMIN';
3824 end if;
3825
3826 wf_engine.SetItemAttrText(itemtype, itemkey, 'ERROR_NTF_RECIPIENT_ROLE', l_error_recipient);
3827
3828
3829 ELSIF (funcmode = 'CANCEL') THEN
3830 resultout := wf_engine.eng_completed;
3831 END IF;
3832
3833
3834 end InitializeErrorInfo;
3835
3836
3837 --
3838 -- RetryEvent
3839 -- ER 10177347: Called by the Error Process, to re-enqueue
3840 -- the notification response message into WF_NOTIFICATION_IN queue
3841 -- IN
3842 -- itemtype - item type
3843 -- itemkey - item key
3844 -- actid - process activity instance id
3845 -- funcmode - execution mode
3846 -- OUT
3847 -- result - 'NULL'
3848 procedure RetryEvent (itemtype in varchar2,
3849 itemkey in varchar2,
3850 actid in number,
3851 funcmode in varchar2,
3852 resultout out nocopy varchar2)
3853 IS
3854
3855 l_event wf_event_t;
3856 l_paramlist wf_parameter_list_t := null;
3857 l_sysName WF_SYSTEMS.NAME%TYPE := null;
3858 l_agent wf_agent_t := null ;
3859
3860
3861 begin
3862
3863 -- Get the Event Message Item Attribute
3864 l_event := wf_engine.GetItemAttrEvent(itemtype => itemtype,
3865 itemkey => itemkey,
3866 name => 'EVENT_MESSAGE' );
3867
3868 l_agent := wf_agent_t(null, null);
3869 l_agent.name := 'WF_NOTIFICATION_IN';
3870 l_agent.SYSTEM := wf_event.local_system_name;
3871
3872 -- enqueue the event message in to WF_NOTIFIOCATION_IN queue again
3873 wf_event_ojmstext_qh.enqueue( l_event, l_agent);
3874
3875
3876 EXCEPTION
3877 WHEN OTHERS THEN
3878 WF_CORE.Context('WF_STANDARD', 'RetryEvent',
3879 itemtype, itemkey, actid, funcmode);
3880 RAISE;
3881
3882 end RetryEvent;
3883
3884
3885 --
3886 -- Validate_Response
3887 -- ER 10177347: -- Post-notification function to verify whether the parent
3888 -- notification is completed when the result string is 'RESOLVED'
3889 -- IN
3890 -- itemtype - item type
3891 -- itemkey - item key
3892 -- actid - process activity instance id
3893 -- funcmode - execution mode
3894 -- OUT
3895 -- result - 'NULL'
3896 PROCEDURE Validate_Response (itemtype in varchar2,
3897 itemkey in varchar2,
3898 actid in number,
3899 funcmode in varchar2,
3900 resultout out nocopy varchar2)
3901 is
3902
3903 l_event_t wf_event_t;
3904 l_paramlist wf_parameter_list_t := null;
3905 l_nid number;
3906 l_user WF_LOCAL_ROLES.NAME%TYPE;
3907 l_itemtype WF_NOTIFICATIONS.MESSAGE_TYPE%TYPE;
3908 l_itemkey WF_NOTIFICATIONS.ITEM_KEY%TYPE;
3909 l_context WF_NOTIFICATIONS.CONTEXT%TYPE;
3910 l_actid number;
3911 l_status WF_ITEM_ACTIVITY_STATUSES.ACTIVITY_STATUS%TYPE;
3912 l_result varchar2(20);
3913 l_err_nid number;
3914
3915 wf_incomplete_ntf exception;
3916
3917
3918 begin
3919
3920
3921 if(funcmode = 'VALIDATE') then
3922
3923 l_event_t := wf_engine.GetItemAttrEvent(
3924 itemtype => itemtype,
3925 itemkey => itemkey,
3926 name => 'EVENT_MESSAGE' );
3927
3928 -- Get the parent notification id
3929 l_nid := l_event_t.getValueForParameter('NOTIFICATION_ID');
3930
3931 -- Get the error notification id from Notification_Status() API by passing itemtype, itemkey and activity id
3932 WF_ITEM_ACTIVITY_STATUS.Notification_Status(itemtype, itemkey, actid, l_err_nid, l_user);
3933
3934 l_result := Wf_Notification.GetAttrText(l_err_nid, 'RESULT');
3935
3936 -- If the result attribute value is 'RESOLVED', then get the activity status of parent notification
3937 if( l_result = 'RESOLVED') then
3938
3939 begin
3940
3941 select message_type, item_key, context
3942 into l_itemtype, l_itemkey, l_context
3943 from wf_notifications
3944 where notification_id = l_nid;
3945
3946 -- extract the activity id
3947 l_actid := to_number(SubStr(l_context, instr(l_context,':',1,2)+1));
3948 WF_ITEM_ACTIVITY_STATUS.status(l_itemtype, l_itemkey, l_actid, l_status);
3949
3950 exception
3951 when others then
3952 SELECT activity_status into l_status FROM wf_item_activity_statuses WHERE notification_id = l_nid;
3953 end;
3954
3955 -- close the error notification only if the parent notification activity is complete,
3956 -- otherwise raise the WFNTF_NOT_COMPLETE error on screen
3957 if(l_status = 'COMPLETE') then
3958 resultout := wf_engine.eng_completed;
3959 else
3960 raise wf_incomplete_ntf;
3961 end if;
3962
3963 end if;
3964
3965 end if;
3966
3967
3968 EXCEPTION
3969 WHEN wf_incomplete_ntf THEN
3970 WF_CORE.Context('WF_STANDARD', 'VALIDATE_RESPONSE',
3971 itemtype, itemkey, actid, funcmode);
3972 wf_core.clear;
3973 Wf_Core.Token('NID', l_nid);
3974 Wf_Core.Raise('WFNTF_NOT_COMPLETE');
3975
3976 WHEN OTHERS THEN
3977 WF_CORE.Context('WF_STANDARD', 'VALIDATE_RESPONSE',
3978 itemtype, itemkey, actid, funcmode);
3979 RAISE;
3980
3981
3982 end VALIDATE_RESPONSE;
3983
3984
3985 END WF_STANDARD;