KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > dom > DeferredDocumentImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.dom;
59
60 import org.w3c.dom.Element JavaDoc;
61 import org.w3c.dom.Node JavaDoc;
62 import org.w3c.dom.TypeInfo JavaDoc;
63
64 import java.util.Vector JavaDoc;
65
66 /**
67  * The Document interface represents the entire HTML or XML document.
68  * Conceptually, it is the root of the document tree, and provides the
69  * primary access to the document's data.
70  * <P>
71  * Since elements, text nodes, comments, processing instructions,
72  * etc. cannot exist outside the context of a Document, the Document
73  * interface also contains the factory methods needed to create these
74  * objects. The Node objects created have a ownerDocument attribute
75  * which associates them with the Document within whose context they
76  * were created.
77  *
78 <<<<<<< DeferredDocumentImpl.java
79  * @version $Id: DeferredDocumentImpl.java,v 1.3 2003/11/18 00:22:50 kk122374 Exp $
80 =======
81  * @version $Id: DeferredDocumentImpl.java,v 1.3 2003/11/18 00:22:50 kk122374 Exp $
82 >>>>>>> 1.1.1.2
83  * @since PR-DOM-Level-1-19980818.
84  */

85 public class DeferredDocumentImpl
86     extends DocumentImpl
87     implements DeferredNode {
88
89     //
90
// Constants
91
//
92

93     /** Serialization version. */
94     static final long serialVersionUID = 5186323580749626857L;
95
96     // debugging
97

98     /** To include code for printing the ref count tables. */
99     private static final boolean DEBUG_PRINT_REF_COUNTS = false;
100
101     /** To include code for printing the internal tables. */
102     private static final boolean DEBUG_PRINT_TABLES = false;
103
104     /** To debug identifiers set to true and recompile. */
105     private static final boolean DEBUG_IDS = false;
106
107     // protected
108

109     /** Chunk shift. */
110     protected static final int CHUNK_SHIFT = 11; // 2^11 = 2k
111

112     /** Chunk size. */
113     protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
114
115     /** Chunk mask. */
116     protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
117
118     /** Initial chunk size. */
119     protected static final int INITIAL_CHUNK_COUNT = (1 << (16 - CHUNK_SHIFT)); // 2^16 = 64k
120

121     //
122
// Data
123
//
124

125     // lazy-eval information
126
// To maximize memory consumption the actual semantic of these fields vary
127
// depending on the node type.
128

129     /** Node count. */
130     protected transient int fNodeCount = 0;
131
132     /** Node types. */
133     protected transient int fNodeType[][];
134
135     /** Node names. */
136     protected transient Object JavaDoc fNodeName[][];
137
138     /** Node values. */
139     protected transient Object JavaDoc fNodeValue[][];
140
141     /** Node parents. */
142     protected transient int fNodeParent[][];
143
144     /** Node first children. */
145     protected transient int fNodeLastChild[][];
146
147     /** Node prev siblings. */
148     protected transient int fNodePrevSib[][];
149
150     /** Node namespace URI. */
151     protected transient Object JavaDoc fNodeURI[][];
152
153     /** Extra data. */
154     protected transient int fNodeExtra[][];
155
156     /** Identifier count. */
157     protected transient int fIdCount;
158
159     /** Identifier name indexes. */
160     protected transient String JavaDoc fIdName[];
161
162     /** Identifier element indexes. */
163     protected transient int fIdElement[];
164
165     /** DOM2: For namespace support in the deferred case.
166      */

167     // Implementation Note: The deferred element and attribute must know how to
168
// interpret the int representing the qname.
169
protected boolean fNamespacesEnabled = false;
170     
171     //
172
// private data
173
//
174
private transient final StringBuffer JavaDoc fBufferStr = new StringBuffer JavaDoc();
175     private transient final Vector JavaDoc fStrChunks = new Vector JavaDoc();
176
177     //
178
// Constructors
179
//
180

181     /**
182      * NON-DOM: Actually creating a Document is outside the DOM's spec,
183      * since it has to operate in terms of a particular implementation.
184      */

185     public DeferredDocumentImpl() {
186         this(false);
187     } // <init>()
188

189     /**
190      * NON-DOM: Actually creating a Document is outside the DOM's spec,
191      * since it has to operate in terms of a particular implementation.
192      */

193     public DeferredDocumentImpl(boolean namespacesEnabled) {
194         this(namespacesEnabled, false);
195     } // <init>(boolean)
196

197     /** Experimental constructor. */
198     public DeferredDocumentImpl(boolean namespaces, boolean grammarAccess) {
199         super(grammarAccess);
200
201         needsSyncData(true);
202         needsSyncChildren(true);
203
204         fNamespacesEnabled = namespaces;
205
206     } // <init>(boolean,boolean)
207

208     //
209
// Public methods
210
//
211

212     /** Returns the cached parser.getNamespaces() value.*/
213     boolean getNamespacesEnabled() {
214         return fNamespacesEnabled;
215     }
216
217     void setNamespacesEnabled(boolean enable) {
218         fNamespacesEnabled = enable;
219     }
220
221     // internal factory methods
222

223     /** Creates a document node in the table. */
224     public int createDeferredDocument() {
225         int nodeIndex = createNode(Node.DOCUMENT_NODE);
226         return nodeIndex;
227     }
228
229     /** Creates a doctype. */
230     public int createDeferredDocumentType(String JavaDoc rootElementName,
231                                           String JavaDoc publicId, String JavaDoc systemId) {
232
233         // create node
234
int nodeIndex = createNode(Node.DOCUMENT_TYPE_NODE);
235         int chunk = nodeIndex >> CHUNK_SHIFT;
236         int index = nodeIndex & CHUNK_MASK;
237
238         // save name, public id, system id
239
setChunkValue(fNodeName, rootElementName, chunk, index);
240         setChunkValue(fNodeValue, publicId, chunk, index);
241         setChunkValue(fNodeURI, systemId, chunk, index);
242
243         // return node index
244
return nodeIndex;
245
246     } // createDeferredDocumentType(String,String,String):int
247

248     public void setInternalSubset(int doctypeIndex, String JavaDoc subset) {
249         int chunk = doctypeIndex >> CHUNK_SHIFT;
250         int index = doctypeIndex & CHUNK_MASK;
251
252         // create extra data node to store internal subset
253
int extraDataIndex = createNode(Node.DOCUMENT_TYPE_NODE);
254         int echunk = extraDataIndex >> CHUNK_SHIFT;
255         int eindex = extraDataIndex & CHUNK_MASK;
256         setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
257         setChunkValue(fNodeValue, subset, echunk, eindex);
258     }
259
260     /** Creates a notation in the table. */
261     public int createDeferredNotation(String JavaDoc notationName,
262                                       String JavaDoc publicId, String JavaDoc systemId, String JavaDoc baseURI) {
263
264         // create node
265
int nodeIndex = createNode(Node.NOTATION_NODE);
266         int chunk = nodeIndex >> CHUNK_SHIFT;
267         int index = nodeIndex & CHUNK_MASK;
268
269
270         // create extra data node
271
int extraDataIndex = createNode(Node.NOTATION_NODE);
272         int echunk = extraDataIndex >> CHUNK_SHIFT;
273         int eindex = extraDataIndex & CHUNK_MASK;
274
275         // save name, public id, system id, and notation name
276
setChunkValue(fNodeName, notationName, chunk, index);
277         setChunkValue(fNodeValue, publicId, chunk, index);
278         setChunkValue(fNodeURI, systemId, chunk, index);
279
280         // in extra data node set baseURI value
281
setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
282         setChunkValue(fNodeName, baseURI, echunk, eindex);
283
284         // return node index
285
return nodeIndex;
286
287     } // createDeferredNotation(String,String,String):int
288

289     /** Creates an entity in the table. */
290     public int createDeferredEntity(String JavaDoc entityName, String JavaDoc publicId,
291                                     String JavaDoc systemId, String JavaDoc notationName,
292                                     String JavaDoc baseURI) {
293         // create node
294
int nodeIndex = createNode(Node.ENTITY_NODE);
295         int chunk = nodeIndex >> CHUNK_SHIFT;
296         int index = nodeIndex & CHUNK_MASK;
297
298         // create extra data node
299
int extraDataIndex = createNode(Node.ENTITY_NODE);
300         int echunk = extraDataIndex >> CHUNK_SHIFT;
301         int eindex = extraDataIndex & CHUNK_MASK;
302
303         // save name, public id, system id, and notation name
304
setChunkValue(fNodeName, entityName, chunk, index);
305         setChunkValue(fNodeValue, publicId, chunk, index);
306         setChunkValue(fNodeURI, systemId, chunk, index);
307         setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
308         // set other values in the extra chunk
309
// notation
310
setChunkValue(fNodeName, notationName, echunk, eindex);
311         // version L3
312
setChunkValue(fNodeValue, null, echunk, eindex);
313         // encoding L3
314
setChunkValue(fNodeURI, null, echunk, eindex);
315
316
317         int extraDataIndex2 = createNode(Node.ENTITY_NODE);
318         int echunk2 = extraDataIndex2 >> CHUNK_SHIFT;
319         int eindex2 = extraDataIndex2 & CHUNK_MASK;
320
321         setChunkIndex(fNodeExtra, extraDataIndex2, echunk, eindex);
322
323         // baseURI
324
setChunkValue(fNodeName, baseURI, echunk2, eindex2);
325
326         // return node index
327
return nodeIndex;
328
329     } // createDeferredEntity(String,String,String,String):int
330

331     public String JavaDoc getDeferredEntityBaseURI (int entityIndex){
332         if (entityIndex != -1) {
333             int extraDataIndex = getNodeExtra(entityIndex, false);
334             extraDataIndex = getNodeExtra(extraDataIndex, false);
335             return getNodeName (extraDataIndex, false);
336         }
337         return null;
338     }
339
340     // DOM Level 3: setting encoding and version
341
public void setEntityInfo(int currentEntityDecl,
342                               String JavaDoc version, String JavaDoc encoding){
343         int eNodeIndex = getNodeExtra(currentEntityDecl, false);
344         if (eNodeIndex !=-1) {
345             int echunk = eNodeIndex >> CHUNK_SHIFT;
346             int eindex = eNodeIndex & CHUNK_MASK;
347             setChunkValue(fNodeValue, version, echunk, eindex);
348             setChunkValue(fNodeURI, encoding, echunk, eindex);
349         }
350     }
351
352
353     /**
354      * DOM Internal
355      *
356      * An attribute specifying the actual encoding of this document. This is
357      * <code>null</code> otherwise.
358      * <br> This attribute represents the property [character encoding scheme]
359      * defined in .
360      */

361     public void setInputEncoding(int currentEntityDecl, String JavaDoc value){
362         // get first extra data chunk
363
int nodeIndex = getNodeExtra(currentEntityDecl, false);
364         // get second extra data chunk
365
int extraDataIndex = getNodeExtra(nodeIndex, false);
366
367         int echunk = extraDataIndex >> CHUNK_SHIFT;
368         int eindex = extraDataIndex & CHUNK_MASK;
369         
370         setChunkValue(fNodeValue, value, echunk, eindex);
371         
372     }
373
374     /** Creates an entity reference node in the table. */
375     public int createDeferredEntityReference(String JavaDoc name, String JavaDoc baseURI) {
376
377         // create node
378
int nodeIndex = createNode(Node.ENTITY_REFERENCE_NODE);
379         int chunk = nodeIndex >> CHUNK_SHIFT;
380         int index = nodeIndex & CHUNK_MASK;
381         setChunkValue(fNodeName, name, chunk, index);
382         setChunkValue(fNodeValue, baseURI, chunk, index);
383
384         // return node index
385
return nodeIndex;
386
387     } // createDeferredEntityReference(String):int
388

389
390     /** Creates an element node with a URI in the table and type information. */
391     public int createDeferredElement(String JavaDoc elementURI, String JavaDoc elementName,
392                                       TypeInfo JavaDoc type) {
393
394         // create node
395
int elementNodeIndex = createNode(Node.ELEMENT_NODE);
396         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
397         int elementIndex = elementNodeIndex & CHUNK_MASK;
398         setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
399         setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
400         setChunkValue(fNodeValue, type, elementChunk, elementIndex);
401  
402         // return node index
403
return elementNodeIndex;
404
405     } // createDeferredElement(String,String):int
406

407     /** @deprecated. Creates an element node in the table. */
408     public int createDeferredElement(String JavaDoc elementName) {
409         return createDeferredElement(null, elementName);
410     }
411
412     /** @deprecated. Creates an element node with a URI in the table. */
413     public int createDeferredElement(String JavaDoc elementURI, String JavaDoc elementName) {
414
415         // create node
416
int elementNodeIndex = createNode(Node.ELEMENT_NODE);
417         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
418         int elementIndex = elementNodeIndex & CHUNK_MASK;
419         setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
420         setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
421  
422         // return node index
423
return elementNodeIndex;
424
425     } // createDeferredElement(String,String):int
426

427     
428     /**
429      * This method is used by the DOMParser to create attributes.
430      * @param elementNodeIndex
431      * @param attrName
432      * @param attrURI
433      * @param attrValue
434      * @param specified
435      * @param id
436      * @param type
437      * @return int
438      */

439     public int setDeferredAttribute(int elementNodeIndex,
440                                 String JavaDoc attrName,
441                                 String JavaDoc attrURI,
442                                 String JavaDoc attrValue,
443                                 boolean specified,
444                                 boolean id,
445                                 TypeInfo JavaDoc type) {
446                                     
447         // create attribute
448
int attrNodeIndex = createDeferredAttribute(attrName, attrURI, attrValue, specified);
449         int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
450         int attrIndex = attrNodeIndex & CHUNK_MASK;
451         // set attribute's parent to element
452
setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
453
454         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
455         int elementIndex = elementNodeIndex & CHUNK_MASK;
456
457         // get element's last attribute
458
int lastAttrNodeIndex = getChunkIndex(fNodeExtra, elementChunk, elementIndex);
459         if (lastAttrNodeIndex != 0) {
460             int lastAttrChunk = lastAttrNodeIndex >> CHUNK_SHIFT;
461             int lastAttrIndex = lastAttrNodeIndex & CHUNK_MASK;
462             // add link from new attribute to last attribute
463
setChunkIndex(fNodePrevSib, lastAttrNodeIndex, attrChunk, attrIndex);
464         }
465         // add link from element to new last attribute
466
setChunkIndex(fNodeExtra, attrNodeIndex, elementChunk, elementIndex);
467
468         int extra = getChunkIndex(fNodeExtra, attrChunk, attrIndex);
469         if (id) {
470             extra = extra | ID;
471             setChunkIndex(fNodeExtra, extra, attrChunk, attrIndex);
472             String JavaDoc value = getChunkValue(fNodeValue, attrChunk, attrIndex);
473             putIdentifier(value, elementNodeIndex);
474         }
475         // store type information
476
if (type != null) {
477             int extraDataIndex = createNode(DeferredNode.TYPE_NODE);
478             int echunk = extraDataIndex >> CHUNK_SHIFT;
479             int eindex = extraDataIndex & CHUNK_MASK;
480
481             setChunkIndex(fNodeLastChild, extraDataIndex, attrChunk, attrIndex);
482             setChunkValue(fNodeValue, type, echunk, eindex);
483         }
484
485         // return node index
486
return attrNodeIndex;
487     }
488     
489     /** @deprecated. Sets an attribute on an element node.*/
490     public int setDeferredAttribute(int elementNodeIndex,
491                                     String JavaDoc attrName, String JavaDoc attrURI,
492                                     String JavaDoc attrValue, boolean specified) {
493         // create attribute
494
int attrNodeIndex = createDeferredAttribute(attrName, attrURI,
495                                                     attrValue, specified);
496         int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
497         int attrIndex = attrNodeIndex & CHUNK_MASK;
498         // set attribute's parent to element
499
setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
500
501         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
502         int elementIndex = elementNodeIndex & CHUNK_MASK;
503
504         // get element's last attribute
505
int lastAttrNodeIndex = getChunkIndex(fNodeExtra,
506                                               elementChunk, elementIndex);
507         if (lastAttrNodeIndex != 0) {
508             int lastAttrChunk = lastAttrNodeIndex >> CHUNK_SHIFT;
509             int lastAttrIndex = lastAttrNodeIndex & CHUNK_MASK;
510             // add link from new attribute to last attribute
511
setChunkIndex(fNodePrevSib, lastAttrNodeIndex,
512                           attrChunk, attrIndex);
513         }
514         // add link from element to new last attribute
515
setChunkIndex(fNodeExtra, attrNodeIndex,
516                       elementChunk, elementIndex);
517  
518         // return node index
519
return attrNodeIndex;
520
521     } // setDeferredAttribute(int,String,String,String,boolean):int
522

523     /** Creates an attribute in the table. */
524     public int createDeferredAttribute(String JavaDoc attrName, String JavaDoc attrValue,
525                                        boolean specified) {
526         return createDeferredAttribute(attrName, null, attrValue, specified);
527     }
528
529     /** Creates an attribute with a URI in the table. */
530     public int createDeferredAttribute(String JavaDoc attrName, String JavaDoc attrURI,
531                                        String JavaDoc attrValue, boolean specified) {
532
533         // create node
534
int nodeIndex = createNode(NodeImpl.ATTRIBUTE_NODE);
535         int chunk = nodeIndex >> CHUNK_SHIFT;
536         int index = nodeIndex & CHUNK_MASK;
537         setChunkValue(fNodeName, attrName, chunk, index);
538         setChunkValue(fNodeURI, attrURI, chunk, index);
539         setChunkValue(fNodeValue, attrValue, chunk, index);
540         int extra = specified ? SPECIFIED : 0;
541         setChunkIndex(fNodeExtra, extra, chunk, index);
542
543         // return node index
544
return nodeIndex;
545
546     } // createDeferredAttribute(String,String,String,boolean):int
547

548     /** Creates an element definition in the table.*/
549     public int createDeferredElementDefinition(String JavaDoc elementName) {
550
551         // create node
552
int nodeIndex = createNode(NodeImpl.ELEMENT_DEFINITION_NODE);
553         int chunk = nodeIndex >> CHUNK_SHIFT;
554         int index = nodeIndex & CHUNK_MASK;
555         setChunkValue(fNodeName, elementName, chunk, index);
556
557         // return node index
558
return nodeIndex;
559
560     } // createDeferredElementDefinition(String):int
561

562     /** Creates a text node in the table. */
563     public int createDeferredTextNode(String JavaDoc data,
564                                       boolean ignorableWhitespace) {
565
566         // create node
567
int nodeIndex = createNode(Node.TEXT_NODE);
568         int chunk = nodeIndex >> CHUNK_SHIFT;
569         int index = nodeIndex & CHUNK_MASK;
570         setChunkValue(fNodeValue, data, chunk, index);
571         // use extra to store ignorableWhitespace info
572
setChunkIndex(fNodeExtra, ignorableWhitespace ? 1 : 0, chunk, index);
573
574         // return node index
575
return nodeIndex;
576
577     } // createDeferredTextNode(String,boolean):int
578

579     /** Creates a CDATA section node in the table. */
580     public int createDeferredCDATASection(String JavaDoc data) {
581
582         // create node
583
int nodeIndex = createNode(Node.CDATA_SECTION_NODE);
584         int chunk = nodeIndex >> CHUNK_SHIFT;
585         int index = nodeIndex & CHUNK_MASK;
586         setChunkValue(fNodeValue, data, chunk, index);
587
588         // return node index
589
return nodeIndex;
590
591     } // createDeferredCDATASection(String):int
592

593     /** Creates a processing instruction node in the table. */
594     public int createDeferredProcessingInstruction(String JavaDoc target,
595                                                    String JavaDoc data) {
596         // create node
597
int nodeIndex = createNode(Node.PROCESSING_INSTRUCTION_NODE);
598         int chunk = nodeIndex >> CHUNK_SHIFT;
599         int index = nodeIndex & CHUNK_MASK;
600         setChunkValue(fNodeName, target, chunk, index);
601         setChunkValue(fNodeValue, data, chunk, index);
602         // return node index
603
return nodeIndex;
604
605     } // createDeferredProcessingInstruction(String,String):int
606

607     /** Creates a comment node in the table. */
608     public int createDeferredComment(String JavaDoc data) {
609
610         // create node
611
int nodeIndex = createNode(Node.COMMENT_NODE);
612         int chunk = nodeIndex >> CHUNK_SHIFT;
613         int index = nodeIndex & CHUNK_MASK;
614         setChunkValue(fNodeValue, data, chunk, index);
615
616         // return node index
617
return nodeIndex;
618
619     } // createDeferredComment(String):int
620

621     /** Creates a clone of the specified node. */
622     public int cloneNode(int nodeIndex, boolean deep) {
623
624         // clone immediate node
625

626         int nchunk = nodeIndex >> CHUNK_SHIFT;
627         int nindex = nodeIndex & CHUNK_MASK;
628         int nodeType = fNodeType[nchunk][nindex];
629         int cloneIndex = createNode((short)nodeType);
630         int cchunk = cloneIndex >> CHUNK_SHIFT;
631         int cindex = cloneIndex & CHUNK_MASK;
632         setChunkValue(fNodeName, fNodeName[nchunk][nindex], cchunk, cindex);
633         setChunkValue(fNodeValue, fNodeValue[nchunk][nindex], cchunk, cindex);
634         setChunkValue(fNodeURI, fNodeURI[nchunk][nindex], cchunk, cindex);
635         int extraIndex = fNodeExtra[nchunk][nindex];
636         if (extraIndex != -1) {
637             if (nodeType != Node.ATTRIBUTE_NODE && nodeType != Node.TEXT_NODE) {
638                 extraIndex = cloneNode(extraIndex, false);
639             }
640             setChunkIndex(fNodeExtra, extraIndex, cchunk, cindex);
641         }
642
643         // clone and attach children
644
if (deep) {
645             int prevIndex = -1;
646             int childIndex = getLastChild(nodeIndex, false);
647             while (childIndex != -1) {
648                 int clonedChildIndex = cloneNode(childIndex, deep);
649                 insertBefore(cloneIndex, clonedChildIndex, prevIndex);
650                 prevIndex = clonedChildIndex;
651                 childIndex = getRealPrevSibling(childIndex, false);
652             }
653             
654
655         }
656         
657         // return cloned node index
658
return cloneIndex;
659
660     } // cloneNode(int,boolean):int
661

662     /** Appends a child to the specified parent in the table. */
663     public void appendChild(int parentIndex, int childIndex) {
664
665         // append parent index
666
int pchunk = parentIndex >> CHUNK_SHIFT;
667         int pindex = parentIndex & CHUNK_MASK;
668         int cchunk = childIndex >> CHUNK_SHIFT;
669         int cindex = childIndex & CHUNK_MASK;
670         setChunkIndex(fNodeParent, parentIndex, cchunk, cindex);
671
672         // set previous sibling of new child
673
int olast = getChunkIndex(fNodeLastChild, pchunk, pindex);
674         setChunkIndex(fNodePrevSib, olast, cchunk, cindex);
675
676         // update parent's last child
677
setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
678
679     } // appendChild(int,int)
680

681     /** Adds an attribute node to the specified element. */
682     public int setAttributeNode(int elemIndex, int attrIndex) {
683
684         int echunk = elemIndex >> CHUNK_SHIFT;
685         int eindex = elemIndex & CHUNK_MASK;
686         int achunk = attrIndex >> CHUNK_SHIFT;
687         int aindex = attrIndex & CHUNK_MASK;
688
689         // see if this attribute is already here
690
String JavaDoc attrName = getChunkValue(fNodeName, achunk, aindex);
691         int oldAttrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
692         int nextIndex = -1;
693         int oachunk = -1;
694         int oaindex = -1;
695         while (oldAttrIndex != -1) {
696             oachunk = oldAttrIndex >> CHUNK_SHIFT;
697             oaindex = oldAttrIndex & CHUNK_MASK;
698             String JavaDoc oldAttrName = getChunkValue(fNodeName, oachunk, oaindex);
699             if (oldAttrName.equals(attrName)) {
700                 break;
701             }
702             nextIndex = oldAttrIndex;
703             oldAttrIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
704         }
705
706         // remove old attribute
707
if (oldAttrIndex != -1) {
708
709             // patch links
710
int prevIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
711             if (nextIndex == -1) {
712                 setChunkIndex(fNodeExtra, prevIndex, echunk, eindex);
713             }
714             else {
715                 int pchunk = nextIndex >> CHUNK_SHIFT;
716                 int pindex = nextIndex & CHUNK_MASK;
717                 setChunkIndex(fNodePrevSib, prevIndex, pchunk, pindex);
718             }
719
720             // remove connections to siblings
721
clearChunkIndex(fNodeType, oachunk, oaindex);
722             clearChunkValue(fNodeName, oachunk, oaindex);
723             clearChunkValue(fNodeValue, oachunk, oaindex);
724             clearChunkIndex(fNodeParent, oachunk, oaindex);
725             clearChunkIndex(fNodePrevSib, oachunk, oaindex);
726             int attrTextIndex =
727                 clearChunkIndex(fNodeLastChild, oachunk, oaindex);
728             int atchunk = attrTextIndex >> CHUNK_SHIFT;
729             int atindex = attrTextIndex & CHUNK_MASK;
730             clearChunkIndex(fNodeType, atchunk, atindex);
731             clearChunkValue(fNodeValue, atchunk, atindex);
732             clearChunkIndex(fNodeParent, atchunk, atindex);
733             clearChunkIndex(fNodeLastChild, atchunk, atindex);
734         }
735
736         // add new attribute
737
int prevIndex = getChunkIndex(fNodeExtra, echunk, eindex);
738         setChunkIndex(fNodeExtra, attrIndex, echunk, eindex);
739         setChunkIndex(fNodePrevSib, prevIndex, achunk, aindex);
740
741         // return
742
return oldAttrIndex;
743
744     } // setAttributeNode(int,int):int
745

746
747     /** Adds an attribute node to the specified element. */
748     public void setIdAttributeNode(int elemIndex, int attrIndex) {
749
750         int chunk = attrIndex >> CHUNK_SHIFT;
751         int index = attrIndex & CHUNK_MASK;
752         int extra = getChunkIndex(fNodeExtra, chunk, index);
753         extra = extra | ID;
754         setChunkIndex(fNodeExtra, extra, chunk, index);
755
756         String JavaDoc value = getChunkValue(fNodeValue, chunk, index);
757         putIdentifier(value, elemIndex);
758     }
759
760
761     /** Sets type of attribute */
762     public void setIdAttribute(int attrIndex) {
763
764         int chunk = attrIndex >> CHUNK_SHIFT;
765         int index = attrIndex & CHUNK_MASK;
766         int extra = getChunkIndex(fNodeExtra, chunk, index);
767         extra = extra | ID;
768         setChunkIndex(fNodeExtra, extra, chunk, index);
769     }
770
771     /** Inserts a child before the specified node in the table. */
772     public int insertBefore(int parentIndex, int newChildIndex, int refChildIndex) {
773
774         if (refChildIndex == -1) {
775             appendChild(parentIndex, newChildIndex);
776             return newChildIndex;
777         }
778
779         int nchunk = newChildIndex >> CHUNK_SHIFT;
780         int nindex = newChildIndex & CHUNK_MASK;
781         int rchunk = refChildIndex >> CHUNK_SHIFT;
782         int rindex = refChildIndex & CHUNK_MASK;
783         int previousIndex = getChunkIndex(fNodePrevSib, rchunk, rindex);
784         setChunkIndex(fNodePrevSib, newChildIndex, rchunk, rindex);
785         setChunkIndex(fNodePrevSib, previousIndex, nchunk, nindex);
786
787         return newChildIndex;
788
789     } // insertBefore(int,int,int):int
790

791     /** Sets the last child of the parentIndex to childIndex. */
792     public void setAsLastChild(int parentIndex, int childIndex) {
793
794         int pchunk = parentIndex >> CHUNK_SHIFT;
795         int pindex = parentIndex & CHUNK_MASK;
796         int chunk = childIndex >> CHUNK_SHIFT;
797         int index = childIndex & CHUNK_MASK;
798         setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
799     } // setAsLastChild(int,int)
800

801     /**
802      * Returns the parent node of the given node.
803      * <em>Calling this method does not free the parent index.</em>
804      */

805     public int getParentNode(int nodeIndex) {
806         return getParentNode(nodeIndex, false);
807     }
808
809     /**
810      * Returns the parent node of the given node.
811      * @param free True to free parent node.
812      */

813     public int getParentNode(int nodeIndex, boolean free) {
814
815         if (nodeIndex == -1) {
816             return -1;
817         }
818
819         int chunk = nodeIndex >> CHUNK_SHIFT;
820         int index = nodeIndex & CHUNK_MASK;
821         return free ? clearChunkIndex(fNodeParent, chunk, index)
822                     : getChunkIndex(fNodeParent, chunk, index);
823
824     } // getParentNode(int):int
825

826     /** Returns the last child of the given node. */
827     public int getLastChild(int nodeIndex) {
828         return getLastChild(nodeIndex, true);
829     }
830
831     /**
832      * Returns the last child of the given node.
833      * @param free True to free child index.
834      */

835     public int getLastChild(int nodeIndex, boolean free) {
836
837         if (nodeIndex == -1) {
838             return -1;
839         }
840
841         int chunk = nodeIndex >> CHUNK_SHIFT;
842         int index = nodeIndex & CHUNK_MASK;
843         return free ? clearChunkIndex(fNodeLastChild, chunk, index)
844                     : getChunkIndex(fNodeLastChild, chunk, index);
845
846     } // getLastChild(int,boolean):int
847

848     /**
849      * Returns the prev sibling of the given node.
850      * This is post-normalization of Text Nodes.
851      */

852     public int getPrevSibling(int nodeIndex) {
853         return getPrevSibling(nodeIndex, true);
854     }
855
856     /**
857      * Returns the prev sibling of the given node.
858      * @param free True to free sibling index.
859      */

860     public int getPrevSibling(int nodeIndex, boolean free) {
861
862         if (nodeIndex == -1) {
863             return -1;
864         }
865
866         int chunk = nodeIndex >> CHUNK_SHIFT;
867         int index = nodeIndex & CHUNK_MASK;
868         int type = getChunkIndex(fNodeType, chunk, index);
869         if (type == Node.TEXT_NODE) {
870             do {
871                 nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
872                 if (nodeIndex == -1) {
873                     break;
874                 }
875                 chunk = nodeIndex >> CHUNK_SHIFT;
876                 index = nodeIndex & CHUNK_MASK;
877                 type = getChunkIndex(fNodeType, chunk, index);
878             } while (type == Node.TEXT_NODE);
879         }
880         else {
881             nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
882         }
883
884         return nodeIndex;
885
886     } // getPrevSibling(int,boolean):int
887

888     /**
889      * Returns the <i>real</i> prev sibling of the given node,
890      * directly from the data structures. Used by TextImpl#getNodeValue()
891      * to normalize values.
892      */

893     public int getRealPrevSibling(int nodeIndex) {
894         return getRealPrevSibling(nodeIndex, true);
895     }
896
897     /**
898      * Returns the <i>real</i> prev sibling of the given node.
899      * @param free True to free sibling index.
900      */

901     public int getRealPrevSibling(int nodeIndex, boolean free) {
902
903      &n