You are on page 1of 62

create or replace package body WF_STANDARD as

/* $Header: wfstdb.pls 120.11.12010000.2 2008/12/05 15:57:09 alsosa ship $ */

------------------------------------------------------------------------------------------------------------- PRIVATE API DECLARATIONS ----------------------------------------------------------------------------------------------------- ContinueMasterFlow


-- Signal Master Flow to continue if all Detail flows have executed
-- Continuation Activity
-- OUT
-- result
- 'NULL'
procedure ContinueMasterFlow( itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
waiting_activity
in varchar2,
resultout
in out nocopy varchar2);
-- ContinueDetailFlow
-- Signal Detail Flows to continue
-- IN
-- waiting_activity - The Name of the activity that is waiting
-- OUT
-- resultout
- 'NULL'
procedure ContinueDetailFlow( itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
waiting_activity
in varchar2,
resultout
out nocopy varchar2
);
-- WaitForDetailFlow
-- Wait for all detail flows to complete continuation activity
-- IN
-- continuation_activity - The Name of the activity that in waiting
-- OUT
-- result
- 'NULL'
procedure WaitForDetailFlow(
itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
continuation_activity in varchar2,
resultout
out nocopy varchar2);
-- WaitForMasterFlow
-- Wait for Master flows to complete continuation activity
-- IN
-- itemtype - item type
-- itemkey - item key
-- actid
- process activity instance id
-- funcmode - execution mode
-- OUT
-- result
- 'NULL'
procedure WaitForMasterFlow(
itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
continuation_activity in varchar2,
resultout
out nocopy varchar2 );
-------------------------------------------------------------------------------

------------------------------- PUBLIC APIs ------------------------------------------------------------------------------------------------------------------ AbortProcess


