DBA Data[Home] [Help]

PACKAGE BODY: APPS.FND_PROFILE

Source


1 PACKAGE BODY fnd_profile AS
2    /* $Header: AFPFPROB.pls 120.43.12020000.3 2013/03/21 13:56:52 rarmaly ship $ */
3 
4    TYPE val_tab_type IS TABLE OF VARCHAR2(255) INDEX BY BINARY_INTEGER;
5    TYPE name_tab_type IS TABLE OF VARCHAR2(80) INDEX BY BINARY_INTEGER;
6 
7    /*
8    ** define the internal table that will be used for Public Put cache
9    ** val_tab(x) is associated with name_tab(x) and dbflag(x)
10    */
11    val_tab    val_tab_type; /* the table of values for public cache */
12    name_tab   name_tab_type; /* the table of names for public cache */
13    /* Increase table size to reduce potential hash collisions - bug 12975860 */
14    table_size BINARY_INTEGER := 2147483646; /* the size of above tables*/
15    /* change INSERTED to number to account for PUT deletes - bug 12975860 */
16    inserted NUMBER := 0; /* count of PUT profiles stored */
17 
18    /*
19    ** Global Session ID tracker
20    */
21    current_icx_session_id NUMBER := DEFAULT_CONTEXT;
22 
23    /*
24    ** Global Context values
25    */
26    profiles_user_id   NUMBER := DEFAULT_CONTEXT;
27    profiles_resp_id   NUMBER := DEFAULT_CONTEXT;
28    profiles_appl_id   NUMBER := DEFAULT_CONTEXT;
29    profiles_server_id NUMBER := DEFAULT_CONTEXT;
30    profiles_org_id    NUMBER := DEFAULT_CONTEXT;
31 
32    /*
33    ** Constant string used to indicate that a cache entry is undefined.
34    */
35    FND_UNDEFINED_VALUE VARCHAR2(30) := '**FND_UNDEFINED_VALUE**';
36 
37   /* Global LEVEL_IDs */
38   SITE_LEVEL_ID     NUMBER := 10001;
39   APPL_LEVEL_ID     NUMBER := 10002;
40   RESP_LEVEL_ID     NUMBER := 10003;
41   USER_LEVEL_ID     NUMBER := 10004;
42   SERVER_LEVEL_ID   NUMBER := 10005;
43   ORG_LEVEL_ID      NUMBER := 10006;
44   SERVRESP_LEVEL_ID NUMBER := 10007;
45 
46    /*
47    ** Constant string used to indicate a delete request in PUT cache.
48    ** -- Bug 12875860 - PER Rewrite
49    */
50    FND_DELETE_VALUE VARCHAR2(30) := '**FND_DELETE_VALUE**';
51 
52    /*
53    ** Global variable used to indicate that the PUT cache was cleared during
54    ** the current run of FND_PROFILE.INITIALIZE -- Bug 12875860 - PER Rewrite
55    */
56    put_cache_is_clear BOOLEAN;
57 
58    /*
59    ** Global variable used to identify core logging is enabled or not.
60    */
61    corelog_is_enabled BOOLEAN := nvl(fnd_core_log.is_enabled, FALSE);
62 
63    /*
64    ** Global variable used to identify the profile that core logging tracks.
65    */
66    profile_to_log VARCHAR2(80) := fnd_core_log.profile_to_log;
67 
68    /*
69    ** Global variable that stores Applications Release Major Version
70    */
71    major_version NUMBER := fnd_release.major_version;
72 
73    /*
74    ** Global variable that stores Applications Release Minor Version
75    */
76    minor_version NUMBER := fnd_release.minor_version;
77 
78    /*
79    ** Global variable that stores Applications Release Point Version
80    */
81    point_version NUMBER := fnd_release.point_version;
82 
83    /*
84    ** Global variable that stores the start time of initial
85    ** FND_PROFILE use
86    */
87    start_time NUMBER := dbms_utility.get_time;
88 
89    /*========================================================================
90    |    Private APIs
91     ========================================================================*/
92 
93    /*
94    ** corelog
95    **    wrapper to FND_CORE_LOG.WRITE_PROFILE with defaulting current
96    **    profile context.
97    */
98    PROCEDURE corelog
99    (
100       profileName  IN VARCHAR2,
101       profileValue IN VARCHAR2 DEFAULT NULL,
102       currentAPI   IN VARCHAR2,
103       userId       IN NUMBER DEFAULT profiles_user_id,
104       respId       IN NUMBER DEFAULT profiles_resp_id,
105       applId       IN NUMBER DEFAULT profiles_appl_id,
106       orgId        IN NUMBER DEFAULT profiles_org_id,
107       serverId     IN NUMBER DEFAULT profiles_server_id
108    ) IS
109    BEGIN
110       IF corelog_is_enabled THEN
111          fnd_core_log.write_profile(profileName,
112                                     profileValue,
113                                     currentAPI,
114                                     userId,
115                                     respId,
116                                     applId,
117                                     orgId,
118                                     serverId,
119                                     to_char(dbms_utility.get_time - start_time,
120                                          '999,999,999.99') || ' ms.');
121       END IF;
122    END corelog;
123 
124    /*
125    ** corelog_using_name
126    **    wrapper to FND_CORE_LOG.PUT_LINE, uses profile option name for
127    **    filtering.
128    */
129    PROCEDURE corelog_using_name
130    (
131       profileName IN VARCHAR2,
132       textLine    IN VARCHAR2
133    ) IS
134   BEGIN
135       IF corelog_is_enabled THEN
136          IF profile_to_log IS NULL THEN
137             fnd_core_log.put_line(profileName || ':' || textLine || ':' ||
138                                   to_char(dbms_utility.get_time - start_time,
139                                       '999,999,999.99') || ' ms.');
140          ELSE
141             IF profileName = profile_to_log THEN
142                fnd_core_log.put_line(profileName || ':' || textLine || ':' ||
143                                      to_char(dbms_utility.get_time - start_time,
144                                              '999,999,999.99') || ' ms.');
145             END IF;
146          END IF;
147       END IF;
148    END corelog_using_name;
149 
150    /*
151    ** corelog_line
152    **    wrapper to FND_CORE_LOG.PUT_LINE, logs a textline and does not filter
153    */
154    PROCEDURE corelog_line(textLine IN VARCHAR2) IS
155    BEGIN
156       IF corelog_is_enabled THEN
157          fnd_core_log.put_line(textLine || ':' ||
158                                to_char(dbms_utility.get_time - start_time,
159                                        '999,999,999.99') || ' ms.');
160       END IF;
161    END corelog_line;
162 
163    /*========================================================================
164    |    Private result set caching functions
165     ========================================================================*/
166 
167    /*
168    ** get_profile_rowid
169    **    get the profile option's rowid that can be used to derive the profile
170    **    option's information. The rowid is cached using the PL/SQL
171    **    cross-session function result caching mechanism.
172    */
173    FUNCTION get_profile_rowid(profileName IN VARCHAR2)
174      RETURN ROWID RESULT_CACHE IS
175      profileRowId ROWID := NULL;
176    BEGIN
177       SELECT ROWID
178         INTO profileRowId
179         FROM fnd_profile_options
180        WHERE profile_option_name = profileName
181          AND start_date_active <= SYSDATE
182          AND nvl(end_date_active, SYSDATE) >= SYSDATE;
183       -- Log that the profile exists in fnd_profile_options
184       corelog_using_name(profileName, 'EXISTS in FND_PROFILE_OPTIONS');
185       RETURN profileRowId;
186    EXCEPTION
187       WHEN no_data_found THEN
188          -- Log that profile does not exist
189          corelog_using_name(profileName,
190                             'DOES NOT EXIST in FND_PROFILE_OPTIONS');
191          RETURN NULL;
192    END get_profile_rowid;
193 
194    /*
195    ** get_profile_name
196    **    get the profile option's name using the profile_option_id +
197    **    application_id. The return value is cached using the PL/SQL
198    **    cross-session function result caching mechanism.
199    */
200    FUNCTION get_profile_name
201    (
202       profileOptionId IN NUMBER,
203       applicationId   IN NUMBER
204    ) RETURN VARCHAR2 RESULT_CACHE IS
205       profileName VARCHAR2(80) := NULL;
206    BEGIN
207       SELECT profile_option_name
208         INTO profileName
209         FROM fnd_profile_options
210        WHERE profile_option_id = profileOptionId
211          AND application_id = applicationId;
212       -- Log the profile_option_name given the profileOptionId + applicationId
213       corelog_using_name(profileName,
214                          'PROFILE_OPTION_NAME found for ID:' ||
215                          profileOptionId || ' + AID:' || applicationId);
216       RETURN profileName;
217   EXCEPTION
218       WHEN no_data_found THEN
219          -- Log no profile_option_id given the profileOptionRowId
220          corelog_using_name(profileName,
221                             'PROFILE_OPTION_NAME is NULL for ID:' ||
222                             profileOptionId || ' + AID:' || applicationId);
223          RETURN NULL;
224    END get_profile_name;
225 
226    /*
227    ** get_profile_id
228    **    get the profile option's ID using the rowid. This is used to
229    **    obtain the profile option's value. The return value is cached using
230    **    the PL/SQL cross-session function result caching mechanism.
231    */
232    FUNCTION get_profile_id
233    (
234       profileOptionRowId IN ROWID,
235       profileName        IN VARCHAR2
236    ) RETURN NUMBER RESULT_CACHE IS
237       profileId NUMBER := NULL;
238    BEGIN
239       SELECT profile_option_id
240         INTO profileId
241         FROM fnd_profile_options
242        WHERE ROWID = profileOptionRowId;
243       -- Log the profile_option_id given the profileOptionRowId
244       corelog_using_name(profileName, 'PROFILE_OPTION_ID = ' || profileId);
245       RETURN profileId;
246    EXCEPTION
247       WHEN no_data_found THEN
248          -- Log no profile_option_id given the profileOptionRowId
249          corelog_using_name(profileName, 'PROFILE_OPTION_ID is NULL');
250          RETURN NULL;
251    END get_profile_id;
252 
253    /*
254    ** get_profile_appl_id
255    **    get the profile option's application ID using the rowid. This is
256    **    used to obtain the profile option's value. The return value is cached
257    **    using the PL/SQL cross-session function result caching mechanism.
258    */
259    FUNCTION get_profile_appl_id
260    (
261       profileOptionRowId IN ROWID,
262       profileName        IN VARCHAR2
263    ) RETURN NUMBER RESULT_CACHE IS
264       profileApplId NUMBER := NULL;
265    BEGIN
266       SELECT application_id
267         INTO profileApplId
268         FROM fnd_profile_options
269        WHERE ROWID = profileOptionRowId;
270       -- Log the application_id given the profileOptionRowId
271       corelog_using_name(profileName, 'APPLICATION_ID = ' || profileApplId);
272       RETURN profileApplId;
273    EXCEPTION
274       WHEN no_data_found THEN
275          -- Log no application_id given the profileOptionRowId
276          corelog_using_name(profileName, 'APPLICATION_ID is NULL');
277          RETURN NULL;
278    END get_profile_appl_id;
279 
280    /*
281    ** get_level_enabled_flag
282    **    get the profile option's level_enabled_flag using the rowid. This is
283    **    used to obtain the profile option's value. The return value is cached
284    **    using the PL/SQL cross-session function result caching mechanism.
285    */
286    FUNCTION get_level_enabled_flag
287    (
288       profileOptionRowId IN ROWID,
289       profileName        IN VARCHAR2,
290       levelName          IN VARCHAR2
291    ) RETURN VARCHAR2 RESULT_CACHE IS
292       profileLevelEnabled VARCHAR2(1) := NULL;
293    BEGIN
294       SELECT decode(levelName,
295                     'USER',
296                     user_enabled_flag,
297                     'RESP',
298                     resp_enabled_flag,
299                     'APPL',
300                     app_enabled_flag,
301                     'SERVER',
302                     server_enabled_flag,
303                     'ORG',
304                     org_enabled_flag,
305                     'SERVRESP',
306                     serverresp_enabled_flag,
307                     'SITE',
308                     site_enabled_flag)
309         INTO profileLevelEnabled
310         FROM fnd_profile_options
311        WHERE ROWID = profileOptionRowId;
312       -- Log the site_enabled_flag given the profileOptionRowId
313       corelog_using_name(profileName,
314                          levelName||'_ENABLED_FLAG = ' || profileLevelEnabled);
315       RETURN profileLevelEnabled;
316    EXCEPTION
317       WHEN no_data_found THEN
318          -- Log no site_enabled_flag given the profileOptionRowId
319          corelog_using_name(profileName,
320                             levelName || '_ENABLED_FLAG is NULL');
321          RETURN NULL;
322    END get_level_enabled_flag;
323 
324    /*
325    ** get_hierarchy_type
326    **    get the profile option's hierarchy_type using the rowid. This
327    **    can be used to obtain the profile option's value. The return value is
328    **    cached using the PL/SQL cross-session function result caching
329    **    mechanism.
330    */
331    FUNCTION get_hierarchy_type
332    (
333       profileOptionRowId IN ROWID,
334       profileName        IN VARCHAR2
335    ) RETURN VARCHAR2 RESULT_CACHE IS
336       profileHierarchyType VARCHAR2(8) := NULL;
337    BEGIN
338       SELECT hierarchy_type
339         INTO profileHierarchyType
340         FROM fnd_profile_options
341        WHERE ROWID = profileOptionRowId;
342       -- Log the hierarchy_type given the profileOptionRowId
343       corelog_using_name(profileName,
344                          'HIERARCHY_TYPE = ' || profileHierarchyType);
345       RETURN profileHierarchyType;
346    EXCEPTION
347       WHEN no_data_found THEN
348          -- Log no hierarchy_type given the profileOptionRowId
349          corelog_using_name(profileName, 'HIERARCHY_TYPE is NULL');
350          RETURN NULL;
351    END get_hierarchy_type;
352 
353    /*
354    ** get_user_changeable_flag
355    **    get the profile option's user_changeable_flag using the rowid. This
356    **    can be used to obtain the profile option's value. The return value is
357    **    cached using the PL/SQL cross-session function result caching
358    **    mechanism.
359    */
360    FUNCTION get_user_changeable_flag
361    (
362       profileOptionRowId IN ROWID,
363       profileName        IN VARCHAR2
364    ) RETURN VARCHAR2 RESULT_CACHE IS
365       profileUserChangeable VARCHAR2(1) := NULL;
366    BEGIN
367       SELECT user_changeable_flag
368         INTO profileUserChangeable
369         FROM fnd_profile_options
370        WHERE ROWID = profileOptionRowId;
371       -- Log the user_changeable_flag given the profileOptionRowId
372       corelog_using_name(profileName,
373                          'USER_CHANGEABLE_FLAG = ' || profileUserChangeable);
374       RETURN profileUserChangeable;
375    EXCEPTION
376       WHEN no_data_found THEN
377          -- Log no user_changeable_flag given the profileOptionRowId
378          corelog_using_name(profileName, 'USER_CHANGEABLE_FLAG is NULL');
379          RETURN NULL;
380    END get_user_changeable_flag;
381 
382    /*
383    ** get_site_value
384    **    get the profile option's site-level value based on the profile
385    **    option's id. The results are cached using the PL/SQL cross-session
386    **    function result caching mechanism. This has a dependency on the view
387    **    fnd_profile_values_site_v
388    */
389    FUNCTION get_site_value
390    (
391       profileOptionId IN NUMBER,
392       applicationId   IN NUMBER
393    ) RETURN VARCHAR2 RESULT_CACHE IS
394       siteLevelValue VARCHAR2(240);
395       profileName    VARCHAR2(80) := get_profile_name(profileOptionId,
396                                                       applicationId);
397    BEGIN
398       SELECT profile_option_value
399         INTO siteLevelValue
400         FROM fnd_profile_values_site_v
401        WHERE profile_option_id = profileOptionId
402          AND application_id = applicationId
403          AND profile_option_value IS NOT NULL;
404       corelog_using_name(profileName, 'SITE LEVEL=' || siteLevelValue);
405       RETURN siteLevelValue;
406    EXCEPTION
407       WHEN no_data_found THEN
408          corelog_using_name(profileName, 'SITE LEVEL=NULL');
409          RETURN NULL;
410    END get_site_value;
411 
412    /*
413    ** get_appl_value
414    **    get the profile option's application-level value based on the profile
415    **    option's id and level_value. The results are cached using the PL/SQL
416    **    cross-session function result caching mechanism. This has a
417    **    dependency on the view fnd_profile_values_appl_v
418    */
419    FUNCTION get_appl_value
420    (
421       profileOptionId IN NUMBER,
422       applicationId   IN NUMBER,
423       applId          IN NUMBER
424    ) RETURN VARCHAR2 RESULT_CACHE IS
425       applLevelValue VARCHAR2(240);
426       profileName    VARCHAR2(80) := get_profile_name(profileOptionId,
427                                                       applicationId);
428    BEGIN
429       SELECT profile_option_value
430         INTO applLevelValue
431         FROM fnd_profile_values_appl_v
432        WHERE profile_option_id = profileOptionId
433          AND application_id = applicationId
434          AND level_value = applId
435          AND profile_option_value IS NOT NULL;
436       corelog_using_name(profileName,
437                          'APPL LEVEL=' || applLevelValue ||
438                          ' with application_id ' || applId);
439       RETURN applLevelValue;
440    EXCEPTION
441       WHEN no_data_found THEN
442          corelog_using_name(profileName,
443                             'APPL LEVEL=NULL with application_id ' ||
444                             applId);
445          RETURN NULL;
446    END get_appl_value;
447 
448    /*
449    ** get_resp_value
450    **    get the profile option's responsibility-level value based on the
451    **    profile option's id, level_value, and level_value_application_id. The
452    **    results are cached using the PL/SQL cross-session function result
453    **    caching mechanism. This has a dependency on the view
454    **    fnd_profile_values_resp_v
455    */
456    FUNCTION get_resp_value
457    (
458       profileOptionId IN NUMBER,
459       applicationId   IN NUMBER,
460       respId          IN NUMBER,
461       applId          IN NUMBER
462    ) RETURN VARCHAR2 RESULT_CACHE IS
463       respLevelValue VARCHAR2(240);
464       profileName    VARCHAR2(80) := get_profile_name(profileOptionId,
465                                                       applicationId);
466    BEGIN
467       SELECT profile_option_value
468         INTO respLevelValue
469         FROM fnd_profile_values_resp_v
470        WHERE profile_option_id = profileOptionId
471          AND application_id = applicationId
472          AND level_value = respId
473          AND level_value_application_id = applId
474          AND profile_option_value IS NOT NULL;
475       corelog_using_name(profileName,
476                          'RESP LEVEL=' || respLevelValue ||
477                          ' with responsibility_id ' || respId ||
478                          '+ application_id ' || applId);
479       RETURN respLevelValue;
480    EXCEPTION
481       WHEN no_data_found THEN
482          corelog_using_name(profileName,
483                             'RESP LEVEL=NULL with responsibility_id ' ||
484                             respId || '+ application_id ' || applId);
485          RETURN NULL;
486    END get_resp_value;
487 
488    /*
489    ** get_user_value
490    **    get the profile option's user-level value based on the profile
491    **    option's id and level_value. The results are cached using the PL/SQL
492    **    cross-session function result caching mechanism. This has a
493    **    dependency on the view fnd_profile_values_user_v
494    **
495    **    This is called in get_specific_value().
496    */
497    FUNCTION get_user_value
498    (
499       profileOptionId IN NUMBER,
500       applicationId   IN NUMBER,
501       userId          IN NUMBER
502    ) RETURN VARCHAR2 RESULT_CACHE IS
503       userLevelValue VARCHAR2(240);
504       profileName    VARCHAR2(80) := get_profile_name(profileOptionId,
505                                                       applicationId);
506    BEGIN
507       SELECT profile_option_value
508         INTO userLevelValue
509         FROM fnd_profile_values_user_v
510        WHERE profile_option_id = profileOptionId
511          AND application_id = applicationId
512          AND level_value = userId
513          AND profile_option_value IS NOT NULL;
514       corelog_using_name(profileName,
515                          'USER_LEVEL=' || userLevelValue ||
516                          ' with user_id ' || userId);
517       RETURN userLevelValue;
518    EXCEPTION
519       WHEN no_data_found THEN
520          corelog_using_name(profileName,
521                             'USER_LEVEL=NULL with user_id ' || userId);
522          RETURN NULL;
523    END get_user_value;
524 
525    /*
526    ** get_server_value
527    **    get the profile option's server-level value based on the profile
528    **    option's id and level_value. The results are cached using the PL/SQL
529    **    cross-session function result caching mechanism. This has a
530    **    dependency on the view fnd_profile_values_server_v
531    **
532    **    This is called in get_specific_value().
533    */
534    FUNCTION get_server_value
535    (
536       profileOptionId IN NUMBER,
537       applicationId   IN NUMBER,
538       serverId        IN NUMBER
539    ) RETURN VARCHAR2 RESULT_CACHE IS
540       serverLevelValue VARCHAR2(240);
541       profileName      VARCHAR2(80) := get_profile_name(profileOptionId,
542                                                         applicationId);
543    BEGIN
544       SELECT profile_option_value
545         INTO serverLevelValue
546         FROM fnd_profile_values_server_v
547        WHERE profile_option_id = profileOptionId
548          AND application_id = applicationId
549          AND level_value = serverId
550          AND profile_option_value IS NOT NULL;
551       corelog_using_name(profileName,
552                          'SERVER LEVEL=' || serverLevelValue ||
553                          ' with server_id ' || serverId);
554       RETURN serverLevelValue;
555    EXCEPTION
556       WHEN no_data_found THEN
557          corelog_using_name(profileName,
558                             'SERVER LEVEL=NULL with server_id ' || serverId);
559          RETURN NULL;
560    END get_server_value;
561 
562    /*
563    ** get_org_value
564    **    get the profile option's org-level value based on the profile
565    **    option's id and level_value. The results are cached using the PL/SQL
566    **    cross-session function result caching mechanism. This has a
567    **    dependency on the view fnd_profile_values_org_v
568    **
569    **    This is called in get_specific_value().
570    */
571    FUNCTION get_org_value
572    (
573       profileOptionId IN NUMBER,
574       applicationId   IN NUMBER,
575       orgId           IN NUMBER DEFAULT fnd_global.org_id
576    ) RETURN VARCHAR2 RESULT_CACHE IS
577       orgLevelValue VARCHAR2(240);
578       profileName   VARCHAR2(80) := get_profile_name(profileOptionId,
579                                                      applicationId);
580    BEGIN
581       SELECT profile_option_value
582         INTO orgLevelValue
583         FROM fnd_profile_values_org_v
584        WHERE profile_option_id = profileOptionId
585          AND application_id = applicationId
586          AND level_value = orgId
587          AND profile_option_value IS NOT NULL;
588       corelog_using_name(profileName,
589                          'ORG LEVEL=' || orgLevelValue || ' with org_id ' ||
590                          orgId);
591       RETURN orgLevelValue;
592    EXCEPTION
593       WHEN no_data_found THEN
594          corelog_using_name(profileName,
595                             'ORG LEVEL=NULL with org_id ' || orgId);
596          RETURN NULL;
597    END get_org_value;
598 
599    /*
600    ** get_servresp_level_value
601    **    get the profile option's servresp level value based on the profile
602    **    option's id, responsibility and server context. The results are cached
603    **    using the PL/SQL cross-session function result caching mechanism.
604    **    This has a dependency on the view fnd_profile_values_servresp_v
605    **
606    **    This is called in get_specific_value().
607    */
608    FUNCTION get_servresp_value
609    (
610       profileOptionId IN NUMBER,
611       applicationId   IN NUMBER,
612       respId          IN NUMBER,
613       applId          IN NUMBER,
614       serverId        IN NUMBER
615    ) RETURN VARCHAR2 RESULT_CACHE IS
616       servrespLevelValue VARCHAR2(240);
617       profileName        VARCHAR2(80) := get_profile_name(profileOptionId,
618                                                           applicationId);
619    BEGIN
620       SELECT profile_option_value
621         INTO servrespLevelValue
622         FROM fnd_profile_values_servresp_v
623        WHERE profile_option_id = profileOptionId
624          AND application_id = applicationId
625          AND level_value = respId
626          AND level_value_application_id = applId
627          AND level_value2 = serverId
628          AND profile_option_value IS NOT NULL;
629       corelog_using_name(profileName,
630                          'SERVRESP LEVEL=' || servrespLevelValue ||
631                          ' with resp_id ' || respId || ' + appl_id ' ||
632                          applId || ' + server_id ' || serverId);
633       RETURN servrespLevelValue;
634    EXCEPTION
635       WHEN no_data_found THEN
636          corelog_using_name(profileName,
637                             'SERVRESP LEVEL=NULL' || ' with resp_id ' ||
638                             respId || ' + appl_id ' || applId ||
639                             ' + server_id ' || serverId);
640          RETURN NULL;
641    END get_servresp_value;
642 
643    /*========================================================================
644    |    Private APIs used by Public PUT cache
645     ========================================================================*/
646 
647    /*
648    ** find - find index of a profile option name in the given cache table
649    **
650    ** RETURNS
651    **    table index if found, TABLE_SIZE if not found.
652    */
653    FUNCTION find
654    (
655       profileName      IN VARCHAR2,
656       profileNameTable IN name_tab_type,
657       profileHashValue IN BINARY_INTEGER
658    ) RETURN BINARY_INTEGER IS
659       tableIndex BINARY_INTEGER;
660       found      BOOLEAN;
661       hashValue  NUMBER;
662    BEGIN
663       -- Check if a hash value was provided. If not, generate one given the
664       -- profile option name and the table size
665       IF (profileHashValue IS NULL) THEN
666          tableIndex := dbms_utility.get_hash_value(profileName,
667                                                    1,
668                                                    table_size);
669       ELSE
670          tableIndex := profileHashValue;
671       END IF;
672 
673       -- Check if the table index exists in the profile name table.
674       IF (profileNameTable.exists(tableIndex)) THEN
675          -- If it does, then check to see if the profile name stored in the
676          -- profile name table at that index value is the same as the profile
677          -- name passed in. If it is, then return the table index.
678          IF (profileNameTable(tableIndex) = profileName) THEN
679             RETURN tableIndex;
680          ELSE
681             -- search for the profile option
682 
683             -- store the original hashvalue for the profile option
684             hashValue := tableIndex;
685             -- start search at next entry
686             tableIndex := tableIndex + 1;
687             found     := FALSE;
688             WHILE (tableIndex < table_size)
689                   AND (NOT found) LOOP
690                IF (profileNameTable.exists(tableIndex)) THEN
691                   IF profileNameTable(tableIndex) = profileName THEN
692                      found := TRUE;
693                   ELSE
694                      tableIndex := tableIndex + 1;
695                   END IF;
696                ELSE
697                   RETURN table_size + 1;
698                END IF;
699             END LOOP;
700 
701             IF (NOT found) THEN
702                -- Didn't find any till the end
703                tableIndex := 1; -- Start from the beginning
704                WHILE (tableIndex < hashValue)
705                      AND (NOT found) LOOP
706                   IF (profileNameTable.exists(tableIndex)) THEN
707                      IF profileNameTable(tableIndex) = profileName THEN
708                         found := TRUE;
709                      ELSE
710                         tableIndex := tableIndex + 1;
711                      END IF;
712                   ELSE
713                      RETURN table_size + 1;
714                   END IF;
715                END LOOP;
716             END IF;
717 
718             IF (NOT found) THEN
719                RETURN table_size + 1; -- Return a higher value
720             END IF;
721          END IF;
722       ELSE
723          RETURN table_size + 1;
724       END IF;
725 
726       RETURN tableIndex;
727 
728    EXCEPTION
729       WHEN OTHERS THEN
730          -- The entry doesn't exist
731          RETURN table_size + 1;
732    END find;
733 
734    /*
735    ** find - find index of a profile option name in the Public PUT cache
736    **        table NAME_TAB.
737    **
738    ** RETURNS
739    **    table index, if found. TABLE_SIZE, if not found.
740    */
741    FUNCTION find(profileName IN VARCHAR2) RETURN BINARY_INTEGER IS
742       -- bug 14773322 - index variable to check for deleted value
743       tab_index BINARY_INTEGER;
744 
745    BEGIN
746       -- bug 14773322 - find index variable to check for deleted value
747       tab_index := find(profileName,
748                   name_tab,
749                   dbms_utility.get_hash_value(profileName, 1, table_size));
750       -- bug 14773322 - check for valid index of profile name with deleted value
751       IF (tab_index < table_size AND
752           val_tab(tab_index) = fnd_delete_value) THEN
753          -- The entry doesn't exist
754          RETURN table_size + 1;
755       END IF;
756 
757       RETURN tab_index;
758 
759    EXCEPTION
760       WHEN OTHERS THEN
761          -- The entry doesn't exist
762          RETURN table_size + 1;
763    END find;
764 
765    /*
766    ** put
767    **    Set or insert a profile option value into the Public Put cache. This
768    **    does not place the profile option value in the database and is only
769    **    available during the session.
770    */
771    PROCEDURE put
772    (
773       profileName       IN VARCHAR2,
774       profileValue      IN VARCHAR2,
775       profileNameTable  IN OUT NOCOPY name_tab_type,
776       profileValueTable IN OUT NOCOPY val_tab_type,
777       profileHashValue  IN BINARY_INTEGER
778    ) IS
779 
780       tableIndex BINARY_INTEGER;
781       stored     BOOLEAN;
782       hashValue  BINARY_INTEGER;
783 
784       -- bug 14773322 - remove dodelete procedure which deleted the name/value
785       -- from the PUT cache and searched for existing Collisions to move them back up.
786       -- Instead, to avoid the complexity of handling potential but rare collisions
787       -- store the fnd_delete_value flag as the value and ignore it on find
788 
789    BEGIN
790       -- Log API entry
791       corelog(profileName, profileValue, 'Enter PUT');
792 
793       IF (profileHashValue IS NULL) THEN
794          tableIndex := dbms_utility.get_hash_value(profileName,
795                                                    1,
796                                                    table_size);
797       ELSE
798          tableIndex := profileHashValue;
799       END IF;
800 
801       stored := FALSE;
802 
803       IF (profileNameTable.exists(tableIndex)) THEN
804          hashValue := tableIndex; -- Store the current spot
805          IF (profileNameTable(tableIndex) = profileName) THEN
806             -- Found the profile indexed by the hash value
807             -- bug 14773322 - remove call to dodelete procedure
808 
809             profileValueTable(tableIndex) := profileValue; -- Store new value
810             stored := TRUE;
811          ELSE
812             -- Collision
813             -- start search at next entry
814             tableIndex := tableIndex + 1;
815             WHILE (tableIndex < table_size)
816                   AND (NOT stored) LOOP
817                IF (profileNameTable.exists(tableIndex)) THEN
818                   IF (profileNameTable(tableIndex) = profileName) THEN
819                      -- Found the profile indexed higher than hash
820                      -- bug 14773322 - remove call to dodelete procedure
821 
822                      profileValueTable(tableIndex) := profileValue; -- Store the new value
823                      stored := TRUE;
824                   ELSE
825                      tableIndex := tableIndex + 1;
826                   END IF;
827                ELSE
828                   -- Log API collision - bug 14773322
829                   corelog(profileName, profileValue,
830                           'Collision FP.P stored at ' ||
831                            tableIndex || ' above hash of ' || hashValue);
832                   -- Store the value and profile for the first time
833                   profileValueTable(tableIndex) := profileValue;
834                   profileNameTable(tableIndex) := profileName;
835                   stored := TRUE;
836                END IF;
837             END LOOP;
838 
839             IF (NOT stored) THEN
840                -- Didn't find any free bucket till the end
841                tableIndex := 1;
842                WHILE (tableIndex < hashValue)
843                      AND (NOT stored) LOOP
844                   IF (profileNameTable.exists(tableIndex)) THEN
845                      IF (profileNameTable(tableIndex) = profileName) THEN
846                         -- Found the profile indexed lower than hash value
847                         -- bug 14773322 - remove call to dodelete procedure
848 
849                         profileValueTable(tableIndex) := profileValue; -- Store the new value
850                         stored := TRUE;
851                      ELSE
852                         tableIndex := tableIndex + 1;
853                      END IF;
854                   ELSE
855                      -- Log API collision - bug 14773322
856                      corelog(profileName, profileValue,
857                              'Collision FP.P stored at '||
858                              tableIndex || ' below hash of ' || hashValue);
859                      -- Store the value and profile for the first time
860                      profileValueTable(tableIndex) := profileValue;
861                      profileNameTable(tableIndex) := profileName;
862                      stored := TRUE;
863                   END IF;
864                END LOOP;
865             END IF;
866          END IF;
867       ELSE
868          -- Store the value and profile for the first time
869          -- bug 14773322 - allow delete value flag to be stored
870          profileNameTable(tableIndex) := profileName; -- Enter the profile
871          profileValueTable(tableIndex) := profileValue; -- Store its value
872          stored := TRUE;
873       END IF;
874 
875       -- bug 16327915 removed this section of code
876       -- the inserted PUT counter should only be tracking
877       -- the profiles inserted into generic PUT cache
878       --IF (stored)
879       --   AND (val <> FND_DELETE_VAL) THEN
880       --   inserted := inserted + 1; /* Increment the PUT counter */
881       --END IF;
882 
883       -- Log API exit
884       corelog(profileName, profileValue, 'Exit PUT');
885 
886    EXCEPTION
887       WHEN OTHERS THEN
888         -- bug14773322 - log exception to directly to corelog
889         -- even if profile filter is not enabled
890         corelog_line(profileName || ':' || profileValue ||':' ||
891                                   'PUT raised exception. SQLCODE:' || SQLCODE);
892         -- output exception to corelog
893         corelog_line(dbms_utility.format_error_stack);
894         -- output error line numbers to corelog
895         corelog_line(dbms_utility.format_error_backtrace);
896 
897    END put;
898 
899    /*
900    ** get_put_value
901    **    get the profile option's value from hash table in case a value was
902    **    placed there using PUT(). A profile value in the hash table overrides
903    **    the database value.
904    **
905    **    This is called in value() and get().
906    */
907    FUNCTION get_put_value(profileName IN VARCHAR2) RETURN VARCHAR2 IS
908       tableIndex       BINARY_INTEGER;
909       profileValue     VARCHAR2(240) := NULL;
910       profileNameUpper VARCHAR2(80) := upper(profileName);
911    BEGIN
912       -- Log API entry
913       corelog(profileName,
914               nvl(profileValue, 'NO VALUE'),
915               'Checking Public Put cache');
916       -- Check if the profile name exists in the NAME_TAB.
917       tableIndex := find(profileNameUpper);
918       -- If a valid table index was found, then use the index to obtain the
919       -- profile option value from the VAL_TAB table.
920       IF tableIndex < table_size THEN
921          profileValue := val_tab(tableIndex);
922          -- Log value found in Public Cache, API Exit
923          corelog(profileNameUpper,
924                  nvl(profileValue, 'NO VALUE'),
925                  'Value exists in Public Put cache');
926       ELSE
927          profileValue := NULL;
928          -- Log no value found in Public Put Cache, API Exit
929          corelog(profileNameUpper,
930                  nvl(profileValue, 'NO VALUE'),
931                  'NO VALUE exists in Public Put cache');
932       END IF;
933       RETURN profileValue;
934    EXCEPTION
935       WHEN OTHERS THEN
936          RETURN NULL;
937    END get_put_value;
938 
939    /*
940    ** invalidate_cache
941    **    Call WF_EVENT.RAISE to invalidate the cache entry corresponding to
942    **    the specified profile. This is needed to notify processes monitoring
943    **    the 'oracle.apps.fnd.profile.value.update' event to invalidate their
944    **    cache and reload from the database.
945    */
946    PROCEDURE invalidate_cache
947    (
948       profileName     IN VARCHAR2,
949       levelId         IN NUMBER,
950       levelValue      IN VARCHAR2,
951       levelValueAppId IN VARCHAR2,
952       levelValue2     IN VARCHAR2 DEFAULT NULL
953    ) IS
954 
955       level_value         NUMBER;
956       level_value_appl_id NUMBER;
957       profileNameUpper    VARCHAR2(80) := upper(profileName);
958       event_key           VARCHAR2(255);
959       level_value2        NUMBER;
960 
961    BEGIN
962       IF (levelId = SITE_LEVEL_ID) THEN
963          level_value         := 0;
964          level_value_appl_id := 0;
965       ELSIF (levelId = APPL_LEVEL_ID) THEN
966          level_value         := to_number(levelValue);
967          level_value_appl_id := 0;
968       ELSIF (levelId = RESP_LEVEL_ID) THEN
969          level_value         := to_number(levelValue);
970          level_value_appl_id := to_number(levelValueAppId);
971       ELSIF (levelId = USER_LEVEL_ID) THEN
972          level_value         := to_number(levelValue);
973          level_value_appl_id := 0;
974       ELSIF (levelId = SERVER_LEVEL_ID) THEN
975          level_value         := to_number(levelValue);
976          level_value_appl_id := 0;
977       ELSIF (levelId = ORG_LEVEL_ID) THEN
978          level_value         := to_number(levelValue);
979          level_value_appl_id := 0;
980       ELSIF (levelId = SERVRESP_LEVEL_ID) THEN
981          level_value         := to_number(levelValue);
982          level_value_appl_id := to_number(levelValueAppId);
983          level_value2        := to_number(levelValue2);
984       ELSE
985          RETURN;
986       END IF;
987 
988       IF (levelId = SERVRESP_LEVEL_ID) THEN
989          -- Event Key has level_value2
990          event_key := levelId || ':' || level_value || ':' ||
991                       level_value_appl_id || ':' || level_value2 || ':' ||
992                       profileName;
993       ELSE
994          -- Original event_key format
995          event_key := levelId || ':' || level_value || ':' ||
996                       level_value_appl_id || ':' || profileName;
997       END IF;
998 
999       -- raise event 'oracle.apps.fnd.profile.value.update' to notify
1000       -- processes monitoring the event to invalidate their cache.
1001       fnd_wf_engine.default_event_raise(p_event_name => 'oracle.apps.fnd.profile.value.update',
1002                                         p_event_key  => event_key);
1003 
1004    END invalidate_cache;
1005 
1006    /*========================================================================
1007    |    Private APIs used to fetch profile option values
1008     ========================================================================*/
1009 
1010    /*
1011    ** get_specific_value
1012    **    get the profile option value based on the profile option information
1013    **    and specific context passed into the API.
1014    **    This calls all the functions that have been enabled to use the PL/SQL
1015    **    cross-session function result caching mechanism.
1016    **
1017    ** The algorithm is such:
1018    **    1. Using the profile option information acquired at declaration,
1019    **       determine if the profile exists in FND_PROFILE_OPTIONS. If it does
1020    **       not, return NULL.
1021    **    2. If it exists and the user_enabled_flag is Y, get user level value.
1022    **    3. If there was no user-level value, proceed to check the applicable
1023    **       levels based on the profile option hierarchy.
1024    **    4. If no value was obtained in all the other levels, check the site
1025    **       level if it is enabled for the profile option.
1026    **
1027    **   Context arguments (userId, responsibilityId, applicationId,
1028    **   orgId, serverId) specify what context to use to determine the
1029    **   profile option value.  Context arguments are interpreted as follows:
1030    **
1031    **        NULL - use current session context value (default)
1032    **          -1 - override current context with "undefined" value
1033    **     <value> - override current context with specified value
1034    **
1035    **   Special Notes:
1036    **     - Context override values are only used for determining the profile
1037    **       option value in this function call, the user session context is not
1038    **       changed.
1039    **
1040    **     - An undefined context value (-1) causes that context level to be
1041    **       skipped during processing, meaning that any profile option values
1042    **       set at that context level are ignored.
1043    **
1044    **     - Regardless of which context levels are specified, the profile option
1045    **       HIERARCHY_TYPE and '%_ENABLED_FLAG' flags determine which context
1046    **       levels are searched to find the value.
1047    */
1048    FUNCTION get_specific_value
1049    (
1050       profileName      IN VARCHAR2,
1051       userId           IN NUMBER DEFAULT NULL,
1052       responsibilityId IN NUMBER DEFAULT NULL,
1053       applicationId    IN NUMBER DEFAULT NULL,
1054       orgId            IN NUMBER DEFAULT NULL,
1055       serverId         IN NUMBER DEFAULT NULL
1056    ) RETURN VARCHAR2 RESULT_CACHE IS
1057       profileOptionValue VARCHAR2(240) := NULL;
1058       profileRowId       ROWID := get_profile_rowid(profileName);
1059       profileOptionId    NUMBER := NULL;
1060       profApplicationId  NUMBER := NULL;
1061       siteEnabled        VARCHAR2(1) := NULL;
1062       applEnabled        VARCHAR2(1) := NULL;
1063       respEnabled        VARCHAR2(1) := NULL;
1064       userEnabled        VARCHAR2(1) := NULL;
1065       orgEnabled         VARCHAR2(1) := NULL;
1066       serverEnabled      VARCHAR2(1) := NULL;
1067       servrespEnabled    VARCHAR2(1) := NULL;
1068       hierarchyType      VARCHAR2(8) := NULL;
1069       userChangeable     VARCHAR2(1) := NULL;
1070       -- For any context passed in as NULL, substitute with the current context
1071       l_userId           NUMBER := nvl(userId, profiles_user_id);
1072       l_responsibilityId NUMBER := nvl(responsibilityId, profiles_resp_id);
1073       l_applicationId    NUMBER := nvl(applicationId, profiles_appl_id);
1074       l_orgId            NUMBER := nvl(orgId, profiles_org_id);
1075       l_serverId         NUMBER := nvl(serverId, profiles_server_id);
1076    BEGIN
1077       -- In value() and get(), if profileRowId is NULL, ***FND_UNDEFINED_VALUE***
1078       -- is placed in Public Put Cache. Since this API does not check Public Put
1079       -- Cache when evaluating a profile option, it would be best not to perform
1080       -- any action related to Public Put Cache. Hence, if profileRowId is NULL,
1081       -- then this API will return NULL for a profile that does not exist in
1082       -- FND_PROFILE_OPTIONS. This is different from value() and get() since
1083       -- profiles that do not exist in FND_PROFILE_OPTIONS are categorized as
1084       -- TRANSIENT and may have values in Public Put Cache.
1085       IF profileRowId IS NULL THEN
1086          -- Log that profile option was not found
1087          corelog_using_name(profileName,
1088                             profileName ||
1089                             'does not exist in FND_PROFILE_OPTIONS, returning NULL');
1090          RETURN NULL;
1091       ELSE
1092          -- If profile exists, then retrieve the definition
1093          profileOptionId   := get_profile_id(profileRowId, profileName);
1094          profApplicationId := get_profile_appl_id(profileRowId, profileName);
1095          siteEnabled:= get_level_enabled_flag(profileRowId,profileName,'SITE');
1096          applEnabled := get_level_enabled_flag(profileRowId,profileName,'APPL');
1097          respEnabled := get_level_enabled_flag(profileRowId,profileName,'RESP');
1098          userEnabled := get_level_enabled_flag(profileRowId,profileName,'USER');
1099          orgEnabled := get_level_enabled_flag(profileRowId,profileName,'ORG');
1100          serverEnabled := get_level_enabled_flag(profileRowId,profileName,'SERVER');
1101          servrespEnabled := get_level_enabled_flag(profileRowId,profileName,'SERVRESP');
1102          hierarchyType := get_hierarchy_type(profileRowId,profileName);
1103          userChangeable := get_user_changeable_flag(profileRowId,profileName);
1104 
1105          -- If profile option is enabled at the user level and userId context is
1106          -- not DEFAULT_CONTEXT or NULL, then check to see if there is a user
1107          -- level value. User level is a common level for all hierarchies.
1108          IF (userEnabled = 'Y')
1109             AND ((userId <> DEFAULT_CONTEXT) AND (userId IS NOT NULL)) THEN
1110             /* USER level */
1111             profileOptionValue := get_user_value(profileOptionId,
1112                                                  profApplicationId,
1113                                                  l_userId);
1114          END IF;
1115 
1116          -- If there is a user-level value, log that it was found.
1117          IF profileOptionValue IS NOT NULL THEN
1118             corelog(profileName,
1119                     profileOptionValue,
1120                     'USER LEVEL value for user_id:' || l_userId);
1121             -- If there is no user-level value, then check the intermediate
1122             -- levels based on the profile option's hierarchy.
1123          ELSE
1124             -- If hierarchy_type of profile option is SECURITY, then check to
1125             -- see if there is a RESPONSIBILITY or APPLICATION level value.
1126             IF hierarchyType = 'SECURITY' THEN
1127                -- If profile option is enabled at the resp level and the
1128                -- responsibilityId and applicationId is not DEFAULT_CONTEXT or
1129                -- NULL, then check to see if there is a responsibility level
1130                -- value.
1131                IF (respEnabled = 'Y')
1132                   AND ((l_responsibilityId <> DEFAULT_CONTEXT) AND
1133                   (l_responsibilityId IS NOT NULL))
1134                   AND ((l_applicationId <> DEFAULT_CONTEXT) AND
1135                   (l_applicationId IS NOT NULL)) THEN
1136                   /* RESP level */
1137                   profileOptionValue := get_resp_value(profileOptionId,
1138                                                        profApplicationId,
1139                                                        l_responsibilityId,
1140                                                        l_applicationId);
1141                END IF;
1142 
1143                IF profileOptionValue IS NOT NULL THEN
1144                   -- If there is an responsibility level value, log it was found
1145                   corelog(profileName,
1146                           profileOptionValue,
1147                           'RESP LEVEL value for context=' ||
1148                           l_responsibilityId || '+' || l_applicationId);
1149                   -- If there is no resp-level value and the profile option is
1150                   -- enabled at the application level and the applicationId is not
1151                   -- DEFAULT_CONTEXT or NULL, then check to see if there is an
1152                   -- application level value.
1153                ELSE
1154                   IF (applEnabled = 'Y')
1155                      AND ((l_applicationId <> DEFAULT_CONTEXT) AND
1156                      (l_applicationId IS NOT NULL)) THEN
1157                      /* APPL level */
1158                      profileOptionValue := get_appl_value(profileOptionId,
1159                                                           profApplicationId,
1160                                                           l_applicationId);
1161                   END IF;
1162                   -- If there is an application level value, log it was found
1163                   IF profileOptionValue IS NOT NULL THEN
1164                      corelog(profileName,
1165                              profileOptionValue,
1166                              'APPL LEVEL value for appl_id=' ||
1167                              l_applicationId);
1168                   END IF;
1169                END IF; -- profileOptionValue IS NOT NULL
1170             END IF; -- hierarchyType = 'SECURITY'
1171 
1172             -- If hierarchy_type of profile option is SERVER, then check to see
1173             -- if there is a SERVER level value.
1174             IF hierarchyType = 'SERVER' THEN
1175                -- If profile option is enabled at the server level and the
1176                -- serverId is not DEFAULT_CONTEXT or NULL, then check to see if
1177                -- there is a server level value.
1178                IF (serverEnabled = 'Y')
1179                   AND ((l_serverId <> DEFAULT_CONTEXT) AND
1180                   (l_serverId IS NOT NULL)) THEN
1181                   /* SERVER level */
1182                   profileOptionValue := get_server_value(profileOptionId,
1183                                                          profApplicationId,
1184                                                          l_serverId);
1185                END IF;
1186                IF profileOptionValue IS NOT NULL THEN
1187                   corelog(profileName,
1188                           profileOptionValue,
1189                           'SERVER LEVEL value for server_id=' || l_serverId);
1190                END IF;
1191             END IF; -- hierarchyType = 'SERVER'
1192 
1193             -- If hierarchy_type of profile option is ORG, then check to see if
1194             -- there is an ORG level value.
1195             IF hierarchyType = 'ORG' THEN
1196                -- If profile option is enabled at the org level and the
1197                -- orgId is not DEFAULT_CONTEXT or NULL, then check to see if
1198                -- there is a org level value.
1199                IF (orgEnabled = 'Y')
1200                   AND ((orgId <> DEFAULT_CONTEXT) AND (orgId IS NOT NULL)) THEN
1201                   /* ORG level */
1202                   profileOptionValue := get_org_value(profileOptionId,
1203                                                       profApplicationId,
1204                                                       l_orgId);
1205                END IF;
1206                IF profileOptionValue IS NOT NULL THEN
1207                   corelog(profileName,
1208                           profileOptionValue,
1209                           'ORG LEVEL value for org_id=' || l_orgId);
1210                END IF;
1211             END IF; -- hierarchyType = 'ORG'
1212 
1213             -- If hierarchy_type of profile option is SERVRESP, then check to
1214             -- see if there is a SERVRESP level value.
1215             IF hierarchyType = 'SERVRESP' THEN
1216                -- If profile option is enabled at the servresp level
1217                IF (servrespEnabled = 'Y') THEN
1218                   -- If responsibilityId and applicationId, or serverId is not
1219                   -- DEFAULT_CONTEXT or NULL, then check to see if there is a
1220                   -- servresp level value.
1221                   IF ((((l_responsibilityId <> DEFAULT_CONTEXT) AND
1222                      (l_responsibilityId IS NOT NULL)) AND
1223                      ((l_applicationId <> DEFAULT_CONTEXT) AND
1224                      (l_applicationId IS NOT NULL))) OR
1225                      ((l_serverId <> DEFAULT_CONTEXT) AND
1226                      (l_serverId IS NOT NULL))) THEN
1227                      /* SERVRESP level, all context values */
1228                      profileOptionValue := get_servresp_value(profileOptionId,
1229                                                               profApplicationId,
1230                                                               l_responsibilityId,
1231                                                               l_applicationId,
1232                                                               l_serverId);
1233                      -- If profileOptionValue is NULL then check to see if there
1234                      -- is a servresp level value using the resp and appl
1235                      -- context values
1236                      IF profileOptionValue IS NOT NULL THEN
1237                         -- If there is a servresp-level value, log it was found
1238                         corelog(profileName,
1239                                 profileOptionValue,
1240                                 'SERVRESP LEVEL value for context=' ||
1241                                 l_responsibilityId || '+' ||
1242                                 l_applicationId || '+' || l_serverId);
1243                      ELSE
1244                         /* SERVRESP level, resp and appl context values */
1245                         profileOptionValue := get_servresp_value(profileOptionId,
1246                                                                  profApplicationId,
1247                                                                  l_responsibilityId,
1248                                                                  l_applicationId,
1249                                                                  DEFAULT_CONTEXT);
1250                         -- If profileOptionValue is NULL then check to see if
1251                         -- there is a servresp level value using the server
1252                         -- context value
1253                         IF profileOptionValue IS NOT NULL THEN
1254                            -- If there is a servresp-level value, log it was
1255                            -- found
1256                            corelog(profileName,
1257                                    profileOptionValue,
1258                                    'SERVRESP LEVEL value for context=' ||
1259                                    l_responsibilityId || '+' ||
1260                                    l_applicationId || '+' ||
1261                                    DEFAULT_CONTEXT);
1262                         ELSE
1263                            /* SERVRESP level, server context value */
1264                            profileOptionValue := get_servresp_value(profileOptionId,
1265                                                                     profApplicationId,
1266                                                                     DEFAULT_CONTEXT,
1267                                                                     DEFAULT_CONTEXT,
1268                                                                     l_serverId);
1269                            IF profileOptionValue IS NOT NULL THEN
1270                               -- If there is a servresp-level value, log it was
1271                               -- found
1272                               corelog(profileName,
1273                                       profileOptionValue,
1274                                       'SERVRESP LEVEL value for context=' ||
1275                                       DEFAULT_CONTEXT || '+' ||
1276                                       DEFAULT_CONTEXT || '+' || l_serverId);
1277                            END IF;
1278                         END IF; -- profileOptionValue IS NOT NULL
1279                      END IF; -- profileOptionValue IS NOT NULL
1280                   END IF; -- responsibilityId, applicationId, serverId
1281                END IF; -- servrespEnabled = 'Y'
1282             END IF; -- hierarchyType = 'SERVRESP'
1283          END IF; -- profileOptionValue IS NOT NULL
1284 
1285          -- If there is still no profile option value, then check the site
1286          -- level. The site level value specifies the default value for a
1287          -- profile option. If there is a value at the site-level, it will
1288          -- be returned.
1289          IF profileOptionValue IS NULL THEN
1290             -- If profile option is enabled at the site level, then check to
1291             -- see if there is a site level value. Site level is a common
1292             -- level for all hierarchies.
1293             IF siteEnabled = 'Y' THEN
1294                /* SITE level */
1295                profileOptionValue := get_site_value(profileOptionId,
1296                                                     profApplicationId);
1297                IF profileOptionValue IS NOT NULL THEN
1298                   -- If there is a site-level value, log it was found
1299                   corelog(profileName,
1300                           profileOptionValue,
1301                           'SITE LEVEL value');
1302                END IF; -- profileOptionValue IS NOT NULL for SITE
1303             END IF; -- siteEnabled = 'Y'
1304          END IF; -- profileOptionValue IS NULL
1305       END IF; -- profileRowId is NULL
1306 
1307       RETURN profileOptionValue;
1308 
1309    END get_specific_value;
1310 
1311    /*========================================================================
1312    |    Private AOL INTERNAL USE ONLY APIs
1313     ========================================================================*/
1314    /*
1315    ** FOR AOL INTERNAL USE ONLY - DO NOT CALL DIRECTLY,
1316    ** CALL VIA FND_GLOBAL.INITIALIZE('ORG_ID',org_id)
1317    ** FND_PROFILE.INITIALIZE also calls this API to initialize the org context.
1318    **
1319    ** initialize_org_context - Initializes the org context
1320    */
1321    PROCEDURE initialize_org_context IS
1322    BEGIN
1323       -- Set Global organization context
1324       profiles_org_id := fnd_global.org_id;
1325       -- Cache org-specific transient profile options in Public Put cache
1326       put('CURRENT_ORG_CONTEXT', to_char(fnd_global.org_id));
1327       put('ORG_NAME', fnd_global.org_name);
1328       -- Bug 16327915, ORG_ID is stored in Public PUT cache by Forms user exit.
1329       -- purge previous context cached value of ORG_ID
1330       -- so that the value for current context can be found.
1331       put('ORG_ID', FND_DELETE_VALUE);
1332 
1333       -- Note: For R12, the profile option ORG_ID is not always an
1334       -- equivalent of FND_GLOBAL.ORG_ID, which is the org context. The
1335       -- global variable PROFILES_ORG_ID is the org context used for
1336       -- evaluating org-level profile option values and should be equal to
1337       -- FND_GLOBAL.ORG_ID. A value fetch on the profile option ORG_ID
1338       -- should return the profile option table value, not the org context.
1339       -- This behavior was confirmed with JMARY and SHNARAYA of the MO Team.
1340       -- CURRENT_ORG_CONTEXT is being introduced so that profiles code can
1341       -- provide similar functionality such that FND_GLOBAL.ORG_ID will be
1342       -- equivalent to FND_PROFILE.VALUE('CURRENT_ORG_CONTEXT').
1343       -- FND_PROFILE.VALUE('ORG_ID') will return a value obtained in the
1344       -- FND_PROFILE_OPTION_VALUES table.
1345 
1346    END initialize_org_context;
1347 
1348    /*
1349    ** FOR AOL INTERNAL USE ONLY - DO NOT CALL DIRECTLY, CALL VIA
1350    ** FND_GLOBAL.APPS_INITIALIZE
1351    ** initialize - Initialize the internal profile information
1352    ** The cache is cleared of all database (non-put) options first.
1353    ** Initializes the profiles for the level context information.
1354    */
1355    PROCEDURE initialize
1356    (
1357       user_id_z           IN NUMBER DEFAULT NULL,
1358       responsibility_id_z IN NUMBER DEFAULT NULL,
1359       application_id_z    IN NUMBER DEFAULT NULL,
1360       site_id_z           IN NUMBER DEFAULT NULL
1361    ) IS
1362 
1363       tempName        VARCHAR2(256);
1364       NewICXSessionId NUMBER;
1365    BEGIN
1366       -- Get session ID
1367       NewICXSessionId := icx_sec.g_session_id;
1368 
1369       -- Bug 12875860, We initialize the put cache clear flag here since it
1370       -- should only be tested by FND_GLOBAL after a call to INITIALIZE
1371       put_cache_is_clear := FALSE;
1372 
1373       -- Log the session IDs for reference.
1374       corelog_line('Session IDs: CISId=' || current_icx_session_id ||
1375                    ';NISId=' || NewICXSessionId || ';DBSId=' ||
1376                    userenv('sessionid'));
1377 
1378       -- Clear Public Put cache when ICX session_id changes.
1379       -- NOTE: This needs to stay even when other caches are not cleared on
1380       -- session change. Put cache is always only good for the current ICX
1381       -- session.
1382       --
1383       -- The only real condition for a Public PUT Cache purge is that the
1384       -- current ICX session ID is different from the new ICX session ID
1385       -- returned by ICX_SEC.G_SESSION_ID, and that the current ICX session ID
1386       -- or the new ICX session ID is not DEFAULT_CONTEXT, i.e. -1.
1387       --
1388       IF ((current_icx_session_id IS NULL) OR (NewICXSessionId IS NULL) OR
1389          ((current_icx_session_id <> NewICXSessionId) AND
1390          (current_icx_session_id <> DEFAULT_CONTEXT) AND
1391          (NewICXSessionId <> DEFAULT_CONTEXT))) THEN
1392          name_tab.delete();
1393          val_tab.delete();
1394          -- mskees 9/1/2011 this is a little used flag for FND_GLOBAL
1395          inserted := 0; -- reset PUT count
1396          -- Bug 12875860 set flag for FND_GLOBAL
1397          put_cache_is_clear := TRUE;
1398          -- userenv('sessionid') is the database session id. It is used by
1399          -- FND_GLOBAL for core logging, and is used here to facilitate better
1400          -- readability of afcorelog_*.txt.
1401          corelog_line('Public Put cache purged:CSId=' ||
1402                       current_icx_session_id || ':SId=' || NewICXSessionId || ':' ||
1403                       userenv('sessionid'));
1404       END IF;
1405 
1406       -- Set Global context values
1407       current_icx_session_id := NewICXSessionId;
1408       profiles_user_id       := user_id_z;
1409       profiles_resp_id       := responsibility_id_z;
1410       profiles_appl_id       := application_id_z;
1411       profiles_server_id     := fnd_global.server_id;
1412 
1413       -- Cache the user context passed in
1414       IF (user_id_z IS NOT NULL) THEN
1415          put('USER_ID', to_char(user_id_z));
1416          IF (user_id_z = fnd_global.user_id) THEN
1417             -- Use global to avoid select if current user
1418             tempName := fnd_global.user_name;
1419          ELSIF (user_id_z = DEFAULT_CONTEXT) THEN
1420             tempName := 'DEFAULT_USER';
1421          ELSE
1422             BEGIN
1423                SELECT user_name
1424                  INTO tempName
1425                  FROM fnd_user
1426                 WHERE user_id = user_id_z;
1427             EXCEPTION
1428                WHEN OTHERS THEN
1429                   tempName := '';
1430             END;
1431          END IF;
1432          put('userName', tempName);
1433       END IF;
1434 
1435       -- Log API entry
1436       corelog('PROFILE_INIT',
1437               tempName,
1438               'INITIALIZE',
1439               user_id_z,
1440               responsibility_id_z,
1441               application_id_z,
1442               fnd_global.org_id,
1443               fnd_global.server_id);
1444 
1445       -- Cache the responsibility context passed in
1446       IF ((responsibility_id_z IS NOT NULL) AND
1447          (application_id_z IS NOT NULL)) THEN
1448          put('RESP_ID', to_char(responsibility_id_z));
1449          put('RESP_APPL_ID', to_char(application_id_z));
1450          IF ((responsibility_id_z = fnd_global.resp_id) AND
1451             (application_id_z = fnd_global.resp_appl_id)) THEN
1452             -- Use global to avoid select if current resp
1453             tempName := fnd_global.resp_name;
1454          ELSIF ((responsibility_id_z = DEFAULT_CONTEXT) AND
1455                (application_id_z = DEFAULT_CONTEXT)) THEN
1456             tempName := 'DEFAULT_RESP';
1457          ELSE
1458             BEGIN
1459                SELECT responsibility_name
1460                  INTO tempName
1461                  FROM fnd_responsibility_vl
1462                 WHERE responsibility_id = responsibility_id_z
1463                   AND application_id = application_id_z;
1464             EXCEPTION
1465                WHEN OTHERS THEN
1466                   tempName := '';
1467             END;
1468          END IF;
1469          put('RESP_NAME', tempName);
1470       END IF;
1471 
1472       -- Place the server context in Public Put cache
1473       put('SERVER_ID', to_char(fnd_global.server_id));
1474 
1475       BEGIN
1476          SELECT node_name
1477            INTO tempName
1478            FROM fnd_nodes
1479           WHERE node_id = fnd_global.server_id;
1480       EXCEPTION
1481          WHEN OTHERS THEN
1482             tempName := '';
1483       END;
1484 
1485       put('SERVER_NAME', tempName);
1486 
1487       -- Finally, initialize the org context
1488       initialize_org_context;
1489 
1490    END initialize;
1491 
1492    /*=========================================================================
1493    |    Public APIs
1494     ========================================================================*/
1495 
1496    /*
1497    ** put
1498    **    Set or insert a profile option value into the Public Put  cache. This
1499    **    does not place the profile option value in the database and is only
1500    **    available during the session.
1501    */
1502    PROCEDURE put
1503    (
1504       name IN VARCHAR2,
1505       val  IN VARCHAR2
1506    ) IS
1507       table_index BINARY_INTEGER;  -- bug 16327915 manage PUT count
1508       profileNameUpper VARCHAR2(80) := upper(name);
1509    BEGIN
1510       -- Log API Entry
1511       corelog(profileNameUpper, val, 'Enter Public PUT');
1512 
1513       -- bug 16327915 manage PUT count of Public PUT cache
1514       -- the inserted PUT counter should be tracking
1515       -- the actual number of true profile values in PUT cache
1516       -- not every call to insert any profile value
1517       -- Search for existing profile option in Public PUT cache
1518       table_index := find(profileNameUpper);
1519       -- if the profile exists in the Public PUT cache
1520       IF (table_index < table_size) THEN
1521          -- if profile value is NOT NULL or being marked for delete
1522          IF ((val <> FND_DELETE_VALUE) AND
1523              (val IS NOT NULL)) THEN
1524             -- if existing profile value is marked deleted
1525             IF (val_tab(table_index) = FND_DELETE_VALUE) THEN
1526               -- we will be reviving the current deleted value
1527               -- increment the PUT counter
1528               inserted := inserted + 1;
1529             END IF;
1530          ELSE  -- we are marking this profile for delete
1531             -- if existing profile value is NOT marked deleted
1532             IF (val_tab(table_index) <> FND_DELETE_VALUE) THEN
1533                -- we will be removing the current value
1534                -- decrement PUT counter
1535                IF (inserted > 0) THEN
1536                  inserted := inserted - 1;
1537                END IF;
1538             END IF;
1539          END IF;
1540       ELSE -- profile value NOT existing in Public PUT cache
1541          -- if profile value is NOT NULL or being marked for delete
1542          IF ((val <> FND_DELETE_VALUE) AND
1543              (val IS NOT NULL)) THEN
1544             -- we are inserting a new value
1545             inserted := inserted + 1;
1546          END IF;
1547       END IF;
1548 
1549       -- Call private PUT
1550       put(profileNameUpper,
1551           val,
1552           name_tab,
1553           val_tab,
1554           dbms_utility.get_hash_value(profileNameUpper, 1, table_size));
1555       -- Log API Exit
1556       corelog(profileNameUpper, val, 'Exit Public PUT Count=' || inserted);
1557    END put;
1558 
1559    /*
1560    ** get
1561    **    returns the profile option value using the prevailing security
1562    **    context. This is the procedure API equivalent to value().
1563    **
1564    ** The algorithm is such:
1565    **    1. Check Public Put Cache to see if a value has already been placed for
1566    **       the profile.
1567    **    2. If no value was found in Public Put Cache, check to see if the
1568    **       profile option exists in FND_PROFILE_OPTIONS using
1569    **       get_profile_rowid().
1570    **    3. If the profile option does not exist, then return NULL.
1571    **       If the profile option exists, call get_specific_value() to get a
1572    **       profile option value.
1573    */
1574    PROCEDURE get
1575    (
1576       name IN VARCHAR2,
1577       val  OUT NOCOPY VARCHAR2
1578    ) IS
1579       profileOptionValue VARCHAR2(240) := NULL;
1580       profileNameUpper   VARCHAR2(80) := upper(name);
1581    BEGIN
1582       -- Log entry
1583       corelog(profileNameUpper, nvl(val, 'NO VALUE'), 'Enter GET');
1584       -- Bug 12395376:Check Public Put Cache to see if a value was placed for the
1585       -- profile option using PUT().
1586       profileOptionValue := get_put_value(profileNameUpper);
1587       -- If no value was found in Public Put cache then
1588       IF profileOptionValue IS NOT NULL THEN
1589          -- If the value found in cache is FND_UNDEFINED_VALUE, then reset it
1590          -- back to NULL.
1591          IF (profileOptionValue = fnd_undefined_value) THEN
1592             profileOptionValue := NULL;
1593          END IF;
1594       ELSE
1595          -- If profile option exists, then
1596          IF get_profile_rowid(profileNameUpper) IS NOT NULL THEN
1597             -- call get_specific_value and explicitly pass in the current context,
1598             -- to find the profile option value. Current context needs to be
1599             -- explicitly passed in, so that the result-caching function
1600             -- get_specific_value() caches a value based on that exact function
1601             -- call signature.
1602             profileOptionValue := get_specific_value(profileNameUpper,
1603                                                      profiles_user_id,
1604                                                      profiles_resp_id,
1605                                                      profiles_appl_id,
1606                                                      profiles_org_id,
1607                                                      profiles_server_id);
1608             -- Log that profile option value was found using get_specific_value()
1609             IF profileOptionValue IS NOT NULL THEN
1610                corelog_using_name(profileNameUpper,
1611                                   ' get gsv() returned ' ||
1612                                   profileOptionValue || ':' ||
1613                                   userenv('sessionid'));
1614             END IF;
1615          ELSE
1616             -- Log that profile option was not found
1617             corelog_using_name(profileNameUpper,
1618                                'TRANSIENT, put ' || fnd_undefined_value ||
1619                                ' in Public Put cache');
1620             -- Cache FND_UNDEFINED_VALUE in Public Put cache
1621             put(profileNameUpper, fnd_undefined_value);
1622          END IF;
1623       END IF; -- profileOptionValue IS NOT NULL in Public Put cache
1624       -- Set value for return argmuent
1625       val := profileOptionValue;
1626       -- Log exit
1627       corelog(profileNameUpper, nvl(val, 'NO VALUE'), 'Exit GET');
1628    EXCEPTION
1629       WHEN OTHERS THEN
1630          NULL;
1631    END get;
1632 
1633    /*
1634    ** get_specific
1635    **    returns a profile option value for a specific context or a combination
1636    **    of contexts. The context will default to current context, if no context
1637    **    was provided.
1638    **
1639    **   Context arguments (USER_ID_Z, RESPONSIBILITY_ID_Z, APPLICATION_ID_Z,
1640    **   ORG_ID_Z, SERVER_ID_Z) specify what context to use to determine the
1641    **   profile option value.  Context arguments are interpreted as follows:
1642    **
1643    **        NULL - use current session context value (default)
1644    **          -1 - override current context with "undefined" value
1645    **     <value> - override current context with specified value
1646    **
1647    **   Special Notes:
1648    **     - Context override values are only used for determining the profile
1649    **       option value in this function call, the user session context is not
1650    **       changed.
1651    **
1652    **     - An undefined context value (-1) causes that context level to be
1653    **       skipped during processing, meaning that any profile option values
1654    **       set at that context level are ignored.
1655    **
1656    **     - Regardless of which context levels are specified, the profile option
1657    **       HIERARCHY_TYPE and '%_ENABLED_FLAG' flags determine which context
1658    **       levels are searched to find the value.
1659    */
1660    PROCEDURE get_specific
1661    (
1662       name_z              IN VARCHAR2,
1663       user_id_z           IN NUMBER DEFAULT NULL,
1664       responsibility_id_z IN NUMBER DEFAULT NULL,
1665       application_id_z    IN NUMBER DEFAULT NULL,
1666       val_z               OUT NOCOPY VARCHAR2,
1667       defined_z           OUT NOCOPY BOOLEAN,
1668       org_id_z            IN NUMBER DEFAULT NULL,
1669       server_id_z         IN NUMBER DEFAULT NULL
1670    ) IS
1671 
1672       profNameUpper VARCHAR2(80) := upper(name_z);
1673    BEGIN
1674       -- Log API entry
1675       corelog(profNameUpper,
1676               nvl(val_z, 'NO VALUE'),
1677               'Enter GET_SPECIFIC',
1678               user_id_z,
1679               responsibility_id_z,
1680               application_id_z,
1681               org_id_z,
1682               server_id_z);
1683       -- If override context passed in matches the existing context, call GET
1684       IF ((user_id_z = profiles_user_id) OR (user_id_z IS NULL))
1685          AND ((responsibility_id_z = profiles_resp_id) OR
1686          (responsibility_id_z IS NULL))
1687          AND ((application_id_z = profiles_appl_id) OR
1688          (application_id_z IS NULL))
1689          AND ((org_id_z = profiles_org_id) OR (org_id_z IS NULL))
1690          AND ((server_id_z = profiles_server_id) OR (server_id_z IS NULL)) THEN
1691          -- Log redirect to GET
1692          corelog(profNameUpper,
1693                  nvl(val_z, 'NO VALUE'),
1694                  'CURRENT context, calling GET');
1695          -- call get()
1696          get(profNameUpper, val_z);
1697       ELSE
1698          -- call get_specific_value()
1699          val_z := get_specific_value(profNameUpper,
1700                                      user_id_z,
1701                                      responsibility_id_z,
1702                                      application_id_z,
1703                                      org_id_z,
1704                                      server_id_z);
1705       END IF;
1706       -- If a profile value is found, then the profile option is considered
1707       -- defined.
1708       IF (val_z IS NOT NULL)
1709          AND (val_z <> fnd_undefined_value) THEN
1710          defined_z := TRUE;
1711       ELSE
1712          defined_z := FALSE;
1713       END IF;
1714 
1715       -- Log API exit
1716       corelog(profNameUpper,
1717               nvl(val_z, 'NO VALUE'),
1718               'Exit GET_SPECIFIC',
1719               user_id_z,
1720               responsibility_id_z,
1721               application_id_z,
1722               org_id_z,
1723               server_id_z);
1724    END get_specific;
1725 
1726    /*
1727    ** value
1728    **    returns the profile option value using the prevailing security
1729    **    context. This is the function API equivalent to get().
1730    **
1731    ** The algorithm is such:
1732    **    1. Check Public Put Cache to see if a value has already been placed for
1733    **       the profile.
1734    **    2. If no value was found in Public Put Cache, check to see if the
1735    **       profile option exists in FND_PROFILE_OPTIONS using
1736    **       get_profile_rowid().
1737    **    3. If the profile option does not exist, then return NULL.
1738    **       If the profile option exists, call get_specific_value() to get a
1739    **       profile option value.
1740    **
1741    */
1742    FUNCTION VALUE(NAME IN VARCHAR2) RETURN VARCHAR2 IS
1743       profileOptionValue VARCHAR2(240) := NULL;
1744       profileNameUpper   VARCHAR2(80) := upper(NAME);
1745    BEGIN
1746       -- Log entry
1747       corelog(profileNameUpper,
1748               nvl(profileOptionValue, 'NO VALUE'),
1749               'Enter VALUE');
1750       -- Bug 12395376:Check Public Put Cache to see if a value was placed for the
1751       -- profile option using PUT().
1752       profileOptionValue := get_put_value(profileNameUpper);
1753       -- If no value was found in Public Put cache then
1754       IF profileOptionValue IS NOT NULL THEN
1755          -- If the value found in cache is FND_UNDEFINED_VALUE, then reset it
1756          -- back to NULL.
1757          IF (profileOptionValue = fnd_undefined_value) THEN
1758             profileOptionValue := NULL;
1759          END IF;
1760       ELSE
1761          -- If profile option exists, then
1762          IF get_profile_rowid(profileNameUpper) IS NOT NULL THEN
1763             -- call get_specific_value and explicitly pass in the current context,
1764             -- to find the profile option value. Current context needs to be
1765             -- explicitly passed in, so that the result-caching function
1766             -- get_specific_value() caches a value based on that exact function
1767             -- call signature.
1768             profileOptionValue := get_specific_value(profileNameUpper,
1769                                                      profiles_user_id,
1770                                                      profiles_resp_id,
1771                                                      profiles_appl_id,
1772                                                      profiles_org_id,
1773                                                      profiles_server_id);
1774             -- Log that profile option value was found using get_specific_value()
1775             IF profileOptionValue IS NOT NULL THEN
1776                corelog_using_name(profileNameUpper,
1777                                   ' value gsv() returned ' ||
1778                                   profileOptionValue || ':' ||
1779                                   userenv('sessionid'));
1780             END IF;
1781          ELSE
1782             -- Log that profile option was not found
1783             corelog_using_name(profileNameUpper,
1784                                'TRANSIENT, put ' || fnd_undefined_value ||
1785                                ' in Public Put cache');
1786             -- Cache FND_UNDEFINED_VALUE in Public Put cache
1787             put(profileNameUpper, fnd_undefined_value);
1788          END IF;
1789       END IF; -- profileOptionValue IS NOT NULL in Public Put cache
1790       -- Log exit
1791       corelog(profileNameUpper,
1792               nvl(profileOptionValue, 'NO VALUE'),
1793               'Exit VALUE');
1794       RETURN profileOptionValue;
1795    END VALUE;
1796 
1797    /*
1798    ** value_specific
1799    **    returns the profile value of a specific security context, i.e. user,
1800    **    responsibility, application, server, organization. This is a wrapper
1801    **    function to value_specific_private().
1802    **
1803    **   Context arguments (USER_ID, RESPONSIBILITY_ID, APPLICATION_ID,
1804    **   ORG_ID, SERVER_ID) specify what context to use to determine the
1805    **   profile option value.  Context arguments are interpreted as follows:
1806    **
1807    **        NULL - use current session context value (default)
1808    **          -1 - override current context with "undefined" value
1809    **     <value> - override current context with specified value
1810    **
1811    **   Special Notes:
1812    **     - Context override values are only used for determining the profile
1813    **       option value in this function call, the user session context is not
1814    **       changed.
1815    **
1816    **     - An undefined context value (-1) causes that context level to be
1817    **       skipped during processing, meaning that any profile option values
1818    **       set at that context level are ignored.
1819    **
1820    **     - Regardless of which context levels are specified, the profile option
1821    **       HIERARCHY_TYPE and '%_ENABLED_FLAG' flags determine which context
1822    **       levels are searched to find the value.
1823    **
1824    **     - value_specific() used to be a wrapper for get_specific(). With the
1825    **       RDBMS result-set caching feature, calling get_specific() was
1826    **       impacting performance. Hence, value_specific() now calls either
1827    **       value() or get_specific_value() for better performance.
1828    **
1829    **     - For any NULL context value passed in, the respective profile level
1830    **       context is defaulted.
1831    */
1832    FUNCTION value_specific
1833    (
1834       name              IN VARCHAR2,
1835       user_id           IN NUMBER DEFAULT NULL,
1836       responsibility_id IN NUMBER DEFAULT NULL,
1837       application_id    IN NUMBER DEFAULT NULL,
1838       org_id            IN NUMBER DEFAULT NULL,
1839       server_id         IN NUMBER DEFAULT NULL
1840    ) RETURN VARCHAR2 IS
1841       profileValue     VARCHAR2(255);
1842       profileNameUpper VARCHAR2(80) := upper(name);
1843    BEGIN
1844       -- Log entry
1845       corelog(profileNameUpper,
1846               nvl(profileValue, 'NO VALUE'),
1847               'Enter VALUE_SPECIFIC',
1848               user_id,
1849               responsibility_id,
1850               application_id,
1851               org_id,
1852               server_id);
1853       -- If override context passed in matches the existing context, call
1854       -- value()
1855       IF ((user_id = profiles_user_id) OR (user_id IS NULL))
1856          AND ((responsibility_id = profiles_resp_id) OR
1857          (responsibility_id IS NULL))
1858          AND
1859          ((application_id = profiles_appl_id) OR (application_id IS NULL))
1860          AND ((org_id = profiles_org_id) OR (org_id IS NULL))
1861          AND ((server_id = profiles_server_id) OR (server_id IS NULL)) THEN
1862          -- Log redirect to value()
1863          corelog(profileNameUpper,
1864                  nvl(profileValue, 'NO VALUE'),
1865                  'CURRENT context, calling VALUE',
1866                  user_id,
1867                  responsibility_id,
1868                  application_id,
1869                  org_id,
1870                  server_id);
1871          -- call value()
1872          profileValue := VALUE(profileNameUpper);
1873       ELSE
1874          -- call get_specific_value()
1875          --
1876          -- Bug 12319479: get_specific_value() needs to be explicitly called with
1877          -- the nvl function because the arguments passed into the API defines the
1878          -- signature of the call, and is the basis of the RDBMS result-set caching
1879          -- feature for returning the proper cached value, IF a cached value
1880          -- applies. Note from the comments above:
1881          --    NULL - use current session context value (default)
1882          -- This condition above is what the nvl function is used for.
1883          profileValue := get_specific_value(profileNameUpper,
1884                                             nvl(user_id, profiles_user_id),
1885                                             nvl(responsibility_id,
1886                                                 profiles_resp_id),
1887                                             nvl(application_id,
1888                                                 profiles_appl_id),
1889                                             nvl(org_id, profiles_org_id),
1890                                             nvl(server_id,
1891                                                 profiles_server_id));
1892       END IF;
1893       -- Log exit
1894       corelog(profileNameUpper,
1895               nvl(profileValue, 'NO VALUE'),
1896               'Exit VALUE_SPECIFIC',
1897               user_id,
1898               responsibility_id,
1899               application_id,
1900               org_id,
1901               server_id);
1902 
1903       RETURN profileValue;
1904 
1905    END value_specific;
1906 
1907    /*
1908    ** defined
1909    **    determines whether a profile option has a value using get().
1910    **
1911    **    RETURNS: TRUE, if the profile option has a value
1912    **             FALSE, otherwise.
1913    **
1914    ** NOTE: A return of FALSE does not imply that the profile option is not
1915    **       defined in FND_PROFILE_OPTIONS. It just means that no value was
1916    **       found in Public Put cache or FND_PROFILE_OPTION_VALUES.
1917    */
1918    FUNCTION defined(NAME IN VARCHAR2) RETURN BOOLEAN IS
1919       profileValue VARCHAR2(240);
1920    BEGIN
1921       get(NAME, profileValue);
1922       RETURN(profileValue IS NOT NULL);
1923    END defined;
1924 
1925    /*
1926    ** save_user
1927    **   Saves the value of a profile option, at the user level for the current
1928    **   user, to the database permanently using save(). This routine will not
1929    **   actually commit the changes; the caller must commit.
1930    **
1931    **  RETURNS: TRUE if successful, FALSE if failure.
1932    */
1933    FUNCTION save_user
1934    (
1935       x_name  IN VARCHAR2, /* Profile name you are setting */
1936       x_value IN VARCHAR2 /* Profile value you are setting */
1937    ) RETURN BOOLEAN IS
1938       result BOOLEAN;
1939    BEGIN
1940       result := SAVE(x_name, x_value, 'USER', fnd_global.user_id);
1941       RETURN result;
1942    END save_user;
1943 
1944    /*
1945    ** save
1946    **    Saves the value of a profile option permanently to the database, at any
1947    **    level using the FND_PROFILE_OPTION_VALUES_PKG. This routine can be used
1948    **    at runtime or during patching.  This routine will not actually commit
1949    **    the changes; the caller must commit.
1950    **
1951    **    ('SITE', 'APPL', 'RESP', 'USER', 'SERVER', 'ORG', or 'SERVRESP').
1952    **
1953    **    Examples of use:
1954    **       FND_PROFILE.SAVE('P_NAME', 'P_VAL', 'SITE');
1955    **       FND_PROFILE.SAVE('P_NAME', 'P_VAL', 'APPL', 321532);
1956    **       FND_PROFILE.SAVE('P_NAME', 'P_VAL', 'RESP', 321532, 345234);
1957    **       FND_PROFILE.SAVE('P_NAME', 'P_VAL', 'USER', 123321);
1958    **       FND_PROFILE.SAVE('P_NAME', 'SERVER', 25);
1959    **       FND_PROFILE.SAVE('P_NAME', 'ORG', 204);
1960    **       FND_PROFILE.SAVE('P_NAME', 'SERVRESP', 321532, 345234, 25);
1961    **       FND_PROFILE.SAVE('P_NAME', 'SERVRESP', 321532, 345234, -1);
1962    **       FND_PROFILE.SAVE('P_NAME', 'SERVRESP', -1, -1, 25);
1963    **
1964    **    Arguments/Parameters:
1965    **       profileName       - Profile name you are setting
1966    **       profileValue      - Profile value you are setting
1967    **       levelName         - Level that you're setting at:
1968    **                           'SITE','APPL','RESP','USER', etc.
1969    **       levelValue        - context value used for setting profile option
1970    **                           value, e.g. user_id for 'USER' level. This does
1971    **                           not apply to 'SITE' level.
1972    **       levelValueAppId   - applies to 'RESP' and 'SERVRESP' levels, i.e.
1973    **                           the Resp Application_Id.
1974    **       levelValue2       - 2nd context value used for setting profile
1975    **                           option value.  This applies to the 'SERVRESP'
1976    **                           hierarchy.
1977    **
1978    **  RETURNS: TRUE if successful, FALSE if failure.
1979    */
1980    FUNCTION SAVE(x_name IN VARCHAR2,
1981                  /* Profile name you are setting */
1982                  x_value IN VARCHAR2,
1983                  /* Profile value you are setting */
1984                  x_level_name IN VARCHAR2,
1985                  /* Level that you're setting at: 'SITE','APPL','RESP','USER',
1986                                     etc. */
1987                  x_level_value IN VARCHAR2 DEFAULT NULL,
1988                  /* Level value that you are setting at, e.g. user id for 'USER'
1989                                     level. X_LEVEL_VALUE is not used at site level. */
1990                  x_level_value_app_id IN VARCHAR2 DEFAULT NULL,
1991                  /* Used for 'RESP' and 'SERVRESP' level; Resp Application_Id. */
1992                  x_level_value2 IN VARCHAR2 DEFAULT NULL
1993                  /* 2nd Level value that you are setting at.  This is for the
1994                                     'SERVRESP' hierarchy. */)
1995      RETURN BOOLEAN IS
1996       profNameUpper      VARCHAR2(80) := upper(x_name);
1997       profileRowId       ROWID := get_profile_rowid(profNameUpper);
1998       profileOptionId    NUMBER := NULL;
1999       applicationId      NUMBER := NULL;
2000       siteEnabled        VARCHAR2(1) := NULL;
2001       applEnabled        VARCHAR2(1) := NULL;
2002       respEnabled        VARCHAR2(1) := NULL;
2003       userEnabled        VARCHAR2(1) := NULL;
2004       orgEnabled         VARCHAR2(1) := NULL;
2005       serverEnabled      VARCHAR2(1) := NULL;
2006       servrespEnabled    VARCHAR2(1) := NULL;
2007       hierarchyType      VARCHAR2(8) := NULL;
2008       userChangeable     VARCHAR2(1) := NULL;
2009       profileOptionValue VARCHAR2(240);
2010       levelId            NUMBER;
2011       levelValueActual   NUMBER;
2012       levelValue2Actual  NUMBER;
2013       userName           VARCHAR2(100);
2014    BEGIN
2015 
2016       fnd_core_log.write_profile_save(profNameUpper,
2017                                       nvl(x_value, 'NO VALUE') ||
2018                                       ':Enter SAVE',
2019                                       x_level_name,
2020                                       x_level_value,
2021                                       x_level_value_app_id,
2022                                       x_level_value2);
2023 
2024       -- If profile option value being set is > 240 characters, then place the
2025       -- message FND_PROFILE_OPTION_VAL_TOO_LRG into the error stack and
2026       -- return FALSE.
2027       --
2028       -- The lengthb() function replaced the length() function to handle
2029       -- multibyte characters appropriately.
2030       IF lengthb(x_value) > 240 THEN
2031          fnd_message.set_name('FND', 'FND_PROFILE_OPTION_VAL_TOO_LRG');
2032          fnd_message.set_token('PROFILE_OPTION_NAME', profNameUpper);
2033          fnd_message.set_token('PROFILE_OPTION_VALUE', x_value);
2034          RETURN FALSE;
2035       END IF;
2036 
2037       IF (profileRowId IS NULL) THEN
2038          -- Log save attempt for non-existent profile
2039          corelog_line('Cannot save value for non-existent profile ' ||
2040                       profNameUpper);
2041          RETURN FALSE;
2042       ELSE
2043          -- If profile option exists, then retrieve the definition
2044          profileOptionId := get_profile_id(profileRowId, profNameUpper);
2045          applicationId   := get_profile_appl_id(profileRowId, profNameUpper);
2046          siteEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'SITE');
2047          applEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'APPL');
2048          respEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'RESP');
2049          userEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'USER');
2050          orgEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'ORG');
2051          serverEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'SERVER');
2052          servrespEnabled := get_level_enabled_flag(profileRowId,profNameUpper,'SERVRESP');
2053          hierarchyType := get_hierarchy_type(profileRowId,profNameUpper);
2054          userChangeable := get_user_changeable_flag(profileRowId,profNameUpper);
2055       END IF;
2056 
2057       /* The following IF-THEN statements check to see if the arguments passed
2058       ** into SAVE comply with FND_PROFILE_OPTION_VALUES constraints with
2059       ** regards to saving profile option values.
2060       */
2061 
2062       -- The LEVEL_VALUE_APPLICATION_ID applies to the Resp and Server/Resp
2063       -- levels only.
2064       IF (x_level_value_app_id IS NOT NULL AND x_level_name <> 'RESP' AND
2065          x_level_name <> 'SERVRESP') THEN
2066          RETURN FALSE;
2067       END IF;
2068 
2069       -- The LEVEL_VALUE can only be null for SITE level.
2070       IF (x_level_value IS NULL) THEN
2071          levelValueActual := 0;
2072          IF (x_level_name <> 'SITE') THEN
2073             RETURN FALSE; -- Only allow NULL levelValue at SITE level
2074          END IF;
2075 
2076          -- The LEVEL_VALUE2 is required for SERVRESP level, -1 should be passed
2077          -- as a default.
2078       ELSIF ((x_level_name = 'SERVRESP') AND (x_level_value2 IS NULL)) THEN
2079          -- 'SERVRESP' requires a value for levelValue2 to save
2080          -- the profile option value properly.
2081          RETURN FALSE;
2082       ELSE
2083          levelValueActual := to_number(x_level_value);
2084          IF (x_level_name = 'SERVRESP')
2085             AND (x_level_value2 IS NOT NULL) THEN
2086             levelValue2Actual := to_number(x_level_value2);
2087          END IF;
2088       END IF;
2089 
2090       /* Check if the profile option value being saved is already the profile
2091       ** option's value at the level specified. If it is, then just return TRUE.
2092       ** This IF-THEN block uses the functions that are enabled for result set
2093       ** caching.
2094       */
2095       -- SITE level
2096       IF (x_level_name = 'SITE' AND siteEnabled = 'Y') THEN
2097          levelId := SITE_LEVEL_ID;
2098 
2099          IF (levelValueActual <> 0) THEN
2100             RETURN FALSE; -- the only site-level allowed is zero.
2101          END IF;
2102          corelog_using_name(profNameUpper, 'SAVE:GSV, Site');
2103          profileOptionValue := get_site_value(profileOptionId,
2104                                               applicationId);
2105 
2106          -- APPLICATION level
2107       ELSIF (x_level_name = 'APPL' AND applEnabled = 'Y') THEN
2108          levelId := APPL_LEVEL_ID;
2109          corelog_using_name(profNameUpper, 'SAVE:GAV, Appl');
2110          profileOptionValue := get_appl_value(profileOptionId,
2111                                               applicationId,
2112                                               levelValueActual);
2113 
2114          -- RESPONSIBILITY level
2115       ELSIF (x_level_name = 'RESP' AND respEnabled = 'Y') THEN
2116          levelId := RESP_LEVEL_ID;
2117          corelog_using_name(profNameUpper, 'SAVE:GRV, Resp');
2118          profileOptionValue := get_resp_value(profileOptionId,
2119                                               applicationId,
2120                                               levelValueActual,
2121                                               x_level_value_app_id);
2122 
2123          -- USER level
2124       ELSIF (x_level_name = 'USER' AND userEnabled = 'Y') THEN
2125          levelId := USER_LEVEL_ID;
2126          corelog_using_name(profNameUpper, 'SAVE:GUV, User');
2127          profileOptionValue := get_user_value(profileOptionId,
2128                                               applicationId,
2129                                               levelValueActual);
2130          corelog_using_name(profNameUpper,
2131                             'SAVE:GUV, User:' ||
2132                             nvl(profileOptionValue, 'NULL'));
2133          -- SERVER level
2134       ELSIF (x_level_name = 'SERVER' AND serverEnabled = 'Y') THEN
2135          levelId := SERVER_LEVEL_ID;
2136          corelog_using_name(profNameUpper, 'SAVE:GSV, Server');
2137          profileOptionValue := get_server_value(profileOptionId,
2138                                                 applicationId,
2139                                                 levelValueActual);
2140 
2141          -- ORGANIZATION level
2142       ELSIF (x_level_name = 'ORG' AND orgEnabled = 'Y') THEN
2143          levelId := ORG_LEVEL_ID;
2144          corelog_using_name(profNameUpper, 'SAVE:GOV, Org');
2145          profileOptionValue := get_org_value(profileOptionId,
2146                                              applicationId,
2147                                              levelValueActual);
2148 
2149          -- SERVER+RESPONSIBILITY level
2150       ELSIF (x_level_name = 'SERVRESP' AND servrespEnabled = 'Y') THEN
2151          levelId := SERVRESP_LEVEL_ID;
2152          corelog_using_name(profNameUpper, 'SAVE:GSRV, ServResp');
2153          profileOptionValue := get_servresp_value(profileOptionId,
2154                                                   applicationId,
2155                                                   levelValueActual,
2156                                                   x_level_value_app_id,
2157                                                   levelValue2Actual);
2158       ELSE
2159          -- If the conditions were not met, then the SAVE() call was likely
2160          -- attempting to save a value that violates the hierarchy and enabled
2161          -- flag constraints, e.g. if level specified is USER and the
2162          -- USER_ENABLED_FLAG is disabled, the value should not be saved.
2163          corelog_line('Conditions not met to save value for ' ||
2164                       'profile ' || profNameUpper);
2165          RETURN FALSE;
2166       END IF;
2167 
2168       -- If the profile option value being saved is the same as the value
2169       -- obtained from the get functions, then there is no need to go further.
2170       -- Just return TRUE;
2171       IF ((profileOptionValue = x_value) OR
2172          (profileOptionValue IS NULL AND x_value IS NULL)) THEN
2173          corelog_line('Value being saved is already the ' ||
2174                       'current value for profile ' || profNameUpper);
2175          RETURN TRUE;
2176       END IF;
2177 
2178       -- If profile option value passed in is NULL, then clear accordingly.
2179       IF (x_value IS NULL) THEN
2180          -- If SERVRESP level, then take LEVEL_VALUE2 into consideration.
2181          IF (levelId = SERVRESP_LEVEL_ID) THEN
2182             -- DELETE
2183             fnd_profile_option_values_pkg.delete_row(applicationId,
2184                                                      profileOptionId,
2185                                                      levelId,
2186                                                      levelValueActual,
2187                                                      x_level_value_app_id,
2188                                                      levelValue2Actual);
2189             -- raise cache invalidation event for processes monitoring the
2190             -- event
2191             invalidate_cache(profNameUpper,
2192                              levelId,
2193                              levelValueActual,
2194                              x_level_value_app_id,
2195                              levelValue2Actual);
2196          ELSE
2197             -- DELETE
2198             fnd_profile_option_values_pkg.delete_row(applicationId,
2199                                                      profileOptionId,
2200                                                      levelId,
2201                                                      levelValueActual,
2202                                                      x_level_value_app_id);
2203             -- raise cache invalidation event for processes monitoring the
2204             -- event
2205             invalidate_cache(profNameUpper,
2206                              levelId,
2207                              levelValueActual,
2208                              x_level_value_app_id);
2209          END IF;
2210       ELSE
2211          -- If profile option value passed in is NOT NULL, then update
2212          -- accordingly. FND_PROFILE_OPTION_VALUES_PKG.UPDATE_ROW() will call
2213          -- FND_PROFILE_OPTION_VALUES_PKG.INSERT_ROW(), if needed. There is no
2214          -- need to call FND_PROFILE_OPTION_VALUES_PKG.INSERT_ROW(), explicitly,
2215          -- from here. If SERVRESP level, then take LEVEL_VALUE2 into
2216          -- consideration.
2217          IF (levelId = SERVRESP_LEVEL_ID) THEN
2218             fnd_profile_option_values_pkg.update_row(applicationId,
2219                                                      profileOptionId,
2220                                                      levelId,
2221                                                      levelValueActual,
2222                                                      x_level_value_app_id,
2223                                                      levelValue2Actual,
2224                                                      x_value,
2225                                                      SYSDATE,
2226                                                      nvl(fnd_global.user_id,
2227                                                          DEFAULT_CONTEXT),
2228                                                      nvl(fnd_global.login_id,
2229                                                          DEFAULT_CONTEXT));
2230             -- raise cache invalidation event for processes monitoring the
2231             -- event
2232             invalidate_cache(profNameUpper,
2233                              levelId,
2234                              levelValueActual,
2235                              x_level_value_app_id,
2236                              levelValue2Actual);
2237          ELSE
2238             fnd_profile_option_values_pkg.update_row(applicationId,
2239                                                      profileOptionId,
2240                                                      levelId,
2241                                                      levelValueActual,
2242                                                      x_level_value_app_id,
2243                                                      NULL,
2244                                                      x_value,
2245                                                      SYSDATE,
2246                                                      nvl(fnd_global.user_id,
2247                                                          DEFAULT_CONTEXT),
2248                                                      nvl(fnd_global.login_id,
2249                                                          DEFAULT_CONTEXT));
2250             -- raise cache invalidation event for processes monitoring the
2251             -- event
2252             invalidate_cache(profNameUpper,
2253                              levelId,
2254                              levelValueActual,
2255                              x_level_value_app_id);
2256          END IF;
2257       END IF;
2258 
2259       /* Bug 3203225: PREFERENCES NOT UPDATED ON FLY IN WF_ROLES VIEW
2260       ** needs to call FND_USER_PKG.User_Synch() whenever an update to
2261       ** ICX_LANGUAGE or ICX_TERRITORY is updated at the user level.
2262       */
2263       IF ((profNameUpper = 'ICX_LANGUAGE') OR
2264          (profNameUpper = 'ICX_TERRITORY')) THEN
2265          IF ((levelId = USER_LEVEL_ID) AND (levelValueActual IS NOT NULL)) THEN
2266             SELECT user_name
2267               INTO userName
2268               FROM fnd_user
2269              WHERE user_id = levelValueActual;
2270 
2271             fnd_user_pkg.user_synch(userName);
2272          END IF;
2273       END IF;
2274 
2275       -- Log exit
2276       fnd_core_log.write_profile_save(profNameUpper,
2277                                       nvl(x_value, 'NO VALUE') ||
2278                                       ':Exit SAVE',
2279                                       x_level_name,
2280                                       x_level_value,
2281                                       x_level_value_app_id,
2282                                       x_level_value2);
2283 
2284       RETURN TRUE;
2285 
2286    END SAVE;
2287 
2288    /*
2289    ** delete
2290    **    deletes the value of a profile option permanently from the database, at
2291    **    any level.  This routine serves as a wrapper to the SAVE routine which
2292    **    means that this routine can be used at runtime or during patching. Like
2293    **    the SAVE routine, this routine will not actually commit the changes;
2294    **    the caller must commit. This API was added for enhancement request
2295    **    4430579.
2296    **
2297    **        ('SITE', 'APPL', 'RESP', 'USER', 'SERVER', 'ORG', or 'SERVRESP').
2298    **
2299    **        Examples of use:
2300    **        FND_PROFILE.DELETE('P_NAME', 'SITE');
2301    **        FND_PROFILE.DELETE('P_NAME', 'APPL', 321532);
2302    **        FND_PROFILE.DELETE('P_NAME', 'RESP', 321532, 345234);
2303    **        FND_PROFILE.DELETE('P_NAME', 'USER', 123321);
2304    **        FND_PROFILE.DELETE('P_NAME', 'SERVER', 25);
2305    **        FND_PROFILE.DELETE('P_NAME', 'ORG', 204);
2306    **        FND_PROFILE.DELETE('P_NAME', 'SERVRESP', 321532, 345234, 25);
2307    **        FND_PROFILE.DELETE('P_NAME', 'SERVRESP', 321532, 345234, -1);
2308    **        FND_PROFILE.DELETE('P_NAME', 'SERVRESP', -1, -1, 25);
2309    **
2310    **    Arguments/Parameters:
2311    **       profileName       - Profile name whose value is to be deleted
2312    **       levelName         - Level deleting at:
2313    **                           'SITE','APPL','RESP','USER', etc.
2314    **       levelValue        - context value used for deleting profile option
2315    **                           value, e.g. user_id for 'USER' level. This does
2316    **                            not apply to 'SITE' level.
2317    **       levelValueAppId   - applies to 'RESP' and 'SERVRESP' levels, i.e.
2318    **                           the Resp Application_Id.
2319    **       levelValue2       - 2nd context value used for deleting profile
2320    **                           option value.  This applies to the 'SERVRESP'
2321    **                           hierarchy.
2322    **
2323    **  RETURNS: TRUE if successful, FALSE if failure.
2324    */
2325    FUNCTION DELETE(x_name IN VARCHAR2,
2326                    /* Profile name you are setting */
2327                    x_level_name IN VARCHAR2,
2328                    /* Level that you're setting at: 'SITE','APPL','RESP','USER',
2329                                         etc. */
2330                    x_level_value IN VARCHAR2 DEFAULT NULL,
2331                    /* Level value that you are setting at, e.g. user id for
2332                                         'USER' level. X_LEVEL_VALUE is not used at site level. */
2333                    x_level_value_app_id IN VARCHAR2 DEFAULT NULL,
2334                    /* Used for 'RESP' and 'SERVRESP' level; Resp Application_Id. */
2335                    x_level_value2 IN VARCHAR2 DEFAULT NULL
2336                    /* 2nd Level value that you are setting at.  This is for the
2337                                         'SERVRESP' hierarchy only. */)
2338       RETURN BOOLEAN IS
2339       deleted BOOLEAN;
2340    BEGIN
2341       -- Call SAVE() and pass NULL for the profile option value. This
2342       -- physically deletes the row from FND_PROFILE_OPTION_VALUES. Ideally,
2343       -- FND_PROFILE_OPTION_VALUES_PKG.DELETE_ROW would be called. However, all
2344       -- validation/conversion performed in SAVE() would have to be written here
2345       -- as well OR writing a completely separate API just to validate the data
2346       -- so that both SAVE and DELETE can use it.
2347       deleted := SAVE(x_name,
2348                       NULL,
2349                       x_level_name,
2350                       x_level_value,
2351                       x_level_value_app_id,
2352                       x_level_value2);
2353       RETURN deleted;
2354    END DELETE;
2355 
2356    /*
2357    ** bumpCacheVersion_RF
2358    **    The rule function for FND's subscription on the
2359    **    oracle.apps.fnd.profile.value.update event.
2360    **    Since level hash table caches are no longer used due to the PL/SQL
2361    **    cross-session function result caching mechanism, this is really no
2362    **    longer being used. It will return SUCCESS for backward compatibility.
2363    */
2364    FUNCTION bumpcacheversion_rf
2365    (
2366       p_subscription_guid IN RAW,
2367       p_event             IN OUT NOCOPY wf_event_t
2368    ) RETURN VARCHAR2 IS
2369    BEGIN
2370       RETURN 'SUCCESS';
2371    END;
2372 
2373    /*
2374    ** putmultiple
2375    **    puts multiple option pairs in the table
2376    **
2377    **    The name and val VARCHAR2s are of max size 2000, and hold the
2378    **    concatenations of the strings for each individual pair, with null
2379    **    terminators (CHR(0)) to seperate the values.  The number of pairs
2380    **    is passed in numval.  This setup is to avoid the overhead of calling
2381    **    the put routine multiple times.
2382    **
2383    ** [NOTE: THIS API IS FOR AOL INTERNAL USE ONLY.]
2384    */
2385    PROCEDURE putmultiple
2386    (
2387       names IN VARCHAR2,
2388       vals  IN VARCHAR2,
2389       num   IN NUMBER
2390    ) IS
2391       pairnum   NUMBER;
2392       nstartloc NUMBER;
2393       nendloc   NUMBER;
2394       vstartloc NUMBER;
2395       vendloc   NUMBER;
2396       onename   VARCHAR2(81);
2397       oneval    VARCHAR2(256);
2398    BEGIN
2399       nstartloc := 1;
2400       vstartloc := 1;
2401       FOR pairnum IN 1 .. num LOOP
2402          nendloc   := instr(names, chr(0), nstartloc);
2403          onename   := substr(names, nstartloc, nendloc - nstartloc);
2404          nstartloc := nendloc + 1;
2405          vendloc   := instr(vals, chr(0), vstartloc);
2406          oneval    := substr(vals, vstartloc, vendloc - vstartloc);
2407          vstartloc := vendloc + 1;
2408          put(onename, oneval);
2409       END LOOP;
2410 
2411    EXCEPTION
2412       WHEN OTHERS THEN
2413          NULL;
2414    END putmultiple;
2415 
2416    /*
2417    ** get_all_table_values
2418    **    get all the values from the Public Put Cache. The varchar2 returned
2419    **    can be up to 32767 characters long.
2420    **
2421    ** [NOTE: THIS API IS FOR AOL INTERNAL USE ONLY.]
2422    */
2423    FUNCTION get_all_table_values(delim IN VARCHAR2) RETURN VARCHAR2 IS
2424       table_index BINARY_INTEGER;
2425       retval      VARCHAR2(32767);
2426       val         VARCHAR2(1000);
2427    BEGIN
2428       -- check inserted counter - bug 12975860
2429       IF (inserted = 0) THEN
2430          RETURN NULL;
2431       END IF;
2432       table_index := 1;
2433       retval      := 'PUT CACHE: ';
2434       WHILE (table_index < table_size) LOOP
2435 
2436          IF (name_tab.exists(table_index) AND
2437              (val_tab(table_index) IS NOT NULL)) THEN
2438             val := name_tab(table_index) || delim || val_tab(table_index) ||
2439                    delim;
2440             corelog_line('FP.GATV: ' ||val);
2441             IF length(val) + length(retval) > 32767 THEN
2442                RETURN retval;
2443             END IF;
2444             retval := retval || val;
2445          END IF;
2446 
2447          table_index := table_index + 1;
2448 
2449       END LOOP;
2450 
2451       RETURN retval;
2452 
2453    EXCEPTION
2454       WHEN OTHERS THEN
2455          -- add a corelog dump on exception
2456          corelog_line('GET_ALL_TABLE_VALUES raised exception. SQLCODE:' || SQLCODE);
2457          -- output exception to corelog
2458          corelog_line(dbms_utility.format_error_stack);
2459          -- output error line numbers to corelog
2460          corelog_line(dbms_utility.format_call_stack);
2461          RETURN NULL;
2462 
2463    END get_all_table_values;
2464 
2465 
2466    /*
2467    ** get_table_value
2468    **    get the value of a profile option from Public Put Cache. This is a
2469    **    wrapper to get_put_value().
2470    **
2471    ** [NOTE: THIS API IS FOR AOL INTERNAL USE ONLY.]
2472    */
2473    FUNCTION get_table_value(name IN VARCHAR2) RETURN VARCHAR2 IS
2474    BEGIN
2475       RETURN get_put_value(name);
2476    END get_table_value;
2477 
2478    /*
2479    ** AOL INTERNAL USE ONLY
2480    **
2481    ** PUT_CACHE_CLEARED - returns true if the put cache was cleared.
2482    */
2483    FUNCTION put_cache_cleared RETURN BOOLEAN IS
2484    BEGIN
2485       RETURN(put_cache_is_clear);
2486    END put_cache_cleared;
2487 
2488    /*
2489    ** value_wnps
2490    **    returns the profile option value using the prevailing security
2491    **    context. This is a wrapper function to value().
2492    **
2493    ** NOTE: Prior to 11g Profile Options Caching, this routine did the
2494    **       same thing as VALUE(); it returns a profile value from the profile
2495    **       cache, or from the database if it isn't already in the profile
2496    **       cache already.  The only difference between this and VALUE() is
2497    **       that this will not put the value into the pl/sql hash table level
2498    **       caches if it is not already there, so repeated calls to this can
2499    **       be slower because it will have to hit the database each time for
2500    **       the profile value.
2501    **
2502    **       With the obsoletion of pl/sql hash table level caches, this API is
2503    **       obsolete and is being maintained for backwards compatibility.
2504    */
2505    FUNCTION value_wnps(name IN VARCHAR2) RETURN VARCHAR2 IS
2506    BEGIN
2507       RETURN value(name);
2508    END value_wnps;
2509 
2510 END fnd_profile;