DBA Data[Home] [Help]

PACKAGE BODY: APPS.JDR_CUSTOM_INTERNAL

Source


1 PACKAGE BODY jdr_custom_internal AS
2 /* $Header: JDRCTINB.pls 120.3 2005/10/26 06:14:58 akbansal noship $ */
3   -----------------------------------------------------------------------------
4   ---------------------------- PRIVATE VARIABLES ------------------------------
5   -----------------------------------------------------------------------------
6 
7   APPS_ROOTDIR   CONSTANT VARCHAR2(30) := '/oracle/apps/';
8   PORTLET        CONSTANT VARCHAR2(10) := 'PORTLET';
9 
10   -- Constants for layer precedence order
11   FUNCTION_LEVEL         CONSTANT NUMBER := 1;
12   VERTICALIZATION_LEVEL  CONSTANT NUMBER := 2;
13   LOCALIZATION_LEVEL     CONSTANT NUMBER := 3;
14   SITE_LEVEL             CONSTANT NUMBER := 4;
15   ORG_LEVEL              CONSTANT NUMBER := 5;
16   RESPONSIBILITY_LEVEL   CONSTANT NUMBER := 6;
17   SEEDED_DEV_USER_LEVEL  CONSTANT NUMBER := 7;
18   SEEDED_CUST_USER_LEVEL CONSTANT NUMBER := 8;
19   END_USER_LEVEL         CONSTANT NUMBER := 9;
20   PORTLET_LEVEL          CONSTANT NUMBER := 10;
21 
22   -----------------------------------------------------------------------------
23   ----------------------------- PRIVATE FUNCTIONS -----------------------------
24   -----------------------------------------------------------------------------
25 
26   -- Add the attributes of the region customization document to the page
27   -- customization document.
28   --
29   -- Parameters:
30   --   pageCustDocID    Document ID of the page customization document
31   --   pageCompSeq      Component sequence of the page component (destination)
32   --   regionCustDocID  Document ID of the region customization document
33   --   regionCompSeq    Component sequence of the region component (source)
34   --   extendingRegion  Component ID of the extending region
35   --   needElementAtt   Is an element attribute needed?
36   PROCEDURE addAttributes(pageCustDocID    jdr_paths.path_docid%TYPE,
37                           pageCompSeq      jdr_attributes.att_comp_seq%TYPE,
38                           regionCustDocID  jdr_paths.path_docid%TYPE,
39                           regionCompSeq    jdr_attributes.att_comp_seq%TYPE,
40                           extendingRegion  jdr_components.comp_id%TYPE,
41                           needElementAtt   BOOLEAN)
42   IS
43     CURSOR c_attributes(docID   jdr_paths.path_docid%TYPE,
44                         compSeq jdr_components.comp_seq%TYPE) IS
45       SELECT att_seq, att_name, att_value
46       FROM jdr_attributes
47       WHERE att_comp_docid = docID AND
48             att_comp_seq = compSeq;
49 
50     attRec           c_attributes%ROWTYPE;
51     nextAttSequence  jdr_attributes.att_seq%TYPE;
52     addElementAtt    BOOLEAN := needElementAtt;
53   BEGIN
54     nextAttSequence := 0;
55 
56     -- Retrieve the attributes from the region document and insert them
57     -- into the page document
58     OPEN c_attributes(regionCustDocID, regionCompSeq);
59     LOOP
60       FETCH c_attributes INTO attRec;
61 
62       IF c_attributes%NOTFOUND THEN
63         CLOSE c_attributes;
64         EXIT;
65       END IF;
66 
67       -- If the attribute is a component reference, then need to add the
68       -- per instance prefix
69       IF (attRec.att_name IN ('element', 'parent', 'after', 'before')) THEN
70         attRec.att_value := extendingRegion || '.' || attRec.att_value;
71       END IF;
72 
73       -- Do not need an element attribute if we already have one
74       IF (attRec.att_name = 'element') THEN
75         addElementAtt := FALSE;
76       END IF;
77 
78       -- Insert the component into the per instance view
79       INSERT INTO jdr_attributes
80         (att_comp_docid, att_comp_seq, att_seq, att_name, att_value)
81       VALUES
82         (pageCustDocID, pageCompSeq,
83          attRec.att_seq, attRec.att_name, attRec.att_value);
84 
85       nextAttSequence := attRec.att_seq + 1;
86     END LOOP;
87 
88     -- Add the element attribute if necessary.  This will occur when the
89     -- reference (in the region customization document) was to the top-level
90     -- component (i.e. the region) and so was implicit.  But since the
91     -- customization is moving from a top-level component to a non top-level
92     -- component, we now must specify the element attribute.
93     IF (addElementAtt = TRUE) THEN
94       INSERT INTO jdr_attributes
95         (att_comp_docid, att_comp_seq, att_seq, att_name, att_value)
96       VALUES
97         (pageCustDocID, pageCompSeq,
98          nextAttSequence, 'element', extendingRegion);
99     END IF;
100   END;
101 
102 
103   -- Add the components of the region customization document to the page
104   -- customization document.
105   --
106   -- Parameters:
107   --   pageCustDocID    Document ID of the page customization document
108   --   pageStartSeq     Start sequence of the page components (destination)
109   --   regionCustDocID  Document ID of the region customization document
110   --   regionStartSeq   Start sequence of the region components (source)
111   --   regionEndSeq     End sequence of the region components
112   --   extendingRegion  Component ID of the extending region
113   PROCEDURE addComponents(pageCustDocID    jdr_paths.path_docid%TYPE,
114                           pageStartSeq     jdr_components.comp_seq%TYPE,
115                           regionCustDocID  jdr_paths.path_docid%TYPE,
116                           regionStartSeq   jdr_components.comp_seq%TYPE,
117                           regionEndSeq     jdr_components.comp_seq%TYPE,
118                           extendingRegion  jdr_components.comp_id%TYPE)
119   IS
120     CURSOR c_components(docID    jdr_paths.path_docid%TYPE,
121                         startSeq jdr_components.comp_seq%TYPE,
122                         endSeq   jdr_components.comp_seq%TYPE) IS
123       SELECT comp_seq, comp_level, comp_grouping, comp_element, comp_id
124       FROM jdr_components
125       WHERE comp_docid = docID AND
126             comp_seq >= startSeq AND
127             comp_seq <= endSeq;
128 
129     pageSeq          jdr_components.comp_seq%TYPE := pageStartSeq;
130     compRec          c_components%ROWTYPE;
131     needElementAtt   BOOLEAN;
132   BEGIN
133     -- Retrieve all of the components from the region document and insert
134     -- them into the page document
135     OPEN c_components(regionCustDocID, regionStartSeq, regionEndSeq);
136     LOOP
137       FETCH c_components INTO compRec;
138 
139       IF c_components%NOTFOUND THEN
140         CLOSE c_components;
141         EXIT;
142       END IF;
143 
144       -- Do not move initial 'views' or 'modifications' grouping unless this is
145       -- the first customization of the page
146       IF (pageSeq <> 1 AND compRec.comp_seq = 1) THEN
147         compRec.comp_grouping := NULL;
148       END IF;
149 
150       -- In the case where we are adding the contents of the view from the
151       -- region to an existing view on the page, we do not want to move the
152       -- 'modifications' grouping as it already exists for the view on the
153       -- page.
154       IF (compRec.comp_seq = regionStartSeq AND
155           compRec.comp_grouping = 'modifications' AND
156           pageSeq <> 1) THEN
157         compRec.comp_grouping := NULL;
158       END IF;
159 
160       INSERT INTO jdr_components
161         (comp_docid, comp_seq, comp_level, comp_grouping, comp_element, comp_id)
162       VALUES
163         (pageCustDocID, pageSeq, compRec.comp_level,
164          compRec.comp_grouping, compRec.comp_element, compRec.comp_id);
165 
166       -- If this row can contain a reference to the customized component, and
167       -- if the shared view references a top-level component, then it
168       -- previously would not have had an 'element' attribute which indicated
169       -- which component to customize (because top-level attributes are
170       -- implicitly referenced).  However, in propagating the view, the
171       -- component may not be a top-level component anymore, and, if so, we
172       -- will need to add an attribute for the reference to the component.
173       IF compRec.comp_element IN ('modify', 'view')  THEN
174         needElementAtt := TRUE;
175       ELSE
176         needElementAtt := FALSE;
177       END IF;
178 
179       addAttributes(pageCustDocID,
180                     pageSeq,
181                     regionCustDocID,
182                     comprec.comp_seq,
183                     extendingRegion,
184                     needElementAtt);
185 
186 
187       -- Prepare for the next component
188       pageSeq := pageSeq + 1;
189     END LOOP;
190   END;
191 
192 
193   -- Append the modifications customizations from the region document to the
194   -- end of the page document.
195   --
196   -- Parameters:
197   --   pageCustDocID    Document ID of the page customization document
198   --   regionCustDocID  Document ID of the region customization document
199   --   extendingRegion  Component ID of the extending region
200   PROCEDURE appendModifications(pageCustDocID    jdr_paths.path_docid%TYPE,
201                                 regionCustDocID  jdr_paths.path_docid%TYPE,
202                                 extendingRegion  jdr_components.comp_id%TYPE)
203 
204   IS
205     pageStartSeq     jdr_components.comp_seq%TYPE;
206     regionEndSeq     jdr_components.comp_seq%TYPE;
207   BEGIN
208     -- Get the starting sequence for the new customizations for the page
209     SELECT MAX(comp_seq) + 1 INTO pageStartSeq
210     FROM jdr_components
211     WHERE comp_docid = pageCustDocID;
212 
213     -- Get the number of components which need to be added from the region
214     SELECT MAX(comp_seq) INTO regionEndSeq
215     FROM jdr_components
216     WHERE comp_docid = regionCustDocID;
217 
218     addComponents(pageCustDocID,
219                   pageStartSeq,
220                   regionCustDocID,
221                   1,
222                   regionEndSeq,
223                   extendingRegion);
224   END;
225 
226 
227   -- Append the view customizations from the region document to the
228   -- page document.
229   --
230   -- Parameters:
231   --   pageCustDocID    Document ID of the page customization document
232   --   regionCustDocID  Document ID of the region customization document
233   --   extendingRegion  Component ID of the extending region
234   --   viewID           ID of the view
235   PROCEDURE appendView(pageCustDocID    jdr_paths.path_docid%TYPE,
236                        regionCustDocID  jdr_paths.path_docid%TYPE,
237                        extendingRegion  jdr_components.comp_id%TYPE,
238                        viewID           jdr_components.comp_id%TYPE)
239   IS
240     pageStartSeq      jdr_components.comp_seq%TYPE;
241     pageEndSeq        jdr_components.comp_seq%TYPE;
242     pageCompLevel     jdr_components.comp_level%TYPE;
243     regionStartSeq    jdr_components.comp_seq%TYPE;
244     regionEndSeq      jdr_components.comp_seq%TYPE;
245     regionCompLevel   jdr_components.comp_level%TYPE;
246 
247     componentsAdded   jdr_components.comp_seq%TYPE;
248   BEGIN
249     -- Get the start sequence of the view
250     SELECT comp_seq, comp_level INTO regionStartSeq, regionCompLevel
251     FROM jdr_components
252     WHERE comp_docid = regionCustDocID AND
253           comp_element = 'view' AND
254           comp_id = viewID;
255 
256     -- Get the end sequence of the view
257     SELECT MIN(comp_seq) - 1  INTO regionEndSeq
258     FROM jdr_components
259     WHERE comp_docid =  regionCustDocID AND
260           comp_seq > regionStartSeq AND
261           comp_level <= regionCompLevel;
262 
263     -- If this is the last view in the document, the end sequence will be the
264     -- last component in the document
265     IF (regionEndSeq IS NULL) THEN
266       SELECT MAX(comp_seq) INTO regionEndSeq
267       FROM jdr_components
268       WHERE comp_docid = regionCustDocID;
269     END IF;
270 
271     -- Check if this view already exists in the page.  If so, we will need
272     -- to append the contents of the region view to the page view
273     BEGIN
274       -- Get the start sequence of the view for the page (if the view exists)
275       SELECT comp_seq, comp_level INTO pageStartSeq, pageCompLevel
276       FROM jdr_components
277       WHERE comp_docid = pageCustDocID AND
278             comp_element = 'view' AND
279             comp_id = viewID;
280 
281       -- Get the end sequence of the view for the page (if the view exists)
282       SELECT MIN(comp_seq) - 1  INTO pageEndSeq
283       FROM jdr_components
284       WHERE comp_docid =  pageCustDocID AND
285             comp_seq > pageStartSeq AND
286             comp_level <= pageCompLevel;
287 
288       -- If this is the last view in the document, the end sequence will be the
289       -- last component in the document
290       IF (pageEndSeq IS NULL) THEN
291         SELECT MAX(comp_seq) INTO pageEndSeq
292         FROM jdr_components
293         WHERE comp_docid = pageCustDocID;
294       END IF;
295 
296     EXCEPTION
297       WHEN NO_DATA_FOUND THEN
298         -- If the view does not exist in the page already, then we will append
299         -- the view to the end of the page customization document.
300         SELECT MAX(comp_seq) + 1 INTO pageStartSeq
301         FROM jdr_components
302         WHERE comp_docid = pageCustDocID;
303     END;
304 
305     IF (pageEndSeq IS NULL) THEN
306       -- A null pageEndSeq indicates that the view does not exist in the page,
307       -- so we can append the view to the end of the page customization
308       -- document
309       addComponents(pageCustDocID,
310                     pageStartSeq,
311                     regionCustDocID,
312                     regionStartSeq,
313                     regionEndSeq,
314                     extendingRegion);
315     ELSE
316       -- The view already exists in the page document, so we need to append the
317       -- contents of the region view to the page view of the same name.  To
318       -- do this, we will shift all of the components after the page view up,
319       -- to make room for the contents of the region view.
320       componentsAdded := regionEndSeq - regionStartSeq + 1;
321 
322       -- Shift the components to make room for the region view
323       UPDATE jdr_components
324       SET comp_seq = comp_seq + componentsAdded
325       WHERE comp_docid = pageCustDocID AND
326             comp_seq > pageEndSeq;
327 
328       -- Shift the attributes to make room for the region view
329       UPDATE jdr_attributes
330       SET att_comp_seq = att_comp_seq + componentsAdded
331       WHERE att_comp_docid = pageCustDocID AND
332             att_comp_seq > pageEndSeq;
333 
334       -- Now that we have made room for the view, we can safely add the
335       -- components.
336       addComponents(pageCustDocID,
337                     pageEndSeq + 1,
338                     regionCustDocID,
339                     regionStartSeq + 1,
340                     regionEndSeq,
341                     extendingRegion);
342     END IF;
343   END;
344 
345   --
346   -- Get precedence order of a customization layer type
347   --
348   FUNCTION getPrecedence(type  VARCHAR2,
349                          value VARCHAR2 DEFAULT NULL) RETURN NUMBER
350   IS
351     upperType  VARCHAR2(100);
352     upperValue VARCHAR2(100);
353   BEGIN
354     upperType := upper(type);
355     IF (upperType = 'FUNCTION')
356     THEN
357       RETURN(FUNCTION_LEVEL);
358     END IF;
359     IF (upperType = 'VERTICALIZATION')
360     THEN
361       RETURN(VERTICALIZATION_LEVEL);
362     END IF;
363     IF (upperType = 'LOCALIZATION')
364     THEN
365       RETURN(LOCALIZATION_LEVEL);
366     END IF;
367     IF (upperType = 'SITE')
368     THEN
369       RETURN(SITE_LEVEL);
370     END IF;
371     IF (upperType = 'ORG')
372     THEN
373       RETURN(ORG_LEVEL);
374     END IF;
375     IF (upperType = 'RESPONSIBILITY')
376     THEN
377       RETURN(RESPONSIBILITY_LEVEL);
378     END IF;
379     IF (upperType = 'USER')
380     THEN
381       IF value IS NOT NULL
382       THEN
383         upperValue := upper(value);
384         IF (upperValue = 'SEEDEDCUSTOMER')
385         THEN
386           RETURN(SEEDED_CUST_USER_LEVEL);
387         ELSIF (upperValue = 'SEEDEDDEVELOPER')
388         THEN
389           RETURN(SEEDED_DEV_USER_LEVEL);
390         END IF;
391       END IF;
392       RETURN(END_USER_LEVEL);
393     END IF;
394     IF (upperType = PORTLET)
395     THEN
396       RETURN(PORTLET_LEVEL);
397     END IF;
398   END;
399 
400   --
401   -- Sorts the layers into precedence order, from lowest to highest
405   PROCEDURE sortLayersWithDocs(lyrTypes  IN OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
402   -- Currently using insertion sort. At the same time, sort customization
403   -- documents to match layer precedence.
404   --
406                                lyrValues IN OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
407                                custDocs  IN OUT NOCOPY /* file.sql.39 change */ jdr_stringArray)
408   IS
409     i NUMBER;
410     j NUMBER;
411     currType  VARCHAR2(50);
412     currValue VARCHAR2(100);
413     currDoc VARCHAR2(512);
414     currPrecedence NUMBER;
415     typeArray jdr_stringArray := lyrTypes;
416     valArray  jdr_stringArray := lyrValues;
417     docArray  jdr_stringArray := custDocs;
418   BEGIN
419     IF typeArray.COUNT > 1
420     THEN
421       FOR i IN 2..typeArray.COUNT LOOP
422         j := i;
423         currType  := typeArray(i);
424         currValue := valArray(i);
425         currDoc   := docArray(i);
426         currPrecedence := getPrecedence(currType, currValue);
427         WHILE (j > 1) AND
428             (getPrecedence(typeArray(j-1), valArray(j-1)) > currPrecedence) LOOP
429           typeArray(j) := typeArray(j-1);
430           valArray(j)  := valArray(j-1);
431           docArray(j)  := docArray(j-1);
432           j := j - 1;
433         END LOOP;
434         typeArray(j) := currType;
435         valArray(j)  := currValue;
436         docArray(j)  := currDoc;
437       END LOOP;
438     END IF;
439     lyrTypes  := typeArray;
440     lyrValues := valArray;
441     custDocs  := docArray;
442   END;
443 
444 
445  -- Returns the full name of the customization document
446   --
447   -- baseDocName is the full name of the base document
448   -- layerType is the type of customization layer - i.e. Site, Localization
449   -- layerValue is the value of the layer type - i.e. Sears, US
450   --
451   -- returns docname = <fullBasePackage>/customizations/<layerName>/
452   --                   <layerValue>/<docName>
453   -- where <fullBasePacakge> is the full name of the package containing the
454   -- base document.
455   -- ex. base page - /oracle/apps/hr/pages/page1
456   --     cust page - /oracle/apps/hr/pages/customizations/site/sears/page1
457   --
458   FUNCTION getCustomizationDocName(
459     baseDocName       VARCHAR2,
460     layerType         VARCHAR2,
461     layerValue        VARCHAR2) RETURN VARCHAR2
462   IS
463     custDocName VARCHAR2(512);
464     lenPkg      NUMBER;
465     lenApp      NUMBER;
466     pkgName     VARCHAR2(512);
467     baseName    VARCHAR2(512);
468   BEGIN
469     lenPkg  := INSTR(baseDocName, '/', -1, 1);
470     IF lenPkg = 0 OR
471        lenPkg = LENGTH(baseDocName)
472     THEN
473       RETURN NULL;
474     END IF;
475     IF lenPkg = 1
476     THEN
477       pkgName  := '';
478     ELSE
479       pkgName  := SUBSTR(baseDocName, 1, lenPkg - 1);
480     END IF;
481     baseName := SUBSTR(baseDocName, lenPkg + 1);
482     custDocName := pkgName || '/customizations/' || layerType  || '/'
483                            || layerValue        || '/'        || baseName;
484     RETURN(custDocName);
485   END;
486 
487 
488   -- Returns the full name of the customization document, using the old
489   -- customization directory structure
490   --
491   -- baseDocName is the full name of the base document
492   -- layerType is the type of customization layer - i.e. Site, Localization
493   -- layerValue is the value of the layer type - i.e. Sears, US
494   --
495   -- returns docname = /oracle/apps/<productname>/customizations/<layertype>/
496   --                   <layervalue>/<remainder of base docname>
497   -- ex. base page - /oracle/apps/hr/pages/page1
498   --     cust page - /oracle/apps/hr/customizations/site/sears/pages/page1
499   --
500   FUNCTION getOldCustomizationDocName(
501     baseDocName       VARCHAR2,
502     layerType         VARCHAR2,
503     layerValue        VARCHAR2) RETURN VARCHAR2
504   IS
505     custDocName VARCHAR2(512);
506     lenRoot NUMBER;
507     lenApp NUMBER;
508     startDoc VARCHAR2(512);
509     endDoc VARCHAR2(512);
510   BEGIN
511     lenRoot := LENGTH(APPS_ROOTDIR);
512     IF SUBSTR(baseDocName, 1, lenRoot) = APPS_ROOTDIR
513     THEN
514       startDoc := APPS_ROOTDIR;
515       endDoc := substr(baseDocName, lenRoot+1);
516       lenApp := instr(endDoc, '/');
517       IF NOT lenApp = 0
518       THEN
519         startDoc := startDoc || substr(endDoc, 1, lenApp);
520         endDoc := substr(endDoc, lenApp+1);
521         custDocName := startDoc || 'customizations/'
522                        || layerType || '/'
523                        || layerValue || '/'
524                        || endDoc;
525       END IF;
526     END IF;
527     RETURN(custDocName);
528   END;
529 
530 
531   -- Returns the full reference to the portlet customization document, using
532   -- the old method of using <portletReferencePath> as the layer value.
533   -- The new method, using <userId_portletReferencePath> as the layer value,
534   -- was developed to resolve bug 2587054.  However, the old reference still
535   -- is used to find any portlet customizations which were created before Apps
536   -- introduced the userId dependency.
537   --
538   -- baseDocName is the full name of the base document
539   -- layerType is the portlet customization layer
540   -- portletVal is the customization layer value of the portlet
541   --
542   FUNCTION getOldPortletReference(
543     baseDocName       VARCHAR2,
544     layerType         VARCHAR2,
545     portletVal        VARCHAR2,
546     newCustDirectory  BOOLEAN DEFAULT TRUE) RETURN VARCHAR2
547   IS
551   BEGIN
548     portletRef    VARCHAR2(512);
549     newPortletVal VARCHAR2(512);
550     userIdx       NUMBER;
552     userIdx := instr(portletVal, '_');
553     IF NOT userIdx = 0
554     THEN
555       newPortletVal  := substr(portletVal, userIdx + 1);
556       IF ( newCustDirectory )
557       THEN
558         portletRef     := getCustomizationDocName(baseDocName,
559                                                   layerType,
560                                                   newPortletVal);
561       ELSE
562         portletRef     := getOldCustomizationDocName(baseDocName,
563                                                      layerType,
564                                                      newPortletVal);
565       END IF;
566     END IF;
567     RETURN(portletRef);
568   END;
569 
570   PROCEDURE getLayers(baseDoc    IN  VARCHAR2,
571                       lyrTypes   IN  jdr_stringArray,
572                       lyrValues  IN  jdr_stringArray,
573                       validTypes OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
574                       custDocs   OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
575                       activeOnly IN  BOOLEAN DEFAULT FALSE)
576   IS
577     valid jdr_stringArray := jdr_stringArray(null);
578     lvals jdr_stringArray := jdr_stringArray(null);
579     docs jdr_stringArray := jdr_stringArray(null);
580     custName    VARCHAR2(512);
581     tmpCustName VARCHAR2(512);
582     custDocID NUMBER;
583     cnt NUMBER := 1;
584     isActive VARCHAR2(10);
585   BEGIN
586     FOR i IN 1..lyrTypes.COUNT LOOP
587       -- For each layer, attempt to find the customization document
588       custName := getCustomizationDocName(baseDoc,
589                                           lyrTypes(i),
590                                           lyrValues(i));
591       IF NOT custName IS NULL
592       THEN
593         custDocID := jdr_mds_internal.getDocumentID(custName, 'DOCUMENT');
594         IF (custDocID = -1)
595         THEN
596           IF (upper(lyrTypes(i)) = PORTLET)
597           THEN
598             -- Assuming that the portlet value is <userid>_<referencepath>,
599             -- try using value <referencepath> if no customization doc was found
600             tmpCustName := getOldPortletReference(baseDoc,
601                                                   lyrTypes(i),
602                                                   lyrValues(i));
603             custDocID := jdr_mds_internal.getDocumentID(tmpCustName,
604                                                         'DOCUMENT');
605             IF ( custDocID <> -1 )
606             THEN
607               custName  := tmpCustName;
608             END IF;
609           END IF;
610           IF ( custDocID = -1 )
611           THEN
612             -- We haven't found a customization document yet. Some
613             -- customizations may have been migrated using the old customization
614             -- directory structure (before the fix for bug 2849379).
615             tmpCustName := getOldCustomizationDocName(baseDoc,
616                                                       lyrTypes(i),
617                                                       lyrValues(i));
618             custDocID := jdr_mds_internal.getDocumentID(tmpcustName,
619                                                         'DOCUMENT');
620             IF ( custDocID <> -1 )
621             THEN
622               custName := tmpCustName;
623             ELSE
624               IF (upper(lyrTypes(i)) = PORTLET)
625               THEN
626                 -- Assuming that the portlet value is <userid>_<referencepath>,
627                 -- try using value <referencepath> in the old customization
628                 -- directory structure
629                 tmpCustName := getOldPortletReference(baseDoc,
630                                                       lyrTypes(i),
631                                                       lyrValues(i),
632                                                       FALSE);
633                 custDocID := jdr_mds_internal.getDocumentID(tmpCustName,
634                                                             'DOCUMENT');
635                 IF ( custDocID <> -1 )
636                 THEN
637                   custName  := tmpCustName;
638                 END IF;
639               END IF;
640             END IF;
641           END IF;
642         END IF;
643         IF NOT custDocID = -1
644         THEN
645           isActive := 'true';  -- by default, all docs are active
646           IF activeOnly
647           THEN
648             BEGIN
649               SELECT  att_value INTO isActive
650                 FROM  jdr_attributes
651                 WHERE att_comp_docid = custDocID AND
652                       att_comp_seq   = 0         AND
653                       att_name = 'MDSActiveDoc';
654             EXCEPTION
655               WHEN NO_DATA_FOUND THEN
656                 isActive := 'true';
657             END;
658           END IF;
659           IF isActive = 'true'
660           THEN
661             IF (cnt <> 1)
662             THEN
663               valid.extend;
664               lvals.extend;
665               docs.extend;
666             END IF;
667             valid(valid.COUNT) := lyrTypes(i);
668             lvals(lvals.COUNT) := lyrValues(i);
669             docs(docs.COUNT) := custName;
670             cnt := cnt + 1;
671           END IF;
672         END IF;
673       END IF;
674       END LOOP;
675     sortLayersWithDocs(valid, lvals, docs);
676     validTypes := valid;
677     custDocs := docs;
678   END;
679 
680 
681   -----------------------------------------------------------------------------
685   PROCEDURE migrateCustomizationsToPage(regionCustDocName   IN VARCHAR2,
682   ---------------------------- PUBLIC FUNCTIONS -------------------------------
683   -----------------------------------------------------------------------------
684 
686                                         extendingRegionName IN VARCHAR2)
687   IS
688     CURSOR c_translations(docID jdr_paths.path_docid%TYPE) IS
689      SELECT  atl_lang, atl_comp_ref, atl_name, atl_value
690      FROM jdr_attributes_trans
691      WHERE atl_comp_docid = docID;
692 
693     CURSOR c_views(docID jdr_paths.path_docid%TYPE) IS
694       SELECT comp_id
695       FROM jdr_components
696       WHERE comp_docid = docID and
697             comp_element = 'view'
698       ORDER BY comp_seq;
699 
700     tranRec            c_translations%ROWTYPE;
701     pageBaseDocName    VARCHAR2(512);
702     pageCustDocName    VARCHAR2(512);
703     pageCustDocID      jdr_paths.path_docid%TYPE;
704     regionBaseDocName  VARCHAR2(512);
705     regionCustDocID    jdr_paths.path_docid%TYPE;
706     regionBaseDocID    jdr_paths.path_docid%TYPE;
707     custType           jdr_components.comp_grouping%TYPE;
708     extendingRegion    jdr_components.comp_id%TYPE;
709     viewID             jdr_components.comp_id%TYPE;
710     pos1               INTEGER;
711     pos2               INTEGER;
712     tempStr            VARCHAR2(1);
713     migrateCusts       BOOLEAN := FALSE;
714   BEGIN
715     -- This will be called when a region has been refactored from inside a
716     -- page to its own document; and when we need the shared customizations on
717     -- the region to be migrated as per instance customizations on the page.
718 
719     -- Create savepoint so we have something to rollback to if an error occurs
720     SAVEPOINT sp;
721     -- Construct the name of the page customization document
722     --
723     -- Suppose the extending region is:
724     --   /oracle/apps/hr/webui/musicpage.extendingRegion
725     -- and the region customization document is:
726     --   /oracle/apps/hr/customizations/site/tower/region
727     -- then the page customization document will be:
728     --  /oracle/apps/hr/customizations/site/tower/webui/musicpage
729     --
730     -- Get the name of the page document and the extending region
731     pos1 := INSTR(extendingRegionName, '.', -1);
732     pageBaseDocName := SUBSTR(extendingRegionName, 1, pos1 - 1);
733     extendingRegion := SUBSTR(extendingRegionName, pos1 + 1);
734 
735     -- Get the "/oracle/apps/hr" portion
736     -- page cust doc -> /oracle/apps/hr
737     pos1 := INSTR(pageBaseDocName, '/', 1, 4);
738     pageCustDocName := SUBSTR(pageBaseDocName, 1, pos1 - 1);
739 
740     -- Add the customizations package
741     -- page cust doc -> /oracle/apps/hr/customizations
742     pageCustDocName := pageCustDocName || '/customizations';
743 
744     -- Add the layer type and layer value
745     -- page cust doc -> /oracle/apps/hr/customizations/site/tower
746     pos1 := INSTR(regionCustDocName, '/customizations');
747     pos1 := INSTR(regionCustDocName, '/', pos1 + 1);
748     pos2 := INSTR(regionCustDocName, '/', pos1 + 1, 2);
749     pageCustDocName := pageCustDocName ||
750                        SUBSTR(regionCustDocName, pos1, pos2 - pos1);
751 
752     -- Add the webui portion and document name
753     -- page cust doc -> /oracle/apps/hr/customizations/site/tower/webui/musicpage
754     pos1 := INSTR(pageBaseDocName, '/', 1, 4);
755     pageCustDocName := pageCustDocName || SUBSTR(pageBaseDocName, pos1);
756 
757     -- Construct the name of the base document of the region.  We need this
758     -- as we will need the children of the region to determine if there are
759     -- any existing customizations on the region from the page customization
760     -- document.
761     pos1 := INSTR(regionCustDocName, '/customizations');
762     pos2 := INSTR(regionCustDocName, '/', pos1 + 1, 3);
763     regionBaseDocName := SUBSTR(regionCustDocName, 1, pos1) ||
764                          SUBSTR(regionCustDocName, pos2 + 1);
765     regionBaseDocID := jdr_mds_internal.getDocumentID(regionBaseDocName, 'DOCUMENT');
766     regionCustDocID := jdr_mds_internal.getDocumentID(regionCustDocName, 'DOCUMENT');
767 
768 
769     -- Check if there are any existing customizations
770     pageCustDocID := jdr_mds_internal.getDocumentID(pageCustDocName, 'DOCUMENT');
771     IF (pageCustDocID > 0) THEN
772       -- The page customization document exists, so we need to check if it
773       -- contains any references to the region
774       BEGIN
775         SELECT 'x' INTO tempStr FROM DUAL WHERE EXISTS (
776           SELECT *
777           FROM jdr_components, jdr_attributes
778           WHERE comp_docid = pageCustDocID AND
779                 att_comp_docid = pageCustDocID AND
780                 att_comp_seq = comp_seq AND
781                 comp_element IN ('view', 'modify', 'move', 'insert', 'criterion') AND
782                 att_name IN ('element', 'before', 'after', 'parent') AND
783                 (
784                   att_value = extendingRegion OR
785                   att_value LIKE extendingRegion||'.%' OR
786                   att_value IN (SELECT comp_id
787                                 FROM jdr_components
788                                 WHERE comp_docid = regionBaseDocID AND
789                                       comp_id IS NOT NULL)
790                 )
791           );
792 
793         -- Since the NO_DATA_FOUND exception did not occur, we know that the
794         -- page customization document already contains customizations on the
795         -- region, so we do NOT want to migrate the customizations.
796         migrateCusts := FALSE;
797       EXCEPTION
798         WHEN NO_DATA_FOUND THEN
799           migrateCusts := TRUE;
800       END;
801     ELSE
802       -- The page customization document does not exist, so we need to migrate
806 
803       -- the customizations
804       migrateCusts := TRUE;
805     END IF;
807     IF (migrateCusts = TRUE) THEN
808       -- Create the customization document if it does not already exist
809       IF (pageCustDocID < 1) THEN
810         DECLARE
811           doc   jdr_docbuilder.document;
812           elem  jdr_docbuilder.element;
813         BEGIN
814           jdr_docbuilder.refresh;
815           doc := jdr_docbuilder.createDocument(pageCustDocName);
816           elem := jdr_docbuilder.createElement(jdr_docbuilder.JRAD_NS, 'customization');
817 
818           jdr_docbuilder.setattribute(elem, 'customizes', pageBaseDocName);
819           jdr_docbuilder.settoplevelelement(doc, elem);
820           IF jdr_docbuilder.save <> jdr_docbuilder.SUCCESS THEN
821             goto error;
822           END IF;
823           pageCustDocID := jdr_mds_internal.getDocumentID(pageCustDocName, 'DOCUMENT');
824         END;
825       END IF;
826 
827 
828       -- Lock the document prior to modifying it
829       jdr_mds_internal.lockDocument(pageCustDocID);
830 
831       -- Customizations views and non-view customizations need to be
832       -- handled differently, since views are a little more complex.
833       -- Determine what type of customization document we are dealing with.
834       SELECT comp_grouping INTO custType
835       FROM jdr_components
836       WHERE comp_docid = regionCustDocID AND
837             comp_seq = 1;
838 
839       IF (custType = 'modifications') THEN
840         appendModifications(pageCustDocID, regionCustDocID, extendingRegion);
841       ELSE
842         -- Since the page customization document may contain views of the same
843         -- name as the region customization document, we need to deal with one
844         -- view at a time.  If the page customization document does not
845         -- contain a view with the same name, we will simply append the view
846         -- to the end of the page document.  If the page does contain a view
847         -- with the same name, then we will append the contents of the view
848         -- of the region to the view of the page.
849         OPEN c_views(regionCustDocID);
850         LOOP
851           FETCH c_views INTO viewID;
852 
853           IF c_views%NOTFOUND THEN
854             CLOSE c_views;
855             EXIT;
856           END IF;
857 
858           -- Add the view to the page customization document
859           appendView(pageCustDocID, regionCustDocID, extendingRegion, viewID);
860         END LOOP;
861       END IF;
862 
863       -- Update the translations
864       OPEN c_translations(regionCustDocID);
865       LOOP
866         FETCH c_translations INTO tranRec;
867 
868         IF c_translations%NOTFOUND THEN
869           CLOSE c_translations;
870           EXIT;
871         END IF;
872 
873         -- Convert the reference appropriately using the following:
874         --   . -> extendingRegion
875         --   :viewID -> :viewID.extendingRegion
876         --   :viewID.child -> :viewID.extendingRegion.child
877         --   child -> extendingRegion.child
878         IF tranRec.atl_comp_ref = '.' THEN
879           tranRec.atl_comp_ref := extendingRegion;
880         ELSIF INSTR(tranRec.atl_comp_ref, ':') <> 1 THEN
881           tranRec.atl_comp_ref := extendingRegion || '.' || tranRec.atl_comp_ref;
882         ELSE
883           pos1 := INSTR(tranRec.atl_comp_ref, '.');
884           IF (pos1 = 0) THEN
885             tranRec.atl_comp_ref := tranRec.atl_comp_ref || '.' || extendingRegion;
886           ELSE
887             tranRec.atl_comp_ref := SUBSTR(tranRec.atl_comp_ref, 1, pos1) ||
888                                     extendingRegion ||
889                                     SUBSTR(tranRec.atl_comp_ref, pos1);
890           END IF;
891         END IF;
892 
893         INSERT INTO jdr_attributes_trans
894           (atl_comp_docid, atl_lang, atl_comp_ref, atl_name, atl_value)
895         VALUES
896           (pageCustDocID,
897            tranRec.atl_lang, tranRec.atl_comp_ref,
898            tranRec.atl_name, tranRec.atl_value);
899       END LOOP;
900     END IF;
901 
902     -- Delete the document and remove any translations
903     jdr_mds_internal.deleteDocument(regionCustDocID, TRUE);
904 
905     DELETE jdr_attributes_trans WHERE atl_comp_docid = regionCustDocID;
906 
907     COMMIT;
908 
909   <<cleanup>>
910     RETURN;
911 
912   <<error>>
913     ROLLBACK TO SAVEPOINT sp;
914     GOTO cleanup;
915 
916   EXCEPTION
917     WHEN OTHERS THEN
918       ROLLBACK TO SAVEPOINT sp;
919   END;
920 
921 
922 
923   PROCEDURE getCustomizationDocs(baseDoc    IN  VARCHAR2,
924                                  custDocs   OUT NOCOPY /* file.sql.39 change */ jdr_stringArray)
925   IS
926     oldRef       VARCHAR2(512);
927     newRef       VARCHAR2(512);
928     currDoc      VARCHAR2(512);
929     currLayer    VARCHAR2(100);
930     pathName     JDR_PATHS.PATH_NAME%TYPE;
931     custIndex    NUMBER;
932     layerIndex   NUMBER;
933     cntDocs      NUMBER  := 1;
934     cntLayers    NUMBER  := 1;
935     layerExists  BOOLEAN := FALSE;
936     getOldRefs   BOOLEAN := TRUE;
937     docs         jdr_stringArray := jdr_stringArray(null);
938     layers       jdr_stringArray := jdr_stringArray(null);
939     CURSOR c(custDocLike VARCHAR2, pathName VARCHAR2) IS
940       SELECT jdr_mds_internal.getDocumentName(path_docid)
941       FROM jdr_paths
942       WHERE path_type = 'DOCUMENT' AND
943             path_name = pathName   AND
944             path_seq  = -1         AND
945             jdr_mds_internal.getDocumentName(path_docid) like custDocLike;
946   BEGIN
950       getOldRefs := FALSE;
947     newRef := getCustomizationDocName(baseDoc, '%', '%');
948     oldRef := getOldCustomizationDocName(baseDoc, '%', '%');
949     IF oldRef IS NULL THEN
951     END IF;
952     IF ( newRef = oldRef ) THEN
953       getOldRefs := FALSE;
954     END IF;
955     -- Get path name of base document
956     pathName := substr(baseDoc, instr(baseDoc, '/', -1) + 1);
957     -- Look for all customization docs using the new reference
958     OPEN c(newRef, pathName);
959     LOOP
960       FETCH c INTO currDoc;
961       IF (c%NOTFOUND) THEN
962         CLOSE c;
963         EXIT;
964       END IF;
965       IF (cntDocs <> 1 ) THEN
966         docs.extend;
967       END IF;
968       docs(docs.COUNT) := currDoc;
969       cntDocs := cntDocs + 1;
970       IF getOldRefs THEN
971       -- Extract the customization layer from the document
972         custIndex := instr(currDoc, '/customizations/');
973         currLayer := substr(currDoc,
974                             custIndex,
975                             instr(currDoc, '/', custIndex, 4) - custIndex);
976         IF ( cntLayers <> 1 ) THEN
977           layers.extend;
978         END IF;
979         layers(layers.COUNT) := currLayer;
980         cntLayers := cntLayers + 1;
981       END IF;
982     END LOOP;
983     IF ( getOldRefs ) THEN
984       -- Look for all customization docs using the old reference;
985       OPEN c(oldRef, pathName);
986       LOOP
987         FETCH c INTO currDoc;
988         IF (c%NOTFOUND) THEN
989           CLOSE c;
990           EXIT;
991         END IF;
992         -- Check whether this customization document is obsolete, i.e. that
993         -- the same document exists under the new reference
994         layerIndex   := layers.FIRST;
995         layerExists := FALSE;
996         WHILE layerIndex IS NOT NULL LOOP
997           IF instr(currDoc, layers(layerIndex)) <> 0 THEN
998             -- This layer already exists
999             layerExists := TRUE;
1000             EXIT;
1001           END IF;
1002           layerIndex := layers.NEXT(layerIndex);
1003         END LOOP;
1004         IF layerExists = FALSE THEN
1005           IF (cntDocs <> 1 ) THEN
1006             docs.extend;
1007           END IF;
1008           docs(docs.COUNT) := currDoc;
1009           cntDocs := cntDocs + 1;
1010         END IF;
1011       END LOOP;
1012     END IF;
1013     custDocs := docs;
1014   END;
1015 
1016   PROCEDURE getActiveLayers(baseDoc   IN  VARCHAR2,
1017                            lyrTypes   IN  jdr_stringArray,
1018                            lyrValues  IN  jdr_stringArray,
1019                            validTypes OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
1020                            custDocs   OUT NOCOPY /* file.sql.39 change */ jdr_stringArray)
1021   IS
1022   BEGIN
1023     getLayers(baseDoc, lyrTypes, lyrValues, validTypes, custDocs, TRUE);
1024   END;
1025 
1026   PROCEDURE getLayers(baseDoc    IN  VARCHAR2,
1027                       lyrTypes   IN  jdr_stringArray,
1028                       lyrValues  IN  jdr_stringArray,
1029                       validTypes OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
1030                       custDocs   OUT NOCOPY /* file.sql.39 change */ jdr_stringArray)
1031   IS
1032   BEGIN
1033     getLayers(baseDoc, lyrTypes, lyrValues, validTypes, custDocs, FALSE);
1034   END;
1035 
1036   --
1037   -- Sorts the layers into precedence order, from lowest to highest
1038   -- Currently using insertion sort.
1039   --
1040   PROCEDURE sortLayers(lyrTypes IN OUT NOCOPY /* file.sql.39 change */ jdr_stringArray)
1041   IS
1042     i NUMBER;
1043     j NUMBER;
1044     currLayer VARCHAR2(50);
1045     currPrecedence NUMBER;
1046     typeArray jdr_stringArray := lyrTypes;
1047   BEGIN
1048     IF typeArray.COUNT > 1
1049     THEN
1050       FOR i IN 2..typeArray.COUNT LOOP
1051         j := i;
1052         currLayer := typeArray(i);
1053         currPrecedence := getPrecedence(currLayer);
1054         WHILE (j > 1) AND
1055              (getPrecedence(typeArray(j-1)) > currPrecedence) LOOP
1056           typeArray(j) := typeArray(j-1);
1057           j := j - 1;
1058         END LOOP;
1059         typeArray(j) := currLayer;
1060       END LOOP;
1061     END IF;
1062     lyrTypes := typeArray;
1063   END;
1064 
1065 END;