DBA Data[Home] [Help]

PACKAGE BODY: APPS.WF_STANDARD

Source


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