DBA Data[Home] [Help]

PACKAGE BODY: APPS.JDR_DOCBUILDER

Source


1 PACKAGE BODY jdr_docbuilder AS
2 /* $Header: JDRDBEXB.pls 120.3 2005/10/26 06:15:23 akbansal noship $ */
3 
4   -----------------------------------------------------------------------------
5   ---------------------------- PRIVATE TYPES ----------------------------------
6   -----------------------------------------------------------------------------
7   -- Use subtypes for less confusion between external and internal types.
8   SUBTYPE ELEM_ID IS ELEMENT;
9   SUBTYPE DOC_ID  IS DOCUMENT;
10 
11   -- Internal representation of a jrad attribute
12   TYPE ATTRIBUTE IS RECORD ( elemId NUMBER,
13                              name   jdr_attributes.att_name%TYPE,
14                              value  jdr_attributes.att_value%TYPE );
15 
16   -- Internal representation of a jrad grouping
17   TYPE GROUPING IS RECORD ( parentId  NUMBER,
18                             ns        VARCHAR2(5),
19                             tagName   jdr_components.comp_grouping%TYPE,
20                             childId   NUMBER );
21 
22   -- Internal representation of a jrad component
23   TYPE ELEM IS RECORD ( id        NUMBER,
24                         ns        VARCHAR2(5),
25                         tagName   jdr_components.comp_element%TYPE );
26 
27   -- Internal representation of a jrad document
28   TYPE DOC IS RECORD ( id         NUMBER,
29                        fullPath   jdr_components.comp_ref%TYPE,
30                        lang       VARCHAR2(5),
31                        topElemId  NUMBER,
32                        parentId   NUMBER);
33 
34   -- Table of documents
35   TYPE DOC_TABLE IS TABLE OF DOC;
36 
37   -- Table of elements
38   TYPE ELEM_TABLE IS TABLE OF ELEM;
39 
40   -- Table of groupings
41   TYPE GROUPING_TABLE IS TABLE OF GROUPING;
42 
43   -- Table of attributes
44   TYPE ATTRIBUTE_TABLE IS TABLE OF ATTRIBUTE;
45 
46   -- Tables containing a database component's properties in bulk-insert
47   -- compatible format
48   TYPE DB_COMPONENT_L1  IS TABLE OF NUMBER;
49   TYPE DB_COMPONENT_L2  IS TABLE OF jdr_components.comp_seq%TYPE;
50   TYPE DB_COMPONENT_L3  IS TABLE OF jdr_components.comp_level%TYPE;
51   TYPE DB_COMPONENT_L4  IS TABLE OF jdr_components.comp_grouping%TYPE;
52   TYPE DB_COMPONENT_L5  IS TABLE OF jdr_components.comp_element%TYPE;
53   TYPE DB_COMPONENT_L6  IS TABLE OF jdr_components.comp_id%TYPE;
54   TYPE DB_COMPONENT_L7  IS TABLE OF jdr_components.comp_ref%TYPE;
55   TYPE DB_COMPONENT_L8  IS TABLE OF jdr_components.comp_extends%TYPE;
56   TYPE DB_COMPONENT_L9  IS TABLE OF jdr_components.comp_use%TYPE;
57   TYPE DB_COMPONENT_L10 IS TABLE OF jdr_components.comp_comment%TYPE;
58 
59   -- Tables containing a database attribute's properties in bulk-insert
60   -- compatible format
61   TYPE DB_ATTRIBUTE_L1 IS TABLE OF jdr_attributes.att_comp_seq%TYPE;
62   TYPE DB_ATTRIBUTE_L2 IS TABLE OF jdr_attributes.att_seq%TYPE;
63   TYPE DB_ATTRIBUTE_L3 IS TABLE OF jdr_attributes.att_name%TYPE;
64   TYPE DB_ATTRIBUTE_L4 IS TABLE OF jdr_attributes.att_value%TYPE;
65 
66   -----------------------------------------------------------------------------
67   ---------------------------- PRIVATE VARIABLES ------------------------------
68   -----------------------------------------------------------------------------
69 
70   mDocs       DOC_TABLE        := DOC_TABLE();
71   mElems      ELEM_TABLE       := ELEM_TABLE();
72   mGroupings  GROUPING_TABLE   := GROUPING_TABLE();
73   mAttributes ATTRIBUTE_TABLE  := ATTRIBUTE_TABLE();
74 
75   compList1  DB_COMPONENT_L1  := DB_COMPONENT_L1();
76   compList2  DB_COMPONENT_L2  := DB_COMPONENT_L2();
77   compList3  DB_COMPONENT_L3  := DB_COMPONENT_L3();
78   compList4  DB_COMPONENT_L4  := DB_COMPONENT_L4();
79   compList5  DB_COMPONENT_L5  := DB_COMPONENT_L5();
80   compList6  DB_COMPONENT_L6  := DB_COMPONENT_L6();
81   compList7  DB_COMPONENT_L7  := DB_COMPONENT_L7();
82   compList8  DB_COMPONENT_L8  := DB_COMPONENT_L8();
83   compList9  DB_COMPONENT_L9  := DB_COMPONENT_L9();
84   compList10 DB_COMPONENT_L10 := DB_COMPONENT_L10();
85 
86   attList1   DB_ATTRIBUTE_L1  := DB_ATTRIBUTE_L1();
87   attList2   DB_ATTRIBUTE_L2  := DB_ATTRIBUTE_L2();
88   attList3   DB_ATTRIBUTE_L3  := DB_ATTRIBUTE_L3();
89   attList4   DB_ATTRIBUTE_L4  := DB_ATTRIBUTE_L4();
90 
91   JRAD_NS_URI CONSTANT VARCHAR2(30) := 'http://xmlns.oracle.com/jrad';
92   OA_NS_URI   CONSTANT VARCHAR2(30) := 'http://xmlns.oracle.com/oa';
93   UI_NS_URI   CONSTANT VARCHAR2(30) := 'http://xmlns.oracle.com/uix/ui';
94   USER_NS_URI CONSTANT VARCHAR2(30) := 'http://xmlns.oracle.com/user';
95 
96   NULL_GROUPING_NAME CONSTANT VARCHAR2(30) := 'nullgrouping';
97   NULL_GROUPING_NS   CONSTANT VARCHAR2(30) := 'null';
98 
99   -----------------------------------------------------------------------------
100   ---------------------------- PRIVATE FUNCTIONS ------------------------------
101   -----------------------------------------------------------------------------
102 
103   -- Add required attributes to the top-level element in the document.
104   -- This includes namespace, version, and language declarations.
105   --
106   -- Parameters:
107   --   p_doc      -  The document pertaining to the top-level element
108   --   p_comp_num -  The index of the top level element in the compList tables
109   --   p_seq      -  The next sequence number with which to add these attributes
110   --   x_attList  - The list of attributes to which these extra attributes will
111   --               be appended.
112   --
113   PROCEDURE addTopLevelAttributes(p_doc      IN     DOC,
114                                   p_comp_num IN     NUMBER,
115                                   p_seq      IN     PLS_INTEGER)
116   IS
117     seq		PLS_INTEGER := p_seq;
118     l_comp_seq	jdr_components.comp_seq%TYPE := compList2(p_comp_num); --comp_seq
119   BEGIN
120     -- set xmlns
121     attList1.EXTEND;
122     attList2.EXTEND;
123     attList3.EXTEND;
124     attList4.EXTEND;
125     attList1(attList1.LAST) := l_comp_seq;
126     attList2(attList2.LAST) := seq;
127     attList3(attList3.LAST) := 'xmlns';
128     attList4(attList4.LAST) := JRAD_NS_URI;
129     -- set xmlns:jrad
130     attList1.EXTEND;
131     attList2.EXTEND;
132     attList3.EXTEND;
133     attList4.EXTEND;
134     attList1(attList1.LAST) := l_comp_seq;
135     attList2(attList2.LAST) := seq + 1;
136     attList3(attList3.LAST) := 'xmlns:jrad';
137     attList4(attList4.LAST) := JRAD_NS_URI;
138     -- set xmlns:ui
139     attList1.EXTEND;
140     attList2.EXTEND;
141     attList3.EXTEND;
142     attList4.EXTEND;
143     attList1(attList1.LAST) := l_comp_seq;
144     attList2(attList2.LAST) := seq + 2;
145     attList3(attList3.LAST) := 'xmlns:ui';
146     attList4(attList4.LAST) := UI_NS_URI;
147     -- set xmlns:oa
148     attList1.EXTEND;
149     attList2.EXTEND;
150     attList3.EXTEND;
151     attList4.EXTEND;
152     attList1(attList1.LAST) := l_comp_seq;
153     attList2(attList2.LAST) := seq + 3;
154     attList3(attList3.LAST) := 'xmlns:oa';
155     attList4(attList4.LAST) := OA_NS_URI;
156     -- set xmlns:user
157     attList1.EXTEND;
158     attList2.EXTEND;
159     attList3.EXTEND;
160     attList4.EXTEND;
161     attList1(attList1.LAST) := l_comp_seq;
162     attList2(attList2.LAST) := seq + 4;
163     attList3(attList3.LAST) := 'xmlns:user';
164     attList4(attList4.LAST) := USER_NS_URI;
165     -- set version
166     attList1.EXTEND;
167     attList2.EXTEND;
168     attList3.EXTEND;
169     attList4.EXTEND;
170     attList1(attList1.LAST) := l_comp_seq;
171     attList2(attList2.LAST) := seq + 5;
172     attList3(attList3.LAST) := 'version';
173     attList4(attList4.LAST) := '9.0.3.8.0_588';
174     -- set language
175     attList1.EXTEND;
176     attList2.EXTEND;
177     attList3.EXTEND;
178     attList4.EXTEND;
179     attList1(attList1.LAST) := l_comp_seq;
180     attList2(attList2.LAST) := seq + 6;
181     attList3(attList3.LAST) := 'xml:lang';
182     attList4(attList4.LAST) := p_doc.lang;
183   END;
184 
185   -- Build the entire list of attributes for a given document. This list closely
186   -- represents the jdr_attributes table structure in the repository. Some
187   -- special attributes, such as id and extends, will be stored directly on the
188   -- DBComponent itself, rather than as a DBAttribute.
189   --
190   -- Note: This function assumes that the ATTRIBUTE_TABLE mAttributes
191   --       has been sorted by elemId.
192   --
193   -- Parameters:
194   --   p_doc      -  The document corresponding to this list of attributes
195   --
196   -- Returns:
197   --   The list of DBAttributes
198   --
199   PROCEDURE buildAttributeList(p_doc      IN     DOC)
200   IS
201     start_j     PLS_INTEGER := 1;
202     i           PLS_INTEGER;
203     j           PLS_INTEGER;
204     currAtt     ATTRIBUTE;
205     comp_elemId NUMBER;
206     att_elemId  NUMBER;
207     attName     jdr_attributes.att_name%TYPE;
208     seq         PLS_INTEGER;
209     foundElem   BOOLEAN := FALSE;
210   BEGIN
211     IF compList1.COUNT > 0 AND mAttributes.COUNT > 0
212     THEN
213       FOR i IN compList1.FIRST..compList1.LAST LOOP
214         comp_elemId := compList1(i);
215         -- initialize sequence to 0
216         seq := 0;
217         foundElem := FALSE;
218         IF mAttributes.COUNT > 0
219         THEN
220           FOR j IN mAttributes.FIRST..mAttributes.LAST LOOP
221             IF mAttributes.EXISTS(j)
222             THEN
223               currAtt := mAttributes(j);
224               IF comp_elemId = currAtt.elemId
225               THEN
226                 foundElem := TRUE;
227                 -- check if this is a special attribute that
228                 -- belongs in one of the component lists instead
229                 attName := currAtt.name;
230                 IF attName = 'extends'
231                 THEN
232 	     	          compList7(i) := currAtt.value;  --comp_ref
233 		              compList8(i) := 'Y';            --comp_extends
234                 ELSIF attName = 'use'
235                 THEN
236 		              compList9(i) := currAtt.value;  --comp_use
237                 ELSIF attName = 'id'
238                 THEN
239 		              compList6(i) := currAtt.value;  --comp_id
240                 ELSIF attName = 'comment'
241                 THEN
242 		              compList10(i) := currAtt.value; --comp_comment
243                 ELSE
244              	    -- Otherwise, add this attribute to the attribute tables
245   		            attList1.EXTEND;
246           		    attList2.EXTEND;
247 		              attList3.EXTEND;
248 		              attList4.EXTEND;
249 		              attList1(attList1.LAST) := compList2(i); --comp_seq
250 		              attList2(attList2.LAST) := seq;
251 		              attList3(attList3.LAST) := currAtt.name;
252 		              attList4(attList4.LAST) := currAtt.value;
253 		              seq := seq + 1;
254                 END IF;
255 	              mAttributes.DELETE(j);
256               ELSIF foundElem = TRUE
257               THEN
258                 EXIT;
259               END IF;
260             END IF;
261           END LOOP;
262         END IF;
263         -- find out if this is the top-level element, check comp_seq and comp_level
264         IF ( compList2(i) = 0 ) AND
265            ( compList3(i) = 0 )
266         THEN
267           -- Check if this is a top-level document, or a child document
268           IF p_doc.parentId = -1
269           THEN
270             addTopLevelAttributes(p_doc, i, seq);
271           END IF;
272         END IF;
273       END LOOP;
274     END IF;
275   END;
276 
277 
278   -- Build the entire list of components, starting with a given element and
279   -- recursing through all its children. This list closely represents the
280   -- jdr_components table structure in the repository.
281   --
282   -- Note: This is a recursive procedure, which assumes that the ELEMENT_TABLE
283   --       mElems has been sorted by elemId and grouping.
284   --
285   -- Parameters:
286   --   p_elem      - The top-level element node
287   --   p_grouping  - The grouping which p_elem belongs to. If p_elem is the
288   --                 top-level component in the document, this will be NULL.
289   --   p_initLevel - The level of p_elem in the document
290   --   p_loopStart - The initial index from which to begin iterating through
291   --                 the groupings table
292   --   p_initSeq   - The sequence number of p_elem in the document
293   --
294   PROCEDURE buildComponentList(p_elem       IN     ELEM,
295                                p_grouping   IN     GROUPING,
296                                p_initLevel  IN     PLS_INTEGER,
297 			                         p_loopStart  IN	   PLS_INTEGER,
298                                x_initSeq    IN OUT NOCOPY /* file.sql.39 change */ PLS_INTEGER)
299   IS
300     i              PLS_INTEGER;
301     childElem      ELEM;
302     currGrouping   GROUPING;
303     lastGrouping   GROUPING;
304     currParentId   NUMBER;
305     seq            PLS_INTEGER := x_initSeq;
306     lev            PLS_INTEGER := p_initLevel;
307     foundParent    BOOLEAN := FALSE;
308     foundChild     BOOLEAN := FALSE;
309     l_loopStart    PLS_INTEGER;
310     childLoopStart PLS_INTEGER;
311     currLevel      PLS_INTEGER;
312   BEGIN
313     -- Extend all of the component lists for the new component
314     compList1.EXTEND;
315     compList2.EXTEND;
316     compList3.EXTEND;
317     compList4.EXTEND;
318     compList5.EXTEND;
319     compList6.EXTEND;
320     compList7.EXTEND;
321     compList8.EXTEND;
322     compList9.EXTEND;
323     compList10.EXTEND;
324 
325     -- Fill in component properties that we know
326     compList1(compList1.LAST) := p_elem.id;
327     compList2(compList2.LAST) := seq;
328     compList3(compList3.LAST) := lev;
329     -- Add the grouping if appropriate
330     IF NOT p_grouping.ns IS NULL
334       -- default namespace
331        AND NOT p_grouping.ns = NULL_GROUPING_NS
332     THEN
333      -- #(3654464) No need to specify the JRAD namespace since it's the
335       IF (p_grouping.ns = JRAD_NS) THEN
336         compList4(compList4.LAST) := p_grouping.tagName;
337       ELSE
338         compList4(compList4.LAST) := p_grouping.ns || p_grouping.tagName;
339       END IF;
340     END IF;
341 
342     -- #(3654464) No need to specify the JRAD namespace since it's the
343     -- default namespace
344     IF (p_elem.ns = JRAD_NS) THEN
345       compList5(compList5.LAST) := p_elem.tagName;
346     ELSE
347       compList5(compList5.LAST) := p_elem.ns || p_elem.tagName;
348     END IF;
349 
350     -- Increment seq value
351     seq := seq + 1;
352 
353     -- Find all groupings where parentId = p_elem
354     IF mGroupings.COUNT > 0
355     THEN
356       IF mGroupings.EXISTS(p_loopStart) THEN
357         l_loopStart := p_loopStart;
358       ELSE
359         l_loopStart := mGroupings.FIRST;
360       END IF;
361       FOR i IN l_loopStart..mGroupings.LAST LOOP
362         IF mGroupings.EXISTS(i)
363         THEN
364           currGrouping := mGroupings(i);
365           currParentId := currGrouping.parentId;
366           IF currParentId = p_elem.id
367           THEN
368             foundParent := TRUE;
369             childElem := mElems(currGrouping.childId);
370             -- determine if this is a new grouping. If so, set foundChild to
371             -- false, so we know to save the grouping on the dbcomponent
372             IF (lastGrouping.ns IS NULL) OR
373                (lastGrouping.ns <> currGrouping.ns) OR
374                (lastGrouping.tagName <> currGrouping.tagName)
375             THEN
376               foundChild := FALSE;
377             END IF;
378 	          --see if we can cheat on the recursive iteration
379 	          IF currParentId < childElem.id THEN
380 	            childLoopStart := i + 1;
381 	          ELSE
382 	            childLoopStart := 0;
383 	          END IF;
384             lastGrouping := currGrouping;
385             IF currGrouping.ns = NULL_GROUPING_NS
386             THEN
387               currLevel := lev + 1;
388             ELSE
389               currLevel := lev + 2;
390             END IF;
391             IF NOT foundChild
392             THEN
393               foundChild := TRUE;
394             ELSE
395               currGrouping := NULL;
396             END IF;
397             buildComponentList(childElem, currGrouping, currLevel, childLoopStart, seq);
398 	          mGroupings.DELETE(i);
399           ELSIF foundParent = TRUE
400           THEN
401             EXIT; -- we've passed all groupings for the parent id
402           END IF;
403         END IF;
404       END LOOP;
405     END IF;
406     x_initSeq := seq;
407   END;
408 
409 
410   -- Compares 2 different attributes, a and b. Returns true if a > b. Otherwise,
411   -- returns false.
412   --
413   -- These attributes are compared based on the elemId. A larger elemId value
414   -- gives an attribute more weight than the other.
415   --
416   -- Parameters:
417   --   a  -  The first attribute being compared
418   --   b  -  The second attribute being compared
419   --
420   -- Returns:
421   --   True, if a > b. False otherwise.
422   --
423   FUNCTION compareAttributes(a ATTRIBUTE,
424                              b ATTRIBUTE) RETURN BOOLEAN
425   IS
426   BEGIN
427     IF a.elemId > b.elemId
428     THEN
429       RETURN (TRUE);
430     END IF;
431     RETURN (FALSE);
432   END;
433 
434 
435   -- Compares 2 different groupings, a and b. Returns true if a > b. Otherwise,
436   -- returns false.
437   --
438   -- These groupings are compared based on the parentId, namespace, and tagName.
439   -- A larger parentId value gives a grouping more weight than the other. If the
440   -- parentId is the same, the namespace is compared based on its internal
441   -- numeric value. If this is also equivalent, then the tagName is compared,
442   -- also based on its internal numeric value.
443   --
444   -- Parameters:
445   --   a  -  The first grouping being compared
446   --   b  -  The second grouping being compared
447   --
448   -- Returns:
449   --   True, if a > b. False otherwise.
450   --
451   FUNCTION compareGroupings(a GROUPING,
452                             b GROUPING) RETURN BOOLEAN
453   IS
454   BEGIN
455     IF a.parentId > b.parentId
456     THEN
457       RETURN (TRUE);
458     ELSIF a.parentId < b.parentId
459     THEN
460       RETURN (FALSE);
461     END IF;
462     -- parentId's are equal
463     IF a.ns > b.ns
464     THEN
465       RETURN (TRUE);
466     ELSIF a.ns < b.ns
467     THEN
468       RETURN (FALSE);
469     END IF;
470     -- namespaces are equal
471     IF a.tagName > b.tagName
472     THEN
473       RETURN (TRUE);
474     ELSIF a.tagName < b.tagName
475     THEN
476       RETURN (FALSE);
477     END IF;
478     -- The groupings belong to the same parent, with the same
479     -- namespace and tagName
480     RETURN (FALSE);
481   END;
485     p_fullPathName VARCHAR2,
482 
483   -- Create a document object
484   FUNCTION createDocument(
486     p_language     VARCHAR2,
487     p_parentId     NUMBER) RETURN DOCUMENT
488   IS
489   newDoc   DOC;
490   d_id     DOC_ID;
491   BEGIN
492     mDocs.EXTEND;
493     newDoc.id        := mDocs.LAST;
494     newDoc.fullPath  := p_fullPathName;
495     newDoc.lang      := p_language;
496     newDoc.parentId  := p_parentId;
497     mDocs(newDoc.id) := newDoc;
498     d_id.id          := newDoc.id;
499     RETURN (d_id);
500   END;
501 
502 
503   -- Bulk Insert the data in the attList tables into the repository
504   --
505   -- Parameters:
506   --   p_docid   -  The document to which these attributes belong to
507   --
508   PROCEDURE insertAttributes(p_docid NUMBER)
509   IS
510     i PLS_INTEGER;
511   BEGIN
512      FORALL i in attList1.FIRST..attList1.LAST
513 	INSERT INTO jdr_attributes
514 	   (ATT_COMP_DOCID, ATT_COMP_SEQ, ATT_SEQ, ATT_NAME, ATT_VALUE)
515 	VALUES
516 	   (p_docid, attList1(i), attList2(i), attList3(i),attList4(i));
517   END;
518 
519 
520   -- Bulk Insert the data in the compList tables into the repository
521   --
522   -- Parameters:
523   --   p_docid   -  The document to which these components belong to
524   --
525   PROCEDURE insertComponents(p_docid NUMBER)
526   IS
527     i PLS_INTEGER;
528  BEGIN
529     FORALL i in compList1.FIRST..compList1.LAST
530        INSERT INTO jdr_components
531 	  (COMP_DOCID, COMP_SEQ , COMP_LEVEL, COMP_GROUPING, COMP_ELEMENT,
532 	   COMP_ID, COMP_REF, COMP_EXTENDS, COMP_USE, COMP_COMMENT)
533        VALUES
534 	  (p_docid, compList2(i), compList3(i), compList4(i), compList5(i),
535 	   compList6(i), compList7(i), compList8(i), compList9(i), compList10(i));
536   END;
537 
538 
539   -- Sort the attributes in the attributes table from lowest to highest elemId.
540   -- This procedure uses the compareAttributes() method to analyze the
541   -- attributes. This is an implementation of insertion-sort.
542   --
543   PROCEDURE sortAttributesTable
544   IS
545     i NUMBER;
546     j NUMBER;
547     currAttribute ATTRIBUTE;
548     attTable      ATTRIBUTE_TABLE := mAttributes;
549   BEGIN
550     IF attTable.COUNT > 1
551     THEN
552       FOR i IN 2..attTable.COUNT LOOP
553         j := i;
554         currAttribute := attTable(i);
555         WHILE (j > 1) AND
556              (compareAttributes(attTable(j-1), currAttribute)) LOOP
557           attTable(j) := attTable(j-1);
558           j := j - 1;
559         END LOOP;
560         attTable(j) := currAttribute;
561       END LOOP;
562     END IF;
563     mAttributes := attTable;
564   END;
565 
566 
567   -- Sort the groupings in the groupings table in the following order:
568   -- 1) From lowest to highest parentId.
569   -- 2) By grouping namespace, in alphabetical order
570   -- 3) By grouping tagName, in alphabetical order
571   --
572   -- This procedure uses the compareGroupings() method to analyze the
573   -- groupings. This is an implementation of insertion-sort.
574   --
575   PROCEDURE sortGroupingsTable
576   IS
577     i NUMBER;
578     j NUMBER;
579     currGrouping GROUPING;
580     groupTable   GROUPING_TABLE := mGroupings;
581   BEGIN
582     IF groupTable.COUNT > 1
583     THEN
584       FOR i IN 2..groupTable.COUNT LOOP
585         j := i;
586         currGrouping := groupTable(i);
587         WHILE (j > 1) AND
588              (compareGroupings(groupTable(j-1), currGrouping)) LOOP
589           groupTable(j) := groupTable(j-1);
590           j := j - 1;
591         END LOOP;
592         groupTable(j) := currGrouping;
593       END LOOP;
594     END IF;
595     mGroupings := groupTable;
596   END;
597 
598   -----------------------------------------------------------------------------
599   ---------------------------- PUBLIC FUNCTIONS -------------------------------
600   -----------------------------------------------------------------------------
601 
602 
603   PROCEDURE addChild(
604       p_parent            ELEMENT,
605       p_groupingNS        VARCHAR2,
606       p_groupingTagName   VARCHAR2,
607       p_child             ELEMENT)
608   IS
609     currGrouping GROUPING;
610   BEGIN
611     IF p_groupingNS = JRAD_NS OR
612        p_groupingNS = OA_NS   OR
613        p_groupingNS = UI_NS   OR
614        p_groupingNS = USER_NS OR
615        p_groupingNS = NULL_GROUPING_NS
616     THEN
617       currGrouping.parentId := p_parent.id;
618       currGrouping.childId  := p_child.id;
619       currGrouping.tagName  := p_groupingTagName;
620       currGrouping.ns       := p_groupingNS;
621       mGroupings.EXTEND;
622       mGroupings(mGroupings.LAST) := currGrouping;
623     ELSE
624       RAISE INVALID_NAMESPACE;
625     END IF;
626   END;
627 
628 
629   PROCEDURE addChild(
630       p_parent            ELEMENT,
631       p_child             ELEMENT)
632   IS
633   BEGIN
634     addChild(p_parent, NULL_GROUPING_NS, NULL_GROUPING_NAME, p_child);
635   END;
636 
637 
638   FUNCTION createChildDocument(
642   pkgName   jdr_components.comp_ref%TYPE;
639     p_fullPathName VARCHAR2) RETURN DOCUMENT
640   IS
641   pkgDocId  NUMBER;
643   BEGIN
644     -- Determine whether the package file exists in the repository
645     pkgName := substr(p_fullPathName,
646                       1,
647                       instr(p_fullPathName, '/', -1, 1) - 1);
648     BEGIN
649       SELECT path_docid INTO pkgDocId
650         FROM jdr_paths
651         WHERE jdr_mds_internal.getDocumentName(path_docid) = pkgName AND
652               path_type = 'PACKAGE' AND
653               path_seq  = 0;
654     EXCEPTION
655       -- No package file exists in the repository.
656       WHEN NO_DATA_FOUND THEN
657         RAISE REF_NOT_FOUND;
658     END;
659     RETURN createDocument(p_fullPathName, NULL, pkgDocId);
660   END;
661 
662 
663   FUNCTION createDocument(
664     p_fullPathName VARCHAR2,
665     p_language     VARCHAR2) RETURN DOCUMENT
666   IS
667   BEGIN
668     RETURN createDocument(p_fullPathName, p_language, -1);
669   END;
670 
671 
672   FUNCTION createElement(
673     p_namespace VARCHAR2,
674     p_tagName   VARCHAR2) RETURN ELEMENT
675   IS
676   newElem ELEM;
677   e_id ELEM_ID;
678   BEGIN
679     IF p_namespace = JRAD_NS OR
680        p_namespace = OA_NS   OR
681        p_namespace = UI_NS   OR
682        p_namespace = USER_NS
683     THEN
684       mElems.EXTEND;
685       newElem.id      := mElems.LAST;
686       newElem.tagName := p_tagName;
687       newElem.ns      := p_namespace;
688       mElems(newElem.id) := newElem;
689       e_id.id := newElem.id;
690     ELSE
691      RAISE INVALID_NAMESPACE;
692     END IF;
693     RETURN(e_id);
694   END;
695 
696 
697   PROCEDURE deleteDocument(
698       p_fullPathName VARCHAR2)
699   IS
700     docid    NUMBER;
701     pathType jdr_paths.path_type%TYPE;
702   BEGIN
703     docid := jdr_mds_internal.getDocumentID(p_fullPathName);
704     IF docid = -1
705     THEN
706       RAISE REF_NOT_FOUND;
707     ELSE
708       SELECT path_type INTO pathType
709         FROM jdr_paths
710         WHERE path_docid = docid;
711       IF pathType = 'DOCUMENT'
712       THEN
713         jdr_mds_internal.dropDocument(docid);
714       ELSE
715         RAISE NOT_DOCUMENT_REF;
716       END IF;
717     END IF;
718   END;
719 
720 
721   FUNCTION documentExists(
722       p_fullPathName VARCHAR2) RETURN BOOLEAN
723   IS
724      docid    NUMBER;
725   BEGIN
726     docid := jdr_mds_internal.getDocumentID(p_fullPathName, 'DOCUMENT');
727     IF docid = -1
728     THEN
729       RETURN(FALSE);
730     ELSE
731       RETURN(TRUE);
732     END IF;
733   END;
734 
735 
736   PROCEDURE refresh
737   IS
738   BEGIN
742     mGroupings  := GROUPING_TABLE();
739     -- re-initialize all member variables
740     mDocs       := DOC_TABLE();
741     mElems      := ELEM_TABLE();
743     mAttributes := ATTRIBUTE_TABLE();
744   END;
745 
746 
747   FUNCTION save RETURN PLS_INTEGER
748   IS
749     docid       PLS_INTEGER;
750     db_docid    NUMBER;
751     currDoc     DOC;
752     topElem     ELEM;
753     seq         PLS_INTEGER := 0;
754     docSeq      jdr_paths.path_seq%TYPE;
755     docName     jdr_paths.path_name%TYPE;
756     isDuplicate BOOLEAN;
757   BEGIN
758     -- Sort the tables such that components, attributes can be found more easily
759     sortAttributesTable();
760     sortGroupingsTable();
761 
762     FOR docid IN mDocs.FIRST..mDocs.LAST LOOP
763       IF mDocs.EXISTS(docid) THEN
764    	    currDoc := mDocs(docid);
765 	      -- Retrieve the top-level element
766 	      topElem   := mElems(currDoc.topElemId);
767         -- Clear the component list tables
768 	      compList1.DELETE;
769 	      compList2.DELETE;
770 	      compList3.DELETE;
771 	      compList4.DELETE;
772 	      compList5.DELETE;
773 	      compList6.DELETE;
774 	      compList7.DELETE;
775 	      compList8.DELETE;
776 	      compList9.DELETE;
777 	      compList10.DELETE;
778         -- Build the component list for this document
779 	      buildComponentList(topElem, NULL, 0, 1, seq);
780      	  -- Clear the attribute list tables
781         attList1.DELETE;
782 	      attList2.DELETE;
783 	      attList3.DELETE;
784 	      attList4.DELETE;
785 	      -- Build the attribute list for this document
786 	      buildAttributeList(currDoc);
787         -- Prepare to insert document.
788         IF currDoc.parentId = -1
789         THEN
790       	  db_docid := jdr_mds_internal.prepareDocumentForInsert('INTERNAL',
791 	  			 		                                                currDoc.fullPath,
792 		  					                                              'DOCUMENT',
793 			  				                                              '1.0',
794 				  			                                              'UTF-8');
795         ELSE
796           -- This is a child document. Lock the package file document
797           jdr_mds_internal.lockDocument(currDoc.parentId);
798           -- Determine whether the document already exists in the repository
799           docName := substr(currDoc.fullPath,
800                             instr(currDoc.fullPath, '/', -1, 1) + 1);
801           BEGIN
802             SELECT path_seq INTO docSeq
803               FROM jdr_paths
804               WHERE path_name = docName AND
805                     path_owner_docid = currDoc.parentId;
806             isDuplicate := TRUE;
807           EXCEPTION
808             -- The document is unique
809             WHEN NO_DATA_FOUND THEN
810               SELECT max(path_seq) INTO docSeq
811                 FROM jdr_paths
812                 WHERE path_owner_docid = currDoc.parentId;
813               docSeq := docSeq + 1;
814               isDuplicate := FALSE;
815           END;
816           db_docid := jdr_mds_internal.prepareDocumentForInsert('INTERNAL',
817                                                                docName,
818                                                                currDoc.parentId,
819                                                                docSeq,
820                                                                'DOCUMENT');
821           IF isDuplicate
822           THEN
823             -- Delete from jdr_attribute and jdr_components table
824             DELETE jdr_attributes WHERE att_comp_docid = db_docid;
825             DELETE jdr_components WHERE comp_docid = db_docid;
826           END IF;
827         END IF;
828 	      -- Bulk Insert the components/attributes
829 	      insertComponents(db_docid);
830 	      insertAttributes(db_docid);
831       END IF;
832       seq := 0;
833     END LOOP;
834     refresh();
835     RETURN(SUCCESS);
836   END;
837 
838 
839   PROCEDURE setAttribute(
840     p_elem       ELEMENT,
841     p_attName    VARCHAR2,
842     p_attValue   VARCHAR2)
843   IS
844     newAtt ATTRIBUTE;
845   BEGIN
846     newAtt.name   := p_attName;
847     newAtt.value  := p_attValue;
848     newAtt.elemId := p_elem.id;
849     mAttributes.EXTEND;
850     mAttributes(mAttributes.LAST) := newAtt;
851   END;
852 
853 
854   PROCEDURE setTopLevelElement(
855     p_doc      DOCUMENT,
856     p_elem     ELEMENT)
857   IS
858     docid   PLS_INTEGER;
859     currDoc DOC;
860   BEGIN
861     docid   := p_doc.id;
862     currDoc := mDocs(docid);
863     currDoc.topElemId := p_elem.id;
864     mDocs(docid) := currDoc;
865   END;
866 
867 END;