1 package body WF_PROCESS_ACTIVITY as
2 /* $Header: wfengb.pls 120.38.12020000.3 2012/11/13 19:42:45 alsosa ship $ */
3
4 type InstanceArrayTyp is table of pls_integer
5 index by binary_integer;
6
7 --
8 -- RootInstanceId
9 -- Globals to cache RootInstanceId result for effeciency
10 --
11 c_itemtype varchar2(8);
12 c_itemkey varchar2(240);
13 c_process varchar2(30);
14 c_rootid pls_integer;
15
16 --
17 -- ClearCache
18 -- Clear runtime cache
19 --
20 procedure ClearCache
21 is
22 begin
23 wf_process_activity.c_itemtype := '';
24 wf_process_activity.c_itemkey := '';
25 wf_process_activity.c_process := '';
26 wf_process_activity.c_rootid := '';
27 exception
28 when others then
29 Wf_Core.Context('Wf_Process_Activity', 'ClearCache');
30 raise;
31 end ClearCache;
32
33 --
34 -- RootInstanceId (PRIVATE)
35 -- Return the instance id for the process activity under the given item
36 -- type. If there is no row found, returns null.
37 -- NOTE
38 -- This function only returns the 'ROOT' row for a process in
39 -- WF_PROCESS_ACTIVITIES. It assumes there will be exactly 1 row
40 -- looking like:
41 -- PROCESS_ITEM_TYPE = itemtype
42 -- PROCESS_NAME = 'ROOT'
43 -- PROCESS_VERSION = version
44 -- INSTANCE_LABEL = process
45 -- for each process in WF_PROCESS_ACTIVITIES.
46 -- IN
47 -- itemtype - Item type of process
48 -- itemkey - Item key
49 -- process - Process name
50 --
51 function RootInstanceId(itemtype in varchar2,
52 itemkey in varchar2,
53 process in varchar2)
54 return number is
55 actdate date;
56 instid pls_integer;
57 begin
58 -- Check cache for a valid value
59 if ((itemtype = wf_process_activity.c_itemtype) and
60 (itemkey = wf_process_activity.c_itemkey) and
61 (process = wf_process_activity.c_process)) then
62 return(wf_process_activity.c_rootid);
63 end if;
64
65 -- No joy. Select a new value.
66 actdate := Wf_Item.Active_Date(itemtype, itemkey);
67
68 select INSTANCE_ID
69 into instid
70 from WF_PROCESS_ACTIVITIES PA, WF_ACTIVITIES A
71 where A.ITEM_TYPE = itemtype
72 and A.NAME = 'ROOT'
73 and actdate >= A.BEGIN_DATE
74 and actdate < NVL(A.END_DATE, actdate+1)
75 and PA.PROCESS_NAME = 'ROOT'
76 and PA.PROCESS_ITEM_TYPE = itemtype
77 and PA.PROCESS_VERSION = A.VERSION
78 and PA.INSTANCE_LABEL = process;
79
80 -- Save value to cache
81 wf_process_activity.c_itemtype := itemtype;
82 wf_process_activity.c_itemkey := itemkey;
83 wf_process_activity.c_process := process;
84 wf_process_activity.c_rootid := instid;
85
86 return instid;
87
88 exception
89 when NO_DATA_FOUND then
90 return '';
91 when OTHERS then
92 Wf_Core.Context('Wf_Process_Activity', 'RootInstanceId', itemtype,
93 itemkey, process);
94 raise;
95 end RootInstanceId;
96
97 --
98 -- ActivityName
99 -- Return the activity type and name, given instance id
100 -- IN
101 -- actid - instance id
102 -- OUT
103 -- act_itemtype - activity itemtype
104 -- act_name - activity name
105 --
106 procedure ActivityName(
107 actid in number,
108 act_itemtype out NOCOPY varchar2,
109 act_name out NOCOPY varchar2)
110 is
111 status PLS_INTEGER;
112
113 begin
114 WF_CACHE.GetProcessActivity(actid, status);
115
116 if (status <> WF_CACHE.task_SUCCESS) then
117
118 select WPA.PROCESS_ITEM_TYPE, WPA.PROCESS_NAME, WPA.PROCESS_VERSION,
119 WPA.ACTIVITY_ITEM_TYPE, WPA.ACTIVITY_NAME, WPA.INSTANCE_ID,
120 WPA.INSTANCE_LABEL, WPA.PERFORM_ROLE, WPA.PERFORM_ROLE_TYPE,
121 WPA.START_END, WPA.DEFAULT_RESULT
122 into WF_CACHE.ProcessActivities(actid)
123 from WF_PROCESS_ACTIVITIES WPA
124 where WPA.INSTANCE_ID = actid;
125
126 end if;
127
128 act_itemtype := WF_CACHE.ProcessActivities(actid).ACTIVITY_ITEM_TYPE;
129 act_name := WF_CACHE.ProcessActivities(actid).ACTIVITY_NAME;
130
131 exception
132 when no_data_found then
133 Wf_Core.Token('ACTID', to_char(actid));
134 Wf_Core.Token('DATE', '');
135 Wf_Core.Raise('WFENG_ACTID');
136 when others then
137 Wf_Core.Context('Wf_Process_Activity', 'ActivityName', to_char(actid));
138 raise;
139 end ActivityName;
140
141 --
142 -- StartInstanceId (PRIVATE)
143 -- Returns instance_id for a start activity, given root process
144 -- name, itemtype, and version.
145 -- IN
146 -- itemtype - Itemtype of process
147 -- process - Process name
148 -- version - Process version
149 -- activity - Start activity instance label
150 --
151 function StartInstanceId(itemtype in varchar2,
152 process in varchar2,
153 version in number,
154 activity in varchar2)
155 return number
156 is
157 instid pls_integer;
158 colon pls_integer;
159 label varchar2(30);
160 begin
161 -- Parse activity arg into <process_name> and <instance_label> components.
162 colon := instr(activity, ':');
163 if (colon <> 0) then
164 -- Activity arg is <process name>:<instance label>
165 label := substr(activity, colon+1);
166 else
167 -- Activity arg is just instance label
168 label := activity;
169 end if;
170
171 select
172 WPA.INSTANCE_ID
173 into instid
174 from WF_PROCESS_ACTIVITIES WPA
175 where WPA.INSTANCE_LABEL = StartInstanceId.label
176 and WPA.PROCESS_ITEM_TYPE = StartInstanceId.itemtype
177 and WPA.PROCESS_NAME = StartInstanceId.process
178 and WPA.PROCESS_VERSION = StartInstanceId.version
179 and WPA.START_END = wf_engine.eng_start;
180
181 return instid;
182 exception
183 when no_data_found then
184 Wf_Core.Context('Wf_Process_Activity', 'StartInstanceId', itemtype,
185 process, to_char(version), activity);
186 Wf_Core.Token('TYPE', itemtype);
187 Wf_Core.Token('PROCESS', process);
188 Wf_Core.Token('NAME', activity);
189 Wf_Core.Raise('WFENG_NOT_START');
190 when too_many_rows then
191 Wf_Core.Context('Wf_Process_Activity', 'StartInstanceId', itemtype,
192 process, to_char(version), activity);
193 Wf_Core.Token('TYPE', itemtype);
194 Wf_Core.Token('PROCESS', process);
195 Wf_Core.Token('NAME', activity);
196 Wf_Core.Raise('WFENG_ACTIVITY_UNIQUE');
197 when others then
198 Wf_Core.Context('Wf_Process_Activity', 'StartInstanceId', itemtype,
199 process, to_char(version), activity);
200 raise;
201 end StartInstanceId;
202
203 --
204 -- ActiveInstanceId (PRIVATE)
205 -- Returns instance_id for an active instance of an activity.
206 -- NOTE
207 -- This is a more efficient version of FindActivity, to be used whenever
208 -- the current status the activity must have is already known.
209 -- It is also able to distinguish between duplicate activities, where
210 -- only one may be active at a given time.
211 -- IN
212 -- itemtype - Itemtype of item
213 -- itemkey - Itemkey of item
214 -- activity - Activity searching for, specified in the form
215 -- [<process_name>:]<instance_label>
216 -- status - Status of activity, or null if status not known
217 -- RETURNS
218 -- Instance id of activity
219 --
220 function ActiveInstanceId(itemtype in varchar2,
221 itemkey in varchar2,
222 activity in varchar2,
223 status in varchar2)
224 return number
225 is
226 colon pls_integer;
227 process varchar2(30);
228 label varchar2(30);
229 instid pls_integer;
230 cur_actid pls_integer;
231 cur_status varchar2(8);
232 cur_result varchar2(30);
233 begin
234 -- Parse activity arg into <process_name> and <instance_label> components.
235 colon := instr(activity, ':');
236 if (colon <> 0) then
237 -- Activity arg is <process name>:<instance label>
238 process := substr(activity, 1, colon-1);
239 label := substr(activity, colon+1);
240 else
241 -- Activity arg is just instance label
242 process := '';
243 label := activity;
244 end if;
245
246 -- SYNCHMODE:
247 -- In synchmode, the row in the WIAS runtime cache MUST be this row,
248 -- because synch processes can only operate on the current activity.
249 --
250 if (itemkey = wf_engine.eng_synch) then
251 -- Get the current item and status in the cache
252 Wf_Item_Activity_Status.LastResult(itemtype, itemkey,
253 cur_actid, cur_status, cur_result);
254
255 -- If status doesn't match one asked for, immediate trouble
256 if (nvl(status, '1') <> nvl(cur_status, '2')) then
257 raise no_data_found;
258 end if;
259
260 -- Check that activity label passed in matched the current actid
261 select WPA.INSTANCE_ID
262 into instid
263 from WF_PROCESS_ACTIVITIES WPA
264 where WPA.INSTANCE_LABEL = activeinstanceid.label
265 and WPA.PROCESS_NAME = nvl(activeinstanceid.process, WPA.PROCESS_NAME)
266 and WPA.INSTANCE_ID = activeinstanceid.cur_actid;
267 else
268 -- NORMAL mode
269 select WPA.INSTANCE_ID
270 into instid
271 from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA
272 where WIAS.ITEM_TYPE = activeinstanceid.itemtype
273 and WIAS.ITEM_KEY = activeinstanceid.itemkey
274 and WIAS.ACTIVITY_STATUS = nvl(activeinstanceid.status,
275 WIAS.ACTIVITY_STATUS)
276 and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
277 and WPA.INSTANCE_LABEL = activeinstanceid.label
278 and WPA.PROCESS_NAME = nvl(activeinstanceid.process, WPA.PROCESS_NAME);
279 end if;
280
281 return instid;
282 exception
283 when no_data_found then
284 return '';
285 when too_many_rows then
286 Wf_Core.Context('Wf_Process_Activity', 'ActiveInstanceId', itemtype,
287 itemkey, activity, status);
288 Wf_Core.Token('TYPE', itemtype);
289 Wf_Core.Token('KEY', itemkey);
290 Wf_Core.Token('NAME', activity);
291 Wf_Core.Raise('WFENG_ITEM_ACTIVITY_UNIQUE');
292 when others then
293 Wf_Core.Context('Wf_Process_Activity', 'ActiveInstanceId', itemtype,
294 itemkey, activity, status);
295 raise;
296 end ActiveInstanceId;
297
298 --
299 -- IsChild (PRIVATE)
300 -- Search for any occurrence of an activity in a process tree, either
301 -- as a direct child, or referenced in an error process attached to a
302 -- child.
303 -- This function does a recursive search of the tree. It should only be
304 -- used if:
305 -- 1. There may not be an entry in WIAS yet for this activity.
306 -- 2. You do not know the immediate parent of the activity.
307 -- IN
308 -- rootid - The instance_id of the parent process
309 -- acttype - Activity itemtype searching for
310 -- actname - Activity name searching for
311 -- actdate - Active date
312 -- RETURNS
313 -- True is activity found anywhere in process tree.
314 --
315 function IsChild(
316 rootid in number,
317 acttype in varchar2,
318 actname in varchar2,
319 actdate in date)
320 return boolean
321 is
322 cursor curs(parentid in pls_integer, actdate in date) is
323 select WPA2.INSTANCE_ID, WPA2.ACTIVITY_ITEM_TYPE, WPA2.ACTIVITY_NAME
324 from WF_PROCESS_ACTIVITIES WPA1,
325 WF_ACTIVITIES WA,
326 WF_PROCESS_ACTIVITIES WPA2
327 where WPA1.INSTANCE_ID = parentid
328 and WPA2.PROCESS_ITEM_TYPE = WA.ITEM_TYPE
329 and WPA2.PROCESS_NAME = WA.NAME
330 and WA.ITEM_TYPE = WPA1.ACTIVITY_ITEM_TYPE
331 and WA.NAME = WPA1.ACTIVITY_NAME
332 and actdate >= WA.BEGIN_DATE
333 and actdate < NVL(WA.END_DATE, actdate+1)
334 and WPA2.PROCESS_VERSION = WA.VERSION;
335
336 childarr InstanceArrayTyp;
337 i pls_integer := 0;
338 errid pls_integer;
339
340 found boolean;
341
342 status PLS_INTEGER;
343 waIND NUMBER;
344
345 begin
346 WF_CACHE.GetProcessActivityInfo(rootid, actdate, status, waIND);
347
348 if (status <> WF_CACHE.task_SUCCESS) then
349 waIND := 0;
350
351 select WA.ITEM_TYPE, WA.NAME, WA.VERSION, WA.TYPE, WA.RERUN,
352 WA.EXPAND_ROLE, WA.COST, WA.ERROR_ITEM_TYPE, WA.ERROR_PROCESS,
353 WA.FUNCTION, WA.FUNCTION_TYPE, WA.MESSAGE, WA.BEGIN_DATE,
354 WA.END_DATE, WA.DIRECTION, WPA.PROCESS_ITEM_TYPE,
355 WPA.PROCESS_NAME, WPA.PROCESS_VERSION, WPA.ACTIVITY_ITEM_TYPE,
356 WPA.ACTIVITY_NAME, WPA.INSTANCE_ID, WPA.INSTANCE_LABEL,
357 WPA.PERFORM_ROLE, WPA.PERFORM_ROLE_TYPE, WPA.START_END,
358 WPA.DEFAULT_RESULT
359
360 into WF_CACHE.Activities(waIND).ITEM_TYPE,
361 WF_CACHE.Activities(waIND).NAME,
362 WF_CACHE.Activities(waIND).VERSION,
363 WF_CACHE.Activities(waIND).TYPE,
364 WF_CACHE.Activities(waIND).RERUN,
365 WF_CACHE.Activities(waIND).EXPAND_ROLE,
366 WF_CACHE.Activities(waIND).COST,
367 WF_CACHE.Activities(waIND).ERROR_ITEM_TYPE,
368 WF_CACHE.Activities(waIND).ERROR_PROCESS,
369 WF_CACHE.Activities(waIND).FUNCTION,
370 WF_CACHE.Activities(waIND).FUNCTION_TYPE,
371 WF_CACHE.Activities(waIND).MESSAGE,
372 WF_CACHE.Activities(waIND).BEGIN_DATE,
373 WF_CACHE.Activities(waIND).END_DATE,
374 WF_CACHE.Activities(waIND).DIRECTION,
375 WF_CACHE.ProcessActivities(rootid).PROCESS_ITEM_TYPE,
376 WF_CACHE.ProcessActivities(rootid).PROCESS_NAME,
377 WF_CACHE.ProcessActivities(rootid).PROCESS_VERSION,
378 WF_CACHE.ProcessActivities(rootid).ACTIVITY_ITEM_TYPE,
379 WF_CACHE.ProcessActivities(rootid).ACTIVITY_NAME,
380 WF_CACHE.ProcessActivities(rootid).INSTANCE_ID,
381 WF_CACHE.ProcessActivities(rootid).INSTANCE_LABEL,
382 WF_CACHE.ProcessActivities(rootid).PERFORM_ROLE,
383 WF_CACHE.ProcessActivities(rootid).PERFORM_ROLE_TYPE,
384 WF_CACHE.ProcessActivities(rootid).START_END,
385 WF_CACHE.ProcessActivities(rootid).DEFAULT_RESULT
386
387 from WF_PROCESS_ACTIVITIES WPA, WF_ACTIVITIES WA
388
389 where WPA.INSTANCE_ID = rootid
390 and WA.ITEM_TYPE = WPA.ACTIVITY_ITEM_TYPE
391 and WA.NAME = WPA.ACTIVITY_NAME
392 and actdate >= WA.BEGIN_DATE
393 and actdate < NVL(WA.END_DATE, actdate+1);
394
395 waIND := WF_CACHE.HashKey(
396 WF_CACHE.ProcessActivities(rootid).ACTIVITY_ITEM_TYPE ||
397 WF_CACHE.ProcessActivities(rootid).ACTIVITY_NAME);
398
399 WF_CACHE.Activities(waIND) := WF_CACHE.Activities(0);
400
401 end if;
402
403
404 -- Quick check to see if root is already right
405 if (((WF_CACHE.ProcessActivities(rootid).PROCESS_ITEM_TYPE = acttype) and
406 (WF_CACHE.ProcessActivities(rootid).PROCESS_NAME = actname)) or
407 ((WF_CACHE.Activities(waIND).ITEM_TYPE = acttype) and
408 (WF_CACHE.Activities(waIND).NAME = actname))) then
409 return(TRUE);
410 end if;
411
412 -- If activity at rootid has an error process, check it recursively
413 -- for a reference to the activity.
414 if (WF_CACHE.Activities(waIND).ERROR_PROCESS is not null) then
415 -- Get root id for the error process
416 begin
417 select WPA.INSTANCE_ID
418 into errid
419 from WF_PROCESS_ACTIVITIES WPA, WF_ACTIVITIES WA
420 where WPA.PROCESS_ITEM_TYPE = WF_CACHE.Activities(waIND).ERROR_ITEM_TYPE
421 and WPA.PROCESS_NAME = 'ROOT'
422 and WPA.PROCESS_VERSION = WA.VERSION
423 and WA.ITEM_TYPE = WPA.PROCESS_ITEM_TYPE
424 and WA.NAME = WPA.PROCESS_NAME
425 and actdate >= WA.BEGIN_DATE
426 and actdate < NVL(WA.END_DATE, actdate+1)
427 and WPA.INSTANCE_LABEL = WF_CACHE.Activities(waIND).ERROR_PROCESS;
428 exception
429 when no_data_found then
430 -- Error process is invalid, so ignore it
431 errid := '';
432 end;
433
434 if (errid is not null) then
435 -- If activity found in error process return immediately.
436 -- If not, continue on to check proper children of rootid.
437 if (IsChild(errid, acttype, actname, actdate)) then
438 return(TRUE);
439 end if;
440 end if;
441 end if;
442
443 -- Check all children of rootid
444 for child in curs(rootid, actdate) loop
445 -- Desired activity found. Return immediately.
446 if ((child.activity_item_type = acttype) and
447 (child.activity_name = actname)) then
448 return(TRUE);
449 end if;
450
451 -- Save all other children in array to be checked
452 childarr(i) := child.instance_id;
453 i := i + 1;
454 end loop;
455 childarr(i) := '';
456
457 -- Loop through and recursively search any PROCESS-type children.
458 i := 0;
459 while (childarr(i) is not null) loop
460 if (Wf_Activity.Instance_Type(childarr(i), actdate) =
461 wf_engine.eng_process) then
462 found := IsChild(childarr(i), acttype, actname, actdate);
463
464 -- If a non-null value is returned, then the activity was
465 -- found in this sub-tree. Return the value and exit immediately.
466 if (found) then
467 return(TRUE);
468 end if;
469 end if;
470 i := i + 1;
471 end loop;
472
473 -- If you made it here the activity was not found anywhere in the tree.
474 return(FALSE);
475 exception
476 when OTHERS then
477 Wf_Core.Context('Wf_Process_Activity', 'IsChild', to_char(rootid),
478 acttype, actname, to_char(actdate));
479 raise;
480 end IsChild;
481
482 --
483 -- FindActivity (PRIVATE)
484 -- Find the instance_id of an activity instance in the tree rooted at
485 -- parentid in the WPA table.
486 -- This function does a recursive search of the tree. It should only be
487 -- used if:
488 -- 1. There may not be an entry in WIAS yet for this activity instance.
489 -- (See ActiveInstanceId above)
490 -- 2. You do not know the immediate parent of the activity.
491 -- IN
492 -- parentid - The instance_id of the parent process.
493 -- activity - Activity searching for, specified in the form
494 -- [<process_name>:]<instance_label>
495 -- actdate - Active date
496 -- RETURNS
497 -- Instance id of activity instance in process tree rooted at parentid.
498 -- Returns null if not found.
499 --
500 function FindActivity(parentid in number,
501 activity in varchar2,
502 actdate in date)
503 return number
504 is
505 colon pls_integer;
506 process varchar2(30);
507 label varchar2(30);
508
509 status PLS_INTEGER;
510
511 cursor curs(parentid in pls_integer, actdate in date) is
512 select WPA2.PROCESS_NAME, WPA2.INSTANCE_ID, WPA2.INSTANCE_LABEL
513 from WF_PROCESS_ACTIVITIES WPA1,
514 WF_ACTIVITIES WA,
515 WF_PROCESS_ACTIVITIES WPA2
516 where WPA1.INSTANCE_ID = parentid
517 and WPA2.PROCESS_ITEM_TYPE = WA.ITEM_TYPE
518 and WPA2.PROCESS_NAME = WA.NAME
519 and WA.ITEM_TYPE = WPA1.ACTIVITY_ITEM_TYPE
520 and WA.NAME = WPA1.ACTIVITY_NAME
521 and actdate >= WA.BEGIN_DATE
522 and actdate < NVL(WA.END_DATE, actdate+1)
523 and WPA2.PROCESS_VERSION = WA.VERSION;
524
525 childarr InstanceArrayTyp;
526 i pls_integer := 0;
527
528 childid pls_integer;
529 actid pls_integer := '';
530 wf_dup_activity exception;
531 begin
532 -- Parse activity arg into <process_name> and <instance_label> components.
533 colon := instr(activity, ':');
534 if (colon <> 0) then
535 -- Activity arg is <process name>:<instance label>
536 process := substr(activity, 1, colon-1);
537 label := substr(activity, colon+1);
538 else
539 -- Activity arg is just instance label
540 process := '';
541 label := activity;
542 end if;
543
544 WF_CACHE.GetProcessActivity(parentid, status);
545
546 if (status <> WF_CACHE.task_SUCCESS) then
547
548 select WPA.PROCESS_ITEM_TYPE, WPA.PROCESS_NAME, WPA.PROCESS_VERSION,
549 WPA.ACTIVITY_ITEM_TYPE, WPA.ACTIVITY_NAME, WPA.INSTANCE_ID,
550 WPA.INSTANCE_LABEL, WPA.PERFORM_ROLE, WPA.PERFORM_ROLE_TYPE,
551 WPA.START_END, WPA.DEFAULT_RESULT
552 into WF_CACHE.ProcessActivities(parentid)
553 from WF_PROCESS_ACTIVITIES WPA
554 where WPA.INSTANCE_ID = parentid;
555
556 end if;
557
558 if ((WF_CACHE.ProcessActivities(parentid).PROCESS_NAME =
559 nvl(process, WF_CACHE.ProcessActivities(parentid).PROCESS_NAME)) and
560 (WF_CACHE.ProcessActivities(parentid).INSTANCE_LABEL = label)) then
561 return(parentid);
562 end if;
563
564 for child in curs(parentid, actdate) loop
565 -- Activity with this name found.
566 if ((child.process_name = nvl(process, child.process_name)) and
567 (child.instance_label = label)) then
568 if ((actid is not null) and (actid <> child.instance_id)) then
569 -- Activity already found once in this process - raise duplicate error.
570 raise wf_dup_activity;
571 else
572 -- Save id of activity
573 actid := child.instance_id;
574 end if;
575 end if;
576
577 -- Save all other children in array to be checked
578 childarr(i) := child.instance_id;
579 i := i + 1;
580 end loop;
581 childarr(i) := '';
582
583 -- Loop through and recursively search any PROCESS-type children.
584 i := 0;
585 while (childarr(i) is not null) loop
586 if (Wf_Activity.Instance_Type(childarr(i), actdate) =
587 wf_engine.eng_process) then
588 childid := FindActivity(childarr(i), activity, actdate);
589
590 -- If a non-null value is returned, then the activity was
591 -- found somewhere in this sub-tree.
592 if (childid is not null) then
593 if ((actid is not null) and (actid <> childid)) then
594 -- Activity already found somewhere else. Raise error.
595 raise wf_dup_activity;
596 else
597 -- Save id of activity
598 actid := childid;
599 end if;
600 end if;
601 end if;
602 i := i + 1;
603 end loop;
604
605 -- Return saved actid. If activity not found anywhere in tree this
606 -- will still be null.
607 return(actid);
608 exception
609 when wf_dup_activity then
610 Wf_Core.Context('Wf_Process_Activity', 'FindActivity', to_char(parentid),
611 activity, to_char(actdate));
612 Wf_Core.Token('NAME', activity);
613 Wf_Core.Raise('WFENG_ACTIVITY_UNIQUE');
614 when OTHERS then
615 Wf_Core.Context('Wf_Process_Activity', 'FindActivity', to_char(parentid),
616 activity, to_char(actdate));
617 raise;
618 end FindActivity;
619
620 end WF_PROCESS_ACTIVITY;