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;