DBA Data[Home] [Help]

PACKAGE BODY: APPS.WF_EVENT

Source


1 package body WF_EVENT as
2 /* $Header: WFEVENTB.pls 120.22.12020000.3 2013/04/25 06:29:14 skandepu ship $ */
3 --------------------------------------------------------------------------
4 /*
5 ** PRIVATE global variables
6 */
7 
8 g_packName varchar2(30) :='wf.plsql.wf_event.';
9 
10 /*
11 ** Cache Variables
12 ** pv_last_agent_name - the value of agent name
13 ** pv_last_queue_name - the value of queue name, no schema information
14 ** pv_last_schema_name - the value of schema name
15 ** pv_last_recipients - the value of last recipients
16 */
17 pv_last_agent_name  varchar2(30);
18 pv_last_queue_name  varchar2(80);
19 pv_last_schema_name varchar2(30);
20 pv_last_recipients  varchar2(30);
21 pv_last_dequeue_enabled varchar2(7);
22 procedure GetAgentDetails(agent_name in varchar2);
23 
24 java_sub varchar2(240) := 'java://';
25 
26 NO_SAVEPOINT exception;                         /* Bug 1840819 */
27 pragma EXCEPTION_INIT(NO_SAVEPOINT,-1086);
28 
29 DISPATCH_ERROR exception;
30 
31   -- 7625944
32   g_navResetThreshold number; -- threshold to reset navigation to FIRST_MESSAGE
33                               -- (applicable to non-TRANSACTIONAL queue agent):
34       -- when reached:
35       -- null value => navigation variable not initialized, will assume default
36       --               navigation (value=0)
37       -- 0 (zero) value => default navigation, ie, navigate rest of queue messages
38       -- value > 0 => limited navigation, ie, navigate messages until number of
39       --              processed messages = g_navResetThreshold, then reset
40       --              message counter and use FIRST_MESSAGE
41   g_currentNavigation BINARY_INTEGER; -- cached value of queue navigation
42   g_processedMessagesCount number :=0; -- count of number of dequeued messages
43   g_groupDequeuing boolean := false; -- flag to mark that dequeueing is by group
44                                      -- (TRANSACTIONAL), only to be used if
45                                      -- message grouping is enabled for the agent
46 
47 --Cursor to get the group members of one agent group.
48 --We assume that group members are of the same system as agent group.
49 CURSOR   agent_group_members(agent_name varchar2,system_name varchar2) is
50   select agt2.name as agt_name,
51          agt2.queue_handler as queue_handler
52   from   wf_agent_groups agp ,
53          wf_agents agt1 ,
54          wf_agents agt2 ,
55          wf_systems sys
56   where  agt1.name      =  agent_name
57   and    agt1.type      = 'GROUP'
58   and    agt1.status    = 'ENABLED'
59   and    agt1.system_guid = sys.guid
60   and    sys.name        = system_name
61   and    agp.group_guid =  agt1.guid
62   and    agp.member_guid = agt2.guid
63   and    agt2.system_guid = sys.guid
64   and    agt2.status      = 'ENABLED';
65 --------------------------------------------------------------------------
66 /*
67 ** setMessage (PRIVATE) - Generate the Message for this event
68 **                                if necessary
69 */
70 PROCEDURE setMessage(p_event in out nocopy wf_event_t)
71 is
72   msg   clob;
73   func  varchar2(240);
74   cmd   varchar2(1000);
75   ename varchar2(240) := p_event.getEventName();
76   ekey  varchar2(240) := p_event.getEventKey();
77   eplist wf_parameter_list_t := p_event.getParameterList();
78   executed boolean;
79   -- Note that ORA-06550 is a generic PL/SQL compilation error
80   -- Here it is most likely caused by "Wrong Number of Arguments".
81   plsql_error EXCEPTION;
82   PRAGMA EXCEPTION_INIT(plsql_error, -06550);
83 
84   -- bes caching implementation
85   l_event_obj wf_event_obj;
86 begin
87   /*
88   ** mjc We are now going to call this from the dispatcher
89   **     if the subscription rule data is MESSAGE
90   */
91   --if (wf_event.test(ename) = 'MESSAGE') then
92 
93     l_event_obj := wf_bes_cache.GetEventByName(ename);
94 
95     if (l_event_obj is null) then
96       wf_core.context('Wf_Event', 'setMessage', ename, ekey);
97       wf_core.raise('WFE_EVENT_NOTEXIST');
98     end if;
99 
100     func := l_event_obj.GENERATE_FUNCTION;
101 
102     if (func is not null) then
103 
104       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
105         wf_log_pkg.string2(wf_log_pkg.level_statement,
106                           'wf.plsql.wf_event.SetMessage.genfunc_callout',
107                           'Start executing generate function - '||func, true);
108       end if;
109 
110       WF_BES_DYN_FUNCS.Generate(func,
111                                 ename,
112                                 ekey,
113                                 eplist,
114                                 msg,
115                                 executed);
116       if (not executed) then
117          /** The Generate Function has been extended to support the passing
118              of the parameter list as well. To make sure we are compatible
119              with 2.6.0, we catch any error if there are too many parameters
120              and try again with the old API signature (eventname, eventkey)
121          **/
122          -- func came from WF_EVENTS.GENERATE_FUNCTION
123          -- BINDVAR_SCAN_IGNORE
124          cmd := 'begin :v1 := '||func||'(:v2, :v3, :v4); end;';
125          begin
126            execute immediate cmd using in out msg, in ename, in ekey, in eplist;
127          exception
128            when plsql_error then
129              -- BINDVAR_SCAN_IGNORE
130              cmd := 'begin :v1 := '||func||'(:v2, :v3); end;';
131              execute immediate cmd using in out msg, in ename, in ekey;
132          end;
133       end if;
134 
135       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
136         wf_log_pkg.string2(wf_log_pkg.level_statement,
137                           'wf.plsql.wf_event.SetMessage.genfunc_callout',
138                           'End executing generate function - '||func, false);
139       end if;
140 
141     else
142       cmd := '<default><event_name>'||ename||'</event_name><event_key>'||
143               p_event.getEventKey()||'</event_key></default>';
144       dbms_lob.createtemporary(msg, FALSE, DBMS_LOB.CALL);
145       dbms_lob.write(msg, length(cmd), 1, cmd);
146     end if;
147 
148     p_event.event_data := msg ;
149     -- p_event.setEventData(msg);
150   --end if;
151 exception
152   when others then
153     if (Wf_Core.Error_Name = 'WFE_EVENT_NOTEXIST') then
154       raise;
155     else
156       wf_core.context('Wf_Event', 'setMessage', ename, ekey, func);
157       WF_CORE.Token('ENAME', p_event.event_name);
158       wf_core.token('FUNCTION_NAME', func);
159       WF_CORE.Token('SQLCODE', to_char(sqlcode));
160       WF_CORE.Token('SQLERRM', sqlerrm);
161       WF_CORE.Raise('WFE_DISPATCH_GEN_ERR');
162     end if;
163 end;
164 -----------------------------------------------------------------------
165 /*
166 ** setErrorInfo - <described in WFEVENTS.pls>
167 */
168 PROCEDURE setErrorInfo(p_event  in out nocopy wf_event_t,
169                        p_type   in     varchar2)
170 is
171   err_name  varchar2(30);
172   err_msg   varchar2(2000);
173   err_stack varchar2(2000);
174 begin
175 
176   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
177      wf_log_pkg.string(wf_log_pkg.level_procedure,
178                       'wf.plsql.WF_EVENT.setErrorInfo.begin',
179                       'Setting Error Info');
180   end if;
181 
182   -- First look for a standard WF_CORE exception.
183   wf_core.get_error(err_name, err_msg, err_stack, 2000);
184 
185   if (err_name is null) then
186     -- If no WF_CORE exception, look for an Oracle error.
187     err_name := to_char(sqlcode);
188     err_msg := sqlerrm;
189   end if;
190 
191   -- set error information into the event --
192   p_event.setErrorMessage(err_msg);
193   p_event.setErrorStack(err_stack);
194   p_event.addParameterToList('ERROR_NAME', err_name);
195   p_event.addParameterToList('ERROR_TYPE', p_type);
196 exception
197   when others then
198     wf_core.context('Wf_Event', 'setErrorInfo', p_event.getEventName());
199     raise;
200 end;
201 -----------------------------------------------------------------------
202 /*
203 ** saveErrorToQueue (PRIVATE) - Save the event to the WF_ERROR queue.
204 */
205 PROCEDURE saveErrorToQueue(p_event in out nocopy wf_event_t)
206 is
207   erragt    wf_agent_t;
208   cmd       varchar2(1000);
209 begin
210 
211   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
212      wf_log_pkg.string(wf_log_pkg.level_procedure,
213                       'wf.plsql.WF_EVENT.saveErrorToQueue.Begin',
214                       'saving event to WF_ERROR on '|| wf_event.local_system_name);
215   end if;
216 
217   erragt := wf_agent_t('WF_ERROR', wf_event.local_system_name);
218 
219   --
220   -- mjc - lets just call the API directly
221   --
222   wf_error_qh.enqueue(p_event, erragt);
223 
224   --cmd := 'begin WF_ERROR_QH.enqueue(:v1, :v2); end;';
225   --execute immediate cmd using in p_event,
226   --                            in erragt;
227   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
228      wf_log_pkg.string(wf_log_pkg.level_procedure,
229                       'wf.plsql.WF_EVENT.saveErrorToQueue.End',
230                       'error info saved');
231   end if;
232 exception
233   when others then
234     wf_core.context('Wf_Event', 'saveErrorToQueue', p_event.getEventName());
235     wf_core.token('FUNCTION_NAME', 'WF_ERROR_QH.enqueue()');
236     --wf_core.raise('WF_EXT_FUNCTION');
237    raise;
238 end;
239 --------------------------------------------------------------------------
240 -----------------------------------------------------------------------
241 /*
242 ** saveErrorToJavaQueue (PRIVATE) - Save the event to the WF_JAVA_ERROR queue.
243 */
244 PROCEDURE saveErrorToJavaQueue(p_event in out nocopy wf_event_t)
245 is
246   erragt    wf_agent_t;
247   cmd       varchar2(1000);
248 begin
249 
250   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
251      wf_log_pkg.string(wf_log_pkg.level_procedure,
252                       'wf.plsql.WF_EVENT.saveErrorToJavaQueue.Begin',
253                       'saving event to WF_JAVA_ERROR on '|| wf_event.local_system_name);
254   end if;
255 
256   erragt := wf_agent_t('WF_JAVA_ERROR', wf_event.local_system_name);
257 
258   --
259   -- mjc - lets just call the API directly
260   --
261   WF_EVENT_OJMSTEXT_QH.enqueue(p_event, erragt);
262 
263   --cmd := 'begin WF_ERROR_QH.enqueue(:v1, :v2); end;';
264   --execute immediate cmd using in p_event,
265   --                            in erragt;
266   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
267      wf_log_pkg.string(wf_log_pkg.level_procedure,
268                       'wf.plsql.WF_EVENT.saveErrorToJavaQueue.End',
269                       'error info saved');
270   end if;
271 exception
272   when others then
273     wf_core.context('Wf_Event', 'saveErrorToQueue', p_event.getEventName());
274     wf_core.token('FUNCTION_NAME', 'WF_EVENT_OJMSTEXT_QH.enqueue()');
275     --wf_core.raise('WF_EXT_FUNCTION');
276    raise;
277 end;
278 --------------------------------------------------------------------------
279 /*
280 ** isDeferToJava (PRIVATE)
281 *  returns true : if current subscription is Java or the event has a
282 *                 Java generate function or there exists a subsequent
283 *                 Java subscription when max threshold is reached
284 *  returns false: otherwise
285 */
286 FUNCTION isDeferToJava(max_threshold_reached    in boolean,
287                        p_event_name             in varchar2,
288                        p_source_type            in varchar2,
289                        p_rule_func              in varchar2,
290                        p_rule_data              in varchar2,
291                        p_phase                  in pls_integer)
292 return boolean
293 is
294   -- bes caching implementation
295   l_event_obj  wf_event_obj;
296   l_subs_list  wf_event_subs_tab;
297   l_java_defer boolean;
298   l_java_gen   boolean;
299   l_phase      number;
300   l_rule_func  varchar2(240);
301   l_rule_data  varchar2(8);
302 begin
303   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
304     wf_log_pkg.string(wf_log_pkg.level_procedure,
305                       'wf.plsql.WF_EVENT.isDeferToJava.begin',
306                       'Checking for Java subscription/generate');
307   end if;
308 
309   if (p_rule_func is not null AND
310       UPPER(substr(p_rule_func, 0, length(java_sub))) = UPPER(java_sub)) then
311     -- this is a Java subscription. Return true
312     if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
313       wf_log_pkg.string(wf_log_pkg.level_statement,
314                         'wf.plsql.WF_EVENT.isDeferToJava.Subscription',
315                         'found a Java subscription');
316     end if;
317     return true;
318   end if;
319 
320   -- event should be in cache by now
321   l_event_obj := wf_bes_cache.GetEventByName(p_event_name);
322 
323   if (l_event_obj is null) then
324     return false;
325   end if;
326 
327   -- set flag to true if java generate function is not null
328   if (l_event_obj.JAVA_GENERATE_FUNC is not null) then
329     l_java_gen := true;
330   else
331     l_java_gen := false;
332   end if;
333 
334   -- Now Checking Generate Functions
335   if (not max_threshold_reached)  then
336 
337     if (l_java_gen AND p_rule_data is not null AND
338         p_rule_data = 'MESSAGE' and p_source_type = 'LOCAL') then
339       -- this is a Java generate function.
340       if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
341         wf_log_pkg.string(wf_log_pkg.level_statement,
342                         'wf.plsql.WF_EVENT.isDeferToJava.Subscription',
343                         'found a Java generate function');
344       end if;
345       return true;
346     else
347       return false;
348     end if;
349   else
350 
351     -- we have event and subscription list from the cache
352     -- o if a subsequent subscription has a java rule func
353     -- o if the event has a java generate function and a subsequent
354     --   subscription has MESSAGE rule data
355 
356     l_java_defer := false;
357     l_subs_list := wf_bes_cache.GetSubscriptions(p_event_name, p_source_type, null);
358 
359     if (l_subs_list is not null) then
360       for i in 1..l_subs_list.COUNT loop
361         l_phase := l_subs_list(i).PHASE;
362         l_rule_func := l_subs_list(i).RULE_FUNCTION;
363         l_rule_data := l_subs_list(i).RULE_DATA;
364 
365         if ((l_phase is null OR l_phase > p_phase) AND
366              ((l_rule_data = 'MESSAGE' AND l_java_gen) OR
367               (UPPER(substr(l_rule_func, 0, length(java_sub))) = UPPER(java_sub)))) then
368           l_java_defer := true;
369           exit;
370         end if;
371 
372       end loop;
373     end if;
374 
375     if(l_java_defer) then
376       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
377         wf_log_pkg.string(wf_log_pkg.level_statement,
378                         'wf.plsql.WF_EVENT.isDeferToJava.Subscription',
379                         'found subsequent Java sub or java generate');
380       end if;
381       return true;
382     else
383       if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
384         wf_log_pkg.string(wf_log_pkg.level_statement,
385                         'wf.plsql.WF_EVENT.isDeferToJava.Subscription',
386                         'No Java sub found or Java Generate Found');
387       end if;
388       return false;
389     end if;
390   end if;
391 
392   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
393     wf_log_pkg.string(wf_log_pkg.level_procedure,
394                       'wf.plsql.WF_EVENT.isDeferToJava.end',
395                       'Checked for Java subscription/generate');
396   end if;
397 
398   return false;
399 exception
400   when others then
401     wf_core.context('Wf_Event', 'isDeferToJava', p_event_name);
402     raise;
403 end isDeferToJava;
404 
405 --------------------------------------------------------------------------
406 /*
407 ** isSaveToJavaError (PRIVATE)
408 *  returns true : if current subscription is Java and source type is ERROR
409 *                 save to Java Error
410 *  returns false: otherwise
411 */
412 FUNCTION isSaveToJavaError(p_event_name             in varchar2,
413                            p_rule_func              in varchar2)
414 return boolean is
415 
416 begin
417   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
418     wf_log_pkg.string(wf_log_pkg.level_procedure,
419                       'wf.plsql.WF_EVENT.isSaveToJavaError.begin',
420                       'Checking Java Error subscription for ' || p_event_name);
421   end if;
422 
423   if (p_rule_func is not null AND
424       UPPER(substr(p_rule_func, 0, length(java_sub))) = UPPER(java_sub)) then
425     -- this is a Java subscription. Return true
426     if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
427       wf_log_pkg.string(wf_log_pkg.level_statement,
428                         'wf.plsql.WF_EVENT.isSaveToJavaError.Subscription',
429                         'found a Java subscription');
430     end if;
431     return true;
432   end if;
433   return false;
434 end isSaveToJavaError;
435 /*
436 ** GetSkippedSub - utility function to get the subscription has skip onerror
437 **                  type
438 */
439 function GetSkippedSub(p_event in wf_event_t)
440          return RAW is
441     l_skip_sub_str VARCHAR2(300);
442 begin
443     l_skip_sub_str := p_event.GETVALUEFORPARAMETER('SKIP_ERROR_SUB');
444     if (l_skip_sub_str is not null) then
445         return hextoraw(l_skip_sub_str);
446     end if;
447     return null;
448 end GetSkippedSub;
449 
450 ------------------------------------------------------------------------
451 /*
452 ** dispatch_internal (PRIVATE)
453 */
454 FUNCTION dispatch_internal(p_source_type        in  varchar2,
455                            p_rule_data          in  varchar2,
456                            p_rule_func          in  varchar2,
457                            p_sub_guid           in  raw,
458                            p_source_agent_guid  in  raw,
459                            p_phase              in  number,
460                            p_priority           in  number,
461                            p_event              in out nocopy wf_event_t,
462                            p_on_error           in  varchar2)
463 return varchar2
464 is
465   res                   varchar2(20);
466   cmd                   varchar2(1000);
467   stat                  varchar2(10);
468   myfunc                varchar2(240);
469   saved                 boolean := FALSE;
470   eguid                 raw(16);
471   defagent              wf_agent_t;
472   subphase              number;
473   genmsg                boolean := FALSE;
474   max_threshold_reached boolean := FALSE;
475   defer_to_java       boolean := FALSE;
476   save_to_java_error    boolean := FALSE;
477   l_skip_sub            raw(16);
478   trig_savepoint exception;
479   pragma exception_init(trig_savepoint, -04092);
480   empty_lob_locator    exception;
481   pragma exception_init (empty_lob_locator, -22275);
482   msg                   clob;
483   -- Bug2786192
484   l_rule_func           VARCHAR2(240);
485   executed              boolean;
486 begin
487     -- Bug 11850350. If database is in PATCH EDITION then
488     -- do not process the event at all. Just return
489     if (wf_core.database_current_edition <> wf_core.database_default_edition) and
490        (p_event.send_date is null or p_event.send_date <= sysdate) then
491       if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
492           wf_log_pkg.string(wf_log_pkg.level_statement,
493                             'wf.plsql.WF_EVENT.dispatch_internal',
494                             'Database not in RUN edition - discarding event');
495         end if;
496       return 'SUCCESS';
497     end if;
498     -- Verify if the subscription is eligible for execution.
499     if ((wf_event.local_system_status = 'ENABLED' OR
500          wf_event.local_system_status = p_source_type)
501          OR
502         (wf_event.local_system_status <> 'DISABLED' AND
503          p_source_type = 'ERROR'))
504         AND
505         (p_phase >= wf_event.phase_minthreshold) then
506 
507       --Bug 2519183
508       --If we are in the deferred processing of an
509       --event we will set back the minthreshold so that its
510       --possible to raise active events within this subscription.
511       --This is after all processed subscriptions have been
512       --discarded hence its fine to set the phase_minthreshold
513       --to zero.
514 
515         if ((wf_event.phase_minthreshold > 0) AND
516             (p_event.from_agent is NOT NULL)) then
517              --Bug 3451981
518              --In the case of EXTERNAL events the from_agent will
519              --not be WF_DEFERRED , in this case no further event
520              --executions are possible with any lower phases
521              --(though logically there is No DEFERRED within DEFERRED
522              --and correspondingly here phase of > 100 or not works the
523              --same way so u can always workaround with higher phases
524              --but not good on design)
525              --So we can possibly check if it is 'EXTERNAL'
526              --and as we know from the check of min_threshold
527              --that we are deferprocessing lets re-set it.
528              if ((p_event.from_agent.getName = 'WF_DEFERRED') OR (p_source_type = 'EXTERNAL')) then
529               wf_event.phase_minthreshold := 0;
530              end if ;
531         end if;
532 
533       --
534       -- mjc  Check if reached the phase threshold and should defer
535       --      If we have encountered a deferred subscription, we will
536       --      get the hell out of Dodge City (aka exiting the loop)
537       --      We should not defer any messages being processed from
538       --      the deferred queue.
539       --
540       -- YOHUANG Bug 4227307
541       -- Error Subscription should never be deferred.
542       if (wf_event.phase_maxthreshold is not null) AND
543          (p_phase >= wf_event.phase_maxthreshold) AND
544          (p_source_type <> 'ERROR')
545       then
546         if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
547           wf_log_pkg.string(wf_log_pkg.level_statement,
548                             'wf.plsql.WF_EVENT.dispatch_internal.Subscription',
549                             'max threshold reached');
550         end if;
551         max_threshold_reached := true;
552       end if;
553 
554        -- check if event needs to be deferred to WF_JAVA_DEFERRED queue
555       if (p_source_type <> 'ERROR') then
556         defer_to_java := isDeferToJava(max_threshold_reached,
557                                        p_event.getEventName(),
558                                        p_source_type, p_rule_func,
559                                        p_rule_data,p_phase);
560       else
561         save_to_java_error := isSaveToJavaError(p_event.getEventName(),
562                                                 p_rule_func);
563       end if;
564 
565       if(defer_to_java OR max_threshold_reached ) then
566         if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
567           wf_log_pkg.string(wf_log_pkg.level_statement,
568                             'wf.plsql.WF_EVENT.dispatch_internal.Subscription',
569                             'detected as deferred');
570         end if;
571         --
572         -- mjc Set action priority now, if we defer, this can be used
573         --     as the priority of the dequeue off the deferred queue
574         --
575         p_event.priority := p_priority;
576 
577         -- Set the Deferred Subscription into the event
578         -- We will use this to figure out which phase we will start
579         -- off with during deferred processing
580         p_event.error_subscription := p_sub_guid;
581 
582         -- set #CURRENT_PHASE  <<sstomar : bug 5870400 >>
583         -- When Last Subscription GUID exist in Event payload but that Subscription
584         -- is not Active/Enabled now. So in such case, Agent Processor doesn't know
585         -- what phase value it should set for Dispatcher to start subscription processing
586         -- (i.e. from which subscription).
587         -- So in such case, Value of #CURRENT_PHASE will be used as starting phase.
588         p_event.AddParameterToList('#CURRENT_PHASE', p_phase);
589 
590         if(defer_to_java) then
591           if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
592             wf_log_pkg.string(wf_log_pkg.level_statement,
593                             'wf.plsql.WF_EVENT.dispatch_internal.Subscription',
594                             'deferring to WF_JAVA_DEFERRED');
595           end if;
596           wf_event.DeferEventToJava(p_source_type, p_event);
597         else
598           if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
599             wf_log_pkg.string(wf_log_pkg.level_statement,
600                             'wf.plsql.WF_EVENT.dispatch_internal.Subscription',
601                              'deferring to WF_DEFERRED');
602           end if;
603           wf_event.deferevent(p_source_type, p_event);
604         end if;
605         res := 'DEFER';
606 
607       elsif (save_to_java_error) then
608         if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
609           wf_log_pkg.string(wf_log_pkg.level_statement,
610                             'wf.plsql.WF_EVENT.dispatch_internal.Subscription',
611                             'save to java error queue');
612         end if;
613         p_event.error_subscription := p_sub_guid;
614         wf_event.saveErrorToJavaQueue(p_event);
615         res := 'DEFER';
616       else
617         -- Generate Method is irrelavant to subscription.
618         -- Exception happened in Generate Method should be thrown
619         -- up.
620         --
621         -- mjc Check if we are required to Generate Message
622         --     Use dbms_lob.istemporary to see if any clob
623         --
624         begin
625           if (NOT genmsg) AND
626           (p_rule_data = 'MESSAGE') AND
627           (p_source_type = 'LOCAL') then
628             if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
629                wf_log_pkg.string(wf_log_pkg.level_statement,
630                                 'wf.plsql.WF_EVENT.dispatch_internal.Rule_Data',
631                                 'Rule Data is MESSAGE and Source is LOCAL');
632             end if;
633             -- if dbms_lob.istemporary(p_event.GetEventData()) = 0 then
634             -- Bug Fix for 4286207
635             begin
636               if (p_event.GetEventData() is null) or
637                  (p_event.GetEventData() is not null and dbms_lob.getlength(p_event.GetEventData()) = 0) then
638                 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
639                    wf_log_pkg.string(wf_log_pkg.level_statement,
640                                     'wf.plsql.WF_EVENT.dispatch_internal.generate',
641                                     'Need to Generate Message');
642                 end if;
643                 wf_event.setMessage(p_event);
644                 genmsg := TRUE;
645               end if;
646             exception
647               when empty_lob_locator then
648                 -- The lob locator is invalid, probably pointing to a empty_clob();
649                 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
650                    wf_log_pkg.string(wf_log_pkg.level_statement,
651                                     'wf.plsql.WF_EVENT.dispatch_internal.generate',
652                                     'Invalid Lob Locator Passed, Generate the Message');
653                 end if;
654                 wf_event.setMessage(p_event);
655                 genmsg := TRUE;
656             end;
657           end if;
658         exception
659           when others then
660             rollback to wf_dispatch_savepoint;
661             p_event.setErrorSubscription(p_sub_guid);
662             wf_event.wf_exception_source := 'RULE';
663             raise;
664         end;
665 
666         --If we came here now we can start processing the
667         --subscription
668         --Set the savepoint here for the SKIP mode and not for error
669         --subscriptions
670         if (p_on_error = 'SKIP' and p_source_type <> 'ERROR') then
671           -- trig_savepoint shall not happen otherwise
672           -- the event level savepoint can't be created.
673           savepoint wf_dispatch_internal;
674         end if;
675 
676         -- If we are in the process of only executing the skipped
677         -- subscription, we should remove this parameter because
678         -- otherwise there will be indefinite loop in case of
679         -- nested raise.
680         l_skip_sub := GetSkippedSub(p_event);
681 
682         if (l_skip_sub is not null AND
683             p_source_type = 'LOCAL') then
684           p_event.AddParameterToList('SKIP_ERROR_SUB', null);
685         end if;
686 
687         --
688         -- If there's a rule function defined, run it.  Otherwise
689         -- just execute the default dispatch functionality
690         --
691         begin
692 
693           if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
694             wf_log_pkg.string2(wf_log_pkg.level_statement,
695                               'wf.plsql.wf_event.dispatch_internal.rulefunc_callout',
696                               'Start executing rule function - '||p_rule_func, true);
697           end if;
698 
699           if (p_rule_func is not null) then
700             WF_BES_DYN_FUNCS.RuleFunction(p_rule_func,
701                                           p_sub_guid,
702                                           p_event,
703                                           res,
704                                           executed);
705             if (not executed) then
706                 -- p_rule_func came from WF_EVENT_SUBSCRIPTIONS.Rule_Function or
707                 -- WF_EVENT_SUBSCRIPTIONS.Java_Rule_Func
708                 myfunc := p_rule_func;
709                 -- BINDVAR_SCAN_IGNORE
710                 cmd := 'begin :v1 := '||myfunc||'(:v2, :v3); end;';
711                 execute immediate cmd using in out res,
712                                             in     p_sub_guid,
713                                             in out p_event;
714             end if;
715           end if;
716 
717           if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
718             wf_log_pkg.string2(wf_log_pkg.level_statement,
719                               'wf.plsql.wf_event.dispatch_internal.rulefunc_callout',
720                               'End executing rule function - '||p_rule_func, false);
721           end if;
722 
723         exception
724           when others then
725             if (p_on_error = 'SKIP') then
726               -- Unexpected Exception is treated the same as ERROR
727               -- if the subscription is marked as SKIP
728               res := 'ERROR';
729             else
730               rollback to wf_dispatch_savepoint;
731               p_event.setErrorSubscription(p_sub_guid);
732               p_event.addParameterToList('ERROR_TYPE', 'UNEXPECTED');
733               wf_event.wf_exception_source := 'RULE';
734               WF_CORE.Token('ENAME', p_event.event_name);
735               WF_CORE.Token('EKEY', p_event.event_key);
736               WF_CORE.Token('RULE',  myfunc);
737               WF_CORE.Token('SQLCODE', to_char(sqlcode));
738               WF_CORE.Token('SQLERRM', sqlerrm);
739               WF_CORE.Raise('WFE_DISPATCH_RULE_ERR');
740             end if;
741 
742         end;
743 
744         if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
745            -- BINDVAR_SCAN_IGNORE[3]
746            wf_log_pkg.string(wf_log_pkg.level_statement,
747                             'wf.plsql.WF_EVENT.dispatch_internal.rule_function',
748                             'Executed Rule Function '||myfunc||' and returned '||res);
749         end if;
750 
751       end if; -- End of "defer_to_java OR max_threshold_reached"
752     else
753       -- Bug 4227307
754       -- Handle the subscriptions that are not eligible for execution.
755       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
756         wf_log_pkg.string(wf_log_pkg.level_statement,
757                           'wf.plsql.wf_event.dispatch_internal.subs_ignore',
758                           'Subscription not executed. Sub Phase='||p_phase||
759                           ', Min threshold='||wf_event.phase_minthreshold);
760       end if;
761       return 'SUCCESS';
762     end if;
763 
764     if (res = 'DEFER' OR res = 'SUCCESS') then
765       return res;
766     end if;
767 
768     p_event.addParameterToList('ERROR_TYPE', res);
769     p_event.setErrorSubscription(p_sub_guid);
770 
771     if (p_source_type = 'ERROR') then
772       -- If subscription returns error when listener listens on error agent.
773       -- Bug 4207885: Set the exception source to Rule when
774       -- Raising exceptions.
775       wf_event.wf_exception_source := 'RULE';
776       wf_core.token('ENAME', p_event.event_name);
777       wf_core.token('EKEY', p_event.event_key);
778       wf_core.token('SQLERRM', null);
779       wf_core.token('SQLCODE', null);
780       wf_core.raise('WFE_DISPATCH_RULE_ERR');
781     end if;
782 
783     if (res = 'ERROR') then
784 
785         if (WF_EVENT.g_message_grouping = 'TRANSACTIONAL') then
786           raise dispatch_error;
787         end if;
788 
789         begin
790           if (p_on_error = 'SKIP' and p_source_type <> 'ERROR') then
791             rollback to wf_dispatch_internal;
792             p_event.AddParameterToList('SKIP_ERROR_SUB', rawtohex(p_sub_guid));
793             res := 'SKIP_ERROR';
794           else
795            rollback to wf_dispatch_savepoint;
796           end if;
797         exception
798            when NO_SAVEPOINT then
799            -- Bug 1840819
800            -- Catch the no savepoint exception incase commit has happened.
801            -- In this case, the subsequent subscriptions can't be executed
802            -- because is savepoint no longer valid.
803            wf_core.token('EVENT',p_event.getEventName());
804            p_event.setErrorMessage(wf_core.substitute('WFERR',
805                                                    'WFE_COMMIT_IN_DISPATCH'));
806            res := 'TRANSACTION_COMMITED';
807         end;
808     end if;
809 
810 
811     wf_event.saveErrorToQueue(p_event);
812     p_event.AddParameterToList('SKIP_ERROR_SUB', null);
813     return (res);
814 
815 exception
816   when others then
817     wf_core.context('Wf_Event', 'dispatch_internal');
818     raise;
819 end;
820 ---------------------------------------------------------------------------
821 /*
822 ** newAgent - <described in WFEVENTS.pls>
823 */
824 FUNCTION newAgent(p_agent_guid in raw) return wf_agent_t
825 is
826   agt_name varchar2(30);
827   sys_name varchar2(30);
828 
829   -- wf bes cache implementation
830   l_agent_obj wf_agent_obj;
831 begin
832   if (p_agent_guid is null) then
833     return null;
834   end if;
835 
836   l_agent_obj := wf_bes_cache.GetAgentByGUID(p_agent_guid);
837 
838   if (l_agent_obj is not null) then
839     return wf_agent_t(l_agent_obj.NAME, l_agent_obj.SYSTEM_NAME);
840   else
841     wf_core.raise('WFE_AGENT_NOTEXIST');
842   end if;
843 exception
844   when others then
845     wf_core.context('Wf_Event', 'newAgent', p_agent_guid);
846     raise;
847 end;
848 ---------------------------------------------------------------------------
849 /*
850 ** test - <Described in WFEVENTS.pls>
851 */
852 FUNCTION test(p_event_name in varchar2) return varchar2
853 is
854   event_guid raw(16);
855   result     varchar2(10) := 'NONE';
856 
857   -- bes caching implementation
858   l_event_obj wf_event_obj;
859   l_subs_list wf_event_subs_tab;
860 
861 begin
862 
863   l_event_obj := wf_bes_cache.GetEventByName(p_event_name);
864 
865   -- if event is not found or no subscriptions to the event, return NONE
866   result := 'NONE';
867   if (l_event_obj is not null) then
868     l_subs_list := wf_bes_cache.GetSubscriptions(p_event_name, 'LOCAL', null);
869 
870     if (l_subs_list is not null) then
871       result := 'KEY';
872       for i in 1..l_subs_list.COUNT loop
873         if (l_subs_list(i).RULE_DATA = 'MESSAGE') then
874           result := 'MESSAGE';
875           exit;
876         end if;
877       end loop;
878     end if;
879   end if;
880   return result;
881 
882 exception
883   when others then
884     wf_core.context('Wf_Event', 'Test', p_event_name);
885     raise;
886 end;
887 ---------------------------------------------------------------------------
888 /*
889 ** send - <Described in WFEVENTS.pls>
890 */
891 PROCEDURE send(p_event in out nocopy wf_event_t) is
892   outguid    WF_AGENTS.GUID%TYPE;
893   toagtname  WF_AGENTS.NAME%TYPE;
894   toagtsys   WF_SYSTEMS.NAME%TYPE;
895   outagtname WF_AGENTS.NAME%TYPE;
896   outagtsys  WF_SYSTEMS.NAME%TYPE;
897   l_to_type  WF_AGENTS.TYPE%TYPE;
898   -- l_mem_agt_name WF_AGENTS.NAME%TYPE;
899   l_to_queue_handler WF_AGENTS.QUEUE_HANDLER%TYPE;
900 
901   -- wf bes cache implementation
902   l_to_agt_obj  wf_agent_obj;
903   l_out_agt_obj wf_agent_obj;
904 begin
905   --
906   -- if from_agent is null, pick one from the local system that uses
907   -- the same queue handler (i.e.: same event type)
908   --
909   -- Note: someday, when we support agent groups, we'd loop through
910   --       the group members and derive a list of proper out agents.
911   --
912   if (p_event.GetToAgent() is null AND p_event.GetFromAgent() is null) then
913     -- Either source or destination must be defined.
914     -- Raise Error.
915     wf_core.context('Wf_Event', 'Send', p_event.getEventName());
916     wf_core.raise('Either source or destination must be defined.'); -- wfsql.msg
917   end if;
918 
919   if p_event.GetToAgent() is not null then
920     toagtname := p_event.getToAgent().getName();
921     toagtsys  := p_event.getToAgent().getSystem();
922   end if;
923 
924   if p_event.GetFromAgent() is not null then
925     outagtname := p_event.getFromAgent().getName();
926     outagtsys  := p_event.getFromAgent().getSystem();
927   end if;
928 
929   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
930      wf_log_pkg.string(wf_log_pkg.level_statement,
931                       'wf.plsql.WF_EVENT.Send.info',
932                       'To Agt: '||toagtname||' To Agt Sys:'||toagtsys||
933                       'Out Agt: '||outagtname||' Out Agt Sys:'||outagtsys);
934   end if;
935 
936   -- enqueue() requires that FromAgent not null.
937   -- pick one from the local system that uses the same queue handler (i.e.: same event type)
938   -- as toAgent uses.
939   -- If the toAgent is an agent group, we assume that agent group
940   -- only contain one type of agents.
941   if (p_event.getFromAgent() is null OR
942       p_event.getFromAgent().getName() is null OR
943       p_event.getFromAgent().getSystem() is null) then
944 
945     l_to_agt_obj := wf_bes_cache.GetAgentByName(toagtname, toagtsys);
946     if (l_to_agt_obj is not null and l_to_agt_obj.STATUS = 'ENABLED') then
947       l_to_type := l_to_agt_obj.TYPE;
948       l_to_queue_handler := l_to_agt_obj.QUEUE_HANDLER;
949     else
950       raise no_data_found;
951     end if;
952 
953     IF (l_to_type = 'GROUP') THEN
954         l_to_queue_handler := NULL;
955         for r_group_members in agent_group_members(toagtname, toagtsys) loop
956           l_to_queue_handler := r_group_members.queue_handler;
957           exit;
958         end loop;
959         if (l_to_queue_handler = null) then
960           raise no_data_found;
961         end if;
962     END IF;
963 
964     l_out_agt_obj := wf_bes_cache.GetAgentByQH(l_to_queue_handler, 'OUT');
965 
966     if (l_out_agt_obj is not null and l_out_agt_obj.STATUS = 'ENABLED') then
967       outguid := l_out_agt_obj.GUID;
968       outagtname := l_out_agt_obj.NAME;
969     else
970       raise no_data_found;
971     end if;
972 
973     p_event.setFromAgent(wf_event.newAgent(outguid));
974   end if;
975 
976   if (p_event.getSendDate() is NULL) then
977     p_event.setSendDate(sysdate);
978   end if;
979 
980   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
981      wf_log_pkg.string(wf_log_pkg.level_statement,
982                       'wf.plsql.WF_EVENT.send.enqueue',
983                       'Sending from '||outagtname||' to '||toagtname);
984   end if;
985 
986   wf_event.enqueue(p_event);
987 exception
988   when no_data_found then
989     wf_core.context('Wf_Event', 'Send', p_event.getEventName());
990     wf_core.token('AGENT', toagtname);
991     wf_core.raise('WFE_AGENT_NOMATCH');
992   when others then
993     wf_core.context('Wf_Event', 'Send', p_event.getEventName());
994     raise;
995 end;
996 ---------------------------------------------------------------------------
997 /*
998 ** Given out agent and to agent info,
999 ** Figure out the recipient address.
1000 ** PRIVATE: Only called by Set_Recipient_List.
1001 ** Assumption: There will be no group under group, so the to agent
1002 **             passed here must have type AGENT.
1003 */
1004 FUNCTION Get_Recipient(p_out_agent_name in varchar2,
1005                        p_out_system_name in varchar2,
1006                        p_to_agent_name  in varchar2,
1007                        p_to_system_name in varchar2,
1008                        p_out_queue_handler in varchar2)
1009          return sys.aq$_agent is
1010     l_to_address         WF_AGENTS.ADDRESS%TYPE;
1011     l_to_protocol        WF_AGENTS.PROTOCOL%TYPE;
1012     l_to_queue_name      WF_AGENTS.QUEUE_NAME%TYPE;
1013     l_to_protocol_number NUMBER := 0; -- Hard code as SQLNET
1014 
1015     -- wf bes cache implementation
1016     l_to_agt_obj wf_agent_obj;
1017 BEGIN
1018 
1019     -- MJC: We need to make sure the recipient address is in the correct
1020     -- format otherwise dequeue will not work.
1021     --
1022     -- Rule 1: Local consumer dequeues from same queue as enqueued
1023     --   --> Address must be null
1024     -- Rule 2: Propagating to local queue
1025     --   --> Address must be <schema>.<queue_name>
1026     -- Rule 3: Propagating to local database
1027     --   --> Address must be <schema>.<queue_name>@dblink
1028 
1029     -- YOHUANG: Different Sql queries for different case to
1030     --          improve performance.
1031 
1032     l_to_agt_obj := wf_bes_cache.GetAgentByName(p_to_agent_name, p_to_system_name);
1033     if (l_to_agt_obj is not null and l_to_agt_obj.STATUS = 'ENABLED') then
1034       l_to_protocol := l_to_agt_obj.PROTOCOL;
1035       l_to_queue_name := l_to_agt_obj.QUEUE_NAME;
1036     else
1037       return null;
1038     end if;
1039 
1040     if (p_to_agent_name = p_out_agent_name and
1041          p_to_system_name = p_out_system_name) then
1042       l_to_address := null;
1043     elsif (p_to_agent_name <> p_out_agent_name and
1044              p_to_system_name = p_out_system_name) then
1045       l_to_address := l_to_queue_name;
1046     -- Bug 7671184 - If message is intended for a remote system use
1047     -- the address of To Agent as To Address for msg propagation
1048     elsif (p_to_system_name <> p_out_system_name) then
1049       l_to_address := l_to_agt_obj.ADDRESS;
1050     end if;
1051 
1052     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1053         wf_log_pkg.string(wf_log_pkg.level_statement,
1054                           'wf.plsql.WF_EVENT.Get_Recipient',
1055                           'Recipient is name: ' || p_to_agent_name ||
1056                           ' address: ' || l_to_address || ' protocol: ' ||l_to_protocol);
1057     end if;
1058 
1059     --  Here is where we will add additional protocol mappings as AQ
1060     --  supports new protocols.  This bit will form a hardcoded mapping
1061     --  from protocol names as used in the event manager and the
1062     --  protocol numbers used by AQ.
1063 
1064     if((l_to_protocol is null) or (l_to_protocol not in ('SQLNET'))) then
1065        wf_core.context('WF_EVENT', 'Get_Recipient', 'Bad Protocol',
1066           l_to_protocol, l_to_queue_name);
1067     end if;
1068 
1069     return sys.aq$_agent(p_to_agent_name,
1070                          l_to_address,
1071                          l_to_protocol_number);
1072 exception
1073     WHEN no_data_found THEN
1074         -- It means that to agent and out agent are not of same type
1075         RETURN null;
1076 end Get_Recipient;
1077 
1078 /*
1079 ** If the ToAgent of event is not null(send), set the recipient list
1080 ** address.
1081 ** Only be called if the event.getToAgent() is not null.
1082 */
1083 PROCEDURE Set_Recipient_List(p_event               in wf_event_t,
1084                              p_out_agent_name     in varchar2,
1085                              p_out_system_name    in varchar2,
1086                              x_message_properties in out nocopy dbms_aq.message_properties_t) IS
1087     l_to_type            WF_AGENTS.TYPE%TYPE;
1088     l_to_agent_name      WF_AGENTS.NAME%TYPE;
1089     l_to_system_name     WF_SYSTEMS.NAME%TYPE;
1090     l_out_queue_handler  WF_AGENTS.QUEUE_HANDLER%TYPE;
1091     l_recipient_agent    sys.aq$_agent;
1092     --Bug 2676549
1093     i    number := 0;
1094 
1095     -- bes cache implementation
1096     l_to_agt_obj   wf_agent_obj;
1097     l_out_agt_obj  wf_agent_obj;
1098 BEGIN
1099 
1100     -- Ignore if to agent is not set or the out agent is DEFERRED.
1101     if ((p_event.getToAgent() is null) or (p_out_agent_name = 'WF_DEFERRED')) then
1102       return;
1103     end if;
1104 
1105     -- if there is a to queue, we need to set the recipient list address
1106     l_to_agent_name := p_event.getToAgent().getName();
1107     l_to_system_name := p_event.getToAgent().getSystem();
1108 
1109     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1110         wf_log_pkg.string(wf_log_pkg.level_statement,
1111                           'wf.plsql.WF_EVENT.setRecieptList',
1112                           'Setting Recipient List: ' || l_to_agent_name);
1113     end if;
1114 
1115     l_to_agt_obj := wf_bes_cache.GetAgentByName(l_to_agent_name, l_to_system_name);
1116     if (l_to_agt_obj is not null and l_to_agt_obj.STATUS = 'ENABLED') then
1117       l_to_type := l_to_agt_obj.TYPE;
1118     else
1119       raise no_data_found;
1120     end if;
1121 
1122     l_out_agt_obj := wf_bes_cache.GetAgentByName(p_out_agent_name, p_out_system_name);
1123     if (l_out_agt_obj is not null and l_out_agt_obj.STATUS = 'ENABLED') then
1124       l_out_queue_handler := l_out_agt_obj.QUEUE_HANDLER;
1125     else
1126       raise no_data_found;
1127     end if;
1128 
1129     if (l_to_type = 'GROUP') then
1130         --Get the agent / agent group from the cursor
1131         for to_agent in agent_group_members(l_to_agent_name,l_to_system_name) loop
1132             l_recipient_agent := Get_Recipient(p_out_agent_name,
1133                                                p_out_system_name,
1134                                                to_agent.agt_name,
1135                                                l_to_system_name,
1136                                                l_out_queue_handler);
1137             if (l_recipient_agent IS NOT NULL) then
1138                 i:= i + 1;
1139                 x_message_properties.recipient_list(i) := l_recipient_agent;
1140             end if;
1141         end loop;
1142         if (i = 0) then
1143             -- There is no qualified agents under this agent group
1144             raise no_data_found;
1145         end if;
1146    else
1147       l_recipient_agent := Get_Recipient(p_out_agent_name,
1148                                          p_out_system_name,
1149                                          l_to_agent_name,
1150                                          l_to_system_name,
1151                                          l_out_queue_handler);
1152       if (l_recipient_agent IS NOT NULL) then
1153         x_message_properties.recipient_list(1) := l_recipient_agent;
1154       else
1155         -- No qualified agent
1156         raise no_data_found;
1157       end if;
1158    end if ;
1159 
1160 END Set_Recipient_List;
1161 
1162 
1163 
1164 /*
1165 ** raise - <Described in WFEVENTS.pls>
1166 */
1167 PROCEDURE raise(p_event_name in varchar2,
1168                 p_event_key  in varchar2,
1169                 p_event_data in clob,
1170                 p_parameters in wf_parameter_list_t,
1171                 p_send_date  in date) is
1172 
1173 
1174 l_parameters  wf_parameter_list_t;
1175 
1176 begin
1177   --If parameter list is null then raise the event
1178   --with a dummy parameter list as raise3 requires
1179   --the parameterlist to be input.Else use the input
1180   --parameter list.
1181   if (p_parameters is NOT NULL) then
1182      l_parameters := p_parameters;
1183   else
1184      l_parameters := wf_parameter_list_t();
1185   end if;
1186   --Raise the event
1187   wf_event.raise3(p_event_name,
1188                   p_event_key,
1189                   p_event_data,
1190                   l_parameters,
1191                   p_send_date);
1192 exception
1193   when others then
1194     raise;
1195 end;
1196 ---------------------------------------------------------------------------
1197 /*
1198 ** listen - <Described in WFEVENTS.pls>
1199 */
1200 PROCEDURE listen(p_agent_name  in varchar2,
1201                  p_wait        in binary_integer,
1202                  p_correlation in varchar2,
1203                  p_deq_condition in varchar2) is
1204 
1205   l_msg_count NUMBER := 0;
1206   l_err_count NUMBER := 0;
1207 begin
1208 
1209   listen(p_agent_name,
1210          p_wait,
1211          p_correlation,
1212          p_deq_condition,
1213          l_msg_count,
1214          l_err_count);
1215 
1216 end;
1217 /*
1218 ** listen - <Described in WFEVENTS.pls>
1219 */
1220 PROCEDURE listen(p_agent_name  in varchar2,
1221                  p_wait        in binary_integer,
1222                  p_correlation in varchar2,
1223                  p_deq_condition in varchar2,
1224                  p_message_count in out nocopy number,
1225                  p_max_error_count in out nocopy number) is
1226 
1227   from_agt_name  varchar2(30);
1228   from_agt_sys   varchar2(30);
1229   st   varchar2(10) := 'LOCAL';
1230   dir  varchar2(10);
1231   qh   varchar2(240);
1232   stat varchar2(10);
1233   agt  raw(16);
1234   sagt raw(16);
1235   evt  wf_event_t;
1236   evt_name      VARCHAR2(240);
1237   evt_errmsg    VARCHAR2(4000);
1238   -- Local Variable, reset everytime the method is called.
1239   l_lsn_msg_count NUMBER := 0;
1240   l_error_count   NUMBER := 0;
1241 
1242   l_queue_name       varchar2(80);
1243   q_name             VARCHAR2(80);
1244   l_enqueue_enabled  VARCHAR2(30);
1245   l_dequeue_enabled  VARCHAR2(30);
1246   l_queueTable       VARCHAR2(30);
1247 
1248   -- bes caching implementation
1249   l_agent_obj  wf_agent_obj;
1250 
1251 begin
1252 
1253   -- return an error if listen is invoked on WF_JAVA_DEFERRED or
1254   -- WF_JAVA_ERROR agents
1255   if (p_agent_name = 'WF_JAVA_DEFERRED') OR
1256      (p_agent_name = 'WF_JAVA_ERROR') then
1257     return;
1258   end if;
1259 
1260   -- Validate the msg count and error count parameters
1261   if (p_message_count is null or p_message_count < 0) then
1262     p_message_count := 0;
1263   end if;
1264 
1265   if (p_max_error_count is null or p_max_error_count < 0) then
1266     p_max_error_count := 0;
1267   end if;
1268 
1269   if ((p_correlation is not NULL) and (p_deq_condition is not NULL)) then
1270     WF_CORE.Context('WF_EVENT', 'Listen', p_agent_name, p_correlation,
1271                      p_deq_condition);
1272     WF_CORE.Raise('WFE_CORRID_VS_CONDITION');
1273 
1274   end if;
1275 
1276   -- lookup agent info --
1277   --<rwunderl:2749563> Tuned and separated sql statement for better performance
1278   --<rwunderl:2792298> restricting Listen() to local system.
1279   if (WF_EVENT.g_local_system_guid is NULL) then
1280     g_local_system_guid := hextoraw(WF_CORE.Translate('WF_SYSTEM_GUID'));
1281   end if;
1282 
1283   -- get the agent information for the local system
1284   l_agent_obj := wf_bes_cache.GetAgentByName(p_agent_name, null);
1285   if (l_agent_obj is not null) then
1286     agt := l_agent_obj.GUID;
1287     dir := upper(l_agent_obj.DIRECTION);
1288   else
1289     raise no_data_found;
1290   end if;
1291 
1292   -- Bug 2307433, 3271311, Use StartAgent as single Source of truth
1293   -- StartAgent becomes the single source to start a particular agent
1294   -- and can be called without worrying about fixed name queues.
1295   StartAgent(p_agent_name);
1296 
1297   -- set default parameters for queue navigation if not previously set
1298   if (g_navResetThreshold is null) then
1299     wf_event.setNavigationParams(p_agent_name, 0);
1300   end if;
1301 
1302     if (WF_EVENT.g_message_grouping = 'TRANSACTIONAL') then
1303       if ((p_correlation is NULL) and (p_deq_condition is NULL)) then
1304         --This is a transactional queue, we will go ahead and call
1305         --the proper api.
1306         WF_EVENT.Listen_GRP(p_agent_name, p_wait);
1307         return;
1308 
1309        else
1310          --This is a transactional queue, but since there was a correlation id
1311          --passed, we cannot call Listen_GRP, so we will raise an error to the
1312          --caller to resolve.
1313          wf_core.context('Wf_Event', 'Listen', p_agent_name);
1314          wf_core.token('AGENT', p_agent_name);
1315          wf_core.token('API', 'WF_EVENT.Listen_GRP');
1316          wf_core.raise('WFE_TRXN_QUEUE');
1317 
1318         end if;
1319     end if;
1320 
1321   -- set source type --
1322   if (p_agent_name = 'WF_ERROR') then
1323     st := 'ERROR';
1324   elsif (dir = 'IN') then
1325     st := 'EXTERNAL';
1326   end if;
1327 
1328   -- check system status
1329   -- stat := wf_core.translate('WF_SYSTEM_STATUS');
1330   -- Set the account name - only need this for WF_DEFERRED
1331   wf_event.SetAccountName;
1332 
1333   if (wf_event.local_system_status = 'DISABLED' OR
1334       wf_core.database_current_edition <> wf_core.database_default_edition) then
1335     return;
1336   end if;
1337 
1338   if (wf_event.local_system_status in ('LOCAL','EXTERNAL')) then
1339     if (st = wf_event.local_system_status
1340         OR st = 'ERROR'
1341         OR p_agent_name = 'WF_DEFERRED') then
1342       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1343          wf_log_pkg.string(wf_log_pkg.level_statement,
1344                           'wf.plsql.WF_EVENT.listen.Check1',
1345                           'Source type is equal to system status '||
1346                           'or ERROR or Deferred Processing');
1347       end if;
1348     else
1349       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1350           wf_log_pkg.string(wf_log_pkg.level_statement,
1351                            'wf.plsql.WF_EVENT.listen.Check2',
1352                            'Source type not valid for current system status');
1353       end if;
1354       return;
1355     end if;
1356   end if;
1357 
1358   -- bug 7828862 Cache apps context before dispatching events
1359   wfa_sec.Cache_Ctx();
1360 
1361   -- We need to explicitly make sure that if someones Queue Handler
1362   -- blows up we rollback the transaction, just in case they don't
1363   begin
1364     savepoint bes_before_dequeue_qh;
1365     wf_event.dequeue(agt, evt, qh, p_wait, p_correlation, p_deq_condition);
1366 
1367   exception
1368     when others then
1369       wf_event.wf_exception_source := 'QH';
1370       rollback to bes_before_dequeue_qh;
1371       raise;
1372    end;
1373 
1374   -- Add support MAX_LSN_MSG_COUNT and MAX_ERROR_COUNT
1375   -- to mimic JAVA GSC Framework implementation
1376   -- Listen will return back to caller if either MAX NUMBER
1377   -- of messages are read or max number of errors happened.
1378   while (evt is not null) loop
1379 
1380     l_lsn_msg_count := l_lsn_msg_count + 1;
1381     if (st <> 'ERROR') then
1382        if (evt.getFromAgent() is null) then
1383          sagt := NULL;
1384        else
1385          from_agt_name := evt.getFromAgent().getName();
1386          from_agt_sys  := evt.getFromAgent().getSystem();
1387 
1388          if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1389             wf_log_pkg.string(wf_log_pkg.level_statement,
1390                              'wf.plsql.WF_EVENT.listen',
1391                              'Event '||evt.getEventName()||
1392                              ', hailing from '||from_agt_name||'@'||from_agt_sys||
1393                              ' was dequeued from '||p_agent_name);
1394          end if;
1395          -- get the from agent guid
1396          GetSourceAgentGUID(agent_name   => from_agt_name,
1397                             agent_system => from_agt_sys,
1398                             agent_guid   => sagt);
1399        end if;
1400     else
1401       sagt := NULL;
1402 
1403       -- Bug 2032654
1404       -- 1. Determine if the event name is null
1405       -- 2. If the event name is NULL, it should be defaulted to UNEXPECTED_ERROR.
1406       -- 3. The text Event Name is NULL is appended to the error message.
1407       evt_name := evt.getEventName;
1408 
1409       IF evt_name IS NULL THEN
1410          evt.setEventName('UNEXPECTED_ERROR');
1411          evt.setEventKey('UNEXPERR');
1412          evt_errmsg := evt.getErrorMessage || wf_core.newline ||
1413                                         wf_core.translate('WF_EVTNAME_NULL');
1414          evt.setErrorMessage(wf_core.translate('WF_EVTNAME_NULL'));
1415       END IF;
1416     end if;
1417 
1418     -- Check if we are doing deferred processing
1419     -- Bug 2210085 - starting a new block to capture exceptions thrown
1420     -- by GetDeferEventCtx
1421     begin
1422       if p_agent_name = 'WF_DEFERRED' then
1423         if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1424            wf_log_pkg.string(wf_log_pkg.level_statement,
1425                             'wf.plsql.WF_EVENT.listen.Deferred',
1426                             'Processing Deferred Event');
1427         end if;
1428 
1429         wf_event.GetDeferEventCtx(st,from_agt_name,from_agt_sys,evt);
1430         -- dispatcher should process all subscriptions
1431         wf_event.phase_maxthreshold := null;
1432       end if;
1433 
1434       begin
1435         -- Dispatcher will throw exception in the following unexpected errors
1436         -- Defer Event Failed
1437         -- Generate Message Failed
1438         -- Rule Function Failed
1439         -- Unable to Save to Error Queue
1440         -- Unable to rollback to savepoint.
1441         -- Listen will swallow all of these exceptions unless the unexpected
1442         -- exception happened when processing error queue
1443         wf_event.dispatch(st, sagt, evt);
1444 
1445         -- We only count consecutive unexpected errors
1446         l_error_count := 0;
1447         commit;
1448 
1449         -- 7828862 Restore apps context from cached values
1450         wfa_sec.Restore_Ctx();
1451       exception
1452         when others then
1453           -- 7828862 Restore apps context from cached values
1454           wfa_sec.Restore_Ctx();
1455 
1456           if (wf_event.wf_exception_source = 'RULE') then
1457             if (st = 'ERROR') then
1458               if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1459                  wf_log_pkg.string(wf_log_pkg.level_error,
1460                                   'wf.plsql.WF_EVENT.listen.dispatch_error',
1461                                   'Rule Function with Source Error Exception');
1462               end if;
1463               raise;
1464             else
1465               if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1466                   wf_log_pkg.string(wf_log_pkg.level_error,
1467                                    'wf.plsql.WF_EVENT.listen.dispatch_error',
1468                                    'Rule Function Error');
1469               end if;
1470               wf_event.setErrorInfo(evt, 'ERROR');
1471               wf_event.saveErrorToQueue(evt);
1472               commit;
1473               l_error_count := l_error_count + 1;
1474             end if;
1475           else
1476             if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1477                wf_log_pkg.string(wf_log_pkg.level_error,
1478                                 'wf.plsql.WF_EVENT.listen.dispatch_error',
1479                                 'Non Rule Function Error');
1480             end if;
1481             -- Bug 4207885: Set the exception source to be WF.
1482             wf_event.wf_exception_source := 'WF';
1483             commit;
1484             raise;
1485           end if;
1486       end;
1487     -- Bug 2210085
1488     exception
1489       when others then
1490         -- 7828862 Restore apps context from cached values
1491         wfa_sec.Restore_Ctx();
1492 
1493         -- Bug 2608037
1494         -- If the execution of rule function had failed and if the
1495         -- agent is the error queue then there is no point in enqueueing
1496         -- the event again into the error queue.
1497         -- In this case we just rollback the dequeue and raise the
1498         -- exception to the user.
1499         if (( wf_event.wf_exception_source = 'RULE') and (st = 'ERROR')) then
1500           if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1501              wf_log_pkg.string(wf_log_pkg.level_error,
1502                               'wf.plsql.WF_EVENT.listen.dispatch_error',
1503                               'Error executing Rule Function with Source Type Error');
1504           end if;
1505           rollback to bes_before_dequeue_qh;
1506 
1507           -- Error WFE_DISPATCH_RULE_ERR already has sufficient info on the error.
1508           -- Just raise it
1509           if (wf_core.error_name = 'WFE_DISPATCH_RULE_ERR') then
1510             raise;
1511           else
1512             wf_core.token('ENAME', evt.event_name);
1513             wf_core.token('EKEY', evt.event_key);
1514             wf_core.token('SQLERRM', sqlerrm);
1515             wf_core.token('SQLCODE', sqlcode);
1516             wf_core.raise('WFE_UNHANDLED_ERROR');
1517           end if;
1518         elsif (wf_event.wf_exception_source = 'WF') then
1519           -- Bug 4207885: Add the handler of exception with source WF
1520           if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1521              wf_log_pkg.string(wf_log_pkg.level_error,
1522                               'wf.plsql.WF_EVENT.listen.dispatch_error',
1523                               'Unexpected Function Error');
1524           end if;
1525           wf_core.token('ENAME', evt.event_name);
1526           wf_core.token('EKEY', evt.event_key);
1527           wf_core.token('SQLERRM', sqlerrm);
1528           wf_core.token('SQLCODE', sqlcode);
1529           wf_core.raise('WFE_UNHANDLED_ERROR');
1530         else
1531           if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1532              wf_log_pkg.string(wf_log_pkg.level_error,
1533                               'wf.plsql.WF_EVENT.listen.error',
1534                               'GetDeferEventCtx Error');
1535           end if;
1536           wf_event.setErrorInfo(evt,'ERROR');
1537           wf_event.saveErrorToQueue(evt);
1538           commit;
1539           l_error_count := l_error_count + 1;
1540         end if;
1541     end;
1542 
1543     -- check system status
1544     stat := wf_core.translate('WF_SYSTEM_STATUS');
1545     if ((stat <> 'ENABLED') AND (st <> stat)) then
1546       exit;
1547     end if;
1548 
1549     evt := null;
1550     wf_event.InitPhaseMinThreshold;
1551     wf_event.SetDispatchMode('SYNC');
1552 
1553     if (p_message_count > 0 AND l_lsn_msg_count >= p_message_count ) then
1554        if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1555           wf_log_pkg.string(wf_log_pkg.level_statement,
1556                             'wf.plsql.WF_EVENT.listen.maxMsgCount',
1557                             'Read the specified maximum number of messages');
1558        end if;
1559        exit;
1560     end if;
1561 
1562     if (p_max_error_count > 0 AND l_error_count >= p_max_error_count ) then
1563        if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1564           wf_log_pkg.string(wf_log_pkg.level_error,
1565                             'wf.plsql.WF_EVENT.listen.maxErrCount',
1566                             'Encountered the specified maximum number of errors');
1567        end if;
1568        exit;
1569     end if;
1570 
1571     -- We need to explicitly make sure that if someones Queue Handler
1572     -- blows up we rollback the transaction, just in case they don't
1573     begin
1574       savepoint bes_before_dequeue_qh;
1575       wf_event.dequeue(agt, evt, qh, p_wait, p_correlation, p_deq_condition);
1576     exception
1577       when others then
1578         wf_event.wf_exception_source := 'QH';
1579         rollback to bes_before_dequeue_qh;
1580         raise;
1581     end;
1582   end loop;
1583 
1584   -- return back the actual read message count
1585   p_message_count := l_lsn_msg_count ;
1586   -- return back the actual error message count
1587   -- Normally l_lsn_msg_count >= l_error_count;
1588   p_max_error_count := l_error_count;
1589 
1590 exception
1591   when no_data_found then
1592     -- 7828862 Restore apps context from cached values
1593     wfa_sec.Restore_Ctx();
1594     if (wf_event.wf_exception_source = 'WF'
1595         OR wf_event.wf_exception_source = 'QH') then
1596       raise;
1597     else
1598       wf_core.context('Wf_Event', 'Listen', p_agent_name);
1599       wf_core.raise('WFE_AGENT_NOTEXIST');
1600     end if;
1601   when others then
1602     wf_core.context('Wf_Event', 'Listen', p_agent_name);
1603     -- 7828862 Restore apps context from cached values
1604     wfa_sec.Restore_Ctx();
1605     raise;
1606 end Listen;
1607 ---------------------------------------------------------------------------
1608 /*
1609 ** listen_concurrent - <Described in WFEVENTS.pls>
1610 */
1611 --Bug 2505487
1612 --Included the AQ wait parameter for the listen_concurrent
1613 
1614 PROCEDURE listen_concurrent(errbuf        out nocopy varchar2,
1615                             retcode       out nocopy  varchar2,
1616                             p_agent_name  in  varchar2,
1617                             p_correlation in  varchar2,
1618                             p_deq_condition in varchar2,
1619                             p_wait    in binary_integer) is
1620   errname  varchar2(30);
1621   errmsg   varchar2(2000);
1622   errstack varchar2(4000);
1623   l_p_wait binary_integer;
1624   l_correlation varchar2(128);
1625 
1626 begin
1627   --Bug 2505487
1628   --Any -ve number for the parameter p_wait in the forms
1629   --is accepted as wait forever.
1630   if (p_wait < 0) then
1631     l_p_wait  := dbms_aq.forever ;
1632   else
1633     l_p_wait  := p_wait;
1634   end if;
1635 
1636 --<rwunderl:2751674>
1637   if (UPPER(p_correlation) = 'NULL') then
1638     l_correlation := NULL;
1639 
1640   else
1641     l_correlation := p_correlation;
1642 
1643   end if;
1644 --</rwunderl:2751674>
1645 
1646   --Bug 2649327
1647   --The deq condition is not used at present for dequeuing
1648   -- Hence setting it to NULL.
1649   wf_event.listen(p_agent_name  => p_agent_name,
1650                   p_wait        => l_p_wait,
1651                   p_correlation => l_correlation,
1652                   p_deq_condition=>NULL);
1653 
1654   -- Return 0 for successful completion --
1655   errbuf  := '';
1656   retcode := '0';
1657 exception
1658   when others then
1659     wf_core.get_error(errname, errmsg, errstack);
1660     if (errmsg is not null) then
1661       errbuf := errmsg;
1662     else
1663       errbuf := sqlerrm;
1664     end if;
1665 
1666     -- Return 2 for error --
1667     retcode := '2';
1668 end;
1669 
1670 ---------------------------------------------------------------------------
1671 /*
1672 ** listen_grp - <Described in WFEVENTS.pls>
1673 */
1674 PROCEDURE listen_grp(p_agent_name in varchar2,
1675                      p_wait       in binary_integer) is
1676 
1677   from_agt_name         varchar2(30);
1678   from_agt_sys          varchar2(30);
1679   st                    varchar2(10) := 'EXTERNAL';
1680   qh                    varchar2(240);
1681   stat                  varchar2(10);
1682   agt                   raw(16);
1683   sagt                  raw(16);
1684   evt                   wf_event_t;
1685   err_evt               wf_event_t;
1686   evt_errmsg            VARCHAR2(4000);
1687   l_queueTable          VARCHAR2(30); --<rwunderl:2749563/>
1688   end_of_transaction    exception;
1689   pragma exception_init (end_of_transaction, -25235);
1690 
1691   -- bes caching implementation
1692   l_agent_obj  wf_agent_obj;
1693 begin
1694 
1695   -- Confirm that p_agent_name includes a transactional queue.
1696 --<rwunderl:2749563> Tuned and separated sql statement for better performance
1697 --<rwunderl:2792298> restricting Listen() to local system.
1698   if (WF_EVENT.g_local_system_guid is NULL) then
1699     g_local_system_guid := hextoraw(WF_CORE.Translate('WF_SYSTEM_GUID'));
1700   end if;
1701 
1702   GetAgentDetails(p_agent_name);
1703 
1704   -- get agent details for local system
1705   l_agent_obj := wf_bes_cache.GetAgentByName(p_agent_name, null);
1706   if (l_agent_obj is null) then
1707     wf_core.context('Wf_Event', 'Listen_GRP', p_agent_name);
1708     wf_core.raise('WFE_AGENT_NOTEXIST');
1709   end if;
1710   qh := l_agent_obj.queue_handler;
1711   agt := l_agent_obj.guid;
1712 
1713 
1714   if (WF_EVENT.g_message_grouping <> 'TRANSACTIONAL') then
1715     --This is not a transactional queue.
1716     WF_CORE.Context('Wf_Event', 'Listen_GRP', p_agent_name);
1717     WF_CORE.Token('AGENT', p_agent_name);
1718     WF_CORE.Token('API', 'WF_EVENT.Listen');
1719     WF_CORE.Raise('WFE_NONTRXN_QUEUE');
1720   end if;
1721 
1722   --Verifying that the system is not disabled.
1723   if (wf_event.local_system_status = 'DISABLED' OR
1724       wf_core.database_current_edition <> wf_core.database_default_edition) then
1725     return;
1726   end if;
1727 
1728     /*
1729     ** We need to explicitly make sure that if someones Queue Handler
1730     ** blows up we rollback the transaction, just in case they don't
1731     */
1732   loop --Outer loop to process all transactions.
1733     WF_CORE.Clear; --Clear any tokens that were set from the previous
1734                    --transaction dequeue.
1735 
1736     begin --We will begin processing a transaction (message group).
1737       savepoint trxn_start;
1738 
1739       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1740          wf_log_pkg.string(wf_log_pkg.level_statement,
1741                           'wf.plsql.WF_EVENT.Listen_GRP.processing',
1742                           'Begin processing transaction');
1743       end if;
1744 
1745       begin
1746 
1747         -- Dequeue the first message in the transaction
1748         savepoint bes_before_dequeue_qh;
1749         wf_event.dequeue(agt, evt, qh,p_wait);
1750 
1751       exception
1752         when end_of_transaction then
1753           if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
1754              wf_log_pkg.string(wf_log_pkg.level_event,
1755                               'wf.plsql.WF_EVENT.Listen_GRP.complete',
1756                               'End of the transaction');
1757           end if;
1758 
1759           -- reset navigation
1760           wf_event.resetNavigationParams;
1761           commit;
1762 
1763         when others then
1764           wf_event.wf_exception_source := 'QH';
1765           rollback to bes_before_dequeue_qh;
1766           raise;
1767 
1768       end;
1769 
1770       while (evt is not null) loop
1771 
1772            if (evt.getFromAgent() is null) then
1773              sagt := NULL;
1774            else
1775              from_agt_name := evt.getFromAgent().getName();
1776              from_agt_sys  := evt.getFromAgent().getSystem();
1777 
1778              if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1779                 wf_log_pkg.string(wf_log_pkg.level_statement,
1780                                  'wf.plsql.WF_EVENT.Listen_GRP.event_dequeued',
1781                                  'Event '||evt.getEventName()||', hailing from '||from_agt_name||'@'||
1782                                   from_agt_sys|| ' was dequeued from '|| p_agent_name);
1783              end if;
1784 
1785              -- get the from agent guid
1786              GetSourceAgentGUID(agent_name   => from_agt_name,
1787                                 agent_system => from_agt_sys,
1788                                 agent_guid   => sagt);
1789            end if;
1790 
1791           /* Bug 2032654
1792              1. Determine if the event name is null
1793              2. If the event name is NULL, it should be defaulted to
1794                 UNEXPECTED_ERROR.
1795              3. The text Event Name is NULL is appended to the error
1796                 message. */
1797 
1798 
1799           if (evt.getEventName) is NULL then
1800                 evt.setEventName('UNEXPECTED_ERROR');
1801                 evt.setEventKey('UNEXPERR');
1802                 evt_errmsg := evt.getErrorMessage || wf_core.newline ||
1803                                   wf_core.translate('WF_EVTNAME_NULL');
1804                 evt.setErrorMessage(wf_core.translate('WF_EVTNAME_NULL'));
1805           END IF;
1806 
1807 
1808           -- Begin Dispatching the event message.
1809 
1810           begin
1811             wf_event.dispatch(st, sagt, evt);
1812 
1813           exception
1814             when others then
1815               if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
1816                  wf_log_pkg.string(wf_log_pkg.level_error,
1817                                   'wf.plsql.WF_EVENT.Listen_GRP.dispatch_error',
1818                                   'Dispatch Error when dispatching Event '||evt.getEventName);
1819               end if;
1820               raise dispatch_error;
1821 
1822           end;
1823 
1824       -- check system status --
1825       stat := wf_core.translate('WF_SYSTEM_STATUS');
1826       if ((stat <> 'ENABLED') AND (st <> stat)) then
1827         exit;
1828       end if;
1829 
1830       evt := null;
1831       wf_event.InitPhaseMinThreshold;
1832       wf_event.SetDispatchMode('SYNC');
1833 
1834       begin
1835         savepoint bes_before_dequeue_qh;
1836         wf_event.dequeue(agt, evt, qh,p_wait);
1837 
1838       exception
1839         when end_of_transaction then
1840           if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
1841              wf_log_pkg.string(wf_log_pkg.level_event,
1842                               'wf.plsql.WF_EVENT.Listen_GRP.complete',
1843                               'End of the transaction');
1844           end if;
1845 
1846           -- reset navigation
1847           wf_event.resetNavigationParams;
1848           commit;
1849 
1850         when others then
1851           wf_event.wf_exception_source := 'QH';
1852           rollback to bes_before_dequeue_qh;
1853           raise;
1854 
1855       end;
1856 
1857     end loop;
1858 
1859 
1860 
1861   exception
1862     when dispatch_error then
1863       --Dequeue the rest of the transaction
1864       begin
1865         loop
1866           wf_event.dequeue(agt, err_evt, qh,p_wait);
1867 
1868         end loop;
1869 
1870       exception
1871         when end_of_transaction then
1872           if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
1873              wf_log_pkg.string(wf_log_pkg.level_event,
1874                               'wf.plsql.WF_EVENT.Listen_GRP.complete',
1875                               'End of the transaction after dispatch error');
1876           end if;
1877 
1878           -- reset navigation
1879           wf_event.resetNavigationParams;
1880 
1881       end;
1882 
1883       --Rollback the whole transaction, which will update the retry count
1884       --on each message.
1885       rollback to trxn_start;
1886 
1887       --We will save the current message to the Error Queue.
1888       if ((evt.getValueForParameter('ERROR_NAME')) is NULL) then
1889         wf_event.setErrorInfo(evt, 'ERROR');
1890 
1891       end if;
1892 
1893       evt.addParameterToList('DEQUEUE_MODE', 'TRANSACTIONAL');
1894       wf_event.saveErrorToQueue(evt);
1895 
1896 
1897     when others then
1898       raise;
1899 
1900     end;
1901 
1902     -- if QH is using setNavigationParams/getQueueNavigation, condition is
1903     -- g_processedMessagesCount = 0 and g_currentNavigation either
1904     -- FIRST_MESSAGE or NEXT_TRANSACTION,
1905     -- otherwise, condition is wf_event.navigation = dbms_aq.first_message
1906     if (g_navResetThreshold is not null and g_processedMessagesCount = 0
1907         and (g_currentNavigation in (dbms_aq.FIRST_MESSAGE, dbms_aq.NEXT_TRANSACTION)))
1908        OR
1909        (g_navResetThreshold is null and wf_event.navigation = dbms_aq.first_message)
1910     then
1911 
1912       exit; --Outer Loop.
1913             --The queue handler must have reached the last message and
1914             --reset the navigation back to the beginning.
1915 
1916     end if;
1917 
1918   end loop; --Outer loop to process all transactions in the queue.
1919 exception
1920   when no_data_found then
1921     if (wf_event.wf_exception_source = 'WF'
1922         OR wf_event.wf_exception_source = 'QH') then
1923       raise;
1924     else
1925       wf_core.context('Wf_Event', 'Listen_GRP', p_agent_name);
1926       wf_core.raise('WFE_AGENT_NOTEXIST');
1927     end if;
1928   when others then
1929     wf_core.context('Wf_Event', 'Listen_GRP', p_agent_name);
1930     raise;
1931 end;
1932 
1933 ---------------------------------------------------------------------------
1934 /*
1935 ** listen__grp_concurrent - <Described in WFEVENTS.pls>
1936 */
1937 PROCEDURE listen_grp_concurrent(errbuf       out nocopy varchar2,
1938                                 retcode      out nocopy varchar2,
1939                                 p_agent_name in  varchar2) is
1940   errname  varchar2(30);
1941   errmsg   varchar2(2000);
1942   errstack varchar2(4000);
1943 begin
1944   wf_event.listen_grp(p_agent_name);
1945 
1946   -- Return 0 for successful completion --
1947   errbuf  := '';
1948   retcode := '0';
1949 exception
1950   when others then
1951     wf_core.get_error(errname, errmsg, errstack);
1952     if (errmsg is not null) then
1953       errbuf := errmsg;
1954     else
1955       errbuf := sqlerrm;
1956     end if;
1957 
1958     -- Return 2 for error --
1959     retcode := '2';
1960 end;
1961 
1962 ---------------------------------------------------------------------------
1963 /*
1964 ** dispatch - <Described in WFEVENTS.pls>
1965 */
1966 PROCEDURE dispatch(p_source_type        in     varchar2,
1967                    p_source_agent_guid  in     raw,
1968                    p_event              in out nocopy wf_event_t)
1969 is
1970   res      varchar2(20);
1971   cmd      varchar2(1000);
1972   stat     varchar2(10);
1973   myfunc   varchar2(240);
1974   ename    varchar2(240);
1975   saved    boolean := FALSE;
1976   subs_found boolean :=FALSE;
1977   eguid    raw(16);
1978   l_skip_sub raw(16);
1979   event_count NUMBER;
1980   l_rule_func varchar2(300);
1981   l_source_type wf_event_subscriptions.source_type%type;
1982   l_phase wf_event_subscriptions.phase%type;
1983   l_rule_data wf_event_subscriptions.rule_data%type;
1984   l_priority wf_event_subscriptions.priority%type;
1985   l_on_error wf_event_subscriptions.on_error_code%type;
1986   --Bug 2437354
1987   trig_savepoint exception;
1988   pragma exception_init(trig_savepoint, -04092);
1989 
1990   -- bes caching implementation
1991   l_event_name varchar2(240);
1992   l_event_obj  wf_event_obj;
1993   l_subs_list  wf_event_subs_tab;
1994   l_sub        wf_event_subs_obj;
1995 begin
1996   l_event_name := p_event.Event_Name;
1997 
1998   -- Deleting any previous Event parameter indexes.
1999   WF_EVENT.evt_param_index.DELETE;
2000 
2001   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2002      wf_log_pkg.string(wf_log_pkg.level_procedure,
2003                       'wf.plsql.WF_EVENT.dispatch.Begin',
2004                       'Dispatching event '||l_event_name);
2005   end if;
2006 
2007   l_event_obj := wf_bes_cache.GetEventByName(l_event_name);
2008   if (l_event_obj is null) then
2009     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2010        wf_log_pkg.string(wf_log_pkg.level_statement,
2011                         'wf.plsql.WF_EVENT.dispatch.no_event',
2012                         'Event is either disabled or product not licensed '||
2013                         'or event not registered');
2014     end if;
2015   end if;
2016 
2017   wf_event.wf_exception_source := 'NONE';
2018 
2019   --
2020   -- mjc If Source Type is LOCAL and Phase Threshold is less than zero,
2021   --     the raise is to be deferred. Then we immediately return to
2022   --     calling subprogram
2023   --
2024   -- The wf_event.deferevent is called within a new block
2025   -- Make sure only defer event when event exists.
2026   begin
2027     if (p_source_type = 'LOCAL' AND
2028          (wf_event.phase_maxthreshold < 0 OR p_event.send_date > sysdate) AND
2029            l_event_obj is not null) then
2030 
2031       if(isDeferToJava(true, l_event_name, p_source_type,
2032                         null, null, null)) then
2033         if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2034           wf_log_pkg.string(wf_log_pkg.level_statement,
2035                            'wf.plsql.WF_EVENT.dispatch.Defer',
2036                            'Detected as deferred raise. Deferring to ' ||
2037                            'WF_JAVA_DEFERRED');
2038         end if;
2039         wf_event.DeferEventToJava(p_source_type, p_event);
2040       else
2041         if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2042           wf_log_pkg.string(wf_log_pkg.level_statement,
2043                            'wf.plsql.WF_EVENT.dispatch.Defer',
2044                            'Detected as deferred raise. Deferring to ' ||
2045                            'WF_DEFERRED');
2046         end if;
2047         wf_event.deferevent(p_source_type, p_event);
2048       end if;
2049       return;
2050     end if;
2051    exception
2052     when others then
2053       wf_event.setErrorInfo(p_event, 'ERROR');
2054       wf_event.saveErrorToQueue(p_event);
2055       wf_core.context('Wf_Event', 'Dispatch', l_event_name);
2056       raise;
2057   end;
2058 
2059   --
2060   -- mjc We have 4 things we need to check for when we are dipatching:
2061   -- 1. Are there any subscriptions for the actual event.
2062   -- 2. Are there any subscriptions to an event group the event belongs to.
2063   -- 3. Are there any subscriptions to the any event.
2064   -- 4. If no subscriptions found in 1,2,3 then check for the unexpected event.
2065   --
2066 
2067   -- YOHUANG
2068   -- TODO
2069   -- Since we know whether this event exist or not, if the event doesn't exist
2070   -- We should execute those expense query such as active_subs, we should instead
2071   -- directly execute active_event_subs for ANY event.
2072   /*
2073   ** Events, Event Groups, Any Event
2074   */
2075   --The savepoint is set if the event has not been deferred
2076   begin
2077     savepoint wf_dispatch_savepoint;
2078   exception
2079     when trig_savepoint then
2080       --If the event has not been deferred, defer the event now.
2081       begin
2082         wf_event.deferevent(p_source_type,p_event);
2083         return;
2084       exception
2085         --Incase deferreing of event fails, save the error to queue.
2086         --Should we save the error to queue since it is WF error?
2087         when others then
2088           wf_event.setErrorInfo(p_event, 'ERROR');
2089           wf_event.saveErrorToQueue(p_event);
2090           wf_core.context('Wf_Event', 'Dispatch', l_event_name);
2091           raise;
2092       end;
2093   end;
2094 
2095   -- Subscriptions dispatch block
2096   begin
2097     -- Only the skipped subscription should be executed when
2098     -- WFERROR DEFAULT_EVENT_ERROR re-raise the event again.
2099     l_skip_sub := GetSkippedSub(p_event);
2100 
2101     if (l_skip_sub is not null AND p_source_type = 'LOCAL') then
2102 
2103       l_sub := wf_bes_cache.GetSubscriptionByGUID(l_event_name, l_skip_sub);
2104       if (l_sub is not null) then
2105         res := wf_event.dispatch_internal(p_source_type => l_sub.SOURCE_TYPE,
2106                                           p_rule_data   => l_sub.RULE_DATA,
2107                                           p_rule_func   => trim(l_sub.RULE_FUNCTION),
2108                                           p_sub_guid    => l_skip_sub,
2109                                           p_source_agent_guid => l_sub.SOURCE_AGENT_GUID,
2110                                           p_phase       => l_sub.PHASE,
2111                                           p_priority    => l_sub.PRIORITY,
2112                                           p_event       => p_event,
2113                                           p_on_error    => l_sub.ON_ERROR_CODE);
2114       end if;
2115       -- Since this is the only sub to be executed, no matter
2116       -- what result it reports, we stop here.
2117       return;
2118     end if;
2119 
2120     -- get and dispatch subscriptions to the even only if the event is
2121     -- valid, product is licensed etc. else directly dispatch Any event
2122     if (l_event_obj is not null) then
2123       -- all subscriptions to the event and Any event in the order of phase
2124       l_subs_list := wf_bes_cache.GetSubscriptions(p_event_name   => l_event_name,
2125                                                    p_source_type  => dispatch.p_source_type,
2126                                                    p_source_agent => dispatch.p_source_agent_guid);
2127       -- dispatching all matching subscriptions for the event
2128       if (l_subs_list is not null) then
2129 
2130         for i in 1..l_subs_list.COUNT loop
2131           if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2132             wf_log_pkg.string(wf_log_pkg.level_statement,
2133                              'wf.plsql.WF_EVENT.dispatch.Subscriptions',
2134                              'Dispatching '||l_subs_list(i).SOURCE_TYPE||' subscription '||
2135                              'with Phase '||l_subs_list(i).PHASE);
2136           end if;
2137 
2138           eguid := l_subs_list(i).GUID;
2139           subs_found := TRUE;
2140 
2141           res := wf_event.dispatch_internal(p_source_type => l_subs_list(i).SOURCE_TYPE,
2142                                             p_rule_data   => l_subs_list(i).RULE_DATA,
2143                                             p_rule_func   => trim(l_subs_list(i).RULE_FUNCTION),
2144                                             p_sub_guid    => l_subs_list(i).GUID,
2145                                             p_source_agent_guid => p_source_agent_guid,
2146                                             p_phase       => l_subs_list(i).PHASE,
2147                                             p_priority    => l_subs_list(i).PRIORITY,
2148                                             p_event       => p_event,
2149                                             p_on_error    => l_subs_list(i).ON_ERROR_CODE);
2150 
2151           if res in ('ERROR', 'DEFER', 'TRANSACTION_COMMITED') then
2152             exit;
2153           end if;
2154         end loop;
2155       end if;
2156 
2157     -- Event object is null, dispatch only Any event subscriptions
2158     else
2159 
2160       -- dispatch subscriptions to Any event. this call does not execute the
2161       -- cursor with union all
2162       l_subs_list := wf_bes_cache.GetSubscriptions(p_event_name   => 'oracle.apps.wf.event.any',
2163                                                    p_source_type  => dispatch.p_source_type,
2164                                                    p_source_agent => dispatch.p_source_agent_guid);
2165       -- dispatching all matching subscriptions for Any event
2166       if (l_subs_list is not null) then
2167 
2168         for i in 1..l_subs_list.COUNT loop
2169           if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2170             wf_log_pkg.string(wf_log_pkg.level_statement,
2171                              'wf.plsql.WF_EVENT.dispatch.Any',
2172                              'Dispatching '||l_subs_list(i).SOURCE_TYPE||' subscription '||
2173                              'with Phase '||l_subs_list(i).PHASE);
2174           end if;
2175 
2176           eguid := l_subs_list(i).GUID;
2177           subs_found := TRUE;
2178 
2179           res := wf_event.dispatch_internal(p_source_type => l_subs_list(i).SOURCE_TYPE,
2180                                             p_rule_data   => l_subs_list(i).RULE_DATA,
2181                                             p_rule_func   => trim(l_subs_list(i).RULE_FUNCTION),
2182                                             p_sub_guid    => l_subs_list(i).GUID,
2183                                             p_source_agent_guid => p_source_agent_guid,
2184                                             p_phase       => l_subs_list(i).PHASE,
2185                                             p_priority    => l_subs_list(i).PRIORITY,
2186                                             p_event       => p_event,
2187                                             p_on_error    => l_subs_list(i).ON_ERROR_CODE);
2188 
2189           if res in ('ERROR', 'DEFER', 'TRANSACTION_COMMITED') then
2190             exit;
2191           end if;
2192         end loop;
2193       end if;
2194     end if;
2195 
2196     -- If no subscriptions dispatched, dispatch subscriptions for Unexpected event.
2197     -- Unexpected event is dispatched only for non-workflow events
2198     if ((not subs_found) and (l_event_name not like 'oracle.apps.wf%')) then
2199 
2200       l_subs_list := wf_bes_cache.GetSubscriptions(p_event_name   => 'oracle.apps.wf.event.unexpected',
2201                                                    p_source_type  => dispatch.p_source_type,
2202                                                    p_source_agent => dispatch.p_source_agent_guid);
2203       if (l_subs_list is not null) then
2204 
2205         for i in 1..l_subs_list.COUNT loop
2206           if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2207             wf_log_pkg.string(wf_log_pkg.level_statement,
2208                              'wf.plsql.WF_EVENT.dispatch.Unexpected',
2209                              'Dispatching '||l_subs_list(i).SOURCE_TYPE||' subscription '||
2210                              'with Phase '||l_subs_list(i).PHASE);
2211           end if;
2212 
2213           eguid := l_subs_list(i).GUID;
2214           res := wf_event.dispatch_internal(p_source_type => l_subs_list(i).SOURCE_TYPE,
2215                                             p_rule_data   => l_subs_list(i).RULE_DATA,
2216                                             p_rule_func   => trim(l_subs_list(i).RULE_FUNCTION),
2217                                             p_sub_guid    => l_subs_list(i).GUID,
2218                                             p_source_agent_guid => p_source_agent_guid,
2219                                             p_phase       => l_subs_list(i).PHASE,
2220                                             p_priority    => l_subs_list(i).PRIORITY,
2221                                             p_event       => p_event,
2222                                             p_on_error    => l_subs_list(i).ON_ERROR_CODE);
2223 
2224           if res in ('ERROR', 'DEFER', 'TRANSACTION_COMMITED') then
2225             exit;
2226           end if;
2227         end loop;
2228       end if;
2229     end if;
2230   exception
2231     when others then
2232       -- Unexpected Error happened in dispatch_internal
2233       if (WF_EVENT.g_message_grouping = 'TRANSACTIONAL') then
2234         WF_CORE.Context('Wf_Event', 'Dispatch', l_event_name);
2235       else
2236         rollback to wf_dispatch_savepoint;
2237         p_event.setErrorSubscription(eguid);
2238         if (wf_event.wf_exception_source <> 'RULE') then
2239           wf_event.wf_exception_source := 'WF';
2240           wf_event.setErrorInfo(p_event, 'UNEXPECTED');
2241           -- Unexpected Exception should be thrown up instead of
2242           -- being enqueued to error queue.
2243           -- wf_event.saveErrorToQueue(p_event);
2244           wf_core.context('Wf_Event', 'Dispatch', l_event_name);
2245         end if;
2246       end if;
2247       raise;
2248   end;
2249 end dispatch;
2250 
2251 
2252 ---------------------------------------------------------------------------
2253 /*
2254 ** enqueue - <Described in WFEVENTS.pls>
2255 */
2256 PROCEDURE enqueue(p_event              in wf_event_t,
2257                   p_out_agent_override in wf_agent_t)
2258 is
2259   cmd     varchar2(1000);
2260   qh      varchar2(240);
2261   agtname varchar2(30);
2262   sysname varchar2(30);
2263 
2264   -- bes caching implementation
2265   l_agent_obj  wf_agent_obj;
2266   p_executed   boolean;
2267 begin
2268   /*
2269   ** mjc If an override agent is defined, we should
2270   **     use that agents queue handler
2271   */
2272   if p_out_agent_override is null then
2273     agtname := p_event.From_Agent.Name;
2274     sysname := p_event.From_Agent.System;
2275   else
2276     agtname := p_out_agent_override.GetName();
2277     sysname := p_out_agent_override.GetSystem();
2278   end if;
2279 
2280   l_agent_obj := wf_bes_cache.GetAgentByName(agtname, sysname);
2281   if (l_agent_obj is not null) then
2282     qh := l_agent_obj.QUEUE_HANDLER;
2283   end if;
2284 
2285   -- Call the static calls implementation first
2286   p_executed := false;
2287 
2288   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2289     wf_log_pkg.string2(wf_log_pkg.level_statement,
2290                       'wf.plsql.wf_event.enqueue.qhandler_callout',
2291                       'Start executing queue handler - '||qh, true);
2292   end if;
2293 
2294   WF_AGT_DYN_FUNCS.StaticEnqueue(qh, p_event, p_out_agent_override, p_executed);
2295 
2296   if (not p_executed) then
2297     -- qh is from WF_AGENTS.QUEUE_HANDLER
2298     -- BINDVAR_SCAN_IGNORE
2299     cmd := 'begin '||qh||'.enqueue(:v1, :v2); end;';
2300     execute immediate cmd using in p_event,
2301                                 in p_out_agent_override;
2302   end if;
2303 
2304   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2305     wf_log_pkg.string2(wf_log_pkg.level_statement,
2306                       'wf.plsql.wf_event.enqueue.qhandler_callout',
2307                       'End executing queue handler - '||qh, false);
2308   end if;
2309 exception
2310   when others then
2311     wf_core.context('Wf_Event', 'Enqueue', p_event.getEventName(), qh);
2312     wf_core.token('FUNCTION_NAME', qh||'.enqueue()');
2313     --wf_core.raise('WF_EXT_FUNCTION');
2314     raise;
2315 end;
2316 ---------------------------------------------------------------------------
2317 /*
2318 ** dequeue - <Described in WFEVENTS.pls>
2319 */
2320 PROCEDURE dequeue(p_agent_guid    in     raw,
2321                   p_event            out nocopy  wf_event_t,
2322                   p_queue_handler in out nocopy varchar2,
2323                   p_wait          in     binary_integer,
2324                   p_correlation   in     varchar2,
2325                   p_deq_condition in     varchar2)
2326 is
2327   qh  varchar2(240);
2328   cmd varchar2(1000);
2329   evt_errmsg varchar2(2000);
2330 
2331   -- bes caching implementation
2332   l_agent_obj  wf_agent_obj;
2333   p_executed   boolean;
2334 begin
2335   if (p_queue_handler is null) then
2336     -- get queue details from cache for given agent GUID
2337     l_agent_obj := wf_bes_cache.GetAgentByGUID(p_agent_guid);
2338     if (l_agent_obj is not null) then
2339       qh := l_agent_obj.QUEUE_HANDLER;
2340     end if;
2341   else
2342     -- ### add verification in the future
2343     qh := p_queue_handler;
2344   end if;
2345 
2346   -- Set globals so the queue handlers can reference them.
2347   WF_EVENT.g_correlation := p_correlation;
2348   WF_EVENT.g_deq_condition := p_deq_condition;
2349 
2350   -- Call the static calls implementation first
2351   p_executed := false;
2352 
2353   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2354     wf_log_pkg.string2(wf_log_pkg.level_statement,
2355                       'wf.plsql.wf_event.dequeue.qhandler_callout',
2356                       'Start executing queue handler - '||qh, true);
2357   end if;
2358 
2359   WF_AGT_DYN_FUNCS.StaticDequeue(qh, p_agent_guid, p_event, p_wait, p_executed);
2360 
2361   if (not p_executed) then
2362     -- p_queue_handler is normally null, or control by us
2363     -- BINDVAR_SCAN_IGNORE
2364     cmd := 'begin '||qh||'.dequeue(:v1, :v2); end;';
2365     execute immediate cmd using in  p_agent_guid,
2366                                 out p_event;
2367   end if;
2368 
2369   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2370     wf_log_pkg.string2(wf_log_pkg.level_statement,
2371                       'wf.plsql.wf_event.dequeue.qhandler_callout',
2372                       'End executing queue handler - '||qh, false);
2373   end if;
2374 
2375   p_queue_handler := qh;
2376 exception
2377   when others then
2378     wf_core.context('Wf_Event', 'Dequeue', p_agent_guid);
2379     wf_core.token('FUNCTION_NAME', qh||'.dequeue()');
2380     --wf_core.raise('WF_EXT_FUNCTION');
2381     raise;
2382 end;
2383 ---------------------------------------------------------------------------
2384 /*
2385 ** AddParameterToList - <described in WFEVENTS.pls>
2386 */
2387 -- YOHUANG 3571176
2388 -- Share the same logic as WF_EVENT_T.AddParameterToList
2389 -- If there is any change of logic in this method, the change
2390 -- should be propagated over to WF_EVENT_T.
2391 PROCEDURE AddParameterToList(p_name  in varchar2,
2392                              p_value in varchar2,
2393                              p_parameterlist in out nocopy wf_parameter_list_t)
2394 is
2395   j       number;
2396   found   boolean := FALSE;
2397 begin
2398   if (p_ParameterList is null) then
2399   --
2400   -- Initialize Parameter List and set value
2401   --
2402       p_ParameterList := wf_parameter_list_t(null);
2403       p_ParameterList(1) := wf_parameter_t(p_Name, p_Value);
2404   else
2405   --
2406   -- parameter list exists, add parameter to list
2407   --
2408     j := 1;
2409     while (NOT found AND j <= p_parameterlist.COUNT ) LOOP
2410       -- YOHUANG 3566991, make sure myList(j) is not null
2411       -- to avoid 36025 ora error
2412       IF (p_parameterlist(j) IS NOT NULL) THEN
2413         if (p_parameterlist(j).getName() = p_name) then
2414            found := TRUE;
2415            p_parameterlist(j).setValue(p_Value);
2416         END if;
2417       END IF;
2418       j := j+1;
2419     end loop;
2420 
2421     -- otherwise, add new parameter to list --
2422 
2423     if (NOT found) then
2424       p_ParameterList.EXTEND;
2425       j := p_ParameterList.COUNT;
2426       p_ParameterList(j) := wf_parameter_t(p_name, p_Value);
2427     end if;
2428   end if;
2429 end AddParameterToList;
2430 ---------------------------------------------------------------------------
2431 /*
2432 ** AddParameterToListPos - <described in WFEVENTS.pls>
2433 */
2434 PROCEDURE AddParameterToListPos(p_name  in varchar2,
2435                              p_value in varchar2,
2436                              p_position out nocopy integer,
2437                              p_parameterlist in out nocopy wf_parameter_list_t)
2438 is
2439   j       integer;
2440 
2441 begin
2442   if (p_ParameterList is null) then
2443   --
2444   -- Initialize Parameter List and set value
2445   --
2446       p_ParameterList := wf_parameter_list_t(null);
2447       p_position := 1;
2448       p_ParameterList(1) := wf_parameter_t(p_Name, p_Value);
2449   else
2450   --
2451   -- parameter list exists, add parameter to list
2452   --
2453     p_ParameterList.EXTEND;
2454     j := p_ParameterList.COUNT;
2455     p_position := j;
2456     p_ParameterList(j) := wf_parameter_t(p_Name, p_Value);
2457   end if;
2458 
2459 end AddParameterToListPos;
2460 ---------------------------------------------------------------------------
2461 /*
2462 ** GetValueForParameter - <described in WFEVENTS.pls>
2463 */
2464 FUNCTION getValueForParameter(p_Name in varchar2,
2465                               p_ParameterList in wf_parameter_list_t )
2466 return varchar2 is
2467   myList  wf_parameter_list_t;
2468   pos     number := 1;
2469 begin
2470   myList := p_ParameterList;
2471   if (myList is null) then
2472     return NULL;
2473   end if;
2474 
2475   pos := myList.LAST;
2476   --while(pos <= myList.COUNT) loop
2477   while(pos is not null) loop
2478     if (myList(pos).getName() = p_Name) then
2479 
2480       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2481          wf_log_pkg.string(wf_log_pkg.level_statement,
2482                           'wf.plsql.WF_EVENT.getValueForParam.get',
2483                           'Name:'||p_Name||' Value:'||myList(pos).getValue());
2484       end if;
2485 
2486       return myList(pos).getValue();
2487     end if;
2488     --pos := pos + 1;
2489     pos := myList.PRIOR(pos);
2490   end loop;
2491   return NULL;
2492 end getValueForParameter;
2493 ---------------------------------------------------------------------------
2494 /*
2495 ** GetValueForParameterPos - Gets value for position from wf_parameter_list_t
2496 */
2497 FUNCTION getValueForParameterPos(p_position in integer,
2498                               p_parameterlist in wf_parameter_list_t)
2499 return varchar2 is
2500   myList  wf_parameter_list_t;
2501 begin
2502   myList := p_ParameterList;
2503   if (myList is null) then
2504     return NULL;
2505   end if;
2506 
2507   return myList(p_position).getValue();
2508 
2509 end getValueForParameterPos;
2510 ---------------------------------------------------------------------------
2511 /*
2512 ** SetDispatchMode - <described in WFEVENTS.pls>
2513 */
2514 PROCEDURE SetDispatchMode (p_mode  in varchar2)
2515 is
2516 begin
2517   if p_mode = 'ASYNC' then
2518     wf_event.phase_maxthreshold := -1;
2519   else
2520     wf_event.phase_maxthreshold := 100;
2521   end if;
2522 exception
2523   when others then
2524     wf_core.context('Wf_Event', 'SetDispatchMode', p_mode);
2525     raise;
2526 end SetDispatchMode;
2527 ---------------------------------------------------------------------------
2528 /*
2529 ** InitPhaseMinThreshold <described in WFEVENTS.pls>
2530 */
2531 PROCEDURE InitPhaseMinThreshold
2532 is
2533 begin
2534   wf_event.phase_minthreshold := 0;
2535 end InitPhaseMinThreshold;
2536 ---------------------------------------------------------------------------
2537 /*
2538 ** DeferEvent - <described in WFEVENTS.pls>
2539 */
2540 PROCEDURE DeferEvent(p_source_type        in     varchar2,
2541                      p_event              in out nocopy wf_event_t)
2542 is
2543   defagent  wf_agent_t;
2544 
2545 begin
2546 
2547   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2548      wf_log_pkg.string(wf_log_pkg.level_procedure,
2549                       'wf.plsql.WF_EVENT.DeferEvent.Begin',
2550                       'Deferring Event: '||p_event.getEventName());
2551   end if;
2552   --
2553   -- Get the Local System Name and set the deferred agent
2554   --
2555 
2556   defagent := wf_agent_t('WF_DEFERRED',wf_event.local_system_name);
2557 
2558   --
2559   -- If the defer is for a local event, set the
2560   -- Deferred Agent/System into the message for
2561   -- reference when we process the event
2562   --
2563   if p_source_type = 'LOCAL' then
2564     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2565        wf_log_pkg.string(wf_log_pkg.level_statement,
2566                         'wf.plsql.WF_EVENT.DeferEvent.Local',
2567                         'Detected as Local, setting From Agent:'||
2568                         'WF_DEFERRED@'||wf_event.local_system_name);
2569     end if;
2570     p_event.From_Agent := defagent;
2571   end if;
2572 
2573   --
2574   -- Enqueue onto the deferred agent
2575   --
2576   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2577      wf_log_pkg.string(wf_log_pkg.level_statement,
2578                       'wf.plsql.WF_EVENT.DeferEvent.done',
2579                       'Enqueuing on Deferred Queue');
2580   end if;
2581 
2582   wf_event.enqueue(p_event,defagent);
2583 
2584 exception
2585   when others then
2586     wf_core.context('Wf_Event', 'DeferEvent', p_event.getEventName(),
2587                         p_event.getEventKey());
2588     raise;
2589 end DeferEvent;
2590 ---------------------------------------------------------------------------
2591 /*
2592 ** DeferEventToJava - <described in WFEVENTS.pls>
2593 */
2594 PROCEDURE DeferEventToJava(p_source_type        in     varchar2,
2595                            p_event              in out nocopy wf_event_t)
2596 is
2597   defagent  wf_agent_t;
2598 
2599 begin
2600   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2601      wf_log_pkg.string(wf_log_pkg.level_procedure,
2602                       'wf.plsql.WF_EVENT.DeferEventToJava.Begin',
2603                       'Deferring Event: '|| p_event.getEventName());
2604   end if;
2605   --
2606   -- Get the Local System Name and set the deferred agent
2607   --
2608   defagent := wf_agent_t('WF_JAVA_DEFERRED', wf_event.local_system_name);
2609 
2610   --
2611   -- If the defer is for a local event, set the
2612   -- Deferred Agent/System into the message for
2613   -- reference when we process the event
2614   --
2615   if p_source_type = 'LOCAL' then
2616     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2617        wf_log_pkg.string(wf_log_pkg.level_statement,
2618                         'wf.plsql.WF_EVENT.DeferEventToJava.Local',
2619                         'Detected as Local, setting From Agent:'||
2620                         'WF_JAVA_DEFERRED@'|| wf_event.local_system_name);
2621 
2622     end if;
2623     p_event.From_Agent := defagent;
2624   end if;
2625 
2626   --
2627   -- Enqueue onto the deferred agent
2628   --
2629 
2630   --
2631   -- NOTE: Since we know that we need to defer to WF_JAVA_DEFERRED, we will
2632   --       directly invoke enqueue on the PL/SQL queue handler
2633   --
2634   wf_event_ojmstext_qh.enqueue(p_event, defagent);
2635 
2636   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2637      wf_log_pkg.string(wf_log_pkg.level_statement,
2638                       'wf.plsql.WF_EVENT.DeferEventToJava.done',
2639                       'Enqueuing on Java Deferred Queue');
2640   end if;
2641 
2642 exception
2643   when others then
2644     wf_core.context('Wf_Event', 'DeferEventToJava', p_event.getEventName(),
2645                      p_event.getEventKey());
2646     raise;
2647 end DeferEventToJava;
2648 ---------------------------------------------------------------------------
2649 /*
2650 ** GetDeferEventCtx - <described in WFEVENTS.pls>
2651 */
2652 PROCEDURE GetDeferEventCtx (p_source_type     in out nocopy     varchar2,
2653                             p_agent_name      in         varchar2,
2654                             p_system_name     in         varchar2,
2655                             p_event           in         wf_event_t)
2656 is
2657   subguid  raw(16);
2658   lphasestart number;
2659   lsrc     varchar2(10);
2660 
2661   -- bes caching implementation
2662   l_sub        wf_event_subs_obj;
2663   l_event_name varchar2(240);
2664 begin
2665 
2666   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2667      wf_log_pkg.string(wf_log_pkg.level_procedure,
2668                       'wf.plsql.WF_EVENT.DeferEventCtx.Begin',
2669                       'Getting Defer Event Ctx');
2670   end if;
2671   --
2672   -- Determine the Start Phase, and sourec type
2673   --
2674   subguid := p_event.Error_Subscription;
2675   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2676      wf_log_pkg.string(wf_log_pkg.level_statement,
2677                       'wf.plsql.WF_EVENT.DeferEventCtx.sub_guid',
2678                       'Sub Guid is '||subguid);
2679   end if;
2680 
2681   l_event_name := p_event.GetEventName();
2682   if subguid is not null then
2683     l_sub := wf_bes_cache.GetSubscriptionByGUID(l_event_name, subguid);
2684 
2685     if (l_sub is not null) then
2686       lsrc := l_sub.SOURCE_TYPE;
2687       lphasestart := l_sub.PHASE;
2688     else
2689       -- << sstomar : bug 5870400>>
2690       lphasestart :=  p_event.GetValueForParameter('#CURRENT_PHASE');
2691 
2692       if(lphasestart is null) then
2693         raise no_data_found;
2694       END if;
2695 
2696     end if;
2697 
2698     wf_event.phase_minthreshold := lphasestart;
2699   else
2700     wf_event.phase_minthreshold := 0; -- for deferred raise
2701   end if;
2702 
2703   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
2704      wf_log_pkg.string(wf_log_pkg.level_statement,
2705                       'wf.plsql.WF_EVENT.DeferEventCtx.phase',
2706                       'Start Phase is '||to_char(wf_event.phase_minthreshold));
2707   end if;
2708 
2709   if lsrc is null then
2710     --
2711     -- Derive the Source Type
2712     --
2713     if ((p_agent_name = 'WF_DEFERRED') AND (p_system_name = wf_event.local_system_name)) then
2714       p_source_type := 'LOCAL';
2715     elsif ((p_system_name is null) OR (p_system_name <> wf_event.local_system_name))then
2716       p_source_type := 'EXTERNAL';
2717     elsif ((p_agent_name <> 'WF_DEFERRED') AND (p_system_name = wf_event.local_system_name)) then
2718       p_source_type := 'EXTERNAL';
2719     end if;
2720   else
2721     p_source_type := lsrc;
2722   end if;
2723 
2724   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2725      wf_log_pkg.string(wf_log_pkg.level_procedure,
2726                       'wf.plsql.WF_EVENT.DeferEventCtx.End',
2727                       'Source Type is '||p_source_type);
2728   end if;
2729 
2730 exception
2731   /* Bug 2210085 */
2732   when no_data_found then
2733     /*
2734     wf_core.context('Wf_Event', 'GetDeferEventCtx','Sub guid is ' || subguid);
2735     wf_core.token('SGUID', subguid);
2736     wf_core.raise('WFE_SUB_DELETED');
2737     */
2738     raise;
2739 
2740   when others then
2741     wf_core.context('Wf_Event', 'GetDeferEventCtx', p_event.getEventName(),
2742                         p_event.getEventKey());
2743     raise;
2744 end GetDeferEventCtx;
2745 ---------------------------------------------------------------------------
2746 /*
2747 ** SetAccountName - <described in WFEVENTS.pls>
2748 */
2749 PROCEDURE SetAccountName
2750 is
2751 begin
2752 -- get the account name - only need this for WF_DEFERRED
2753   select sys_context('USERENV', 'CURRENT_SCHEMA')
2754   into wf_event.account_name
2755   from sys.dual;
2756 exception
2757   when others then
2758     wf_core.context('Wf_Event', 'SetAccountName');
2759     raise;
2760 end SetAccountName;
2761 ---------------------------------------------------------------------------
2762 --
2763 -- Bug# 2211719 - New API raise2 for calls that donot understand
2764 --                Oracle data types`
2765 /*
2766 ** raise2 - <Described in WFEVENTS.pls>
2767 */
2768 
2769 PROCEDURE raise2(p_event_name      in varchar2,
2770                 p_event_key        in varchar2,
2771                 p_event_data       in clob,
2772                 p_parameter_name1  in varchar2,
2773                 p_parameter_value1 in varchar2,
2774                 p_parameter_name2  in varchar2,
2775                 p_parameter_value2 in varchar2,
2776                 p_parameter_name3  in varchar2,
2777                 p_parameter_value3 in varchar2,
2778                 p_parameter_name4  in varchar2,
2779                 p_parameter_value4 in varchar2,
2780                 p_parameter_name5  in varchar2,
2781                 p_parameter_value5 in varchar2,
2782                 p_parameter_name6  in varchar2,
2783                 p_parameter_value6 in varchar2,
2784                 p_parameter_name7  in varchar2,
2785                 p_parameter_value7 in varchar2,
2786                 p_parameter_name8  in varchar2,
2787                 p_parameter_value8 in varchar2,
2788                 p_parameter_name9  in varchar2,
2789                 p_parameter_value9 in varchar2,
2790                 p_parameter_name10  in varchar2,
2791                 p_parameter_value10 in varchar2,
2792                 p_parameter_name11  in varchar2,
2793                 p_parameter_value11 in varchar2,
2794                 p_parameter_name12  in varchar2,
2795                 p_parameter_value12 in varchar2,
2796                 p_parameter_name13  in varchar2,
2797                 p_parameter_value13 in varchar2,
2798                 p_parameter_name14  in varchar2,
2799                 p_parameter_value14 in varchar2,
2800                 p_parameter_name15  in varchar2,
2801                 p_parameter_value15 in varchar2,
2802                 p_parameter_name16  in varchar2,
2803                 p_parameter_value16 in varchar2,
2804                 p_parameter_name17  in varchar2,
2805                 p_parameter_value17 in varchar2,
2806                 p_parameter_name18  in varchar2,
2807                 p_parameter_value18 in varchar2,
2808                 p_parameter_name19  in varchar2,
2809                 p_parameter_value19 in varchar2,
2810                 p_parameter_name20  in varchar2,
2811                 p_parameter_value20 in varchar2,
2812                 p_send_date  in date) is
2813 l_parameter_list wf_parameter_list_t := wf_parameter_list_t();
2814 i number := 1;
2815 begin
2816 
2817   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2818      wf_log_pkg.string(wf_log_pkg.level_procedure,
2819                       'wf.plsql.WF_EVENT.raise2.Begin',
2820                       'Event Name:'||p_event_name||' Event Key:'||p_event_key);
2821   end if;
2822 
2823   if (p_parameter_name1 is not NULL) then
2824      l_parameter_list.extend;
2825      l_parameter_list(i) := CreateParameter(p_parameter_name1, p_parameter_value1);
2826      i := i + 1;
2827   end if;
2828 
2829   if (p_parameter_name2 is not NULL) then
2830      l_parameter_list.extend;
2831      l_parameter_list(i) := CreateParameter(p_parameter_name2, p_parameter_value2);
2832      i := i + 1;
2833   end if;
2834 
2835   if (p_parameter_name3 is not NULL) then
2836      l_parameter_list.extend;
2837      l_parameter_list(i) := CreateParameter(p_parameter_name3, p_parameter_value3);
2838      i := i + 1;
2839   end if;
2840 
2841   if (p_parameter_name4 is not NULL) then
2842      l_parameter_list.extend;
2843      l_parameter_list(i) := CreateParameter(p_parameter_name4, p_parameter_value4);
2844      i := i + 1;
2845   end if;
2846 
2847   if (p_parameter_name5 is not NULL) then
2848      l_parameter_list.extend;
2849      l_parameter_list(i) := CreateParameter(p_parameter_name5, p_parameter_value5);
2850      i := i + 1;
2851   end if;
2852 
2853   if (p_parameter_name6 is not NULL) then
2854      l_parameter_list.extend;
2855      l_parameter_list(i) := CreateParameter(p_parameter_name6, p_parameter_value6);
2856      i := i + 1;
2857   end if;
2858 
2859   if (p_parameter_name7 is not NULL) then
2860      l_parameter_list.extend;
2861      l_parameter_list(i) := CreateParameter(p_parameter_name7, p_parameter_value7);
2862      i := i + 1;
2863   end if;
2864 
2865   if (p_parameter_name8 is not NULL) then
2866      l_parameter_list.extend;
2867      l_parameter_list(i) := CreateParameter(p_parameter_name8, p_parameter_value8);
2868      i := i + 1;
2869   end if;
2870 
2871   if (p_parameter_name9 is not NULL) then
2872      l_parameter_list.extend;
2873      l_parameter_list(i) := CreateParameter(p_parameter_name9, p_parameter_value9);
2874      i := i + 1;
2875   end if;
2876 
2877   if (p_parameter_name10 is not NULL) then
2878      l_parameter_list.extend;
2879      l_parameter_list(i) := CreateParameter(p_parameter_name10, p_parameter_value10);
2880      i := i + 1;
2881   end if;
2882 
2883   if (p_parameter_name11 is not NULL) then
2884      l_parameter_list.extend;
2885      l_parameter_list(i) := CreateParameter(p_parameter_name11, p_parameter_value11);
2886      i := i + 1;
2887   end if;
2888 
2889   if (p_parameter_name12 is not NULL) then
2890      l_parameter_list.extend;
2891      l_parameter_list(i) := CreateParameter(p_parameter_name12, p_parameter_value12);
2892      i := i + 1;
2893   end if;
2894 
2895   if (p_parameter_name13 is not NULL) then
2896      l_parameter_list.extend;
2897      l_parameter_list(i) := CreateParameter(p_parameter_name13, p_parameter_value13);
2898      i := i + 1;
2899   end if;
2900 
2901   if (p_parameter_name14 is not NULL) then
2902      l_parameter_list.extend;
2903      l_parameter_list(i) := CreateParameter(p_parameter_name14, p_parameter_value14);
2904      i := i + 1;
2905   end if;
2906 
2907   if (p_parameter_name15 is not NULL) then
2908      l_parameter_list.extend;
2909      l_parameter_list(i) := CreateParameter(p_parameter_name15, p_parameter_value15);
2910      i := i + 1;
2911   end if;
2912 
2913   if (p_parameter_name16 is not NULL) then
2914      l_parameter_list.extend;
2915      l_parameter_list(i) := CreateParameter(p_parameter_name16, p_parameter_value16);
2916      i := i + 1;
2917   end if;
2918 
2919   if (p_parameter_name17 is not NULL) then
2920      l_parameter_list.extend;
2921      l_parameter_list(i) := CreateParameter(p_parameter_name17, p_parameter_value17);
2922      i := i + 1;
2923   end if;
2924 
2925   if (p_parameter_name18 is not NULL) then
2926      l_parameter_list.extend;
2927      l_parameter_list(i) := CreateParameter(p_parameter_name18, p_parameter_value18);
2928      i := i + 1;
2929   end if;
2930 
2931   if (p_parameter_name19 is not NULL) then
2932      l_parameter_list.extend;
2933      l_parameter_list(i) := CreateParameter(p_parameter_name19, p_parameter_value19);
2934      i := i + 1;
2935   end if;
2936 
2937   if (p_parameter_name20 is not NULL) then
2938      l_parameter_list.extend;
2939      l_parameter_list(i) := CreateParameter(p_parameter_name20, p_parameter_value20);
2940   end if;
2941 
2942   wf_event.raise(p_event_name, p_event_key, p_event_data, l_parameter_list, p_send_date);
2943 
2944 exception
2945   when others then
2946     raise;
2947 end raise2;
2948 ---------------------------------------------------------------------------
2949 /*
2950 ** CreateParameter - <Described in WFEVENTS.pls>
2951 */
2952 FUNCTION CreateParameter( p_name      in  varchar2,
2953                           p_value     in  varchar2)
2954 return wf_parameter_t
2955 is
2956 l_parameter wf_parameter_t := wf_parameter_t(null, null);
2957 begin
2958     l_parameter.SetName(p_name);
2959     l_parameter.SetValue(p_value);
2960     return l_parameter;
2961 exception
2962     when others then
2963        raise;
2964 end CreateParameter;
2965 
2966 --------------------------------------------------------------------
2967 --Bug 2375902
2968 --New API raise3 which has the parameters of the event
2969 --as in out parameters and hence can be used by the calling program.
2970 --------------------------------------------------------------------
2971 PROCEDURE raise3(p_event_name      in varchar2,
2972                 p_event_key        in varchar2,
2973                 p_event_data       in clob,
2974                 p_parameter_list   in out nocopy wf_parameter_list_t,
2975                 p_send_date        in date)
2976 is
2977   o_value varchar2(200);
2978 event wf_event_t;
2979 begin
2980 
2981   -- Bug 9370391: tag DB session for BES module
2982   wf_core.tag_db_session(wf_core.conn_tag_bes, p_event_name);
2983 
2984   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2985      wf_log_pkg.string(wf_log_pkg.level_procedure,
2986                       'wf.plsql.WF_EVENT.raise3.Begin',
2987                       'Event Name:'||p_event_name||' Event Key:'||p_event_key ||
2988                       'Maximum nested raise count:'|| wf_event.max_nested_raises||
2989                       'Nested raise count: '|| wf_event.nested_raise_count);
2990   end if;
2991 
2992   wf_event.nested_raise_count := wf_event.nested_raise_count + 1;
2993   if (wf_event.nested_raise_count > wf_event.max_nested_raises) then
2994     --Bug 2620834
2995     --The nested count is reset to the initial value that was set before the
2996     --recursion error occurs.
2997     --In future if we allow the user to set the nested-raises -count
2998     --we could think of restting it to that value instead of zero.
2999     wf_event.nested_raise_count := 0;
3000 
3001     if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
3002        wf_log_pkg.string(wf_log_pkg.level_error,
3003                         'wf.plsql.WF_EVENT.raise3.recursion_error',
3004                         'Recursion error raised. Nested raise count exceeded threshold');
3005     end if;
3006 
3007     wf_core.context('Wf_Event', 'raise', p_event_name, p_event_key);
3008     wf_core.raise('WFE_RECURSION');
3009   end if;
3010 
3011   --Create the event that is to be raised
3012   wf_event_t.initialize(event);
3013   event.Send_Date      := nvl(p_send_date,sysdate);
3014   event.Event_Name     := p_event_name;
3015   event.Event_Key      := p_event_key;
3016   event.Parameter_List := p_parameter_list;
3017   if (p_event_data is not null) then
3018     event.event_data   := p_event_data ;
3019   end if;
3020 
3021   wf_event.dispatch('LOCAL', null, event);
3022 
3023   --Output the parameterlist which may have been
3024   --modified
3025   p_parameter_list := event.getParameterList();
3026 
3027   if (wf_event.nested_raise_count >0) then
3028     wf_event.nested_raise_count := wf_event.nested_raise_count - 1;
3029   end if;
3030 
3031   event := null;
3032 
3033 exception
3034   when others then
3035     raise;
3036 end raise3;
3037 
3038 --------------------------------------------------------------------------------
3039 -- Sets the correlation for dequeuing.
3040 --
3041 -- NOTE: This has been done because we did not want to change the signature of
3042 --       dequeue in the queue handlers
3043 --
3044 -- p_correlation - the correlation
3045 --------------------------------------------------------------------------------
3046 PROCEDURE Set_Correlation(p_correlation in varchar2)
3047 IS
3048 BEGIN
3049   WF_EVENT.g_correlation := p_correlation;
3050   WF_EVENT.navigation := dbms_aq.first_message;
3051 
3052 END Set_Correlation;
3053 
3054 ---------------------------------------------------------------------------
3055 /*
3056 ** SetMaxNestedRaise  - Populates Global Variable : max_nested_raises
3057 **                      with the value specified in the input parameter.
3058 */
3059 PROCEDURE SetMaxNestedRaise (maxcount in  number)
3060 is
3061 begin
3062   wf_event.max_nested_raises := maxcount;
3063 end;
3064 ---------------------------------------------------------------------------
3065 /*
3066 ** SetNestedRaiseCount  - Populates Global Variable : nested_raises_count
3067 **                        with the value specified in the input parameter.
3068 ** PRIVATE PROCEDURE
3069 */
3070 PROCEDURE SetNestedRaiseCount (nestedcount in number)
3071 is
3072 begin
3073   wf_event.nested_raise_count := nestedcount;
3074   --This private variable P_NESTED_RAISE_COUNT is updated
3075   --in sync with the setting of nested_raise_count global variable
3076   --It is used when the recursion error occurs inorder to reset the
3077   --value of wf_event.nested_raise_count.
3078   --P_NESTED_RAISE_COUNT        := wf_event.nested_raise_count;
3079 end;
3080 ---------------------------------------------------------------------------
3081 /*
3082 ** GetMaxNestedRaise  - Get the value of the Global Variable max_nested_raises
3083 */
3084 
3085 FUNCTION GetMaxNestedRaise
3086 return number
3087 is
3088 begin
3089   return wf_event.max_nested_raises;
3090 end;
3091 
3092 ---------------------------------------------------------------------------
3093 /*
3094 ** GetNestedRaiseCount  - Get the value of the Global Variable
3095 **                        nested_raises_count
3096 */
3097 
3098 FUNCTION GetNestedRaiseCount
3099 return number
3100 is
3101 begin
3102   return wf_event.nested_raise_count;
3103 end;
3104 
3105 ---------------------------------------------------------------------------
3106 
3107 FUNCTION Get_MsgId
3108 return varchar2
3109 is
3110 begin
3111   return wf_event.g_msgid;
3112 end;
3113 
3114 ---------------------------------------------------------------------------
3115 /*
3116 ** GetLocalSystemInfo - <described in WFEVENTS.pls>
3117 */
3118 PROCEDURE GetLocalSystemInfo(system_guid   out nocopy raw,
3119                              system_name   out nocopy varchar2,
3120                              system_status out nocopy varchar2)
3121 is
3122 begin
3123   system_guid := wf_event.local_system_guid;
3124   system_name := wf_event.local_system_name;
3125   system_status := wf_event.local_system_status;
3126 exception
3127   when others then
3128     wf_core.context('Wf_Event', 'GetLocalSystemName');
3129 end GetLocalSystemInfo;
3130 ---------------------------------------------------------------------------
3131 /*
3132 ** GetSourceAgentGUID - <described in WFEVENTS.pls>
3133 */
3134 PROCEDURE GetSourceAgentGUID(agent_name   in         varchar2,
3135                              agent_system in         varchar2,
3136                              agent_guid   out nocopy raw)
3137 is
3138   -- bes caching implementation
3139   l_agent_obj  wf_agent_obj;
3140 begin
3141 
3142   l_agent_obj := wf_bes_cache.GetAgentByName(agent_name, agent_system);
3143 
3144   if (l_agent_obj is not null) then
3145     agent_guid := l_agent_obj.GUID;
3146   else
3147     if (wf_log_pkg.level_error >= fnd_log.g_current_runtime_level) then
3148       wf_log_pkg.string(wf_log_pkg.level_error,
3149                         'wf.plsql.WF_EVENT.GetSourceAgentGUID.Error',
3150                         'Specified source agent row does '||
3151                         'not exist in database.  Setting to NULL.');
3152     end if;
3153     agent_guid := null;
3154   end if;
3155 exception
3156   when others then
3157     wf_core.context('Wf_Event', 'GetSourceAgentGUID', agent_name);
3158     raise;
3159 end GetSourceAgentGUID;
3160 ---------------------------------------------------------------------------
3161 /*
3162  ** GetAgentDetails (PRIVATE) - Gets the agents details such as the queue name
3163  **                              schema name and recepients
3164  */
3165 procedure GetAgentDetails(agent_name    in        varchar2)
3166 is
3167 
3168   l_queue_name     varchar2(80);
3169   l_pos            number := 0;
3170   l_name           varchar2(30);
3171   l_owner          varchar2(30);
3172   l_queue_table    varchar2(30);
3173 
3174   -- bes caching implementation
3175   l_agent_obj     wf_agent_obj;
3176 begin
3177   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3178     wf_log_pkg.string(wf_log_pkg.level_procedure,
3179                       'wf.plsql.WF_EVENT.GetAgentDetails.Begin',
3180                       'Get Agent Details');
3181   end if;
3182 
3183    if(agent_name is not null and agent_name <> wf_event.pv_last_agent_name) then
3184     -- for a given agent name Query wf_agents to get the agent info
3185 
3186     l_agent_obj := wf_bes_cache.GetAgentByName(agent_name, null);
3187     if (l_agent_obj is not null) then
3188       l_queue_name := l_agent_obj.QUEUE_NAME;
3189     end if;
3190 
3191     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
3192       wf_log_pkg.string(wf_log_pkg.level_statement,
3193                        'wf.plsql.WF_EVENT.GetAgentDetails',
3194                        'l_queue_name = ' || l_queue_name);
3195     end if;
3196 
3197     -- since since queue_name is a nullable col. l_queue_name could be null
3198     -- let the caller program handle the case of null queue_name
3199     if(l_queue_name is not null) then
3200       -- derive the queue name and the schema
3201 
3202       l_pos := instr(l_queue_name,'.');
3203       l_name := substr(l_queue_name, l_pos + 1);
3204 
3205       if (l_pos > 0) then
3206         l_owner := substr(l_queue_name, 1, l_pos - 1);
3207       else
3208         -- if queue_name does not contain schema we will look in WF_SCHEMA
3209         l_owner := wf_event.schema_name;
3210       end if;
3211 
3212       if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
3213         wf_log_pkg.string(wf_log_pkg.level_statement,
3214                          'wf.plsql.WF_EVENT.GetAgentDetails',
3215                          'l_name = ' || l_name ||
3216                          ' l_owner = ' || l_owner);
3217       end if;
3218 
3219       -- retrieve recipients (MULTIPLE or SINGLE) for AQ
3220       -- 3659756 When get agent details, check if the enqueue and dequeue are enabled.
3221       select aq.queue_type, aq.QUEUE_TABLE, trim(dequeue_enabled)
3222       into WF_EVENT.g_queueType, l_queue_table, WF_EVENT.pv_last_dequeue_enabled
3223       from   all_queues aq
3224       where  aq.owner = l_owner
3225       and    aq.name = l_name;
3226 
3227       select aqt.recipients, aqt.message_grouping
3228       into   WF_EVENT.pv_last_recipients, WF_EVENT.g_message_grouping
3229       from   all_queue_tables aqt
3230       where  aqt.queue_table = l_queue_table
3231       and    aqt.owner = l_owner;
3232 
3233       -- update package variables
3234       wf_event.pv_last_agent_name := agent_name;
3235       -- YOHUANG, l_queue_name shouldn't have owner information
3236       wf_event.pv_last_queue_name := l_name; --l_queue_name;
3237       wf_event.pv_last_schema_name := l_owner;
3238     else
3239       raise no_data_found;
3240     end if;
3241   end if;
3242   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3243     wf_log_pkg.string(wf_log_pkg.level_procedure,
3244                       'wf.plsql.WF_EVENT.GetAgentDetails.END',
3245                       'Get Agent Details');
3246   end if;
3247 exception
3248   when no_data_found then
3249     -- let the caller handle it
3250      raise;
3251   when others then
3252     -- let the caller handle it
3253      raise;
3254 end GetAgentDetails;
3255 ---------------------------------------------------------------------------
3256 /*
3257  ** StartAgent - <described in WFEVENTS.pls>
3258  ** Though We cache the agent details, we still check if the agent and
3259  ** fixed name queues are started or not every time when listen() or
3260  ** listen_to_agent is called, just be conservative
3261  ** Bug 3659756
3262  **   Assume the fixed name queues are always started (if not, the component listener
3263  **   will error out and sys admin will fix it)
3264  **   Only start the agent that is being listened.
3265  **   Only start the agent once per session if agent name is not changed in the same session.
3266  */
3267 procedure StartAgent(agent_name   in        varchar2)
3268 is
3269   -- l_enqueue_enabled   VARCHAR2(30);
3270   -- l_dequeue_enabled   VARCHAR2(30);
3271 
3272    --Bug 2307433
3273    --Cursor for obtaining the names of the
3274    --deferred and error queue.
3275    --Bug 3271311, add the WF_JAVA queues for start.
3276    --Bug 3659756, no longer start fixed name queues.
3277    /**
3278    CURSOR    q_disabled (schema varchar2) is
3279      SELECT  name
3280      FROM    all_queues
3281      WHERE   name in ('WF_DEFERRED', 'WF_ERROR', 'WF_JAVA_DEFERRED','WF_JAVA_ERROR')
3282      AND     owner =schema
3283      AND   ((trim(enqueue_enabled) = 'NO') OR (trim(dequeue_enabled) = 'NO'));
3284    */
3285 
3286 begin
3287   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3288     wf_log_pkg.string(wf_log_pkg.level_procedure,
3289                       'wf.plsql.WF_EVENT.StartAgent.Begin',
3290                       'Starting Agents');
3291   end if;
3292   --Bug 2307433
3293    --Enable the deferred and error queues for
3294    --enqueue and dequeue incase they are disabled
3295    --In any cases, the WF_DEFERRED, WF_ERROR, WF_JAVA_ERROR and WF_JAVA_DEFERRED
3296    --must be started.
3297    --schema := wf_core.translate('WF_SCHEMA');
3298    --Bug 3659756, no longer start fixed name queues.
3299    /*
3300    for q_name in q_disabled (wf_event.schema_name) loop
3301      DBMS_AQADM.START_QUEUE(wf_event.schema_name||'.'||q_name.name);
3302    end loop;
3303    */
3304    -- The agent details must be retrieved even for seeded queue.
3305   GetAgentDetails(agent_name);
3306 
3307   if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
3308       wf_log_pkg.string(wf_log_pkg.level_statement,
3309                        'wf.plsql.WF_EVENT.StartAgent',
3310                        'dequeue_enabled = ' || WF_EVENT.pv_last_dequeue_enabled);
3311   end if;
3312 
3313   if (WF_EVENT.pv_last_dequeue_enabled = 'NO') then
3314   -- If the user has disabled the queue for enqueue don't override it.
3315   -- So we only enable the dequeue if dequeue is not enabled and we don't change
3316   -- the current setting of enqueue.
3317 
3318     if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
3319          wf_log_pkg.string(wf_log_pkg.level_statement,
3320                            'wf.plsql.WF_EVENT.StartAgent',
3321                            'starting queue = ' || wf_event.pv_last_schema_name
3322                             || '.' || wf_event.pv_last_agent_name);
3323     end if;
3324 
3325     DBMS_AQADM.START_QUEUE(wf_event.pv_last_schema_name || '.' || wf_event.pv_last_queue_name, FALSE);
3326 
3327     WF_EVENT.pv_last_dequeue_enabled := 'YES';
3328   end if;
3329 
3330   if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3331     wf_log_pkg.string(wf_log_pkg.level_procedure,
3332                       'wf.plsql.WF_EVENT.StartAgent.End',
3333                       'Starting Agents');
3334   end if;
3335 exception
3336   when no_data_found then
3337     wf_core.context('Wf_Event', 'StartAgent', agent_name);
3338     wf_core.raise('WFE_AGENT_NOTEXIST');
3339   when others then
3340     wf_core.context('Wf_Event', 'StartAgent', agent_name);
3341     raise;
3342 end StartAgent;
3343 ---------------------------------------------------------------------------
3344 /*
3345 ** Peek_Agent  - <Described in WFEVENTS.pls>
3346 */
3347 FUNCTION Peek_Agent  (p_agent_name IN VARCHAR2)
3348          RETURN VARCHAR2
3349 AS
3350   -- NOTE: This must be done in PL/SQL because in 8i DBMS_AQ.LISTEN is not
3351   -- supported in Java
3352 
3353   l_agent          sys.aq$_agent;
3354   l_agent_list     dbms_aq.aq$_agent_list_t;
3355 
3356   LISTEN_EXCEPTION exception;
3357 
3358   pragma exception_init(LISTEN_EXCEPTION, -25254);
3359 BEGIN
3360 
3361   if p_agent_name is null then
3362     return 'N';
3363   end if;
3364 
3365   -- Perf bug 2987857
3366   -- If p_agent_name is same as pkg var, then details are not required
3367   -- to be retrieved again
3368   -- YOHUANG, move the cache validation logic into getAgentDetails
3369 
3370     -- Retrieve queue name for the agent
3371     -- Only local agents should be checked for - bug 2902048
3372     -- GetAgentDetails becomes the single source to start a particular agent
3373     -- and can be called without worrying about fixed name queues
3374     GetAgentDetails(p_agent_name);
3375 
3376   -- bug 2897326, agent_list is initialized differently for
3377   -- multi or single consumer queue
3378 
3379   IF wf_event.pv_last_recipients = 'MULTIPLE' THEN
3380     l_agent_list(1) := sys.aq$_agent(wf_event.pv_last_agent_name,
3381                                     wf_event.pv_last_schema_name || '.' || wf_event.pv_last_queue_name, null);
3382   ELSE
3383     l_agent_list(1) := sys.aq$_agent(null,
3384                                      wf_event.pv_last_schema_name || '.' || wf_event.pv_last_queue_name, null);
3385   END IF;
3386 
3387   -- "Listen" for messages on this queue
3388   BEGIN
3389     DBMS_AQ.Listen(agent_list => l_agent_list,
3390                    wait       => 0,
3391                    agent      => l_agent);
3392   EXCEPTION
3393   WHEN LISTEN_EXCEPTION THEN
3394       RETURN 'N';
3395   END;
3396 
3397   RETURN 'Y';
3398 END Peek_Agent ;
3399 
3400 -- GetParamListFromString
3401 --   Takes a space delimited NAME=VALUE pairs of Subscription Parameters
3402 --   string and returns a WF_PARAMETER_LIST_T
3403 -- IN
3404 --   p_parameters A string with space delimited name=value pairs
3405 function GetParamListFromString(p_parameters in varchar2)
3406 return wf_parameter_list_t
3407 is
3408   l_parameters varchar2(5000);
3409   l_start      pls_integer := 0;
3410   l_end        pls_integer := 0;
3411   l_endposition number;
3412   l_namevalue  varchar2(4000);
3413   l_value      varchar2(4000);
3414   l_name       varchar2(4000);
3415   l_equalpos   number;
3416   l_param_list wf_parameter_list_t;
3417 begin
3418   l_parameters := p_parameters;
3419 
3420   if (l_parameters is not null) then
3421     l_parameters := replace(l_parameters, wf_core.newline,' ');
3422     l_parameters := replace(l_parameters, wf_core.tab,' ');
3423     l_parameters := replace(l_parameters, wf_core.cr,'');
3424     l_parameters := l_parameters||' ';
3425 
3426     l_start:= 1;
3427     l_end := length(l_parameters);
3428 
3429     while (l_start < l_end) loop
3430       l_endposition := instr(l_parameters, ' ', l_start, 1);
3431       l_namevalue := rtrim(ltrim(substr(l_parameters, l_start, l_endposition-l_start)));
3432 
3433       l_equalpos := instr(l_namevalue, '=', 1, 1);
3434       l_name := substr(l_namevalue,1,l_equalpos-1);
3435       l_value := substr(l_namevalue,l_equalpos+1,length(l_namevalue));
3436 
3437       wf_event.AddParameterToList(l_name, l_value, l_param_list);
3438       l_start := l_endposition+1;
3439     end loop;
3440   end if;
3441   return l_param_list;
3442 exception
3443   when others then
3444     wf_core.Context('WF_EVENT', 'GetParamListFromString');
3445     raise;
3446 end GetParamListFromString;
3447 
3448   /* PRIVATE
3449    *
3450    * gets the agent's message_grouping, returns TRUE if TRANSACTIONAL, FALSE
3451    * otherwise.
3452    */
3453   function isValidToGroupMessages(p_agentName in varchar2) return boolean
3454   is
3455     l_msgGrouping varchar2(30);
3456   begin
3457     if (p_agentName is not null) then
3458 
3459       if(p_agentName <> wf_event.pv_last_agent_name) then
3460         GetAgentDetails(p_agentName);
3461       end if;
3462 
3463       return (WF_EVENT.g_message_grouping = 'TRANSACTIONAL');
3464     else
3465       return false;
3466     end if;
3467   exception
3468   when OTHERS then
3469     return false;
3470   end;
3471 
3472   -- for logging purposes
3473   function getNavigationParams return varchar2 is
3474     l_ret varchar2(1000):= 'navigation(';
3475   begin
3476     if (g_currentNavigation is null) then
3477       l_ret:= l_ret|| 'null), ';
3478     elsif g_currentNavigation= dbms_aq.NEXT_MESSAGE then
3479       l_ret:= l_ret|| 'NEXT_MESSAGE), ';
3480     elsif g_currentNavigation= dbms_aq.FIRST_MESSAGE then
3481       l_ret:= l_ret|| 'FIRST_MESSAGE), ';
3482     elsif g_currentNavigation= dbms_aq.NEXT_TRANSACTION then
3483       l_ret:= l_ret|| 'NEXT_TRANSACTION), ';
3484     else
3485       l_ret:= l_ret|| g_currentNavigation||'), ';
3486     end if;
3487 
3488     l_ret := l_ret|| ' threshold(';
3489     if (g_navResetThreshold is null) then
3490       l_ret:= l_ret|| 'null), ';
3491     else
3492       l_ret:= l_ret|| g_navResetThreshold||'), ';
3493     end if;
3494 
3495     l_ret := l_ret|| ' messageCount(';
3496     if (g_processedMessagesCount is null) then
3497       l_ret:= l_ret|| 'null), ';
3498     else
3499       l_ret:= l_ret|| g_processedMessagesCount||'), ';
3500     end if;
3501 
3502     l_ret := l_ret|| ' message grouping(';
3503     if (g_groupDequeuing) then
3504       l_ret:= l_ret|| 'TRUE)';
3505     else
3506       l_ret:= l_ret|| 'FALSE)';
3507     end if;
3508 
3509     return l_ret;
3510   end getNavigationParams;
3511 
3512   -- PUBLIC - see description in package spec
3513   procedure setNavigationParams(p_agentName in varchar2
3514                                    , p_navigationThreshold in number)
3515   is
3516     l_api varchar2(100) := g_packName||'setNavigationParams';
3517   begin
3518     if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3519        wf_log_pkg.string(wf_log_pkg.level_procedure, l_api,
3520                'BEGIN agent('||p_agentName||'), navigationThreshold(' ||
3521                      p_navigationThreshold||')');
3522     end if;
3523 
3524     -- if not parameters are passed, we assume it is a call from exception block,
3525     -- so we keep previous values IF ANY, except for g_processedMessagesCount
3526     if (p_agentName is not null) then
3527       -- 0 or positive are valid only
3528       if (p_navigationThreshold>0) then
3529         g_navResetThreshold := p_navigationThreshold;
3530       else
3531         g_navResetThreshold:=0; -- default behavior, no max threshold
3532       end if;
3533 
3534       g_groupDequeuing := isValidToGroupMessages(p_agentName);
3535       g_currentNavigation :=null;
3536     end if;
3537 
3538     g_processedMessagesCount :=0;
3539 
3540     if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3541        wf_log_pkg.string(wf_log_pkg.level_procedure, l_api,
3542                                                 'END '||getNavigationParams);
3543     end if;
3544   end;
3545 
3546   -- PUBLIC - see description in package spec
3547   function getQueueNavigation return BINARY_INTEGER is
3548     l_ret BINARY_INTEGER;
3549     l_api varchar2(100) := g_packName||'getQueueNavigation';
3550   begin
3551     if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3552        wf_log_pkg.string(wf_log_pkg.level_procedure, l_api,
3553              'BEGIN '||getNavigationParams);
3554     end if;
3555     if (g_navResetThreshold is null)  then -- agent navigation not initialized
3556       -- since we don't know what is the component parameter, we assume default
3557       -- behavior
3558       g_navResetThreshold :=0;
3559     end if;
3560 
3561     -- TRANSACTIONAL dequeuing, no threshold logic
3562     if ( g_groupDequeuing ) then
3563 
3564       -- first call (g_processedMessagesCount = 0).
3565       -- If navigation params are not initialized, return FIRST_MESSAGE
3566       -- else return NEXT_MESSAGE
3567       if ( g_processedMessagesCount = 0 ) then
3568         if (g_currentNavigation is null) then
3569           l_ret := dbms_aq.FIRST_MESSAGE;
3570         else
3571           l_ret := dbms_aq.NEXT_TRANSACTION;
3572         end if;
3573       else
3574         l_ret := dbms_aq.NEXT_MESSAGE;
3575       end if;
3576     else -- no TRANSACTIONAL navigation, threshold logic applies
3577 
3578       -- If first call (g_processedMessagesCount = 0), or if threshold is
3579       -- reached, return FIRST_MESSAGE,
3580       -- else return NEXT_MESSAGE
3581       if ( g_processedMessagesCount = 0 ) or
3582          (g_navResetThreshold >0 and
3583                              g_ProcessedMessagesCount >= g_navResetThreshold)
3584       then
3585         g_processedMessagesCount := 0; -- reset counter, if threshold is reached
3586         l_ret := dbms_aq.FIRST_MESSAGE;
3587       else
3588         l_ret := dbms_aq.NEXT_MESSAGE;
3589       end if;
3590     end if;
3591 
3592     g_processedMessagesCount := g_processedMessagesCount + 1;
3593     g_currentNavigation := l_ret;
3594 
3595     if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3596        wf_log_pkg.string(wf_log_pkg.level_procedure, l_api
3597                                           ,'END return='||getNavigationParams);
3598     end if;
3599 
3600     return l_ret;
3601   end;
3602 
3603   procedure resetNavigationParams
3604   is
3605   begin
3606     -- pass no parameters, just reset message counter
3607     setNavigationParams;
3608   end;
3609 
3610   /*
3611   ** Submits the concurrent request for FNDWFLIC CP.
3612   ** -- It being used to submit CP reuqest from PATCH edition.
3613   */
3614   procedure submit_cp_request
3615   is
3616 
3617     l_count number := 0;
3618     l_request_id number;
3619     l_returncode  boolean;
3620     l_user_id fnd_user.user_id%TYPE;
3621     l_user_name fnd_user.user_name%TYPE;
3622     l_resp_appl_id fnd_responsibility.application_id%TYPE;
3623     l_resp_key fnd_responsibility.responsibility_key%TYPE;
3624     l_resp_id fnd_responsibility.responsibility_id%TYPE;
3625     l_appl_short_name fnd_application.application_short_name%TYPE;
3626 
3627     PRAGMA AUTONOMOUS_TRANSACTION;
3628 
3629   begin
3630 
3631      select count(1)
3632      into l_count
3633      from fnd_concurrent_requests
3634      where concurrent_program_id in
3635                   (select concurrent_program_id
3636                   from fnd_concurrent_programs
3637                   where concurrent_program_name = 'FNDWFLIC')
3638      and phase_code = 'P' -- Pending
3639      and status_code = 'I' -- Normal
3640      and edition_name = ad_zd.get_edition
3641      and rownum < 2;
3642 
3643      -- Bug 16676888: submit CP request for FNDWFLIC only if there is no
3644      -- request submitted already from patch edition
3645      if(l_count = 0) then
3646 
3647         l_appl_short_name := 'SYSADMIN';
3648         l_user_name := 'SYSADMIN';
3649         l_resp_key := 'SYSTEM_ADMINISTRATOR';
3650 
3651         begin
3652 
3653            SELECT u.user_id
3654            INTO l_user_id
3655            FROM fnd_user u
3656            WHERE u.user_name = l_user_name;
3657 
3658            SELECT r.application_id, r.responsibility_id
3659            INTO l_resp_appl_id, l_resp_id
3660            FROM fnd_application a, fnd_responsibility r
3661            WHERE r.application_id = a.application_id
3662            AND a.application_short_name = l_appl_short_name
3663            AND r.responsibility_key = l_resp_key;
3664 
3665         exception
3666           when no_data_found then
3667              l_user_id := 0;
3668              l_resp_id := 20420;
3669              l_resp_appl_id := 1;
3670         end;
3671 
3672         --Set the SYSADMIN context
3673         fnd_global.apps_initialize(
3674 	                user_id       => l_user_id,
3675 	                resp_id       => l_resp_id,
3676 			resp_appl_id  => l_resp_appl_id);
3677 
3678 	--Set database trigger mode to TRUE
3679 	l_returncode := fnd_request.set_mode (TRUE);
3680 
3681         l_request_id := fnd_request.submit_request(
3682                             application => 'FND',
3683                             program     => 'FNDWFLIC',
3684                             description => 'Submitted Concurrent request within
3685 			                   FND_PROD_LIC_TGR trigger from PATCH edition',
3686                             start_time  => NULL,
3687                             sub_request => FALSE);
3688      end if;
3689      commit;
3690 
3691 end submit_cp_request;
3692 
3693 ---------------------------------------------------------------------------
3694 /*
3695 ** SetSystemGlobals - Populates System Global Variables
3696 */
3697 begin
3698   wf_event.local_system_guid := hextoraw(wf_core.translate('WF_SYSTEM_GUID'));
3699 
3700   wf_event.local_system_status := wf_core.translate('WF_SYSTEM_STATUS');
3701 
3702   select name into wf_event.local_system_name
3703   from wf_systems
3704   where guid = wf_event.local_system_guid;
3705 ---------------------------------------------------------------------------
3706   wf_event.schema_name := wf_core.translate('WF_SCHEMA');
3707 
3708   wf_event.pv_last_agent_name   := ' ';
3709   wf_event.pv_last_queue_name   := ' ';
3710   wf_event.pv_last_schema_name  := ' ';
3711   wf_event.pv_last_recipients   := ' ';
3712   wf_event.pv_last_dequeue_enabled := ' ';
3713 
3714 end WF_EVENT;