DBA Data[Home] [Help]

PACKAGE BODY: APPS.FND_FLEX_SERVER4

Source


1 PACKAGE BODY fnd_flex_server4 AS
2 /* $Header: AFFFSV4B.pls 120.6.12010000.1 2008/07/25 14:14:32 appldev ship $ */
3 
4 
5 
6   --------
7   -- PRIVATE TYPES
8   --
9 
10   TYPE ValidatedSegmentArray IS RECORD
11        (nvalidated      NUMBER,
12         segstats        VARCHAR2(31),
13         segfmts         FND_FLEX_SERVER1.SegFormats,
14         segcols         FND_FLEX_SERVER1.TabColArray,
15         segcoltypes     FND_FLEX_SERVER1.CharArray,
16         dispvals        FND_FLEX_SERVER1.ValueArray,
17         vals            FND_FLEX_SERVER1.ValueArray,
18         ids             FND_FLEX_SERVER1.ValueIdArray,
19         descs           FND_FLEX_SERVER1.ValueDescArray,
20         catdesclens     FND_FLEX_SERVER1.NumberArray,
21         dispsegs        FND_FLEX_SERVER1.DisplayedSegs);
22 
23   ------------
24   -- PRIVATE CONSTANTS
25   --
26 
27   MAX_NSEGS             CONSTANT NUMBER := 30;
28   MAX_CATSEG_LEN        CONSTANT NUMBER := 700;
29 
30   -- ==================================================
31   -- CACHING
32   -- ==================================================
33 
34   g_cache_return_code VARCHAR2(30);
35   g_cache_key         VARCHAR2(2000);
36   g_cache_value       fnd_plsql_cache.generic_cache_value_type;
37 
38   -- --------------------------------------------------
39   -- cxc : Context Cache
40   -- --------------------------------------------------
41   cxc_cache_controller      fnd_plsql_cache.cache_1to1_controller_type;
42   cxc_cache_storage         fnd_plsql_cache.generic_cache_values_type;
43 
44   -- --------------------------------------------------
45   -- gcc : Global Context Cache
46   -- --------------------------------------------------
47   gcc_cache_controller      fnd_plsql_cache.cache_1to1_controller_type;
48   gcc_cache_storage         fnd_plsql_cache.generic_cache_values_type;
49 
50 /* -------------------------------------------------------------------- */
51 /*                        Private global variables                      */
52 /* -------------------------------------------------------------------- */
53 
54 /* -------------------------------------------------------------------- */
55 /*                        Private definitions                           */
56 /* -------------------------------------------------------------------- */
57 
58   FUNCTION find_descsegs(dflex_info IN  FND_FLEX_SERVER1.DescFlexInfo,
59                          row_id     IN  ROWID,
60                          alt_table  IN  VARCHAR2,
61                          data_field IN  VARCHAR2,
62                          vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
63                          nsegs_out  OUT nocopy NUMBER,
64                          segs_out   OUT nocopy FND_FLEX_SERVER1.StringArray)
65                                                         RETURN BOOLEAN;
66 
67   FUNCTION read_datafield(dflex_info IN  FND_FLEX_SERVER1.DescFlexInfo,
68                           row_id     IN  ROWID,
69                           table_name IN  VARCHAR2,
70                           datafield  IN  VARCHAR2,
71                           nsegs      OUT nocopy NUMBER,
72                           segs       OUT nocopy FND_FLEX_SERVER1.StringArray)
73                                                            RETURN BOOLEAN;
74 
75   FUNCTION read_segment_cols(dflex_info IN  FND_FLEX_SERVER1.DescFlexInfo,
76                         row_id     IN  ROWID,
77                         table_name IN  VARCHAR2,
78                         vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
79                         nsegs      OUT nocopy NUMBER,
80                         segs       OUT nocopy FND_FLEX_SERVER1.StringArray)
81                                                         RETURN BOOLEAN;
82 
83   FUNCTION get_desc_cols(dff_info   IN  FND_FLEX_SERVER1.DescFlexInfo,
84                          context    IN  VARCHAR2,
85                          vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
86                          contextn   OUT nocopy NUMBER,
87                          ncols      OUT nocopy NUMBER,
88                          cols       OUT nocopy FND_FLEX_SERVER1.TabColArray,
89                          coltypes   OUT nocopy FND_FLEX_SERVER1.CharArray,
90                          segfmts    OUT nocopy FND_FLEX_SERVER1.SegFormats)
91                                                         RETURN BOOLEAN;
92 
93   FUNCTION get_descsegs(dff_info IN  FND_FLEX_SERVER1.DescFlexInfo,
94                         coldef     IN  FND_FLEX_SERVER1.ColumnDefinitions,
95                         vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
96                         nsegs_out  OUT nocopy NUMBER,
97                         segs_out   OUT nocopy FND_FLEX_SERVER1.stringarray,
98                         x_context_segment_included OUT nocopy BOOLEAN)
99                                                         RETURN BOOLEAN;
100 
101   FUNCTION get_column_value(colvals  IN  FND_FLEX_SERVER1.ColumnValues,
102                             colname  IN  VARCHAR2,
103                             coltype  IN  VARCHAR2,
104                             seg_fmt  IN  VARCHAR2,
105                             seg_len  IN  NUMBER,
106                             val      OUT nocopy VARCHAR2) RETURN BOOLEAN;
107 
108   FUNCTION
109    validate_descsegs(dff_info   IN  FND_FLEX_SERVER1.DescFlexInfo,
110                      nsegs_in   IN  NUMBER,
111                      segs       IN  FND_FLEX_SERVER1.StringArray,
112                      vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
113                      v_date     IN  DATE,
114                      uappid     IN  NUMBER,
115                      respid     IN  NUMBER,
116                      nsegs_out  OUT nocopy NUMBER,
117                      segfmts    OUT nocopy FND_FLEX_SERVER1.SegFormats,
118                      segstats   OUT nocopy VARCHAR2,
119                      cols       OUT nocopy FND_FLEX_SERVER1.TabColArray,
120                      coltypes   OUT nocopy FND_FLEX_SERVER1.CharArray,
121                      v_dispvals OUT nocopy FND_FLEX_SERVER1.ValueArray,
122                      v_vals     OUT nocopy FND_FLEX_SERVER1.ValueArray,
123                      v_ids      OUT nocopy FND_FLEX_SERVER1.ValueIdArray,
124                      v_descs    OUT nocopy FND_FLEX_SERVER1.ValueDescArray,
125                      desc_lens  OUT nocopy FND_FLEX_SERVER1.NumberArray,
126                      dispsegs   OUT nocopy FND_FLEX_SERVER1.DisplayedSegs,
127                      errsegn    OUT nocopy NUMBER) RETURN NUMBER;
128 
129   FUNCTION
130   validate_context_segs(dff_info     IN  FND_FLEX_SERVER1.DescFlexInfo,
131                         contxt_name  IN  VARCHAR2,
132                         nsegs        IN  NUMBER,
133                         segs         IN  FND_FLEX_SERVER1.StringArray,
134                         vflags       IN  FND_FLEX_SERVER1.ValueValidationFlags,
135                         vdate        IN  DATE,
136                         uappid       IN  NUMBER,
137                         respid       IN  NUMBER,
138                         vsa          OUT nocopy ValidatedSegmentArray,
139                         errsegnum    OUT nocopy NUMBER) RETURN NUMBER;
140 
141   FUNCTION
142        validate_context(dff_info     IN  FND_FLEX_SERVER1.DescFlexInfo,
143                         context_sval IN  VARCHAR2,
144                         vflags       IN  FND_FLEX_SERVER1.ValueValidationFlags,
145                         vsa          OUT nocopy ValidatedSegmentArray)  RETURN NUMBER;
146 
147   FUNCTION find_context_value(appl_id       IN  VARCHAR2,
148                               dflex_name    IN  VARCHAR2,
149                               p_id_or_value IN  VARCHAR2,
150                               seg_in        IN  VARCHAR2,
151                               context_id    OUT nocopy VARCHAR2,
152                               context_val   OUT nocopy VARCHAR2,
153                               context_desc  OUT nocopy VARCHAR2,
154                               p_global_flag OUT nocopy VARCHAR2) RETURN VARCHAR2;
155 
156   FUNCTION get_global_context(appl_id      IN  NUMBER,
157                               dflex_name   IN  VARCHAR2,
158                               glob_context OUT nocopy VARCHAR2) RETURN BOOLEAN;
159 
160   FUNCTION append_vsegarray(destvsa    IN OUT  nocopy ValidatedSegmentArray,
161                             sourcevsa  IN      ValidatedSegmentArray)
162                                                              RETURN BOOLEAN;
163 
164   PROCEDURE initialize_vsegarray(v_seg_array  OUT nocopy ValidatedSegmentArray);
165 
166 /* -------------------------------------------------------------------- */
167 /*                        Functions and procedures                      */
168 /* -------------------------------------------------------------------- */
169 
170 
171 /* ------------------------------------------------------------------------- */
172 /*      The general purpose engine for descriptive flexfield validation.     */
173 /*                                                                           */
174 /*      Takes concatenated segments or rowid as input.                       */
175 /*                                                                           */
176 /*      This function returns output arrays that may or may not be           */
177 /*      populated depending on the point at which the validation stopped.    */
178 /*      The number of output array elements populated is specified by        */
179 /*      nvalidated.  Nvalidated is the number of enabled segments that       */
180 /*      were validated before validation stopped.                            */
181 /*      Many error conditions return no array information at all.  In        */
182 /*      this case nvalidated = 0 is returned.                                */
183 /*                                                                           */
184 /*      NOTE:  Make sure to call FND_FLEX_SERVER1.init_globals before        */
185 /*      calling this function, to initialize debugging and messages.         */
186 /* ------------------------------------------------------------------------  */
187 
188   PROCEDURE descval_engine
189     (user_apid       IN  NUMBER,
190      user_resp       IN  NUMBER,
191      userid          IN  NUMBER,
192      flex_app_sname  IN  VARCHAR2,
193      desc_flex_name  IN  VARCHAR2,
194      val_date        IN  DATE,
195      invoking_mode   IN  VARCHAR2,
196      allow_nulls     IN  BOOLEAN,
197      update_table    IN  BOOLEAN,
198      ignore_active   IN  BOOLEAN,
199      concat_segs     IN  VARCHAR2,
200      vals_not_ids    IN  BOOLEAN,
201      use_column_def  IN  BOOLEAN,
202      column_def      IN  FND_FLEX_SERVER1.ColumnDefinitions,
203      rowid_in        IN  ROWID,
204      alt_tbl_name    IN  VARCHAR2,
205      data_field_name IN  VARCHAR2,
206      nvalidated      OUT nocopy NUMBER,
207      displayed_vals  OUT nocopy FND_FLEX_SERVER1.ValueArray,
208      stored_vals     OUT nocopy FND_FLEX_SERVER1.ValueArray,
209      segment_ids     OUT nocopy FND_FLEX_SERVER1.ValueIdArray,
210      descriptions    OUT nocopy FND_FLEX_SERVER1.ValueDescArray,
211      desc_lengths    OUT nocopy FND_FLEX_SERVER1.NumberArray,
212      seg_colnames    OUT nocopy FND_FLEX_SERVER1.TabColArray,
213      seg_coltypes    OUT nocopy FND_FLEX_SERVER1.CharArray,
214      segment_types   OUT nocopy FND_FLEX_SERVER1.SegFormats,
215      displayed_segs  OUT nocopy FND_FLEX_SERVER1.DisplayedSegs,
216      seg_delimiter   OUT nocopy VARCHAR2,
217      v_status        OUT nocopy NUMBER,
218      seg_codes       OUT nocopy VARCHAR2,
219      err_segnum      OUT nocopy NUMBER) IS
220 
221     nvals       NUMBER;
222     nsegs       NUMBER;
223     entered     VARCHAR2(1);
224     dff_info    FND_FLEX_SERVER1.DescFlexInfo;
225     dff_id      FND_FLEX_SERVER1.FlexStructId;
226     segs        FND_FLEX_SERVER1.StringArray;
227     value_dvals FND_FLEX_SERVER1.ValueArray;
228     value_vals  FND_FLEX_SERVER1.ValueArray;
229     value_ids   FND_FLEX_SERVER1.ValueIdArray;
230     value_descs FND_FLEX_SERVER1.ValueDescArray;
231     cc_cols     FND_FLEX_SERVER1.TabColArray;
232     cc_coltypes FND_FLEX_SERVER1.CharArray;
233     desc_lens   FND_FLEX_SERVER1.NumberArray;
234     disp_segs   FND_FLEX_SERVER1.DisplayedSegs;
235     vv_flags    FND_FLEX_SERVER1.ValueValidationFlags;
236     segtypes    FND_FLEX_SERVER1.SegFormats;
237     segcodes    VARCHAR2(31);
238     errcode     NUMBER;
239     errsegnum   NUMBER;
240     catsegs     VARCHAR2(32000);
241     l_context_segment_included BOOLEAN;
242 
243   BEGIN
244      IF (fnd_flex_server1.g_debug_level > 0) THEN
245         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
246                                    'BEGIN SV4.descval_engine() ');
247      END IF;
248 
249 --  Initialize all output variables so that returning from any point
250 --  results in a valid state.
251 --
252     nvalidated := 0;
253     segment_types.nsegs := 0;
254     displayed_segs.n_segflags := 0;
255     v_status := FND_FLEX_SERVER1.VV_ERROR;
256     l_context_segment_included := FALSE;
257 
258 --  Initialize everything which affects returned information.  This way we
259 --  can process all returned information before returning when exiting from
260 --  any point in this code even if there is an error.
261 --  Dont worry about initializing strings to null.
262 
263     nvals := 0;
264     nsegs := 0;
265     segtypes.nsegs := 0;
266     disp_segs.n_segflags := 0;
267     errcode := FND_FLEX_SERVER1.VV_ERROR;
268 
269     if((concat_segs is null) and (rowid_in is null)) then
270       entered := 'N';
271     else
272       entered := 'Y';
273     end if;
274 
275 --  Get all required info about the desired flexfield structure.
276 --
277     if(FND_FLEX_SERVER2.get_descstruct(flex_app_sname, desc_flex_name,
278                                        dff_info) = FALSE) then
279       goto return_error;
280     end if;
281 
282 --  Limit concatenated segment length for compatibility with client
283 --
284     if(LENGTHB(concat_segs) > MAX_CATSEG_LEN) then
285       FND_MESSAGE.set_name('FND', 'FLEX-CONCAT LEN > IAPFLEN');
286       FND_MESSAGE.set_token('MAXFLDLEN', to_char(MAX_CATSEG_LEN));
287       goto return_error;
288     end if;
289 
290 --  First check that operation makes sense
291 --
292     if((invoking_mode is null) or
293        (invoking_mode NOT IN ('V', 'P', 'L', 'C', 'D'))) then
294       FND_MESSAGE.set_name('FND', 'FLEX-SSV BAD INVOKE');
295       goto return_error;
296     end if;
297 
298 -- Set validation flags.
299 -- Descriptive flexfields similar to key flexfields except:
300 --   Required token is always Yes for Descriptive flexfields.
301 --   Descriptive flexfields always in PARTIAL validation mode (never PIP).
302 --
303     vv_flags.default_all_displayed := TRUE;
304     vv_flags.values_not_ids := vals_not_ids and
305                                (invoking_mode not in ('L', 'C'));
306     vv_flags.default_all_required := ((invoking_mode in ('V', 'D')) and (entered='N'));
307     vv_flags.default_non_displayed := (invoking_mode in ('P', 'V', 'D'));
308     vv_flags.allow_nulls := allow_nulls;
309     vv_flags.message_on_null := TRUE;
310     vv_flags.all_orphans_valid := FALSE;
311     vv_flags.ignore_security := (invoking_mode = 'L');
312     vv_flags.ignore_expired := (invoking_mode = 'L') or ignore_active;
313     vv_flags.ignore_disabled := (invoking_mode = 'L') or ignore_active;
314     vv_flags.message_on_security := (invoking_mode <> 'L');
315     vv_flags.stop_on_value_error := (invoking_mode <> 'P');
316     vv_flags.exact_nsegs_required := ((invoking_mode in ('L', 'C')) or
317                 ((invoking_mode in ('V', 'D')) and not vv_flags.default_all_required));
318     vv_flags.stop_on_security := (invoking_mode in ('V', 'C', 'D'));
319 
320     /* invoking_mode is added for bug872437. */
321     vv_flags.invoking_mode := invoking_mode;
322 
323 --  Add input parameters to the debug information
324 --
325     IF (fnd_flex_server1.g_debug_level > 0) THEN
326        FND_FLEX_SERVER1.add_debug('User AppId = ' || to_char(user_apid));
327        FND_FLEX_SERVER1.add_debug(', User Resp = ' || to_char(user_resp));
328        FND_FLEX_SERVER1.add_debug(', User Id = ' || to_char(userid));
329        FND_FLEX_SERVER1.add_debug(', Ap Short Name = ' || flex_app_sname);
330        FND_FLEX_SERVER1.add_debug(', Desc Flex Name = '||desc_flex_name||' ');
331        FND_FLEX_SERVER1.add_debug(', Val Date = ' ||
332                                   to_char(val_date, 'YYYY/MM/DD HH24:MI:SS'));
333        FND_FLEX_SERVER1.add_debug(', Invoke = ' || invoking_mode);
334        if(ignore_active) then
335           FND_FLEX_SERVER1.add_debug(', Ignore disabled/expired');
336        end if;
337        if(allow_nulls) then
338           FND_FLEX_SERVER1.add_debug(', Allow Nulls');
339        end if;
340        if(update_table) then
341           FND_FLEX_SERVER1.add_debug(', Update Table');
342        end if;
343        FND_FLEX_SERVER1.add_debug(', Concat Segs = ' || concat_segs);
344        if(vals_not_ids) then
345           FND_FLEX_SERVER1.add_debug(', Vals');
346         else
347           FND_FLEX_SERVER1.add_debug(', Ids');
348        end if;
349        FND_FLEX_SERVER1.add_debug(', Rowid = ' || ROWIDTOCHAR(rowid_in));
350        FND_FLEX_SERVER1.add_debug(', Alt Table = ' || alt_tbl_name);
351        FND_FLEX_SERVER1.add_debug(', Data Field = ' || data_field_name||'.  ');
352        if(use_column_def) then
353           FND_FLEX_SERVER1.add_debug(', ColDefs: ');
354           if(column_def.context_value_set) then
355              FND_FLEX_SERVER1.add_debug('*Context* = ('
356                                         || column_def.context_value || ') ');
357           end if;
358           for i in 1..column_def.colvals.ncolumns loop
359              FND_FLEX_SERVER1.add_debug
360                (column_def.colvals.column_names(i) || ':' ||
361                 column_def.colvals.column_types(i) || ' = (' ||
362                 column_def.colvals.column_values(i) || ') ');
363           end loop;
364        end if;
365     END IF;
366 
367 --  If LOADDESC or CHECKDESC modes get the ids from the row in the table
368 --  if rowid not null.  If LOADDESC, CHECKDESC or VALDESC and rowid is null
369 --  then get inputs from the column definitions if use_column_def is TRUE.
370 --  Otherwise break up the concatenated segments.
371 --
372     if((invoking_mode in ('L', 'C')) and (rowid_in is not null)) THEN
373        IF (fnd_flex_server1.g_debug_level > 0) THEN
374           fnd_flex_server1.add_debug('calling find_descsegs()');
375        END IF;
376       if(find_descsegs(dff_info, rowid_in, alt_tbl_name, data_field_name,
377                        vv_flags, nsegs, segs) = FALSE) then
378         goto return_error;
379       end if;
380      elsif((invoking_mode in ('L', 'C', 'V', 'D')) and use_column_def) THEN
381        IF (fnd_flex_server1.g_debug_level > 0) THEN
382           fnd_flex_server1.add_debug('calling get_descsegs()');
383        END IF;
384 
385       if(get_descsegs(dff_info, column_def, vv_flags, nsegs, segs, l_context_segment_included)=FALSE) then
386         goto return_error;
387       end if;
388     else
389        IF (fnd_flex_server1.g_debug_level > 0) THEN
390           fnd_flex_server1.add_debug('calling to_stringarray()');
391        END IF;
392        nsegs := FND_FLEX_SERVER1.to_stringarray(concat_segs,
393                          dff_info.segment_delimiter, segs);
394     end if;
395 
396 --  Check to make sure there are not too many segments.
397 --
398 
399     if(nsegs > MAX_NSEGS) then
400        if (l_context_Segment_included and (nsegs = MAX_NSEGS + 1)) then
401           NULL;
402         else
403           FND_MESSAGE.set_name('FND', 'FLEX-TOO MANY SEGS');
404           FND_MESSAGE.set_token('NSEGS', MAX_NSEGS);
405           goto return_error;
406        end if;
407     END IF;
408 
409 
410     if (nsegs = 0) then
411        if (column_def.context_value_set) then
412           errcode := FND_FLEX_SERVER1.VV_VALID;
413           goto return_outvars;
414        end if;
415     end if;
416 
417 
418     IF (fnd_flex_server1.g_debug_level > 0) THEN
419        catsegs := substrb(FND_FLEX_SERVER1.from_stringarray(nsegs, segs, '*'), 1, 32000);
420         FND_FLEX_SERVER1.add_debug(catsegs);
421     END IF;
422 
423 
424 --  Validate segments.
425 --
426     errcode := validate_descsegs(dff_info, nsegs, segs, vv_flags, val_date,
427                 user_apid, user_resp, nvals, segtypes, segcodes, cc_cols,
428                 cc_coltypes, value_dvals, value_vals, value_ids, value_descs,
429                 desc_lens, disp_segs, errsegnum);
430 
431     IF (fnd_flex_server1.g_debug_level > 0) THEN
432        FND_FLEX_SERVER1.add_debug(' validate_descsegs() returns errcode ');
433        FND_FLEX_SERVER1.add_debug(to_char(errcode) ||' and '|| to_char(nvals));
434        FND_FLEX_SERVER1.add_debug(' values.  SegCodes: ' || segcodes);
435        FND_FLEX_SERVER1.add_debug(' ErrSeg: ' || to_char(errsegnum));
436        FND_FLEX_SERVER1.add_debug(' Returned arrays:');
437        for i in 1..nvals loop
438           FND_FLEX_SERVER1.add_debug('"' || segtypes.vs_format(i));
439           FND_FLEX_SERVER1.add_debug(to_char(segtypes.vs_maxsize(i), 'S099'));
440           FND_FLEX_SERVER1.add_debug('*' || value_dvals(i) || '*');
441           FND_FLEX_SERVER1.add_debug(cc_cols(i) || ':' ||cc_coltypes(i)||'" ');
442        end loop;
443     END IF;
444   <<return_outvars>>
445     displayed_vals := value_dvals;
446     stored_vals := value_vals;
447     segment_ids := value_ids;
448     descriptions := value_descs;
449     desc_lengths := desc_lens;
450     seg_colnames := cc_cols;
451     seg_coltypes := cc_coltypes;
452     nvalidated := nvals;
453     segment_types := segtypes;
454     displayed_segs := disp_segs;
455     seg_delimiter := dff_info.segment_delimiter;
456     seg_codes := segcodes;
457     err_segnum := errsegnum;
458     v_status := errcode;
459     return;
460 
461   <<return_error>>
462     v_status := FND_FLEX_SERVER1.VV_ERROR;
463     return;
464 
465   EXCEPTION
466     WHEN OTHERS then
467       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
468       FND_MESSAGE.set_token('MSG','descval_engine() exception: ' || SQLERRM);
469       v_status := FND_FLEX_SERVER1.VV_ERROR;
470       return;
471   END descval_engine;
472 
473 /* ------------------------------------------------------------------------ */
474 /*      Finds descriptive flexfield segment ids from existing row in table. */
475 /*      If alt_table is not null looks for the row in that table rather     */
476 /*      than in the table on which the descriptive flexfield is defined.    */
477 /*      Note special error if columns do not match up.                      */
478 /*      If data_field is not null, uses this field as source of             */
479 /*      concatenated ids rather than the individual segment fields.         */
480 /*      Returns segment ids for all enabled segments whether or not they    */
481 /*      are displayed in the order that they are displayed within each      */
482 /*      context.                                                            */
483 /*      Returns TRUE if all ok, or FALSE and sets FND_MESSAGE on error.     */
484 /* ------------------------------------------------------------------------ */
485 
486   FUNCTION find_descsegs(dflex_info IN  FND_FLEX_SERVER1.DescFlexInfo,
487                          row_id     IN  ROWID,
488                          alt_table  IN  VARCHAR2,
489                          data_field IN  VARCHAR2,
490                          vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
491                          nsegs_out  OUT nocopy NUMBER,
492                          segs_out   OUT nocopy FND_FLEX_SERVER1.StringArray)
493                                                         RETURN BOOLEAN IS
494     effective_table     VARCHAR2(30);
495 
496   BEGIN
497      IF (fnd_flex_server1.g_debug_level > 0) THEN
498         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
499                                    'BEGIN SV4.find_descsegs() ');
500      END IF;
501 
502     nsegs_out := 0;
503 
504     if(alt_table is not null) then
505       effective_table := SUBSTRB(alt_table, 1, 30);
506     else
507       effective_table := dflex_info.table_name;
508     end if;
509 
510 --  If use data field just select that column and break up segment ids.
511 --  Otherwise must get all columns.
512 
513     if(data_field is not null) then
514       return(read_datafield(dflex_info, row_id, effective_table,
515                             data_field, nsegs_out, segs_out));
516     end if;
517     return(read_segment_cols(dflex_info, row_id, effective_table,
518                                   vflags, nsegs_out, segs_out));
519   EXCEPTION
520     WHEN OTHERS then
521       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
522       FND_MESSAGE.set_token('MSG','find_descsegs() exception: ' || SQLERRM);
523       return(FALSE);
524 
525   END find_descsegs;
526 
527 /* ------------------------------------------------------------------------ */
528 /*      Reads concatenated segment ids from data field in the particular    */
529 /*      row of the specified table.  Breaks up concatenated segments into   */
530 /*      a string array for return.                                          */
531 /*      Returns TRUE on success or FALSE and sets FND_MESSAGE on error.     */
532 /* ------------------------------------------------------------------------ */
533 
534   FUNCTION read_datafield(dflex_info IN  FND_FLEX_SERVER1.DescFlexInfo,
535                           row_id     IN  ROWID,
536                           table_name IN  VARCHAR2,
537                           datafield  IN  VARCHAR2,
538                           nsegs      OUT nocopy NUMBER,
539                           segs       OUT nocopy FND_FLEX_SERVER1.StringArray)
540                                                            RETURN BOOLEAN IS
541     concat_segids  VARCHAR2(2000);
542     rstat          NUMBER;
543 
544   BEGIN
545      IF (fnd_flex_server1.g_debug_level > 0) THEN
546         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
547                                    'BEGIN SV4.read_datafield() ');
548      END IF;
549 
550      fnd_dsql.init;
551      fnd_dsql.add_text('select SUBSTRB(' || datafield || ', 1, 2000)' ||
552                        ' from ' || table_name ||
553                        ' where rowid = CHARTOROWID(');
554      fnd_dsql.add_bind(ROWIDTOCHAR(row_id));
555      fnd_dsql.add_text(')');
556 
557 --  Look up the segment values or ids.
558 --
559     rstat := FND_FLEX_SERVER1.x_dsql_select_one(concat_segids);
560     if(rstat <> 1) then
561       if(rstat = 0) then
562         FND_MESSAGE.set_name('FND', 'FLEX-DFF ROW NOT FOUND');
563         FND_MESSAGE.set_token('TABLE', table_name);
564         FND_MESSAGE.set_token('ROWID', ROWIDTOCHAR(row_id));
565       elsif(rstat = -2) then
566         FND_MESSAGE.set_name('FND', 'FLEX-DFF BAD DATAFIELD');
567         FND_MESSAGE.set_token('TABLE', table_name);
568         FND_MESSAGE.set_token('DATAFIELD', datafield);
569       else
570         null;
571       end if;
572       return(FALSE);
573     end if;
574 
575     nsegs := FND_FLEX_SERVER1.to_stringarray(concat_segids,
576                                 dflex_info.segment_delimiter, segs);
577     return(TRUE);
578 
579   EXCEPTION
580     WHEN OTHERS then
581       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
582       FND_MESSAGE.set_token('MSG','read_datafield() exception: '||SQLERRM);
583       return(FALSE);
584 
585   END read_datafield;
586 
587 /* ------------------------------------------------------------------------ */
588 /*      Reads segment ids from individual attribute columns in the row      */
589 /*      of the effective table specified.  Validates the context in the     */
590 /*      process to determine which columns to use for context-sensitive     */
591 /*      segments.  Looks up the context value from table.                   */
592 /*      Returns TRUE on success or FALSE and sets FND_MESSAGE on error.     */
593 /* ------------------------------------------------------------------------ */
594 
595   FUNCTION read_segment_cols(dflex_info IN  FND_FLEX_SERVER1.DescFlexInfo,
596                         row_id     IN  ROWID,
597                         table_name IN  VARCHAR2,
598                         vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
599                         nsegs      OUT nocopy NUMBER,
600                         segs       OUT nocopy FND_FLEX_SERVER1.StringArray)
601                                                         RETURN BOOLEAN IS
602     ncols               NUMBER;
603     cols                FND_FLEX_SERVER1.TabColArray;
604     coltypes            FND_FLEX_SERVER1.CharArray;
605     segfmts             FND_FLEX_SERVER1.SegFormats;
606     value_component     NUMBER;
607     rstat               NUMBER;
608     context             VARCHAR2(80);
609     context_number      NUMBER;
610 
611     BEGIN
612      IF (fnd_flex_server1.g_debug_level > 0) THEN
613         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
614                                    'BEGIN SV4.read_segment_cols() ');
615      END IF;
616 
617     nsegs := 0;
618 
619 --  Determine if values or ids are stored in the table columns.
620 --  Generally only expect ids, but in some cases we may want to
621 --  allow users to input values into the segment columns and have
622 --  us turn them into ids.
623 --
624     if(vflags.values_not_ids) then
625       value_component := FND_FLEX_SERVER1.VC_VALUE;
626     else
627       value_component := FND_FLEX_SERVER1.VC_ID;
628     end if;
629 
630 --  Get context value stored in the table
631 --  Assume context column is CHAR or VARCHAR2
632 --
633     IF (fnd_flex_server1.g_debug_level > 0) THEN
634        FND_FLEX_SERVER1.add_debug(' Context col: '||dflex_info.context_column);
635     END IF;
636 
637     fnd_dsql.init;
638     fnd_dsql.add_text('select SUBSTRB(' || dflex_info.context_column || ', 1, 80)' ||
639                       ' from ' || table_name ||
640                       ' where rowid = CHARTOROWID(');
641     fnd_dsql.add_bind(ROWIDTOCHAR(row_id));
642     fnd_dsql.add_text(')');
643 
644     rstat := FND_FLEX_SERVER1.x_dsql_select_one(context);
645     if(rstat <> 1) then
646       if(rstat = 0) then
647         FND_MESSAGE.set_name('FND', 'FLEX-DFF ROW NOT FOUND');
648         FND_MESSAGE.set_token('TABLE', table_name);
649         FND_MESSAGE.set_token('ROWID', ROWIDTOCHAR(row_id));
650       elsif(rstat = -2) then
651         FND_MESSAGE.set_name('FND', 'FLEX-DFF BAD SEGCOLS');
652         FND_MESSAGE.set_token('TABLE', table_name);
653       else
654         null;
655       end if;
656       return(FALSE);
657     end if;
658 
659 --  Get names of columns used.  Must validate context to do this.
660 --
661     if(get_desc_cols(dflex_info, context, vflags, context_number,
662                      ncols, cols, coltypes, segfmts) = FALSE) then
663       return(FALSE);
664     end if;
665 
666     IF (fnd_flex_server1.g_debug_level > 0) THEN
667        FND_FLEX_SERVER1.add_debug('Selecting all columns ');
668     END IF;
669 
670 --  Build SQL statement to select segment columns in order for
671 --  global segments, the context segment, and context-sensitive segments.
672 --
673 
674     fnd_dsql.init;
675     fnd_dsql.add_text('select ');
676     for i in 1..ncols loop
677       if(i > 1) then
678          fnd_dsql.add_text(', ');
679       end if;
680       fnd_dsql.add_text(FND_FLEX_SERVER1.select_clause
681                         (cols(i), coltypes(i),
682                          value_component, segfmts.vs_format(i), segfmts.vs_maxsize(i)));
683     end loop;
684     fnd_dsql.add_text(' from ' || table_name ||
685                       ' where rowid = CHARTOROWID(');
686     fnd_dsql.add_bind(ROWIDTOCHAR(row_id));
687     fnd_dsql.add_text(')');
688 
689 --  Look up the segment values or ids.
690 --
691     rstat := FND_FLEX_SERVER1.x_dsql_select(ncols, segs);
692     if(rstat <> 1) then
693       if(rstat = 0) then
694         FND_MESSAGE.set_name('FND', 'FLEX-DFF ROW NOT FOUND');
695         FND_MESSAGE.set_token('TABLE', table_name);
696         FND_MESSAGE.set_token('ROWID', ROWIDTOCHAR(row_id));
697       elsif(rstat = -2) then
698         FND_MESSAGE.set_name('FND', 'FLEX-DFF BAD SEGCOLS');
699         FND_MESSAGE.set_token('TABLE', table_name);
700       else
701         null;
702       end if;
703       return(FALSE);
704     end if;
705 
706     nsegs := ncols;
707     return(TRUE);
708 
709   EXCEPTION
710     WHEN OTHERS then
711       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
712       FND_MESSAGE.set_token('MSG','read_segment_cols() exception: '||SQLERRM);
713       return(FALSE);
714 
715   END read_segment_cols;
716 
717 /* ------------------------------------------------------------------------ */
718 /*      Gets the names of the columns corresponding to the segment ids      */
719 /*      for the specified descriptive flexfield.  Validates the context     */
720 /*      value in the process to determine which context segment columns     */
721 /*      to use.  Returns the columns in display order within each context   */
722 /*      for all enabled segments even if they are not displayed.  Returns   */
723 /*      global context segment columns first, then the context segment      */
724 /*      column, then the columns of the context-sensitive segments.         */
725 /*      Also returns a number indicating the context segment number.        */
726 /*      Returns TRUE if all ok, or FALSE and sets FND_MESSAGE on error.     */
727 /* ------------------------------------------------------------------------ */
728 
729   FUNCTION get_desc_cols(dff_info   IN  FND_FLEX_SERVER1.DescFlexInfo,
730                          context    IN  VARCHAR2,
731                          vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
732                          contextn   OUT nocopy NUMBER,
733                          ncols      OUT nocopy NUMBER,
734                          cols       OUT nocopy FND_FLEX_SERVER1.TabColArray,
735                          coltypes   OUT nocopy FND_FLEX_SERVER1.CharArray,
736                          segfmts    OUT nocopy FND_FLEX_SERVER1.SegFormats)
737                                                         RETURN BOOLEAN IS
738 
739     fstruct           FND_FLEX_SERVER1.FlexStructId;
740 
741     n_global          NUMBER;
742     global_cols       FND_FLEX_SERVER1.TabColArray;
743     global_coltypes   FND_FLEX_SERVER1.CharArray;
744     global_segfmts    FND_FLEX_SERVER1.SegFormats;
745 
746     n_context         NUMBER;
747     context_cols      FND_FLEX_SERVER1.TabColArray;
748     context_coltypes  FND_FLEX_SERVER1.CharArray;
749     context_segfmts   FND_FLEX_SERVER1.SegFormats;
750 
751     context_vsa       ValidatedSegmentArray;
752     colcount          NUMBER;
753     rstat             NUMBER;
754     vc_return         NUMBER;
755 
756   BEGIN
757      IF (fnd_flex_server1.g_debug_level > 0) THEN
758         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
759                                    'BEGIN SV4.get_desc_cols() ');
760      END IF;
761 
762 --  Initialize outputs to return nothing in case of error.
763 --
764     ncols := 0;
765     segfmts.nsegs := 0;
766 
767     fstruct.isa_key_flexfield := FALSE;
768     fstruct.application_id := dff_info.application_id;
769     fstruct.desc_flex_name := dff_info.name;
770 
771 --  Return name of global context.
772 --
773     if(get_global_context(dff_info.application_id, dff_info.name,
774                           fstruct.desc_flex_context) = FALSE) then
775       return(FALSE);
776     end if;
777 
778 --  Get segment mapping for global segments
779 --
780     if(FND_FLEX_SERVER2.get_struct_cols(fstruct, dff_info.table_appl_id,
781                                dff_info.table_id, n_global, global_cols,
782                                global_coltypes, global_segfmts) = FALSE) then
783       return(FALSE);
784     end if;
785     IF (fnd_flex_server1.g_debug_level > 0) THEN
786        FND_FLEX_SERVER1.add_debug(' Found global segment mapping: [');
787        for i in 1..n_global loop
788           FND_FLEX_SERVER1.add_debug(global_cols(i) || ':' ||
789                                      global_coltypes(i) ||' ');
790        end loop;
791        FND_FLEX_SERVER1.add_debug('] ');
792     END IF;
793 
794 --  Validate the context value
795 --
796     vc_return := validate_context(dff_info, context, vflags, context_vsa);
797     IF (vc_return <> FND_FLEX_SERVER1.VV_VALID) then
798       IF (vc_return <> FND_FLEX_SERVER1.VV_CTXTNOSEG) then
799          return(FALSE);
800       END IF;
801     END IF;
802 --      return(FALSE);
803 --    end if;
804 
805 
806     IF (fnd_flex_server1.g_debug_level > 0) THEN
807        FND_FLEX_SERVER1.add_debug('Context value (' || context_vsa.ids(1) ||
808                                   ') valid. ');
809     END IF;
810 
811 --  Get segment mapping for context-sensitive segments
812 --
813     fstruct.desc_flex_context := context_vsa.ids(1);
814     IF (fstruct.desc_flex_context IS NOT NULL) AND
815        (vc_return <> FND_FLEX_SERVER1.VV_CTXTNOSEG) THEN
816        if(FND_FLEX_SERVER2.get_struct_cols
817           (fstruct, dff_info.table_appl_id,
818            dff_info.table_id, n_context, context_cols,
819            context_coltypes, context_segfmts) = FALSE) then
820           return(FALSE);
821        end if;
822 
823        IF (fnd_flex_server1.g_debug_level > 0) THEN
824           FND_FLEX_SERVER1.add_debug(' Found context segment mapping: [');
825           for i in 1..n_context loop
826              FND_FLEX_SERVER1.add_debug(context_cols(i) || ':' ||
827                                         context_coltypes(i) ||' ');
828           end loop;
829           FND_FLEX_SERVER1.add_debug('] ');
830        END IF;
831      ELSE
832        n_context := 0;
833        context_segfmts.nsegs := 0;
834     END IF;
835 
836 --  Now concatenate the semgment columns for global,
837 --  context, and context-sensitive contexts.
838 
839     colcount := 0;
840 
841 --  Global columns
842 --
843     for i in 1..n_global loop
844       colcount := colcount + 1;
845       cols(colcount) := global_cols(i);
846       coltypes(colcount) := global_coltypes(i);
847       segfmts.vs_format(colcount) := global_segfmts.vs_format(i);
848       segfmts.vs_maxsize(colcount) := global_segfmts.vs_maxsize(i);
849     end loop;
850 
851 --  Context column.  Also note which it is.
852 --
853     colcount := colcount + 1;
854     cols(colcount) := context_vsa.segcols(1);
855     coltypes(colcount) := context_vsa.segcoltypes(1);
856     segfmts.vs_format(colcount) := context_vsa.segfmts.vs_format(1);
857     segfmts.vs_maxsize(colcount) := context_vsa.segfmts.vs_maxsize(1);
858     contextn := colcount;
859 
860 --  Context-sensitive columns
861 --
862     for i in 1..n_context loop
863       colcount := colcount + 1;
864       cols(colcount) := context_cols(i);
865       coltypes(colcount) := context_coltypes(i);
866       segfmts.vs_format(colcount) := context_segfmts.vs_format(i);
867       segfmts.vs_maxsize(colcount) := context_segfmts.vs_maxsize(i);
868     end loop;
869 
870     segfmts.nsegs := colcount;
871     ncols := colcount;
872     return(TRUE);
873 
874   EXCEPTION
875     WHEN OTHERS then
876       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
877       FND_MESSAGE.set_token('MSG','get_desc_cols() exception: ' || SQLERRM);
878       return(FALSE);
879 
880   END get_desc_cols;
881 
882 /* ------------------------------------------------------------------------ */
883 /*      Gets descriptive flexfield segment ids from the column definitions. */
884 /*      Error if some required columns are not defined or if the column     */
885 /*      data types do not match those expected from the segment columns.    */
886 /*      Returns segment ids for all enabled segments whether or not they    */
887 /*      are displayed in the order that they are displayed within each      */
888 /*      context.                                                            */
889 /*      Returns TRUE if all ok, or FALSE and sets FND_MESSAGE on error.     */
890 /* ------------------------------------------------------------------------ */
891 
892   FUNCTION get_descsegs(dff_info   IN  FND_FLEX_SERVER1.DescFlexInfo,
893                         coldef     IN  FND_FLEX_SERVER1.ColumnDefinitions,
894                         vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
895                         nsegs_out  OUT nocopy NUMBER,
896                         segs_out   OUT nocopy FND_FLEX_SERVER1.StringArray,
897                         x_context_segment_included OUT nocopy BOOLEAN)
898                                                         RETURN BOOLEAN IS
899     thisval        VARCHAR2(1000);
900     fstruct        FND_FLEX_SERVER1.FlexStructId;
901 
902     n_segs         NUMBER;
903     seg_cols       FND_FLEX_SERVER1.TabColArray;
904     seg_coltypes   FND_FLEX_SERVER1.CharArray;
905     seg_fmts       FND_FLEX_SERVER1.SegFormats;
906     context_seg    NUMBER;
907 
908   BEGIN
909      IF (fnd_flex_server1.g_debug_level > 0) THEN
910         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
911                                    'BEGIN SV4.get_descsegs() ');
912      END IF;
913 
914 --  Initialize outputs in case of error.
915 --  Start with no defined segments
916 --
917     nsegs_out := 0;
918     x_context_segment_included := FALSE;
919 
920 --  Get the context value.  It might already be set in the coldef.
921 --  If not, then look it up from the column values.
922 --
923 
924     if(coldef.context_value_set) then
925       thisval := coldef.context_value;
926       IF (fnd_flex_server1.g_debug_level > 0) THEN
927          FND_FLEX_SERVER1.add_debug('*Context* = (' || thisval || ') ');
928       END IF;
929     else
930       if(get_column_value(coldef.colvals, dff_info.context_column,
931                           'V', 'C', 30, thisval) = FALSE) then
932         return(FALSE);
933       end if;
934     end if;
935 
936 --  Get names of columns used.  Must validate context to do this.
937 --
938     if(get_desc_cols(dff_info, thisval, vflags, context_seg,
939                      n_segs, seg_cols, seg_coltypes, seg_fmts) = FALSE) then
940       return(FALSE);
941     end if;
942 
943 --  Loop through the segment columns and get the corresponding values
944 --  in the desired order.  Use the context value passed in for the context
945 --  segment if it is defined.
946 --
947     for i in 1..n_segs loop
948       if((i = context_seg) and (coldef.context_value_set)) then
949         segs_out(i) := coldef.context_value;
950         x_context_segment_included := TRUE;
951         IF (fnd_flex_server1.g_debug_level > 0) THEN
952            FND_FLEX_SERVER1.add_debug('*Context* = (' ||
953                                       coldef.context_value || ') ');
954         END IF;
955       else
956         if(get_column_value(coldef.colvals, seg_cols(i), seg_coltypes(i),
957            seg_fmts.vs_format(i), seg_fmts.vs_maxsize(i), thisval)=FALSE) then
958           return(FALSE);
959         end if;
960         segs_out(i) := thisval;
961       end if;
962     end loop;
963 
964 --  Return the segments out
965 --
966     nsegs_out := n_segs;
967     return(TRUE);
968 
969   EXCEPTION
970     WHEN OTHERS then
971       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
972       FND_MESSAGE.set_token('MSG','get_descsegs() exception: ' || SQLERRM);
973       return(FALSE);
974 
975   END get_descsegs;
976 
977 /* ----------------------------------------------------------------------- */
978 /*      Gets the value associated with a given column name from the        */
979 /*      pre-defined ColumnValues structure.  A column with the same name   */
980 /*      and data type must be found to consider the column found.          */
981 /*      Converts the column value stored in the generic character          */
982 /*      representation into the representation required for a segment      */
983 /*      with the indicated value set format and size.                      */
984 /*      Performs case-insensitive column name comparison.                  */
985 /*      Returns TRUE if all ok, or FALSE and sets FND_MESSAGE on error.    */
986 /* ----------------------------------------------------------------------- */
987 
988   FUNCTION get_column_value(colvals  IN  FND_FLEX_SERVER1.ColumnValues,
989                             colname  IN  VARCHAR2,
990                             coltype  IN  VARCHAR2,
991                             seg_fmt  IN  VARCHAR2,
992                             seg_len  IN  NUMBER,
993                             val      OUT nocopy VARCHAR2) RETURN BOOLEAN IS
994     d         DATE;
995     dfmt      VARCHAR2(40);
996     valindex  NUMBER;
997     niceval   VARCHAR2(1000);
998 
999   BEGIN
1000      IF (fnd_flex_server1.g_debug_level > 0) THEN
1001         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1002                                    'BEGIN SV4.get_column_value() ');
1003      END IF;
1004 
1005 -- Find index to value in column value table.
1006 --
1007     valindex := 0;
1008     for i in 1..colvals.ncolumns loop
1009       if((colname = colvals.column_names(i)) and
1010          ((coltype = colvals.column_types(i)) or
1011            (coltype in ('C', 'V') and
1012             colvals.column_types(i) in ('C', 'V')))) then
1013         valindex := i;
1014         exit;
1015       end if;
1016     end loop;
1017 
1018 --  Error if column not defined
1019 --
1020     if(valindex = 0) then
1021       FND_MESSAGE.set_name('FND', 'FLEX-DFF COLUMN UNDEFINED');
1022       FND_MESSAGE.set_token('COLNAME', colname);
1023       FND_MESSAGE.set_token('COLTYPE', coltype);
1024       return(FALSE);
1025     end if;
1026 
1027 --  Convert format of data to that desired for the value set.
1028 --  Assume numbers are already in the default to_char(n) format, and
1029 --  that dates are in the to_char(d, FND_FLEX_SERVER1.DATETIME_FMT) format.
1030 --
1031 --  Flex expects numbers to be in the default to_char(n) format.
1032 --  Flex expects most dates to be in the default to_char(d) format,
1033 --  except translatable dates which are in FND_FLEX_SERVER1.stored_date_format
1034 --  if ids or FND_FLEX_SERVER1.displayed_date_format if values.  So we need
1035 --  to convert only if column is of date type.
1036 --  Dates input are the stored not displayed formats.
1037 --  See FND_FLEX_SERVER1.select_clause().
1038 --
1039     if(coltype = 'D') then
1040       d := to_date(colvals.column_values(valindex),
1041                    FND_FLEX_SERVER1.DATETIME_FMT);
1042       if(seg_fmt in ('X', 'Y', 'Z')) then
1043         dfmt := FND_FLEX_SERVER1.stored_date_format(seg_fmt, seg_len);
1044         niceval := to_char(d, dfmt);
1045       else
1046         niceval := to_char(d);
1047       end if;
1048     else
1049       niceval := colvals.column_values(valindex);
1050     end if;
1051 
1052     IF (fnd_flex_server1.g_debug_level > 0) THEN
1053        FND_FLEX_SERVER1.add_debug('Column ' || colname || ':' || coltype ||
1054                                   ' = (' || niceval || ') ');
1055     END IF;
1056     val := niceval;
1057 
1058 <<done_return>>
1059 
1060     return(TRUE);
1061 
1062   EXCEPTION
1063     WHEN OTHERS then
1064       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1065       FND_MESSAGE.set_token('MSG','get_column_value() exception: ' || SQLERRM);
1066       return(FALSE);
1067 
1068   END get_column_value;
1069 
1070 /* ----------------------------------------------------------------------- */
1071 /*      Validates all segments for a given descriptive flexfield.          */
1072 /*      Includes segments from the global context, the context segment     */
1073 /*      and the segments for the particular context.                       */
1074 /*      Input all segments in an array.                                    */
1075 /*      Returns error code and sets FND_MESSAGE on error, or returns       */
1076 /*      VV_VALID if all ok.                                                */
1077 /* ----------------------------------------------------------------------- */
1078 
1079   FUNCTION
1080    validate_descsegs(dff_info   IN  FND_FLEX_SERVER1.DescFlexInfo,
1081                      nsegs_in   IN  NUMBER,
1082                      segs       IN  FND_FLEX_SERVER1.StringArray,
1083                      vflags     IN  FND_FLEX_SERVER1.ValueValidationFlags,
1084                      v_date     IN  DATE,
1085                      uappid     IN  NUMBER,
1086                      respid     IN  NUMBER,
1087                      nsegs_out  OUT nocopy NUMBER,
1088                      segfmts    OUT nocopy FND_FLEX_SERVER1.SegFormats,
1089                      segstats   OUT nocopy VARCHAR2,
1090                      cols       OUT nocopy FND_FLEX_SERVER1.TabColArray,
1091                      coltypes   OUT nocopy FND_FLEX_SERVER1.CharArray,
1092                      v_dispvals OUT nocopy FND_FLEX_SERVER1.ValueArray,
1093                      v_vals     OUT nocopy FND_FLEX_SERVER1.ValueArray,
1094                      v_ids      OUT nocopy FND_FLEX_SERVER1.ValueIdArray,
1095                      v_descs    OUT nocopy FND_FLEX_SERVER1.ValueDescArray,
1096                      desc_lens  OUT nocopy FND_FLEX_SERVER1.NumberArray,
1097                      dispsegs   OUT nocopy FND_FLEX_SERVER1.DisplayedSegs,
1098                      errsegn    OUT nocopy NUMBER) RETURN NUMBER IS
1099 
1100 -- Remember to check all sizes!
1101 --
1102 
1103     global_context_name VARCHAR2(30);
1104 
1105     context_segnum      NUMBER;
1106     context_seg         VARCHAR2(80);
1107 
1108     context_segs_in     FND_FLEX_SERVER1.StringArray;
1109     ncontext_segs_in    NUMBER;
1110 
1111     global_segs         ValidatedSegmentArray;
1112     context_segment     ValidatedSegmentArray;
1113     context_segs        ValidatedSegmentArray;
1114 
1115     global_vflags       FND_FLEX_SERVER1.ValueValidationFlags;
1116     global_error_segnum NUMBER;
1117     global_error_msg    VARCHAR2(2000);
1118     global_return_code  NUMBER;
1119     error_segnum        NUMBER;
1120     return_code         NUMBER;
1121 
1122   BEGIN
1123      IF (fnd_flex_server1.g_debug_level > 0) THEN
1124         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1125                                    'BEGIN SV4.validate_descsegs() ');
1126      END IF;
1127 
1128 --  Initialize all returned values and all derived values with defaults
1129 --
1130     nsegs_out := 0;
1131     dispsegs.n_segflags := 0;
1132     segfmts.nsegs := 0;
1133 
1134 --  Initialize segment arrays to 0 segments in case of error.
1135 --
1136     initialize_vsegarray(global_segs);
1137     initialize_vsegarray(context_segment);
1138     initialize_vsegarray(context_segs);
1139 
1140 --  Return name of global context.
1141 --
1142     if(get_global_context(dff_info.application_id, dff_info.name,
1143                           global_context_name) = FALSE) then
1144       return_code := FND_FLEX_SERVER1.VV_ERROR;
1145       goto return_values;
1146     end if;
1147 
1148 --  Global context cannot require exact segs because we dont know
1149 --  how many segments are in the global structure beforehand.
1150 --  Make up a set of value validation flags like those input but which
1151 --  allow extra segments.
1152 --
1153     global_vflags := vflags;
1154     global_vflags.exact_nsegs_required := FALSE;
1155 
1156 --  Validate global context segments
1157 --
1158     IF (fnd_flex_server1.g_debug_level > 0) THEN
1159        FND_FLEX_SERVER1.add_debug('  Global segments: ');
1160     END IF;
1161     global_return_code := validate_context_segs(dff_info, global_context_name,
1162                                 nsegs_in, segs, global_vflags, v_date, uappid,
1163                                 respid, global_segs, global_error_segnum);
1164 
1165 --  Quit only if invalid and the error requires stopping.  If error does
1166 --  not require stopping, save error message so it doesn't get
1167 --  overwritten by context validation.
1168 --
1169     if(global_return_code <> FND_FLEX_SERVER1.VV_VALID) then
1170       if(global_error_segnum is not null) then
1171         global_error_msg := FND_MESSAGE.GET_ENCODED;
1172       end if;
1173       if(not (((global_return_code = FND_FLEX_SERVER1.VV_SECURED) and
1174                (not global_vflags.stop_on_security)) OR
1175               ((global_return_code = FND_FLEX_SERVER1.VV_VALUES) and
1176                (not global_vflags.stop_on_value_error)))) then
1177         goto return_values;
1178       end if;
1179     end if;
1180 
1181 --  Determine which segment is the context segment.
1182 --  If IDs input all segments are displayed so the context segment is
1183 --  just global_segs.nvalidated + 1.  However, if VALUES are input,
1184 --  then input segs are only the displayed segments, so have to
1185 --  count the number of displayed segments in the global context
1186 --  to determine the number of the context segment.
1187 --
1188 -- Bug 1459072: There is no need to validate the context segment if one
1189 -- does not exist.
1190 
1191     IF dff_info.context_override = 'N'
1192        AND dff_info.context_required = 'N'
1193        AND dff_info.default_context IS NULL
1194        AND dff_info.reference_field IS NULL
1195        -- Bug#4220582, to enforce validation checking even when ids are passed and not values.
1196        AND vflags.values_not_ids = TRUE then
1197          context_seg := NULL;
1198          return_code := FND_FLEX_SERVER1.VV_VALID;
1199     ELSE
1200       if(vflags.values_not_ids) then
1201         context_segnum := 1;
1202         for i in 1..global_segs.dispsegs.n_segflags loop
1203           if(global_segs.dispsegs.segflags(i)) then
1204             context_segnum := context_segnum + 1;
1205           end if;
1206         end loop;
1207       else
1208         context_segnum := global_segs.nvalidated + 1;
1209       end if;
1210 
1211 --  If ids passed in, or if context field displayed, then get context
1212 --  from input segment array.  Otherwise treat it as null and let it
1213 --  get defaulted if necessary.
1214 --  Set context_segnum to the first context-sensitive segment.
1215 --
1216 --  PROBLEM:  IF CONTEXT field not displayed, but defaulted using the
1217 --  reference field mechanism, then the context value won't get passed
1218 --  in and the default value will not be available on the server.
1219 --
1220     -- if the context segment is set, then use it.
1221       if((not vflags.values_not_ids) or
1222          (dff_info.context_override = 'Y') OR
1223          (context_segnum <= nsegs_in AND
1224           segs(context_segnum) IS NOT NULL)) then
1225         if(nsegs_in < context_segnum) then
1226           if(vflags.exact_nsegs_required and
1227              not ((nsegs_in = 0) and (context_segnum = 1))) then
1228             FND_MESSAGE.set_name('FND', 'FLEX-MISSING CONCAT VALUES');
1229             error_segnum := global_segs.nvalidated + 1;
1230             return_code := FND_FLEX_SERVER1.VV_ERROR;
1231             goto return_values;
1232           else
1233             context_seg := NULL;
1234           end if;
1235         else
1236           context_seg := SUBSTRB(segs(context_segnum), 1, 80);
1237         end if;
1238         IF (fnd_flex_server1.g_debug_level > 0) THEN
1239           FND_FLEX_SERVER1.add_debug(' Context seg '||to_char(context_segnum));
1240           FND_FLEX_SERVER1.add_debug(' = (' || context_seg || ') ');
1241         END IF;
1242       --
1243       -- add 1. Beginning index for context sens. segs.
1244       --
1245         context_segnum := context_segnum + 1;
1246       end if;
1247 
1248       IF (fnd_flex_server1.g_debug_level > 0) THEN
1249         FND_FLEX_SERVER1.add_debug('Context SEG#:' || To_char(context_segnum));
1250       END IF;
1251 --  Validate context segment.  Default it if it's null and defaults
1252 --  are required.
1253 --
1254       return_code := validate_context(dff_info, context_seg, vflags,
1255                                       context_segment);
1256 
1257 --  If context field is valid, validate context.  Pass in only context segs.
1258 --
1259       if((return_code <> FND_FLEX_SERVER1.VV_VALID) and
1260         (return_code <> FND_FLEX_SERVER1.VV_CTXTNOSEG)) then
1261         error_segnum := global_segs.nvalidated + 1;
1262       else
1263         ncontext_segs_in := 0;
1264         for i in context_segnum..nsegs_in loop
1265           ncontext_segs_in := ncontext_segs_in + 1;
1266           context_segs_in(ncontext_segs_in) := segs(i);
1267         end loop;
1268         IF (fnd_flex_server1.g_debug_level > 0) THEN
1269           FND_FLEX_SERVER1.add_debug('  Context-sensitive segments: ');
1270         END IF;
1271         IF (ncontext_segs_in > 0) THEN
1272           return_code := validate_context_segs(dff_info, context_segment.ids(1),
1273                            ncontext_segs_in, context_segs_in, vflags, v_date,
1274                            uappid, respid, context_segs, error_segnum);
1275         END IF;
1276         if(error_segnum is not null) then
1277           error_segnum := error_segnum + global_segs.nvalidated + 1;
1278         end if;
1279       end if;
1280     END IF;
1281 
1282     <<return_values>>
1283 
1284 -- Join global segments, context segment and context-senstive segments
1285 -- for output.
1286 --
1287     if((append_vsegarray(global_segs, context_segment) = FALSE) or
1288        (append_vsegarray(global_segs, context_segs) = FALSE)) then
1289        return(FND_FLEX_SERVER1.VV_ERROR);
1290     end if;
1291 
1292 --  Return all the segment info
1293 --
1294     nsegs_out := global_segs.nvalidated;
1295     segfmts := global_segs.segfmts;
1296     segstats := global_segs.segstats;
1297     cols := global_segs.segcols;
1298     coltypes := global_segs.segcoltypes;
1299     v_dispvals := global_segs.dispvals;
1300     v_vals := global_segs.vals;
1301     v_ids := global_segs.ids;
1302     v_descs := global_segs.descs;
1303     desc_lens := global_segs.catdesclens;
1304     dispsegs := global_segs.dispsegs;
1305 
1306 -- Prioritize errors and return code.
1307 -- If error in global segments worse than that in context or
1308 -- context-sensitive segments then use global error code, segnum and message.
1309 
1310 -- Return context return code, error message and error segment by default.
1311 --
1312     errsegn := error_segnum;
1313 
1314     if(global_return_code is not null) then
1315       if(global_return_code = FND_FLEX_SERVER1.VV_VALID) then
1316         null;
1317       elsif(global_return_code = FND_FLEX_SERVER1.VV_SECURED) then
1318         if((return_code is null) or
1319            (return_code = FND_FLEX_SERVER1.VV_VALID) or
1320            (return_code = FND_FLEX_SERVER1.VV_SECURED)) then
1321           goto return_global_error;
1322         end if;
1323       elsif(global_return_code = FND_FLEX_SERVER1.VV_VALUES) then
1324         if((return_code is null) or
1325            (return_code = FND_FLEX_SERVER1.VV_VALID) or
1326            (return_code = FND_FLEX_SERVER1.VV_SECURED) or
1327            (return_code = FND_FLEX_SERVER1.VV_VALUES)) then
1328           goto return_global_error;
1329         end if;
1330       else
1331         goto return_global_error;
1332       end if;
1333     end if;
1334 
1335     if(return_code is null) then
1336       return_code := FND_FLEX_SERVER1.VV_ERROR;
1337     end if;
1338     return(return_code);
1339 
1340     <<return_global_error>>
1341     errsegn := global_error_segnum;
1342     FND_MESSAGE.SET_ENCODED(global_error_msg);
1343     return(global_return_code);
1344 
1345   EXCEPTION
1346     WHEN OTHERS then
1347       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1348       FND_MESSAGE.set_token('MSG','validate_descsegs() exception:  '||SQLERRM);
1349       return(FND_FLEX_SERVER1.VV_ERROR);
1350 
1351   END validate_descsegs;
1352 
1353 /* ----------------------------------------------------------------------- */
1354 /*      Validates the context-sensitive segments of the descriptive        */
1355 /*      for the context of the given name returning a validated context    */
1356 /*      structure and error segment number relative to this context        */
1357 /*      as output.  If context name is NULL, returns a valid context with  */
1358 /*      0 segments.  Returns error code and sets FND_MESSAGE with error    */
1359 /*      or returns FND_FLEX_SERVER1.VV_VALID if ok.                        */
1360 /* ----------------------------------------------------------------------- */
1361 
1362   FUNCTION
1363   validate_context_segs(dff_info     IN  FND_FLEX_SERVER1.DescFlexInfo,
1364                         contxt_name  IN  VARCHAR2,
1365                         nsegs        IN  NUMBER,
1366                         segs         IN  FND_FLEX_SERVER1.StringArray,
1367                         vflags       IN  FND_FLEX_SERVER1.ValueValidationFlags,
1368                         vdate        IN  DATE,
1369                         uappid       IN  NUMBER,
1370                         respid       IN  NUMBER,
1371                         vsa          OUT nocopy ValidatedSegmentArray,
1372                         errsegnum    OUT nocopy NUMBER) RETURN NUMBER IS
1373 
1374     f_struct    FND_FLEX_SERVER1.FlexStructId;
1375     disp_segs   FND_FLEX_SERVER1.DisplayedSegs;
1376     no_vrules   FND_FLEX_SERVER1.Vrules;
1377     no_dvals    FND_FLEX_SERVER1.DerivedVals;
1378     no_dquals   FND_FLEX_SERVER1.Qualifiers;
1379 
1380     l_nsegs_out   NUMBER;
1381     l_segfmts     FND_FLEX_SERVER1.segformats;
1382     l_segstats    VARCHAR2(30);
1383     l_tabcols     FND_FLEX_SERVER1.tabcolarray;
1384     l_tabcoltypes FND_FLEX_SERVER1.chararray;
1385     l_v_dispvals  FND_FLEX_SERVER1.valuearray;
1386     l_v_vals      FND_FLEX_SERVER1.valuearray;
1387     l_v_ids       FND_FLEX_SERVER1.valueidarray;
1388     l_v_descs     FND_FLEX_SERVER1.valuedescarray;
1389     l_desc_lens   FND_FLEX_SERVER1.numberarray;
1390     l_errsegn     NUMBER;
1391     l_ret_code    NUMBER;
1392   BEGIN
1393      IF (fnd_flex_server1.g_debug_level > 0) THEN
1394         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1395                                    'BEGIN SV4.validate_context_segs() ');
1396      END IF;
1397 
1398 
1399 --  Initialize returned ValidatedSegmentArray to no segments.
1400 --
1401     initialize_vsegarray(vsa);
1402 
1403 --  Return a null ValidatedSegmentArray if no context name.
1404 --
1405     if(contxt_name is null) then
1406       return(FND_FLEX_SERVER1.VV_VALID);
1407     end if;
1408 
1409 --  Set up flex structure
1410 --
1411     f_struct.isa_key_flexfield := FALSE;
1412     f_struct.application_id := dff_info.application_id;
1413     f_struct.desc_flex_name := dff_info.name;
1414     f_struct.desc_flex_context := contxt_name;
1415 
1416 --  Set up dummy vrules.  No vrules for descriptive flexfields
1417 --
1418     no_vrules.nvrules := 0;
1419 
1420 --  Determine displayed segments for this context
1421 --
1422     if(FND_FLEX_SERVER.parse_displayed(f_struct, 'ALL', disp_segs)) then
1423        l_ret_code := FND_FLEX_SERVER1.validate_struct
1424          (f_struct, dff_info.table_appl_id,
1425           dff_info.table_id, nsegs, segs, disp_segs, vflags,
1426           vdate, no_vrules, uappid, respid,
1427           l_nsegs_out, l_segfmts, l_segstats, l_tabcols,
1428           l_tabcoltypes, l_v_dispvals, l_v_vals,
1429           l_v_ids, l_v_descs, l_desc_lens,
1430           no_dvals, no_dquals, l_errsegn);
1431 
1432        vsa.nvalidated  := l_nsegs_out;
1433        vsa.segfmts     := l_segfmts;
1434        vsa.segstats    := l_segstats;
1435        vsa.segcols     := l_tabcols;
1436        vsa.segcoltypes := l_tabcoltypes;
1437        vsa.dispvals    := l_v_dispvals;
1438        vsa.vals        := l_v_vals;
1439        vsa.ids         := l_v_ids;
1440        vsa.descs       := l_v_descs;
1441        vsa.catdesclens := l_desc_lens;
1442        errsegnum       := l_errsegn;
1443        vsa.dispsegs    := disp_segs;
1444        RETURN(l_ret_code);
1445     end if;
1446     return(FND_FLEX_SERVER1.VV_ERROR);
1447 
1448   EXCEPTION
1449     WHEN OTHERS then
1450       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1451       FND_MESSAGE.set_token('MSG', 'validate_context_segs() exception: '
1452                                                                || SQLERRM);
1453       return(FND_FLEX_SERVER1.VV_ERROR);
1454 
1455   END validate_context_segs;
1456 
1457 /* ----------------------------------------------------------------------- */
1458 /*      Validates the context value for the specified descriptive          */
1459 /*      flexfield.  Returns an error code and sets FND_MESSAGE on error    */
1460 /*      or returns FND_FLEX_SERVER1.VV_VALID and a ValidatedSegmentArray   */
1461 /*      with only one segment if valid.                                    */
1462 /*      Note:  Unlike regular value validation, validation must always     */
1463 /*      stop if the context segment is invalid because the remaining       */
1464 /*      segments all depend on it.                                         */
1465 /* ----------------------------------------------------------------------- */
1466 
1467   FUNCTION
1468        validate_context(dff_info     IN  FND_FLEX_SERVER1.DescFlexInfo,
1469                         context_sval IN  VARCHAR2,
1470                         vflags       IN  FND_FLEX_SERVER1.ValueValidationFlags,
1471                         vsa          OUT nocopy ValidatedSegmentArray)
1472                                                         RETURN NUMBER IS
1473 
1474     context_segval      VARCHAR2(80);
1475     context_id          VARCHAR2(30);
1476     context_val         VARCHAR2(80);
1477     context_description VARCHAR2(240);
1478     context_displayed   BOOLEAN;
1479     vcode               VARCHAR2(1);
1480     l_id_or_value       VARCHAR2(10);
1481     l_max_lengthb       NUMBER;
1482     l_global_flag       VARCHAR2(10);
1483     vset                FND_VSET.valueset_r;
1484     fmt                 FND_VSET.valueset_dr;
1485     c_found             BOOLEAN;
1486     c_row               NUMBER;
1487     c_value             FND_VSET.value_dr;
1488 
1489   BEGIN
1490      IF (fnd_flex_server1.g_debug_level > 0) THEN
1491         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1492                                    'BEGIN SV4.validate_context() ');
1493      END IF;
1494 
1495 
1496 --  Prepare to return error in case of exception
1497 --
1498     context_displayed := (dff_info.context_override = 'Y');
1499 
1500     vsa.nvalidated := 1;
1501     vsa.segstats := FND_FLEX_SERVER1.FF_VERROR;
1502     vsa.segfmts.nsegs := 1;
1503     vsa.segfmts.vs_format(1) := 'C';
1504     vsa.segfmts.vs_maxsize(1) := 30;
1505     vsa.segcols(1) := dff_info.context_column;
1506     vsa.segcoltypes(1) := 'V';
1507     vsa.dispvals(1) := context_sval;
1508     vsa.vals(1) := context_sval;
1509     vsa.ids(1) := context_sval;
1510     vsa.descs(1) := NULL;
1511     vsa.catdesclens(1) := 240;
1512     vsa.dispsegs.n_segflags := 1;
1513     vsa.dispsegs.segflags(1) := context_displayed;
1514 
1515     IF (fnd_flex_server1.g_debug_level > 0) THEN
1516        FND_FLEX_SERVER1.add_debug('CONTEXT:'||context_sval);
1517     END IF;
1518 
1519 --  Strip whitespace from around context value only if its a value
1520 --
1521     if(vflags.values_not_ids) THEN
1522        l_id_or_value := 'V';
1523        l_max_lengthb := 80;
1524        context_segval := SUBSTRB(LTRIM(RTRIM(context_sval)), 1, l_max_lengthb);
1525      ELSE
1526        l_id_or_value := 'I';
1527        l_max_lengthb := 30;
1528        context_segval := SUBSTRB(context_sval, 1, l_max_lengthb);
1529     end if;
1530 
1531     if((context_segval is not null) and
1532        (LENGTHB(context_segval) > l_max_lengthb)) then
1533       FND_MESSAGE.set_name('FND', 'FLEX-VALUE TOO LONG');
1534       FND_MESSAGE.set_token('VALUE', context_segval || '...');
1535       FND_MESSAGE.set_token('LENGTH', to_char(l_max_lengthb));
1536       vcode := FND_FLEX_SERVER1.FF_VFORMAT;
1537       goto return_status;
1538     end if;
1539 
1540 --  Default the context if necessary
1541 --
1542     if((context_segval is null) and
1543        ((context_displayed and vflags.default_all_displayed) or
1544          ((dff_info.context_required = 'Y') and vflags.default_all_required) or
1545          ((dff_info.context_required = 'Y') and (not context_displayed) and
1546           vflags.default_non_displayed))) then
1547       context_segval := dff_info.default_context;
1548       IF (fnd_flex_server1.g_debug_level > 0) THEN
1549          FND_FLEX_SERVER1.add_debug('Defaulted context segment to '
1550                                     || context_segval);
1551       END IF;
1552     end if;
1553 
1554     IF (context_segval IS NOT NULL) THEN
1555        vcode := find_context_value(dff_info.application_id, dff_info.name,
1556                                    l_id_or_value, context_segval, context_id,
1557                                    context_val, context_description, l_global_flag);
1558        if (vcode = FND_FLEX_SERVER1.FF_CTXTNOSEG) THEN
1559           IF (dff_info.context_override_value_set_id IS NOT NULL) THEN
1560              fnd_vset.get_valueset(dff_info.context_override_value_set_id, vset, fmt);
1561              fnd_vset.get_value_init(vset, TRUE);
1562              fnd_vset.get_value(vset, c_row, c_found, c_value);
1563              WHILE(c_found) LOOP
1564                 IF (context_segval = c_value.value) THEN
1565                    vcode := FND_FLEX_SERVER1.FF_VVALID;
1566                    EXIT;
1567                 END IF;
1568                 fnd_vset.get_value(vset, c_row, c_found, c_value);
1569              END LOOP;
1570              fnd_vset.get_value_end(vset);
1571              IF (c_found = FALSE) THEN
1572                 vcode:= FND_FLEX_SERVER1.FF_VNOTFOUND;
1573              END IF;
1574           END IF;
1575 
1576        END IF;
1577        --
1578        -- Some developers set Global as regular context.
1579        --
1580        IF (l_global_flag = 'Y') THEN
1581           IF (fnd_flex_server1.g_debug_level > 0) THEN
1582              FND_FLEX_SERVER1.add_debug('Setting context to NULL, Global Data Elements is not a context.');
1583           END IF;
1584           context_id := NULL;
1585           context_val := NULL;
1586           context_description := NULL;
1587        END IF;
1588     END IF;
1589 
1590 --  If value still null its an error if required, or valid if not.
1591 --
1592 
1593     if(context_segval is null) then
1594       if((dff_info.context_required = 'N') or (vflags.allow_nulls)) then
1595         vcode := FND_FLEX_SERVER1.FF_VVALID;
1596       else
1597         vcode := FND_FLEX_SERVER1.FF_VREQUIRED;
1598         if(vflags.message_on_null) then
1599           FND_MESSAGE.set_name('FND', 'FLEX-MISSING CONTEXT VALUE');
1600           FND_MESSAGE.set_token('FLEXFIELD', dff_info.name);
1601 --        FND_MESSAGE.set_name('FND', 'FLEX-NULL SEGMENT');
1602         end if;
1603       end if;
1604     end if;
1605 
1606     <<return_status>>
1607 --  Return vcode as the segment status
1608 --
1609     vsa.segstats := vcode;
1610 
1611 --  Pretend context field is a non-validated character value set
1612 --  I assume context field must be on a VARCHAR2 type column.
1613 --
1614     if(vcode = FND_FLEX_SERVER1.FF_VVALID) then
1615       vsa.dispvals(1) := context_val;
1616       vsa.vals(1) := context_val;
1617       vsa.ids(1) := context_id;
1618       vsa.descs(1) := context_description;
1619       return(FND_FLEX_SERVER1.VV_VALID);
1620     elsif(vcode = FND_FLEX_SERVER1.FF_VERROR) then
1621       return(FND_FLEX_SERVER1.VV_ERROR);
1622     else
1623       FND_MESSAGE.set_name('FND', 'FLEX-CONTEXT NOT FOUND');
1624       FND_MESSAGE.set_token('VALUE', context_segval);
1625       FND_MESSAGE.set_token('DFF', dff_info.name);
1626       return(FND_FLEX_SERVER1.VV_VALUES);
1627     end if;
1628 
1629     return(FND_FLEX_SERVER1.VV_ERROR);
1630 
1631   EXCEPTION
1632     WHEN OTHERS then
1633       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1634       FND_MESSAGE.set_token('MSG', 'validate_context() exception: '||SQLERRM);
1635       return(FND_FLEX_SERVER1.VV_ERROR);
1636 
1637   END validate_context;
1638 
1639 /* ----------------------------------------------------------------------- */
1640 /*      Appends segments from one ValidatedSegmentArray to another.        */
1641 /*      Returns TRUE if OK, or FALSE if any errors.                        */
1642 /* ----------------------------------------------------------------------- */
1643 
1644   FUNCTION append_vsegarray(destvsa    IN OUT  nocopy ValidatedSegmentArray,
1645                             sourcevsa  IN      ValidatedSegmentArray)
1646                                                              RETURN BOOLEAN IS
1647     n   NUMBER;
1648 
1649   BEGIN
1650      IF (fnd_flex_server1.g_debug_level > 0) THEN
1651         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1652                                    'BEGIN SV4.append_vsegarray() ');
1653      END IF;
1654 
1655     n := destvsa.nvalidated;
1656     for i in 1..sourcevsa.nvalidated loop
1657       n := n + 1;
1658       destvsa.segfmts.vs_format(n) := sourcevsa.segfmts.vs_format(i);
1659       destvsa.segfmts.vs_maxsize(n) := sourcevsa.segfmts.vs_maxsize(i);
1660       destvsa.segcols(n) := sourcevsa.segcols(i);
1661       destvsa.segcoltypes(n) := sourcevsa.segcoltypes(i);
1662       destvsa.dispvals(n) := sourcevsa.dispvals(i);
1663       destvsa.vals(n) := sourcevsa.vals(i);
1664       destvsa.ids(n) := sourcevsa.ids(i);
1665       destvsa.descs(n) := sourcevsa.descs(i);
1666       destvsa.catdesclens(n) := sourcevsa.catdesclens(i);
1667       destvsa.dispsegs.segflags(n) := sourcevsa.dispsegs.segflags(i);
1668     end loop;
1669 
1670     destvsa.nvalidated := n;
1671     destvsa.segfmts.nsegs := n;
1672     destvsa.dispsegs.n_segflags := n;
1673     destvsa.segstats := destvsa.segstats || sourcevsa.segstats;
1674 
1675     return(TRUE);
1676 
1677   EXCEPTION
1678     WHEN OTHERS then
1679       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1680       FND_MESSAGE.set_token('MSG','append_vsegarray() exception:  '||SQLERRM);
1681       return(FALSE);
1682 
1683   END append_vsegarray;
1684 
1685 /* ----------------------------------------------------------------------- */
1686 /*      Initializes ValidatedSegmentArray.                                 */
1687 /* ----------------------------------------------------------------------- */
1688 
1689   PROCEDURE initialize_vsegarray(v_seg_array  OUT nocopy ValidatedSegmentArray) IS
1690   BEGIN
1691     v_seg_array.nvalidated := 0;
1692     v_seg_array.segfmts.nsegs := 0;
1693     v_seg_array.dispsegs.n_segflags := 0;
1694   END initialize_vsegarray;
1695 
1696 /* ----------------------------------------------------------------------- */
1697 /*      Initializes ColumnDefinitions.                                     */
1698 /* ----------------------------------------------------------------------- */
1699 
1700   PROCEDURE init_coldef(column_defn OUT nocopy FND_FLEX_SERVER1.ColumnDefinitions) IS
1701   BEGIN
1702     column_defn.context_value_set := FALSE;
1703     column_defn.context_value := NULL;
1704     init_colvals(column_defn.colvals);
1705   END init_coldef;
1706 
1707 /* ----------------------------------------------------------------------- */
1708 /*      Initializes ColumnValues.                                          */
1709 /* ----------------------------------------------------------------------- */
1710 
1711   PROCEDURE init_colvals(column_vals OUT nocopy FND_FLEX_SERVER1.ColumnValues) IS
1712   BEGIN
1713     column_vals.ncolumns := 0;
1714   END init_colvals;
1715 
1716 /* ----------------------------------------------------------------------- */
1717 /*      Finds enabled context value and description from context segment.  */
1718 /*      Only considers enabled contexts.                                   */
1719 /*                                                                         */
1720 /*      In future we may support:                                          */
1721 /*      If no context is found that exactly matches the context segment    */
1722 /*      input, then a case-insensitive match is done on values that start  */
1723 /*      with the context segment input.  If only one value matches that,   */
1724 /*      that context is returned.  Otherwise the context is not found.     */
1725 /*                                                                         */
1726 /*      Returns value validation code FND_FLEX_SERVER1.FF_VALID if ok.     */
1727 /*      Otherwise sets error message in FND_MESSAGE and returns            */
1728 /*      FF_VVALUES if not found or FF_VERROR on error.                     */
1729 /* ----------------------------------------------------------------------- */
1730 
1731   FUNCTION find_context_value(appl_id       IN  VARCHAR2,
1732                               dflex_name    IN  VARCHAR2,
1733                               p_id_or_value IN  VARCHAR2,
1734                               seg_in        IN  VARCHAR2,
1735                               context_id    OUT nocopy VARCHAR2,
1736                               context_val   OUT nocopy VARCHAR2,
1737                               context_desc  OUT nocopy VARCHAR2,
1738                               p_global_flag OUT nocopy VARCHAR2) RETURN VARCHAR2 IS
1739 
1740     vcode               VARCHAR2(1);
1741 
1742   BEGIN
1743      IF (fnd_flex_server1.g_debug_level > 0) THEN
1744         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1745                                    'BEGIN SV4.find_context_value(' ||
1746                                    p_id_or_value || ',' || seg_in ||') ');
1747      END IF;
1748 
1749      g_cache_key := (appl_id || '.' || dflex_name || '.' ||
1750                      p_id_or_value  || '.' || seg_in);
1751      fnd_plsql_cache.generic_1to1_get_value(cxc_cache_controller,
1752                                             cxc_cache_storage,
1753                                             g_cache_key,
1754                                             g_cache_value,
1755                                             g_cache_return_code);
1756      IF (g_cache_return_code = fnd_plsql_cache.CACHE_FOUND) THEN
1757         NULL;
1758       ELSE
1759         SELECT
1760           descriptive_flex_context_code,
1761           descriptive_flex_context_name,
1762           description,
1763           global_flag
1764           INTO
1765           g_cache_value.varchar2_1,
1766           g_cache_value.varchar2_2,
1767           g_cache_value.varchar2_3,
1768           g_cache_value.varchar2_4
1769       FROM fnd_descr_flex_contexts_vl
1770      WHERE application_id = appl_id
1771        AND descriptive_flexfield_name = dflex_name
1772        AND ((p_id_or_value = 'I' AND
1773              descriptive_flex_context_code = seg_in) OR
1774             (p_id_or_value = 'V' AND
1775              descriptive_flex_context_name = seg_in))
1776        AND enabled_flag = 'Y';
1777 
1778         fnd_plsql_cache.generic_1to1_put_value(cxc_cache_controller,
1779                                                cxc_cache_storage,
1780                                                g_cache_key,
1781                                                g_cache_value);
1782      END IF;
1783 
1784      context_id := g_cache_value.varchar2_1;
1785      context_val := g_cache_value.varchar2_2;
1786      context_desc := g_cache_value.varchar2_3;
1787      p_global_flag := g_cache_value.varchar2_4;
1788 
1789      return(FND_FLEX_SERVER1.FF_VVALID);
1790 
1791   EXCEPTION
1792     WHEN NO_DATA_FOUND then
1793 ----      vcode := context_vs_validation();
1794 --      context_id := seg_in;
1795 --      context_val := seg_in;
1796 --      context_desc := 'Dummy';
1797 --      p_global_flag := 'X';
1798         vcode := FND_FLEX_SERVER1.FF_CTXTNOSEG;
1799 --      IF(vcode = FND_FLEX_SERVER1.FF_CTXTNOSEG) THEN
1800         return(FND_FLEX_SERVER1.FF_CTXTNOSEG);
1801 --      ELSE
1802 --        FND_MESSAGE.set_name('FND', 'FLEX-CONTEXT NOT FOUND');
1803 --        FND_MESSAGE.set_token('VALUE', seg_in);
1804 --        FND_MESSAGE.set_token('DFF', dflex_name);
1805 --        return(FND_FLEX_SERVER1.FF_VNOTFOUND);
1806 --      END IF;
1807     WHEN OTHERS then
1808       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1809       FND_MESSAGE.set_token('MSG','find_context_value() exception: '||SQLERRM);
1810       return(FND_FLEX_SERVER1.FF_VERROR);
1811 
1812    END find_context_value;
1813 
1814 /* ----------------------------------------------------------------------- */
1815 /*      Gets the name of the global context for the specified flexfield.   */
1816 /*      Error if the global context name is not enabled.                   */
1817 /*      Returns TRUE if OK or FALSE and sets FND_MESSAGE if error.         */
1818 /* ----------------------------------------------------------------------- */
1819 
1820   FUNCTION get_global_context(appl_id      IN  NUMBER,
1821                               dflex_name   IN  VARCHAR2,
1822                               glob_context OUT nocopy VARCHAR2) RETURN BOOLEAN IS
1823   BEGIN
1824      IF (fnd_flex_server1.g_debug_level > 0) THEN
1825         FND_FLEX_SERVER1.add_debug(fnd_global.newline ||
1826                                    'BEGIN SV4.get_global_context() ');
1827      END IF;
1828 
1829      g_cache_key := appl_id || '.' || dflex_name;
1830      fnd_plsql_cache.generic_1to1_get_value(gcc_cache_controller,
1831                                             gcc_cache_storage,
1832                                             g_cache_key,
1833                                             g_cache_value,
1834                                             g_cache_return_code);
1835      IF (g_cache_return_code = fnd_plsql_cache.CACHE_FOUND) THEN
1836         NULL;
1837       ELSE
1838         SELECT
1839           descriptive_flex_context_code
1840           INTO
1841           g_cache_value.varchar2_1
1842           FROM fnd_descr_flex_contexts
1843           WHERE application_id = appl_id
1844           AND descriptive_flexfield_name = dflex_name
1845           AND enabled_flag = 'Y'
1846           AND global_flag = 'Y';
1847 
1848         fnd_plsql_cache.generic_1to1_put_value(gcc_cache_controller,
1849                                                gcc_cache_storage,
1850                                                g_cache_key,
1851                                                g_cache_value);
1852      END IF;
1853 
1854      glob_context := g_cache_value.varchar2_1;
1855 
1856      return(TRUE);
1857 
1858   EXCEPTION
1859     WHEN NO_DATA_FOUND then
1860       FND_MESSAGE.set_name('FND', 'FLEX-NO ENABLED GLOBAL CONTEXT');
1861       return(FALSE);
1862     WHEN TOO_MANY_ROWS then
1863       FND_MESSAGE.set_name('FND', 'FLEX-DUPLICATE GLOBAL CONTEXTS');
1864       FND_MESSAGE.set_token('APID', appl_id);
1865       FND_MESSAGE.set_token('NAME', dflex_name);
1866       return(FALSE);
1867     WHEN OTHERS then
1868       FND_MESSAGE.set_name('FND', 'FLEX-SSV EXCEPTION');
1869       FND_MESSAGE.set_token('MSG','get_global_context() exception: '||SQLERRM);
1870       return(FALSE);
1871   END get_global_context;
1872 
1873 /* ----------------------------------------------------------------------- */
1874 
1875 BEGIN
1876    fnd_plsql_cache.generic_1to1_init('SV4.CXC',
1877                                      cxc_cache_controller,
1878                                      cxc_cache_storage);
1879 
1880    fnd_plsql_cache.generic_1to1_init('SV4.GCC',
1881                                      gcc_cache_controller,
1882                                      gcc_cache_storage);
1883 END fnd_flex_server4;