1 package body WF_XML as
2 /* $Header: wfmxmlb.pls 120.31.12010000.10 2009/02/12 02:15:33 alepe ship $ */
3 --
4 -- Exceptions
5 --
6 dequeue_timeout exception;
7 pragma EXCEPTION_INIT(dequeue_timeout, -25228);
8
9 dequeue_disabled exception;
10 pragma EXCEPTION_INIT(dequeue_disabled, -25226);
11
12 dequeue_outofseq exception;
13 pragma EXCEPTION_INIT(dequeue_outofseq, -25237);
14
15 no_queue exception;
16 pragma EXCEPTION_INIT(no_queue, -24010);
17
18 -- g_fist_message
19 -- Flag to control the dequeuing of the SMTP queue
20 g_first_message boolean := TRUE;
21
22 TYPE parserStack_t IS TABLE OF
23 varchar2(2000) INDEX BY BINARY_INTEGER;
24
25 g_LOBTable wf_temp_lob.wf_temp_lob_table_type;
26
27 TYPE wf_resourceList_rec_t IS RECORD
28 (
29 contentId VARCHAR2(1000),
30 fileName VARCHAR2(1000),
31 contentType VARCHAR2(1000),
32 value VARCHAR2(4000)
33
34 );
35
36 TYPE resourceList_t IS TABLE OF
37 wf_resourceList_rec_t INDEX BY BINARY_INTEGER;
38
39 cursor g_urls(p_nid varchar2) is
40 select WMA.TYPE, WMA.DISPLAY_NAME, WNA.TEXT_VALUE, WNA.NAME
41 from WF_NOTIFICATION_ATTRIBUTES WNA, WF_NOTIFICATIONS WN,
42 WF_MESSAGE_ATTRIBUTES_VL WMA
43 where WNA.NOTIFICATION_ID = p_nid
44 and WN.NOTIFICATION_ID = WNA.NOTIFICATION_ID
45 and WN.MESSAGE_TYPE = WMA.MESSAGE_TYPE
46 and WN.MESSAGE_NAME = WMA.MESSAGE_NAME
47 and WMA.TYPE = 'URL'
48 and WMA.ATTACH = 'N'
49 and WMA.NAME = WNA.NAME;
50
51 -- Set these constants as session level varaibles to minumise the
52 -- calls to wf_core.
53 g_newLine varchar2(1) := wf_core.newLine;
54 g_install varchar2(100) := wf_core.Translate('WF_INSTALL');
55 g_htmlmessage varchar2(200);
56 g_urlNotification varchar2(200);
57 g_urlListAttachment varchar2(200);
58 -- These are only used in legacy procedures.
59 g_webAgent varchar2(200) := wf_core.translate('WF_WEB_AGENT');
60 g_wfSchema varchar2(200) := wf_core.translate('WF_SCHEMA');
61 g_fndapi_misschr varchar2(1) := FND_API.G_MISS_CHAR;
62
63 g_ntfDocText varchar2(30) := wf_notification.doc_text;
64 g_ntfDocHtml varchar2(30) := wf_notification.doc_html;
65
66 -- <<sstomar> : nls changes
67 g_base_language v$nls_parameters.value%TYPE ;
68 g_base_territory v$nls_parameters.value%TYPE ;
69 g_base_codeset v$nls_parameters.value%TYPE ;
70
71 -- << sstomar>> : Initialization can be done by using
72 -- variables from wf_core.nls_date_format,
73 -- wf_core.nls_date_language etc. but since
74 -- when calling WF_NOTIFICATION_UTIL.set/getNLSContext to retrieve
75 -- defaul NLS Language etc. we can define vars. here also.
76 g_base_nlsDateFormat v$nls_parameters.value%TYPE := wf_core.nls_date_format;
77 g_base_nlsDateLanguage v$nls_parameters.value%TYPE := wf_core.nls_date_language;
78 g_base_nlsCalendar v$nls_parameters.value%TYPE := wf_core.nls_calendar;
79 g_base_nlsSort v$nls_parameters.value%TYPE := wf_core.nls_sort ;
80 g_base_nlsNumericCharacters v$nls_parameters.value%TYPE := wf_core.nls_numeric_characters;
81
82
83 -- Return TRUE if the URL points to a image file.
84 -- The URL is pretested to ensure that it does NOT contain
85 -- any URL parameters.
86 function isImageReference(url in varchar2, renderType in varchar2)
87 return boolean
88 is
89 extPos pls_integer;
90 extStr varchar2(1000);
91 params pls_integer;
92
93 l_renderType varchar2(10);
94
95 begin
96 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
97 wf_log_pkg.string(WF_LOG_PKG.level_statement,
98 'wf.plsql.WF_XML.isImageReference',
99 'BEGIN {'||url||'} {'||renderType||'}');
100 end if;
101 l_renderType := renderType;
102
103 params := instr(url, '?');
104 if (params = 0) then
105 extPos := instrb(url, '.', -1, 1) + 1;
106 extStr := lower(substrb(url, extPos));
107
108 if (( l_renderType is null or l_renderType = 'IMG:') and
109 extStr in ('gif','jpg','png','tif','bmp','jpeg')) then
110 return true;
111 else
112 l_renderType := 'LNK:';
113 end if;
114
115 if l_renderType = 'LNK:' then
116 return false;
117 end if;
118 else
119 return false;
120 end if;
121 end isImageReference;
122
123 -- GetRecipients
124 -- IN
125 -- Role
126 -- OUT
127 -- List of recipients with their details contained in a PL/SQL Table.
128 -- NOTE
129 -- A role will only be resolved to one level. If a role contains has a
130 -- role associated to it, then that's as far as we go.
131 procedure GetRecipients(p_role in varchar2,
132 p_recipient_list in out NOCOPY WF_DIRECTORY.wf_local_roles_tbl_type)
133 is
134
135 l_display_name wf_roles.display_name%TYPE;
136 l_description wf_roles.description%TYPE;
137 l_email_address wf_roles.email_address%TYPE;
138 l_notification_preference wf_roles.notification_preference%TYPE;
139 l_language wf_roles.language%TYPE;
140 l_territory wf_roles.territory%TYPE;
141
142 cursor urc1(role varchar2, colon binary_integer) is
143 select name
144 from wf_users
145 where (name, orig_system, orig_system_id) in
146 (select user_name, user_orig_system, user_orig_system_id
147 from wf_user_roles
148 where role_name = urc1.role
149 and role_orig_system = substr(urc1.role, 1, urc1.colon-1)
150 and role_orig_system_id = substr(urc1.role, urc1.colon+1)
151 and user_name <> role_name
152 and user_orig_system <> role_orig_system
153 and user_orig_system_id <> role_orig_system_id)
154 and notification_preference not in ('SUMMARY','QUERY')
155 order by notification_preference, language;
156
157
158 cursor urc2(role varchar2) is
159 select name
160 from wf_users
161 where (name, orig_system, orig_system_id) in
162 (select user_name, user_orig_system, user_orig_system_id
163 from wf_user_roles
164 where role_name = urc2.role
165 and user_name <> role_name)
166 and notification_preference not in ('SUMMARY','QUERY')
167 order by notification_preference, language;
168
169 i binary_integer := 0;
170 colon binary_integer;
171
172
173 begin
174
175 -- Get role details.
176 wf_directory.GetRoleInfo(p_role, l_display_name, l_email_address,
177 l_notification_preference, l_language,
178 l_territory);
179
180 -- If the email address is NULL, then look for the members attached to
181 -- the role. Only attach those roles that 'want' a notification.
182 if l_email_address is not NULL
183 and l_notification_preference not in ('SUMMARY','QUERY') then
184 i := p_recipient_list.COUNT + 1;
185 p_recipient_list(i).name := p_role;
186 p_recipient_list(i).display_name := l_display_name;
187 p_recipient_list(i).description := l_description;
188 p_recipient_list(i).notification_preference :=
189 l_notification_preference;
190 p_recipient_list(i).language := l_language;
191 p_recipient_list(i).territory := l_territory;
192 p_recipient_list(i).email_address := l_email_address;
193 else
194 -- The the ROLE has a blank email address, then we
195 -- are interested only in resolving it one level.
196 -- If this is a user with a blank email address, then no one
197 -- will get a notification.
198 colon := instr(p_role, ':');
199 if colon > 0 then
200 for urrec in urc1(p_role, colon) loop
201 wf_directory.GetRoleInfo(urrec.name, l_display_name,
202 l_email_address,
203 l_notification_preference, l_language,
204 l_territory);
205 i := p_recipient_list.COUNT + 1;
206 p_recipient_list(i).name := p_role;
207 p_recipient_list(i).display_name := l_display_name;
208 p_recipient_list(i).description := l_description;
209 p_recipient_list(i).notification_preference :=
210 l_notification_preference;
211 p_recipient_list(i).language := l_language;
212 p_recipient_list(i).territory := l_territory;
213 p_recipient_list(i).email_address := l_email_address;
214 end loop;
215 else
216 for urrec in urc2(p_role) loop
217 wf_directory.GetRoleInfo(urrec.name, l_display_name,
218 l_email_address,
219 l_notification_preference, l_language,
220 l_territory);
221 i := p_recipient_list.COUNT + 1;
222 p_recipient_list(i).name := p_role;
223 p_recipient_list(i).display_name := l_display_name;
224 p_recipient_list(i).description := l_description;
225 p_recipient_list(i).notification_preference :=
226 l_notification_preference;
227 p_recipient_list(i).language := l_language;
228 p_recipient_list(i).territory := l_territory;
229 p_recipient_list(i).email_address := l_email_address;
230 end loop;
231 end if;
232 end if;
233 exception
234 when others then
235 wf_core.context('Wf_XML','GetRecipients',p_role);
236 raise;
237 end GetRecipients;
238
239 -- EncodeEntityReference
240 -- IN
241 -- Data to be encoded
242 -- RETURN
243 -- Encoded data.
244 -- NOTE
245 -- This is needed to encode the HTML data before placing it into
246 -- the XML structure. If it is placed in neat, then the XML parser
247 -- will not be able to cope.
248 function EncodeEntityReference(p_str in varchar2) return varchar2
249 is
250 l_str varchar2(32000);
251 begin
252 l_str := p_str;
253 l_str := replace(l_str,'&','&'||'amp;');
254 l_str := replace(l_str,'<','&'||'lt;');
255 l_str := replace(l_str,'>','&'||'gt;');
256 l_str := replace(l_str,'"','&'||'quot;');
257 l_str := replace(l_str,'''','&'||'apos;');
258 return l_str;
259 end EncodeEntityReference;
260
261
262 -- DecodeEntityReference (PRIVATE)
263 -- IN
264 -- Data to be decoded
265 -- RETURN
266 -- Decoded data.
267 -- NOTE
268 -- This is needed to decode the HTML data after extracting it from
269 -- the XML structure.
270 function DecodeEntityReference(some_text in varchar2)
271 return varchar2 is
272 l_amp varchar2(1) := '&';
273 buf varchar2(32000);
274 begin
275 buf := some_text;
276 buf := replace(buf, l_amp||'#38;', l_amp);
277 buf := replace(buf, l_amp||'lt;', '<');
278 buf := replace(buf, l_amp||'#60;', '<');
279 buf := replace(buf, l_amp||'gt;', '>');
280 buf := replace(buf, l_amp||'#92;', '\');
281 buf := replace(buf, l_amp||'#39;', '''');
282 buf := replace(buf, l_amp||'apos;', '''');
283 buf := replace(buf, l_amp||'quot;', '"');
284 buf := replace(buf, l_amp||'amp;', l_amp);
285 return buf;
286 exception
287 when others then
288 wf_core.context('Wf_Notification', 'DecodeEntityReference');
289 raise;
290 end DecodeEntityReference;
291
292 -- EnqueueLOBMessage
293 -- IN
294 -- Queue Name
295 -- Priority of the message
296 -- Correlation for the message - the NID of the notification
297 -- for this implementation.
298 -- Message - XML encoded.
299 procedure EnqueueLOBMessage(p_queue in varchar2,
300 p_priority number,
301 p_correlation in varchar2,
302 p_message in CLOB) is
303
304 l_enqueue_options dbms_aq.enqueue_options_t;
305 l_message_properties dbms_aq.message_properties_t;
306 l_correlation varchar2(255) := NULL;
307 l_msgid raw(16);
308
309 l_queueu VARCHAR2(200);
310 l_queueName VARCHAR2(30);
311 l_queueTable VARCHAR2(200);
312 l_schemaName VARCHAR2(320);
313 l_msgLength NUMBER;
314 l_sqlbuf VARCHAR2(2000);
315
316 l_amount binary_integer;
317 l_pos pls_integer;
318
319 l_dequeue_options dbms_aq.dequeue_options_t;
320 begin
321
322
323 /** wf_message_payload_t is obsolete in 2.6.4 onwards **/
324 null;
325
326 exception
327 when others then
328 wf_core.context('WF_XML','EnqueueLOBMessage',p_queue,
329 to_char(p_priority),
330 p_correlation);
331 raise;
332 end EnqueueLOBMessage;
333
334
335 -- EnqueueMessage
336 -- IN
337 -- Queue Name
338 -- Priority of the message
339 -- Correlation for the message - the NID of the notification
340 -- for this implementation.
341 -- Message - XML encoded.
342 procedure EnqueueMessage(p_queue in varchar2,
343 p_priority number,
344 p_correlation in varchar2,
345 p_message in VARCHAR2) is
346
347 l_enqueue_options dbms_aq.enqueue_options_t;
348 l_message_properties dbms_aq.message_properties_t;
349 l_correlation varchar2(255) := NULL;
350 l_msgid raw(16);
351
352 -- l_msgLob CLOB;
353 l_msgLobIdx pls_integer;
354 l_queueu VARCHAR2(200);
355 l_queueName VARCHAR2(30);
356 l_queueTable VARCHAR2(200);
357 l_schemaName VARCHAR2(320);
358 l_msgLength NUMBER;
359 l_sqlbuf VARCHAR2(2000);
360
361 l_amount binary_integer;
362 l_pos pls_integer;
363
364 l_dequeue_options dbms_aq.dequeue_options_t;
365 begin
366
367 /** wf_message_payload_t is obsolete in 2.6.4 onwards **/
368 null;
369
370 exception
371 when others then
372 -- just in case, check and free it any way.
373 wf_temp_lob.ReleaseLob(g_LOBTable, l_msgLobIdx);
374 wf_core.context('WF_XML','EnqueueMessage',p_queue, to_char(p_priority),
375 p_correlation);
376 raise;
377 end EnqueueMessage;
378
379
380 -- NewLOBTag - Create a new TAG node and insert it into the
381 -- Document Tree
382 -- IN
383 -- document as a CLOB
384 -- Position to take the new Tag Node
385 -- New Tag to be created
386 -- Data to be added between the start and end TAGs
387 -- Attribute list to be included in the opening TAG
388 -- OUT
389 -- The document containing the new TAG.
390 function NewLOBTag (p_doc in out NOCOPY CLOB,
391 p_pos in integer,
392 p_tag in varchar2,
393 p_data in varchar2,
394 p_attribute_list IN OUT NOCOPY wf_xml_attr_table_type)
395 return integer
396 is
397
398 -- l_temp CLOB;
399 l_tempStr varchar2(32000);
400 l_tempIdx pls_integer;
401 l_node varchar2(32000);
402 l_start varchar2(32000);
403 l_end varchar2(250);
404 l_pos integer;
405 l_nodesize number;
406
407 l_size number;
408 l_amount number;
409
410 begin
411
412 -- Create an instance of the node
413 -- A Node is deemed to be <TAG>Data</TAG>
414 -- dbms_lob.createTemporary(l_temp, TRUE, dbms_lob.CALL);
415 l_tempIdx := -1;
416
417 l_start := '<' || upper(p_tag);
418
419 -- If there are any attributes to add to the tag, then
420 -- add them now, otherwise, close off the TAG.
421 if p_attribute_list.COUNT = 0 then
422 l_start := l_start || '>';
423 else
424 for i in 1..p_attribute_list.COUNT loop
425 l_start := l_start || ' ' ||
426 p_attribute_list(i).attribute || '="' ||
427 p_attribute_list(i).value || '"';
428 end loop;
429 l_start := l_start || '>';
430 end if;
431
432 -- Create the end TAG.
433 l_end := '</' || upper(p_tag) || '>'||g_newLine;
434
435
436 l_size := dbms_lob.getlength(p_doc);
437
438 -- Create the full node to be inserted.
439 l_node := l_start || p_data || l_end;
440 l_nodesize := length(l_node);
441
442 l_amount := 0;
443 if l_size > 1 and l_size <> p_pos then
444 -- Copy the tail end of the LOB to a holder.
445 l_amount := l_size - p_pos;
446 if l_amount < 32000 then
447 dbms_lob.read(lob_loc => p_doc,
448 amount => l_amount,
449 offset => p_pos + 1,
450 buffer => l_tempStr);
451 else
452 l_tempIdx := wf_temp_lob.GetLob(g_LOBTable);
453 dbms_lob.copy(dest_lob => g_LOBTable(l_tempIdx).temp_lob,
454 src_lob => p_doc,
455 amount => l_amount,
456 dest_offset => 1,
457 src_offset => p_pos +1);
458 end if;
459 end if;
460
461 -- Now insert the new node into the p_pos location
462 dbms_lob.Write(p_doc, l_nodesize, p_pos + 1 , l_node);
463
464 -- Append the saved portion of the LOB
465 -- If l_tempIdx is still -1, then no LOB was used or initialised
466 -- but for the lob, makesure that there is something in it to be
467 -- used (l_amount > 0).
468 if l_tempIdx = -1 and l_amount > 0 then
469 dbms_lob.write(lob_loc => p_doc,
470 amount => l_amount,
471 offset => p_pos + l_nodesize + 1,
472 buffer => l_tempStr);
473 elsif l_amount > 0 then
474 dbms_lob.copy(dest_lob => p_doc,
475 src_lob => g_LOBTable(l_tempIdx).temp_lob,
476 amount => l_amount ,
477 dest_offset => p_pos + l_nodesize + 1);
478 wf_temp_lob.ReleaseLob(g_LOBTable, l_tempIdx);
479 end if;
480
481 l_pos := (p_pos + l_nodesize) - length(l_end);
482 -- Free up the use of the temporary LOB
483 -- dbms_lob.FreeTemporary(l_temp);
484
485 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
486 wf_log_pkg.string(WF_LOG_PKG.level_statement,
487 'wf.plsql.WF_XML.newLOBTag',
488 'TAG: '||l_start||' POS: '||to_char(l_pos));
489 end if;
490
491 return l_pos;
492
493 exception
494 when others then
495 wf_temp_lob.ReleaseLob(g_LOBTable, l_tempIdx);
496 wf_core.context('WF_XML','NewLOBTag', p_tag);
497 raise;
498 end NewLOBTag;
499
500 -- NewLOBTag - Create a new TAG node and insert it into the
501 -- Document Tree
502 -- IN
503 -- document as a CLOB
504 -- Position to take the new Tag Node
505 -- New Tag to be created
506 -- Data to be added between the start and end TAGs
507 -- Attribute list to be included in the opening TAG
508 -- OUT
509 -- The document containing the new TAG.
510 function NewLOBTag (p_doc in out NOCOPY CLOB,
511 p_pos in integer,
512 p_tag in varchar2,
513 p_data in CLOB,
514 p_attribute_list IN OUT NOCOPY wf_xml_attr_table_type)
515 return integer
516 is
517
518 l_tempIdx pls_integer;
519 l_nodeIdx pls_integer;
520 l_tempStr varchar2(32000);
521 l_start varchar2(250);
522 l_end varchar2(250);
523 l_pos integer;
524 l_nodesize number;
525
526 l_size number;
527 l_dataSize number;
528 l_amount number;
529
530 begin
531
532 -- Create an instance of the node
533 -- A Node is deemed to be <TAG>Data</TAG>
534 l_tempIdx := -1;
535 l_nodeIdx := wf_temp_lob.getLob(g_LOBTable);
536
537 l_start := '<' || upper(p_tag);
538
539 -- If there are any attributes to add to the tag, then
540 -- add them now, otherwise, close off the TAG.
541 if p_attribute_list.COUNT = 0 then
542 l_start := l_start || '>';
543 else
544 for i in 1..p_attribute_list.COUNT loop
545 l_start := l_start || ' ' ||
546 p_attribute_list(i).attribute || '="' ||
547 p_attribute_list(i).value || '"';
548 end loop;
549 l_start := l_start || '>';
550 end if;
551
552 -- Create the end TAG.
553 l_end := '</' || upper(p_tag) || '>'||g_newLine;
554
555 l_size := dbms_lob.getlength(p_doc);
556 l_dataSize := dbms_lob.getlength(p_data);
557
558 -- Create the full node to be inserted.
559 dbms_lob.writeAppend(g_LOBTable(l_nodeIdx).temp_lob, length(l_start),
560 l_start);
561 l_nodesize := length(l_start); -- dbms_lob.getLength(g_LOBTable(l_nodeIdx).temp_lob);
562 dbms_lob.copy(dest_lob => g_LOBTable(l_nodeIdx).temp_lob,
563 src_lob => p_data,
564 amount => l_dataSize,
565 dest_offset => l_nodesize+1,
566 src_offset => 1);
567 dbms_lob.writeAppend(g_LOBTable(l_nodeIdx).temp_lob, length(l_end),
568 l_end);
569 l_nodesize := dbms_lob.getLength(g_LOBTable(l_nodeIdx).temp_lob);
570
571 l_amount := 0;
572 if l_size > 1 and l_size <> p_pos then
573 l_amount := l_size - p_pos;
574 -- Copy the tail end of the LOB to a holder.
575 if l_amount < 32000 then
576 dbms_lob.read(lob_loc => p_doc,
577 amount => l_amount,
578 offset => p_pos + 1,
579 buffer => l_tempStr);
580 else
581 l_tempIdx := wf_temp_lob.GetLob(g_LOBTable);
582 dbms_lob.copy(dest_lob => g_LOBTable(l_tempIdx).temp_lob,
583 src_lob => p_doc,
584 amount => l_amount,
585 dest_offset => 1,
586 src_offset => p_pos +1);
587 end if;
588 end if;
589
590 -- Now insert the new node into the p_pos location
591 dbms_lob.copy(dest_lob => p_doc,
592 src_lob => g_LOBTable(l_nodeIdx).temp_lob,
593 amount => l_nodesize,
594 dest_offset => p_pos + 1);
595
596 -- Append the saved portion of the LOB
597 if l_tempIdx = -1 and l_amount > 0 then
598 dbms_lob.write(lob_loc => p_doc,
599 amount => l_amount,
600 offset => p_pos + l_nodesize + 1,
601 buffer => l_tempStr);
602 elsif l_tempIdx > 0 then
603 if l_amount > 0 then
604 dbms_lob.copy(dest_lob => p_doc,
605 src_lob => g_LOBTable(l_tempIdx).temp_lob,
606 amount => l_amount,
607 dest_offset => p_pos + l_nodesize + 1);
608 end if;
609 -- Free up the use of the temporary LOBs
610 wf_temp_lob.releaseLOB(g_LOBTable, l_tempIdx);
611 end if;
612
613
614 l_pos := (p_pos + l_nodesize) - length(l_end);
615
616 -- Free up the use of the temporary LOBs
617 wf_temp_lob.releaseLOB(g_LOBTable, l_nodeIdx);
618
619 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
620 wf_log_pkg.string(WF_LOG_PKG.level_statement,
621 'wf.plsql.WF_XML.newLOBTag',
622 'TAG: '||l_start||' POS: '||to_char(l_pos));
623 end if;
624
625 return l_pos;
626
627 exception
628 when others then
629 wf_temp_lob.releaseLOB(g_LOBTable, l_tempIdx);
630 wf_temp_lob.releaseLOB(g_LOBTable, l_nodeIdx);
631 wf_core.context('WF_XML','NewLOBTag', p_tag);
632 raise;
633 end NewLOBTag;
634
635 -- NewTag - Create a new TAG node and insert it into the
636 -- Document Tree
637 -- IN
638 -- document as a CLOB
639 -- Position to take the new Tag Node
640 -- New Tag to be created
641 -- Data to be added between the start and end TAGs
642 -- Attribute list to be included in the opening TAG
643 -- OUT
644 -- The document containing the new TAG.
645 function NewTag (p_doc in out NOCOPY VARCHAR2,
646 p_pos in integer ,
647 p_tag in varchar2,
648 p_data in varchar2,
649 p_attribute_list IN OUT NOCOPY wf_xml_attr_table_type)
650 return integer
651 is
652
653 l_temp VARCHAR2(32000);
654 l_node varchar2(32000);
655 l_start varchar2(250);
656 l_end varchar2(250);
657 l_pos integer;
658 l_nodesize number;
659
660 l_size number;
661 l_amount number;
662
663 begin
664
665 -- Create an instance of the node
666 -- A Node is deemed to be <TAG>Data</TAG>
667
668 l_start := '<' || upper(p_tag);
669
670 -- If there are any attributes to add to the tag, then
671 -- add them now, otherwise, close off the TAG.
672 if p_attribute_list.COUNT = 0 then
673 l_start := l_start || '>';
674 else
675 for i in 1..p_attribute_list.COUNT loop
676 l_start := l_start || ' ' ||
677 p_attribute_list(i).attribute || '="' ||
678 p_attribute_list(i).value || '"';
679 end loop;
680 l_start := l_start || '>';
681 end if;
682
683 -- Create the end TAG.
684 l_end := '</' || upper(p_tag) || '>'||g_newLine;
685
686
687 l_size := length(p_doc);
688
689 -- Create the full node to be inserted.
690 l_node := l_start || p_data || l_end;
691 l_nodesize := length(l_node);
692
693 l_amount := 0;
694 if l_size > 1 and l_size <> p_pos then
695 -- Copy the tail end of the LOB to a holder.
696 l_amount := l_size - p_pos;
697 l_temp := substr(p_doc, p_pos +1, l_amount);
698 end if;
699
700 -- Now insert the new node into the p_pos location
701 p_doc := substr(p_doc, 1, p_pos)||l_node;
702
703 if Length(l_temp) > 1 then
704 -- Append the saved portion of the LOB
705 p_doc := p_doc||l_temp;
706 end if;
707
708 l_pos := (p_pos + l_nodesize) - length(l_end);
709
710 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
711 wf_log_pkg.string(WF_LOG_PKG.level_statement,
712 'wf.plsql.WF_XML.newTag',
713 'TAG: '||l_start||' POS: '||to_char(l_pos));
714 end if;
715 return l_pos;
716
717 exception
718 when others then
719 wf_core.context('WF_XML','NewTag', p_tag);
720 raise;
721 end NewTag;
722
723
724
725 -- SkipLOBTag - To move return a pointer past the nominated TAG
726 -- starting from a given position in the document.
727 -- IN
728 -- document
729 -- Position to take the new Tag Node
730 -- New Tag to be created
731 -- Data to be added
732 -- RETURN
733 -- New position past the </TAG>.
734 function SkipLOBTag (p_doc in out NOCOPY CLOB,
735 p_tag in varchar2,
736 p_offset in out NOCOPY integer,
737 p_occurance in out NOCOPY integer) return integer is
738
739 l_pos integer;
740 l_tag varchar2(250);
741
742 begin
743
744 l_tag := '</'||upper(p_tag)||'>';
745 l_pos := dbms_lob.instr(p_doc, l_tag, p_offset, p_occurance);
746
747 return l_pos + length(l_tag);
748
749 exception
750 when others then
751 wf_core.context('WF_XML','SkipLOBTag', p_tag, to_char(p_offset),
752 to_char(p_occurance));
753 raise;
754 end SkipLOBTag;
755
756 -- SkipTag - To move return a pointer past the nominated TAG
757 -- starting from a given position in the document.
758 -- IN
759 -- document
760 -- Position to take the new Tag Node
761 -- New Tag to be created
762 -- Data to be added
763 -- RETURN
764 -- New position past the </TAG>.
765 function SkipTag (p_doc in out NOCOPY VARCHAR2,
766 p_tag in varchar2,
767 p_offset in out NOCOPY integer,
768 p_occurance in out NOCOPY integer) return integer is
769
770 l_pos integer;
771 l_tag varchar2(250);
772
773 begin
774
775 l_tag := '</'||upper(p_tag)||'>';
776 l_pos := instr(p_doc, l_tag, p_offset, p_occurance);
777
778 return l_pos + length(l_tag);
779
780 exception
781 when others then
782 wf_core.context('WF_XML','SkipTag', p_tag, to_char(p_offset),
783 to_char(p_occurance));
784 raise;
785 end SkipTag;
786
787
788 -- GetTagValue - Obtain the value for a given TAG from within the
789 -- Document Tree
790 -- IN
791 -- document as a CLOB
792 -- TAG to find the value of
793 -- The position to start looking for the TAG from
794 -- OUT
795 -- Value of the TAG. ie the value between the start and end TAGs
796 -- The position in the CLOB after the find
797 -- The list of attributes associated with the TAG (Not implemented as yet)
798 procedure GetTagValue(p_doc in out NOCOPY CLOB,
799 p_tag in varchar2,
800 p_value out NOCOPY varchar2,
801 p_pos in out NOCOPY integer,
802 p_attrlist in out NOCOPY wf_xml_attr_table_type)
803 as
804
805 l_value varchar2(32000);
806 l_length integer;
807 l_startTag varchar2(255);
808 l_endTag varchar2(255);
809 l_startPos integer;
810 l_endPos integer;
811 l_pos integer;
812 l_occurance integer := 1;
813
814 begin
815
816 -- The idea is to look for the value of a tag from
817 -- a given point (p_pos)
818 l_pos := p_pos;
819 -- Set the opening TAG. Don't use the '>' as there may be
820 -- attributes set on the TAG.
821 l_startTag := '<'||upper(p_tag);
822 l_endTag := '</'||upper(p_tag)||'>';
823
824 l_startPos := dbms_lob.instr(p_doc, l_startTag, l_pos, l_occurance);
825 l_startPos := dbms_lob.instr(p_doc, '>', l_startPos, l_occurance) + 1;
826
827
828 l_endPos := dbms_lob.instr(p_doc, l_endTag, l_startpos, l_occurance) - 1;
829 l_length := l_endPos - l_startPos + 1;
830
831 dbms_lob.read(p_doc, l_length, l_startPos, l_value);
832
833 -- Reposition the position pointer to after the end
834 -- of the current TAG set.
835 p_pos := l_endPos + length(l_endTag) + 1;
836 p_value := l_value;
837 exception
838 when others then
839 wf_core.context('WF_XML','GetTagValue',p_tag, to_char(p_pos));
840 raise;
841 end GetTagValue;
842
843
844 -- AddElementAttribute - Add an Element Attribute Value pair to the attribute
845 -- list.
846 -- IN
847 -- Name of the attribute
848 -- Value for the attribute
849 -- The attribute list to add the name/value pair to.
850 procedure AddElementAttribute(p_attribute_name IN VARCHAR2,
851 p_attribute_value IN VARCHAR2,
852 p_attribute_list IN OUT NOCOPY wf_xml_attr_table_type)
853 is
854 l_index integer;
855 begin
856 l_index := p_attribute_list.COUNT + 1;
857 p_attribute_list(l_index).attribute := p_attribute_name;
858 p_attribute_list(l_index).value := p_attribute_value;
859 exception
860 when others then
861 wf_core.context('WF_XML','AddElementAttribute',p_attribute_name,
862 p_attribute_value);
863 raise;
864 end;
865
866
867 -- STRPARSER - Parse a string and seperate the elements
868 -- into a memeory table based on the content of the
869 -- seperators.
870 -- IN
871 -- str - The Varchar2 that is to be parsed
872 -- sep - The list of SINGLE character seprators that will
873 -- segment the str.
874 -- RETURN parserStack_t a memory table of Varchar2
875 --
876 function strParser(str in varchar2, sep in varchar2) return parserStack_t
877 is
878 quot pls_integer;
879 i pls_integer;
880 c varchar2(1);
881 attr varchar2(2000);
882 defv varchar2(2000);
883
884 stack parserStack_t;
885 buf varchar2(2000);
886
887 begin
888 if str is not null or str <> '' then
889 quot := 1;
890 i := 1;
891 buf := '';
892 while i <= length(str) loop
893 c := substrb(str, i, 1);
894 if instrb(sep, c,1 ,1)>0 then
895 if buf is not null or buf <> '' then
896 -- Push the buffer to the stack and start again
897 stack(quot) := trim(buf);
898 quot := quot + 1;
899 buf := '';
900 end if;
901 elsif c = '\' then
902 -- Escape character. Consume this and the next
903 -- character.
904 i := i + 1;
905 c := substrb(str, i, 1);
906 buf := buf ||c;
907 else
908 buf := buf || c;
909 end if;
910 i := i + 1;
911 end loop;
912 if buf is not null or buf <> '' then
913 stack(quot) := trim(buf);
914 end if;
915 end if;
916 return stack;
917 end strParser;
918
919 -- parseContentType
920 -- IN
921 -- pContentType The Content-Type string to be parsed
922 -- OUT
923 -- pMimeType The MIME type part of the Content-Type
924 -- pFileName The file name part of the Content-Type
925 -- pExtn The extention of the file name
926 -- pEncoding The content-encoding part of the Content-Type
927 --
928 -- NOTE: For bug 3735752, a copy of parseContentType was taken and
929 -- placed into WF_MAIL_UTIL in order to prevent a dependancy
930 -- on WF_XML for WFA_HTML. This copy remains in tact.
931 procedure parseContentType(pContentType in varchar2,
932 pMimeType out nocopy varchar2,
933 pFileName out nocopy varchar2,
934 pExtn out nocopy varchar2,
935 pEncoding out nocopy varchar2)
936 is
937 i pls_integer;
938 l_content_type varchar2(255);
939 l_paramlist parserStack_t;
940 l_sublist parserStack_t;
941
942 begin
943 -- Derrive the name for the attachment.
944 l_content_type := pContentType;
945 pExtn := '';
946 pFilename := '';
947 pMimeType := '';
948 pEncoding := '';
949 l_paramlist := strParser(l_content_type, ';');
950 pMimeType := l_paramlist(1);
951 for i in 1..l_paramlist.COUNT loop
952 l_sublist := strParser(l_paramlist(i),'/');
953 if l_sublist.COUNT = 2 then
954 pExtn := l_sublist(2);
955 end if;
956 l_sublist.DELETE;
957 l_sublist := strParser(l_paramList(i),'="');
958 for i in 1..l_sublist.COUNT loop
959 if lower(l_sublist(i)) = 'name' then
960 pFilename := l_sublist(i+1);
961 end if;
962 if lower(l_sublist(i)) = 'encoding' then
963 pEncoding := l_sublist(i+1);
964 end if;
965 end loop;
966 l_sublist.DELETE;
967 end loop;
968 if lower(pExtn) = 'tab-separated-values' then
969 pExtn := 'tsv';
970 elsif
971 lower(pExtn) = 'comma-separated-values' then
972 pExtn := 'csv';
973 elsif
974 lower(pExtn) = 'plain' then
975 pExtn := 'txt';
976 elsif
977 lower(pExtn) like '%excel' then
978 pExtn := 'xls';
979 elsif
980 lower(pExtn) = 'html' then
981 pExtn := 'htm';
982 elsif
983 lower(pExtn) like '%msword' then
984 pExtn := 'doc';
985 end if;
986
987 end parseContentType;
988
989 -- GetAttachment - Create an attachment tag for each of the URLs and
990 -- DOCUMENT attributes.
991 -- IN
992 -- Notification ID
993 -- Document handle
994 -- MIME Agent for the attachment
995 -- Position in the document where to place the attachment.
996 -- OUT
997 -- New location of the position
998 function GetAttachment(p_nid in number,
999 p_doc in out NOCOPY CLOB,
1000 p_agent in varchar2,
1001 p_disposition in varchar2,
1002 p_doc_type in varchar2,
1003 p_pos in out NOCOPY integer) return integer
1004 is
1005
1006 l_pos integer;
1007 l_occurance integer := 1;
1008 l_tmpcontent varchar2(32000);
1009 -- l_content CLOB;
1010 l_contentIdx pls_integer;
1011 l_blob BLOB;
1012 l_atthname varchar2(255);
1013 l_display_type varchar2(255) := p_doc_type;
1014 l_content_type varchar2(255);
1015 l_attrlist wf_xml_attr_table_type;
1016 l_cbuf varchar2(32000);
1017 l_doc_end integer;
1018 l_doc_length number;
1019 l_start VARCHAR2(10) := '<![CDATA[';
1020 l_end VARCHAR2(4) := ']]>';
1021 l_isURLAttrs boolean;
1022 l_aname varchar2(30);
1023
1024
1025 l_error_result varchar2 (2000);
1026 l_err_name varchar2(30);
1027 l_err_message varchar2(2000);
1028 l_err_stack varchar2(4000);
1029
1030 cursor c_attr(p_nid varchar2) is
1031 select WMA.TYPE, WMA.DISPLAY_NAME,
1032 decode(WMA.TYPE, 'URL', WF_NOTIFICATION.GetUrlText(WNA.TEXT_VALUE,
1033 p_nid), WNA.TEXT_VALUE) URL, WNA.NAME
1034 from WF_NOTIFICATION_ATTRIBUTES WNA, WF_NOTIFICATIONS WN,
1035 WF_MESSAGE_ATTRIBUTES_VL WMA
1036 where WNA.NOTIFICATION_ID = p_nid
1037 and WN.NOTIFICATION_ID = WNA.NOTIFICATION_ID
1038 and WN.MESSAGE_TYPE = WMA.MESSAGE_TYPE
1039 and WN.MESSAGE_NAME = WMA.MESSAGE_NAME
1040 and (WMA.TYPE = 'URL' or WMA.TYPE = 'DOCUMENT')
1041 and WMA.ATTACH = 'Y'
1042 and WMA.NAME = WNA.NAME;
1043
1044 l_extn varchar2(20);
1045 l_mimeType varchar2(255);
1046 l_encoding varchar2(255);
1047 l_filename varchar2(320);
1048 l_attr_url varchar2(32000);
1049
1050 begin
1051
1052 -- dbms_lob.createTemporary(l_content, TRUE, dbms_lob.CALL);
1053
1054 -- Allocate LOB from WF_TEMP LOB pool.
1055 l_contentIdx := wf_temp_lob.getLOB(g_LOBTable);
1056 dbms_lob.createTemporary(l_blob, TRUE, dbms_lob.CALL);
1057
1058 l_pos := p_pos;
1059 for l_crec in c_attr(p_nid) loop
1060 dbms_lob.trim(g_LOBTable(l_contentIdx).temp_lob, 0);
1061 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
1062
1063 wf_log_pkg.string(WF_LOG_PKG.level_statement,
1064 'wf.plsql.WF_XML.GetAttachment',
1065 'Document URL {'||l_crec.url||'}');
1066 end if;
1067
1068 if l_crec.type = 'URL' then
1069 l_isURLAttrs := true;
1070 else
1071 /*
1072 ** The mechanism to obtain PLSQL and PLSQLCLOB documents
1073 ** as attachments.
1074 */
1075 if upper(substr(l_crec.url,1, 6)) = 'PLSQL:' then
1076
1077 -- wf_mail.getDocContent(p_nid, l_crec.name, l_display_type,
1078 -- l_tmpcontent, l_error_result);
1079 -- bug 2879507. call wf_notification.GetAttrDoc2 to get the
1080 -- doc content as well as the document type
1081 wf_notification.GetAttrDoc2(p_nid, l_crec.name, l_display_type,
1082 l_tmpcontent, l_content_type);
1083 l_tmpContent := replace(l_tmpContent, g_fndapi_misschr);
1084 -- default to display type if no document type specified
1085 if (l_content_type is null) then
1086 l_content_type := l_display_type;
1087 end if;
1088 -- Derrive the name for the attachment.
1089 parseContentType(l_content_type, l_mimeType, l_filename,
1090 l_extn, l_encoding);
1091 if l_filename is null or l_filename = '' then
1092 l_filename := l_crec.display_name ||'.'||l_extn;
1093 end if;
1094
1095 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1096 l_pos := NewLOBTag(p_doc, l_pos, 'BODYPART', '', l_attrlist);
1097 l_attrlist.DELETE;
1098 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1099 AddElementAttribute('content-disposition',p_disposition,
1100 l_attrlist);
1101 AddElementAttribute('filename', l_filename, l_attrlist);
1102 AddElementAttribute('encoding', l_encoding, l_attrlist);
1103 dbms_lob.trim(g_LOBTable(l_contentIdx).temp_lob,0);
1104 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1105 length(l_start), l_start);
1106 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1107 length(l_tmpContent),
1108 l_tmpContent);
1109 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1110 length(l_end), l_end);
1111
1112 l_pos := NewLOBTag(p_doc, l_pos, 'MESSAGE',
1113 g_LOBTable(l_contentIdx).temp_lob,
1114 l_attrlist);
1115 l_pos := SkipLOBTag(p_doc, 'MESSAGE', l_pos, l_occurance);
1116 l_pos := SkipLOBTag(p_doc, 'BODYPART', l_pos, l_occurance);
1117 elsif upper(substr(l_crec.url,1, 10)) = 'PLSQLCLOB:' then
1118 /*
1119 ** For PLSQLCLOB documents.
1120 */
1121 dbms_lob.trim(g_LOBTable(l_contentIdx).temp_lob,0);
1122 l_content_type := '';
1123
1124 --
1125 -- Getting Content
1126 -- First we call the existing APIs to render the
1127 -- content and then we fetch the content into
1128 -- the new structure.
1129 -- Note: LOB allocated within wf_mail.getLOBDocContent API
1130 -- is released here after processing by calling
1131 -- WF_MAIL.CloseLob(l_display_type) api.
1132 wf_mail.getLOBDocContent(p_nid, l_crec.name, l_display_type,
1133 l_content_type, l_error_result);
1134
1135 if l_error_result is not null or l_error_result <> '' then
1136 -- Error in getting content
1137 wf_core.context('WF_XML', 'GetAttachment', to_char(p_nid),
1138 l_display_type);
1139 wf_core.raise('WFMLR_DOCUMENT_ERROR');
1140 end if;
1141
1142 -- default to display type is no document type is specified
1143 if (l_content_type is null) then
1144 l_content_type := l_display_type;
1145 end if;
1146 -- Derrive the name for the attachment.
1147 parseContentType(l_content_type, l_mimeType, l_filename,
1148 l_extn, l_encoding);
1149 if l_filename is null or l_filename = '' then
1150 l_filename := l_crec.display_name ||'.'||l_extn;
1151 end if;
1152
1153 if lower(l_mimeType) not like 'text/%' and
1154 (l_encoding is null or lower(l_encoding) <> 'base64') then
1155 -- Assume that there has been no encoding on a RAW
1156 -- type lob. Do not include it here. Defer attaching
1157 -- the content.
1158 --
1159 -- Build the attribute list for the attachment
1160 -- including the content-type, file name etc.
1161 --
1162
1163 -- First the BODYPART structure to take the MESSAGE
1164 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1165 l_pos := NewLOBTag(p_doc, l_pos, 'BODYPART', '', l_attrlist);
1166 l_attrlist.DELETE;
1167 l_attr_url := Wf_Notification.GetText(l_crec.URL, p_nid, l_display_type);
1168 AddElementAttribute('src', l_attr_url, l_attrlist);
1169 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1170 AddElementAttribute('content-disposition',p_disposition,
1171 l_attrlist);
1172 AddElementAttribute('filename', l_filename, l_attrlist);
1173
1174 l_pos := NewLOBTag(p_doc, l_pos, 'MESSAGE', '',
1175 l_attrlist);
1176 l_pos := SkipLOBTag(p_doc, 'MESSAGE', l_pos, l_occurance);
1177 l_pos := SkipLOBTag(p_doc, 'BODYPART', l_pos, l_occurance);
1178
1179 else
1180
1181 -- Fetch the content
1182 WF_MAIL.InitFetchLOB(l_display_type, l_doc_length);
1183 l_doc_end := 0;
1184 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1185 length(l_start), l_start);
1186 while l_doc_end = 0 loop
1187 WF_MAIL.FetchLobContent(l_tmpContent, l_display_type,
1188 l_doc_end);
1189 l_tmpContent := replace(l_tmpContent, g_fndapi_misschr);
1190 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1191 length(l_tmpContent), l_tmpContent);
1192 end loop;
1193
1194
1195 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1196 length(l_end), l_end);
1197 --
1198 -- Build the attribute list for the attachment
1199 -- including the content-type, file name etc.
1200 --
1201
1202 -- First the BODYPART structure to take the MESSAGE
1203 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1204 l_pos := NewLOBTag(p_doc, l_pos, 'BODYPART', '', l_attrlist);
1205 l_attrlist.DELETE;
1206
1207 AddElementAttribute('content-type', l_mimeType, l_attrlist);
1208 AddElementAttribute('content-disposition',p_disposition,
1209 l_attrlist);
1210 AddElementAttribute('filename', l_filename, l_attrlist);
1211 AddElementAttribute('encoding', l_encoding, l_attrlist);
1212
1213 l_pos := NewLOBTag(p_doc, l_pos, 'MESSAGE',
1214 g_LOBTable(l_contentIdx).temp_lob,
1215 l_attrlist);
1216 l_pos := SkipLOBTag(p_doc, 'MESSAGE', l_pos, l_occurance);
1217 l_pos := SkipLOBTag(p_doc, 'BODYPART', l_pos, l_occurance);
1218 end if;
1219
1220 -- Release temp LOB allocated within wf_mail.getLOBDocContent
1221 -- i.e. wf_mail.g_html_messageIdx or wf_mail.g_text_messageIdx Locators
1222 WF_MAIL.CloseLob(l_display_type);
1223
1224 elsif upper(substr(l_crec.url,1, 10)) = 'PLSQLBLOB:' then
1225 /*
1226 ** For PLSQLBLOB documents.
1227 */
1228 dbms_lob.trim(l_blob,0);
1229
1230 --
1231 -- Getting Content
1232 -- First we call the existing APIs to render the
1233 -- content and then we fetch the content into
1234 -- the new structure.
1235 --
1236 begin
1237 Wf_Notification.GetAttrBLOB(p_nid, l_crec.name,
1238 l_display_type,
1239 l_blob, l_content_type,
1240 l_aname);
1241 exception
1242 when others then
1243 if (wf_log_pkg.level_error >=
1244 fnd_log.g_current_runtime_level) then
1245 wf_log_pkg.string(WF_LOG_PKG.level_error,
1246 'wf.plsql.WF_XML.GetAttachment',
1247 'Error when getting BLOB attachment -> '||sqlerrm);
1248 end if;
1249 wf_core.context('WF_XML', 'GetAttachment', to_char(p_nid),
1250 l_display_type);
1251 wf_core.raise('WFMLR_DOCUMENT_ERROR');
1252 end;
1253
1254 -- default to display type is no document type is specified
1255 if (l_content_type is null) then
1256 l_content_type := l_display_type;
1257 end if;
1258 -- Derrive the name for the attachment.
1259 parseContentType(l_content_type, l_mimeType, l_filename,
1260 l_extn, l_encoding);
1261 if l_filename is null or l_filename = '' then
1262 l_filename := l_crec.display_name ||'.'||l_extn;
1263 end if;
1264
1265 -- First the BODYPART structure to take the MESSAGE
1266 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1267 l_pos := NewLOBTag(p_doc, l_pos, 'BODYPART', '', l_attrlist);
1268 l_attrlist.DELETE;
1269 l_attr_url := Wf_Notification.GetText(l_crec.URL, p_nid, l_display_type);
1270 AddElementAttribute('src', l_attr_url, l_attrlist);
1271 AddElementAttribute('content-type',l_mimeType, l_attrlist);
1272 AddElementAttribute('content-disposition',p_disposition,
1273 l_attrlist);
1274 AddElementAttribute('filename', l_filename, l_attrlist);
1275
1276 l_pos := NewLOBTag(p_doc, l_pos, 'MESSAGE', '',
1277 l_attrlist);
1278 l_pos := SkipLOBTag(p_doc, 'MESSAGE', l_pos, l_occurance);
1279 l_pos := SkipLOBTag(p_doc, 'BODYPART', l_pos, l_occurance);
1280
1281 end if;
1282 end if;
1283 l_attrlist.DELETE;
1284 end loop;
1285
1286 -- BUG 3285943 - If this is for a framework notification
1287 -- then we don't need the attached URLs.
1288 -- Bug 5456241 : Pick html / text msg body based on content-type.
1289 if (WF_NOTIFICATION.isFwkRegion(p_nid, l_display_type)='Y' and g_install='EMBEDDED') then
1290 l_isURLAttrs := FALSE;
1291 end if;
1292
1293 if l_isURLAttrs then
1294 dbms_lob.trim(g_LOBTable(l_contentIdx).temp_lob,0);
1295
1296 wf_mail.GetURLAttachment(p_nid, l_tmpContent, l_error_result);
1297 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1298 length(l_start), l_start);
1299 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1300 length(l_tmpContent), l_tmpContent);
1301 dbms_lob.writeAppend(g_LOBTable(l_contentIdx).temp_lob,
1302 length(l_end), l_end);
1303
1304
1305 if l_error_result is not null or l_error_result <> '' then
1306 wf_core.context('WF_XML', 'GetAttachments', to_char(p_nid),
1307 p_agent, to_char(p_pos));
1308 wf_core.token('SQLERR', l_error_result);
1309 wf_core.raise('WF_URLLIST_ERROR');
1310 end if;
1311
1312 l_fileName := g_urlListAttachment||'.html';
1313
1314 -- First the BODYPART structure to take the MESSAGE
1315 AddElementAttribute('content-type',l_display_type, l_attrlist);
1316 l_pos := NewLOBTag(p_doc, l_pos, 'BODYPART', '', l_attrlist);
1317 l_attrlist.DELETE;
1318
1319 AddElementAttribute('content-type',g_ntfDocHtml,
1320 l_attrlist);
1321 AddElementAttribute('content-disposition',p_disposition,
1322 l_attrlist);
1323 AddElementAttribute('filename', l_filename, l_attrlist);
1324
1325 l_pos := NewLOBTag(p_doc, l_pos, 'MESSAGE',
1326 g_LOBTable(l_contentIdx).temp_lob, l_attrlist);
1327 l_pos := SkipLOBTag(p_doc, 'MESSAGE', l_pos, l_occurance);
1328 l_pos := SkipLOBTag(p_doc, 'BODYPART', l_pos, l_occurance);
1329
1330 end if;
1331
1332 -- relase TEMP allocated LOB
1333 wf_temp_lob.releaseLob(g_LOBTable, l_contentIdx);
1334
1335 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
1336 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
1337 'wf.plsql.WF_XML.GetAttachment',
1338 'END');
1339 end if;
1340
1341 return l_pos;
1342 exception
1343 when others then
1344 WF_MAIL.CloseLob(l_display_type);
1345 wf_temp_lob.releaseLob(g_LOBTable, l_contentIdx);
1346 wf_core.context('WF_XML', 'GetAttachments', to_char(p_nid), p_agent,
1347 to_char(p_pos));
1348 l_err_message := sqlerrm;
1349 raise;
1350 end GetAttachment;
1351
1352
1353 -- GetAttributes - Create an attribute tag for each of the response
1354 -- required attributes.
1355 -- IN
1356 -- Notification ID
1357 -- Document handle
1358 -- MIME Agent for the attribute
1359 -- Location in the document to insert the new TAG(s)
1360 -- RETURN
1361 -- The new position in the docuemnt.
1362 function GetAttributes(p_nid in number,
1363 p_doc in out NOCOPY CLOB,
1364 p_agent in varchar2,
1365 p_pos in out NOCOPY integer) return integer
1366 is
1367
1368 l_pos integer;
1369 l_attrlist wf_xml_attr_table_type;
1370 l_occurance integer := 1;
1371 l_error_result varchar2 (2000);
1372 l_err_name varchar2(30);
1373 l_err_message varchar2(2000);
1374 l_err_stack varchar2(4000);
1375 l_value varchar2(2000);
1376
1377 cursor c1 is
1378 select WMA.NAME, WMA.DISPLAY_NAME, WMA.DESCRIPTION, WMA.TYPE, WMA.FORMAT,
1379 decode(WMA.TYPE,
1380 'VARCHAR2', decode(WMA.FORMAT,
1381 '', WNA.TEXT_VALUE,
1382 substr(WNA.TEXT_VALUE, 1, to_number(WMA.FORMAT))),
1383 'NUMBER', decode(WMA.FORMAT,
1384 '', to_char(WNA.NUMBER_VALUE),
1385 to_char(WNA.NUMBER_VALUE, WMA.FORMAT)),
1386 'DATE', decode(WMA.FORMAT,
1387 '', to_char(WNA.DATE_VALUE),
1388 to_char(WNA.DATE_VALUE, WMA.FORMAT)),
1389 'LOOKUP', WNA.TEXT_VALUE,
1390 WNA.TEXT_VALUE) VALUE
1391 from WF_NOTIFICATION_ATTRIBUTES WNA,
1392 WF_NOTIFICATIONS WN,
1393 WF_MESSAGE_ATTRIBUTES_VL WMA
1394 where WNA.NOTIFICATION_ID = p_nid
1395 and WN.NOTIFICATION_ID = WNA.NOTIFICATION_ID
1396 and WN.MESSAGE_TYPE = WMA.MESSAGE_TYPE
1397 and WN.MESSAGE_NAME = WMA.MESSAGE_NAME
1398 and WMA.NAME = WNA.NAME
1399 and WMA.SUBTYPE = 'RESPOND'
1400 and WMA.TYPE not in ('FORM', 'URL')
1401 order by WMA.SEQUENCE;
1402
1403 begin
1404
1405 l_pos := p_pos;
1406 for rec in c1 loop
1407 l_attrlist.DELETE;
1408 AddElementAttribute('name',rec.name, l_attrlist);
1409 AddElementAttribute('type',rec.type, l_attrlist);
1410 if rec.format is not NULL then
1411 AddElementAttribute('format',rec.format, l_attrlist);
1412 end if;
1413 l_pos := NewLOBTag(p_doc, l_pos, 'ATTRIBUTE','',l_attrlist);
1414 l_attrlist.DELETE;
1415 l_pos := NewLOBTag(p_doc, l_pos, 'NAME', rec.display_name, l_attrlist);
1416 l_pos := SkipLOBTag(p_doc, 'NAME', l_pos, l_occurance);
1417 l_value := EncodeEntityReference(rec.value);
1418 l_pos := NewLOBTag(p_doc, l_pos, 'VALUE', rec.value, l_attrlist);
1419
1420 l_pos := SkipLOBTag(p_doc, 'ATTRIBUTE', l_pos, l_occurance);
1421
1422 end loop;
1423 return l_pos;
1424 exception
1425 when others then
1426 wf_core.context('WF_XML', 'GetAttributes', to_char(p_nid));
1427 raise;
1428 end GetAttributes;
1429
1430 -- GetXMLMessage - Return a CLOB Document containing an XML encoded version of the
1431 -- notification. No recipients list will be populated. That
1432 -- will be the responsibility of the calling procedure.
1433 --
1434 -- IN
1435 -- notification id
1436 -- Protocol for the message
1437 -- List of recipients to recieve the notification
1438 -- mailer node name
1439 -- Web Agent for the HTML attachments
1440 -- Reply to address for the final notification
1441 -- Language for the notification
1442 -- Territory for the notification
1443 -- OUT
1444 -- Piority for the message
1445 -- A CLOB Containing the XML encoded message.
1446 procedure GetXMLMessage (p_nid in number,
1447 p_protocol in varchar2,
1448 p_recipient_list in WF_DIRECTORY.wf_local_roles_tbl_type,
1449 p_node in varchar2,
1450 p_agent in varchar2,
1451 p_replyto in varchar2,
1452 p_nlang in varchar2,
1453 p_nterr in varchar2,
1454 p_priority out NOCOPY number,
1455 p_message in out NOCOPY CLOB)
1456 is
1457 -- l_doc CLOB;
1458 l_docIdx pls_integer;
1459 l_doctype varchar(100);
1460 l_pos integer;
1461 l_occurance integer := 1;
1462 l_item_type wf_items.item_type%TYPE;
1463 l_item_key wf_items.item_key%TYPE;
1464 l_priority wf_notifications.priority%TYPE;
1465 l_access_key wf_notifications.access_key%TYPE;
1466
1467 l_response integer;
1468
1469 l_attrlist wf_xml_attr_table_type;
1470 l_receiverlist varchar2 (4000);
1471 l_status varchar2 (8);
1472 l_language varchar2 (30);
1473 l_territory varchar2 (30);
1474 l_installed_lang varchar2 (1);
1475 l_str varchar2 (250);
1476 l_subject varchar2 (2000);
1477 l_text_body varchar2 (32000);
1478 l_html_body varchar2 (32000);
1479 l_body_atth varchar2 (32000);
1480 l_error_result varchar2 (2000);
1481 l_err_name varchar2 (30);
1482 l_err_message varchar2 (2000);
1483 l_err_stack varchar2 (4000);
1484
1485 begin
1486
1487 -- Grab the details of the message to be enqueued using the
1488 -- previous interface of WF_MAIL.GetMessage.
1489 begin
1490
1491 select installed_flag
1492 into l_installed_lang
1493 from wf_languages
1494 where nls_language = p_nlang
1495 and nls_territory = p_nterr
1496 and installed_flag = 'Y';
1497
1498 l_language := ''''||p_nlang||'''';
1499 l_territory := ''''||p_nterr||'''';
1500 exception
1501 when others then
1502 l_language := 'AMERICAN';
1503 l_territory := 'AMERICA';
1504 end;
1505 dbms_session.set_nls('NLS_LANGUAGE' , l_language);
1506 dbms_session.set_nls('NLS_TERRITORY' , l_territory);
1507
1508 wf_mail.getmessage(p_nid, p_node, p_agent, p_replyto,
1509 l_subject, l_text_body, l_html_body, l_body_atth,
1510 l_error_result);
1511 -- Check for any problems
1512 if l_error_result is not NULL then
1513 wf_core.token('LANG', l_language);
1514 wf_core.token('TERR', l_territory);
1515 wf_core.token('ERRMSG', l_error_result);
1516 wf_core.raise('WFXMLERR');
1517 end if;
1518
1519
1520 -- Instantiate a handle to the new document.
1521 -- dbms_lob.createTemporary(l_doc, TRUE, dbms_lob.session);
1522 l_docIdx := wf_temp_lob.getLob(g_LOBTable);
1523
1524 -- Initialise the XML Document and then progressively walk
1525 -- through the elements. Populating them as we go.
1526 -- l_pos is crucial as it determines where the next nodes
1527 -- will be placed.
1528 l_str := '<?xml version="1.0"?>';
1529 l_pos := length(l_str);
1530
1531 dbms_lob.write(g_LOBTable(l_docIdx).temp_lob, l_pos, 1, l_str);
1532
1533 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1534 'NOTIFICATION','',l_attrlist);
1535
1536
1537 AddElementAttribute('language',p_nlang, l_attrlist);
1538 AddElementAttribute('territory',p_nterr, l_attrlist);
1539 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'HEADER', '',
1540 l_attrlist);
1541 l_attrlist.DELETE;
1542
1543 -- Attach the NID
1544 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'NID',
1545 to_char(p_nid),l_attrlist);
1546 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'NID', l_pos, l_occurance);
1547
1548 begin
1549 select priority, access_key, status
1550 into l_priority, l_access_key, l_status
1551 from wf_notifications_view
1552 where notification_id = p_nid;
1553 exception
1554 when NO_DATA_FOUND then
1555 wf_core.raise('WFNTFGM_FAILED');
1556 end;
1557
1558 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'PRIORITY',
1559 to_char(l_priority), l_attrlist);
1560 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'PRIORITY', l_pos,
1561 l_occurance);
1562 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'ACCESSKEY',
1563 l_access_key, l_attrlist);
1564 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'ACCESSKEY', l_pos,
1565 l_occurance);
1566
1567 -- Register the receivers as a single string of email addresses
1568 l_receiverlist := NULL;
1569 for i in 1..p_recipient_list.COUNT loop
1570 l_receiverlist := l_receiverlist || p_recipient_list(i).NAME || ',';
1571 end loop;
1572
1573 l_receiverlist := substr(l_receiverlist,1,length(l_receiverlist)-1);
1574 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'RECEIVERLIST',
1575 l_receiverlist, l_attrlist);
1576 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'RECEIVERLIST',
1577 l_pos, l_occurance);
1578
1579 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'SENDER', '',
1580 l_attrlist);
1581 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'SENDER', l_pos,
1582 l_occurance);
1583
1584 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'STATUS',
1585 l_status, l_attrlist);
1586 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'STATUS', l_pos,
1587 l_occurance);
1588
1589 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'SUBJECT',
1590 l_subject, l_attrlist);
1591 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'HEADER', l_pos,
1592 l_occurance);
1593
1594 l_text_body := EncodeEntityReference(l_text_body);
1595 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'BODYTEXT',
1596 l_text_body, l_attrlist);
1597 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'BODYTEXT', l_pos, l_occurance);
1598
1599 AddElementAttribute('content-type','text/html', l_attrlist);
1600 AddElementAttribute('hmldesc','HTML', l_attrlist);
1601 AddElementAttribute('htmlagent',p_agent, l_attrlist);
1602
1603 l_html_body := EncodeEntityReference(l_html_body);
1604
1605 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos, 'BODYHTML',
1606 l_html_body, l_attrlist);
1607 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'BODYHTML', l_pos,
1608 l_occurance);
1609 l_attrlist.DELETE;
1610
1611 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1612 'ATTACHMENTLIST', '', l_attrlist);
1613 -- Next will be to attach all URLs and DOCUMENT attributes
1614 -- as attachments.
1615 l_pos := GetAttachment(p_nid, g_LOBTable(l_docIdx).temp_lob, p_agent,
1616 NULL, l_doctype, l_pos);
1617 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob, 'ATTACHMENTLIST',
1618 l_pos, l_occurance);
1619
1620 -- Check to see if the notification is a reponse and attach
1621 -- the response attributes.
1622 l_response := 0;
1623 begin
1624 select 1 into l_response
1625 from dual
1626 where exists (select NULL
1627 from WF_MESSAGE_ATTRIBUTES MA,
1628 WF_NOTIFICATIONS N
1629 where N.NOTIFICATION_ID = p_nid
1630 and MA.MESSAGE_TYPE = N.MESSAGE_TYPE
1631 and MA.MESSAGE_NAME = N.MESSAGE_NAME
1632 and MA.SUBTYPE = 'RESPOND');
1633
1634 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1635 'ATTRIBUTELIST', '', l_attrlist);
1636 l_pos := GetAttributes(p_nid, g_LOBTable(l_docIdx).temp_lob, p_agent,
1637 l_pos);
1638
1639 exception
1640 when NO_DATA_FOUND then
1641 null;
1642 end;
1643
1644 p_priority := l_priority;
1645 dbms_lob.copy(p_message, g_LOBTable(l_docIdx).temp_lob,
1646 dbms_lob.getLength(g_LOBTable(l_docIdx).temp_lob), 1, 1);
1647 -- dbms_lob.freetemporary(l_doc).temp_lob);
1648 wf_temp_lob.releaseLob(g_LOBTable, l_docIdx);
1649
1650 exception
1651 when others then
1652 wf_temp_lob.releaseLob(g_LOBTable, l_docIdx);
1653 wf_core.context('WF_XML', 'GetXMLMessage', to_char(p_nid), p_protocol,
1654 p_node, p_nlang, p_nterr);
1655 raise;
1656 end getXMLMessage;
1657
1658 -- GetShortLOBXMLMessage -
1659 -- Return a CLOB Document containing an XML encoded versi on of the
1660 -- notification. No recipients list will be populated. That
1661 -- will be the responsibility of the calling procedure.
1662 --
1663 -- IN
1664 -- notification id
1665 -- Protocol for the message
1666 -- List of recipients to recieve the notification
1667 -- mailer node name
1668 -- Web Agent for the HTML attachments
1669 -- Reply to address for the final notification
1670 -- Language for the notification
1671 -- Territory for the notification
1672 -- OUT
1673 -- Piority for the message
1674 -- A CLOB Containing the XML encoded message.
1675 procedure GetShortLOBXMLMessage (p_nid in number,
1676 p_priority out NOCOPY number,
1677 p_message in out NOCOPY CLOB)
1678 is
1679 -- l_doc CLOB;
1680 l_docIdx pls_integer;
1681 l_pos integer;
1682 l_occurance integer := 1;
1683 l_priority wf_notifications.priority%TYPE;
1684 l_status wf_notifications.status%TYPE;
1685 l_recipient wf_notifications.recipient_role%TYPE;
1686
1687 l_attrlist wf_xml_attr_table_type;
1688 l_str varchar2 (250);
1689
1690 l_error_result varchar2 (2000);
1691 l_err_name varchar2 (30);
1692 l_err_message varchar2 (2000);
1693 l_err_stack varchar2 (4000);
1694 l_more_info_role varchar2(320);
1695
1696 begin
1697
1698 -- Grab the details of the message to be enqueued using the
1699 -- previous interface of WF_MAIL.GetMessage.
1700
1701 -- Instantiate a handle to the new document.
1702 -- dbms_lob.createTemporary(l_doc, TRUE, dbms_lob.session);
1703 l_docIdx := wf_temp_lob.getLOB(g_LOBTable);
1704
1705 -- Initialise the XML Document and then progressively walk
1706 -- through the elements. Populating them as we go.
1707 -- l_pos is crucial as it determines where the next nodes
1708 -- will be placed.
1709 l_str := '<?xml version="1.0"?>';
1710 l_pos := length(l_str);
1711
1712 dbms_lob.write(g_LOBTable(l_docIdx).temp_lob, l_pos, 1, l_str);
1713
1714 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1715 'NOTIFICATION','',l_attrlist);
1716
1717 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1718 'HEADER', '', l_attrlist);
1719 l_attrlist.DELETE;
1720
1721 -- Attach the NID
1722 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1723 'NID', to_char(p_nid),l_attrlist);
1724 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob,
1725 'NID', l_pos, l_occurance);
1726
1727 begin
1728 select recipient_role, priority, status, more_info_role
1729 into l_recipient, l_priority, l_status, l_more_info_role
1730 from wf_notifications
1731 where notification_id = p_nid;
1732 exception
1733 when NO_DATA_FOUND then
1734 wf_core.raise('WFNTFGM_FAILED');
1735 end;
1736
1737 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1738 'PRIORITY', to_char(l_priority), l_attrlist);
1739 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob,
1740 'PRIORITY', l_pos, l_occurance);
1741
1742 if (l_more_info_role is not null) then
1743 l_recipient := l_more_info_role;
1744 end if;
1745 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1746 'RECIPIENT', l_recipient, l_attrlist);
1747 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob,
1748 'RECIPIENT', l_pos, l_occurance);
1749
1750 l_pos := NewLOBTag(g_LOBTable(l_docIdx).temp_lob, l_pos,
1751 'STATUS', l_status, l_attrlist);
1752 l_pos := SkipLOBTag(g_LOBTable(l_docIdx).temp_lob,
1753 'STATUS', l_pos, l_occurance);
1754
1755 p_priority := l_priority;
1756 dbms_lob.copy(p_message, g_LOBTable(l_docIdx).temp_lob,
1757 dbms_lob.getLength(g_LOBTable(l_docIdx).temp_lob), 1, 1);
1758 -- dbms_lob.freetemporary(g_LOBTable(l_docIdx).temp_lob);
1759 wf_temp_lob.releaseLob(g_LOBTable, l_docIdx);
1760
1761 exception
1762 when others then
1763 wf_temp_lob.releaseLob(g_LOBTable, l_docIdx);
1764 wf_core.context('WF_XML', 'GetShortLOBXMLMessage', to_char(p_nid));
1765 raise;
1766 end getShortLOBXMLMessage;
1767
1768 -- GetShortXMLMessage -
1769 -- Return a VARCHAR Document containing an XML encoded versi on of the
1770 -- notification. No recipients list will be populated. That
1771 -- will be the responsibility of the calling procedure.
1772 --
1773 -- IN
1774 -- notification id
1775 -- Protocol for the message
1776 -- List of recipients to recieve the notification
1777 -- mailer node name
1778 -- Web Agent for the HTML attachments
1779 -- Reply to address for the final notification
1780 -- Language for the notification
1781 -- Territory for the notification
1782 -- OUT
1783 -- Piority for the message
1784 -- A VARCHAR Containing the XML encoded message.
1785 procedure GetShortXMLMessage (p_nid in number,
1786 p_priority out NOCOPY number,
1787 p_message in out NOCOPY VARCHAR2)
1788 is
1789 l_pos integer;
1790 l_occurance integer := 1;
1791 l_priority wf_notifications.priority%TYPE;
1792 l_status wf_notifications.status%TYPE;
1793 l_recipient wf_notifications.recipient_role%TYPE;
1794
1795 l_attrlist wf_xml_attr_table_type;
1796 l_str varchar2 (250);
1797
1798 l_error_result varchar2 (2000);
1799 l_err_name varchar2 (30);
1800 l_err_message varchar2 (2000);
1801 l_err_stack varchar2 (4000);
1802 l_more_info_role varchar2(320);
1803
1804 begin
1805
1806 -- Grab the details of the message to be enqueued using the
1807 -- previous interface of WF_MAIL.GetMessage.
1808
1809 -- Instantiate a handle to the new document.
1810 p_message := '';
1811
1812 -- Initialise the XML Document and then progressively walk
1813 -- through the elements. Populating them as we go.
1814 -- l_pos is crucial as it determines where the next nodes
1815 -- will be placed.
1816 l_str := '<?xml version="1.0"?>';
1817 l_pos := length(l_str);
1818
1819 p_message := p_message||l_str;
1820
1821 l_pos := NewTag(p_message, l_pos, 'NOTIFICATION',NULL,l_attrlist);
1822
1823 l_pos := NewTag(p_message, l_pos, 'HEADER', NULL, l_attrlist);
1824 l_attrlist.DELETE;
1825
1826 -- Attach the NID
1827 l_pos := NewTag(p_message, l_pos, 'NID', to_char(p_nid),l_attrlist);
1828 l_pos := SkipTag(p_message, 'NID', l_pos, l_occurance);
1829
1830 begin
1831 select recipient_role, priority, status, more_info_role
1832 into l_recipient, l_priority, l_status, l_more_info_role
1833 from wf_notifications
1834 where notification_id = p_nid;
1835 exception
1836 when NO_DATA_FOUND then
1837 wf_core.raise('WFNTFGM_FAILED');
1838 end;
1839
1840 l_pos := NewTag(p_message, l_pos, 'PRIORITY', to_char(l_priority),
1841 l_attrlist);
1842 l_pos := SkipTag(p_message, 'PRIORITY', l_pos, l_occurance);
1843
1844 if (l_more_info_role is not null) then
1845 l_recipient := l_more_info_role;
1846 end if;
1847 l_pos := NewTag(p_message, l_pos, 'RECIPIENT', l_recipient, l_attrlist);
1848 l_pos := SkipTag(p_message, 'RECIPIENT', l_pos, l_occurance);
1849
1850 l_pos := NewTag(p_message, l_pos, 'STATUS', l_status, l_attrlist);
1851 l_pos := SkipTag(p_message, 'STATUS', l_pos, l_occurance);
1852
1853 p_priority := l_priority;
1854
1855 exception
1856 when others then
1857 wf_core.context('WF_XML', 'GetShortXMLMessage', to_char(p_nid));
1858 raise;
1859 end getShortXMLMessage;
1860
1861
1862 -- EnqueueFullNotification -
1863 -- To push a notification to the outbound notification queue.
1864 -- IN
1865 -- Notification ID
1866 procedure EnqueueFullNotification(p_nid in number) is
1867
1868 l_queue_name varchar2(255);
1869
1870 l_node varchar2(30);
1871 l_agent varchar(255) := g_webAgent;
1872 l_replyto varchar2(320);
1873
1874 l_nlang wf_languages.nls_language%TYPE;
1875 l_nterr wf_languages.nls_territory%TYPE;
1876 l_priority number;
1877 -- l_message CLOB;
1878 l_messageIdx pls_integer;
1879
1880 l_recipient_role varchar2(320);
1881 l_ntf_pref varchar2(30);
1882 l_language varchar2(30);
1883 l_recipient_list WF_DIRECTORY.wf_local_roles_tbl_type;
1884 l_recipient_lang WF_DIRECTORY.wf_local_roles_tbl_type;
1885 l_wf_schema varchar2(320) := g_wfSchema;
1886
1887 l_err_name varchar2(30);
1888 l_err_message varchar2(2000);
1889 l_err_stack varchar2(4000);
1890
1891 i binary_integer := 0;
1892 j binary_integer := 0;
1893
1894 begin
1895
1896 -- Obtain the name of the recipient role, but only if a
1897 -- notification is needed to go out. ie the mail status
1898 -- indicates that a notification should be sent.
1899 begin
1900 select recipient_role
1901 into l_recipient_role
1902 from wf_notifications
1903 where notification_id = p_nid
1904 and ((MAIL_STATUS = 'MAIL' and STATUS <> 'CLOSED')
1905 or (MAIL_STATUS = 'INVALID'));
1906 exception
1907 when NO_DATA_FOUND then
1908 l_recipient_role := NULL;
1909 when others then
1910 raise;
1911 end;
1912 if l_recipient_role is not null then
1913 -- Determine the total list of individual recipients
1914 -- ordered by Protocol and then Language.
1915 l_recipient_list.DELETE;
1916 GetRecipients(l_recipient_role, l_recipient_list);
1917
1918 end if;
1919
1920 if l_recipient_list.COUNT > 0 then
1921 -- A valid role has been found for a notification
1922 -- that is required to go out.
1923 -- Prepare a LOB to contain the payload message.
1924 -- dbms_lob.createTemporary(l_message, TRUE, dbms_lob.SESSION);
1925 l_messageIdx := wf_temp_lob.getLob(g_LOBTable);
1926
1927 wf_queue.set_queue_names;
1928 wf_queue.get_hash_queue_name (p_protocol => 'SMTP',
1929 p_inbound_outbound => 'OUTBOUND',
1930 p_queue_name => l_queue_name);
1931 l_language := l_recipient_list(1).language;
1932 l_ntf_pref := l_recipient_list(1).notification_preference;
1933 l_recipient_lang.DELETE;
1934 j := 1;
1935 i := 1;
1936
1937
1938 -- Walk through the recipient list. This will be sorted by Notification
1939 -- preference and language. We group the recipients this way to help
1940 -- minimise the number of Queue messages to the number of recipients.
1941 loop
1942 exit when i > l_recipient_list.COUNT;
1943 if l_ntf_pref <> l_recipient_list(i).notification_preference then
1944 wf_queue.get_hash_queue_name (p_protocol => 'SMTP',
1945 p_inbound_outbound => 'OUTBOUND',
1946 p_queue_name => l_queue_name);
1947
1948 end if;
1949 loop
1950 exit when (i > l_recipient_list.COUNT)
1951 or (l_ntf_pref <> l_recipient_list(i).notification_preference);
1952 j := 1;
1953 loop
1954 exit when (i > l_recipient_list.COUNT)
1955 or (l_ntf_pref <> l_recipient_list(i).notification_preference)
1956 or (l_language <> l_recipient_list(i).language);
1957
1958 l_recipient_lang(j) := l_recipient_list(i);
1959 i := i + 1;
1960 j := j + 1;
1961 end loop;
1962 -- Get an encoded payload.
1963 getXMLMessage(p_nid, l_ntf_pref,
1964 l_recipient_lang, l_node, l_agent,
1965 l_replyto,
1966 l_recipient_lang(1).language,
1967 l_recipient_lang(1).territory, l_priority, g_LOBTable(l_messageIdx).temp_lob);
1968
1969 -- Push the message to the queue.
1970 enqueueLOBMessage(p_queue => l_queue_name,
1971 p_priority => l_priority,
1972 p_correlation => wf_queue.account_name ||':'||
1973 to_char(p_nid),
1974 p_message => g_LOBTable(l_messageIdx).temp_lob);
1975
1976 j := 1;
1977 l_recipient_lang.DELETE;
1978 if i <= l_recipient_list.COUNT then
1979 l_ntf_pref := l_recipient_list(i).notification_preference;
1980 end if;
1981 end loop;
1982 end loop;
1983 -- dbms_lob.freetemporary(l_message);
1984 wf_temp_lob.releaseLob(g_LOBTable, l_messageIdx);
1985 end if;
1986
1987 exception
1988 when others then
1989 wf_temp_lob.releaseLob(g_LOBTable, l_messageIdx);
1990 wf_core.context('WF_XML', 'EnqueueFullNotification', to_char(p_nid));
1991 raise;
1992 end EnqueueFullNotification;
1993
1994
1995 -- EnqueueLOBNotification - To push a notification ID to the outbound
1996 -- notification queue.
1997 -- IN
1998 -- Notification ID
1999 procedure EnqueueLOBNotification(p_nid in number) is
2000
2001 l_queue_name varchar2(255);
2002 l_priority number;
2003
2004 l_recipient_role varchar2(320);
2005 -- l_message CLOB;
2006 l_messageIdx pls_integer;
2007
2008 l_err_name varchar2(30);
2009 l_err_message varchar2(2000);
2010 l_err_stack varchar2(4000);
2011
2012 begin
2013
2014 -- Obtain the name of the recipient role, but only if a
2015 -- notification is needed to go out. ie the mail status
2016 -- indicates that a notification should be sent.
2017 begin
2018 select recipient_role
2019 into l_recipient_role
2020 from wf_notifications
2021 where notification_id = p_nid
2022 and MAIL_STATUS in ('MAIL', 'INVALID');
2023 exception
2024 when NO_DATA_FOUND then
2025 l_recipient_role := NULL;
2026 when others then
2027 raise;
2028 end;
2029 if l_recipient_role is not null then
2030 -- A valid role has been found for a notification
2031 -- that is required to go out.
2032
2033 -- dbms_lob.createTemporary(l_message, TRUE, dbms_lob.CALL);
2034 l_messageIdx := wf_temp_lob.getLob(g_LOBTable);
2035 -- Get an encoded payload.
2036 getShortLOBXMLMessage(p_nid, l_priority,
2037 g_LOBTable(l_messageIdx).temp_lob);
2038
2039 wf_queue.set_queue_names;
2040 wf_queue.get_hash_queue_name (p_protocol => 'SMTP',
2041 p_inbound_outbound => 'OUTBOUND',
2042 p_queue_name => l_queue_name);
2043
2044 -- Push the message to the queue.
2045 enqueueLOBMessage(p_queue => l_queue_name,
2046 p_priority => l_priority,
2047 p_correlation => wf_queue.account_name ||':'||
2048 to_char(p_nid),
2049 p_message => g_LOBTable(l_messageIdx).temp_lob);
2050 end if;
2051 wf_temp_lob.releaseLob(g_LOBTable, l_messageIdx);
2052
2053 exception
2054 when others then
2055 wf_temp_lob.releaseLob(g_LOBTable, l_messageIdx);
2056 wf_core.context('WF_XML', 'EnqueueLOBNotification', to_char(p_nid));
2057 raise;
2058 end EnqueueLOBNotification;
2059
2060 -- EnqueueNotification - To push a notification ID to the outbound
2061 -- notification queue.
2062 -- IN
2063 -- Notification ID
2064 procedure EnqueueNotification(p_nid in number) is
2065
2066 l_queue_name varchar2(255);
2067 l_priority number;
2068
2069 l_recipient_role varchar2(320);
2070 l_message VARCHAR2(32000);
2071
2072 l_err_name varchar2(30);
2073 l_err_message varchar2(2000);
2074 l_err_stack varchar2(4000);
2075 l_more_info_role varchar2(320);
2076 begin
2077
2078 -- Obtain the name of the recipient role, but only if a
2079 -- notification is needed to go out. ie the mail status
2080 -- indicates that a notification should be sent.
2081 begin
2082 select recipient_role, more_info_role
2083 into l_recipient_role, l_more_info_role
2084 from wf_notifications
2085 where notification_id = p_nid
2086 and MAIL_STATUS in ('MAIL', 'INVALID')
2087 and STATUS <> 'CLOSED';
2088 exception
2089 when NO_DATA_FOUND then
2090 l_recipient_role := NULL;
2091 l_more_info_role := NULL;
2092 when others then
2093 raise;
2094 end;
2095 if (l_recipient_role is not null or l_more_info_role is not null) then
2096 -- A valid role has been found for a notification
2097 -- that is required to go out.
2098
2099 -- Get an encoded payload.
2100 getShortXMLMessage(p_nid, l_priority, l_message);
2101
2102 wf_queue.set_queue_names;
2103 wf_queue.get_hash_queue_name (p_protocol => 'SMTP',
2104 p_inbound_outbound => 'OUTBOUND',
2105 p_queue_name => l_queue_name);
2106
2107 -- Push the message to the queue.
2108 enqueueMessage(p_queue => l_queue_name,
2109 p_priority => l_priority,
2110 p_correlation => wf_queue.account_name ||':'||
2111 to_char(p_nid),
2112 p_message => l_message);
2113 end if;
2114
2115 exception
2116 when others then
2117 wf_core.context('WF_XML', 'EnqueueNotification', to_char(p_nid));
2118 raise;
2119 end EnqueueNotification;
2120
2121
2122 -- DequeueMessage - Remove a notification from the queue
2123 -- IN
2124 -- Queue name to operate on
2125 -- Correlation for the message - NID in this implementation
2126 -- OUT
2127 -- The message that is obtained from the queue.
2128 -- Timeout to signal whether the queue is empty.
2129 procedure DequeueMessage(p_queue_name in varchar2,
2130 p_correlation in varchar2,
2131 p_message in out NOCOPY CLOB,
2132 p_timeout out NOCOPY boolean)
2133 as
2134
2135 l_dequeue_options dbms_aq.dequeue_options_t;
2136 l_message_properties dbms_aq.message_properties_t;
2137 l_correlation varchar2(255) := NULL;
2138 l_message_handle RAW(16);
2139
2140 begin
2141
2142 /** wf_message_payload_t is obsolete in 2.6.4 onwards **/
2143 null;
2144
2145 exception
2146 when dequeue_timeout then
2147 p_timeout := TRUE;
2148 when others then
2149 Wf_Core.Context('WF_XML', 'DequeueMessage', p_queue_name,
2150 p_correlation);
2151 p_timeout := FALSE;
2152 raise;
2153 end DequeueMessage;
2154
2155
2156
2157 -- GetMessage - Get email message data
2158 -- IN
2159 -- Queue number to operate on
2160 -- OUT
2161 -- Notification ID
2162 -- Comma seperated list of the recipients of the notification
2163 -- Status of the notification - For the purpose of message templating
2164 -- Timout. Returns TRUE where the queue is empty.
2165 -- Error message
2166 procedure GetMessage(
2167 p_queue in number,
2168 p_nid out NOCOPY number,
2169 p_receiverlist out NOCOPY varchar2,
2170 p_status out NOCOPY varchar2,
2171 p_timeout out NOCOPY integer,
2172 p_error_result in out NOCOPY varchar2)
2173 is
2174
2175 l_nid number;
2176 l_queue_name varchar2(255);
2177 l_status varchar2(8);
2178 l_receiverlist varchar2(4000);
2179
2180 l_message CLOB;
2181 l_timeout BOOLEAN;
2182 l_pos integer;
2183 l_attrlist wf_xml_attr_table_type;
2184
2185 l_err_name varchar2(30);
2186 l_err_message varchar2(2000);
2187 l_err_stack varchar2(4000);
2188 no_program_unit exception;
2189 pragma exception_init(no_program_unit, -6508);
2190
2191 begin
2192
2193 l_queue_name := g_wfSchema||'.WF_SMTP_O_'||
2194 to_char(p_queue)||'_QUEUE';
2195
2196 -- Grab the next available message from the queue.
2197 DequeueMessage(p_queue_name => l_queue_name,
2198 p_correlation => NULL,
2199 p_message => l_message,
2200 p_timeout => l_timeout);
2201
2202 -- If the result is from the queue being empty then we want to
2203 -- inform the caller to maybe go and do something else a while.
2204 if NOT l_timeout then
2205 -- We now have a message as a CLOB. we need to parse it
2206 -- to reconstruct the DOM Document.
2207 -- new parser
2208
2209 -- Grab the components of the notification to send
2210 -- back to the caller
2211
2212 l_pos := 1;
2213
2214 GetTagValue(l_message, 'NID', l_nid, l_pos, l_attrlist);
2215 GetTagValue(l_message, 'RECEIVERLIST', l_receiverlist, l_pos,
2216 l_attrlist);
2217 GetTagValue(l_message, 'STATUS', l_status, l_pos, l_attrlist);
2218
2219 end if;
2220
2221 p_nid := to_number(l_nid);
2222 p_receiverlist := l_receiverlist;
2223 p_status := l_status;
2224
2225 if l_timeout then
2226 p_timeout := 1;
2227 else
2228 p_timeout := 0;
2229 end if;
2230
2231 exception
2232 when no_program_unit then
2233 wf_core.context('WF_XML', 'GetMessage', to_char(p_queue));
2234 raise;
2235
2236 when others then
2237 -- First look for a wf_core error.
2238 wf_core.get_error(l_err_name, l_err_message, l_err_stack);
2239
2240 -- If no wf_core error look for a sql error.
2241 if (l_err_name is null) then
2242 l_err_message := sqlerrm;
2243 end if;
2244
2245 p_error_result := l_err_message;
2246 wf_core.context('WF_XML', 'GetMessage', to_char(p_queue));
2247 raise;
2248
2249 end GetMessage;
2250
2251 -- GetShortMessage - Get email message data
2252 -- IN
2253 -- Queue number to operate on
2254 -- OUT
2255 -- Notification ID
2256 -- Comma seperated list of the recipients of the notification
2257 -- Status of the notification - For the purpose of message templating
2258 -- Timout. Returns TRUE where the queue is empty.
2259 -- Error message
2260 procedure GetShortMessage(
2261 p_queue in number,
2262 p_nid out NOCOPY number,
2263 p_recipient out NOCOPY varchar2,
2264 p_status out NOCOPY varchar2,
2265 p_timeout out NOCOPY integer,
2266 p_error_result in out NOCOPY varchar2)
2267 is
2268
2269 l_queue_name varchar2(200);
2270
2271 l_err_name varchar2(30);
2272 l_err_message varchar2(2000);
2273 l_err_stack varchar2(4000);
2274 no_program_unit exception;
2275 pragma exception_init(no_program_unit, -6508);
2276
2277 begin
2278
2279 l_queue_name := g_wfSchema||'.WF_SMTP_O_'||
2280 to_char(p_queue)||'_QUEUE';
2281
2282 GetQueueMessage(l_queue_name, p_nid, p_recipient, p_status,
2283 p_timeout, p_error_result);
2284 exception
2285 when no_program_unit then
2286 wf_core.context('WF_XML', 'GetShortMessage', to_char(p_queue));
2287 raise;
2288
2289 when others then
2290 -- First look for a wf_core error.
2291 wf_core.get_error(l_err_name, l_err_message, l_err_stack);
2292
2293 -- If no wf_core error look for a sql error.
2294 if (l_err_name is null) then
2295 l_err_message := sqlerrm;
2296 end if;
2297
2298 p_error_result := l_err_message;
2299 wf_core.context('WF_XML', 'GetShortMessage', to_char(p_queue));
2300 raise;
2301
2302 end GetShortMessage;
2303
2304
2305 -- GetExceptionMessage - Get email message data
2306 -- IN
2307 -- Queue number to operate on
2308 -- OUT
2309 -- Notification ID
2310 -- Comma seperated list of the recipients of the notification
2311 -- Status of the notification - For the purpose of message templating
2312 -- Timout. Returns TRUE where the queue is empty.
2313 -- Error message
2314 procedure GetExceptionMessage(
2315 p_queue in number,
2316 p_nid out NOCOPY number,
2317 p_recipient out NOCOPY varchar2,
2318 p_status out NOCOPY varchar2,
2319 p_timeout out NOCOPY boolean,
2320 p_error_result in out NOCOPY varchar2)
2321 is
2322 l_timeout integer;
2323 l_queue_name varchar2(200);
2324
2325 l_err_name varchar2(30);
2326 l_err_message varchar2(2000);
2327 l_err_stack varchar2(4000);
2328 no_program_unit exception;
2329 pragma exception_init(no_program_unit, -6508);
2330
2331 begin
2332
2333 l_queue_name := wf_queue.enable_exception_queue(
2334 g_wfSchema||
2335 '.WF_SMTP_O_'||to_char(p_queue)||'_QUEUE');
2336 if l_queue_name is not NULL then
2337 GetQueueMessage(l_queue_name, p_nid, p_recipient, p_status,
2338 l_timeout, p_error_result);
2339 -- GetQueueMessage returns timeout as an integer for the benefit
2340 if l_timeout = 0 then
2341 p_timeout := FALSE;
2342 else
2343 p_timeout := TRUE;
2344 end if;
2345 else
2346 p_timeout := TRUE;
2347 end if;
2348
2349 exception
2350 when no_program_unit then
2351 wf_core.context('WF_XML', 'GetExceptionMessage', to_char(p_queue));
2352 raise;
2353
2354 when others then
2355 -- First look for a wf_core error.
2356 wf_core.get_error(l_err_name, l_err_message, l_err_stack);
2357
2358 -- If no wf_core error look for a sql error.
2359 if (l_err_name is null) then
2360 l_err_message := sqlerrm;
2361 end if;
2362
2363 p_error_result := l_err_message;
2364 wf_core.context('WF_XML', 'GetExceptionMessage', to_char(p_queue));
2365 raise;
2366
2367 end GetExceptionMessage;
2368
2369 -- GetQueueMessage - Get email message data
2370 -- IN
2371 -- Queue name
2372 -- OUT
2373 -- Notification ID
2374 -- Comma seperated list of the recipients of the notification
2375 -- Status of the notification - For the purpose of message templating
2376 -- Timout. Returns TRUE where the queue is empty.
2377 -- Error message
2378 procedure GetQueueMessage(
2379 p_queuename in varchar2,
2380 p_nid out NOCOPY number,
2381 p_recipient out NOCOPY varchar2,
2382 p_status out NOCOPY varchar2,
2383 p_timeout out NOCOPY integer,
2384 p_error_result in out NOCOPY varchar2)
2385 is
2386
2387 l_message CLOB;
2388 l_nid number;
2389 l_queue_name varchar2(255);
2390 l_status varchar2(8) := NULL;
2391 l_currstatus varchar2(8);
2392 l_recipient WF_NOTIFICATIONS.RECIPIENT_ROLE%TYPE := NULL;
2393 l_attrlist wf_xml_attr_table_type;
2394 l_timeout BOOLEAN;
2395 l_pos integer;
2396 l_statusOK boolean;
2397
2398 l_err_name varchar2(30);
2399 l_err_message varchar2(2000);
2400 l_err_stack varchar2(4000);
2401 no_program_unit exception;
2402 pragma exception_init(no_program_unit, -6508);
2403
2404 begin
2405
2406 l_queue_name := p_queuename;
2407
2408 -- Grab the next available message from the queue.
2409 -- The lob located will contain a reference to a persistent
2410 -- LOB so there is not need to pre-create a temporary LOB.
2411 loop
2412 DequeueMessage(p_queue_name => l_queue_name,
2413 p_correlation => NULL,
2414 p_message => l_message,
2415 p_timeout => l_timeout);
2416
2417 -- If the result is from the queue being empty then we want to
2418 -- inform the caller to maybe go and do something else a while.
2419 if NOT l_timeout then
2420 -- We now have a message as a CLOB. we need to parse it
2421 -- to reconstruct the DOM Document.
2422 -- new parser
2423
2424 -- Grab the components of the notification to send
2425 -- back to the caller
2426
2427 l_pos := 1;
2428
2429 GetTagValue(l_message, 'NID', l_nid, l_pos, l_attrlist);
2430 GetTagValue(l_message, 'RECIPIENT', l_recipient, l_pos, l_attrlist);
2431 GetTagValue(l_message, 'STATUS', l_status, l_pos, l_attrlist);
2432
2433 -- Verify that the status of the notification is
2434 -- still OK.
2435 begin
2436 select status into l_currstatus
2437 from wf_notifications
2438 where notification_id = l_nid
2439 and status in ('OPEN','CANCELED', 'CLOSED')
2440 and mail_status in ('MAIL','INVALID','FAILED');
2441 l_statusOK := TRUE;
2442 exception
2443 when no_data_found then
2444 l_statusOK := FALSE;
2445 when others then raise;
2446 end;
2447 end if;
2448 exit when l_timeout or l_statusOK;
2449 end loop;
2450 p_nid := to_number(l_nid);
2451 p_recipient := l_recipient;
2452 p_status := l_status;
2453
2454 if l_timeout then
2455 p_timeout := 1;
2456 else
2457 p_timeout := 0;
2458 end if;
2459
2460 exception
2461 when no_program_unit then
2462 wf_core.context('WF_XML', 'GetQueueMessage', p_queuename);
2463 raise;
2464
2465 when others then
2466 -- First look for a wf_core error.
2467 wf_core.get_error(l_err_name, l_err_message, l_err_stack);
2468
2469 -- If no wf_core error look for a sql error.
2470 if (l_err_name is null) then
2471 l_err_message := sqlerrm;
2472 end if;
2473
2474 p_error_result := l_err_message;
2475 wf_core.context('WF_XML', 'GetQueueMessage', p_queuename);
2476 raise;
2477
2478 end GetQueueMessage;
2479
2480
2481 -- RemoveMessage
2482 -- To remove any messages associated with a particular Notification ID.
2483 -- Note that a notification can contain more than one message. Each of
2484 -- these messages will have a unique message handle and could be
2485 -- enqueued on more than one queue.
2486 -- IN
2487 -- Queue Name to remove the messages from
2488 -- Correlation or the Notification ID of the messages to remove.
2489 -- OUT
2490 -- Timeout. Returns TRUE if there was nothing on the Queue
2491 procedure RemoveMessage(p_queue_name in varchar2,
2492 p_correlation in varchar2,
2493 p_timeout out NOCOPY boolean)
2494 is
2495 l_dequeue_options dbms_aq.dequeue_options_t;
2496 l_message_properties dbms_aq.message_properties_t;
2497 l_correlation varchar2(255) := NULL;
2498 l_message_handle RAW(16);
2499
2500 begin
2501
2502 /** wf_message_payload_t is obsolete in 2.6.4 onwards **/
2503 null;
2504
2505 exception
2506 when others then
2507 Wf_Core.Context('WF_XML', 'RemoveMessage', p_queue_name, p_correlation);
2508 p_timeout := FALSE;
2509 raise;
2510 end RemoveMessage;
2511
2512
2513 -- RemoveNotification
2514 -- To remove all enqueues messages for a given notification.
2515 -- IN
2516 -- Notification ID of the message to locate and remove.
2517 -- NOTE
2518 -- This is a destructive procedure that's sole purpose is to purge the
2519 -- message from the queue. We only call this when we do not care for the
2520 -- content.
2521 procedure RemoveNotification (p_nid in number)
2522 is
2523 l_protocol varchar2(10);
2524 l_iobound varchar2(10);
2525 l_queue_count integer;
2526 l_queue_name varchar2(100);
2527 l_wf_schema varchar2(320);
2528 l_timeout boolean;
2529 begin
2530
2531 select protocol, inbound_outbound, queue_count
2532 into l_protocol, l_iobound, l_queue_count
2533 from wf_queues
2534 where protocol = 'SMTP'
2535 and INBOUND_OUTBOUND = 'OUTBOUND'
2536 and DISABLE_FLAG = 'N';
2537
2538 -- Walk though ALL queue names to hunt for the notifications
2539 wf_queue.set_queue_names;
2540 l_wf_schema := g_wfSchema;
2541 for i in 1..l_queue_count loop
2542 -- Build the queue name from the information we know.
2543 l_queue_name := l_wf_schema||'.WF_'||l_protocol||'_'||
2544 substr(l_iobound,1,1)||'_'||to_char(i)||'_QUEUE';
2545 l_timeout := FALSE;
2546 while not l_timeout loop
2547 -- Kill all traces of the message.
2548 RemoveMessage(l_queue_name, wf_queue.account_name||':'||
2549 to_char(p_nid), l_timeout);
2550 end loop;
2551 end loop;
2552 -- Remove the messages from the default Exception queues also
2553 for i in 1..l_queue_count loop
2554 -- Build the queue name from the information we know.
2555 l_queue_name := wf_queue.enable_exception_queue('WF_'||l_protocol||
2556 '_'||substr(l_iobound,1,1)||'_'||to_char(i)||'_QUEUE');
2557 if l_queue_name is not NULL then
2558 l_timeout := FALSE;
2559 while not l_timeout loop
2560 -- Kill all traces of the message.
2561 RemoveMessage(l_queue_name, wf_queue.account_name||':'||
2562 to_char(p_nid), l_timeout);
2563 end loop;
2564 end if;
2565 end loop;
2566
2567 exception
2568 when others then
2569 wf_core.context('WF_XML','RemoveNotification',to_char(p_nid));
2570 raise;
2571 end RemoveNotification;
2572
2573
2574 -- setFistMessage
2575 -- To set the global variable g_first_message for the deqeuing
2576 -- of the SMTP queue.
2577 -- IN
2578 -- 'Y' to set the flag to TRUE
2579 procedure setFirstMessage(p_first_message IN varchar2)
2580 is
2581 begin
2582 if (upper(substrb(p_first_message, 1, 1)) in ('Y','T')) then
2583 g_first_message := TRUE;
2584 else
2585 g_first_message := FALSE;
2586 end if;
2587 end;
2588
2589 --
2590 -- getBodyPart
2591 --
2592 procedure getBodyPart(p_doc in out NOCOPY CLOB,
2593 p_nid in number,
2594 p_doctype in varchar2)
2595 is
2596 l_message varchar2(32000);
2597 l_doc_length number := 0;
2598 l_doc_end integer := 0;
2599 l_start VARCHAR2(10) := '<![CDATA[';
2600 l_end VARCHAR2(4) := ']]>';
2601 begin
2602
2603 WF_MAIL.InitFetchLOB(p_doctype, l_doc_length);
2604 l_doc_end := 0;
2605 dbms_lob.writeAppend(p_doc, length(l_start), l_start);
2606 while l_doc_end = 0 loop
2607 WF_MAIL.FetchLobContent(l_message, p_doctype, l_doc_end);
2608 l_message := replace(l_message, g_fndapi_misschr);
2609 dbms_lob.writeAppend(p_doc, length(l_message), l_message);
2610 end loop;
2611 dbms_lob.writeAppend(p_doc, length(l_end), l_end);
2612 WF_MAIL.CloseLob(p_doctype);
2613
2614 exception
2615 when others then
2616 wf_core.context('WF_XML','getBodyPart',to_char(p_nid),p_doctype);
2617 raise;
2618 end getBodyPart;
2619
2620
2621 procedure GetNLS(base_lang out NOCOPY varchar2, base_territory OUT NOCOPY VARCHAR2,
2622 base_codeset OUT NOCOPY VARCHAR2)
2623 is
2624 nls_base varchar2(100);
2625 underscore_pos integer;
2626 dot_pos integer;
2627
2628 begin
2629 select userenv('LANGUAGE')
2630 into nls_base
2631 from sys.dual;
2632
2633 underscore_pos := instr(nls_base, '_');
2634 dot_pos := instr(nls_base, '.');
2635
2636 base_lang := substr(nls_base, 1, underscore_pos -1);
2637 base_territory := substr(nls_base, underscore_pos +1,
2638 (dot_pos - underscore_pos)-1);
2639 base_codeset := substr(nls_base, dot_pos + 1);
2640
2641
2642 exception
2643 when others then
2644 wf_core.context('WF_XML','GetNLS');
2645 raise;
2646 end getNLS;
2647
2648
2649 -- SetNLS
2650 -- To set the NLS lang and territory of the current session
2651 -- IN
2652 -- language - a varchar2 of the language code
2653 -- territory - a varchar2 of the territory code.
2654 procedure SetNLS(language in VARCHAR2, territory in VARCHAR2)
2655 is
2656 l_language varchar2(30);
2657 l_territory varchar2(30);
2658 l_installed_flag varchar2(1);
2659 begin
2660 begin
2661 -- If nothing is passed in, force it to AMERICAN_AMERICA
2662 if language is null or language = '' then
2663 l_language := 'AMERICAN';
2664 end if;
2665 if territory is null or territory = '' then
2666 l_territory := 'AMERICA';
2667 end if;
2668
2669 select installed_flag
2670 into l_installed_flag
2671 from wf_languages
2672 where nls_language = language
2673 and installed_flag = 'Y';
2674
2675 l_language := ''''||language||'''';
2676 l_territory := ''''||territory||'''';
2677 exception
2678 when others then
2679 l_language := 'AMERICAN';
2680 l_territory := 'AMERICA';
2681 end;
2682
2683 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
2684 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
2685 'wf.plsql.WF_XML.SetNLS',
2686 'Setting Language {'||l_language||'} {'||
2687 l_territory||'} - Passed in {'||language||
2688 '} {'||territory||'}');
2689 end if;
2690
2691 dbms_session.set_nls('NLS_LANGUAGE' , l_language);
2692 dbms_session.set_nls('NLS_TERRITORY' , l_territory);
2693 exception
2694 when others then
2695 wf_core.context('WF_XML','SetNLS', language, territory);
2696 raise;
2697 end setNLS;
2698
2699 -- Parse the p_doc for the URL attributes and edit
2700 -- their src= reference in preperation for email.
2701 function ParseForInlineImages(msgBody IN OUT NOCOPY CLOB,
2702 nid IN number,
2703 resourceList IN OUT NOCOPY resourceList_t)
2704 return boolean
2705 is
2706
2707 imgStrPos number;
2708 value varchar2(32000);
2709 newValue varchar2(32000);
2710 origValue varchar2(4000);
2711 contentId varchar2(1000);
2712
2713 tmpIdx pls_integer;
2714 nameStart pls_integer;
2715 nameEnd pls_integer;
2716 amount number;
2717 tmpLength number;
2718
2719 imagesFound boolean := false;
2720
2721 renderType varchar2(10);
2722 resourceIdx pls_integer;
2723 fileName varchar2(1000);
2724 contentType varchar2(200);
2725 extPos pls_integer;
2726
2727 begin
2728
2729 resourceIdx := 1;
2730 resourceList.DELETE;
2731
2732 imagesFound := false;
2733
2734 tmpIdx := wf_temp_lob.getLob(g_LOBTable);
2735 for url in g_urls(nid) loop
2736 value := url.text_value;
2737 value := wf_notification.SetFrameworkAgent(value);
2738
2739 -- Check if there is a render type specification on the URL
2740 -- Remove it and set the renderType appropriately.
2741 renderType := substr(value, 1, 4);
2742 if(renderType in ('IMG:','LNK:')) then
2743 value := substr(value, 5);
2744 else
2745 renderType := null;
2746 end if;
2747
2748 if isImageReference(value, renderType) then
2749 origValue := value;
2750 value := '<IMG SRC="'||value||
2751 '" alt="'|| url.display_name||'"></IMG>';
2752 imgStrPos := dbms_lob.instr(msgBody, value, 1, 1);
2753 if imgStrPos > 0 then
2754 dbms_lob.trim(g_LOBTable(tmpIdx).temp_lob, 0);
2755 dbms_lob.copy(g_LOBTable(tmpIdx).temp_lob , msgBody,
2756 imgStrPos-1, 1, 1);
2757
2758 nameStart := instrb(origValue, '/', -1, 1);
2759 if nameStart = 0 then
2760 contentId := trim(value);
2761 fileName := contentId;
2762 contentId := replace(contentId, '.');
2763 else
2764 contentId := trim(substrb(origValue, nameStart+1 ));
2765 fileName := contentId;
2766 contentId := replace(contentId, '.');
2767 end if;
2768 contentId := contentID||'.'||trim(to_char(resourceIdx));
2769
2770 extPos := instrb(fileName, '.', -1, 1);
2771 if (extPos > 0) then
2772 contentType := 'image/'||substr(fileName, extPos+1);
2773 else
2774 contentType := 'image/*';
2775 end if;
2776
2777 newValue := '<IMG SRC="cid:'||contentId||
2778 '" alt="'|| url.display_name||
2779 '"></IMG>';
2780
2781 dbms_lob.writeAppend(g_LOBTable(tmpIdx).temp_lob,
2782 length(newValue), newValue);
2783 amount := dbms_lob.getlength(msgBody)-imgStrPos+length(value);
2784 tmpLength := dbms_lob.getlength(g_LOBTable(tmpIdx).temp_lob);
2785 dbms_lob.Copy(g_LOBTable(tmpIdx).temp_lob, msgBody, amount,
2786 tmpLength+1, imgStrPos+length(value));
2787 dbms_lob.trim(msgBody, 0);
2788 dbms_lob.append(msgBody, g_LOBTable(tmpIdx).temp_lob);
2789
2790 imagesFound := TRUE;
2791 resourceList(resourceIdx).value := origValue;
2792 resourceList(resourceIdx).contentId := contentId;
2793 resourceList(resourceIdx).fileName := fileName;
2794 resourceList(resourceIdx).contentType := contentType;
2795 resourceIdx := resourceIdx + 1;
2796 end if; -- Image TAG is in the messages body
2797 end if; -- The URL is an image reference
2798 end loop;
2799
2800 wf_temp_lob.releaseLob(g_LOBTable, tmpIdx);
2801
2802 return imagesFound;
2803 exception
2804 when others then
2805 -- Release temp LOB if any error , bug 6511028
2806 wf_temp_lob.releaseLob(g_LOBTable, tmpIdx);
2807
2808 wf_core.context('WF_XML','ParseForInlineImages',to_char(nid));
2809 raise;
2810 end ParseForInlineImages;
2811
2812 -- Adds the RESOURCE tags for the inline images.
2813 procedure addInlineImages(doc IN OUT NOCOPY CLOB,
2814 pos IN OUT NOCOPY number,
2815 attrlist IN OUT NOCOPY wf_xml_attr_table_type,
2816 nid IN number,
2817 disposition in varchar2,
2818 resourceList in resourceList_t)
2819 is
2820 extPos pls_integer;
2821 contentType varchar2(1000);
2822 value varchar2(32000);
2823 encodedURL varchar2(32000);
2824 nameStart pls_integer;
2825 contentId varchar2(1000);
2826 fileName varchar2(1000);
2827 occurance number := 1;
2828
2829 renderType varchar2(10);
2830
2831 begin
2832 attrlist.DELETE;
2833
2834 for resourceIdx in 1..resourceList.COUNT loop
2835
2836 encodedURL := wf_mail.urlEncode(resourceList(resourceIdx).value);
2837 AddElementAttribute('content-type', resourceList(resourceIdx).contentType, attrlist);
2838 AddElementAttribute('src', resourceList(resourceIdx).value, attrlist);
2839 AddElementAttribute('content-id', resourceList(resourceIdx).contentId, attrlist);
2840 AddElementAttribute('filename', resourceList(resourceIdx).fileName, attrlist);
2841 AddElementAttribute('content-disposition', disposition, attrlist);
2842
2843 pos := NewLOBTag(doc, pos, 'RESOURCE','',attrlist);
2844 pos := SkipLOBTag(doc, 'RESOURCE', pos, occurance);
2845 attrlist.DELETE;
2846
2847 end loop;
2848
2849 exception
2850 when others then
2851 wf_core.context('WF_XML','addInlineImages', to_char(nid));
2852 raise;
2853 end addInlineImages;
2854
2855
2856 -- Adds a recipient element to the XML in p_doc at position p_pos.
2857 --
2858 -- p_doc The XML document to receive the RECIPIENT element
2859 -- p_role The WF_ROLE name of the recipient
2860 -- p_type The type of recipient - to, cc or bcc
2861 -- p_name The display name for the recipient
2862 -- p_email The email address for the recipient
2863 -- p_pos The position at which the element should be added.
2864
2865 procedure addRecipient(p_doc in out nocopy varchar2,
2866 p_role in varchar2,
2867 p_type in varchar2,
2868 p_name in varchar2,
2869 p_email in varchar2,
2870 p_pos in out nocopy number)
2871 is
2872 display_name varchar2(360);
2873 email varchar2(320);
2874
2875 attrlist wf_xml_attr_table_type;
2876 occurance integer := 1;
2877
2878 begin
2879 AddElementAttribute('name', p_role, attrlist);
2880 AddElementAttribute('type', p_type, attrlist);
2881 p_pos := NewTag(p_doc, p_pos, 'RECIPIENT', '', attrlist);
2882 attrlist.DELETE;
2883 if (p_name is not null or p_name <> '') then
2884 display_name := replace(p_name, g_newLine);
2885 display_name := '<![CDATA['||display_name||']]>';
2886 else
2887 display_name := '';
2888 end if;
2889 p_pos := NewTag(p_doc, p_pos, 'NAME', display_name, attrlist);
2890 p_pos := SkipTag(p_doc, 'NAME', p_pos, occurance);
2891
2892 email := replace(p_email, g_newLine);
2893 email := '<![CDATA['||email||']]>';
2894 p_pos := NewTag(p_doc, p_pos, 'ADDRESS', email, attrlist);
2895 p_pos := SkipTag(p_doc, 'ADDRESS', p_pos, occurance);
2896
2897 p_pos := SkipTag(p_doc, 'RECIPIENT', p_pos, occurance);
2898 end;
2899
2900 -- Adds the recipients identified in p_list to the XML document
2901 -- provided in p_doc. This is a helper procedure for the processing
2902 -- of CC and BCC recipients.
2903 -- p_doc The XML Header document to be modified
2904 -- p_list the semicolon list of recipients
2905 -- p_type The type of recipient to set ("cc" or "bcc").
2906 -- p_pos The current pos in the p_doc to add the recipients. This
2907 -- value will be updated after completion to the current update point.
2908
2909 procedure addCopyRecipients(p_doc in out nocopy varchar2,
2910 p_list in varchar2,
2911 p_type in varchar2,
2912 p_pos in out nocopy integer)
2913 is
2914 copy_recipient_list WF_MAIL_UTIL.parserStack_t;
2915 atPos pls_integer;
2916
2917 display_name varchar2(360);
2918 recipient_role varchar2(320);
2919 email varchar2(320);
2920 pref varchar2(8);
2921 dummy varchar2(1000);
2922 dummy_number number;
2923 orig_system varchar2(30);
2924 orig_system_id number;
2925
2926 cursor members(rname varchar2, rorig varchar2, rorigid number) is
2927 select UR.USER_NAME, UR.USER_ORIG_SYSTEM, UR.USER_ORIG_SYSTEM_ID
2928 from WF_USER_ROLES UR
2929 where UR.ROLE_NAME = rname
2930 and UR.ROLE_ORIG_SYSTEM = rorig
2931 and UR.ROLE_ORIG_SYSTEM_ID = rorigid
2932 and ((UR.USER_NAME <> UR.ROLE_NAME) or
2933 (UR.USER_ORIG_SYSTEM <> UR.ROLE_ORIG_SYSTEM and
2934 UR.USER_ORIG_SYSTEM_ID <> UR.ROLE_ORIG_SYSTEM_ID));
2935
2936 step varchar2(200);
2937
2938 begin
2939 step := 'Initializing the copy list';
2940 copy_recipient_list.DELETE;
2941 copy_recipient_list := WF_MAIL_UTIL.strParser(p_list, ';');
2942 if (copy_recipient_list.COUNT > 0) then
2943
2944 for i in 1..copy_recipient_list.COUNT loop
2945
2946 step := 'Processing {'||copy_recipient_list(i)||'}';
2947 atPos := instrb(copy_recipient_list(i), '@', 1);
2948 if (atPos > 0) then
2949 step := 'Processing email address {'||
2950 copy_recipient_list(i)||'}';
2951 addRecipient(p_doc => p_doc, p_role => '', p_type => p_type,
2952 p_name => '', p_email => copy_recipient_list(i),
2953 p_pos => p_pos);
2954
2955 else
2956
2957 step := 'Processing role {'||copy_recipient_list(i)||'}';
2958
2959 -- Get the qualified email address but the other details
2960 -- are not needed.
2961 WF_DIRECTORY.GetRoleInfoMail(role => copy_recipient_list(i),
2962 display_name => display_name,
2963 email_address => email,
2964 notification_preference => pref,
2965 language => dummy,
2966 territory => dummy,
2967 orig_system => orig_system,
2968 orig_system_id => orig_system_id,
2969 installed_flag => dummy);
2970 if (email is not null and pref <> 'DISABLED') then
2971 step := 'Adding role {'||copy_recipient_list(i)||
2972 '} details to the document';
2973 recipient_role := EncodeEntityReference(copy_recipient_list(i));
2974 addRecipient(p_doc => p_doc,
2975 p_role => recipient_role,
2976 p_type => p_type,
2977 p_name => display_name,
2978 p_email => email,
2979 p_pos => p_pos);
2980
2981 elsif (display_name is not null) then
2982
2983 -- A null email address implies a role with members.
2984
2985 -- Recursion *could* be used here to build a list of
2986 -- single memeber roles and then call the addCopyRecipients
2987 -- to build the XML. Since there is no control then on
2988 -- cyclic references, we will traverse the list only
2989 -- at one level.
2990 for r in members(copy_recipient_list(i), orig_system,
2991 orig_system_id) loop
2992
2993 step := 'Getting member role '||r.user_name||
2994 'details to the document';
2995 WF_DIRECTORY.GetRoleInfoMail(role => r.user_name,
2996 display_name => display_name,
2997 email_address => email,
2998 notification_preference => pref,
2999 language => dummy,
3000 territory => dummy,
3001 orig_system => dummy,
3002 orig_system_id => dummy_number,
3003 installed_flag => dummy);
3004
3005 if (email is not null and pref <> 'DISABLED') then
3006 step := 'Adding member role {'||r.user_name||
3007 '} details to the document';
3008 recipient_role := EncodeEntityReference(r.user_name);
3009 addRecipient(p_doc => p_doc,
3010 p_role => recipient_role,
3011 p_type => p_type,
3012 p_name => display_name,
3013 p_email => email,
3014 p_pos => p_pos);
3015 end if;
3016 end loop; -- Memebers
3017 end if; -- role with members
3018 end if; -- Processing a role
3019 end loop;
3020 end if;
3021 exception
3022 when others then
3023 wf_core.context('WF_XML','addCopyRecipients', p_list, p_type,
3024 step);
3025 end addCopyRecipients;
3026
3027
3028 -- Sets the response template delimiters for HTML messages.
3029 --
3030 -- The delimiter string, rather than containing a set of delimiters
3031 -- to use will contain a code that maps to the delimiters to use.
3032 -- This is to avoid confusion on what this value can be set to and
3033 -- simplifies the parsing of the string.
3034 --
3035 -- Allowable Values:
3036 --
3037 -- DEFAULT or blank - Use the hard coded defaults
3038 -- APOS - '
3039 -- QUOTE - "
3040 -- BRACKET - [ ]
3041 -- IN
3042 -- delimiter_string - The code that represents the HTML delimiters
3043 -- to use.
3044 --
3045 procedure setHtmlDelimiters(delimiter_string IN VARCHAR2)
3046 is
3047 open_html_delimiter VARCHAR2(8);
3048 close_html_delimiter VARCHAR2(8);
3049 begin
3050
3051 if delimiter_string = 'DEFAULT' or delimiter_string is null then
3052 -- No delimiters, then use the hard coded defaults.
3053 open_html_delimiter := null;
3054 close_html_delimiter := null;
3055 elsif delimiter_string = 'APOS' then
3056 open_html_delimiter := '''';
3057 close_html_delimiter := '''';
3058 elsif delimiter_string = 'QUOTE' then
3059 open_html_delimiter := '"';
3060 close_html_delimiter := '"';
3061 elsif delimiter_string = 'BRACKET' then
3062 open_html_delimiter := '[';
3063 close_html_delimiter := ']';
3064 else
3065 -- Unable to recognize the value, so use the hard coded default.
3066 open_html_delimiter := null;
3067 close_html_delimiter := null;
3068 end if;
3069
3070
3071
3072 wf_mail.SetResponseDelimiters(open_text => null,
3073 close_text => null,
3074 open_html => open_html_delimiter,
3075 close_html => close_html_delimiter);
3076
3077 end setHtmlDelimiters;
3078
3079
3080 --
3081 -- GenerateDoc
3082 -- To generate the XML content for the enqueued notifications.
3083 procedure GenerateDoc (p_doc in out NOCOPY CLOB,
3084 p_pos in out NOCOPY number,
3085 p_recipient_role in varchar2,
3086 p_event_name in varchar2,
3087 p_event_key in varchar2,
3088 p_parameter_list in wf_parameter_list_t)
3089 is
3090 -- message CLOB;
3091 l_sec_policy varchar2(100);
3092 t_name varchar2(100);
3093 messageIdx pls_integer;
3094 nid NUMBER;
3095 msgbody VARCHAR2(32000);
3096 end_of_msgbody BOOLEAN;
3097 doctype VARCHAR2(100);
3098
3099 pos integer;
3100 amt number;
3101 installed VARCHAR2(1);
3102
3103 orig_system VARCHAR2(100);
3104 orig_system_id number;
3105
3106 -- <<sstomar> : nls parameters, l_nlsCurrency can be removed once
3107 -- it being removed from WFDS APIs
3108 l_nlsDateFormat VARCHAR2(120);
3109 l_nlsDateLanguage varchar2(120);
3110 l_nlsCalendar varchar2(120);
3111 l_nlsNumericCharacters varchar2(30);
3112 l_nlsSort varchar2(120);
3113 l_nlsLanguage VARCHAR2(120);
3114 l_nlsTerritory VARCHAR2(120);
3115 l_nlsCodeset VARCHAR2(30);
3116
3117 --
3118 l_nlsCurrency VARCHAR2(30);
3119
3120 -- whether context has been changes or not.
3121 l_context_changed BOOLEAN := false;
3122
3123 nidStr varchar2(100);
3124 hdrxml varchar2(32000);
3125 hdrxmlPos integer;
3126
3127 access_key VARCHAR2(100);
3128 priority NUMBER;
3129 recipient_role VARCHAR2(100);
3130 status VARCHAR2(100);
3131 subject VARCHAR2(4000);
3132
3133 role VARCHAR2(100);
3134 display_name VARCHAR2(200);
3135 email VARCHAR2(1000);
3136 notification_pref VARCHAR2(100);
3137
3138 occurance integer := 1;
3139 attrlist wf_xml_attr_table_type;
3140 str varchar2 (250);
3141 nodeName varchar2(100) := '#NODE';
3142 agent varchar2(100) := '#AGENT';
3143 replyto varchar2(100) := '#REPLYTO';
3144 fromName varchar2(100) := '#FROM';
3145 disposition varchar2(100) := '#DISPOSITION';
3146 directResponse varchar2(1);
3147 emailParser varchar2(100);
3148 corrId varchar2(128);
3149 htmlfilename varchar2(100);
3150 urlfilename varchar2(100);
3151 inlineAtt varchar2(10);
3152 sendAccessKey varchar2(10);
3153 stylesheetEnabled varchar2(10);
3154 body_atth varchar2 (32000);
3155 messageType varchar2(8);
3156 messageName varchar2(30);
3157 error_result varchar2 (2000);
3158 err_name varchar2 (30);
3159 err_message varchar2 (2000);
3160 err_stack varchar2 (4000);
3161 moreInfoRole varchar2(320);
3162
3163 frameworkContent boolean;
3164 attachInlineImages varchar2(1);
3165
3166 ntfURL varchar2(2000);
3167 imgFound boolean;
3168
3169 bodyToken varchar2(1);
3170
3171 FromInAttr varchar2(1);
3172 ReplyToInAttr varchar2(1);
3173 EnableStyleInAttr varchar2(1);
3174 dummy varchar2(10);
3175
3176 cc_list varchar2(4000);
3177 bcc_list varchar2(4000);
3178
3179 delimiter_string VARCHAR2(8);
3180
3181 resourceList resourceList_t;
3182
3183 begin
3184
3185 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3186 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3187 'wf.plsql.WF_XML.generateDoc', 'BEGIN');
3188 end if;
3189
3190 nid := to_number(p_event_key);
3191
3192 -- retrive base nls parameters
3193 -- Get the Base NLS.
3194 -- 4743123 Only set the value of base NLS params once in a session.
3195 -- <<sstomar>>: already being set in GENERATE function,
3196
3197 -- Obtain notification information
3198 begin -- 3741599 no_data_found should exit gracefully.
3199 select ACCESS_KEY, PRIORITY, STATUS, MESSAGE_TYPE,
3200 MESSAGE_NAME, MORE_INFO_ROLE
3201 into access_key, priority, status, messageType,
3202 messageName, moreInfoRole
3203 from WF_NOTIFICATIONS
3204 where NOTIFICATION_ID = nid;
3205 exception
3206 when no_data_found then
3207 -- 4104735 Empty documents now provide a document type and
3208 -- if a empty document, must provide a reason.
3209
3210 -- <<sstomar>>: Not changing default Lang. territory settings:
3211 -- FOR BUG 7578922
3212 AddElementAttribute('nid', nid, attrlist);
3213 AddElementAttribute('language', 'AMERICAN', attrlist);
3214 AddElementAttribute('territory', 'AMERICA', attrlist);
3215 AddElementAttribute('codeset', 'UTF8', attrlist);
3216
3217 -- Added below default base parameters.
3218 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
3219 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
3220 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
3221 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
3222
3223 AddElementAttribute('full-document', 'N', attrlist);
3224 AddElementAttribute('reason', 'no_data_found', attrlist);
3225 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATION', '', attrlist);
3226 attrlist.DELETE;
3227 p_pos := SkipLOBTag(p_doc, 'NOTIFICATION', p_pos, occurance);
3228
3229 return;
3230 when others then
3231 wf_core.context('WF_XML','GenerateDoc',to_char(nid));
3232 raise;
3233 end;
3234
3235 if (wf_mail.test_flag = TRUE) then
3236 if (status not in ('OPEN','CANCELED','CLOSED')) then
3237 status := 'OPEN';
3238 end if;
3239 end if;
3240
3241 recipient_role := p_recipient_role;
3242
3243 -- <<sstomar>> :
3244 -- Obtain recipient's NLS information by using new API
3245 WF_DIRECTORY.GetRoleInfoMail2(recipient_role, display_name, email,
3246 notification_pref,
3247 orig_system,
3248 orig_system_id,
3249 installed,
3250 l_nlsLanguage ,
3251 l_nlsTerritory ,
3252 l_nlsDateFormat ,
3253 l_nlsDateLanguage ,
3254 l_nlsCalendar ,
3255 l_nlsNumericCharacters ,
3256 l_nlsSort ,
3257 l_nlsCurrency );
3258
3259
3260 if notification_pref in ('QUERY', 'SUMMARY','SUMHTML', 'DISABLED')
3261 or email is null then
3262 -- 4104735 Empty documents now provide a document type and
3263 -- if a empty document, must provide a reason.
3264 AddElementAttribute('nid', nid, attrlist);
3265 AddElementAttribute('language', 'AMERICAN', attrlist);
3266 AddElementAttribute('territory', 'AMERICA', attrlist);
3267 AddElementAttribute('codeset', 'UTF8', attrlist);
3268
3269 -- Added below default base parameters.
3270 AddElementAttribute('nlsDateFormat', wf_core.nls_date_format, attrlist);
3271 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
3272 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
3273 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
3274
3275 AddElementAttribute('full-document', 'N', attrlist);
3276 AddElementAttribute('reason', 'NOTIFICATION_PREFERENCE:'||
3277 notification_pref, attrlist);
3278 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATION', '', attrlist);
3279 attrlist.DELETE;
3280 p_pos := SkipLOBTag(p_doc, 'NOTIFICATION', p_pos, occurance);
3281
3282 return;
3283 end if;
3284
3285
3286 corrId := wf_event.getValueForParameter('Q_CORRELATION_ID',
3287 p_parameter_list);
3288 -- Obtain the values for the configurable items
3289 nodename := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
3290 pCorrId => corrId,
3291 pName => 'NODENAME',
3292 pInAttr => dummy);
3293
3294 agent := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
3295 pCorrId => corrId,
3296 pName => 'HTMLAGENT',
3297 pInAttr => dummy);
3298
3299 fromName := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
3300 pCorrId => corrId,
3301 pName => 'FROM',
3302 pInAttr => FromInAttr);
3303
3304 replyto := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
3305 pCorrId => corrId,
3306 pName => 'REPLYTO',
3307 pInAttr => ReplyToInAttr);
3308
3309 inlineAtt := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
3310 pCorrId => corrId,
3311 pName => 'INLINE_ATTACHMENT',
3312 pInAttr => dummy);
3313
3314 sendAccessKey := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
3315 pCorrId => corrId,
3316 pName => 'SEND_ACCESS_KEY',
3317 pInAttr => dummy);
3318
3319 stylesheetEnabled := wf_mailer_parameter.getValueForCorr(pNid => nid,
3320 pCorrId => corrId,
3321 pName => 'ENABLE_STYLESHEET',
3322 pInAttr => EnableStyleInAttr);
3323
3324 -- 5393647 - Parameter to control the text/html response
3325 -- template delimiter
3326 delimiter_string := wf_mailer_parameter.getValueForCorr(pNId => nid,
3327 pCorrId => corrId,
3328 pName => 'HTML_DELIMITER',
3329 pInAttr => dummy);
3330
3331 setHtmlDelimiters(upper(trim(delimiter_string)));
3332
3333 -- 4676402 Support for CC and BCC. These are not configuration parameters
3334 -- so the values can not be retrieved through the wf_mailer_parameter
3335 -- interface.
3336 -- The precedence will be only for normal notifications. Requests
3337 -- for more information will not be subject to the cc and bcc
3338 -- handling.
3339 -- moreInfoRole is null : either FIRST_SEND or wf.notification.answer event.
3340 if (moreInfoRole is null) then
3341 begin
3342 cc_list := upper(Wf_Notification.GetAttrText(nid, '#WFM_CC'));
3343 exception
3344 when others then
3345 if (wf_core.error_name = 'WFNTF_ATTR') then
3346 wf_core.clear();
3347 cc_list := null;
3348 else
3349 raise;
3350 end if;
3351 end;
3352
3353 begin
3354 bcc_list := upper(Wf_Notification.GetAttrText(nid, '#WFM_BCC'));
3355 exception
3356 when others then
3357 if (wf_core.error_name = 'WFNTF_ATTR') then
3358 wf_core.clear();
3359 bcc_list := null;
3360 else
3361 raise;
3362 end if;
3363 end;
3364 end if;
3365 -- Direct Response is not reconfigurable through the message attributes
3366 -- Use the standard API to obtain its value.
3367 -- They are not configurable at the message level because of the
3368 -- confusion caused with multiple mailers and especially those that
3369 -- share the same correlation ID. The value must be consisten in the
3370 -- PL/SQL layer as well as the Java layer.
3371 directResponse := WF_MAILER_PARAMETER.getValueForCorr(pCorrId => corrId,
3372 pName => 'DIRECT_RESPONSE');
3373
3374 attachInlineImages := WF_MAILER_PARAMETER.GetValueForCorr (
3375 pCorrId => corrId,
3376 pName => 'ATTACH_IMAGES');
3377 if inlineAtt = 'Y' then
3378 disposition := 'inline';
3379 else
3380 disposition := 'attachment';
3381 end if;
3382
3383 if sendAccessKey = 'Y' then
3384 wf_mail.Send_Access_Key_On;
3385 else
3386 wf_mail.Send_Access_Key_Off;
3387 end if;
3388
3389 if directResponse = 'Y' then
3390 wf_mail.direct_response_on;
3391 else
3392 wf_mail.direct_response_off;
3393 end if;
3394
3395 -- If we are here, we are going to generate notification xml payload
3396 -- So allocate TEMP LOB now. << bug 6511028 >>
3397 messageIdx := wf_temp_lob.getLob(g_LOBTable);
3398
3399 WF_MAIL.setContext(nid);
3400
3401 -- Set the preferred document type based on the
3402 -- notification preference.
3403 if notification_pref = 'MAILTEXT' then
3404 doctype := g_ntfDocText;
3405 elsif notification_pref in ('MAILHTML','MAILATTH','MAILHTM2') then
3406 doctype := g_ntfDocHtml;
3407 end if;
3408
3409 -- bug 5456241 : Passing doctype parameter
3410 if (WF_NOTIFICATION.isFwkRegion(nid, doctype)='Y' and
3411 g_install ='EMBEDDED') then
3412
3413 frameworkContent := TRUE;
3414 -- 3803327 Text email with framework is currently disabled
3415 -- until the issues with the region facet for text can be
3416 -- fixed.
3417 -- if (notification_pref = 'MAILTEXT') then
3418 -- notification_pref := 'MAILHTM2';
3419 -- elsif (notification_pref = 'MAILATTH') then
3420 -- notification_pref := 'MAILHTML';
3421 -- end if;
3422 -- 3803327 end.
3423 else
3424 frameworkContent := FALSE;
3425 end if;
3426
3427 -- Get the language, territory and codeset for this notification
3428 -- If #WFM_* not defined or not installd, then user's language will be used
3429 -- If user's language also not installed then below API updates OUT params
3430 -- with base language, territory and charset etc..
3431 --
3432 -- TODO : Get_Ntf_Language : optimization required.
3433 WF_MAIL.Get_Ntf_Language(nid, l_nlsLanguage, l_nlsTerritory, l_nlsCodeset);
3434
3435 -- Set NLS language and territory for this notification
3436 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3437 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3438 'wf.plsql.WF_XML.generateDoc',
3439 'Setting User NLS {'|| l_nlsLanguage ||'} {'||l_nlsTerritory||'}'
3440 || l_nlsDateFormat || '} {' || l_nlsDateLanguage || '} {'
3441 || '} {' || l_nlsCalendar || '} {' || l_nlsNumericCharacters
3442 || '} {' || l_nlsSort || '}');
3443 end if;
3444
3445 -- set user's language and territory : charset we can not chage for a session at DB layer.
3446 -- setNLS(l_nlsLanguage, l_nlsTerritory);
3447
3448
3449
3450 if( nvl(l_nlsLanguage, 'AMERICA') <> g_base_language or
3451 NVL( l_nlsTerritory, 'AMERICAN') <> g_base_territory or
3452 nvl(l_nlsDateFormat , wf_core.nls_date_format) <> g_base_nlsDateFormat or
3453 nvl(l_nlsDateLanguage, wf_core.nls_date_language) <> g_base_nlsDateLanguage or
3454 nvl(l_nlsNumericCharacters, wf_core.nls_numeric_characters) <> g_base_nlsNumericCharacters or
3455 nvl(l_nlsSort, wf_core.nls_sort) <> g_base_nlsSort ) then
3456
3457 -- nid, l_nlsCalendar, just set here only.
3458 -- at other places pass value as null.
3459 WF_NOTIFICATION_UTIL.SetNLSContext(nid,
3460 l_nlsLanguage ,
3461 l_nlsTerritory ,
3462 l_nlsDateFormat ,
3463 l_nlsDateLanguage ,
3464 l_nlsNumericCharacters ,
3465 l_nlsSort ,
3466 l_nlsCalendar );
3467
3468 l_context_changed := true;
3469 else
3470
3471 -- No need to SET context but set NID, Calendar as these two parameters
3472 -- are being used in WF_NOTIFICATION_UTIL.GetCalendarDate
3473 WF_NOTIFICATION_UTIL.setCurrentNID(nid);
3474 WF_NOTIFICATION_UTIL.setCurrentCalendar(l_nlsCalendar);
3475
3476 END if;
3477
3478
3479 -- Initialise the XML Document and then progressively walk
3480 -- through the elements. Populating them as we go.
3481 -- l_pos is crucial as it determines where the next nodes
3482 -- will be placed.
3483 pos := p_pos;
3484
3485 if frameworkContent = TRUE then
3486 -- Get a modified version of the message. All is rendered
3487 -- except for the &BODY token.
3488 -- NOTE: TEMP LOBs allocated within WF_MAIL.GetLobMessage3 for
3489 -- message body contents should be released here
3490 -- after processsing
3491 WF_MAIL.GetLobMessage3(nid, nodeName, agent, replyto,
3492 recipient_role, l_nlsLanguage, l_nlsTerritory,
3493 notification_pref, email,
3494 display_name,
3495 'N',
3496 subject, body_atth,
3497 error_result, bodyToken);
3498
3499 else
3500 WF_MAIL.GetLobMessage3(nid, nodeName, agent, replyto,
3501 recipient_role, l_nlsLanguage, l_nlsTerritory,
3502 notification_pref, email,
3503 display_name,
3504 'Y',
3505 subject, body_atth,
3506 error_result, bodyToken);
3507
3508 end if;
3509
3510 if error_result is not null or error_result <> '' then
3511 wf_core.token('ERROR',error_result);
3512 wf_core.raise('WFMLR_GENERATE_FAILED');
3513 end if;
3514
3515 g_htmlmessage := wf_core.translate('WF_HTML_MESSAGE');
3516 g_urlNotification := wf_core.translate('WF_URL_NOTIFICATION');
3517 g_urlListAttachment := wf_core.translate('WF_URLLIST_ATTACHMENT');
3518
3519 -- Reset base NLS settings
3520 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3521 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3522 'wf.plsql.WF_XML.generateDoc',
3523 'Re-Setting Base NLS {'|| g_base_language ||'} {'||g_base_territory||'}'
3524 || g_base_nlsDateFormat || '} {' || g_base_nlsDateLanguage || '} {'
3525 || '} {' || g_base_nlsCalendar || '} {' || g_base_nlsNumericCharacters
3526 || '} {' || g_base_nlsSort || '}');
3527 end if;
3528
3529
3530 -- RESET base setting so that all XML generation
3531 -- processing would be in DEFAULT settings
3532 -- << sstomar>> : RESETTING for base NLS can be done once ..
3533 -- after generating XML Payload but problem may be that
3534 -- Mailer which runs on default NLS may not be able to parse payload??
3535 -- TODO : need to check above case.
3536 if(l_context_changed ) then
3537
3538 -- set nid, calendar once only.
3539 -- <<bug 8220816>> : keep WF_NOTIFICATION_UTIL.g_nid and g_calendar in global variable
3540 -- during life-life cycle of this API.
3541 WF_NOTIFICATION_UTIL.SetNLSContext(
3542 nid,
3543 g_base_language ,
3544 g_base_territory ,
3545 g_base_nlsDateFormat ,
3546 g_base_nlsDateLanguage ,
3547 g_base_nlsNumericCharacters ,
3548 g_base_nlsSort ,
3549 g_base_nlsCalendar );
3550
3551 end if;
3552
3553 htmlfilename := g_htmlmessage||'.html';
3554 urlfilename := g_urlNotification||'.html';
3555
3556 nidStr := 'NID['||to_char(nid)||'/'||access_key||'@'||nodeName||']';
3557 if directResponse = 'Y' then
3558 nidStr := nidStr||'[2]';
3559 end if;
3560
3561 AddElementAttribute('nid', p_event_key, attrlist);
3562 AddElementAttribute('nidstr', nidStr, attrlist);
3563
3564 AddElementAttribute('language', l_nlsLanguage, attrlist);
3565 AddElementAttribute('territory', l_nlsTerritory, attrlist);
3566 AddElementAttribute('codeset', l_nlsCodeset, attrlist);
3567 --
3568 -- <<sstomar>> : NLS changes, bug 7578922
3569 AddElementAttribute('nlsDateformat', l_nlsDateFormat, attrlist);
3570
3571 -- << REMOVE validation later> we can validate if date_language is installed or not.
3572 if(WF_NOTIFICATION_UTIL.isLanguageInstalled(l_nlsDateLanguage)) then
3573 AddElementAttribute('nlsDateLanguage', l_nlsDateLanguage, attrlist);
3574 else
3575 AddElementAttribute('nlsDateLanguage', l_nlsLanguage, attrlist);
3576 end if;
3577
3578 AddElementAttribute('nlsNumericCharacters', l_nlsNumericCharacters, attrlist);
3579 AddElementAttribute('nlsSort', l_nlsSort, attrlist);
3580
3581 AddElementAttribute('priority', to_char(priority), attrlist);
3582 AddElementAttribute('item_type', messageType, attrlist);
3583 AddElementAttribute('message_name', messageName, attrlist);
3584 AddElementAttribute('full-document', 'Y', attrlist);
3585
3586 pos := NewLOBTag(p_doc, pos, 'NOTIFICATION', '', attrlist);
3587 attrlist.DELETE;
3588
3589 hdrxmlPos := 0;
3590 hdrxml := '';
3591
3592 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'RECIPIENTLIST', '', attrlist);
3593
3594 -- 4676402 Adding support for CC and BCC. The recipients are
3595 -- straight email addresses in a semi-colon seperated list.
3596 -- Commas should not be used as delimiters as they can appear in the
3597 -- email address.
3598
3599 recipient_role := EncodeEntityReference(recipient_role);
3600 addRecipient(p_doc => hdrxml,
3601 p_role => recipient_role,
3602 p_type => 'to',
3603 p_name => display_name,
3604 p_email => email,
3605 p_pos => hdrxmlPos);
3606
3607 addCopyRecipients(hdrxml, cc_list, 'cc', hdrxmlPos);
3608 addCopyRecipients(hdrxml, bcc_list, 'bcc', hdrxmlPos);
3609
3610 hdrxmlPos := SkipTag(hdrxml, 'RECIPIENTLIST', hdrxmlPos, occurance);
3611
3612 -- 3692786 Only if the FROM and REPLYTO are defined as message
3613 -- attributes will they be put on the XML. Otherwise it will
3614 -- be up to what is defined for the mailer.
3615 if FromInAttr = 'Y' or ReplyToInAttr = 'Y' then
3616 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'FROM', '', attrlist);
3617
3618 if FromInAttr = 'Y' then
3619 fromName := replace(fromName, g_newLine);
3620 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'NAME', fromName, attrlist);
3621 hdrxmlPos := SkipTag(hdrxml, 'NAME', hdrxmlPos, occurance);
3622 end if;
3623 if ReplyToInAttr = 'Y' then
3624 replyto := replace(replyto, g_newLine);
3625 replyto := '<![CDATA['||replyto||']]>';
3626 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'ADDRESS', replyto,
3627 attrlist);
3628 hdrxmlPos := SkipTag(hdrxml, 'ADDRESS', hdrxmlPos, occurance);
3629 end if;
3630 hdrxmlPos := SkipTag(hdrxml, 'FROM', hdrxmlPos, occurance);
3631 end if;
3632
3633 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'STATUS', status, attrlist);
3634 hdrxmlPos := SkipTag(hdrxml, 'STATUS', hdrxmlPos, occurance);
3635
3636 subject := replace(subject, g_newLine);
3637 subject := '<![CDATA['||subject||']]>';
3638 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'SUBJECT', subject, attrlist);
3639
3640 pos := NewLOBTag(p_doc, pos, 'HEADER', hdrxml, attrlist);
3641 pos := SkipLOBTag(p_doc, 'HEADER', pos, occurance);
3642
3643 -- <<sstomar bug 6993909>> : to get #WF_SECURITY_POLICY
3644 --- Below API returns Template Name based on l_sec_policy . So if 'OPEN_MAIL_SECURE'
3645 -- it means user should view online version of ntf but user will
3646 -- get "notification detail.html" as attachement.
3647 Wf_Mail.ProcessSecurityPolicy(nid, l_sec_policy, t_name);
3648
3649
3650 /*
3651 ** Potentially, it could be possible for a text/plain notification
3652 ** but that would mean looking ahead to ensure that there are
3653 ** absolutely no attachments of any description.
3654 */
3655 /*
3656 ** The body part section of the XML structure will contain
3657 ** a <![CDATA ]]> construct which removes the need to URL
3658 ** encode the data.
3659 */
3660 if notification_pref in ('MAILTEXT','MAILATTH') then
3661 /*
3662 ** MAILTEXT and MAILATTH will have the text/plain as the
3663 ** primary messasge content. The others will be in the
3664 ** from of an attachment.
3665 */
3666 dbms_lob.trim(g_LOBTable(messageIdx).temp_lob, 0);
3667
3668 -- This getBodyPart API releases temp lob allocated within
3669 -- WF_MAIL.GetLobMessage3 for doctype (text/plain )
3670 -- i.e. g_text_messageIdx locator
3671 getBodyPart(g_LOBTable(messageIdx).temp_lob, nid,
3672 g_ntfDocText);
3673
3674 -- bug 6196382 :
3675 -- Outer structure i.e. <CONTENT tag>'s content-type for fwk based ntf.
3676 -- should be multipart/related; otherwise Thunderbird email client
3677 -- will show text/html body part also with text/plain for MAILATTH user
3678 --
3679
3680 -- << sstomar bug 6993909 >> :
3681 -- Always use 'multipart/mixed' with CONTENT tag for 'MAILTEXT','MAILATTH'.
3682 -- It should also be used when #WF_SECURITY_POLICY=NO_EMAIL
3683 -- i.e. t_name (Template name) ='OPEN_MAIL_SECURE'
3684 AddElementAttribute('content-type', 'multipart/mixed', attrlist);
3685
3686
3687 pos := NewLOBTag(p_doc, pos, 'CONTENT', '', attrlist);
3688 attrlist.DELETE;
3689
3690 -- -- BODYPART TAG: This text/plain is a first body part for
3691 -- MAILATTH and MAILTEXT users.
3692
3693 AddElementAttribute('content-type', g_ntfDocText, attrlist);
3694
3695 pos := NewLOBTag(p_doc, pos, 'BODYPART', '', attrlist);
3696
3697 -- Same Content-Type with message TAG as there won't be Images or
3698 -- Other resources referring within first message BODY.
3699 pos := NewLOBTag(p_doc, pos, 'MESSAGE',
3700 g_LOBTable(messageIdx).temp_lob, attrlist);
3701
3702 pos := SkipLOBTag(p_doc, 'MESSAGE', pos, occurance);
3703
3704 if frameworkContent = TRUE and bodyToken = 'Y' then
3705 -- Build the resource section of the XML so that the
3706 -- java layer can locate the notification body to
3707 -- merge into the template.
3708
3709 ntfURL := wf_mail.urlEncode(wf_notification.getFwkBodyURL2(nid,
3710 g_ntfDocText,
3711 l_nlsLanguage,
3712 l_nlsCalendar));
3713
3714 AddElementAttribute('page-type','fwk', attrlist);
3715 AddElementAttribute('src',ntfURL, attrlist);
3716 if EnableStyleInAttr = 'Y' then
3717 AddElementAttribute('enable-stylesheet', stylesheetEnabled,
3718 attrlist);
3719 end if;
3720
3721 -- <<sstomar>>: These parameters may be redundant as Notification
3722 -- level parameter would be used for NLS context at java layer
3723 AddElementAttribute('language',l_nlsLanguage, attrlist);
3724 AddElementAttribute('territory',l_nlsTerritory, attrlist);
3725
3726 AddElementAttribute('token', 'BODY', attrlist);
3727
3728
3729 pos := NewLOBTag(p_doc, pos, 'RESOURCE','',attrlist);
3730 attrlist.DELETE;
3731 pos := SkipLOBTag(p_doc, 'RESOURCE', pos, occurance);
3732 end if;
3733
3734 pos := SkipLOBTag(p_doc, 'BODYPART', pos, occurance);
3735 attrlist.DELETE;
3736 end if; -- END for 'MAILTEXT','MAILATTH'
3737
3738 if notification_pref in ('MAILHTML','MAILATTH','MAILHTM2') then
3739
3740 --
3741 -- The HTML version of the message is only available
3742 -- to MAILHTML and MAILATTH recipients.
3743 -- MAILHTML2 is a text/html message without the additional
3744 -- two framed "Notification Detail.html" attachment, but other attachement
3745 -- may be available.
3746 --
3747 dbms_lob.trim(g_LOBTable(messageIdx).temp_lob, 0);
3748
3749 -- This getBodyPart API releases temp lob allocated within
3750 -- WF_MAIL.GetLobMessage3 for doctype (text/html )
3751 -- i.e. g_html_messageIdx locator
3752 getBodyPart(g_LOBTable(messageIdx).temp_lob, nid,
3753 g_ntfDocHtml);
3754
3755 imgFound := FALSE;
3756 resourceList.DELETE;
3757
3758 if frameworkContent = FALSE AND attachInlineImages = 'Y' then
3759 imgFound := ParseForInlineImages(g_LOBTable(messageIdx).temp_lob,
3760 nid, resourceList);
3761 end if;
3762
3763 --
3764 -- The content-type for the CONTENT tag is based on a set of rules.
3765 -- It can only be multiplart/mixed or multiplart/related if it is a framework region,
3766 -- or there is an inline image. Inline images and framework regions are
3767 -- only allowed for HTML type notifications.
3768 --
3769 -- 4481199 - If the prefernce is MAILATTH, then the CONTENT
3770 -- element is already defined.
3771
3772 -- << sstomar, bug6993909 : commenting below code block >>
3773 -- if (notification_pref in ('MAILHTML', 'MAILHTM2')) then
3774 -- if(frameworkContent = TRUE or imgFound = TRUE) then
3775 -- AddElementAttribute('content-type', 'multipart/related', attrlist);
3776 -- else
3777 -- AddElementAttribute('content-type', 'multipart/mixed', attrlist);
3778 -- end if;
3779 --
3780 -- pos := NewLOBTag(p_doc, pos, 'CONTENT', '', attrlist);
3781 -- attrlist.DELETE;
3782 -- end if;
3783
3784 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3785 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3786 'wf.plsql.WF_XML.generateDoc',
3787 ' Template Name returned by Wf_Mail.ProcessSecurityPolicy: [' || t_name || ']' );
3788
3789 if (frameworkContent ) then
3790 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3791 'wf.plsql.WF_XML.generateDoc', ' framework-Content ?: YES') ;
3792 else
3793 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3794 'wf.plsql.WF_XML.generateDoc', ' framework-Content ?: NO') ;
3795 end if;
3796 end if;
3797
3798 -- << sstomar bug 6993909>> :
3799 -- CASE 1 : MAILHTM2
3800 if ( notification_pref in ('MAILHTM2') ) then
3801
3802 -- MAILHTM2, text/html only be exist as a FIRST body part but may have
3803 -- additional attachements EXCEPT "Notification Detail.html".
3804
3805 -- For CONTENT tag.
3806 if ((frameworkContent = true or imgFound = true) and
3807 ( t_name is null or t_name <>'OPEN_MAIL_SECURE') ) then
3808
3809 AddElementAttribute('content-type', 'multipart/related', attrlist);
3810 else
3811 -- NOT a Fwk Content:
3812 -- MAILHTM2 may have INLINE / attachements resources.
3813 AddElementAttribute('content-type', 'multipart/mixed', attrlist);
3814 end if;
3815
3816 pos := NewLOBTag(p_doc, pos, 'CONTENT', '', attrlist);
3817 attrlist.DELETE;
3818
3819 -- For BODYPART tag
3820 -- NOTE : This would be a first BODY part so SET it text/html
3821 AddElementAttribute('content-type', 'text/html', attrlist);
3822
3823 -- CASE 2: MAILHTML always will have "Notification Detail.html" attachement
3824 elsif (notification_pref in ('MAILHTML') ) then
3825
3826 -- No need to check t_name ==>'OPEN_MAIL_SECURE' because
3827 -- "Notification Detail.html" always be there for MAILHTML.
3828 AddElementAttribute('content-type', 'multipart/mixed', attrlist);
3829
3830 pos := NewLOBTag(p_doc, pos, 'CONTENT', '', attrlist);
3831 attrlist.DELETE;
3832
3833 -- For BODYPART tag
3834 if ( (frameworkContent = true or imgFound = true) and
3835 ( t_name is null or t_name <>'OPEN_MAIL_SECURE') ) then
3836
3837 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3838 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3839 'wf.plsql.WF_XML.generateDoc',
3840 'Setting BODYPART content-type multipart/related');
3841 end if;
3842
3843 -- Set Content-Type = multipart/related because this BODY MAY have
3844 -- other related body-parts which make aggregate body OBJECT ...
3845 AddElementAttribute('content-type', 'multipart/related', attrlist);
3846 else
3847 -- NO Fwk /Image ref : default text/html
3848 AddElementAttribute('content-type', 'text/html', attrlist);
3849 end if;
3850
3851 -- CASE 3: MAILATTH
3852 else
3853 -- Content-Type for CONTENT tag has already been set.
3854
3855 -- For MAILATTH : text/html msg body would be seen as attachement
3856 -- + "Notification Detail.html"
3857 -- BUT text/html will have references of Images / Stylesheets
3858 -- ( NOT be sent as INLINE attachment).
3859
3860 -- For BODYPART tag
3861 AddElementAttribute('content-type', 'text/html', attrlist);
3862
3863 end if;
3864
3865 pos := NewLOBTag(p_doc, pos, 'BODYPART', '', attrlist);
3866 attrlist.DELETE;
3867
3868 -- FOR MESSAGE tag
3869 AddElementAttribute('content-type', g_ntfDocHtml, attrlist);
3870
3871 if notification_pref = 'MAILATTH' then
3872
3873 -- The text/html will be an attachment for MAILTEXT
3874 AddElementAttribute('content-disposition',disposition, attrlist);
3875 AddElementAttribute('filename',htmlfilename, attrlist);
3876 end if;
3877
3878 pos := NewLOBTag(p_doc, pos, 'MESSAGE',
3879 g_LOBTable(messageIdx).temp_lob, attrlist);
3880 pos := SkipLOBTag(p_doc, 'MESSAGE', pos, occurance);
3881
3882 if frameworkContent = TRUE and bodyToken = 'Y' then
3883 -- Build the resource section of the XML so that the
3884 -- java layer can locate the notification body to
3885 -- merge into the template.
3886
3887 ntfURL := wf_mail.urlEncode(wf_notification.getFwkBodyURL2(nid,
3888 g_ntfDocHtml,
3889 l_nlsLanguage,
3890 l_nlsCalendar));
3891
3892
3893 AddElementAttribute('page-type','fwk', attrlist);
3894 AddElementAttribute('src',ntfURL, attrlist);
3895 if EnableStyleInAttr = 'Y' then
3896 AddElementAttribute('enable-stylesheet', stylesheetEnabled,
3897 attrlist);
3898 end if;
3899
3900 AddElementAttribute('language', l_nlsLanguage, attrlist);
3901 AddElementAttribute('territory', l_nlsTerritory, attrlist);
3902 AddElementAttribute('token', 'BODY', attrlist);
3903
3904
3905 pos := NewLOBTag(p_doc, pos, 'RESOURCE','',attrlist);
3906 attrlist.DELETE;
3907 pos := SkipLOBTag(p_doc, 'RESOURCE', pos, occurance);
3908 elsif (frameworkContent = FALSE AND imgFound = TRUE) then
3909 -- Add RESOURCE tags for each of the images pased in
3910 -- in the ParseForInlineImages
3911 addInlineImages(p_doc, pos, attrlist, nid, disposition,
3912 resourceList);
3913 end if;
3914
3915 pos := SkipLOBTag(p_doc, 'BODYPART', pos, occurance);
3916 attrlist.DELETE;
3917 end if;
3918
3919 if notification_pref in ('MAILHTML','MAILATTH') then
3920 /*
3921 ** Adding the text/html component to the notification.
3922 ** This is the little two framed representation of the
3923 ** notification.
3924 **
3925 ** This is only available for the MAILHTML and MAILATTH recipients.
3926 */
3927 AddElementAttribute('content-type',g_ntfDocHtml, attrlist);
3928 pos := NewLOBTag(p_doc, pos, 'BODYPART', '', attrlist);
3929
3930 body_atth := '<![CDATA['||body_atth||']]>';
3931 AddElementAttribute('content-disposition',disposition, attrlist);
3932 AddElementAttribute('filename',urlfilename, attrlist);
3933 pos := NewLOBTag(p_doc, pos, 'MESSAGE', body_atth, attrlist);
3934 pos := SkipLOBTag(p_doc, 'MESSAGE', pos, occurance);
3935 pos := SkipLOBTag(p_doc, 'BODYPART', pos, occurance);
3936 attrlist.DELETE;
3937 end if;
3938
3939
3940 -- Bug 5379861: Notification Reference section and Attachements of a pl/sql
3941 -- notificaton appears as Non-Translated.
3942 -- Set NLS language and territory for this notification
3943 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3944 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3945 'wf.plsql.WF_XML.generateDoc',
3946 'Setting User NLS {'|| l_nlsLanguage ||'} {'||l_nlsTerritory||'}'
3947 || l_nlsDateFormat || '} {' || l_nlsDateLanguage || '} {'
3948 || '} {' || l_nlsCalendar || '} {' || l_nlsNumericCharacters
3949 || '} {' || l_nlsSort || '}');
3950 end if;
3951
3952 -- Set notification /user language before processing attachements.
3953 -- SetNLS(l_nlsLanguage, l_nlsTerritory);
3954 if(l_context_changed ) then
3955
3956 -- l_nlsCalendar only will be stored in global variable
3957 WF_NOTIFICATION_UTIL.SetNLSContext(
3958 nid,
3959 l_nlsLanguage ,
3960 l_nlsTerritory ,
3961 l_nlsDateFormat ,
3962 l_nlsDateLanguage ,
3963 l_nlsNumericCharacters ,
3964 l_nlsSort ,
3965 l_nlsCalendar );
3966
3967
3968 END if;
3969
3970 --
3971 -- Next will be to attach all URLs and DOCUMENT attributes
3972 -- as attachments. Disposition for all URL and DOCUMENT attributes
3973 -- with ATTACH=Y should be attachment.
3974 --
3975
3976 --
3977 -- Bug 6671568: When #WF_SECURITY_POLICY = 'NO_EMAIL' or 'ENC_EMAIL_ONLY'
3978 -- we should not send any other content related to the notification, either
3979 -- attachment or inline through e-mail.
3980 --
3981
3982 -- << sstomar : below API is being called above so t_name have assigned (null or somevalue) .
3983 -- Wf_Mail.ProcessSecurityPolicy(nid, l_sec_policy, t_name);
3984
3985 if (t_name is not null) then
3986 if (t_name <> 'OPEN_MAIL_SECURE')
3987 then
3988 pos := GetAttachment(nid, p_doc, agent, 'attachment', doctype, pos);
3989 end if;
3990 else
3991 pos := GetAttachment(nid, p_doc, agent, 'attachment', doctype, pos);
3992 end if;
3993
3994 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
3995 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
3996 'wf.plsql.WF_XML.generateDoc',
3997 'Re-Setting Base NLS {'|| g_base_language ||'} {'||g_base_territory||'}'
3998 || g_base_nlsDateFormat || '} {' || g_base_nlsDateLanguage || '} {'
3999 || '} {' || g_base_nlsCalendar || '} {' || g_base_nlsNumericCharacters
4000 || '} {' || g_base_nlsSort || '}');
4001 end if;
4002
4003 -- Bug 5379861: Reset back base language.
4004 -- SetNLS(g_base_language, g_base_territory);
4005 -- Reset base language
4006 if( l_context_changed ) then
4007
4008 WF_NOTIFICATION_UTIL.SetNLSContext
4009 (null, -- Resetting null for Nid is fine.
4010 g_base_language ,
4011 g_base_territory ,
4012 g_base_nlsDateFormat ,
4013 g_base_nlsDateLanguage ,
4014 g_base_nlsNumericCharacters ,
4015 g_base_nlsSort ,
4016 g_base_nlsCalendar );
4017 end if;
4018
4019 pos := SkipLOBTag(p_doc, 'CONTENT', pos, occurance);
4020 pos := SkipLOBTag(p_doc, 'NOTIFICATION', pos, occurance);
4021
4022 p_pos := pos;
4023 wf_temp_lob.releaseLob(g_LOBTable, messageIdx);
4024
4025
4026 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
4027 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
4028 'wf.plsql.WF_XML.generateDoc', 'END');
4029 end if;
4030 exception
4031 when others then
4032
4033 wf_temp_lob.releaseLob(g_LOBTable, messageIdx);
4034
4035 -- Since within wf_mail.getLOBMessage3 we are releasing
4036 -- TEMP LOBs incase of any exception, so there is no need to
4037 -- release those LOBs here. -- WF_MAIL.CloseLob(doctype)
4038
4039 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
4040 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
4041 'wf.plsql.WF_XML.generateDoc',
4042 'Re-Setting Base NLS {'|| g_base_language ||'} {'||g_base_territory||'}'
4043 || g_base_nlsDateFormat || '} {' || g_base_nlsDateLanguage || '} {'
4044 || '} {' || g_base_nlsCalendar || '} {' || g_base_nlsNumericCharacters
4045 || '} {' || g_base_nlsSort || '}');
4046 end if;
4047
4048 -- Reset base language, in case of exception.
4049 -- SetNLS(g_base_language, g_base_territory);
4050 -- Reset base language
4051 WF_NOTIFICATION_UTIL.SetNLSContext(
4052 null,
4053 g_base_language ,
4054 g_base_territory ,
4055 g_base_nlsDateFormat ,
4056 g_base_nlsDateLanguage ,
4057 g_base_nlsNumericCharacters ,
4058 g_base_nlsSort ,
4059 g_base_nlsCalendar );
4060
4061
4062
4063 wf_core.context('WF_XML', 'GenerateDoc', p_event_name, p_event_key);
4064 raise;
4065 end GenerateDoc;
4066
4067
4068 -- GenerateGroupDoc
4069 -- To generate the complete set of notification for a group.
4070 procedure GenerateGroupDoc(p_doc in out NOCOPY CLOB,
4071 p_pos in out NOCOPY number,
4072 p_recipient_role in varchar2,
4073 p_notification_pref in varchar2,
4074 p_orig_system in varchar2,
4075 p_orig_system_id in number,
4076 p_event_name in varchar2,
4077 p_event_key in varchar2,
4078 p_parameter_list in wf_parameter_list_t)
4079 is
4080
4081 cursor members(rname varchar2, rorig varchar2, rorigid number) is
4082 select UR.USER_NAME, UR.USER_ORIG_SYSTEM, UR.USER_ORIG_SYSTEM_ID
4083 from WF_USER_ROLES UR
4084 where UR.ROLE_NAME = rname
4085 and UR.ROLE_ORIG_SYSTEM = rorig
4086 and UR.ROLE_ORIG_SYSTEM_ID = rorigid
4087 and ((UR.USER_NAME <> UR.ROLE_NAME) or
4088 (UR.USER_ORIG_SYSTEM <> UR.ROLE_ORIG_SYSTEM and
4089 UR.USER_ORIG_SYSTEM_ID <> UR.ROLE_ORIG_SYSTEM_ID));
4090
4091 members_type members%ROWTYPE;
4092 TYPE members_table_type is TABLE OF members%ROWTYPE
4093 INDEX BY BINARY_INTEGER;
4094 i pls_integer := 1;
4095
4096 members_t members_table_type;
4097 attrlist wf_xml_attr_table_type;
4098 inAttr varchar2(1);
4099 resetNls varchar2(10);
4100 corrId varchar2(128);
4101
4102 begin
4103 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
4104 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
4105 'wf.plsql.WF_XML.generateGroupDoc', 'BEGIN');
4106 end if;
4107 i := 1;
4108 for r in members(p_recipient_role, p_orig_system, p_orig_system_id) loop
4109 members_t(i).user_name := r.user_name;
4110 members_t(i).user_orig_system:= r.user_orig_system;
4111 members_t(i).user_orig_system_id:= r.user_orig_system_id;
4112 i := i + 1;
4113 end loop;
4114
4115
4116 -- 4104735 Removing the test for "p_notification_pref not in
4117 -- ('QUERY','SUMMARY','SUMHTML', 'DISABLED')". The rule to
4118 -- send or not should come from the individual memebers and not the
4119 -- parent role. If there are simply no members then the NULL document
4120 -- should be sent. The testing of the notification preference for
4121 -- the members will be performed again in genreateDoc.
4122 if members_t.count = 0 then
4123 -- No role members. Only log it for now and change the
4124 -- notification preference to QUERY.
4125 -- ---------------------------------------------------
4126 -- wf_core.context('WF_XML','GenerateGroup', p_event_name,
4127 -- p_event_key);
4128 -- wf_core.token('NID', p_event_key);
4129 -- wf_core.token('ROLE', p_recipient_role);
4130 -- wf_core.raise('WFMLR_NOROLEMEMBERS');
4131 -- ---------------------------------------------------
4132 AddElementAttribute('maxcount', '1', attrlist);
4133 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATIONGROUP', '', attrlist);
4134 attrlist.DELETE;
4135
4136 -- 4104735 Empty documents now provide a document type and
4137 -- if a empty document, must provide a reason.
4138 AddElementAttribute('nid', p_event_key, attrlist);
4139 AddElementAttribute('language', 'AMERICAN', attrlist);
4140 AddElementAttribute('territory', 'AMERICA', attrlist);
4141 AddElementAttribute('codeset', 'UTF8', attrlist);
4142 -- Added below default base parameters.
4143 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
4144 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
4145 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
4146 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
4147
4148 AddElementAttribute('full-document', 'N', attrlist);
4149 AddElementAttribute('reason', 'no_members', attrlist);
4150 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATION', '', attrlist);
4151 attrlist.DELETE;
4152
4153 else
4154
4155 -- 4628088 Send the RESET_NLS flag if one is defined
4156 -- at the message level.
4157 corrId := wf_event.getValueForParameter('Q_CORRELATION_ID',
4158 p_parameter_list);
4159 resetNls := WF_MAILER_PARAMETER.GetValueForCorr (pNid => p_event_key,
4160 pCorrId => corrId,
4161 pName => 'RESET_NLS',
4162 pInAttr => inAttr);
4163
4164 AddElementAttribute('maxcount',to_char(members_t.count), attrlist);
4165 if(inAttr = 'Y') then
4166 AddElementAttribute('reset-nls',resetNls, attrlist);
4167 end if;
4168 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATIONGROUP', '', attrlist);
4169 attrlist.DELETE;
4170
4171 for i in 1..members_t.count loop
4172 generateDoc(p_doc, p_pos, members_t(i).user_name,
4173 p_event_name, p_event_key, p_parameter_list);
4174 end loop;
4175 end if;
4176
4177 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
4178 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
4179 'wf.plsql.WF_XML.generateGroupDoc', 'END');
4180 end if;
4181 exception
4182 when others then
4183 wf_core.context('WF_XML','GenerateGroupDoc',p_event_name, p_event_key);
4184 raise;
4185 end GenerateGroupDoc;
4186
4187 -- GenerateMessage
4188 -- To generate the XML content for a single notification
4189 procedure GenerateMessage(p_doc in out nocopy CLOB,
4190 p_event_name in varchar2,
4191 p_event_key in varchar2,
4192 p_parameter_list in wf_parameter_list_t)
4193 is
4194 nid NUMBER;
4195
4196 pos integer;
4197 amt number;
4198
4199 installed VARCHAR2(1);
4200 language VARCHAR2(100);
4201 territory VARCHAR2(100);
4202 codeset VARCHAR2(100);
4203 orig_system VARCHAR2(100);
4204 orig_system_id number;
4205
4206 recipient_role VARCHAR2(100);
4207 status VARCHAR2(100);
4208 mail_status VARCHAR2(100);
4209 str varchar2 (2000);
4210
4211 role VARCHAR2(100);
4212 display_name VARCHAR2(200);
4213 email VARCHAR2(1000);
4214 notification_pref VARCHAR2(100);
4215
4216 attrlist wf_xml_attr_table_type;
4217
4218 nodename varchar2(100);
4219 messageType varchar2(8);
4220 messageName varchar2(30);
4221
4222 inAttr varchar2(1);
4223 resetNls varchar2(10);
4224
4225 begin
4226
4227 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
4228 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
4229 'wf.plsql.WF_XML.generateMessage', 'BEGIN');
4230 end if;
4231
4232 nid := to_number(p_event_key);
4233
4234 -- Obtain notification information
4235 begin -- 3741599 If there is no notification, exit gracefully
4236 select NVL(MORE_INFO_ROLE, RECIPIENT_ROLE), STATUS, MAIL_STATUS,
4237 MESSAGE_TYPE, MESSAGE_NAME
4238 into recipient_role, status, mail_status, messageType, messageName
4239 from WF_NOTIFICATIONS
4240 where NOTIFICATION_ID = nid;
4241 exception
4242 when no_data_found then
4243 str := '<?xml version="1.0" ?>';
4244 pos := length(str);
4245 dbms_lob.write(p_doc, pos, 1, str);
4246 nodename := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
4247 pCorrId => messageType,
4248 pName => 'NODENAME',
4249 pInAttr => inAttr);
4250
4251 AddElementAttribute('maxcount','1', attrlist);
4252 pos := NewLOBTag(p_doc, pos, 'NOTIFICATIONGROUP', '', attrlist);
4253 attrlist.DELETE;
4254
4255 -- 4104735 Empty documents now provide a document type and
4256 -- if a empty document, must provide a reason.
4257 AddElementAttribute('nid', nid, attrlist);
4258 AddElementAttribute('language', 'AMERICAN', attrlist);
4259 AddElementAttribute('territory', 'AMERICA', attrlist);
4260 AddElementAttribute('codeset', 'UTF8', attrlist);
4261
4262 -- Added below default base parameters.
4263 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
4264 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
4265 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
4266 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
4267
4268 AddElementAttribute('full-document', 'N', attrlist);
4269 AddElementAttribute('reason', 'no_data_found', attrlist);
4270 pos := NewLOBTag(p_doc, pos, 'NOTIFICATION', '', attrlist);
4271 attrlist.DELETE;
4272
4273 return;
4274 when others then
4275 wf_core.context('WF_XML','GenerateMessage',to_char(nid));
4276 raise;
4277 end;
4278
4279 if (wf_mail.test_flag = TRUE) then
4280 mail_status := 'MAIL';
4281 if (status not in ('OPEN','CANCELED','CLOSED')) then
4282 status := 'OPEN';
4283 end if;
4284 end if;
4285
4286 if MAIL_STATUS is null or MAIL_STATUS not in ('MAIL','INVALID') then
4287
4288 str := '<?xml version="1.0" ?>';
4289 pos := length(str);
4290 dbms_lob.write(p_doc, pos, 1, str);
4291 nodename := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
4292 pCorrId => messageType,
4293 pName => 'NODENAME',
4294 pInAttr => inAttr);
4295
4296 AddElementAttribute('maxcount','1', attrlist);
4297 pos := NewLOBTag(p_doc, pos, 'NOTIFICATIONGROUP', '', attrlist);
4298 attrlist.DELETE;
4299
4300 -- 4104735 Empty documents now provide a document type and
4301 -- if a empty document, must provide a reason.
4302 AddElementAttribute('nid', nid, attrlist);
4303 AddElementAttribute('language', 'AMERICAN', attrlist);
4304 AddElementAttribute('territory', 'AMERICA', attrlist);
4305 AddElementAttribute('codeset', 'UTF8', attrlist);
4306
4307 -- Added below default base parameters.
4308 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
4309 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
4310 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
4311 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
4312
4313 AddElementAttribute('full-document', 'N', attrlist);
4314 AddElementAttribute('reason', 'MAIL_STATUS:'||
4315 MAIL_STATUS, attrlist);
4316 pos := NewLOBTag(p_doc, pos, 'NOTIFICATION', '', attrlist);
4317 attrlist.DELETE;
4318
4319 return;
4320 end if;
4321
4322 -- <<sstomar>>:
4323 -- Call OLD API instead of WF_DIRECTORY.GetRoleInfoMail2
4324 -- here I think we are OK as we are not using other parameters.
4325 --
4326 -- Obtain recipient information
4327 WF_DIRECTORY.GetRoleInfoMail(recipient_role, display_name, email,
4328 notification_pref,
4329 language, territory,
4330 orig_system, orig_system_id, installed);
4331
4332 if email is not null then
4333 -- Email address is provided. process for one recipient
4334
4335 if notification_pref not in ('QUERY','SUMMARY','SUMHTML',
4336 'DISABLED') then
4337 str := '<?xml version="1.0" ?>';
4338 pos := length(str);
4339 dbms_lob.write(p_doc, pos, 1, str);
4340
4341 -- 4628088 Send the RESET_NLS flag if one is defined
4342 -- at the message level.
4343 resetNls := WF_MAILER_PARAMETER.GetValueForCorr (pNid => nid,
4344 pCorrId => messageType,
4345 pName => 'RESET_NLS',
4346 pInAttr => inAttr);
4347
4348 AddElementAttribute('maxcount','1', attrlist);
4349
4350 if(inAttr = 'Y') then
4351 AddElementAttribute('reset-nls',resetNls, attrlist);
4352 end if;
4353
4354 pos := NewLOBTag(p_doc, pos, 'NOTIFICATIONGROUP', '', attrlist);
4355 attrlist.DELETE;
4356
4357 -- generate XML payload
4358 generateDoc(p_doc, pos, recipient_role,
4359 p_event_name, p_event_key, p_parameter_list);
4360
4361 else
4362 -- This case should not be reached if the notification system
4363 -- is working correctly ie that a NULL is placed in the mail_status
4364 -- However, just in case, generate a blank NOTIFICATION element
4365 -- all the same.
4366
4367 str := '<?xml version="1.0" ?>';
4368 pos := length(str);
4369 dbms_lob.write(p_doc, pos, 1, str);
4370
4371 AddElementAttribute('maxcount','1', attrlist);
4372 pos := NewLOBTag(p_doc, pos, 'NOTIFICATIONGROUP', '', attrlist);
4373 attrlist.DELETE;
4374
4375 -- 4104735 Empty documents now provide a document type and
4376 -- if a empty document, must provide a reason.
4377 AddElementAttribute('nid', nid, attrlist);
4378 AddElementAttribute('language', 'AMERICAN', attrlist);
4379 AddElementAttribute('territory', 'AMERICA', attrlist);
4380 AddElementAttribute('codeset', 'UTF8', attrlist);
4381
4382 -- Added below default base parameters.
4383 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
4384 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
4385 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
4386 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
4387
4388 AddElementAttribute('full-document', 'N', attrlist);
4389 AddElementAttribute('reason', 'NOTIFICATION_PREFERENCE:'||
4390 notification_pref, attrlist);
4391 pos := NewLOBTag(p_doc, pos, 'NOTIFICATION', '', attrlist);
4392 attrlist.DELETE;
4393 end if;
4394 else
4395 -- No email address is provided. Assume that this is a
4396 -- role with members.
4397 -- Failure to yeild members will result in a notification
4398 -- being generated to go to the system admin and the
4399 -- error process to be called.
4400 str := '<?xml version="1.0" ?>';
4401 pos := length(str);
4402 dbms_lob.write(p_doc, pos, 1, str);
4403 generateGroupDoc(p_doc, pos, recipient_role, notification_pref,
4404 orig_system, orig_system_id,
4405 p_event_name, p_event_key, p_parameter_list);
4406 end if;
4407
4408 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
4409 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
4410 'wf.plsql.WF_XML.generateMessage', 'END');
4411 end if;
4412 exception
4413 when others then
4414 wf_core.context('WF_XML','Generate',p_event_name, p_event_key);
4415 raise;
4416 end GenerateMessage;
4417
4418 -- GenerateSummaryDoc
4419 -- To generate the XML content for the OPEN notifications.
4420
4421 procedure GenerateSummaryDoc (p_doc in out NOCOPY CLOB,
4422 p_pos in out NOCOPY number,
4423 p_recipient_role in varchar2,
4424 p_event_name in varchar2,
4425 p_event_key in varchar2,
4426 p_parameter_list in wf_parameter_list_t)
4427 is
4428 pos integer;
4429 attrlist wf_xml_attr_table_type;
4430 occurance integer;
4431
4432 docType VARCHAR2(100);
4433
4434 recipient_role VARCHAR2(100);
4435 display_name VARCHAR2(200);
4436 email VARCHAR2(1000);
4437
4438 notification_pref VARCHAR2(100);
4439
4440 orig_system VARCHAR2(100);
4441 orig_system_id number;
4442 installed VARCHAR2(1);
4443
4444 l_nlsDateFormat VARCHAR2(120);
4445 l_nlsDateLanguage varchar2(120);
4446 l_nlsCalendar varchar2(120);
4447 l_nlsNumericCharacters varchar2(30);
4448 l_nlsSort varchar2(120);
4449 l_nlsCurrency varchar2(30);
4450
4451 l_nlsLanguage VARCHAR2(120);
4452 l_nlsTerritory VARCHAR2(120);
4453 l_nlsCodeset VARCHAR2(30);
4454
4455 l_context_changed BOOLEAN := false;
4456
4457 hdrxml varchar2(32000);
4458 hdrxmlPos integer;
4459
4460 corrId varchar2(128);
4461 nodename varchar2(100);
4462 fromName varchar2(100);
4463 replyto varchar2(100);
4464 subject VARCHAR2(4000);
4465
4466 msgbody VARCHAR2(32000);
4467 -- message CLOB;
4468 messageIdx pls_integer;
4469 l_lob VARCHAR2(1);
4470 resourceSrc varchar2(4000);
4471 l_renderBody varchar2(1);
4472 l_messageName varchar2(30);
4473
4474 begin
4475
4476 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
4477 wf_log_pkg.string(wf_log_pkg.level_event,
4478 'wf.plsql.WF_XML.GenerateSummaryDoc',
4479 'BEGIN');
4480 end if;
4481
4482 recipient_role := p_recipient_role;
4483
4484 corrId := wf_event.getValueForParameter('Q_CORRELATION_ID',
4485 p_parameter_list);
4486 messageIdx := 0;
4487 pos := p_pos;
4488 occurance := 1;
4489
4490 -- Obtain recipient information
4491 --WF_DIRECTORY.GetRoleInfoMail(recipient_role, display_name, email,
4492 -- notification_pref,
4493 -- language, territory,
4494 -- orig_system, orig_system_id, installed);
4495
4496 -- Obtain recipient's NLS information too
4497 WF_DIRECTORY.GetRoleInfoMail2(recipient_role, display_name, email,
4498 notification_pref,
4499 orig_system,
4500 orig_system_id,
4501 installed,
4502 l_nlsLanguage ,
4503 l_nlsTerritory ,
4504 l_nlsDateFormat ,
4505 l_nlsDateLanguage ,
4506 l_nlsCalendar ,
4507 l_nlsNumericCharacters ,
4508 l_nlsSort ,
4509 l_nlsCurrency );
4510
4511
4512 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
4513 wf_log_pkg.string(wf_log_pkg.level_statement,
4514 'wf.plsql.WF_XML.GenerateSummaryDoc',
4515 'ROLE {'||recipient_role||'} LANG {'||l_nlsLanguage||
4516 '} TERR {'||l_nlsTerritory||' NTF {'||notification_pref||
4517 '} EMAIL {'||email||'}');
4518
4519 end if;
4520
4521 -- XX TODO Sentinal for DISABLED case? Though there is no NID to be
4522 -- updated, can be used as documentation in the log
4523 if notification_pref not in ('SUMMARY','SUMHTML') or
4524 email is null then
4525 if (wf_log_pkg.level_exception >= fnd_log.g_current_runtime_level) then
4526 if email is null then
4527 wf_log_pkg.string(wf_log_pkg.level_exception,
4528 'wf.plsql.WF_XML.GenerateSummaryDoc',
4529 'Not generating. Recipient has a null '||
4530 'email address');
4531 else
4532 wf_log_pkg.string(wf_log_pkg.level_exception,
4533 'wf.plsql.WF_XML.GenerateSummaryDoc',
4534 'Not generating. Recipient has pref: '||
4535 notification_pref);
4536 end if;
4537 end if;
4538
4539 AddElementAttribute('nid', '0', attrlist);
4540 AddElementAttribute('language', 'AMERICAN', attrlist);
4541 AddElementAttribute('territory', 'AMERICA', attrlist);
4542 AddElementAttribute('codeset', 'UTF8', attrlist);
4543
4544 -- set values of attributes as notification is NOT to be sent
4545 -- Added below default base parameters.
4546 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
4547 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
4548
4549 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
4550 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
4551 AddElementAttribute('full-document', 'N', attrlist);
4552
4553 AddElementAttribute('reason', 'NOTIFICATION_PREFERENCE:'||
4554 notification_pref, attrlist);
4555 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATION', '', attrlist);
4556 attrlist.DELETE;
4557 p_pos := SkipLOBTag(p_doc, 'NOTIFICATION', p_pos, occurance);
4558
4559 return;
4560
4561 end if;
4562
4563 -- Set the preferred document type based on the
4564 -- notification preference.
4565 if g_install = 'EMBEDDED' then
4566 l_renderBody := 'N';
4567 l_messageName := 'SUMHTML';
4568 if notification_pref = 'SUMMARY' then
4569 docType := g_ntfDocText;
4570 elsif notification_pref = 'SUMHTML' then
4571 docType := g_ntfDocHtml;
4572 end if;
4573 else
4574 l_renderBody := 'Y';
4575 l_messageName := 'SUMMARY';
4576 docType := g_ntfDocText;
4577 end if;
4578
4579 -- Get the Base NLS.
4580 -- << sstomar>> : already being set in GENERATE function
4581 -- WF_MAIL.GetSessionLanguage(base_lang, base_territory, base_codeset);
4582
4583 -- If requested language is not installed, use base NLS setting
4584 if installed = 'N' then
4585 l_nlsLanguage := g_base_language;
4586 l_nlsTerritory := g_base_territory;
4587 end if;
4588 begin
4589 select nls_codeset
4590 into l_nlsCodeset
4591 from wf_languages
4592 where nls_language = l_nlsLanguage;
4593 exception
4594 when others then
4595 l_nlsCodeset := g_base_codeset;
4596 end;
4597
4598 -- <<sstomar>> :
4599 --
4600 -- setNLS(language, territory);
4601 -- Set user / role's context
4602 if( nvl(l_nlsLanguage, 'AMERICA') <> g_base_language or
4603 nvl(l_nlsTerritory, 'AMERICAN') <> g_base_territory or
4604 nvl(l_nlsDateFormat , wf_core.nls_date_format) <> g_base_nlsDateFormat or
4605 nvl(l_nlsDateLanguage, wf_core.nls_date_language) <> g_base_nlsDateLanguage or
4606 nvl(l_nlsNumericCharacters, wf_core.nls_numeric_characters) <> g_base_nlsNumericCharacters or
4607 nvl(l_nlsSort, wf_core.nls_sort) <> g_base_nlsSort ) then
4608
4609
4610 WF_NOTIFICATION_UTIL.SetNLSContext(0,
4611 l_nlsLanguage ,
4612 l_nlsTerritory ,
4613 l_nlsDateFormat ,
4614 l_nlsDateLanguage ,
4615 l_nlsNumericCharacters ,
4616 l_nlsSort ,
4617 l_nlsCalendar);
4618
4619 l_context_changed := true;
4620
4621
4622 END if;
4623
4624 -- Initialise the XML Document and then progressively walk
4625 -- through the elements. Populating them as we go.
4626 -- l_pos is crucial as it determines where the next nodes
4627 -- will be placed.
4628
4629 l_lob := 'N';
4630
4631 -- <<sstomar>>:
4632 -- This WF_MAIL.GetSummary2 API may allocate temp LOB depending on
4633 -- size of contents. We release within getBodyPart api, getBodyPart
4634 -- is being called below...
4635 WF_MAIL.GetSummary2(
4636 role => recipient_role,
4637 dname => display_name,
4638 node => nodename,
4639 renderBody=> l_renderBody,
4640 contType => docType,
4641 subject => subject,
4642 body_text => msgbody,
4643 lob => l_lob);
4644
4645 --SetNLS(base_lang, base_territory);
4646
4647 -- Reset base NLS Context
4648 if( l_context_changed ) then
4649
4650 WF_NOTIFICATION_UTIL.SetNLSContext(
4651 null,
4652 g_base_language ,
4653 g_base_territory ,
4654 g_base_nlsDateFormat ,
4655 g_base_nlsDateLanguage ,
4656 g_base_nlsNumericCharacters ,
4657 g_base_nlsSort ,
4658 g_base_nlsCalendar );
4659 END if;
4660
4661
4662 -- NID hardcoded to 0 for Summary
4663 AddElementAttribute('nid', '0', attrlist);
4664
4665 AddElementAttribute('language', l_nlsLanguage, attrlist);
4666 AddElementAttribute('territory', l_nlsTerritory, attrlist);
4667 AddElementAttribute('codeset', l_nlsCodeset, attrlist);
4668
4669 AddElementAttribute('nlsDateformat', l_nlsDateFormat, attrlist);
4670 AddElementAttribute('nlsDateLanguage', l_nlsDateLanguage, attrlist);
4671
4672 AddElementAttribute('nlsNumericCharacters', l_nlsNumericCharacters, attrlist);
4673 AddElementAttribute('nlsSort', l_nlsSort, attrlist);
4674
4675 -- priority hardcoded to 50
4676 AddElementAttribute('priority', '50', attrlist);
4677 -- Not addding accesskey as no response processing is done for summary email
4678 AddElementAttribute('node', nodename, attrlist);
4679 -- ItemType / messageType hardcoded to WFMAIL
4680 AddElementAttribute('item_type', 'WFMAIL', attrlist);
4681 AddElementAttribute('message_name', l_messageName, attrlist);
4682 AddElementAttribute('full-document', 'Y', attrlist);
4683 pos := NewLOBTag(p_doc, pos, 'NOTIFICATION', '', attrlist);
4684 attrlist.DELETE;
4685
4686 hdrxmlPos := 0;
4687 hdrxml := '';
4688
4689 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'RECIPIENTLIST', '', attrlist);
4690
4691 addRecipient(p_doc => hdrxml,
4692 p_role => recipient_role,
4693 p_type => 'to',
4694 p_name => display_name,
4695 p_email => email,
4696 p_pos => hdrxmlPos);
4697
4698 hdrxmlPos := SkipTag(hdrxml, 'RECIPIENTLIST', hdrxmlPos, occurance);
4699
4700 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'FROM', '', attrlist);
4701
4702 -- fromName := 'FROM';
4703 fromName := WF_MAILER_PARAMETER.GetValueForCorr (pCorrId => corrId,
4704 pName => 'FROM');
4705 fromName := replace(fromName, g_newLine);
4706 fromName := '<![CDATA['||fromName||']]>';
4707 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'NAME', fromName, attrlist);
4708 hdrxmlPos := SkipTag(hdrxml, 'NAME', hdrxmlPos, occurance);
4709
4710 -- replyto := 'REPLYTO';
4711 replyto := WF_MAILER_PARAMETER.GetValueForCorr (pCorrId => corrId,
4712 pName => 'REPLYTO');
4713 replyto := replace(replyto, g_newLine);
4714 replyto := '<![CDATA['||replyto||']]>';
4715 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'ADDRESS', replyto, attrlist);
4716 hdrxmlPos := SkipTag(hdrxml, 'ADDRESS', hdrxmlPos, occurance);
4717 hdrxmlPos := SkipTag(hdrxml, 'FROM', hdrxmlPos, occurance);
4718
4719 -- Not addding status as not needed for summary email
4720
4721 subject := replace(subject, g_newLine);
4722 subject := '<![CDATA['||subject||']]>';
4723 hdrxmlPos := NewTag(hdrxml, hdrxmlPos, 'SUBJECT', subject, attrlist);
4724
4725 pos := NewLOBTag(p_doc, pos, 'HEADER', hdrxml, attrlist);
4726 pos := SkipLOBTag(p_doc, 'HEADER', pos, occurance);
4727
4728 -- <sstomar bug 6993909>>
4729 -- So far I did not see any issue with SUMHTML
4730 -- If required then outer structure can be set multipart/related
4731 -- for SUMHTML, text/plain for SUMMARY.
4732 AddElementAttribute('content-type', 'multipart/mixed', attrlist);
4733 pos := NewLOBTag(p_doc, pos, 'CONTENT', '', attrlist);
4734 attrlist.DELETE;
4735
4736 /*
4737 ** The body part section of the XML structure will contain
4738 ** a <![CDATA ]]> construct which removes the need to URL
4739 ** encode the data.
4740 */
4741 if (l_renderBody = 'Y') then
4742 AddElementAttribute('content-type', 'text/plain', attrlist);
4743 else
4744 AddElementAttribute('content-type', 'multipart/related', attrlist);
4745 end if;
4746 pos := NewLOBTag(p_doc, pos, 'BODYPART', '', attrlist);
4747 attrlist.DELETE;
4748
4749 -- Set the content-type of the MESSAGE tag to being the
4750 -- preferred output.
4751 AddElementAttribute('content-type', docType, attrlist);
4752 if (l_lob = 'Y') then
4753
4754 -- dbms_lob.createTemporary(message, TRUE, dbms_lob.CALL);
4755 messageIdx := wf_temp_lob.getLob(g_LOBTable);
4756 dbms_lob.trim(g_LOBTable(messageIdx).temp_lob, 0);
4757
4758 -- << bug 6511028 >>
4759 -- This getBodyPart API also releases temp lob allocated within
4760 -- WF_MAIL.GetSummary2 for doctype (text/plain )
4761 -- i.e. g_text_messageIdx locator
4762 getBodyPart(g_LOBTable(messageIdx).temp_lob, 1,
4763 g_ntfDocText);
4764
4765 pos := NewLOBTag(p_doc, pos, 'MESSAGE',
4766 g_LOBTable(messageIdx).temp_lob, attrlist);
4767 -- release Temp lob to pool.
4768 wf_temp_lob.releaseLob(g_LOBTable, messageIdx);
4769
4770 else
4771
4772 msgbody := '<![CDATA['||msgbody||']]>';
4773
4774 pos := NewLOBTag(p_doc, pos, 'MESSAGE', msgbody, attrlist);
4775
4776 end if;
4777
4778 pos := SkipLOBTag(p_doc, 'MESSAGE', pos, occurance);
4779 if l_renderBody = 'N' then
4780 -- If this is a HTML summary notification then
4781 -- create a RESOURCE tag to obtain the content from
4782 -- the Applications Framework
4783 resourceSrc := wf_mail.urlEncode(wf_notification.getSummaryUrl2(
4784 recipient_role, docType, l_nlsCalendar));
4785 AddElementAttribute('page-type','fwk', attrlist);
4786 AddElementAttribute('src', resourceSrc, attrlist);
4787
4788 -- << sstomar>> : these attribute may not be used at java layer, insead of
4789 -- Notification level attributes would be used,
4790 AddElementAttribute('language', l_nlsLanguage, attrlist);
4791 AddElementAttribute('territory', l_nlsTerritory, attrlist);
4792 AddElementAttribute('token', 'SUMMARY', attrlist);
4793 pos := NewLOBTag(p_doc, pos, 'RESOURCE', '', attrlist);
4794 pos := SkipLOBTag(p_doc, 'RESOURCE', pos, occurance);
4795 attrList.DELETE;
4796 end if;
4797 pos := SkipLOBTag(p_doc, 'BODYPART', pos, occurance);
4798 attrlist.DELETE;
4799
4800 pos := SkipLOBTag(p_doc, 'CONTENT', pos, occurance);
4801 pos := SkipLOBTag(p_doc, 'NOTIFICATION', pos, occurance);
4802
4803 p_pos := pos;
4804
4805 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
4806 wf_log_pkg.string(wf_log_pkg.level_event,
4807 'wf.plsql.WF_XML.GenerateSummaryDoc',
4808 'END');
4809 end if;
4810
4811 exception
4812 when others then
4813 if (messageIdx > 0) then
4814 wf_temp_lob.releaseLob(g_LOBTable, messageIdx);
4815 end if;
4816
4817 -- Reset base NLS Context in case of any EXCEPTION
4818 WF_NOTIFICATION_UTIL.SetNLSContext(
4819 null,
4820 g_base_language ,
4821 g_base_territory ,
4822 g_base_nlsDateFormat ,
4823 g_base_nlsDateLanguage ,
4824 g_base_nlsNumericCharacters ,
4825 g_base_nlsSort ,
4826 g_base_nlsCalendar );
4827
4828
4829 wf_core.context('WF_XML', 'GenerateSummaryDoc', p_event_name,
4830 p_event_key);
4831 raise;
4832 end GenerateSummaryDoc;
4833
4834 -- Generate
4835 procedure GenerateGroupSummaryDoc (p_doc in out NOCOPY CLOB,
4836 p_pos in out NOCOPY number,
4837 p_recipient_role in varchar2,
4838 p_orig_system in varchar2,
4839 p_orig_system_id in number,
4840 p_event_name in varchar2,
4841 p_event_key in varchar2,
4842 p_parameter_list in wf_parameter_list_t)
4843 is
4844
4845 cursor members(rname varchar2, rorig varchar2, rorigid number) is
4846 select UR.USER_NAME, UR.USER_ORIG_SYSTEM, UR.USER_ORIG_SYSTEM_ID
4847 from WF_USER_ROLES UR
4848 where UR.ROLE_NAME = rname
4849 and UR.ROLE_ORIG_SYSTEM = rorig
4850 and UR.ROLE_ORIG_SYSTEM_ID = rorigid
4851 and ((UR.USER_NAME <> UR.ROLE_NAME) or
4852 (UR.USER_ORIG_SYSTEM <> UR.ROLE_ORIG_SYSTEM and
4853 UR.USER_ORIG_SYSTEM_ID <> UR.ROLE_ORIG_SYSTEM_ID));
4854
4855 members_type members%ROWTYPE;
4856 TYPE members_table_type is TABLE OF members%ROWTYPE
4857 INDEX BY BINARY_INTEGER;
4858
4859 i pls_integer := 1;
4860
4861 members_t members_table_type;
4862 attrlist wf_xml_attr_table_type;
4863
4864 begin
4865
4866 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
4867 wf_log_pkg.string(wf_log_pkg.level_event,
4868 'wf.plsql.WF_XML.GenerateGroupSummaryDoc',
4869 'BEGIN');
4870 end if;
4871
4872 i := 1;
4873 for r in members(p_recipient_role, p_orig_system, p_orig_system_id) loop
4874 members_t(i).user_name := r.user_name;
4875 members_t(i).user_orig_system:= r.user_orig_system;
4876 members_t(i).user_orig_system_id:= r.user_orig_system_id;
4877 i := i + 1;
4878 end loop;
4879
4880 if members_t.count = 0 then
4881 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
4882 wf_log_pkg.string(wf_log_pkg.level_event,
4883 'wf.plsql.WF_XML.GenerateGroupSummaryDoc',
4884 'No role members.');
4885 end if;
4886
4887 AddElementAttribute('maxcount', '1', attrlist);
4888 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATIONGROUP', '', attrlist);
4889 attrlist.DELETE;
4890
4891 -- 4104735 Empty documents now provide a document type and
4892 -- if a empty document, must provide a reason.
4893 AddElementAttribute('nid', '0', attrlist);
4894 AddElementAttribute('language', 'AMERICAN', attrlist);
4895 AddElementAttribute('territory', 'AMERICA', attrlist);
4896 AddElementAttribute('codeset', 'UTF8', attrlist);
4897
4898 -- Added below default base parameters.
4899 AddElementAttribute('nlsDateformat', wf_core.nls_date_format, attrlist);
4900 AddElementAttribute('nlsDateLanguage', wf_core.nls_date_language, attrlist);
4901
4902 AddElementAttribute('nlsNumericCharacters', wf_core.nls_numeric_characters, attrlist);
4903 AddElementAttribute('nlsSort', wf_core.nls_sort, attrlist);
4904
4905 AddElementAttribute('full-document', 'N', attrlist);
4906 AddElementAttribute('reason', 'no_members', attrlist);
4907 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATION', '', attrlist);
4908 attrlist.DELETE;
4909 else
4910
4911 AddElementAttribute('maxcount',to_char(members_t.count), attrlist);
4912 p_pos := NewLOBTag(p_doc, p_pos, 'NOTIFICATIONGROUP', '', attrlist);
4913 attrlist.DELETE;
4914
4915 for i in 1..members_t.count loop
4916 GenerateSummaryDoc (p_doc, p_pos, members_t(i).user_name,
4917 p_event_name, p_event_key, p_parameter_list);
4918 end loop;
4919 end if;
4920
4921 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
4922 wf_log_pkg.string(wf_log_pkg.level_event,
4923 'wf.plsql.WF_XML.GenerateGroupSummaryDoc',
4924 'END');
4925 end if;
4926
4927 exception
4928 when others then
4929 wf_core.context('WF_XML','GenerateGroupSummaryDoc ',p_event_name,
4930 p_event_key);
4931 raise;
4932 end GenerateGroupSummaryDoc ;
4933
4934
4935 -- GenerateSummary
4936 -- To generate the XML content for the enqueued Summary notifications.
4937 procedure GenerateSummary (p_doc in out nocopy CLOB,
4938 p_event_name in varchar2,
4939 p_event_key in varchar2,
4940 p_parameter_list in wf_parameter_list_t)
4941 is
4942 pos integer;
4943
4944 attrlist wf_xml_attr_table_type;
4945 str varchar2 (2000);
4946
4947 recipient_role VARCHAR2(100);
4948
4949 display_name VARCHAR2(200);
4950 email VARCHAR2(1000);
4951 notification_pref VARCHAR2(100);
4952 language VARCHAR2(100);
4953 territory VARCHAR2(100);
4954 orig_system VARCHAR2(100);
4955 orig_system_id number;
4956 installed VARCHAR2(1);
4957
4958 e_RoleNameNotSpecified EXCEPTION;
4959
4960 begin
4961
4962 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
4963 wf_log_pkg.string(wf_log_pkg.level_event,
4964 'wf.plsql.WF_XML.GenerateSummary',
4965 'BEGIN');
4966 end if;
4967
4968 if p_parameter_list is not null then
4969 recipient_role := wf_event.getValueForParameter('ROLE_NAME',
4970 p_parameter_list);
4971 end if;
4972
4973 if recipient_role is null then
4974 raise e_RoleNameNotSpecified;
4975 end if;
4976
4977 -- Initialise the XML Document and then progressively walk
4978 -- through the elements. Populating them as we go.
4979 -- l_pos is crucial as it determines where the next nodes
4980 -- will be placed.
4981 str := '<?xml version="1.0" ?>';
4982 pos := length(str);
4983 dbms_lob.write(p_doc, pos, 1, str);
4984
4985 -- Obtain recipient information
4986 WF_DIRECTORY.GetRoleInfoMail(recipient_role, display_name, email,
4987 notification_pref,
4988 language, territory,
4989 orig_system, orig_system_id, installed);
4990
4991 if email is not null or email <> '' then
4992
4993 AddElementAttribute('maxcount','1', attrlist);
4994 pos := NewLOBTag(p_doc, pos, 'NOTIFICATIONGROUP', '', attrlist);
4995 attrlist.DELETE;
4996 -- Email address is provided. process for one recipient
4997
4998 GenerateSummaryDoc (p_doc, pos, recipient_role, p_event_name,
4999 p_event_key, p_parameter_list);
5000
5001 else
5002
5003 -- No email address is provided. Assume that this is a
5004 -- role with members.
5005 -- Failure to yeild members will result in a notification
5006 -- being generated to go to the system admin and the
5007 -- error process to be called.
5008
5009 GenerateGroupSummaryDoc (p_doc, pos, recipient_role, orig_system,
5010 orig_system_id, p_event_name, p_event_key,
5011 p_parameter_list);
5012
5013 end if;
5014
5015 if (wf_log_pkg.level_event >= fnd_log.g_current_runtime_level) then
5016 wf_log_pkg.string(wf_log_pkg.level_event,
5017 'wf.plsql.WF_XML.GenerateSummary',
5018 'END');
5019 end if;
5020 exception
5021
5022 when e_RoleNameNotSpecified then
5023 wf_core.context('WF_XML','GenerateSummary',p_event_name, p_event_key);
5024 raise;
5025
5026 when others then
5027 wf_core.context('WF_XML','GenerateSummary',p_event_name, p_event_key);
5028 raise;
5029 end GenerateSummary;
5030
5031 -- Generate
5032 -- To generate the XML content for the enqueued notifications.
5033 function Generate(p_event_name in varchar2,
5034 p_event_key in varchar2,
5035 p_parameter_list in wf_parameter_list_t)
5036 return clob
5037 is
5038 l_doc CLOB;
5039 l_evt wf_event_t;
5040 l_parameters wf_parameter_list_t;
5041 l_erragt wf_agent_t;
5042
5043 begin
5044 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
5045 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
5046 'wf.plsql.WF_XML.generate', 'BEGIN');
5047 end if;
5048 -- We do not use the LOB pooling for the generate as the LOB
5049 -- is to be returned and not reused.
5050 dbms_lob.createTemporary(l_doc, TRUE, dbms_lob.call);
5051
5052
5053 BEGIN
5054
5055 -- <<sstomar>>:
5056 -- Since base NLS parameters / context would be used in subsequent methods
5057 -- So better to set them here.
5058 --
5059 if(g_base_language is null or
5060 g_base_territory is null or
5061 g_base_codeset is NULL OR
5062 g_base_nlsDateFormat is NULL OR
5063 g_base_nlsDateLanguage is NULL OR
5064 g_base_nlsNumericCharacters is NULL OR
5065 g_base_nlsSort is NULL
5066 ) then
5067
5068 WF_NOTIFICATION_UTIL.getNLSContext(
5069 g_base_language ,
5070 g_base_territory ,
5071 g_base_codeset ,
5072 g_base_nlsDateFormat ,
5073 g_base_nlsDateLanguage ,
5074 g_base_nlsNumericCharacters ,
5075 g_base_nlsSort ,
5076 g_base_nlsCalendar );
5077
5078
5079
5080 end if;
5081
5082 -- <sstomar> bug 7130745 : added Question / Answere events
5083 if p_event_name in (wf_xml.WF_NTF_SEND_MESSAGE,
5084 wf_xml.WF_NTF_CANCEL,
5085 wf_xml.WF_NTF_REASIGN,
5086 wf_xml.WF_NTF_SEND_QUESTION,
5087 wf_xml.WF_NTF_SEND_ANSWER ) then
5088
5089 GenerateMessage(l_doc, p_event_name, p_event_key,
5090 p_parameter_list);
5091
5092 elsif p_event_name = WF_NTF_SEND_SUMMARY then
5093
5094
5095 -- Summary events.
5096 GenerateSummary (l_doc, p_event_name, p_event_key, p_parameter_list);
5097
5098 end if;
5099 exception
5100 when others then
5101 wf_core.context('WF_XML','Generate',p_event_name, p_event_key);
5102
5103 -- RESET BASSE LANGUAGE
5104 WF_NOTIFICATION_UTIL.SetNLSContext(null,
5105 g_base_language ,
5106 g_base_territory ,
5107 g_base_nlsDateFormat ,
5108 g_base_nlsDateLanguage ,
5109 g_base_nlsNumericCharacters ,
5110 g_base_nlsSort ,
5111 g_base_nlsCalendar );
5112
5113
5114 raise;
5115 end;
5116
5117 if (wf_log_pkg.level_procedure >= fnd_log.g_current_runtime_level) then
5118 wf_log_pkg.string(WF_LOG_PKG.level_procedure,
5119 'wf.plsql.WF_XML.generate', 'END');
5120 end if;
5121 return l_doc;
5122
5123 end Generate;
5124
5125
5126 -- notificationIsOpen
5127 -- Return the current status of the notification
5128 function notificationIsOpen(nid in number) return boolean
5129 is
5130 l_open integer := 0;
5131 begin
5132 begin
5133 select 1
5134 into l_open
5135 from wf_notifications
5136 where notification_id = nid
5137 and status = 'OPEN';
5138 exception
5139 when others then l_open := 0;
5140 end;
5141 return l_open > 0;
5142 end notificationIsOpen;
5143
5144 -- GetResponseDetails
5145 -- Gets the response details from the incoming XML Notifiction
5146 -- structure.
5147 --
5148 -- IN
5149 -- message - The XML Notification structure containing the
5150 -- inbound response
5151 procedure getResponseDetails(message in CLOB)
5152 IS
5153
5154 l_node varchar2(4000);
5155 l_version integer;
5156 l_from_role varchar2(4000);
5157 l_responses wf_responseList_t;
5158
5159 begin
5160
5161 getResponseDetails(message => message,
5162 node => l_node,
5163 version => l_version,
5164 fromRole => l_from_role,
5165 responses => l_responses);
5166
5167 end getResponseDetails;
5168
5169 -- GetResponseDetails
5170 -- Gets the response details from the incoming XML Notifiction
5171 -- structure.
5172 --
5173 -- IN
5174 -- message - The XML Notification structure containing the
5175 -- inbound response
5176 procedure getResponseDetails(message in CLOB, node out NOCOPY varchar2,
5177 version out NOCOPY integer,
5178 fromRole out NOCOPY varchar2,
5179 responses in out NOCOPY wf_responseList_t)
5180 IS
5181
5182 p xmlparser.parser;
5183 doc xmldom.DOMDocument;
5184
5185 nl xmldom.DOMNodeList;
5186 len1 number;
5187 len2 number;
5188 n xmldom.DOMNode;
5189 m xmldom.DOMNode;
5190 nnm xmldom.DOMNamedNodeMap;
5191
5192 fromAddress varchar2(4000);
5193 attrname varchar2(4000);
5194 attrval varchar2(4000);
5195
5196 node_data varchar2(32000);
5197 node_name varchar2(4000);
5198 from_node_found boolean;
5199
5200 attribute_found boolean;
5201 response_count number;
5202
5203 response_attr_name varchar2(4000);
5204 response_attr_val varchar2(32000);
5205 response_attr_type varchar2(4000);
5206 response_attr_format varchar2(4000);
5207
5208 step varchar2(200);
5209
5210 begin
5211
5212 from_node_found := FALSE;
5213 attribute_found := FALSE;
5214 response_count := 0;
5215 responses.delete;
5216 node := '';
5217 fromRole := '';
5218
5219 -- new parser
5220 p := xmlparser.newParser;
5221
5222 -- set some characteristics
5223 xmlparser.setValidationMode(p, FALSE);
5224
5225 -- parse input file
5226 xmlparser.parseClob(p, message);
5227
5228 -- get document
5229 doc := xmlparser.getDocument(p);
5230
5231 -- get all elements
5232 nl := xmldom.getElementsByTagName(doc, '*');
5233 len1 := xmldom.getLength(nl);
5234
5235 -- loop through elements
5236 for j in 0..len1-1 loop
5237
5238 n := xmldom.item(nl, j);
5239 node_name := xmldom.getNodeName(n);
5240
5241 step := 'Processing ['||node_name||']';
5242 if node_name = 'NOTIFICATION' then
5243
5244 -- get all attributes of element
5245 nnm := xmldom.getAttributes(n);
5246
5247 if (xmldom.isNull(nnm) = FALSE) then
5248
5249 len2 := xmldom.getLength(nnm);
5250
5251 -- loop through attributes
5252 for i in 0..len2-1 loop
5253
5254 m := xmldom.item(nnm, i);
5255 attrname := xmldom.getNodeName(m);
5256
5257 step := 'Processing ['||node_name||'] ['||attrname||']';
5258
5259 if attrname = 'node' then
5260
5261 attrval := xmldom.getNodeValue(m);
5262 node := attrval;
5263 elsif attrname = 'version' then
5264
5265 attrval := xmldom.getNodeValue(m);
5266 begin
5267 version := to_number(attrval);
5268 exception
5269 when others then
5270 version := 0;
5271 end;
5272 end if;
5273
5274 end loop;
5275
5276
5277 end if;
5278
5279 elsif node_name = 'FROM' then
5280
5281 from_node_found := TRUE;
5282
5283 elsif node_name = 'NAME' then
5284
5285 if from_node_found then
5286
5287 n := xmldom.getFirstChild(n);
5288
5289 if ((not xmldom.isNull(n))
5290 and (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
5291
5292 node_data := xmlDom.getNodeValue(n);
5293 fromRole := node_data;
5294
5295 end if;
5296
5297 end if;
5298
5299 elsif node_name = 'ADDRESS' then
5300
5301 if from_node_found then
5302
5303 from_node_found := FALSE;
5304
5305 n := xmldom.getFirstChild(n);
5306
5307 if ((not xmldom.isNull(n))
5308 and (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
5309
5310 node_data := xmlDom.getNodeValue(n);
5311 fromAddress := node_data;
5312
5313 fromRole := '"'||fromRole||'" <'||fromAddress||'>';
5314
5315 end if;
5316
5317 end if;
5318
5319 elsif node_name = 'ATTRIBUTE' then
5320
5321 -- get all attributes of element
5322 nnm := xmldom.getAttributes(n);
5323
5324 if (xmldom.isNull(nnm) = FALSE) then
5325
5326 attribute_found := FALSE;
5327 response_attr_name := '';
5328 response_attr_val := '';
5329 response_attr_type := '';
5330 response_attr_format := '';
5331
5332 len2 := xmldom.getLength(nnm);
5333
5334 -- loop through attributes
5335 for i in 0..len2-1 loop
5336
5337 m := xmldom.item(nnm, i);
5338 attrname := xmldom.getNodeName(m);
5339
5340 step := 'Processing ['||node_name||'] ['||attrname||']';
5341
5342 if attrname = 'name' then
5343
5344 attribute_found := TRUE;
5345 attrval := xmldom.getNodeValue(m);
5346 response_attr_name := attrval;
5347
5348 elsif attrname = 'type' then
5349
5350 attrval := xmldom.getNodeValue(m);
5351 response_attr_type := attrval;
5352
5353 elsif attrname = 'format' then
5354
5355 attrval := xmldom.getNodeValue(m);
5356 response_attr_format := attrval;
5357
5358 end if;
5359
5360 end loop;
5361
5362 if attribute_found then
5363
5364 n := xmldom.getFirstChild(n);
5365
5366 if ((not xmldom.isNull(n)) and
5367 (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
5368
5369 node_data := substrb(xmlDom.getNodeValue(n), 1, 32000);
5370 response_attr_val := node_data;
5371 end if;
5372
5373 response_count := response_count + 1;
5374 responses(response_count).NAME := response_attr_name;
5375 responses(response_count).TYPE := response_attr_type;
5376 responses(response_count).FORMAT := response_attr_format;
5377 responses(response_count).VALUE := response_attr_val;
5378
5379
5380 end if;
5381
5382 end if;
5383
5384 end if;
5385 step := 'Fishished {'||step||'}';
5386
5387 end loop;
5388
5389 if (not xmldom.isNull(doc)) then
5390 xmldom.freeDocument (doc);
5391 end if;
5392
5393 xmlparser.freeParser (p);
5394
5395 exception
5396
5397 when xmldom.INDEX_SIZE_ERR then
5398 wf_core.context('WF_XML','getResponseDetails', step);
5399 raise;
5400
5401 when xmldom.DOMSTRING_SIZE_ERR then
5402 wf_core.context('WF_XML','getResponseDetails', step);
5403 raise;
5404
5405 when xmldom.HIERARCHY_REQUEST_ERR then
5406 wf_core.context('WF_XML','getResponseDetails', step);
5407 raise;
5408
5409 when xmldom.WRONG_DOCUMENT_ERR then
5410 wf_core.context('WF_XML','getResponseDetails', step);
5411 raise;
5412
5413 when xmldom.INVALID_CHARACTER_ERR then
5414 wf_core.context('WF_XML','getResponseDetails', step);
5415 raise;
5416
5417 when xmldom.NO_DATA_ALLOWED_ERR then
5418 wf_core.context('WF_XML','getResponseDetails', step);
5419 raise;
5420
5421 when xmldom.NO_MODIFICATION_ALLOWED_ERR then
5422 wf_core.context('WF_XML','getResponseDetails', step);
5423 raise;
5424
5425 when xmldom.NOT_FOUND_ERR then
5426 wf_core.context('WF_XML','getResponseDetails', step);
5427 raise;
5428
5429 when xmldom.NOT_SUPPORTED_ERR then
5430 wf_core.context('WF_XML','getResponseDetails', step);
5431 raise;
5432
5433 when xmldom.INUSE_ATTRIBUTE_ERR then
5434 wf_core.context('WF_XML','getResponseDetails', step);
5435 raise;
5436
5437 when others then
5438 wf_core.context('WF_XML','getResponseDetails', step);
5439 raise;
5440
5441 end getResponseDetails;
5442
5443
5444 -- sendNotification
5445 -- This API is a wrapper to the wf_xml.enqueueNotification. It is provided
5446 -- as forward compatabilty for the original mailer since the call to
5447 -- wf_xml.enqueueNotification has been removed from
5448 -- wf_notification.sendSingle.
5449 -- To use the original mailer, one must enable the subscription that will
5450 -- call this rule function.
5451 -- IN
5452 -- p_subscription
5453 -- p_event
5454 -- RETURN
5455 -- varchar2 of the status
5456 function SendNotification (p_subscription_guid in raw,
5457 p_event in out NOCOPY WF_EVENT_T) return varchar2
5458 is
5459 l_eventName varchar2(80);
5460 l_eventkey varchar(80);
5461 l_nid number;
5462 begin
5463 l_eventkey := p_event.GetEventKey();
5464 l_nid := to_number(l_eventKey);
5465 l_eventName := p_event.GetEventName();
5466 if l_eventName in (wf_xml.WF_NTF_SEND_MESSAGE, wf_xml.WF_NTF_CANCEL,
5467 wf_xml.WF_NTF_REASIGN) then
5468 wf_xml.enqueueNotification(l_nid);
5469 else
5470 return wf_rule.default_rule(p_subscription_guid, p_event);
5471 end if;
5472 return 'SUCCESS';
5473 exception
5474 when others then
5475 wf_core.Context('WF_XML','SendNotification',p_event.getEventName(),
5476 p_subscription_guid);
5477 -- Save error message and set status to INVALID so mailer will
5478 -- bounce an "invalid reply" message to sender.
5479 wf_event.SetErrorInfo(p_event, 'ERROR');
5480 return 'ERROR';
5481 end sendNotification;
5482
5483
5484 -- handleRecevieEvent
5485 --
5486 function handleReceiveEvent(p_subscription_guid in raw,
5487 p_event in out NOCOPY WF_EVENT_T) return varchar2
5488 is
5489 l_eventName varchar2(80);
5490 l_eventkey varchar(80);
5491 l_paramlist wf_parameter_list_t;
5492 l_eventData CLOB;
5493 l_node varchar2(30);
5494 l_version integer;
5495 l_user varchar2(320);
5496 l_comment varchar2(4000);
5497 l_fromAddr varchar2(2000);
5498 l_nid number;
5499 l_template varchar2(30);
5500 l_module varchar2(200);
5501 l_error varchar2(2000);
5502 i int;
5503 l_responses wf_responseList_t;
5504 lk_type varchar2(240);
5505 lk_code varchar2(4000);
5506 lk_meaning varchar2(1000);
5507 l_value varchar2(4000);
5508 l_error_result varchar2(4000);
5509 l_sig_policy varchar2(100);
5510
5511 l_step varchar2(240);
5512 begin
5513
5514 l_eventkey := p_event.GetEventKey();
5515 l_nid := to_number(l_eventKey);
5516 l_eventName := p_event.GetEventName();
5517 l_paramList := p_event.getParameterList();
5518 l_eventData := p_event.getEventData();
5519
5520 -- Recieve the message.
5521 -- Unpack the content and pass it to the
5522 -- routine in charge of parsing it.
5523
5524 -- Allow the response handling handle the closed notification
5525 -- 3736816 Uncommenting and reimplementing this logic to
5526 -- ensure that responses to CANCELED notifications are processed
5527 -- but do not update anything.
5528 l_step := 'Checking the notification status';
5529 if not notificationIsOpen(l_nid) then
5530 begin
5531 lk_type := '';
5532 lk_code := '';
5533 wf_log_pkg.string(WF_LOG_PKG.LEVEL_EXCEPTION,
5534 'WF_XML.handleReceiveEvent',
5535 'Notification is not OPEN. Submitting response '||
5536 'to provide user feedback');
5537 Wf_Notification.Respond(l_nid, NULL, 'email:'||l_fromAddr);
5538 exception
5539 when others then
5540 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
5541 wf_log_pkg.string(WF_LOG_PKG.level_statement,
5542 'wf.plsql.WF_XML.handleReceiveEvent',
5543 'Exception on call to Wf_Notification.Respond NID['||l_nid||'] '||
5544 'Error Msg '||sqlerrm);
5545 end if;
5546
5547 wf_core.Context('WF_XML','handleReceiveEvent',
5548 p_event.getEventName(), p_subscription_guid);
5549 -- Save error message and set status to INVALID so mailer will
5550 -- bounce an "invalid reply" message to sender.
5551 WF_MAIL.HandleResponseError(l_nid, lk_type, lk_code,
5552 l_error_result);
5553 end;
5554 return 'SUCCESS';
5555 end if;
5556
5557 l_step := 'Getting the response details';
5558 getResponseDetails(l_eventData, l_node, l_version, l_fromAddr,
5559 l_responses);
5560
5561 l_step := 'Processing the responses';
5562 if l_responses.COUNT > 0 then
5563 begin
5564 -- Check if this notification requires a Signature. Other than DEFAULT
5565 -- policies, no other policy is processed by the mailer.
5566 Wf_Mail.GetSignaturePolicy(l_nid, l_sig_policy);
5567 if (l_sig_policy is not NULL and upper(l_sig_policy) <> 'DEFAULT') then
5568 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
5569 wf_log_pkg.string(WF_LOG_PKG.level_statement,
5570 'wf.plsql.WF_XML.handleReceiveEvent',
5571 'Signature policy is not DEFAULT');
5572 end if;
5573
5574 -- If a new policy is added, only wfmail.msg needs to be updated
5575 wf_core.context('WF_XML', 'HandleReceiveEvent',
5576 to_char(l_nid), l_node, l_fromAddr);
5577 wf_core.token('NID', to_char(l_nid));
5578 wf_core.raise('WFRSPR_' || l_sig_policy);
5579 end if;
5580
5581 for i in 1..l_responses.COUNT loop
5582 l_step := 'Processing the responses -> '||l_responses(i).name;
5583 lk_type := l_responses(i).format;
5584 lk_code := substrb(l_responses(i).value, 1, 4000);
5585 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
5586 wf_log_pkg.string(WF_LOG_PKG.level_statement,
5587 'wf.plsql.WF_XML.handleReceiveEvent',
5588 'Response VALUE ['||
5589 substrb(lk_code, 1, 100)||
5590 '] TYPE ['||lk_type||']');
5591 end if;
5592
5593 if l_version < 3 then
5594
5595 ----------------------------------
5596 -- verion < 3 is a normal response
5597 ----------------------------------
5598
5599 -- Process the responses for standard responses
5600 if l_responses(i).type = 'LOOKUP' then
5601 -- Verify the content of the lookup. This will raise
5602 -- an exception if it is not matched. GetLovMeaning
5603 -- allows for nulls. This is not acceptable here.
5604
5605 lk_meaning := wf_mail.GetLovMeaning(lk_type,
5606 lk_code);
5607 if lk_meaning is null then
5608 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
5609 wf_log_pkg.string(WF_LOG_PKG.level_statement,
5610 'wf.plsql.WF_XML.handleReceiveEvent',
5611 'LOV Meaning is null');
5612 end if;
5613
5614 wf_core.token('TYPE', lk_type);
5615 wf_core.token('CODE', lk_code);
5616 wf_core.raise('WFSQL_LOOKUP_CODE');
5617 end if;
5618 end if;
5619 if l_responses(i).type = 'MOREINFO' then
5620 null; -- discard these responses
5621 else
5622 wf_notification.setAttrText(l_nid, l_responses(i).name,
5623 lk_code);
5624 end if;
5625 end if;
5626
5627 -- Only process attributes of type MOREINFO on
5628 -- version 3 and 4 templates.
5629 if l_responses(i).type = 'MOREINFO'
5630 and l_version in (3, 4) then
5631 if lk_code is not null then
5632 if l_version = 3 then
5633
5634 if l_responses(i).name = 'WFNTF_MOREINFO_FROM' then
5635 l_user := DecodeEntityReference(lk_code);
5636 elsif l_responses(i).name = 'WFNTF_MOREINFO_QPROMPT' then
5637 if length(l_responses(i).value) > 4000 then
5638 wf_core.context('WF_XML', 'HandleReceiveEvent',
5639 l_responses(i).type,
5640 l_responses(i).name, l_step);
5641 lk_code := substrb(l_responses(i).value, 1,
5642 1000);
5643 wf_core.raise('WFNTF_QUESTION_TOO_LARGE');
5644 end if;
5645 l_comment := lk_code;
5646 end if;
5647 elsif l_version = 4 then
5648 if l_responses(i).name = 'WFNTF_MOREINFO_APROMPT' then
5649 if length(l_responses(i).value) > 4000 then
5650 wf_core.context('WF_XML', 'HandleReceiveEvent',
5651 l_responses(i).type,
5652 l_responses(i).name, l_step);
5653 lk_code := substrb(l_responses(i).value, 1,
5654 1000);
5655 wf_core.raise('WFNTF_QUESTION_TOO_LARGE');
5656 end if;
5657 l_comment := lk_code;
5658 end if;
5659 end if;
5660 end if;
5661 end if;
5662 end loop;
5663
5664 -- Update the results of the more information to the
5665 -- comments table by calling the update API in the
5666 -- correct mode based on the template version.
5667 l_step := 'Updating the notification';
5668 if l_version = 3 then
5669 -- Question mode
5670 -- Send a email back to the sender that the More Info User is invalid
5671 if (l_user is null or length(trim(l_user)) = 0) then
5672 wf_core.raise('WFNTF_NO_ROLE');
5673 elsif(l_comment is null or length(trim(l_comment)) = 0) then
5674 wf_core.raise('WFNTF_NO_QUESTION');
5675 else
5676 wf_notification.UpdateInfo2(l_nid, l_user, l_fromAddr,
5677 l_comment);
5678 end if;
5679 elsif l_version = 4 then
5680 -- Answer mode
5681 l_user := null;
5682 if(l_comment is null or length(trim(l_comment)) = 0) then
5683 wf_core.raise('WFNTF_NO_ANSWER');
5684 else
5685 wf_notification.UpdateInfo2(l_nid, l_user, l_fromAddr,
5686 l_comment);
5687 end if;
5688 else
5689 -- Do not need to preserve context
5690 wf_engine.preserved_context := FALSE;
5691
5692 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
5693 wf_log_pkg.string(WF_LOG_PKG.level_statement,
5694 'wf.plsql.WF_XML.handleReceiveEvent',
5695 'Calling Wf_Notification.Respond');
5696 end if;
5697
5698 Wf_Notification.Respond(nid => l_nid,
5699 responder => 'email:'||l_fromAddr);
5700 end if;
5701 exception
5702 when others then
5703 if (wf_log_pkg.level_statement >= fnd_log.g_current_runtime_level) then
5704 wf_log_pkg.string(WF_LOG_PKG.level_statement,
5705 'wf.plsql.WF_XML.handleReceiveEvent',
5706 'Exception in processing the Response. Step '||l_step||
5707 ' Error Msg '||sqlerrm);
5708 end if;
5709
5710 wf_core.Context('WF_XML','handleReceiveEvent',
5711 to_char(l_nid), 'Step '||l_step);
5712 wf_core.context('WF_MAIL','HandleRevieveEvent', to_char(l_nid));
5713 -- Save error message and set status to INVALID so mailer will
5714 -- bounce an "invalid reply" message to sender.
5715 WF_MAIL.HandleResponseError(l_nid, lk_type,
5716 substrb(lk_code, 1, 1000),
5717 l_error_result);
5718 end;
5719 end if;
5720 return 'SUCCESS';
5721
5722 exception
5723
5724 when others then
5725 wf_core.Context('WF_XML','handleReceiveEvent',p_event.getEventName(),
5726 p_subscription_guid);
5727 -- Save error message and set status to INVALID so mailer will
5728 -- bounce an "invalid reply" message to sender.
5729 wf_event.SetErrorInfo(p_event, 'ERROR');
5730 return 'ERROR';
5731
5732 end handleReceiveEvent;
5733
5734
5735 -- receive
5736 -- Handle the notification receive events
5737 -- This will handle the processing of the inbound responses
5738 -- IN
5739 -- p_subscription_guid - The RAW GUID of the event subscription
5740 -- p_event - The WF_EVENT_T containing the event information
5741 -- RETURN
5742 -- varchar2 of the status
5743 function receive (p_subscription_guid in raw,
5744 p_event in out NOCOPY WF_EVENT_T) return varchar2
5745 is
5746 l_eventName varchar2(80);
5747 result varchar2(30);
5748 erragt wf_agent_t;
5749 l_paramlist wf_parameter_list_t;
5750 errMsg varchar2(4000);
5751 errStack varchar2(4000);
5752
5753 begin
5754
5755 l_eventName := p_event.GetEventName();
5756 l_paramList := p_event.getParameterList();
5757
5758 if l_eventName = WF_NTF_RECEIVE_MESSAGE then
5759
5760 result := handleReceiveEvent(p_subscription_guid, p_event);
5761
5762 elsif l_eventName = WF_NTF_RECEIVE_ERROR then
5763 errMsg := wf_event.getValueForParameter('ERROR_MESSAGE',
5764 l_paramList);
5765 errStack := wf_event.getValueForParameter('ERROR_STACK',
5766 l_paramList);
5767 p_event.setErrorSubscription(p_subscription_guid);
5768 p_event.setErrorMessage(substrb(errMsg,1,4000));
5769 p_event.setErrorStack(substrb(errStack,1,4000));
5770 p_event.addParameterToList('ERROR_NAME', 'WF_NTF_RECEIVE_ERROR');
5771 p_event.addParameterToList('ERROR_TYPE', 'ERROR');
5772
5773 erragt := wf_agent_t('WF_ERROR', wf_event.local_system_name);
5774
5775 --
5776 -- sjm - lets just call the API directly
5777 --
5778 wf_error_qh.enqueue(p_event, erragt);
5779
5780 result := 'SUCCESS';
5781
5782 else
5783
5784 return wf_rule.default_rule(p_subscription_guid, p_event);
5785
5786 end if;
5787
5788 return result;
5789
5790 exception
5791
5792 when others then
5793 wf_core.Context('WF_XML','Receive',p_event.getEventName(),
5794 p_subscription_guid);
5795 -- Save error message and set status to INVALID so mailer will
5796 -- bounce an "invalid reply" message to sender.
5797 wf_event.SetErrorInfo(p_event, 'ERROR');
5798 return 'ERROR';
5799 end receive;
5800
5801 -- SummaryRule
5802 -- To handle the summary notification request event
5803 -- and call the approapriate summary generate function for
5804 -- either the role or the member of the role.
5805 -- IN
5806 -- p_subscription_guid The RAW GUID for the subscription
5807 -- p_event The WF_EVENT_T containing the event details
5808 -- OUT
5809 -- VARCHAR2 - The status
5810 function SummaryRule (p_subscription_guid in raw,
5811 p_event in out NOCOPY WF_EVENT_T) return varchar2
5812 is
5813 l_eventName varchar2(80);
5814 l_eventkey varchar(80);
5815 l_paramlist wf_parameter_list_t;
5816
5817 l_event_paramlist wf_parameter_list_t;
5818 -- NOTE: For bug 6049086, more_info_role is included in the SQL
5819 -- in order to send summary mail to more_info_role and not
5820 -- to recepient_role if notification more_info_role is not null.
5821 CURSOR c_get_summary_roles is
5822 SELECT recipient from
5823 (SELECT distinct nvl(more_info_role,recipient_role) recipient
5824 FROM wf_notifications
5825 WHERE mail_status is null
5826 AND status = 'OPEN'
5827 AND rownum > 0)
5828 WHERE Wf_Directory.GetRoleNtfPref(recipient) in ('SUMMARY', 'SUMHTML');
5829
5830 begin
5831
5832 l_eventkey := p_event.GetEventKey();
5833 l_eventName := p_event.GetEventName();
5834 l_paramList := p_event.getParameterList();
5835
5836 for rec_summary_role in c_get_summary_roles loop
5837
5838 l_event_paramlist := wf_parameter_list_t();
5839 wf_event.addParameterToList('ROLE_NAME',
5840 rec_summary_role.RECIPIENT,
5841 l_event_paramlist);
5842 -- Set AQs correlation id to item type i.e. 'WFMAIL'
5843 wf_event.addParameterToList('Q_CORRELATION_ID', 'WFMAIL:SUM',
5844 l_event_paramlist);
5845 wf_event.addParameterToList('NOTIFICATION_ID', '0',
5846 l_event_paramlist);
5847
5848 wf_event.raise(WF_NTF_SEND_SUMMARY,
5849 rec_summary_role.RECIPIENT||':'||sysdate,
5850 null, l_event_paramlist);
5851 end loop;
5852
5853 return 'SUCCESS';
5854
5855 exception
5856
5857 when others then
5858 wf_core.Context('WF_XML','SummaryRule',p_event.getEventName(),
5859 p_subscription_guid);
5860 wf_event.SetErrorInfo(p_event, 'ERROR');
5861 return 'ERROR';
5862 end SummaryRule;
5863
5864 -- Parse the XML message and seperate out the main elements
5865 -- so that a new notification can be constructed including
5866 -- the information on the previous email.
5867 procedure getMessageDetails(pmessage IN CLOB,
5868 pnode OUT NOCOPY varchar2,
5869 planguage OUT NOCOPY varchar2,
5870 pterritory OUT NOCOPY varchar2,
5871 pcodeset OUT NOCOPY varchar2,
5872 pcontentBody OUT NOCOPY varchar2,
5873 psubject OUT NOCOPY varchar2,
5874 pFromRole OUT NOCOPY varchar2,
5875 pFromAddress OUT NOCOPY varchar2)
5876 is
5877 p xmlparser.parser;
5878 doc xmldom.DOMDocument;
5879
5880 nl xmldom.DOMNodeList;
5881 len1 number;
5882 len2 number;
5883 n xmldom.DOMNode;
5884 m xmldom.DOMNode;
5885 nnm xmldom.DOMNamedNodeMap;
5886
5887 from_node_found boolean := FALSE;
5888 fromRole varchar2(4000);
5889 fromAddress varchar2(4000);
5890
5891 node_data varchar2(4000);
5892 node_name varchar2(4000);
5893 attrname varchar2(4000);
5894 attrval varchar2(4000);
5895
5896
5897 subject varchar2(4000);
5898
5899 contentType varchar2(4000);
5900 textPlain_found boolean := FALSE;
5901
5902 begin
5903
5904 -- new parser
5905 p := xmlparser.newParser;
5906
5907 -- set some characteristics
5908 xmlparser.setValidationMode(p, FALSE);
5909
5910 -- parse input file
5911 xmlparser.parseClob(p, pmessage);
5912
5913 -- get document
5914 doc := xmlparser.getDocument(p);
5915
5916 -- get all elements
5917 nl := xmldom.getElementsByTagName(doc, '*');
5918 len1 := xmldom.getLength(nl);
5919
5920 -- loop through elements
5921 for j in 0..len1-1 loop
5922 n := xmldom.item(nl, j);
5923 node_name := xmldom.getNodeName(n);
5924
5925 if node_name = 'NOTIFICATION' then
5926 -- get all attributes of element
5927 nnm := xmldom.getAttributes(n);
5928
5929 if (xmldom.isNull(nnm) = FALSE) then
5930
5931 len2 := xmldom.getLength(nnm);
5932
5933 -- loop through attributes
5934 for i in 0..len2-1 loop
5935 m := xmldom.item(nnm, i);
5936 attrname := xmldom.getNodeName(m);
5937 if attrname = 'node' then
5938 attrval := xmldom.getNodeValue(m);
5939 pnode := attrval;
5940 -- exit;
5941 elsif attrname = 'language' then
5942 attrval := xmldom.getNodeValue(m);
5943 planguage := attrval;
5944 elsif attrname = 'territory' then
5945 attrval := xmldom.getNodeValue(m);
5946 pterritory := attrval;
5947 elsif attrname = 'codeset' then
5948 attrval := xmldom.getNodeValue(m);
5949 pcodeset := attrval;
5950 end if;
5951
5952 end loop;
5953 end if;
5954 elsif node_name = 'SUBJECT' then
5955 n := xmldom.getFirstChild(n);
5956
5957 if ((not xmldom.isNull(n)) and
5958 (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
5959
5960 node_data := xmlDom.getNodeValue(n);
5961 psubject := node_data;
5962
5963 end if;
5964
5965 elsif node_name = 'FROM' then
5966 from_node_found := TRUE;
5967
5968 elsif node_name = 'NAME' then
5969 if from_node_found then
5970 n := xmldom.getFirstChild(n);
5971
5972 if ((not xmldom.isNull(n)) and
5973 (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
5974
5975 node_data := xmlDom.getNodeValue(n);
5976 pfromRole := node_data;
5977
5978 end if;
5979 end if;
5980 elsif node_name = 'ADDRESS' then
5981 if from_node_found then
5982
5983 from_node_found := FALSE;
5984
5985 n := xmldom.getFirstChild(n);
5986
5987 if ((not xmldom.isNull(n)) and
5988 (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
5989
5990 node_data := xmlDom.getNodeValue(n);
5991 pfromAddress := node_data;
5992
5993 end if;
5994 end if;
5995 elsif node_name = 'MESSAGE' then
5996
5997 nnm := xmldom.getAttributes(n);
5998
5999 if (xmldom.isNull(nnm) = FALSE) then
6000
6001 len2 := xmldom.getLength(nnm);
6002
6003 -- loop through attributes
6004 for i in 0..len2-1 loop
6005 m := xmldom.item(nnm, i);
6006 attrname := xmldom.getNodeName(m);
6007 if upper(attrname) = 'CONTENT-TYPE' then
6008 attrval := xmldom.getNodeValue(m);
6009 contentType := attrval;
6010 exit;
6011 end if;
6012 end loop;
6013 textPlain_found := upper(contentType) = 'TEXT/PLAIN';
6014 end if;
6015 if textPlain_found then
6016 n := xmldom.getFirstChild(n);
6017
6018 if ((not xmldom.isNull(n)) and
6019 (xmldom.getNodeType(n) = xmldom.TEXT_NODE)) then
6020
6021 node_data := xmlDom.getNodeValue(n);
6022 pcontentBody := node_data;
6023 end if;
6024 end if;
6025 end if;
6026 end loop;
6027
6028 end getMessageDetails;
6029
6030 FUNCTION error_rule(p_subscription_guid in raw,
6031 p_event in out nocopy wf_event_t) return varchar2
6032 is
6033 nid number;
6034 param_list wf_parameter_list_t;
6035 cb varchar2(240);
6036 ctx varchar2(2000);
6037 itemType varchar2(8);
6038 itemKey varchar2(240);
6039 items pls_integer;
6040 role varchar2(320);
6041
6042 colPos1 pls_integer;
6043 colPos2 pls_integer;
6044
6045 error_name varchar2(4000);
6046 error_msg varchar2(4000);
6047 error_stack varchar2(4000);
6048
6049 -- Dynamic sql stuff
6050 sqlbuf varchar2(120);
6051 tvalue varchar2(4000) := '';
6052 nvalue number := '';
6053 dvalue date := '';
6054 command varchar2(200) :='ERROR';
6055
6056 status varchar2(8);
6057 l_dummy varchar2(1);
6058
6059 begin
6060 param_list := p_event.Parameter_List;
6061 nid := to_number(wf_event.getValueForParameter('NOTIFICATION_ID',
6062 param_list));
6063 error_msg := p_event.getErrorMessage;
6064 error_stack := p_event.getErrorStack;
6065 begin
6066 select MESSAGE_TYPE, CALLBACK, CONTEXT, STATUS
6067 into itemType, cb, ctx, status
6068 from WF_NOTIFICATIONS
6069 where NOTIFICATION_ID = nid;
6070
6071 -- If the notification is closed, then do not bother
6072 -- to process any errors.
6073 if status = 'CLOSED' then
6074 return 'SUCCESS';
6075 end if;
6076
6077 update wf_notifications
6078 set mail_status = 'ERROR'
6079 where notification_id = nid;
6080
6081 if ctx is not null then
6082 colPos1 := instrb(ctx, ':', 1);
6083 colPos2 := instrb(ctx, ':', -1);
6084 if colPos1 > 0 and colPos2 > 0 then
6085 itemKey := substrb(ctx, colPos1+1, (colPos2 - colPos1) -1);
6086 else
6087 itemType := null;
6088 itemKey := null;
6089 end if;
6090 else
6091 itemType := null;
6092 itemKey := null;
6093 end if;
6094
6095 exception
6096 when others then
6097 cb := null;
6098 ctx := null;
6099 itemType := null;
6100 itemKey := null;
6101 return 'SUCCESS';
6102 end;
6103
6104 -- Check to see if the item type still exists and is not
6105 -- complete. If it does not exist or is complete, then
6106 -- do not bother with processing the error.
6107 if itemType is not null and itemKey is not null then
6108 begin
6109 select ACTIVITY_STATUS
6110 into status
6111 from wf_item_activity_statuses ias
6112 , wf_process_activities pa
6113 where ias.item_type = itemType
6114 and ias.item_key = itemKey
6115 and ias.process_activity = pa.instance_id
6116 and pa.process_name = 'ROOT';
6117
6118 -- This will prevent FYI message that are in error being reported.
6119 -- if status = wf_engine.eng_completed then
6120 -- return 'SUCCESS';
6121 -- end if;
6122
6123 exception
6124 when no_data_found then
6125 return 'SUCCESS';
6126 when others then
6127 error_msg := sqlerrm;
6128 wf_core.context('WF_XML','ERROR_RULE','NID['||to_char(nid)||']',
6129 'CTX['||ctx||']');
6130 raise;
6131 end;
6132 else
6133 return 'SUCCESS';
6134 end if;
6135
6136 if cb is not null then
6137 -- Put the error onto the stack.
6138 begin
6139 wf_core.token('ERROR_MESSAGE', error_msg);
6140 wf_core.token('ERROR_STACK', error_stack);
6141 wf_core.raise('WF_ERROR');
6142 exception
6143 when others then null;
6144 end;
6145 l_dummy := '';
6146 -- ### cb is from table
6147 -- BINDVAR_SCAN_IGNORE
6148 sqlbuf := 'begin '||cb||
6149 '(:p1, :p2, :p3, :p4, :p5, :p6, :p7); end;';
6150 begin
6151 execute immediate sqlbuf using
6152 in command,
6153 in ctx,
6154 in l_dummy,
6155 in l_dummy,
6156 in out tvalue,
6157 in out nvalue,
6158 in out dvalue;
6159 exception
6160 when others then
6161 error_msg := sqlerrm;
6162 wf_core.context('WF_XML','ERROR_RULE','NID['||to_char(nid)||']',
6163 'CTX['||ctx||']');
6164 raise;
6165 end;
6166 end if;
6167
6168 return wf_rule.error_rule(p_subscription_guid, p_event);
6169
6170 end error_rule;
6171
6172 -- Gets the LOB content for a PLSQLCLOB
6173 -- IN
6174 -- pAPI the API to call
6175 -- pDoc The LOB to take the document
6176 procedure getDocContent(pNid in NUMBER, pAPI in VARCHAR2,
6177 pDoc in out nocopy CLOB)
6178 is
6179 colon pls_integer;
6180 slash pls_integer;
6181 procname varchar2(240);
6182 procarg varchar2(32000);
6183
6184 target varchar2(240) := '_main';
6185 disptype varchar2(240) := g_ntfDocHtml;
6186 doctype varchar2(240);
6187
6188 sqlbuf varchar2(2000);
6189
6190 begin
6191
6192 colon := instr(pAPI, ':');
6193 slash := instr(pAPI, '/');
6194 if (slash = 0) then
6195 procname := substr(pAPI, colon+1);
6196 procarg := '';
6197 else
6198 procname := substr(pAPI, colon+1, slash-colon-1);
6199 procarg := substr(pAPI, slash+1);
6200 end if;
6201
6202 -- Dynamic sql call to procedure
6203
6204 if (procarg is null) then
6205 procarg := '-dummy-';
6206 elsif pNid > 0 then
6207 procarg := Wf_Notification.GetText(procarg, pNid, disptype);
6208 end if;
6209
6210 sqlbuf := 'begin '||procname||'(:p1, :p2, :p3, :p4); end;';
6211 execute immediate sqlbuf using
6212 in procarg,
6213 in disptype,
6214 in out pDoc,
6215 in out doctype;
6216
6217 end getDocContent;
6218
6219 -- Gets the LOB content for a PLSQLCLOB
6220 -- IN
6221 -- pAPI the API to call
6222 -- pDoc The LOB to take the document
6223 procedure getBDocContent(pNid in NUMBER, pAPI in VARCHAR2,
6224 pDoc in out nocopy BLOB)
6225 is
6226
6227 colon pls_integer;
6228 slash pls_integer;
6229 procname varchar2(240);
6230 procarg varchar2(32000);
6231
6232 target varchar2(240) := '_main';
6233 disptype varchar2(240) := g_ntfDocHtml;
6234 doctype varchar2(240);
6235
6236 sqlbuf varchar2(2000);
6237
6238 begin
6239
6240 colon := instr(pAPI, ':');
6241 slash := instr(pAPI, '/');
6242 if (slash = 0) then
6243 procname := substr(pAPI, colon+1);
6244 procarg := '';
6245 else
6246 procname := substr(pAPI, colon+1, slash-colon-1);
6247 procarg := substr(pAPI, slash+1);
6248 end if;
6249
6250 -- Dynamic sql call to procedure
6251
6252 if (procarg is null) then
6253 procarg := '-dummy-';
6254 elsif pNid > 0 then
6255 procarg := Wf_Notification.GetText(procarg, pNid, disptype);
6256 end if;
6257
6258 sqlbuf := 'begin '||procname||'(:p1, :p2, :p3, :p4); end;';
6259 execute immediate sqlbuf using
6260 in procarg,
6261 in disptype,
6262 in out pDoc,
6263 in out doctype;
6264
6265 end getBDocContent;
6266
6267 -- gets the size of the current LOB table
6268 function getLobTableSize return number
6269 is
6270 begin
6271 return g_LOBTable.COUNT;
6272 end;
6273
6274 end WF_XML;