-- cover to wf_engine abort process used in error process.
procedure AbortProcess(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2) is
l_error_itemtype varchar2(8);
l_error_itemkey varchar2(240);
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
--- Get the type and the key of the process that errored out
-- these were set in the erroring out process by Execute_Error_Process
-l_error_itemkey := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ITEM_KEY' );
l_error_itemtype := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ITEM_TYPE' );
-- now abort the process: dont specify the process so it defaults to the root
Wf_Engine.AbortProcess(itemtype => l_error_itemtype, itemkey=>l_error_itemkey
);
resultout := wf_engine.eng_null;
exception
when others then
Wf_Core.Context('Wf_Standard', 'AbortProcess', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end AbortProcess;
-- OrJoin
-- Parallel Or Join.
-- Always returns 'NULL' result immediately, since an 'Or' succeeds
-- as soon as first in-transition activity completes.
-- OUT
-- result
- 'NULL'
procedure OrJoin(itemtype in varchar2,
itemkey in varchar2,
actid in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
begin

resultout := wf_engine.eng_null;
exception
when others then
Wf_Core.Context('Wf_Standard', 'OrJoin', itemtype, itemkey,
to_char(actid), funcmode);
raise;
end OrJoin;
-- AndJoin
-- Parallel And Join
-- Returns 'NULL' if all in-transition activities have completed.
-- Returns 'WAITING' if at least one in-transition activity is not
-- complete, or is complete with the wrong result.
-- OUT
-- result
- 'WAITING' | 'NULL'
procedure AndJoin(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
cnt pls_integer;
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.AndJoin');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
-- The And fails if there is at least one in-transition which is either
-- incomplete or complete with the wrong result.
SELECT count(1)
into cnt
FROM WF_ACTIVITY_TRANSITIONS WAT
WHERE WAT.TO_PROCESS_ACTIVITY = actid
AND NOT EXISTS
(SELECT NULL
FROM WF_ITEM_ACTIVITY_STATUSES WIAS
WHERE WIAS.PROCESS_ACTIVITY = WAT.FROM_PROCESS_ACTIVITY
AND WIAS.ITEM_TYPE = itemtype
AND WIAS.ITEM_KEY = itemkey
AND WIAS.ACTIVITY_STATUS = 'COMPLETE'
AND (WAT.RESULT_CODE in (WIAS.ACTIVITY_RESULT_CODE,
wf_engine.eng_trans_any)
OR (WAT.RESULT_CODE = wf_engine.eng_trans_default
AND NOT EXISTS
(SELECT NULL
FROM WF_ACTIVITY_TRANSITIONS WAT2
WHERE WAT2.FROM_PROCESS_ACTIVITY =
WAT.FROM_PROCESS_ACTIVITY
AND WAT2.RESULT_CODE = WIAS.ACTIVITY_RESULT_CODE)
)
)

);
if (cnt > 0) then
-- This means there is at least one in-transition either incomplete
-- or complete with the wrong result.
-- The LogicalAnd fails, return a result of 'WAITING'.
resultout := wf_engine.eng_waiting;
else
-- This means there are no in-transition activities that are either
-- incomplete or complete with the wrong result.
-- The LogicalAnd succeeds, return a result of 'NULL' to continue.
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
end if;
return;
exception
when others then
Wf_Core.Context('Wf_Standard', 'AndJoin', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end AndJoin;
-- Assign
-- Assign a value to an item attribute
-- OUT
-- result - null
-- ACTIVITY ATTRIBUTES REFERENCED
-- ATTR
- Item attribute
-- DATE_VALUE - date value
-- NUMBER_VALUE - number value
-- TEXT_VALUE - text value
procedure Assign(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
atype
varchar2(8);
asubtype varchar2(8);
aformat varchar2(240);
aname
varchar2(30);
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- Get attribute info
aname := wf_engine.GetActivityAttrText(itemtype, itemkey, actid, 'ATTR');
wf_engine.GetItemAttrInfo(itemtype, aname, atype, asubtype, aformat);
-- NUMBER value
if (atype = 'NUMBER') then
wf_engine.SetItemAttrNumber(itemtype,itemkey,aname,
wf_engine.GetActivityAttrNumber(itemtype,itemkey,actid, 'NUMBER_VALUE'));
-- DATE value
elsif (atype = 'DATE') then
wf_engine.SetItemAttrDate(itemtype,itemkey,aname,

wf_engine.GetActivityAttrDate(itemtype,itemkey,actid, 'DATE_VALUE'));
-- TEXT value (VARCHAR2, LOOKUP, FORM, URL, DOCUMENT, etc)
else
wf_engine.SetItemAttrText(itemtype,itemkey,aname,
wf_engine.GetActivityAttrText(itemtype,itemkey,actid, 'TEXT_VALUE'));
end if;
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
exception
when others then
Wf_Core.Context('Wf_Standard', 'Assign', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end Assign;
-- GetURL
-- Get monitor URL, store in item attribute
-- OUT
-- result
- 'NULL'
-- ACTIVITY ATTRIBUTES REFERENCED
-- ATTR
- Item attribute to set
-- ADMIN_MODE - administration mode (Y / N)
procedure GetURL(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
aname
varchar2(30);
admin
varchar2(8);
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.GetUrl');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
-- Get item attribute name
aname := wf_engine.GetActivityAttrText(itemtype,itemkey,actid, 'ATTR');
-- Get admin mode
admin := wf_engine.GetActivityAttrText(itemtype,itemkey,actid, 'ADMIN_MODE');
-- Set item attribute
wf_engine.SetItemAttrText(itemtype, itemkey, aname,
wf_monitor.geturl(
wf_core.translate('WF_WEB_AGENT'), itemtype, itemkey, admin));
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
exception
when others then
Wf_Core.Context('Wf_Standard', 'GetUrl', itemtype,

itemkey, to_char(actid), funcmode);


raise;
end GetURL;
-- Compare
-- Standard Compare function.
-- OUT
-- comparison value (LT, EQ, GT, NULL)
-- ACTIVITY ATTRIBUTES REFERENCED
-- VALUE1 - Test value
-- VALUE2 - Reference value
procedure Compare(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
atype
varchar2(8);
asubtype varchar2(8);
aformat varchar2(240);
aname
varchar2(30);
nval1
number;
nval2
number;
dval1
date;
dval2
date;
tval1
varchar2(4000);
tval2
varchar2(4000);
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- Get comparison data type
Wf_Engine.GetActivityAttrInfo(itemtype, itemkey, actid, 'VALUE1',
atype, asubtype, aformat);
tval1 := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'VALUE1');
--- NUMBER value
-if (atype = 'NUMBER') then
-- Get the two number values
nval1 := Wf_Engine.GetActivityAttrNumber(itemtype,itemkey,actid, 'VALUE1');
nval2 := Wf_Engine.GetActivityAttrNumber(itemtype,itemkey,actid, 'VALUE2');
-- Compare
if (nval1 is null or nval2 is null) then
resultout := wf_engine.eng_completed||':NULL';
elsif (nval1 < nval2) then
resultout := wf_engine.eng_completed||':LT';
elsif (nval1 > nval2) then
resultout := wf_engine.eng_completed||':GT';
elsif (nval1 = nval2) then
resultout := wf_engine.eng_completed||':EQ';
end if;

--- DATE value


-elsif (atype = 'DATE') then
-- Get the two date values
dval1 := Wf_Engine.GetActivityAttrDate(itemtype,itemkey,actid, 'VALUE1');
dval2 := Wf_Engine.GetActivityAttrDate(itemtype,itemkey,actid, 'VALUE2');
-- Compare
if (dval1 is null or dval2 is null) then
resultout := wf_engine.eng_completed||':NULL';
elsif (dval1 < dval2) then
resultout := wf_engine.eng_completed||':LT';
elsif (dval1 > dval2) then
resultout := wf_engine.eng_completed||':GT';
elsif (dval1 = dval2) then
resultout := wf_engine.eng_completed||':EQ';
end if;
--- TEXT value (VARCHAR2, LOOKUP, FORM, URL, DOCUMENT, etc)
-else
-- Get the two text values
tval1 := Wf_Engine.GetActivityAttrText(itemtype,itemkey,actid, 'VALUE1');
tval2 := Wf_Engine.GetActivityAttrText(itemtype,itemkey,actid, 'VALUE2');
-- Compare
if (tval1 is null or tval2 is null) then
resultout := wf_engine.eng_completed||':NULL';
elsif (tval1 < tval2) then
resultout := wf_engine.eng_completed||':LT';
elsif (tval1 > tval2) then
resultout := wf_engine.eng_completed||':GT';
elsif (tval1 = tval2) then
resultout := wf_engine.eng_completed||':EQ';
end if;
end if;
exception
when others then
Wf_Core.Context('Wf_Standard', 'Compare', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end Compare;
-- CompareExecutionTime
-- Compare Execution Time function.
-- OUT
-- comparison value (LT, EQ, GT, NULL)
-- ACTIVITY ATTRIBUTES REFERENCED
-- EXECUTIONTIME - Execution time Test value in seconds
-- PARENTTYPE
- Either ROOT or SUBPROCESS
procedure CompareExecutionTime(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)

is
etime
delta
processid
ptype

number;
number;
number;
varchar2(30);

cursor GetRunningTime (itemtype in varchar2,


itemkey in varchar2, actid in number) is
select (sysdate - nvl(begin_date,sysdate))*86400
from wf_item_activity_statuses
where item_type = itemtype
and
item_key = itemkey
and
process_activity = actid;
cursor GetExecutionTime (itemtype in varchar2,
itemkey in varchar2) is
select (sysdate - begin_date)*86400
from wf_items
where item_type = itemtype
and
item_key = itemkey;
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
Ptype := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'PARENTTYPE')
;
if Ptype = 'ROOT' then
-- calculate the execution time
open GetExecutionTime(itemtype, itemkey);
fetch GetExecutionTime into delta;
close GetExecutionTime;
else
processid := WF_ENGINE_UTIL.activity_parent_process(itemtype, itemkey, acti
d);
-- calculate the execution time
open GetRunningTime(itemtype, itemkey, processid);
fetch GetRunningTime into delta;
close GetRunningTime;
end if;
-- look up the test value for execution time
Etime := Wf_Engine.GetActivityAttrNumber(itemtype, itemkey, actid, 'EXECUTIONT
IME');
-- execute comparison
if (delta is null or etime is null) then
resultout := wf_engine.eng_completed||':NULL';
elsif (delta < etime) then
resultout := wf_engine.eng_completed||':LT';
elsif (delta > etime) then
resultout := wf_engine.eng_completed||':GT';
elsif (delta = etime) then
resultout := wf_engine.eng_completed||':EQ';
end if;

exception
when others then
Wf_Core.Context('Wf_Standard', 'CompareExecutionTime', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end CompareExecutionTime;
-- CompareEventProperty
-- Compare a property on an event
-- IN
-- itemtype - item type
-- itemkey - item key
-- actid
- process activity instance id
-- funcmode - execution mode
-- OUT
-- comparison result (WFSTD_COMPARISON lookup code)
-- GT LT EQ NULL
-- ACTIVITY ATTRIBUTES REFERENCED
-- EVENT - Event whose property is to be compared
-- PROPERTY - Event Property Reference (Based on the lookup of EVENTPROPERTY
-- PARAMETER - Parameter Name if Lookup type = Parameter
-- VALUE - Constant value of correct type
procedure CompareEventProperty(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
lEvent WF_EVENT_T;
lAgent WF_AGENT_T;
lNVal NUMBER;
lDVal DATE;
lTVal VARCHAR2 (4000);
lProperty VARCHAR2 (20);
lParameter VARCHAR2(200);
lType VARCHAR2 (20);
lSubType VARCHAR2 (20);
lFormat VARCHAR2 (20);
begin
lEvent := wf_engine.getActivityAttrEvent(itemtype, itemkey,
actid, 'EVENT');
lProperty := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'PROPERTY');
if (lProperty = 'PRIORITY') then
lNVal := wf_engine.getActivityAttrNumber(itemtype, itemkey,
actid, 'NUMBER_VALUE');
if (lEvent.priority is NULL or lNVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (lEvent.priority < lNVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (lEvent.priority > lNVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (lEvent.priority = lNVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;

elsif (lProperty = 'SEND_DATE') then


lDVal := wf_engine.getActivityAttrDate(itemtype, itemkey,
actid, 'DATE_VALUE');
if (lEvent.send_date is NULL or lDVal is null) then
resultout := wf_engine.eng_completed||':NULL';
elsif (lEvent.send_date < lDVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (lEvent.send_date > lDVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (lEvent.send_date = lDVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'RECEIVE_DATE') then
lDVal := wf_engine.getActivityAttrDate(itemtype, itemkey,
actid, 'DATE_VALUE');
if (lEvent.receive_date is NULL or lDVal is null) then
resultout := wf_engine.eng_completed||':NULL';
elsif (lEvent.receive_date < lDVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (lEvent.receive_date > lDVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (lEvent.receive_date = lDVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'CORRELATION_ID') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.correlation_id is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.correlation_id < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.correlation_id > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.correlation_id = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'EVENT_NAME') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.event_name is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.event_name < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.event_name > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.event_name = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'EVENT_KEY') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.event_key is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.event_key < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.event_key > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.event_key = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;

elsif (lProperty = 'FROM_AGENT_NAME') then


lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.From_Agent.Name is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.From_Agent.Name < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.From_Agent.Name > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.From_Agent.Name = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'FROM_AGENT_SYSTEM') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.From_Agent.System is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.From_Agent.System < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.From_Agent.System > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.From_Agent.System = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'TO_AGENT_NAME') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.To_Agent.Name is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.To_Agent.Name < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.To_Agent.Name > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.To_Agent.Name = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'TO_AGENT_SYSTEM') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.To_Agent.System is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.To_Agent.System < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.To_Agent.System > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.To_Agent.System = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'FROM_AGENT') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.From_Agent.Name is NULL
or LEvent.From_Agent.System is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.From_Agent.Name||'@'||LEvent.From_Agent.System < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.From_Agent.Name||'@'||LEvent.From_Agent.System > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.From_Agent.Name||'@'||LEvent.From_Agent.System = lTVal) then
resultout := wf_engine.eng_completed||':EQ';

end if;
elsif (lProperty = 'TO_AGENT') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
if (LEvent.To_Agent.Name is NULL
or LEvent.To_Agent.System is NULL or lTVal is NULL) then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.To_Agent.Name||'@'||LEvent.To_Agent.System < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.To_Agent.Name||'@'||LEvent.To_Agent.System > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.To_Agent.Name||'@'||LEvent.To_Agent.System = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
elsif (lProperty = 'PARAMETER') then
lTVal := wf_engine.getActivityAttrText(itemtype, itemkey,
actid, 'TEXT_VALUE');
lParameter := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'PARAMETER');
if (LEvent.GetValueForParameter(lParameter)) is NULL then
resultout := wf_engine.eng_completed||':NULL';
elsif (LEvent.GetValueForParameter(lParameter) < lTVal) then
resultout := wf_engine.eng_completed||':LT';
elsif (LEvent.GetValueForParameter(lParameter) > lTVal) then
resultout := wf_engine.eng_completed||':GT';
elsif (LEvent.GetValueForParameter(lParameter) = lTVal) then
resultout := wf_engine.eng_completed||':EQ';
end if;
else
-- Unhandled property. Return NULL
resultout := wf_engine.eng_completed||':NULL';
end if;
exception
when others then
Wf_Core.Context('Wf_Standard', 'CompareEventProperty', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end CompareEventProperty;
-- SetEventProperty
-- Set the property in an Event to a given value
-- IN
-- itemtype - item type
-- itemkey - item key
-- actid
- process activity instance id
-- funcmode - execution mode
-- OUT
-- NONE
-- ACTIVITY ATTRIBUTES REFERENCED
-- EVENT - Event whose property is to be compared
-- PROPERTY - Event Property Reference (Based on the lookup of EVENTPROPERTY
-- PARAMETER - Parameter name
-- VALUE - Constant value of correct type
procedure SetEventProperty(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,

resultout in out nocopy varchar2)


is
lEvent WF_EVENT_T;
lNVal NUMBER;
lDVal DATE;
lTVal VARCHAR2 (4000);
lAName VARCHAR2(30);
lProperty VARCHAR2 (20);
lParameter VARCHAR2(200);
lType VARCHAR2 (20);
lSubType VARCHAR2 (20);
lFormat VARCHAR2 (20);
lRefFlag VARCHAR2(8);
lAtSign PLS_INTEGER;
lFromAgent WF_AGENT_T := WF_AGENT_T(NULL, NULL);
lToAgent WF_AGENT_T := WF_AGENT_T(NULL, NULL);
begin
if (funcmode = 'RUN') then
-- First get the name of the Item Attribute that EVENT points to
select WAAV.VALUE_TYPE, substrb(WAAV.TEXT_VALUE, 1, 30)
into LRefflag, LAName
from WF_ACTIVITY_ATTR_VALUES WAAV
where WAAV.PROCESS_ACTIVITY_ID = actid
and WAAV.NAME = 'EVENT';
/* Should be able to use the GetActivityAttrEvent to do this
lEvent := wf_engine.getItemAttrEvent(itemtype => itemtype,
itemkey => itemkey,
name => LAName);
*/
lEvent := wf_engine.getActivityAttrEvent(itemtype, itemkey,
actid, 'EVENT');
lProperty := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'PROPERTY');
if (lProperty = 'PRIORITY') then
lNVal := wf_engine.getActivityAttrNumber(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'NUMBER_VALUE');
lEvent.setPriority(lNVal);
elsif (lProperty = 'SEND_DATE') then
lDVal := wf_engine.getActivityAttrDate(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'DATE_VALUE');
lEvent.setSendDate(lDVal);
elsif (lProperty = 'RECEIVE_DATE') then
lDVal := wf_engine.getActivityAttrDate(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'DATE_VALUE');
lEvent.setReceiveDate(lDVal);
elsif (lProperty = 'CORRELATION_ID') then

lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,


itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
lEvent.setCorrelationID(lTVal);
elsif (lProperty = 'EVENT_NAME') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
lEvent.setEventName(lTVal);
elsif (lProperty = 'EVENT_KEY') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
lEvent.setEventKey(lTVal);
elsif (lProperty = 'FROM_AGENT_NAME') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
if lEvent.GetFromAgent() is not null then
lFromAgent := lEvent.GetFromAgent();
end if;
lFromAgent.SetName(lTVal);
lEvent.SetFromAgent(lFromAgent);
elsif (lProperty = 'FROM_AGENT_SYSTEM') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
if lEvent.GetFromAgent() is not null then
lFromAgent := lEvent.GetFromAgent();
end if;
lFromAgent.SetSystem(lTVal);
lEvent.SetFromAgent(lFromAgent);
elsif (lProperty = 'TO_AGENT_NAME') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
if lEvent.GetToAgent() is not null then
lToAgent := lEvent.GetToAgent();
end if;
lToAgent.SetName(lTVal);
lEvent.SetToAgent(lToAgent);
elsif (lProperty = 'TO_AGENT_SYSTEM') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
if lEvent.GetToAgent() is not null then
lToAgent := lEvent.GetToAgent();
end if;
lToAgent.SetSystem(lTVal);
lEvent.SetToAgent(lToAgent);
elsif (lProperty = 'FROM_AGENT') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,

actid => actid,


aname => 'TEXT_VALUE');
lAtSign := instr(lTVal, '@');
lFromAgent.SetName(substr(lTVal, 1, lAtSign-1));
lFromAgent.SetSystem(substr(lTVal, lAtSign+1));
lEvent.SetFromAgent(lFromAgent);
elsif (lProperty = 'TO_AGENT') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
lAtSign := instr(lTVal, '@');
lToAgent.SetName(substr(lTVal, 1, lAtSign-1));
lToAgent.SetSystem(substr(lTVal, lAtSign+1));
lEvent.SetToAgent(lToAgent);
elsif (lProperty = 'PARAMETER') then
lTVal := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'TEXT_VALUE');
lParameter := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'PARAMETER');
lEvent.AddParameterToList(lParameter, lTVal);
end if;
wf_engine.setItemAttrEvent(itemtype => itemtype,
itemkey => itemkey,
name => lAName,
event => lEvent);
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
end if; -- RUN
exception
when others then
Wf_Core.Context('Wf_Standard', 'SetEventProperty', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end SetEventProperty;
-- GetEventProperty
-- Get a property of an Event and assign it to an Item Attribute
-- IN
-- itemtype - item type
-- itemkey - item key
-- actid
- process activity instance id
-- funcmode - execution mode
-- OUT
-- NONE
-- ACTIVITY ATTRIBUTES REFERENCED
-- EVENT - Event whose property is to be compared
-- PROPERTY - Event Property Reference (Based on the lookup of EVENTPROPERTY
-- PARAMETER - Event Parameter Name
-- VALUE - Constant value of correct type
procedure GetEventProperty(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,

resultout in out nocopy varchar2)


is
lEvent WF_EVENT_T;
lNVal NUMBER;
lDVal DATE;
lTVal VARCHAR2 (4000);
lAName VARCHAR2(30);
lProperty VARCHAR2 (20);
lParameter VARCHAR2(200);
lType VARCHAR2 (20);
lSubType VARCHAR2 (20);
lFormat VARCHAR2 (20);
lRefFlag VARCHAR2(8);
begin
if (funcmode = 'RUN') then
lEvent := wf_engine.getActivityAttrEvent(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
name => 'EVENT');
lProperty := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'PROPERTY');
lAName := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'ATTR');
if (lProperty = 'PRIORITY') then
wf_engine.SetItemAttrNumber(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getPriority());
lEvent.setPriority(lNVal);
elsif (lProperty = 'SEND_DATE') then
wf_engine.SetItemAttrDate(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getSendDate());
elsif (lProperty = 'RECEIVE_DATE') then
wf_engine.SetItemAttrDate(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getReceiveDate());
elsif (lProperty = 'CORRELATION_ID') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getCorrelationID());
elsif (lProperty = 'EVENT_NAME') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getEventName());
elsif (lProperty = 'EVENT_KEY') then

wf_engine.SetItemAttrText(itemtype => itemtype,


itemkey => itemkey,
aname => LAName,
avalue => lEvent.getEventKey());
elsif (lProperty = 'FROM_AGENT_NAME') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getFromAgent().getName());
elsif (lProperty = 'FROM_AGENT_SYSTEM') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getFromAgent().getSystem());
elsif (lProperty = 'TO_AGENT_NAME') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getToAgent().getName());
elsif (lProperty = 'TO_AGENT_SYSTEM') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue => lEvent.getToAgent().getSystem());
elsif (lProperty = 'FROM_AGENT') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue =>
lEvent.getFromAgent().getName()||
'@'||lEvent.getFromAgent().getSystem());
elsif (lProperty = 'TO_AGENT') then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue =>
lEvent.getToAgent().getName()||
'@'||lEvent.getToAgent().getSystem());
elsif (lProperty = 'PARAMETER') then
lParameter := wf_engine.getActivityAttrText(itemtype => itemtype,
itemkey => itemkey,
actid => actid,
aname => 'PARAMETER');
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => LAName,
avalue =>
lEvent.GetValueForParameter(lParameter));
end if;
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
end if; -- RUN
exception
when others then
Wf_Core.Context('Wf_Standard', 'GetEventProperty', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end GetEventProperty;

-- LaunchProcess
-- launches a process
-- IN
-- itemtype - item type
-- itemkey - item key
-- actid
- process activity instance id
-- funcmode - execution mode
-- OUT
-- result
- NULL
-- ACTIVITY ATTRIBUTES REFERENCED
-- START_ITEMTYPE,START_ITEMKEY,START_PROCESS,START_USER_KEY,START_OWNER
procedure LaunchProcess
(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2) is
SItemtype varchar2(8);
SItemKey varchar2(30);
SProcess varchar2(30);
SUserKey varchar2(320);
SOwner
varchar2(320);
Deferit varchar2(2);
Launch_count number;
status
varchar2(8);
result
varchar2(30);
loop_flag BOOLEAN;
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
SItemtype := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'IT
EMTYPE'));
Deferit := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'DEFER');
if SItemtype is null then
wf_core.token('ITEMTYPE','NULL');
wf_core.raise('WFSQL_ARGS');
end if;
if deferit = 'Y' then
-- Check if this is the first or second execution of this activity.
-- First -> result_code will be null (really null).
-- Second -> result_code will be '#NULL' (set that way by execution 1).
Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
if (result = wf_engine.eng_null) then
-- Second execution.
-- Defer must have been picked up by the background engine,
-- so return complete result.
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
else
-- Return deferred result
resultout := wf_engine.eng_deferred;

