1 package body WF_ITEM as
2 /* $Header: wfengb.pls 120.25.12010000.3 2008/10/28 15:19:48 alepe ship $ */
3
4 c_itemtype varchar2(8);
5 c_itemkey varchar2(240);
6
7 c_ondemand boolean;
8
9 c_root_activity varchar2(30);
10 c_root_activity_version pls_integer;
11 c_begin_date date;
12 c_userkey varchar2(240);
13
14 --
15 -- ClearCache
16 -- Clear runtime cache
17 --
18 procedure ClearCache
19 is
20 begin
21 wf_item.c_itemtype := '';
22 wf_item.c_itemkey := '';
23 wf_item.c_root_activity := '';
24 wf_item.c_root_activity_version := '';
25 wf_item.c_begin_date := to_date(NULL);
26 wf_item.c_userkey := '';
27
28 --clear ondemand flag
29 wf_item.c_ondemand := null;
30 -- Clear the synch attribute cache too
31 wf_engine.synch_attr_count := 0;
32
33 exception
34 when others then
35 Wf_Core.Context('Wf_Item', 'ClearCache');
36 raise;
37 end ClearCache;
38
39 --
40 -- InitCache (PRIVATE)
41 -- Initialize package cache
42 -- IN
43 -- itemtype - Item type
44 -- itemkey - Item key
45 --
46 procedure InitCache(
47 itemtype in varchar2,
48 itemkey in varchar2,
49 ignore_notfound in boolean default FALSE)
50
51 is
52 rootid number;
53 status varchar2(8);
54 onDemandFlag wf_activity_attributes.text_default%type;
55 begin
56 -- Check for refresh
57 if ((itemtype = wf_item.c_itemtype) and
58 (itemkey = wf_item.c_itemkey)) then
59 return;
60 end if;
61
62 -- SYNCHMODE: If
63 -- 1. Asking for an item other than the cached one AND
64 -- 2. The cached item is a synch process AND
65 -- 3. The cached item has not yet completed
66 -- then raise an error. Other items cannot be accessed until synch
67 -- item completes, because it can't be restarted from db
68 if (wf_item.c_itemkey = wf_engine.eng_synch) then
69 -- Get status of root process of cached item
70 -- Note: If process completed successfully, the last thing in the
71 -- WIAS runtime cache should be the root process, which is the
72 -- only reason this will work.
73 begin
74 rootid := Wf_Process_Activity.RootInstanceId(c_itemtype, c_itemkey,
75 c_root_activity);
76 Wf_Item_Activity_Status.Status(c_itemtype, c_itemkey, rootid, status);
77 exception
78 when others then
79 status := 'x'; -- Treat errors like incomplete process
80 end;
81 if (nvl(status, 'x') <> wf_engine.eng_completed) then
82 Wf_Core.Token('ITEMTYPE', itemtype);
83 Wf_Core.Token('ITEMKEY', itemkey);
84 Wf_Core.Raise('WFENG_SYNCH_ITEM');
85 end if;
86 end if;
87
88 -- Query new values
89 select WI.ROOT_ACTIVITY, WI.ROOT_ACTIVITY_VERSION, WI.BEGIN_DATE,
90 WI.USER_KEY
91 into wf_item.c_root_activity, wf_item.c_root_activity_version,
92 wf_item.c_begin_date, wf_item.c_userkey
93 from WF_ITEMS WI
94 where WI.ITEM_TYPE = InitCache.itemtype
95 and WI.ITEM_KEY = InitCache.itemkey;
96
97 -- Save cache key values
98 wf_item.c_itemtype := itemtype;
99 wf_item.c_itemkey := itemkey;
100
101 --cache ondemand flag
102 -- this could potentially have some impact on the performance as this
103 -- routine is called many times while we are dealing with design time data.
104 -- ondemand is true if the name process #ONDEMANDATTR attribute exist,
105 -- otherwise, it is false.
106 --
107 begin
108 select text_default into onDemandFlag from wf_activity_attributes
109 where activity_item_type = c_itemtype
110 and activity_name = c_root_activity
111 and activity_version=c_root_activity_version
112 and name = '#ONDEMANDATTR';
113
114 wf_item.c_ondemand := true;
115 exception
116 when no_data_found then
117 wf_item.c_ondemand := false;
118 end;
119
120
121
122 exception
123 when NO_DATA_FOUND then
124 if (ignore_notfound) then
125 WF_ITEM.ClearCache;
126
127 else
128
129 Wf_Core.Context('Wf_Item', 'InitCache', itemtype, itemkey);
130 raise;
131
132 end if;
133
134 when others then
135 Wf_Core.Context('Wf_Item', 'InitCache', itemtype, itemkey);
136 raise;
137 end InitCache;
138
139 --
140 -- Attribute_On_Demand
141 -- Set parent ids of an item
142 -- IN
143 -- itemtype - Item type
144 -- itemkey - Item key
145 -- Initialize cache if not already done then return c_ondemand;
146 --
147
148 function Attribute_On_Demand(
149 itemtype in varchar2,
150 itemkey in varchar2
151 ) return boolean
152 as
153 begin
154 --
155 --we need to call in case itemtype and itemkey are not in synch with
156 --cached value.
157 --
158 Wf_Item.InitCache(itemtype, itemkey, ignore_notfound=>TRUE);
159 return c_ondemand;
160 end Attribute_On_Demand;
161
162 --
163 -- Set_Item_Parent
164 -- Set parent ids of an item
165 -- IN
166 -- itemtype - Item type
167 -- itemkey - Item key
168 -- parent_itemtype - Itemtype of parent
169 -- parent_itemkey - Itemkey of parent
170 -- parent_context - Context info about parent
171 --
172 procedure Set_Item_Parent(itemtype in varchar2,
173 itemkey in varchar2,
174 parent_itemtype in varchar2,
175 parent_itemkey in varchar2,
176 parent_context in varchar2,
177 masterdetail in boolean)
178 is
179 ValTooLarge EXCEPTION;
180 pragma exception_init(ValTooLarge, -01401);
181
182 begin
183 update WF_ITEMS set
184 PARENT_ITEM_TYPE = Set_Item_Parent.parent_itemtype,
185 PARENT_ITEM_KEY = Set_Item_Parent.parent_itemkey,
186 PARENT_CONTEXT = Set_Item_Parent.parent_context
187 where ITEM_TYPE = Set_Item_Parent.itemtype
188 and ITEM_KEY = Set_Item_Parent.itemkey;
189
190 if (sql%notfound) then
191 raise no_data_found;
192 end if;
193
194 if (masterdetail) then
195 --Increment #WAITFORDETAIL master counter if it exists.
196 if (WF_ENGINE.AddToItemAttrNumber(parent_itemType, parent_itemKey,
197 '#WAITFORDETAIL', 1) is NOT NULL) then
198 if (parent_context is NOT null) then
199 --Increment/Create label counter.
200 if (length(parent_context) > 25) then
201 WF_CORE.Token('LABEL', parent_context);
202 WF_CORE.Token('LENGTH', '25');
203 WF_CORE.Raise('WFENG_LABEL_TOO_LARGE');
204
205 elsif (WF_ENGINE.AddToItemAttrNumber(parent_itemType, parent_itemKey,
206 '#CNT_'||parent_context, 1)
207 is NULL) then
208 WF_ENGINE.AddItemAttr(itemType=>parent_itemType,
209 itemKey=>parent_itemKey,
210 aname=>'#CNT_'||parent_context,
211 number_value=>1);
212 end if; --Label Counter exists
213
214 WF_ENGINE.AddItemAttr(itemType=>itemType, itemKey=>itemKey,
215 aname=>'#LBL_'||parent_context,
216 text_value=>parent_context);
217
218 else
219 -- Parent context is null
220 -- increase all known #CNT counter by 1
221 update WF_ITEM_ATTRIBUTE_VALUES
222 set NUMBER_VALUE = NUMBER_VALUE + 1
223 where NAME like '#CNT_%'
224 and NUMBER_VALUE is not null
225 and ITEM_TYPE = parent_itemType
226 and ITEM_KEY = parent_itemKey;
227
228 end if; --Parent context is not null
229 end if; --#WAITFORDETAIL exists
230 end if; --Caller is signalling that this "should" be a coordinated flow.
231
232 exception
233 when no_data_found then
234 Wf_Core.Context('Wf_Item', 'Set_Item_Parent', itemtype, itemkey,
235 parent_itemtype, parent_itemkey, parent_context);
236 Wf_Core.Token('TYPE', itemtype);
237 Wf_Core.Token('KEY', itemkey);
238 Wf_Core.Raise('WFENG_ITEM');
239
240 when ValTooLarge then
241 Wf_Core.Context('Wf_Item', 'Set_Item_Parent', itemtype, itemkey,
242 parent_itemtype, parent_itemkey, parent_context, 'TRUE');
243 WF_CORE.Token('LABEL', parent_context);
244 WF_CORE.Token('LENGTH', 25);
245 WF_CORE.Raise('WFENG_LABEL_TOO_LARGE');
246
247 when others then
248 Wf_Core.Context('Wf_Item', 'Set_Item_Parent', itemtype, itemkey,
249 parent_itemtype, parent_itemkey, parent_context);
250 raise;
251 end Set_Item_Parent;
252
253 --
254 -- SetItemOwner
255 -- Set the owner of an item
256 -- IN
257 -- itemtype - Item type
258 -- itemkey - Item key
259 -- owner - Role designated as owner of the item
260 --
261 procedure SetItemOwner(
262 itemtype in varchar2,
263 itemkey in varchar2,
264 owner in varchar2)
265 is
266 begin
267
268 -- Update owner column
269 update WF_ITEMS WI set
270 OWNER_ROLE = SetItemOwner.owner
271 where WI.ITEM_TYPE = SetItemOwner.itemtype
272 and WI.ITEM_KEY = SetItemOwner.itemkey;
273
274 if (sql%notfound) then
275 raise no_data_found;
276 end if;
277 exception
278 when no_data_found then
279 Wf_Core.Context('Wf_Item', 'SetItemOwner', itemtype, itemkey,
280 owner);
281 Wf_Core.Token('TYPE', itemtype);
282 Wf_Core.Token('KEY', itemkey);
283 Wf_Core.Raise('WFENG_ITEM');
284 when others then
285 Wf_Core.Context('Wf_Item', 'SetItemOwner', itemtype, itemkey,
286 owner);
287 raise;
288 end SetItemOwner;
289
290 --
291 -- SetItemUserKey
292 -- Set the user key of an item
293 -- IN
294 -- itemtype - Item type
295 -- itemkey - Item key
296 -- userkey - User key to be set
297 --
298 procedure SetItemUserKey(
299 itemtype in varchar2,
300 itemkey in varchar2,
301 userkey in varchar2)
302 is
303 begin
304 update WF_ITEMS WI set
305 USER_KEY = SetItemUserKey.userkey
306 where WI.ITEM_TYPE = SetItemUserKey.itemtype
307 and WI.ITEM_KEY = SetItemUserKey.itemkey;
308
309 if (sql%notfound) then
310 raise no_data_found;
311 end if;
312
313 -- Set value in the local cache the right item
314 if ((itemtype = wf_item.c_itemtype) and
315 (itemkey = wf_item.c_itemkey)) then
316 wf_item.c_userkey := userkey;
317 end if;
318 exception
319 when no_data_found then
320 Wf_Core.Context('Wf_Item', 'SetItemUserKey', itemtype, itemkey,
321 userkey);
322 Wf_Core.Token('TYPE', itemtype);
323 Wf_Core.Token('KEY', itemkey);
324 Wf_Core.Raise('WFENG_ITEM');
325 when others then
326 Wf_Core.Context('Wf_Item', 'SetItemUserKey', itemtype, itemkey,
327 userkey);
328 raise;
329 end SetItemUserKey;
330
331 --
332 -- GetItemUserKey
333 -- Get the user key of an item
334 -- IN
335 -- itemtype - Item type
336 -- itemkey - Item key
337 -- RETURNS
338 -- User key of the item
339 --
340 function GetItemUserKey(
341 itemtype in varchar2,
342 itemkey in varchar2)
343 return varchar2
344 is
345 buf varchar2(240);
346 begin
347 -- Check first for cached value
348 if ((itemtype = wf_item.c_itemtype) and
349 (itemkey = wf_item.c_itemkey)) then
350 return(wf_item.c_userkey);
351 end if;
352
353 -- No cached value, go directly to the source
354 select USER_KEY
355 into buf
356 from WF_ITEMS WI
357 where WI.ITEM_TYPE = GetItemUserKey.itemtype
358 and WI.ITEM_KEY = GetItemUserKey.itemkey;
359
360 return(buf);
361 exception
362 when no_data_found then
363 Wf_Core.Context('Wf_Item', 'GetItemUserKey', itemtype, itemkey);
364 Wf_Core.Token('TYPE', itemtype);
365 Wf_Core.Token('KEY', itemkey);
366 Wf_Core.Raise('WFENG_ITEM');
367 when others then
368 Wf_Core.Context('Wf_Item', 'GetItemUserKey', itemtype, itemkey);
369 raise;
370 end GetItemUserKey;
371
372 --
373 -- Item_Exist (PRIVATE)
374 -- Returns TRUE if this is an existing item. Otherwise return FALSE.
375 -- IN
376 -- itemtype - item type
377 -- itemkey - item key
378 --
379 function Item_Exist(itemtype in varchar2,
380 itemkey in varchar2)
381 return boolean
382 is
383 begin
384
385 Wf_Item.InitCache(itemtype, itemkey, ignore_notfound=>TRUE);
386
387 if (wf_item.c_itemtype is not null) then
388
389 return(TRUE);
390
391 else
392
393 return(FALSE);
394
395 end if;
396
397 exception
398 when OTHERS then
399 Wf_Core.Context('Wf_Item', 'Item_Exist', itemtype, itemkey);
400 raise;
401 end Item_Exist;
402
403 --
404 -- Root_Process (PRIVATE)
405 -- If the item exists, wflow out variable will contain the root process
406 -- name for this item key. Otherwise the wflow out variable will be null.
407 -- IN
408 -- itemtype - item type
409 -- itemkey - item key
410 -- OUT
411 -- wflow - root process
412 -- version - root process version
413 --
414 procedure Root_Process(itemtype in varchar2,
415 itemkey in varchar2,
416 wflow out NOCOPY varchar2,
417 version out NOCOPY number)
418 is
419 begin
420
421 Wf_Item.InitCache(itemtype, itemkey);
422 wflow := wf_item.c_root_activity;
423 version := wf_item.c_root_activity_version;
424
425 exception
426 when NO_DATA_FOUND then
427 wflow := '';
428 version := -1;
429 when OTHERS then
430 Wf_Core.Context('Wf_Item', 'Root_Process', itemtype, itemkey);
431 raise;
432 end Root_Process;
433
434 --
435 -- Create_Item (PRIVATE)
436 -- Create one row in the WF_ITEMS table with the given item type, item key
437 -- and the root process name.
438 -- IN
439 -- itemtype - item type
440 -- itemkey - item key
441 -- wflow - root process name for this item key.
442 -- actdate - active date of item
443 --
444 procedure Create_Item(
445 itemtype in varchar2,
446 itemkey in varchar2,
447 wflow in varchar2,
448 actdate in date,
449 user_key in varchar2,
450 owner_role in varchar2)
451 is
452
453 rootversion number;
454 rootid number;
455
456 onDemandFlag wf_activity_attributes.text_default%type;
457 --<rwunderl:2412940>
458 status PLS_INTEGER;
459 wiaIND NUMBER;
460 wiavIND NUMBER;
461
462 cursor attrcurs(itype in varchar2) is
463 select WIA.ITEM_TYPE, WIA.NAME, WIA.TYPE, WIA.SUBTYPE, WIA.FORMAT,
464 WIA.TEXT_DEFAULT, WIA.NUMBER_DEFAULT, WIA.DATE_DEFAULT
465 from WF_ITEM_ATTRIBUTES WIA
466 where WIA.ITEM_TYPE = itype;
467
468 begin
469
470 rootversion := Wf_Activity.Version(itemtype, wflow, actdate);
471
472 if (itemkey <> wf_engine.eng_synch) then
473 -- NORMAL: Insert new item and attributes directly in the db
474 insert into WF_ITEMS (
475 ITEM_TYPE,
476 ITEM_KEY,
477 ROOT_ACTIVITY,
478 ROOT_ACTIVITY_VERSION,
479 OWNER_ROLE,
480 PARENT_ITEM_TYPE,
481 PARENT_ITEM_KEY,
482 BEGIN_DATE,
483 END_DATE,
484 USER_KEY
485 ) values (
486 itemtype,
487 itemkey,
488 wflow,
489 rootversion,
490 Create_Item.owner_role,
491 '',
492 '',
493 actdate,
494 to_date(NULL),
495 Create_item.user_key
496 );
497 end if;
498
499 -- Initialize runtime cache (used in both NORMAL and SYNCHMODE).
500 wf_item.c_itemtype := itemtype;
501 wf_item.c_itemkey := itemkey;
502 wf_item.c_root_activity := wflow;
503 wf_item.c_root_activity_version := rootversion;
504 wf_item.c_begin_date := actdate;
505 wf_item.c_userkey := Create_item.user_key;
506
507 --
508 --ondemand flag
509 --
510 begin
511 select text_default into onDemandFlag from wf_activity_attributes
512 where activity_item_type = c_itemtype
513 and activity_name = c_root_activity
514 and activity_version=c_root_activity_version
515 and name = '#ONDEMANDATTR';
516 wf_item.c_ondemand := true;
517 exception
518 when no_data_found then
519 wf_item.c_ondemand := false;
520 end;
521
522 -- Initialize item attributes
523 if (itemkey <> wf_engine.eng_synch) then
524 -- NORMAL: store attributes in table
525 if(not wf_item.c_ondemand) then
526 -- only popluate when the flag is false
527 insert into WF_ITEM_ATTRIBUTE_VALUES (
528 ITEM_TYPE,
529 ITEM_KEY,
530 NAME,
531 TEXT_VALUE,
532 NUMBER_VALUE,
533 DATE_VALUE
534 ) select
535 itemtype,
536 itemkey,
537 WIA.NAME,
538 WIA.TEXT_DEFAULT,
539 WIA.NUMBER_DEFAULT,
540 WIA.DATE_DEFAULT
541 from WF_ITEM_ATTRIBUTES WIA
542 where WIA.ITEM_TYPE = itemtype;
543 end if;
544 else
545 -- SYNCHMODE: store attributes in plsql only
546 for curs in attrcurs(itemtype) loop
547 --Getting the index for the item attribute.
548 WF_CACHE.GetItemAttribute(itemtype, curs.name, status, wiaIND);
549
550 --Getting the index for the item attribute value
551 WF_CACHE.GetItemAttrValue(itemtype, itemkey, curs.name, status, wiavIND);
552
553 --Loading the item attribute into cache for synch mode.
554 WF_CACHE.ItemAttributes(wiaIND).ITEM_TYPE := itemType;
555 WF_CACHE.ItemAttributes(wiaIND).NAME := curs.name;
556 WF_CACHE.ItemAttributes(wiaIND).TYPE := curs.type;
557 WF_CACHE.ItemAttributes(wiaIND).SUBTYPE := curs.subtype;
558 WF_CACHE.ItemAttributes(wiaIND).FORMAT := curs.format;
559 WF_CACHE.ItemAttributes(wiaIND).TEXT_DEFAULT := curs.text_default;
560 WF_CACHE.ItemAttributes(wiaIND).NUMBER_DEFAULT := curs.number_default;
561 WF_CACHE.ItemAttributes(wiaIND).DATE_DEFAULT := curs.date_default;
562
563 --Loading the item attribute value into cache for use by synch processes
564 --only until we introduce the item locking feature.
565 WF_CACHE.ItemAttrValues(wiavIND).ITEM_TYPE := itemType;
566 WF_CACHE.ItemAttrValues(wiavIND).ITEM_KEY := itemKey;
567 WF_CACHE.ItemAttrValues(wiavIND).NAME := curs.name;
568 WF_CACHE.ItemAttrValues(wiavIND).TEXT_VALUE := curs.text_default;
569 WF_CACHE.ItemAttrValues(wiavIND).NUMBER_VALUE := curs.number_default;
570 WF_CACHE.ItemAttrValues(wiavIND).DATE_VALUE := curs.date_default;
571
572 end loop;
573 end if;
574
575 exception
576 when DUP_VAL_ON_INDEX then
577 Wf_Core.Context('Wf_Item', 'Create_Item', itemtype, itemkey, wflow);
578 Wf_Core.Token('TYPE', itemtype);
579 Wf_Core.Token('KEY', itemkey);
580 Wf_Core.Raise('WFENG_ITEM_UNIQUE');
581 when OTHERS then
582 Wf_Core.Context('Wf_Item', 'Create_Item', itemtype, itemkey, wflow);
583 raise;
584 end Create_Item;
585
586 --
587 -- Active_Date (PRIVATE)
588 -- Return the begin date of an item
589 -- IN
590 -- itemtype
591 -- itemkey
592 -- RETURN
593 -- Begin date of item
594 --
595 function Active_Date(itemtype in varchar2,
596 itemkey in varchar2)
597 return date
598 is
599 begin
600 Wf_Item.InitCache(itemtype, itemkey);
601 return(wf_item.c_begin_date);
602 exception
603 when NO_DATA_FOUND then
604 Wf_Core.Context('Wf_Item', 'Active_Date', itemtype, itemkey);
605 Wf_Core.Token('TYPE', itemtype);
606 Wf_Core.Token('KEY', itemkey);
607 Wf_Core.Raise('WFENG_ITEM');
608 when OTHERS then
609 Wf_Core.Context('Wf_Item', 'Active_Date', itemtype, itemkey);
610 end Active_Date;
611
612 --Function Acquire_lock (PRIVATE)
613 --This function tries to lock the particular item (for the give
614 --itemtype/itemkey ) in the wf_items table. It returns true if the lock
615 --acquired else returns false.
616
617 --Here we will not do any error handling but return true/false
618 --for the case of lock_acquired or not . This leaves the caller
619 --the decision of what to do when a resource busy error occurs
620 --(ie FALSE) . For eg : Background engine will ignore it and move
621 --on , WF Engine will raise exception etc.
622
623 function acquire_lock(itemtype in varchar2,
624 itemkey in varchar2,
625 raise_exception in boolean)
626 return boolean
627 is
628 --Bug 2607770
629 --Cursor for acquiring lock
630 cursor itemlock (itemtype varchar2, itemkey varchar2) is
631 select '1'
632 from wf_items
633 where item_type = itemtype
634 and item_key = itemkey
635 for update nowait;
636
637 --Define an exception to capture the resource_busy error
638 resource_busy exception;
639 pragma EXCEPTION_INIT(resource_busy,-00054);
640
641 begin
642 --Acquire lock here by opening the cursor
643 OPEN itemlock (itemtype,itemkey);
644 --Close the cursor once the lock has been acquired
645 CLOSE itemlock;
646 return TRUE;
647 exception
648 --Capture the exception on resource-busy error
649 when resource_busy then
650 --Lets double check that the cursor is not open
651 if (itemlock%ISOPEN) then
652 CLOSE itemlock;
653 end if;
654 --check the if_raise flag . If its true then raise
655 --the exception
656 --else return false and let the caller decide what to do.
657 if raise_exception then
658 raise;
659 --If not able to acquire lock return FALSE
660 else
661 return FALSE;
662 end if;
663 when others then
664 --Lets double check that the cursor is not open
665 if (itemlock%ISOPEN) then
666 CLOSE itemlock;
667 end if;
668 --In this case we do not want a TRUE/FALSE return
669 --we just raise the error.
670 Wf_Core.Context('Wf_Item', 'Acquire_lock', itemtype, itemkey);
671 raise;
672 end;
673
674 --
675 -- SetEndDate (Private)
676 -- Sets end_date and completes any coordinated counter processing.
677 -- IN
678 -- p_itemtype - process item type
679 -- p_itemkey - process item key
680 -- RETURNS
681 -- number
682 -- NOTE:
683 -- This function will return a status of one of the following:
684 -- 0 - Item was found, active, and the end_date was set.
685 -- 1 - The item was not found. (ERROR)
686 function SetEndDate(p_itemtype in varchar2,
687 p_itemkey in varchar2) return number
688 is
689 l_parent_itemType VARCHAR2(8);
690 l_parent_itemKey VARCHAR2(240);
691 l_parent_context VARCHAR2(2000);
692
693 TYPE nameTAB is TABLE of VARCHAR2(30) index by binary_integer;
694 attrNames nameTAB;
695
696 l_result NUMBER;
697 i NUMBER;
698 begin
699 UPDATE wf_items
700 SET end_date = sysdate
701 WHERE item_type = p_itemType
702 AND item_key = p_itemKey
703 AND end_date is NULL
704 RETURNING parent_item_type, parent_item_key, parent_context
705 INTO l_parent_itemtype, l_parent_itemkey, l_parent_context;
706
707 if (sql%notfound) then
708 return 1;
709 end if;
710
711 --We need to perform some counter processing if they exist.
712 if ((l_parent_itemType is NOT null) and
713 (l_parent_itemKey is NOT null)) then
714 if (WF_ENGINE.AddToItemAttrNumber(l_parent_itemType, l_parent_itemKey,
715 '#WAITFORDETAIL', -1) is NOT null) then
716 if ((l_parent_context is NOT null) and
717 (WF_ENGINE.GetItemAttrText(p_itemType, p_itemKey,
718 '#LBL_'||l_parent_context, TRUE) is NOT NULL)) then
719 if (WF_ENGINE.SetItemAttrText2(p_itemType, p_itemKey,
720 '#LBL_'||l_parent_context, NULL)) then
721 l_result := WF_ENGINE.AddToItemAttrNumber(l_parent_itemType,
722 l_parent_itemKey,
723 '#CNT_'||l_parent_context,
724 -1);
725 end if;
726 else
727 SELECT TEXT_VALUE
728 bulk collect into attrNames
729 FROM WF_ITEM_ATTRIBUTE_VALUES
730 WHERE ITEM_TYPE = p_itemType
731 AND ITEM_KEY = p_itemKey
732 AND NAME like ('#LBL_%')
733 AND TEXT_VALUE is NOT null;
734
735 if (attrNames.COUNT > 0) then
736 for i in attrNames.FIRST..attrNames.LAST loop
737 if (WF_ENGINE.SetItemAttrText2(p_itemType, p_itemKey,
738 '#LBL_'||attrNames(i), NULL)) then
739 l_result := WF_ENGINE.AddToItemAttrNumber(l_parent_itemtype,
740 l_parent_itemkey,
741 '#CNT_'||attrNames(i),
742 -1);
743 end if; --#LBL_ exists as expected.
744 end loop;
745 end if; --There are non-null #LBL_ attributes.
746 --<rwunderl:4271715> We need to decrement any #CNT_ attributes
747 --in the parent which the child may not have created the corresponding
748 --#LBL_ (did not arrive) such as in the case of an AbortProcess()
749 SELECT wiav.NAME
750 bulk collect into attrNames
751 FROM WF_ITEM_ATTRIBUTE_VALUES wiav
752 WHERE wiav.ITEM_TYPE = l_parent_itemType
753 AND wiav.ITEM_KEY = l_parent_itemKey
754 and wiav.NAME like ('#CNT_%')
755 AND NOT EXISTS (select null
756 from wf_item_attribute_values wiav2
757 where wiav2.item_type = p_itemType
758 and wiav2.item_key = p_itemKey
759 and wiav2.name = REPLACE(wiav.name,'#CNT_','#LBL_'));
760 if (attrNames.COUNT > 0) then
761 for i in attrNames.FIRST..attrNames.LAST loop
762 l_result := WF_ENGINE.AddToItemAttrNumber(l_parent_itemtype,
763 l_parent_itemkey,
764 attrNames(i), -1);
765 end loop;
766 end if; --There were unvisited ContinueFlow() activites in the child.
767 end if; --Parent Context
768 end if; --We were able to decrement the #WAITFORDETAIL
769 end if; --This item has a parent.
770 return 0;
771 exception
772 when OTHERS then
773 WF_CORE.Context('WF_ITEM', 'SetEndDate', p_itemType, p_itemKey);
774 raise;
775
776 end SetEndDate;
777
778 end WF_ITEM;