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;
378 END IF;
375 IF (upperType = 'RESPONSIBILITY')
376 THEN
377 RETURN(RESPONSIBILITY_LEVEL);
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
402 -- Currently using insertion sort. At the same time, sort customization
403 -- documents to match layer precedence.
404 --
405 PROCEDURE sortLayersWithDocs(lyrTypes IN OUT NOCOPY /* file.sql.39 change */ jdr_stringArray,
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;
511 lenRoot := LENGTH(APPS_ROOTDIR);
508 startDoc VARCHAR2(512);
509 endDoc VARCHAR2(512);
510 BEGIN
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
548 portletRef VARCHAR2(512);
549 newPortletVal VARCHAR2(512);
550 userIdx NUMBER;
551 BEGIN
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
632 FALSE);
629 tmpCustName := getOldPortletReference(baseDoc,
630 lyrTypes(i),
631 lyrValues(i),
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 -----------------------------------------------------------------------------
682 ---------------------------- PUBLIC FUNCTIONS -------------------------------
683 -----------------------------------------------------------------------------
684
685 PROCEDURE migrateCustomizationsToPage(regionCustDocName IN VARCHAR2,
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);
758 -- as we will need the children of the region to determine if there are
755 pageCustDocName := pageCustDocName || SUBSTR(pageBaseDocName, pos1);
756
757 -- Construct the name of the base document of the region. We need this
759 -- any existing customizations on the region from the page customization
760 -- document.
761 pos1 := INSTR(regionCustDocName, '/customizations');
765 regionBaseDocID := jdr_mds_internal.getDocumentID(regionBaseDocName, 'DOCUMENT');
762 pos2 := INSTR(regionCustDocName, '/', pos1 + 1, 3);
763 regionBaseDocName := SUBSTR(regionCustDocName, 1, pos1) ||
764 SUBSTR(regionCustDocName, pos2 + 1);
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
803 -- the customizations
804 migrateCusts := TRUE;
805 END IF;
806
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);
893 INSERT INTO jdr_attributes_trans
890 END IF;
891 END IF;
892
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
947 newRef := getCustomizationDocName(baseDoc, '%', '%');
948 oldRef := getOldCustomizationDocName(baseDoc, '%', '%');
949 IF oldRef IS NULL THEN
950 getOldRefs := FALSE;
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);
1048 IF typeArray.COUNT > 1
1045 currPrecedence NUMBER;
1046 typeArray jdr_stringArray := lyrTypes;
1047 BEGIN
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;