return;
end if;
end if;
-- if we have got this far, go ahead and launch the process.
SItemkey := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'ITEMKEY'
);
SProcess := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'PR
OCESS_NAME'));
SUserkey := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'USER_KEY
');
SOwner
:= Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'OWNER');
if sItemkey is not null then
wf_engine.LaunchProcess(SItemtype, SItemkey, SProcess, SUserkey, SOwner);
else
begin
launch_count := wf_engine.GetItemAttrNumber(
itemtype, itemkey, 'LAUNCH_COUNT');
exception
when others then
--- If item attribute does not exist then create it;
-if ( wf_core.error_name = 'WFENG_ITEM_ATTR' ) then
wf_engine.AddItemAttr(itemtype,itemkey, 'LAUNCH_COUNT');
launch_count := 0;
else
raise;
end if;
end;
loop_flag:=TRUE;
while loop_flag loop
begin
launch_count:=launch_count+1;
-- imtetype:itemkey is unique so the new itemkey should be unique
sItemkey := itemtype||':'||itemkey||'-'||to_char(launch_count);
wf_engine.LaunchProcess(SItemtype, SItemkey, SProcess,
SUserkey, SOwner);
loop_flag:=FALSE;
exception
when others then
--- Dont raise error if its a dup name: instead we will loop
-- around and increment the counter.
if ( wf_core.error_name <> 'WFENG_ITEM_UNIQUE' ) then
raise;
end if;
end;
end loop;
wf_engine.SetItemAttrNumber(
itemtype, itemkey, 'LAUNCH_COUNT',launch_count);
end if;
resultout := wf_engine.eng_completed;

exception
when others then
Wf_Core.Context('Wf_Standard', 'LaunchProcess', itemtype,
itemkey, to_char(actid), Sitemtype||':'||Sitemkey||SProcess)
;
raise;
end LaunchProcess;
-- LaunchProcess
-- Forks the item by creating a duplicate item with the same history.
-- The new forked item will be identical up to the point of this activity.
-- However this activity will be marked as NOTIFIED. It will be upto the user
-- to push it forward using CompleteActivity.
-- NOTE: this is not permitted for #SYNCH items.
-- IN
-- itemtype - item type
-- itemkey - item key
-- actid
- process activity instance id
-- funcmode - execution mode
-- OUT
-- result
- NULL
-- ACTIVITY ATTRIBUTES REFERENCED
-- NEW_ITEMKEY - the itemkey for the new item (required)
-- SAME_VERSION - TRUE creates a duplicate, FALSE uses the latest version
procedure ForkItem(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2) is
sitemkey varchar2(30);
sameversion boolean;
sameversionFlag varchar2(1);
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.ForkItem');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;

SItemkey := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'NEW


_ITEMKEY'));
SameVersionFlag := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, '
SAME_VERSION');
if SItemkey is null
or SameVersionFlag is null then
wf_core.token('ITEMKEY',Sitemkey);
wf_core.token('SAME_VERSION',SameVersionFlag);
wf_core.raise('WFSQL_ARGS');
end if;

if SameVersionFlag = 'T' then


sameversion := TRUE;
else
sameversion := FALSE;
end if;
-- go ahead and create the new process.
wf_engine.CreateForkProcess(Itemtype, Itemkey, SItemkey, SameVersion);
-- start the new process
wf_engine.StartForkProcess(Itemtype, SItemkey);
resultout := wf_engine.eng_completed;
exception
when others then
Wf_Core.Context('Wf_Standard', 'ForkItem', itemtype,
itemkey, to_char(actid), Sitemkey);
raise;
end ForkItem;
-- Noop
-- Does nothing
-- OUT
-- result
- NULL
procedure Noop(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
begin
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
exception
when others then
Wf_Core.Context('Wf_Standard', 'Noop', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end Noop;
-- Notify
-- Public wrapper to engine notification call
-- the engine notification package will retrieve the activity attributes.
-- OUT
-- result
- NULL
procedure Notify(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
msg varchar2(30);
msgtype varchar2(8);
prole varchar2(320);
expand_role varchar2(1);
colon pls_integer;
avalue varchar2(240);

begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- lookup notification base info
Wf_Activity.Notification_Info(itemtype, itemkey, actid, msg, msgtype,
expand_role);
-- see if this activity is already assigned to a role
prole := Wf_Activity.Perform_Role(itemtype, itemkey, actid);
-- if it isnt then use the value from activity attribute
if prole is null then
prole := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'PERFORME
R');
end if;
if prole is null then
Wf_Core.Token('TYPE', itemtype);
Wf_Core.Token('ACTID', to_char(actid));
Wf_Core.Raise('WFENG_NOTIFICATION_PERFORMER');
end if;
-- message name and expand roles will be null. Get these from attributes
avalue := upper(Wf_Engine.GetActivityAttrText(itemtype, itemkey,
actid, 'MESSAGE'));
-- let notification_send catch a missing message name.
expand_role := nvl(Wf_Engine.GetActivityAttrText(itemtype, itemkey,
actid, 'EXPANDROLES'),'N');
-- parse out the message type if given
colon := instr(avalue, ':');
if colon = 0 then
msgtype := itemtype;
msg := avalue;
else
msgtype := substr(avalue, 1, colon - 1);
msg := substr(avalue, colon + 1);
end if;
-- Actually send the notification
Wf_Engine_Util.Notification_Send(itemtype, itemkey, actid,
msg, msgtype, prole, expand_role,
resultout);
--resultout is determined by Notification_Send as either
--NULL
if notification is FYI
--NOTIFIED:notid:role if notification requires responce
exception
when others then
Wf_Core.Context('Wf_Standard', 'Notify', itemtype,

itemkey, to_char(actid), funcmode);


raise;
end Notify;
-- Block
-- Stop and wait for external completion
-- OUT
-- result
- NOTIFIED
procedure Block(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
resultout := wf_engine.eng_notified||':'||wf_engine.eng_null||
':'||wf_engine.eng_null;
exception
when others then
Wf_Core.Context('Wf_Standard', 'Block', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end Block;
-- Block
-- Defers the thread by requesting a wait of zero seconds
-- OUT
-- result
- DEFERRED
-procedure Defer(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
status
varchar2(8);
result
varchar2(30);
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- Check if this is the first or second execution of this activity.
-- First -> result_code will be null (really null).
-- Second -> result_code will be '#NULL' (set that way by execution 1).
Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
if (result = wf_engine.eng_null) then
-- Second execution.
-- Defer must have been picked up by the background engine,

-- so return complete result.


resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
else
-- Return deferred result
resultout := wf_engine.eng_deferred;
end if;
exception
when others then
Wf_Core.Context('Wf_Standard', 'Defer', itemtype, itemkey,
to_char(actid), funcmode);
raise;
end Defer;
-- Wait
-- Wait until given date and time.
-- OUT
-- result
- 'DEFERRED' or 'NULL'
-'DEFERRED' if this is the first call and wait is beginning
-'NULL' if this is the second call and wait period has completed
-- ACTIVITY ATTRIBUTES REFERENCED
-- WAIT_MODE - Lookup
-'ABSOLUTE' - Wait until date in WAIT_ABSOLUTE_DATE
-'RELATIVE' - Wait until time WAIT_RELATIVE_TIME after current date
-'DAY_OF_WEEK' - Wait until next occurrence of day of week
-'DAY_OF_MONTH' - Wait until next occurrence of day of month
-- WAIT_ABSOLUTE_DATE - Date
-Date to wait until if WAIT_MODE = 'ABSOLUTE'
-(Ignored if mode <> 'ABSOLUTE')
-- WAIT_RELATIVE_TIME - Number (expressed in <days>.<fraction of days>)
-Time to wait after current date if WAIT_MODE = 'RELATIVE'
-(Ignored if mode <> 'RELATIVE')
-- WAIT_DAY_OF_WEEK - Lookup
-Next day of week (SUNDAY, MONDAY, etc) after current date
-(Ignored if mode <> 'DAY_OF_WEEK')
-- WAIT_DAY_OF_MONTH - Lookup
-Next day of month (1, 2, ..., 31, LAST) after current date
-(Ignored if mode <> 'DAY_OF_MONTH')
-- WAIT_TIME - Date (format HH24:MI)
-Time of day to complete activity. Valid for all wait modes.
-If null default time to 00:00 (midnight), except RELATIVE mode.
-For RELATIVE mode, if time is null then complete relative to current
-date and time.
-- NOTE:
-For all WAIT_MODEs, the completion day is determined by the attribute
-- associated with the mode, and the completion time by the WAIT_TIME
-- attribute.
-For all modes except RELATIVE, the completion time is WAIT_TIME on
-- the day selected by the mode's attribute. If WAIT_TIME is null, the
-- default is 00:00 (midnight).
-For RELATIVE mode, if WAIT_TIME is null the completion time is
-- figured relative to the current date and time. If WAIT_TIME is not
-- null the completion time is WAIT_TIME on the day selected regardless
-- of the current time.
procedure Wait(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is

status
varchar2(8);
result
varchar2(30);
wait_mode varchar2(30);
wait_date date;
wakeup
date;
daybuf
varchar2(30);
time
date;
wf_invalid_mode exception;
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.Wait');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
-- Check if this is the first or second execution of this activity.
-- First -> result_code will be null (really null).
-- Second -> result_code will be '#NULL' (set that way by execution 1).
Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
if (result = wf_engine.eng_null) then
-- Second execution.
-- Wait is completed, return complete result.
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
else
-- First execution.
wait_mode := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
'WAIT_MODE');
if (wait_mode = 'ABSOLUTE') then
-- Absolute date
wakeup := Wf_Engine.GetActivityAttrDate(itemtype, itemkey, actid,
'WAIT_ABSOLUTE_DATE');
elsif (wait_mode = 'RELATIVE') then
-- Relative date. Figure offset from sysdate.
wakeup := Wf_Engine.GetActivityAttrNumber(itemtype, itemkey, actid,
'WAIT_RELATIVE_TIME') + sysdate;
elsif (wait_mode = 'DAY_OF_WEEK') then
-- Day of week.
daybuf := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
'WAIT_DAY_OF_WEEK');
wakeup := next_day(trunc(sysdate), daybuf);
elsif (wait_mode = 'DAY_OF_MONTH') then
daybuf := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
'WAIT_DAY_OF_MONTH');
-- Figure wakeup time as offset from beginning of current month
if (daybuf = 'LAST') then
-- Set to last day of current month
wakeup := last_day(to_date('01/'||to_char(sysdate, 'MM/YYYY'),
'DD/MM/YYYY'));

else
-- Set to day x of current month
wakeup := to_date('01/'||to_char(sysdate, 'MM/YYYY'),
'DD/MM/YYYY') + to_number(daybuf) - 1;
end if;
-- If wakeup is before current date, then shift to next month
if (wakeup <= sysdate) then
if (daybuf = 'LAST') then
-- Set to last day of following month
wakeup := last_day(add_months(to_date('01/'||to_char(sysdate,
'MM/YYYY'),
'DD/MM/YYYY'), 1));
else
-- Set to day x of the following month
wakeup := add_months(to_date('01/'||to_char(sysdate, 'MM/YYYY'),
'DD/MM/YYYY'), 1)
+ to_number(daybuf) - 1;
end if;
end if;
else
raise wf_invalid_mode;
end if;
-- Add the WAIT_TIME to the wakeup if specified
time := Wf_Engine.GetActivityAttrDate(itemtype, itemkey, actid,
'WAIT_TIME');
if (time is not null) then
wakeup := to_date(to_char(wakeup, 'DD/MM/YYYY')||
to_char(time, ' HH24:MI'), 'DD/MM/YYYY HH24:MI');
end if;
-- Return deferred result with wakeup time appended
resultout := wf_engine.eng_deferred||':'||
to_char(wakeup, wf_engine.date_format);
end if;
exception
when wf_invalid_mode then
Wf_Core.Context('Wf_Standard', 'Wait', itemtype, itemkey,
to_char(actid), funcmode);
Wf_Core.Token('COMMAND', wait_mode);
Wf_Core.Raise('WFSQL_COMMAND');
when others then
Wf_Core.Context('Wf_Standard', 'Wait', itemtype, itemkey,
to_char(actid), funcmode);
raise;
end Wait;
-- ResetError
-- Reset the status of an errored activity in an WFERROR process.
-- OUT
-- result
- 'NULL'
-- ACTIVITY ATTRIBUTES REFERENCED
-- COMMAND - 'SKIP' or 'RETRY'
-'SKIP' marks the errored activity complete and continues processing
-'RETRY' clears the errored activity and runs it again
-- RESULT - Result code to complete the activity with if COMMAND = 'SKIP'

procedure ResetError(itemtype in varchar2,


itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
cmd varchar2(8);
result varchar2(30);
err_itemtype varchar2(8);
err_itemkey varchar2(240);
err_actlabel varchar2(62);
wf_invalid_command exception;
begin
-- Do nothing in cancel or timeout mode
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.ResetError');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
-- Get RETRY or SKIP command
cmd := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid, 'COMMAND');
-- Get original errored activity info
err_itemtype := Wf_Engine.GetItemAttrText(itemtype, itemkey,
'ERROR_ITEM_TYPE');
err_itemkey := Wf_Engine.GetItemAttrText(itemtype, itemkey,
'ERROR_ITEM_KEY');
err_actlabel := Wf_Engine.GetItemAttrText(itemtype, itemkey,
'ERROR_ACTIVITY_LABEL');
if (cmd = wf_engine.eng_retry) then
-- Rerun activity
Wf_Engine.HandleError(err_itemtype, err_itemkey, err_actlabel,
cmd, '');
/* Disallow skip mode because it is too difficult to
assign and validate the RESULT value
elsif (cmd = wf_engine.eng_skip) then
-- Get result code
result := Wf_Engine.GetActivityAttrText(itemtype, itemkey, actid,
'RESULT');
-- Mark activity complete and continue processing
Wf_Engine.HandleError(err_itemtype, err_itemkey, err_actlabel,
cmd, result);
*/
else
raise wf_invalid_command;
end if;
resultout := wf_engine.eng_null;
exception
when wf_invalid_command then
Wf_Core.Context('Wf_Standard', 'ResetError', itemtype,
itemkey, to_char(actid), funcmode);

Wf_Core.Token('COMMAND', cmd);
Wf_Core.Raise('WFSQL_COMMAND');
when others then
Wf_Core.Context('Wf_Standard', 'ResetError', itemtype,
itemkey, to_char(actid), funcmode);
raise;
end ResetError;
-- RoleResolution
-- Resolve A Role which comprises a group to an individual
-- OUT
-- result
- 'NULL'
-- ACTIVITY ATTRIBUTES REFERENCED
-- COMMAND - 'LOAD_BALANCE' or 'ROUND_ROBIN'
-'LOAD_BALANCE' Assigns to user with least open notifications
-'ROUND_ROBIN' Assigns notification to users sequencially
procedure RoleResolution(itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2) is
cmd
varchar2(30);
wf_invalid_command
exception;
actdate
date;
label
varchar2(30);
prole
varchar2(320);
--- select all out-transitions of RoleResolution Activity
-cursor out_transitions is
SELECT wat.to_process_activity,
wpa.activity_name,
wpa.perform_role,
wpa.perform_role_type
FROM
wf_activity_transitions wat,
wf_process_activities wpa
WHERE wat.from_process_activity
= actid
AND
wat.result_code
= wf_engine.eng_trans_default
AND
wat.to_process_activity
= wpa.instance_id;
--- select number of activities the user currently has in worklist
-cursor load_balance(user in varchar2, act_name varchar2 ) is
select count(1)
from
wf_item_activity_statuses wias,
wf_process_activities wpa
where wias.item_type
= itemtype
and
wias.activity_status
= 'NOTIFIED'
and
wias.process_activity = wpa.instance_id
and
wpa.activity_name
= act_name
and
assigned_user
= user;
--- select the date of the last time the user was notified
-cursor round_robin(user in varchar2, act_name varchar2 ) is
select max(begin_date)
from
wf_item_activity_statuses wias,
wf_process_activities wpa
where wias.item_type
= itemtype

and
wias.process_activity = wpa.instance_id
and
wpa.activity_name
= act_name
and
wias.assigned_user
= user;
-begin
--- Do nothing in cancel mode
-if (funcmode <> wf_engine.eng_run ) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.AndJoin');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
actdate := wf_item.active_date(itemtype, itemkey);
cmd := Wf_Engine.GetActivityAttrText(itemtype,itemkey,actid,'METHOD');
-- loop thru all out-transiations of role resolution activity
for trans_rec in out_transitions loop
declare
usertab
wf_directory.UserTable;
min_assigned_activities number := -1;
min_begin_date
date;
assigned_performer
varchar2(320);
begin
-if (Wf_Activity.Type(itemtype, trans_rec.activity_name, actdate) =
wf_engine.eng_notification) then
-- Get perform_role from constant or itemattr value
if (trans_rec.perform_role_type = 'CONSTANT') then
prole := trans_rec.perform_role;
else
prole := Wf_Engine.GetItemAttrText(itemtype, itemkey,
trans_rec.perform_role);
end if;
wf_directory.GetRoleUsers(prole,usertab);
if ( cmd = 'LOAD_BALANCE' ) then
declare
assigned_activities
number := 0;
indx
number := 1;
begin
loop -- loop until NO_DATA_FOUND
open
load_balance(usertab(indx),
trans_rec.activity_name);
fetch load_balance into assigned_activities;
close load_balance;
if ((assigned_activities < min_assigned_activities or
min_assigned_activities = -1) and
wf_directory.UserActive(usertab(indx))) then
min_assigned_activities := assigned_activities;
assigned_performer
:= usertab(indx);
end if;
indx := indx + 1;

end loop;
exception
when NO_DATA_FOUND then
null;
end;
elsif ( cmd = 'ROUND_ROBIN' ) then
declare
begin_date
date;
indx
number :=1;
begin
loop -- until access of usertab raises NO_DATA_FOUND
open
round_robin(usertab(indx),
trans_rec.activity_name);
fetch round_robin into begin_date;
close round_robin;
if (begin_date is null) then
begin_date := to_date('01/01/0001','DD/MM/YYYY');
end if;
if ((begin_date < min_begin_date or
min_begin_date is null) and
wf_directory.UserActive(usertab(indx))) then
min_begin_date
:= begin_date;
assigned_performer
:= usertab(indx);
end if;
indx := indx + 1;
end loop;
exception
when NO_DATA_FOUND then
null;
end;
else
raise wf_invalid_command;
end if;
if ( assigned_performer is not null ) then
--- Retreieve instance_label for activity
-select wpa.instance_label
into label
from wf_process_activities wpa
where wpa.instance_id = trans_rec.to_process_activity;
wf_engine.AssignActivity(itemtype,itemkey,label,
assigned_performer);
end if;
resultout := wf_engine.eng_null;
end if;
end;
end loop;
exception
when wf_invalid_command then
wf_core.context('Wf_Standard', 'RoleResoluion',
itemtype, itemkey, to_char(actid), funcmode);
wf_core.token('COMMAND', cmd);

wf_core.raise('WFSQL_COMMAND');
when others then
wf_core.Context('Wf_Standard', 'RoleResolution',
itemtype, itemkey, to_char(actid), funcmode);
raise;
end RoleResolution;
-- ContinueFlow
-- Signal Flow to continue
-- OUT
-- result
- 'NULL'
-- ACTIVITY ATTRIBUTES REFERENCED
-- WAITING_ACTIVITY
-- WAITING_FLOW
procedure ContinueFlow( itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2 ) is
l_waiting_activity
varchar2(30);
l_waiting_flow
varchar2(30);
wf_invalid_command
exception;
begin
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.AndJoin');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
l_waiting_activity := upper(Wf_Engine.GetActivityAttrText(
itemtype, itemkey, actid,'WAITING_ACTIVITY'));
l_waiting_flow
:= Wf_Engine.GetActivityAttrText(
itemtype, itemkey, actid,'WAITING_FLOW');
if ( l_waiting_flow = 'MASTER' ) then
ContinueMasterFlow(itemtype,itemkey,actid,l_waiting_activity,resultout);
elsif ( l_waiting_flow = 'DETAIL' ) then
ContinueDetailFlow(itemtype,itemkey,actid,l_waiting_activity,resultout);
else
raise wf_invalid_command;
end if;
exception
when wf_invalid_command then
Wf_Core.Context('Wf_Standard', 'ContinueFlow',
itemtype,itemkey, to_char(actid), funcmode);
Wf_Core.Token('COMMAND', l_waiting_flow );
Wf_Core.Raise('WFSQL_COMMAND');
when others then
Wf_Core.Context('Wf_Standard', 'ContinueFlow',
itemtype,itemkey, to_char(actid), funcmode);
raise;
end continueflow;

-- WaitForFlow
-- Wait for flow to complete
-- OUT
-- result
- 'NULL'
-- ACTIVITY ATTRIBUTES REFERENCED
-- CONTINUATION_ACTIVITY
-- CONTINUATION_FLOW
procedure WaitForFlow( itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2) is
l_continuation_activity varchar2(30);
l_continuation_flow
varchar2(30);
wf_invalid_command
exception;
begin
if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.WaitForFlow');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
l_continuation_activity := upper(Wf_Engine.GetActivityAttrText(
itemtype, itemkey, actid,
'CONTINUATION_ACTIVITY'));
l_continuation_flow
:= Wf_Engine.GetActivityAttrText(
itemtype,itemkey,actid,'CONTINUATION_FLOW');
if ( l_continuation_flow = 'MASTER' ) then
WaitForMasterFlow(itemtype,itemkey,actid,
l_continuation_activity,resultout);
elsif ( l_continuation_flow = 'DETAIL' ) then
WaitForDetailFlow(itemtype,itemkey,actid,
l_continuation_activity,resultout);
else
raise wf_invalid_command;
end if;
exception
when wf_invalid_command then
Wf_Core.Context('Wf_Standard', 'WaitForFlow',
itemtype,itemkey, to_char(actid), funcmode);
Wf_Core.Token('COMMAND', l_continuation_flow );
Wf_Core.Raise('WFSQL_COMMAND');
when others then
Wf_Core.Context('Wf_Standard', 'WaitForFlow',
itemtype,itemkey, to_char(actid), funcmode);
raise;
end WaitForFlow;
-- LoopCounter
-Count the number of times the activity has been visited.
-- OUT

-- result
-- ACTIVITY ATTRIBUTES REFERENCED
-MAX_TIMES
procedure LoopCounter( itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2) is
max_times
pls_integer;
loop_count
pls_integer;
begin
--- Do nothing in cancel mode
-if (funcmode <> wf_engine.eng_run) then
resultout := wf_engine.eng_null;
return;
end if;
-- Get maximum times activity can be executed.
max_times := wf_engine.GetActivityAttrNumber(
itemtype, itemkey, actid, 'MAX_TIMES');
if ( max_times is null ) then
wf_core.token('MAX_TIMES',max_times);
wf_core.raise('WFSQL_ARGS');
end if;
begin
loop_count := wf_engine.GetItemAttrNumber(
itemtype, itemkey, 'LOOP_COUNT'||':'||actid);
exception
when others then
--- If item attribute does not exist then create it;
-if ( wf_core.error_name = 'WFENG_ITEM_ATTR' ) then
wf_engine.AddItemAttr(
itemtype,itemkey, 'LOOP_COUNT'||':'||actid);
loop_count := 0;
else
raise;
end if;
end;
if ( loop_count >= max_times ) then
loop_count := 0;
resultout := 'EXIT';
else
loop_count := loop_count +1;
resultout := 'LOOP';
end if;
wf_engine.SetItemAttrNumber(
itemtype, itemkey, 'LOOP_COUNT'||':'||actid,loop_count);
exception
when others then
wf_core.context('Wf_Standard','LoopCount',
itemtype, itemkey, to_char(actid), funcmode);
raise;
end loopcounter;

-- VoteForResultType
-Standard Voting Function
-- IN
-- itemtype - A valid item type from (WF_ITEM_TYPES table).
-- itemkey - A string generated from the application object's primary key.
-- actid
- The process activity(instance id).
-- funcmode - Run/Cancel
-- OUT
-- result
--- USED BY ACTIVITIES
--- WFSTD.VoteForResultType
--- ACTIVITY ATTRIBUTES REFERENCED
-VOTING_OPTION
-- WAIT_FOR_ALL_VOTES - Evaluate voting after all votes are cast
-- or a Timeout condition closes the voting
-- polls. When a Timeout occurs the
-- voting percentages are calculated as a
-- percentage ofvotes cast.
--- REQUIRE_ALL_VOTES - Evaluate voting after all votes are cast.
-- If a Timeout occurs and all votes have not
-- been cast then the standard timeout
-- transition is taken. Votes are calculated
-- as a percenatage of users notified to vote.
--- TALLY_ON_EVERY_VOTE - Evaluate voting after every vote or a
-- Timeout condition closes the voting polls.
-- After every vote voting percentages are
-- calculated as a percentage of user notified
-- to vote. After a timeout voting
-- percentages are calculated as a percentage
-- of votes cast.
--"One attribute for each of the activities result type codes"
--- The standard Activity VOTEFORRESULTTYPE has the WFSTD_YES_NO
-- result type assigned.
-- Thefore activity has two activity attributes.
--Y
- Percenatage required for Yes transition
-N
- Percentage required for No transition
-procedure VoteForResultType(
itemtype in varchar2,
itemkey
in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
-- Select all lookup codes for an activities result type
cursor result_codes is
select wfl.lookup_code result_code
from
wf_lookups wfl,
wf_activities wfa,
wf_process_activities wfpa,
wf_items wfi

where
and
and
and
and
and
and
and

wfl.lookup_type
wfa.name
wfi.begin_date
wfi.begin_date
wfpa.activity_item_type
wfpa.instance_id
wfi.item_key
wfi.item_type

= wfa.result_type
= wfpa.activity_name
>= wfa.begin_date
< nvl(wfa.end_date,wfi.begin_date+1)
= wfa.item_type
= actid
= itemkey
= itemtype;

l_code_count
pls_integer;
l_group_id
pls_integer;
l_user
varchar2(320);
l_voting_option varchar2(30);
l_per_of_total number;
l_per_of_vote number;
l_per_code
number;
per_success
number;
max_default
pls_integer := 0;
default_result varchar2(30) := '';
result
varchar2(30) := '';
wf_invalid_command exception;
begin
-- Do nothing unless in RUN or TIMEOUT modes
if (funcmode <> wf_engine.eng_run)
and (funcmode <> wf_engine.eng_timeout) then
resultout := wf_engine.eng_null;
return;
end if;
-- SYNCHMODE: Not allowed
if (itemkey = wf_engine.eng_synch) then
Wf_Core.Token('OPERATION', 'Wf_Standard.VotForResultType');
Wf_Core.Raise('WFENG_SYNCH_DISABLED');
end if;
-- Get Notifications group_id for activity
Wf_Item_Activity_Status.Notification_Status(itemtype,itemkey,actid,
l_group_id,l_user);
l_voting_option := Wf_Engine.GetActivityAttrText(itemtype,itemkey,
actid,'VOTING_OPTION');
if (l_voting_option not in ('REQUIRE_ALL_VOTES', 'WAIT_FOR_ALL_VOTES',
'TALLY_ON_EVERY_VOTE')) then
raise wf_invalid_command;
end if;
------if

If the mode is one of:


a. REQUIRE_ALL_VOTES
b. WAIT_FOR_ALL_VOTES and no timeout has occurred
and there are still open notifications, then return WAITING to
either continue voting (in run mode) or trigger timeout processing
(in timeout mode).
((l_voting_option = 'REQUIRE_ALL_VOTES') or
((funcmode = wf_engine.eng_run) and
(l_voting_option = 'WAIT_FOR_ALL_VOTES'))) then
if (wf_notification.OpenNotificationsExist(l_group_id)) then
resultout := wf_engine.eng_waiting;
return;
end if;
end if;

-- If here, then the mode is one of:


-- a. TALLY_ON_ALL_VOTES
-- b. WAIT_FOR_ALL_VOTES and timeout has occurred
-- c. WAIT_FOR_ALL_VOTES and all votes are cast
-- d. REQUIRE_ALL_VOTES and all votes are cast
-- Tally votes.
for result_rec in result_codes loop
-- Tally Vote Count for this result code
Wf_Notification.VoteCount(l_group_id,result_rec.result_code,
l_code_count,l_per_of_total,l_per_of_vote);
-- If this is timeout mode, then use the percent of votes cast so far.
-- If this is run mode, then use the percent of total votes possible.
if (funcmode = wf_engine.eng_timeout) then
l_per_code := l_per_of_vote;
else
l_per_code := l_per_of_total;
end if;
-- Get percent vote needed for this result to succeed
per_success := Wf_Engine.GetActivityAttrNumber(itemtype,itemkey,
actid,result_rec.result_code);
if (per_success is null) then
-- Null value means this is a default result.
-- Save the default result with max code_count.
if (l_code_count > max_default) then
max_default := l_code_count;
default_result := result_rec.result_code;
elsif (l_code_count = max_default) then
-- Tie for default result.
default_result := wf_engine.eng_tie;
end if;
else
-- If:
-- a. % vote for this result > % needed for success OR
-- b. % vote is 100% AND
-- c. at least 1 vote for this result
-- then this result succeeds.
if (((l_per_code > per_success) or (l_per_code = 100)) and
(l_code_count > 0))
then
if (result is null) then
-- Save satisfied result.
result := result_rec.result_code;
else
-- This is the second result to be satisfied. Return a tie.
resultout := wf_engine.eng_completed||':'||wf_engine.eng_tie;
return;
end if;
end if;
end if;
end loop;
if (result is not null) then
-- Return the satisfied result code.
resultout := wf_engine.eng_completed||':'||result;
else
-- If we get here no non-default results were satisfied.
if (funcmode = wf_engine.eng_run and

wf_notification.OpenNotificationsExist(l_group_id)) then
-- Not timed out and still open notifications.
-- Return waiting to continue voting.
resultout := wf_engine.eng_waiting;
elsif (default_result is not null) then
-- Either timeout or all notifications closed
-- Return default result if one found.
resultout := wf_engine.eng_completed||':'||default_result;
elsif (funcmode = wf_engine.eng_timeout) then
-- If Timeout has occured then return result Timeout so the Timeout
-- transition will occur - BUG2885157
resultout := wf_engine.eng_completed||':'||wf_engine.eng_timedout;
else
-- All notifications closed, and no default.
-- Return nomatch
resultout := wf_engine.eng_completed||':'||wf_engine.eng_nomatch;
end if;
end if;
return;
exception
when wf_invalid_command then
Wf_Core.Context('Wf_Standard', 'VoteForResultType', itemtype,
itemkey, to_char(actid), funcmode);
Wf_Core.Token('COMMAND', l_voting_option);
Wf_Core.Raise('WFSQL_COMMAND');
when others then
Wf_Core.Context('Wf_Standard', 'VoteForResultType',itemtype,
itemkey, to_char(actid), funcmode);
raise;
end VoteForResultType;
------------------------------------------------------------------------------------------------------------- PRIVATE APIs ------------------------------------------------------------------------------------------------------------------ WaitForMasterFlow
-- Wait for Master flow to complete continuation activity
-- OUT
-- result
- 'NULL'
procedure WaitForMasterFlow(
itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
continuation_activity in varchar2,
resultout
out nocopy varchar2 )
is
l_parent_itemtype
varchar2(8);
l_parent_itemkey
varchar2(240);
l_activity_status
varchar2(30);
colon pls_integer;
process varchar2(30);
label varchar2(30);
instid pls_integer;
dummy varchar2(50);
begin
-- Parse activity arg into <process_name> and <instance_label> components.
colon := instr(continuation_activity, ':');

if (colon <> 0) then


-- Activity arg is <process name>:<instance label>
process := substr(continuation_activity, 1, colon-1);
label := substr(continuation_activity, colon+1);
else
-- Activity arg is just instance label
process := '';
label := continuation_activity;
end if;
select
into
from
where
and

parent_item_type, parent_item_key
l_parent_itemtype, l_parent_itemkey
wf_items
item_type
= WaitForMasterFlow.itemtype
item_key
= WaitForMasterFlow.itemkey;

begin
select 'master activity not complete'
into dummy
from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA
where WIAS.ITEM_TYPE = l_parent_itemtype
and WIAS.ITEM_KEY = l_parent_itemkey
and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
and WPA.INSTANCE_LABEL = label
and WPA.PROCESS_NAME = nvl(process, WPA.PROCESS_NAME)
and wias.activity_status in (wf_engine.eng_completed, wf_engine.eng_act
ive);
exception
-- When not complete return NOTIFIED to cause engine to stall
when NO_DATA_FOUND then
resultout := wf_engine.eng_notified||':'||wf_engine.eng_null|| ':'||
wf_engine.eng_null;
return;
end;
resultout := wf_engine.eng_null;
exception
when others then
wf_core.context('Wf_Standard', 'WaitForMasterFlow',
itemtype,itemkey,to_char(actid),continuation_activity);
raise;
end WaitForMasterFlow;
-- WaitForDetailFlow
-- Wait for detail flows to complete continuation activity
-- OUT
-- result
- 'NULL'
procedure WaitForDetailFlow(
itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
continuation_activity in varchar2,
resultout
out nocopy varchar2) is
cursor child_flows is
-- select all active children of parent flow
select count(1)
from
wf_items
where parent_item_type
= itemtype
and
parent_item_key
= itemkey
and
end_date
is null;

cursor child_activities (itemtype varchar2, itemkey varchar2,


pname varchar2, plabel varchar2) is
select count(1)
from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA
where (WIAS.ITEM_TYPE, WIAS.ITEM_KEY) in (select item_type,item_key
from wf_items
where parent_item_type =itemtype
and parent_item_key =itemkey
and end_date is null)
and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
and WPA.INSTANCE_LABEL = plabel
and WPA.PROCESS_NAME = nvl(pname, WPA.PROCESS_NAME)
and wias.activity_status in (wf_engine.eng_completed, wf_engine.eng_active)
;
cursor current_process (p_actid number) is
select instance_label
from wf_process_activities
where instance_id = p_actid;
colon pls_integer;
process varchar2(30);
label varchar2(30);
instid pls_integer;
number_active pls_integer;
number_complete pls_integer;
l_childCount number;
l_labelCount number;
l_waitLabel varchar2(30);
begin
-- Parse activity arg into <process_name> and <instance_label> components.
colon := instr(continuation_activity, ':');
if (colon <> 0) then
-- Activity arg is <process name>:<instance label>
process := substr(continuation_activity, 1, colon-1);
label := substr(continuation_activity, colon+1);
else
-- Activity arg is just instance label
process := '';
label := continuation_activity;
end if;
--Retrieve the label for the WaitForFlow activity.
open current_process(actid);
fetch current_process into l_waitLabel;
close current_process;
l_labelCount := WF_ENGINE.GetItemAttrNumber(itemType, itemKey,
'#CNT_'||l_waitLabel, TRUE);
if (l_labelCount is NULL) then
l_childCount := WF_ENGINE.GetItemAttrNumber(itemType, itemKey,
'#WAITFORDETAIL', TRUE);
if (l_childCount is NULL) then --Fall back to the old path.
open child_flows;
fetch child_flows into number_active;
close child_flows;
if (number_active < 1) then

resultout := wf_engine.eng_null;
else
open child_activities(itemtype, itemkey, process, label);
fetch child_activities into number_complete;
close child_activities;
if number_active > number_complete then
resultout := wf_engine.eng_notified||':'||
wf_engine.eng_null||':'||wf_engine.eng_null;
else
resultout := wf_engine.eng_null;
end if;
end if; --There are no children
else --#WAITFORDETAIL exists
WF_ENGINE.AddItemAttr(itemtype=>WaitForDetailFlow.itemtype,
itemkey=>WaitForDetailFlow.itemkey,
aname=>'#CNT_'||l_waitLabel,
number_value=>l_childCount);
if (l_childCount > 0) then
resultout := wf_engine.eng_notified||':'||
wf_engine.eng_null||':'||wf_engine.eng_null;
else
resultout := wf_engine.eng_null;
end if; --l_childCount > 0
end if; -- #WAITFORDETAIL
elsif (l_labelCount > 0) then
--The #CNT_ attribute exists and is 1 or greater so this will remain
--notified.
resultout := wf_engine.eng_notified||':'||wf_engine.eng_null||
':'||wf_engine.eng_null;
else --The labelcount exists and is < 1 so we can continue.
resultout := wf_engine.eng_null;
end if;
exception
when others then
wf_core.context('Wf_Standard', 'WaitForDetailFlow',
itemtype,itemkey,to_char(actid),continuation_activity);
raise;
end WaitForDetailFlow;
-- ContinueDetailFlow
-- Signal Detail Flows to continue
-- IN
-- itemtype - A valid item type from (WF_ITEM_TYPES table).
-- itemkey - A string generated from the application object's primary key.
-- actid
- The process activity(instance id).
-- waiting_activity - The Name of the activity that in waiting
-- OUT
-- resultout
- 'NULL'
procedure ContinueDetailFlow( itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
waiting_activity
in varchar2,
resultout
out nocopy varchar2
) is

-cursor child_flows is
--- select all active children of parent flow
-select item_type, item_key
from
wf_items
where parent_item_type
= itemtype
and
parent_item_key
= itemkey
and
end_date
is null;
-begin
for child_flows_rec in child_flows loop
--- Complete Waiting Activity in All Detail Flows
-begin
wf_engine.CompleteActivity(child_flows_rec.item_type,
child_flows_rec.item_key, waiting_activity,wf_engine.eng_null);
exception
when others then
-- If call to CompleteActivity cannot find activity, return null
-- As either the detail flows does not have a waiting activity OR
-- the detail flow has not reach the waiting activity
if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
wf_core.clear;
else
raise;
end if;
end;
end loop;
ContinueDetailFlow.resultout := wf_engine.eng_null;
exception
when others then
wf_core.context('Wf_Standard','ContinueDetailFlow',
itemtype, itemkey, to_char(actid),waiting_activity);
raise;
end ContinueDetailFlow;
-- ContinueMasterFlow
-- Signal Master Flow to continue if all Detail flows have
-- executed Continuation Activity
-- OUT
-- result
- 'NULL'
procedure ContinueMasterFlow( itemtype
in varchar2,
itemkey
in varchar2,
actid
in number,
waiting_activity
in varchar2,
resultout
in out nocopy varchar2)
is
l_activity_status
varchar2(8);
l_parent_itemtype
varchar2(8);
l_parent_itemkey
varchar2(240);
label
varchar2(30);
number_active pls_integer;

number_complete pls_integer;
-- CTILLEY bug 1941013
l_parent_context varchar2(2000);
cursor child_flows_mwf is
-- This cursor is used if there are multiple WaitForFlow Activities in the
-- parent flow (the parent_context must be set). CTILLEY bug 1941013
-- select all active children of parent flow excluding current work item
select count(1)
from
wf_items
where parent_item_type
= l_parent_itemtype
and
parent_item_key
= l_parent_itemkey
and
parent_context
= l_parent_context
and
(item_type
<> ContinueMasterFlow.itemtype
or item_key
<> ContinueMasterFlow.itemkey)
and
end_date
is null;
cursor child_flows2 is
-- select all active children of parent flow excluding current work item
select count(1)
from
wf_items
where parent_item_type
= l_parent_itemtype
and
parent_item_key
= l_parent_itemkey
and
(item_type
<> ContinueMasterFlow.itemtype
or item_key
<> ContinueMasterFlow.itemkey)
and
end_date
is null;
cursor child_activities2 is
select count(1)
from WF_ITEM_ACTIVITY_STATUSES WIAS, WF_PROCESS_ACTIVITIES WPA,
WF_ITEMS WI
where WIAS.ITEM_TYPE
= itemtype
and WIAS.ITEM_KEY
= WI.item_key
and WI.parent_item_type = l_parent_itemtype
and WI.parent_item_key = l_parent_itemkey
and (WI.item_type <> itemtype OR WI.item_key <> itemkey )
and WI.end_date is null
and WIAS.PROCESS_ACTIVITY = WPA.INSTANCE_ID
and WPA.INSTANCE_LABEL = label
and wias.activity_status in (wf_engine.eng_completed,
wf_engine.eng_active);
dummy varchar2(240);
status varchar2(8);
result varchar2(30);
l_count number;
l_defer varchar2(4000);
l_childwaiting number;
begin
--- select parent details
-select parent_item_type, parent_item_key, parent_context
into
l_parent_itemtype, l_parent_itemkey, l_parent_context
from
wf_items
where item_type = ContinueMasterFlow.itemtype
and
item_key = ContinueMasterFlow.itemkey;
select instance_label

into
from
where

label
wf_process_activities
instance_id
= actid;

-- Check if this is the first or second execution of this activity.


-- First -> result_code will be null (really null).
-- Second -> result_code will be '#NULL' (set that way by execution 1).
Wf_Item_Activity_Status.Result(itemtype, itemkey, actid, status, result);
if (result = wf_engine.eng_null) then
-- Second execution.
-- ContinueFlow() completed and was deferred.
resultout := wf_engine.eng_completed||':'||wf_engine.eng_null;
return;
else
--First execution.
-- lock the parent item, so only one child can execute this at the time.
select item_key
into
dummy
from
wf_items
where item_type
= l_parent_itemtype
and
item_key
= l_parent_itemkey
for update;
--Nulling out the #LBL_ attribute, if it does not exist, we will check the
--parent flow for #WAITFORDETAIL to see if we can create the #LBL_
--attribute.
if NOT (WF_ENGINE.SetItemAttrText2(ContinueMasterFlow.itemtype,
ContinueMasterFlow.itemkey,
'#LBL_'||waiting_activity,
NULL)) then
l_childwaiting := WF_ENGINE.GetItemAttrNumber(
l_parent_itemtype, l_parent_itemkey,
'#WAITFORDETAIL', TRUE);
if (l_childwaiting is NOT NULL) then
--The parent has #WAITFORDETAIL, so we can create the #LBL_ attribute
WF_ENGINE.AddItemAttr(ContinueMasterFlow.itemtype,
ContinueMasterFlow.itemkey,
'#LBL_'||waiting_activity, NULL);
else --#WAITFORDETAIL does not exist in the parent, so we will fall back
--to old code path.
-- If parent_context is not set then there is one WaitForFlow Activity
-- use original cursor.
if (l_parent_context is null) then
open child_flows2;
fetch child_flows2 into number_active;
close child_flows2;
else
open child_flows_mwf;
fetch child_flows_mwf into number_active;
close child_flows_mwf;
end if;
if (number_active < 1) then
begin
wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
waiting_activity,wf_engine.eng_null);

resultout := wf_engine.eng_null;
exception
when OTHERS then
if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
wf_core.clear;
ContinueMasterFlow.resultout := wf_engine.eng_null;
else
raise;
end if;
end;
else
open child_activities2;
fetch child_activities2 into number_complete;
close child_activities2;
begin
if number_active = number_complete then
wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
waiting_activity,wf_engine.eng_null);
end if;
resultout := wf_engine.eng_null;
exception
when others then
--- If call to CompleteActivity cannot find activity, return
-- null and wait for master flow
-if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then
wf_core.clear;
ContinueMasterFlow.resultout := wf_engine.eng_null;
else
raise;
end if;
end;
end if; -- number_active was more than 0
return; -- done with old code path
end if; --#WAITFORDETAIL exists in the parent
end if; --#LBL_ is not null
-- If we come to here, we must be progressing in the new code path.
--Now we will try to decrement the corresponding #CNT_ attribute if it
--exists, and will create it with a value of 0 if it does not yet exist.
l_count := WF_ENGINE.AddToItemAttrNumber(l_parent_itemtype,
l_parent_itemkey,
'#CNT_'||waiting_activity, -1);
if (l_count is NULL) then
WF_ENGINE.AddItemAttr(itemtype=>l_parent_itemtype,
itemkey=>l_parent_itemkey,
aname=>'#CNT_'||waiting_activity,
number_value=>l_childwaiting - 1);
elsif (l_count < 1) then
begin
wf_engine.CompleteActivity(l_parent_itemtype,l_parent_itemkey,
waiting_activity,wf_engine.eng_null);
exception
when OTHERS then
if ( wf_core.error_name = 'WFENG_NOT_NOTIFIED' ) then

wf_core.clear;
ContinueMasterFlow.resultout := wf_engine.eng_null;
else
raise;
end if;
end;
end if;
l_defer := WF_ENGINE.GetActivityAttrText(itemtype, itemkey, actid,
'#HINT', TRUE);
--If #HINT is not set to 'NO_DEFER', or is null we will set the
--threshold to cause the next activity to defer.
if ((l_defer is null) or (l_defer <> 'NO_DEFER')) then
resultout := wf_engine.eng_deferred;
else
resultout := wf_engine.eng_null;
end if;
end if; --First execution
exception
when others then
wf_core.context('Wf_Standard', 'ContinueMasterFlow',
itemtype, itemkey, to_char(actid), waiting_activity);
raise;
end ContinueMasterFlow;

-- -------------------------------------------------------------------- InitializeErrors
-- checks if an item attribute for Workflow administrator exists in
-- the item that just errored out. If it does, then it uses this
-- role to send notifications to, overriding the default role
-- in this item.
-- NOTE: the item attibute in the workflow-in-error must have an
-- internal name of WF_ADMINISTRATOR.
--- Called by default error process.
-- ------------------------------------------------------------------PROCEDURE InitializeErrors(
itemtype
VARCHAR2,
itemkey
VARCHAR2,
actid
NUMBER,
funcmode
VARCHAR2,
result
OUT NOCOPY VARCHAR2 ) IS
l_error_itemtype
l_error_itemkey
l_error_name
l_error_msg
l_timeout
l_administrator

VARCHAR2(8);
VARCHAR2(240);
VARCHAR2(30);
VARCHAR2(2000);
PLS_INTEGER;
VARCHAR2(100);

BEGIN
IF (funcmode = 'RUN') THEN
--

-- Get the type and the key of the process that errored out
-- these were set in the erroring out process by Execute_Error_Process
-l_error_itemkey := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ITEM_KEY' );
l_error_itemtype := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ITEM_TYPE' );
--- Check if the workflow administrator exists
-- If it does, then assign the notification to this role
-begin
--if this item type doesnt exist an exception is raised.
l_administrator := WF_ENGINE.GetItemAttrText(
itemtype
=> l_error_itemtype,
itemkey
=> l_error_itemkey,
aname
=> 'WF_ADMINISTRATOR' );
--<rwunderl:2775132> Put first assignemt in their own block
--in case DEFAULT_RESET_ERROR_NTF does not exist.
begin
wf_engine.AssignActivity(itemtype,itemkey,
'DEFAULT_RESET_ERROR_NTF',
l_administrator);
exception
when OTHERS then
null; --We only null this exception because the parent
--block nulls the expeption.
end;
wf_engine.AssignActivity(itemtype,itemkey,'RETRY_ONLY_NTF',
l_administrator);
exception
when others then null;
end;
--- Check if a timeout value exists
-- If it does, then set the error timeout
-begin
--if this item type doesnt exist an exception is raised.
l_timeout := WF_ENGINE.GetItemAttrNumber(
itemtype
=> l_error_itemtype,
itemkey
=> l_error_itemkey,
aname
=> 'ERROR_TIMEOUT' );
wf_engine.SetItemAttrNumber(itemtype,itemkey,'TIMEOUT_VALUE',l_tim
eout);
exception
when others then null;
end;

result := wf_engine.eng_completed;
ELSIF (funcmode = 'CANCEL') THEN
result := wf_engine.eng_completed;
END IF;
EXCEPTION
WHEN OTHERS THEN
WF_CORE.Context('WF_STANDARD', 'InitializeErrors',
itemtype, itemkey, actid, funcmode);
RAISE;
END InitializeErrors;
-- -------------------------------------------------------------------- CheckErrorActive
-- checks if an error is still active and returns TRUE/FALSE.
-- Use this in an error process to exit out of a timeout loop
-- Called by default error process.
-- ------------------------------------------------------------------PROCEDURE CheckErrorActive(
itemtype
IN VARCHAR2,
itemkey
IN VARCHAR2,
actid
IN NUMBER,
funcmode
IN VARCHAR2,
result
OUT NOCOPY VARCHAR2 ) IS
l_error_itemtype
l_error_itemkey
l_error_actid
status

VARCHAR2(8);
VARCHAR2(240);
NUMBER;
VARCHAR2(30);

cursor activity_status (litemtype varchar2, litemkey varchar2, lactid number


) is
select WIAS.ACTIVITY_STATUS
from WF_ITEM_ACTIVITY_STATUSES WIAS
where WIAS.ITEM_TYPE = litemtype
and WIAS.ITEM_KEY = litemkey
and WIAS.PROCESS_ACTIVITY = lactid;
BEGIN
IF (funcmode = 'RUN') THEN
--- Get the type and the key of the process that errored out
-- these were set in the erroring out process by Execute_Error_Process
-l_error_itemkey := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ITEM_KEY' );
l_error_itemtype := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ITEM_TYPE' );
l_error_actid := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_ACTIVITY_ID' );
open activity_status(l_error_itemtype, l_error_itemkey, l_error_actid);

fetch activity_status into status;


close activity_status;
if status = 'ERROR' then
result:='T';
else
result:='F';
end if;
END IF;
EXCEPTION
WHEN OTHERS THEN
WF_CORE.Context('WF_STANDARD', 'CheckErrorActive',
itemtype, itemkey, actid, funcmode);
RAISE;
END CheckErrorActive;
-- -------------------------------------------------------------------- InitializeEventError
-- Called by the Error Process, this sets up various
-- item attributes.
-- ------------------------------------------------------------------PROCEDURE InitializeEventError( itemtype
VARCHAR2,
itemkey
VARCHAR2,
actid
NUMBER,
funcmode
VARCHAR2,
resultout
OUT NOCOPY VARCHAR2 ) IS
l_event_t
wf_event_t;
l_error_name
varchar2(240);
l_error_type
varchar2(240);
l_error_message
varchar2(2000);
l_error_stack
varchar2(2000);
l_subscription
RAW(16);
l_url
varchar2(4000);
l_eventdataurl
varchar2(4000);
l_source
varchar2(8);
begin
IF (funcmode = 'RUN') THEN
--- Get the Event Item Attribute
-l_event_t := WF_ENGINE.GetItemAttrEvent(
itemtype
=> itemtype,
itemkey
=> itemkey,
name
=> 'EVENT_MESSAGE' );
--- Get the Errored Subscription GUID
-l_subscription := l_event_t.GetErrorSubscription();
--- Get the Error Type from the Item Attribute - set by Engine
-l_error_type := WF_ENGINE.GetItemAttrText(
itemtype
=> itemtype,
itemkey
=> itemkey,

aname
=> 'ERROR_TYPE');
--- If the error type is null, this must be an UNEXPECTED event
-IF l_error_type IS NULL THEN
l_error_type := 'UNEXPECTED';
wf_engine.SetItemAttrText(itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'ERROR_TYPE',
avalue
=> l_error_type);
END IF;
--- Determine if this event is LOCAL or EXTERNAL
-if l_subscription is not null then
-- If a subscription found, look at its source
select source_type into l_source
from wf_event_subscriptions
where guid = l_subscription;
if l_source = 'ERROR' then
l_source := 'LOCAL';
end if;
else
-- Since no subscription found, look at from agent details
begin
select 'LOCAL' into l_source
from wf_systems ws
where ws.guid = hextoraw(wf_core.translate('WF_SYSTEM_GUID'))
and ws.name = nvl(l_event_t.GetFromAgent().GetSystem(),ws.name);
exception
when no_data_found then
l_source := 'EXTERNAL';
end;
end if;
--- Get the Error Message, or set it if UNEXPECTED
-l_error_message := substr(l_event_t.GetErrorMessage(),1,2000);
IF (l_error_message is null) THEN
l_error_message := wf_core.translate('NO_MATCHING_SUBSCRIPTIONS');
END IF;
-- Get the Error Stack
l_error_stack := substr(l_event_t.GetErrorStack(),1,2000);
-- Get the Errored Subscription GUID
l_subscription := l_event_t.GetErrorSubscription();
-- Generate the URL
wf_event_html.GetFWKEvtSubscriptionUrl(l_subscription, l_url);
l_eventdataurl := wf_oam_util.GetViewXMLURL(p_eventattribute => 'EVENT_MESSA
GE',
p_itemtype => itemtype,
p_itemkey => itemkey);
-- Set the Item Attributes

wf_engine.SetItemAttrText(itemtype
itemkey
aname
avalue

=>
=>
=>
=>

itemtype,
itemkey,
'ERROR_MESSAGE',
l_error_message);

wf_engine.SetItemAttrText(itemtype
itemkey
aname
avalue

=>
=>
=>
=>

itemtype,
itemkey,
'ERROR_STACK',
l_error_stack);

-- Set the PL/SQL Document for the Event


wf_engine.SetItemAttrText(itemtype
itemkey
aname
avalue
/'||ItemType||':'||ItemKey);

Details
=> itemtype,
=> itemkey,
=> 'EVENT_DETAILS',
=> 'PLSQL:WF_STANDARD.EVENTDETAILS

wf_engine.SetItemAttrText(itemtype
itemkey
aname
avalue
||ItemType||':'||ItemKey);

=>
=>
=>
=>

itemtype,
itemkey,
'ERROR_DETAILS',
'PLSQL:WF_STANDARD.ErrorDetails/'

wf_engine.SetItemAttrText(itemtype
itemkey
aname
avalue
tails/'||ItemType||':'||ItemKey);

=>
=>
=>
=>

itemtype,
itemkey,
'SUBSCRIPTION_DETAILS',
'PLSQL:WF_STANDARD.SubscriptionDe

-- Set the Value for the Error Subscription URL


wf_engine.SetItemAttrText(itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'EVENT_SUBSCRIPTION',
avalue
=> l_url);
-- Set the Value for the Event Data URL
wf_engine.SetItemAttrText(itemtype
=> itemtype,
itemkey
=> itemkey,
aname
=> 'EVENT_DATA_URL',
avalue
=> l_eventdataurl);
IF l_error_type IN ('ERROR','UNEXPECTED') THEN
IF l_source = 'LOCAL' THEN
resultout := 'EVENT_ERROR';
ELSE
resultout := 'EVENT_EXTERNAL_ERROR';
END IF;
ELSE
resultout := 'EVENT_WARNING';
END IF;
ELSIF (funcmode = 'CANCEL') THEN
resultout := wf_engine.eng_completed;
END IF;
EXCEPTION
WHEN OTHERS THEN
WF_CORE.Context('WF_STANDARD', 'InitializeEventError',
itemtype, itemkey, actid, funcmode);
RAISE;
END InitializeEventError;
-- --------------------------------------------------------------------

-- EventDetails
-- PL/SQL Document for Event Attributes
-- -------------------------------------------------------------------procedure EventDetails ( document_id in varchar2,
display_type in varchar2,
document
in out nocopy varchar2,
document_type in out nocopy varchar2) IS
ItemType
ItemKey

varchar2(30);
varchar2(30);

l_to_agent
varchar2(60);
l_to_system varchar2(60);
l_from_agent varchar2(60);
l_from_system varchar2(60);
l_priority
varchar2(10);
l_send_date date;
l_send_date_text
varchar2(60);
l_receive_date date;
l_receive_date_text varchar2(60);
i

pls_integer;

l_event_t
l_parmlist_t
l_cells
j
l_result

wf_event_t;
wf_parameter_list_t;
wf_notification.tdType;
number;
varchar2(32000);

begin
-- parse document_id for the ':' dividing item type name from item key value
-- document_id value will take the form <ITEMTYPE>:<ITEMKEY> starting with
-- release 2.5
ItemType := nvl(substr(document_id, 1, instr(document_id,':')-1),'WFERROR');
ItemKey := substr(document_id
, instr(document_id,':')+1);

l_event_t := wf_engine.GetItemAttrEvent(
itemtype
itemkey
name

=> itemtype,
=> itemkey,
=> 'EVENT_MESSAGE' );

--- Get the Agent Details, we don't want any errors if the Agent
-- didn't get populated with anything
-if l_event_t.To_Agent is not null then
l_to_agent := l_event_t.GetToAgent().GetName();
l_to_system := l_event_t.GetToAgent().GetSystem();
end if;
if l_event_t.From_Agent is not null then
l_from_agent := l_event_t.GetFromAgent().GetName();
l_from_system := l_event_t.GetFromAgent().GetSystem();
end if;
--

-- Get any date values and format if required


-l_send_date := l_event_t.GetSendDate();
IF l_send_date IS NOT NULL THEN
l_send_date_text := WF_NOTIFICATION_UTIL.GetCalendarDate(-1, l_send_date
, null, true);
END IF;
l_receive_date := l_event_t.GetReceiveDate();
IF l_receive_date IS NOT NULL THEN
l_receive_date_text := WF_NOTIFICATION_UTIL.GetCalendarDate(-1, l_receiv
e_date, null, true);
END IF;
--- Get the Priority
-l_priority := l_event_t.GetPriority();
-------if

Build up the PL/SQL Document depending on the User Mail Preference


bug 6955474
Using WF_NOTIFICATION.NTF_Table API to maintain consistency with BLAF
Build the Table
(display_type = wf_notification.doc_html) then
i := 1;
l_cells(i) := wf_core.translate('WF_EVENT_HEADING');
l_cells(i) := 'S30%:'||l_cells(i);
i := i + 1;
l_cells(i) := wf_core.translate('WF_VALUE');
l_cells(i) := 'S70%:'||l_cells(i);
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_EVENT_NAME');
i := i + 1;
l_cells(i) := 'S:'||nvl(l_event_t.GetEventName(),'&'||'nbsp');
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_EVENT_KEY');
i := i + 1;
l_cells(i) := 'S:'||nvl(l_event_t.GetEventKey(),'&'||'nbsp');
i := i + 1;
l_cells(i) :=
i := i + 1;
l_cells(i) :=
i := i + 1;
l_cells(i) :=
i := i + 1;
l_cells(i) :=

'S:'||wf_core.translate('WF_TO_AGENT_NAME');
'S:'||l_to_agent;
'S:'||wf_core.translate('WF_TO_AGENT_SYSTEM');
'S:'||l_to_system;

i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_FROM_AGENT_NAME');
i := i + 1;
l_cells(i) := 'S:'||l_from_agent;

i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_FROM_AGENT_SYSTEM');
i := i + 1;
l_cells(i) := 'S:'||l_from_system;
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_SEND_DATE');
i := i + 1;
l_cells(i) := 'S:<BDO DIR="LTR">'||l_send_date_text||'</BDO>';
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_RECEIVE_DATE');
i := i + 1;
l_cells(i) := 'S:<BDO DIR="LTR">'||l_receive_date_text||'</BDO>';
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_PRIORITY');
i := i + 1;
l_cells(i) := 'S:'||l_priority;
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_CORRELATION');
i := i + 1;
l_cells(i) := 'S:'||nvl(l_event_t.GetCorrelationId(),'&'||'nbsp');
else
l_result := Wf_Core.Newline||rpad(wf_core.translate('WF_EVENT_HEADING'),40)
||wf_core.translate('WF_VALUE')||Wf_Core.Newline;
l_result := l_result||rpad(wf_core.translate('WF_EVENT_NAME'),40)||
l_event_t.GetEventName()||Wf_Core.Newline||
rpad(wf_core.translate('WF_EVENT_KEY'),40)||
l_event_t.GetEventKey()||Wf_Core.Newline||
rpad(wf_core.translate('WF_FROM_AGENT_NAME'),40)||
l_From_Agent||Wf_Core.Newline||
rpad(wf_core.translate('WF_FROM_AGENT_SYSTEM'),40)||
l_From_System||Wf_Core.Newline||
rpad(wf_core.translate('WF_TO_AGENT_NAME'),40)||
l_To_Agent||Wf_Core.Newline||
rpad(wf_core.translate('WF_TO_AGENT_SYSTEM'),40)||
l_To_System||Wf_Core.Newline||
rpad(wf_core.translate('WF_PRIORITY'),40)||
l_Priority||Wf_Core.Newline||
rpad(wf_core.translate('WF_SEND_DATE'),40)||
l_send_date_text||Wf_Core.Newline||
rpad(wf_core.translate('WF_RECEIVE_DATE'),40)||
l_receive_date_text||Wf_Core.Newline||
rpad(wf_core.translate('WF_CORRELATION'),40)||
l_event_t.GetCorrelationId()||Wf_Core.Newline;
end if;
-- Display the Parameter List
l_parmlist_t := l_event_t.getParameterList();
if (l_parmlist_t is not null) then
j := l_parmlist_t.FIRST;
while (j <= l_parmlist_t.LAST) loop
if (display_type = wf_notification.doc_html) then
i := i + 1;
l_cells(i) := 'S:'||wf_core.translate('WF_PARAMETER')||' : '||l_parmlist

_t(j).getName();
i := i + 1;
l_cells(i) :=
'S:'||substr(nvl(l_parmlist_t(j).getValue(),'&'||'nbsp'),1,20);
else
l_result := l_result||rpad(wf_core.translate('WF_PARAMETER')
||l_parmlist_t(j).getName(),40)
||substr(l_parmlist_t(j).getValue(),1,20)||Wf_Core.Newline;
end if;
j := l_parmlist_t.NEXT(j);
end loop;
end if;
if (display_type = wf_notification.doc_html) then
document_type := wf_notification.doc_html;
wf_notification.NTF_Table(cells => l_cells,
col => 2,
type => 'H',
rs
=> l_result);
-- Display title
l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1"
>' ||
'<tr><td class="x3w">'||wf_core.Translate('WFITD_EVENT_DETAILS')
||
'</td></tr>'||'<tr><td>'||l_result||'</td></tr></table>';
else
document_type := wf_notification.doc_text;
end if;
document := l_result;
exception
when others then
wf_core.context('WF_STANDARD','EventDetails',document_id, display_type);
raise;
end EventDetails;
-- --------------------------------------------------------------------- Retry Raise
-- Executes command depending on notification response
-- -------------------------------------------------------------------PROCEDURE RetryRaise
( itemtype in
varchar2,
itemkey in
varchar2,
actid
in
number,
funcmode in
varchar2,
resultout out nocopy varchar2 ) IS
aname
varchar2(100);
l_event_t
wf_event_t;
l_toagent
wf_agent_t;
l_skip_sub varchar2(300) := null;
l_parameterList wf_parameter_list_t := null;
begin
IF (funcmode = 'RUN') THEN
l_event_t := wf_engine.GetItemAttrEvent(
itemtype
itemkey

=> itemtype,
=> itemkey,

name

=> 'EVENT_MESSAGE' );

aname := wf_engine.GetActivityAttrText(itemtype,
itemkey,
actid,
'COMMAND');
-- Bug 4198975
-- If the SKIP_ERROR_SUB is not null, then this parameber will
-- be passed over to raise in all the cases.
l_skip_sub := l_event_t.GETVALUEFORPARAMETER('SKIP_ERROR_SUB');
if (l_skip_sub is not null) then
l_parameterList := wf_parameter_list_t();
wf_event.addParameterToList('SKIP_ERROR_SUB', l_skip_sub, l_parameterLis
t);
end if;
IF aname = 'RAISE_KEY' THEN
wf_event.raise(p_event_name => l_event_t.GetEventName(),
p_event_key => l_event_t.GetEventKey(),
p_parameters => l_parameterList);
ELSIF aname = 'RAISE_KEY_DATA' THEN
wf_event.raise(p_event_name => l_event_t.GetEventName(),
p_event_key => l_event_t.GetEventKey(),
p_event_data => l_event_t.GetEventData(),
p_parameters => l_parameterList);
ELSIF aname = 'RAISE_KEY_DATA_PARAM' THEN
wf_event.raise(l_event_t.GetEventName(),
l_event_t.GetEventKey(),
l_event_t.GetEventData(),
l_event_t.GetParameterList());
ELSIF aname = 'ENQUEUE' THEN
l_toagent := l_event_t.GetToAgent();
l_event_t.SetPriority(-1); -- want this dequeued ASAP
wf_event.enqueue(l_event_t, l_toagent);
ELSE
wf_core.raise('WFSQL_ARGS');
END IF;
resultout := wf_engine.eng_completed;
ELSIF (funcmode = 'CANCEL') THEN
resultout := wf_engine.eng_completed;
END IF;
EXCEPTION
WHEN OTHERS THEN
WF_CORE.Context('WF_STANDARD', 'RetryRaise',
itemtype, itemkey, actid, funcmode);
RAISE;
end RetryRaise;
-- --------------------------------------------------------------------- GetAgents
-- Gets the Event Subscription Out and To Agent
-- -------------------------------------------------------------------procedure GetAgents
( itemtype in
varchar2,
itemkey in
varchar2,

actid
in
number,
funcmode in
varchar2,
resultout out nocopy varchar2)
is
--l_subguid
l_subguid
l_outagentattr
l_toagentattr
l_outagentguid
l_toagentguid
l_outagent
l_toagent
cursor
select
from
where

raw(16);
varchar2(100);
varchar2(100);
varchar2(100);
raw(16);
raw(16);
varchar2(100);
varchar2(100);

c_agents is
out_agent_guid, to_agent_guid
wf_event_subscriptions
guid = l_subguid;

begin
IF (funcmode = 'RUN') THEN
l_subguid := wf_engine.GetActivityAttrText(itemtype,
itemkey,
actid,
'SUB_GUID');
l_outagentattr := wf_engine.GetActivityAttrText(itemtype,
itemkey,
actid,
'FROMAGENT');
l_toagentattr := wf_engine.GetActivityAttrText(itemtype,
itemkey,
actid,
'TOAGENT');
-- Get the Agent Guids
open c_agents;
fetch c_agents into l_outagentguid, l_toagentguid;
close c_agents;
if l_toagentguid is not null then
-- Get the Out Agent in the agent@system format
if l_outagentguid is not null then
select wfa.name||'@'||wfs.name
into l_outagent
from wf_agents wfa, wf_systems wfs
where wfa.guid = l_outagentguid
and wfa.system_guid = wfs.guid;
end if;
-- Get the To Agent in the agent@system format
select wfa.name||'@'||wfs.name
into l_toagent
from wf_agents wfa, wf_systems wfs
where wfa.guid = l_toagentguid
and wfa.system_guid = wfs.guid;

-- Update the agent item attributes


wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => l_outagentattr,
avalue => l_outagent);
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => l_toagentattr,
avalue => l_toagent);
resultout := 'T';
else
resultout := 'F';
end if;
ELSIF (funcmode = 'CANCEL') THEN
resultout := wf_engine.eng_completed;
END IF;
EXCEPTION
WHEN OTHERS THEN
WF_CORE.Context('WF_STANDARD', 'GetAgents',
itemtype, itemkey, actid, funcmode);
RAISE;
end GetAgents;
-- --------------------------------------------------------------------- GetAckAgent
-- Gets the Acknowledge To Agent based on the Event Message
-- -------------------------------------------------------------------procedure GetAckAgent
( itemtype in
varchar2,
itemkey in
varchar2,
actid
in
number,
funcmode in
varchar2,
resultout out nocopy varchar2)
is
l_event_t
l_toagentattr
l_system
l_agent

wf_event_t;
varchar2(100);
varchar2(30);
varchar2(30);

cursor c_return_agent is
select wfa.name agent
from wf_systems wfs,
wf_agents wfa
where wfs.name = l_system
and wfa.status = 'ENABLED'
and wfa.direction = 'IN'
and wfa.name not in ('WF_ERROR','WF_DEFERRED');
begin
IF (funcmode = 'RUN') THEN
l_event_t := wf_engine.GetActivityAttrEvent(
itemtype
itemkey
actid
name

=>
=>
=>
=>

itemtype,
itemkey,
actid,
'EVENTMESSAGE');

l_toagentattr := wf_engine.GetActivityAttrText(itemtype,

itemkey,
actid,
'ACKTOAGENT');
l_system := l_event_t.GetFromAgent().GetSystem();
open c_return_agent;
fetch c_return_agent into l_agent;
close c_return_agent;
if l_agent is not null then
wf_engine.SetItemAttrText(itemtype => itemtype,
itemkey => itemkey,
aname => l_toagentattr,
avalue => l_agent||'@'||l_system);
end if;
resultout := wf_engine.eng_completed;
ELSIF (funcmode = 'CANCEL') THEN
resultout := wf_engine.eng_completed;
END IF;
EXCEPTION
WHEN OTHERS THEN
WF_CORE.Context('WF_STANDARD', 'GetAckAgent',
itemtype, itemkey, actid, funcmode);
RAISE;
end GetAckAgent;
-- SubscriptionDetails
-- PL/SQL Document to display subscription
-- IN
-- document_id
-- display_type
-- document
-- document_type
procedure SubscriptionDetails (document_id
display_type
document
document_type
is
l_item_type
varchar2(10);
l_item_key
varchar2(240);
l_subscription raw(16);
l_params
varchar2(4000);
l_rule_func
varchar2(240);
l_cells
wf_notification.tdType;
l_cells2
wf_notification.tdType;
i
pls_integer;
j
pls_integer;
l_document
varchar2(32000);
l_sub_param_list wf_parameter_list_t;
l_event_t
wf_event_t;
l_result
varchar2(22000);
l_result2
varchar2(10000);
l_url
varchar2(500);
l_sub_url
varchar2(1000);
l_evt_url
varchar2(1000);
begin

parameter details

in
in
in
in

varchar2,
varchar2,
out nocopy varchar2,
out nocopy varchar2)

l_item_type := nvl(substr(document_id, 1,
instr(document_id,':')-1),'WFERROR');
l_item_key := substr(document_id, instr(document_id,':')+1);
l_event_t := wf_engine.GetItemAttrEvent(itemtype => l_item_type,
itemkey => l_item_key,
name
=> 'EVENT_MESSAGE');
l_subscription := l_event_t.GetErrorSubscription();
if (l_subscription is not null) then
SELECT
INTO
FROM
WHERE

parameters, java_rule_func
l_params, l_rule_func
wf_event_subscriptions
guid = l_subscription;

l_sub_param_list := wf_event.GetParamListFromString(l_params);
if (display_type = wf_notification.doc_html) then
i := 1;
l_cells(i) := 'S30%:'||wf_core.Translate('WF_PARAMETER');
i := i + 1;
l_cells(i) := 'S70%:'||wf_core.Translate('WF_VALUE');
else
l_result := Wf_Core.Newline||rpad(wf_core.Translate('WF_PARAMETER'), 40)
||wf_core.translate('WF_VALUE')||Wf_Core.Newline;
end if;
-- Show all Subscription Parameters that are currently used as
-- meta-data store for WS definition
if (l_sub_param_list is not null) then
j := l_sub_param_list.FIRST;
while (j is not null) loop
if (display_type = wf_notification.doc_html) then
i := i + 1;
l_cells(i) := 'S:'||l_sub_param_list(j).getName();
i := i + 1;
l_cells(i) := 'S:'||l_sub_param_list(j).getValue();
else
l_result := l_result||rpad(l_sub_param_list(j).getName(),40)||
rpad(l_sub_param_list(j).getValue(),40)||wf_core
.newline;
end if;
j := l_sub_param_list.NEXT(j);
end loop;
end if;
-- Show Invoker Rule Function since it may be a Custom one extended from
-- seeded. Also the Event Payload is WS input message
l_evt_url := wf_engine.GetItemAttrText(itemtype => l_item_type,
itemkey => l_item_key,
aname
=> 'EVENT_DATA_URL');
l_sub_url := wf_engine.GetItemAttrText(itemtype => l_item_type,
itemkey => l_item_key,
aname
=> 'EVENT_SUBSCRIPTION');
if (display_type = wf_notification.doc_html) then
i := i + 1;

l_cells(i) := 'S:'||wf_core.Translate('WF_INOKER_RULE_FUNC');
i := i + 1;
l_cells(i) := 'S:'||l_rule_func;
i := i + 1;
l_cells(i) := 'S:'||wf_core.Translate('WF_WS_INPUT_MESG');
i := i + 1;
l_url := '<a href="'||l_evt_url||'" class="xd">'||wf_core.Translate('WF_CL
ICK_HERE')||'</a>';
l_cells(i) := 'S:'||l_url;
i := i + 1;
l_cells(i) := 'S:'||wf_core.Translate('WF_SUBSCRIPTION_PAGE');
i := i + 1;
l_url := '<a href="'||l_sub_url||'" class="xd">'||wf_core.Translate('WF_CL
ICK_HERE')||'</a>';
l_cells(i) := 'S:'||l_url;
wf_notification.Ntf_Table(l_cells, 2, 'H', l_result);
-- Display title "Web Service Details"
l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="
1">' ||
'<tr><td class="x3w">'||wf_core.Translate('WF_WEBSERVICE_DETAILS
')||'</td></tr>'||
'<tr><td>'||l_result||'</td></tr></table>';
else
l_result := l_result||rpad(wf_core.Translate('WF_INOKER_RULE_FUNC'),40)||
rpad(l_rule_func,40)||wf_core.newline||
rpad(wf_core.Translate('WF_WS_INPUT_MESG'),40)||
rpad(l_evt_url,40)||wf_core.newline||
rpad(wf_core.Translate('WF_SUBSCRIPTION_PAGE'),40)||
rpad(l_sub_url,40)||wf_core.newline;
end if;
end if;
document := l_result;
exception
when others then
wf_core.context('WF_STANDARD', 'SubscriptionDetails', document_id);
raise;
end SubscriptionDetails;
-- ErrorDetails
-- PL/SQL Document to display event
-- IN
-- document_id
-- display_type
-- document
-- document_type
procedure ErrorDetails (document_id
display_type
document
document_type
is
l_result
varchar2(32000);
l_error_name varchar2(240);
l_item_type varchar2(30);
l_item_key varchar2(240);

error details

in
in
in
in

varchar2,
varchar2,
out nocopy varchar2,
out nocopy varchar2)

l_error_message varchar2(2000);
l_error_stack varchar2(2000);
l_cells
wf_notification.tdType;
i
pls_integer;
begin
l_item_type := nvl(substr(document_id, 1, instr(document_id,':')-1),'WFERROR')
;
l_item_key := substr(document_id, instr(document_id,':')+1);
l_error_name := wf_engine.GetItemAttrText(itemtype => l_item_type,
itemkey => l_item_key,
aname
=> 'ERROR_NAME');
l_error_message := wf_engine.GetItemAttrText(itemtype => l_item_type,
itemkey => l_item_key,
aname
=> 'ERROR_MESSAGE');
l_error_stack := wf_engine.GetItemAttrText(itemtype => l_item_type,
itemkey => l_item_key,
aname
=> 'ERROR_STACK');
if (display_type = wf_notification.doc_html) then
document_type := wf_notification.doc_html;
i := 1;
if (l_error_name is not null) then
l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_NAME');
i := i + 1;
l_cells(i) := 'S:'||l_error_name;
i := i + 1;
end if;
l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_MESSAGE');
i := i + 1;
l_cells(i) := 'S:'||l_error_message;
i := i + 1;
l_cells(i) := 'E20%:'||wf_core.Translate('WFMON_ERROR_STACK');
i := i + 1;
l_cells(i) := 'S:'||l_error_stack;
wf_notification.NTF_Table(cells
col
type
rs

=>
=>
=>
=>

l_cells,
2,
'V',
l_result);

-- Display title
l_result := '<table width="100%" border="0" cellspacing="1" cellpadding="1"
>' ||
'<tr><td class="x3w">'||wf_core.Translate('WF_ERROR_DETAILS') ||
'</td></tr>'||'<tr><td>'||l_result||'</td></tr></table>';
else
document_type := wf_notification.doc_text;
l_result := rpad(wf_core.Translate('WFMON_ERROR_NAME'),40)||' : '||l_error_n
ame||wf_core.newline||
rpad(wf_core.Translate('WFMON_ERROR_MESSAGE'),40)||' : '||l_erro
r_message||wf_core.newline||
rpad(wf_core.Translate('WFMON_ERROR_STACK'),40)||' : '||l_error_
stack||wf_core.newline;
end if;
document := l_result;

exception
when others then
wf_core.context('WF_STANDARD', 'ErrorDetails', document_id);
raise;
end ErrorDetails;
-- SubscriptionAction
-- Returns Subscription's Action Code based on which a specific notification
-- could be sent
procedure SubscriptionAction(itemtype in varchar2,
itemkey in varchar2,
actid
in number,
funcmode in varchar2,
resultout in out nocopy varchar2)
is
l_event_t
wf_event_t;
l_subscription raw(16);
l_action_code varchar2(30);
begin
if (funcmode = 'RUN') then
l_event_t := wf_engine.GetItemAttrEvent(itemtype => itemtype,
itemkey => itemkey,
name
=> 'EVENT_MESSAGE');
l_subscription := l_event_t.GetErrorSubscription();
SELECT
INTO
FROM
WHERE

action_code
l_action_code
wf_event_subscriptions
guid = l_subscription;

if (l_action_code is not null) then


resultout := wf_engine.eng_completed||':'||l_action_code;
else
resultout := wf_engine.eng_completed||':CUSTOM_RG';
end if;
elsif (funcmode = 'CANCEL') then
resultout := wf_engine.eng_completed;
end if;
end SubscriptionAction;
END WF_STANDARD;

You might also like