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         if (nodeIndex == -1) {
904             return -1;
905         }
906
907         int chunk = nodeIndex >> CHUNK_SHIFT;
908         int index = nodeIndex & CHUNK_MASK;
909         return free ? clearChunkIndex(fNodePrevSib, chunk, index)
910                     : getChunkIndex(fNodePrevSib, chunk, index);
911
912     } // getReadPrevSibling(int,boolean):int
913

914     /**
915      * Returns the index of the element definition in the table
916      * with the specified name index, or -1 if no such definition
917      * exists.
918      */

919     public int lookupElementDefinition(String JavaDoc elementName) {
920
921         if (fNodeCount > 1) {
922
923             // find doctype
924
int docTypeIndex = -1;
925             int nchunk = 0;
926             int nindex = 0;
927             for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
928                  index != -1;
929                  index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {
930
931                 nchunk = index >> CHUNK_SHIFT;
932                 nindex = index & CHUNK_MASK;
933                 if (getChunkIndex(fNodeType, nchunk, nindex) == Node.DOCUMENT_TYPE_NODE) {
934                     docTypeIndex = index;
935                     break;
936                 }
937             }
938
939             // find element definition
940
if (docTypeIndex == -1) {
941                 return -1;
942             }
943             nchunk = docTypeIndex >> CHUNK_SHIFT;
944             nindex = docTypeIndex & CHUNK_MASK;
945             for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
946                  index != -1;
947                  index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {
948
949                 nchunk = index >> CHUNK_SHIFT;
950                 nindex = index & CHUNK_MASK;
951                 if (getChunkIndex(fNodeType, nchunk, nindex) ==
952                                            NodeImpl.ELEMENT_DEFINITION_NODE
953                  && getChunkValue(fNodeName, nchunk, nindex) == elementName) {
954                     return index;
955                 }
956             }
957         }
958
959         return -1;
960
961     } // lookupElementDefinition(String):int
962

963     /** Instantiates the requested node object. */
964     public DeferredNode getNodeObject(int nodeIndex) {
965
966         // is there anything to do?
967
if (nodeIndex == -1) {
968             return null;
969         }
970
971         // get node type
972
int chunk = nodeIndex >> CHUNK_SHIFT;
973         int index = nodeIndex & CHUNK_MASK;
974         int type = getChunkIndex(fNodeType, chunk, index);
975         if (type != Node.TEXT_NODE && type != Node.CDATA_SECTION_NODE) {
976             clearChunkIndex(fNodeType, chunk, index);
977         }
978
979         // create new node
980
DeferredNode node = null;
981         switch (type) {
982
983             //
984
// Standard DOM node types
985
//
986

987             case Node.ATTRIBUTE_NODE: {
988                 if (fNamespacesEnabled) {
989                     node = new DeferredAttrNSImpl(this, nodeIndex);
990                 } else {
991                     node = new DeferredAttrImpl(this, nodeIndex);
992                 }
993                 break;
994             }
995
996             case Node.CDATA_SECTION_NODE: {
997                 node = new DeferredCDATASectionImpl(this, nodeIndex);
998                 break;
999             }
1000
1001            case Node.COMMENT_NODE: {
1002                node = new DeferredCommentImpl(this, nodeIndex);
1003                break;
1004            }
1005
1006            // NOTE: Document fragments can never be "fast".
1007
//
1008
// The parser will never ask to create a document
1009
// fragment during the parse. Document fragments
1010
// are used by the application *after* the parse.
1011
//
1012
// case Node.DOCUMENT_FRAGMENT_NODE: { break; }
1013
case Node.DOCUMENT_NODE: {
1014                // this node is never "fast"
1015
node = this;
1016                break;
1017            }
1018
1019            case Node.DOCUMENT_TYPE_NODE: {
1020                node = new DeferredDocumentTypeImpl(this, nodeIndex);
1021                // save the doctype node
1022
docType = (DocumentTypeImpl)node;
1023                break;
1024            }
1025
1026            case Node.ELEMENT_NODE: {
1027
1028                if (DEBUG_IDS) {
1029                    System.out.println("getNodeObject(ELEMENT_NODE): "+nodeIndex);
1030                }
1031
1032                // create node
1033
if (fNamespacesEnabled) {
1034                    node = new DeferredElementNSImpl(this, nodeIndex);
1035                } else {
1036                    node = new DeferredElementImpl(this, nodeIndex);
1037                }
1038
1039                // save the document element node
1040
if (docElement == null) {
1041                    docElement = (ElementImpl)node;
1042                }
1043
1044                // check to see if this element needs to be
1045
// registered for its ID attributes
1046
if (fIdElement != null) {
1047                    int idIndex = binarySearch(fIdElement, 0,
1048                                               fIdCount-1, nodeIndex);
1049                    while (idIndex != -1) {
1050
1051                        if (DEBUG_IDS) {
1052                            System.out.println(" id index: "+idIndex);
1053                            System.out.println(" fIdName["+idIndex+
1054                                               "]: "+fIdName[idIndex]);
1055                        }
1056
1057                        // register ID
1058
String JavaDoc name = fIdName[idIndex];
1059                        if (name != null) {
1060                            if (DEBUG_IDS) {
1061                                System.out.println(" name: "+name);
1062                                System.out.print("getNodeObject()#");
1063                            }
1064                            putIdentifier0(name, (Element JavaDoc)node);
1065                            fIdName[idIndex] = null;
1066                        }
1067
1068                        // continue if there are more IDs for
1069
// this element
1070
if (idIndex + 1 < fIdCount &&
1071                            fIdElement[idIndex + 1] == nodeIndex) {
1072                            idIndex++;
1073                        }
1074                        else {
1075                            idIndex = -1;
1076                        }
1077                    }
1078                }
1079                break;
1080            }
1081
1082            case Node.ENTITY_NODE: {
1083                node = new DeferredEntityImpl(this, nodeIndex);
1084                break;
1085            }
1086
1087            case Node.ENTITY_REFERENCE_NODE: {
1088                node = new DeferredEntityReferenceImpl(this, nodeIndex);
1089                break;
1090            }
1091
1092            case Node.NOTATION_NODE: {
1093                node = new DeferredNotationImpl(this, nodeIndex);
1094                break;
1095            }
1096
1097            case Node.PROCESSING_INSTRUCTION_NODE: {
1098                node = new DeferredProcessingInstructionImpl(this, nodeIndex);
1099                break;
1100            }
1101
1102            case Node.TEXT_NODE: {
1103                node = new DeferredTextImpl(this, nodeIndex);
1104                break;
1105            }
1106
1107            //
1108
// non-standard DOM node types
1109
//
1110

1111            case NodeImpl.ELEMENT_DEFINITION_NODE: {
1112                node = new DeferredElementDefinitionImpl(this, nodeIndex);
1113                break;
1114            }
1115
1116            default: {
1117                throw new IllegalArgumentException JavaDoc("type: "+type);
1118            }
1119
1120        } // switch node type
1121

1122        // store and return
1123
if (node != null) {
1124            return node;
1125        }
1126
1127        // error
1128
throw new IllegalArgumentException JavaDoc();
1129
1130    } // createNodeObject(int):Node
1131

1132    /** Returns the name of the given node. */
1133    public String JavaDoc getNodeName(int nodeIndex) {
1134        return getNodeName(nodeIndex, true);
1135    } // getNodeNameString(int):String
1136

1137    /**
1138     * Returns the name of the given node.
1139     * @param free True to free the string index.
1140     */

1141    public String JavaDoc getNodeName(int nodeIndex, boolean free) {
1142
1143        if (nodeIndex == -1) {
1144            return null;
1145        }
1146
1147        int chunk = nodeIndex >> CHUNK_SHIFT;
1148        int index = nodeIndex & CHUNK_MASK;
1149        return free ? clearChunkValue(fNodeName, chunk, index)
1150                    : getChunkValue(fNodeName, chunk, index);
1151
1152    } // getNodeName(int,boolean):String
1153

1154    /** Returns the real value of the given node. */
1155    public String JavaDoc getNodeValueString(int nodeIndex) {
1156        return getNodeValueString(nodeIndex, true);
1157    } // getNodeValueString(int):String
1158

1159    /**
1160     * Returns the real value of the given node.
1161     * @param free True to free the string index.
1162     */

1163    public String JavaDoc getNodeValueString(int nodeIndex, boolean free) {
1164
1165        if (nodeIndex == -1) {
1166            return null;
1167        }
1168        
1169        int chunk = nodeIndex >> CHUNK_SHIFT;
1170        int index = nodeIndex & CHUNK_MASK;
1171        String JavaDoc value = free ? clearChunkValue(fNodeValue, chunk, index)
1172                            : getChunkValue(fNodeValue, chunk, index);
1173        if (value == null) {
1174            return null;
1175        }
1176        
1177        int type = getChunkIndex(fNodeType, chunk, index);
1178        if (type == Node.TEXT_NODE) {
1179            int prevSib = getRealPrevSibling(nodeIndex);
1180            if (prevSib != -1 &&
1181                getNodeType(prevSib, false) == Node.TEXT_NODE) {
1182                // append data that is stored in fNodeValue
1183
// REVISIT: for text nodes it works differently than for CDATA
1184
// nodes.
1185
fStrChunks.addElement(value);
1186                do {
1187                    // go in reverse order: find last child, then
1188
// its previous sibling, etc
1189
chunk = prevSib >> CHUNK_SHIFT;
1190                    index = prevSib & CHUNK_MASK;
1191                    value = getChunkValue(fNodeValue, chunk, index);
1192                    fStrChunks.addElement(value);
1193                    prevSib = getChunkIndex(fNodePrevSib, chunk, index);
1194                    if (prevSib == -1) {
1195                        break;
1196                    }
1197                } while (getNodeType(prevSib, false) == Node.TEXT_NODE);
1198                
1199                int chunkCount = fStrChunks.size();
1200
1201                // add to the buffer in the correct order.
1202
for (int i = chunkCount - 1; i >= 0; i--) {
1203                    fBufferStr.append((String JavaDoc)fStrChunks.elementAt(i));
1204                }
1205                
1206                value = fBufferStr.toString();
1207                fStrChunks.removeAllElements();
1208                fBufferStr.setLength(0);
1209                return value;
1210            }
1211        }
1212        else if (type == Node.CDATA_SECTION_NODE) {
1213            // find if any other data stored in children
1214
int child = getLastChild(nodeIndex, false);
1215            if (child !=-1) {
1216                // append data that is stored in fNodeValue
1217
fBufferStr.append(value);
1218                while (child !=-1) {
1219                    // go in reverse order: find last child, then
1220
// its previous sibling, etc
1221
chunk = child >> CHUNK_SHIFT;
1222                    index = child & CHUNK_MASK;
1223                    value = getChunkValue(fNodeValue, chunk, index);
1224                    fStrChunks.addElement(value);
1225                    child = getChunkIndex(fNodePrevSib, chunk, index);
1226                }
1227                // add to the buffer in the correct order.
1228
for (int i=fStrChunks.size()-1; i>=0; i--) {
1229                     fBufferStr.append((String JavaDoc)fStrChunks.elementAt(i));
1230                }
1231                                                         
1232                value = fBufferStr.toString();
1233                fStrChunks.setSize(0);
1234                fBufferStr.setLength(0);
1235                return value;
1236            }
1237        }
1238
1239        return value;
1240
1241    } // getNodeValueString(int,boolean):String
1242

1243    /**
1244     * Returns the value of the given node.
1245     */

1246    public String JavaDoc getNodeValue(int nodeIndex) {
1247        return getNodeValue(nodeIndex, true);
1248    }
1249    
1250    /**
1251     * Clears the type info that is stored in the fNodeValue array
1252     * @param nodeIndex
1253     * @return Object - type information for the attribute/element node
1254     */

1255    public TypeInfo JavaDoc getTypeInfo(int nodeIndex) {
1256        if (nodeIndex == -1) {
1257            return null;
1258        }
1259
1260        int chunk = nodeIndex >> CHUNK_SHIFT;
1261        int index = nodeIndex & CHUNK_MASK;
1262        
1263        
1264        TypeInfo JavaDoc value = (TypeInfo JavaDoc)(fNodeValue[chunk] != null ? fNodeValue[chunk][index] : null);
1265        if (value != null) {
1266            fNodeValue[chunk][index] = null;
1267            RefCount c = (RefCount) fNodeValue[chunk][CHUNK_SIZE];
1268            c.fCount--;
1269            if (c.fCount == 0) {
1270                fNodeValue[chunk] = null;
1271            }
1272        }
1273        return value;
1274    }
1275
1276    /**
1277     * Returns the value of the given node.
1278     * @param free True to free the value index.
1279     */

1280    public String JavaDoc getNodeValue(int nodeIndex, boolean free) {
1281
1282        if (nodeIndex == -1) {
1283            return null;
1284        }
1285
1286        int chunk = nodeIndex >> CHUNK_SHIFT;
1287        int index = nodeIndex & CHUNK_MASK;
1288        return free ? clearChunkValue(fNodeValue, chunk, index)
1289                    : getChunkValue(fNodeValue, chunk, index);
1290
1291    } // getNodeValue(int,boolean):String
1292

1293    /**
1294     * Returns the extra info of the given node.
1295     * Used by AttrImpl to store specified value (1 == true).
1296     */

1297    public int getNodeExtra(int nodeIndex) {
1298        return getNodeExtra(nodeIndex, true);
1299    }
1300
1301    /**
1302     * Returns the extra info of the given node.
1303     * @param free True to free the value index.
1304     */

1305    public int getNodeExtra(int nodeIndex, boolean free) {
1306
1307        if (nodeIndex == -1) {
1308            return -1;
1309        }
1310
1311        int chunk = nodeIndex >> CHUNK_SHIFT;
1312        int index = nodeIndex & CHUNK_MASK;
1313        return free ? clearChunkIndex(fNodeExtra, chunk, index)
1314                    : getChunkIndex(fNodeExtra, chunk, index);
1315
1316    } // getNodeExtra(int,boolean):int
1317

1318    /** Returns the type of the given node. */
1319    public short getNodeType(int nodeIndex) {
1320        return getNodeType(nodeIndex, true);
1321    }
1322
1323    /**
1324     * Returns the type of the given node.
1325     * @param free True to free type index.
1326     */

1327    public short getNodeType(int nodeIndex, boolean free) {
1328
1329        if (nodeIndex == -1) {
1330            return -1;
1331        }
1332
1333        int chunk = nodeIndex >> CHUNK_SHIFT;
1334        int index = nodeIndex & CHUNK_MASK;
1335        return free ? (short)clearChunkIndex(fNodeType, chunk, index)
1336                    : (short)getChunkIndex(fNodeType, chunk, index);
1337
1338    } // getNodeType(int):int
1339

1340    /** Returns the attribute value of the given name. */
1341    public String JavaDoc getAttribute(int elemIndex, String JavaDoc name) {
1342        if (elemIndex == -1 || name == null) {
1343            return null;
1344        }
1345        int echunk = elemIndex >> CHUNK_SHIFT;
1346        int eindex = elemIndex & CHUNK_MASK;
1347        int attrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
1348        while (attrIndex != -1) {
1349            int achunk = attrIndex >> CHUNK_SHIFT;
1350            int aindex = attrIndex & CHUNK_MASK;
1351            if (getChunkValue(fNodeName, achunk, aindex) == name) {
1352                return getChunkValue(fNodeValue, achunk, aindex);
1353            }
1354            attrIndex = getChunkIndex(fNodePrevSib, achunk, aindex);
1355        }
1356        return null;
1357    }
1358
1359    /** Returns the URI of the given node. */
1360    public String JavaDoc getNodeURI(int nodeIndex) {
1361        return getNodeURI(nodeIndex, true);
1362    }
1363
1364    /**
1365     * Returns the URI of the given node.
1366     * @param free True to free URI index.
1367     */

1368    public String JavaDoc getNodeURI(int nodeIndex, boolean free) {
1369
1370        if (nodeIndex == -1) {
1371            return null;
1372        }
1373
1374        int chunk = nodeIndex >> CHUNK_SHIFT;
1375        int index = nodeIndex & CHUNK_MASK;
1376        return free ? clearChunkValue(fNodeURI, chunk, index)
1377                    : getChunkValue(fNodeURI, chunk, index);
1378
1379    } // getNodeURI(int,int):String
1380

1381    // identifier maintenance
1382

1383    /** Registers an identifier name with a specified element node. */
1384    public void putIdentifier(String JavaDoc name, int elementNodeIndex) {
1385
1386        if (DEBUG_IDS) {
1387            System.out.println("putIdentifier(" + name + ", "
1388                               + elementNodeIndex + ')' + " // " +
1389                               getChunkValue(fNodeName,
1390                                             elementNodeIndex >> CHUNK_SHIFT,
1391                                             elementNodeIndex & CHUNK_MASK));
1392        }
1393
1394        // initialize arrays
1395
if (fIdName == null) {
1396            fIdName = new String JavaDoc[64];
1397            fIdElement = new int[64];
1398        }
1399
1400        // resize arrays
1401
if (fIdCount == fIdName.length) {
1402            String JavaDoc idName[] = new String JavaDoc[fIdCount * 2];
1403            System.arraycopy(fIdName, 0, idName, 0, fIdCount);
1404            fIdName = idName;
1405
1406            int idElement[] = new int[idName.length];
1407            System.arraycopy(fIdElement, 0, idElement, 0, fIdCount);
1408            fIdElement = idElement;
1409        }
1410
1411        // store identifier
1412
fIdName[fIdCount] = name;
1413        fIdElement[fIdCount] = elementNodeIndex;
1414        fIdCount++;
1415
1416    } // putIdentifier(String,int)
1417

1418    //
1419
// DEBUG
1420
//
1421

1422    /** Prints out the tables. */
1423    public void print() {
1424
1425        if (DEBUG_PRINT_REF_COUNTS) {
1426            System.out.print("num\t");
1427            System.out.print("type\t");
1428            System.out.print("name\t");
1429            System.out.print("val\t");
1430            System.out.print("par\t");
1431            System.out.print("lch\t");
1432            System.out.print("psib");
1433            System.out.println();
1434            for (int i = 0; i < fNodeType.length; i++) {
1435                if (fNodeType[i] != null) {
1436                    // separator
1437
System.out.print("--------");
1438                    System.out.print("--------");
1439                    System.out.print("--------");
1440                    System.out.print("--------");
1441                    System.out.print("--------");
1442                    System.out.print("--------");
1443                    System.out.print("--------");
1444                    System.out.println();
1445
1446                    // ref count
1447
System.out.print(i);
1448                    System.out.print('\t');
1449                    switch (fNodeType[i][CHUNK_SIZE]) {
1450                        case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
1451                        case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
1452                        case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
1453                        case Node.COMMENT_NODE: { System.out.print("Com"); break; }
1454                        case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
1455                        case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
1456                        case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
1457                        case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
1458                        case Node.TEXT_NODE: { System.out.print("Text"); break; }
1459                        case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
1460                        case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
1461                        default: { System.out.print("?"+fNodeType[i][CHUNK_SIZE]); }
1462                    }
1463                    System.out.print('\t');
1464                    System.out.print(fNodeName[i][CHUNK_SIZE]);
1465                    System.out.print('\t');
1466                    System.out.print(fNodeValue[i][CHUNK_SIZE]);
1467                    System.out.print('\t');
1468                    System.out.print(fNodeURI[i][CHUNK_SIZE]);
1469                    System.out.print('\t');
1470                    System.out.print(fNodeParent[i][CHUNK_SIZE]);
1471                    System.out.print('\t');
1472                    System.out.print(fNodeLastChild[i][CHUNK_SIZE]);
1473                    System.out.print('\t');
1474                    System.out.print(fNodePrevSib[i][CHUNK_SIZE]);
1475                    System.out.print('\t');
1476                    System.out.print(fNodeExtra[i][CHUNK_SIZE]);
1477                    System.out.println();
1478                }
1479            }
1480        }
1481
1482        if (DEBUG_PRINT_TABLES) {
1483            // This assumes that the document is small
1484
System.out.println("# start table");
1485            for (int i = 0; i < fNodeCount; i++) {
1486                int chunk = i >> CHUNK_SHIFT;
1487                int index = i & CHUNK_MASK;
1488                if (i % 10 == 0) {
1489                    System.out.print("num\t");
1490                    System.out.print("type\t");
1491                    System.out.print("name\t");
1492                    System.out.print("val\t");
1493                    System.out.print("uri\t");
1494                    System.out.print("par\t");
1495                    System.out.print("lch\t");
1496                    System.out.print("psib\t");
1497                    System.out.print("xtra");
1498                    System.out.println();
1499                }
1500                System.out.print(i);
1501                System.out.print('\t');
1502                switch (getChunkIndex(fNodeType, chunk, index)) {
1503                    case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
1504                    case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
1505                    case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
1506                    case Node.COMMENT_NODE: { System.out.print("Com"); break; }
1507                    case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
1508                    case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
1509                    case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
1510                    case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
1511                    case Node.TEXT_NODE: { System.out.print("Text"); break; }
1512                    case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
1513                    case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
1514                    default: { System.out.print("?"+getChunkIndex(fNodeType, chunk, index)); }
1515                }
1516                System.out.print('\t');
1517                System.out.print(getChunkValue(fNodeName, chunk, index));
1518                System.out.print('\t');
1519                System.out.print(getNodeValue(chunk, index));
1520                System.out.print('\t');
1521                System.out.print(getChunkValue(fNodeURI, chunk, index));
1522                System.out.print('\t');
1523                System.out.print(getChunkIndex(fNodeParent, chunk, index));
1524                System.out.print('\t');
1525                System.out.print(getChunkIndex(fNodeLastChild, chunk, index));
1526                System.out.print('\t');
1527                System.out.print(getChunkIndex(fNodePrevSib, chunk, index));
1528                System.out.print('\t');
1529                System.out.print(getChunkIndex(fNodeExtra, chunk, index));
1530                System.out.println();
1531            }
1532            System.out.println("# end table");
1533        }
1534
1535    } // print()
1536

1537    //
1538
// DeferredNode methods
1539
//
1540

1541    /** Returns the node index. */
1542    public int getNodeIndex() {
1543        return 0;
1544    }
1545
1546    //
1547
// Protected methods
1548
//
1549

1550    /** Synchronizes the node's data. */
1551    protected void synchronizeData() {
1552
1553        // no need to sync in the future
1554
needsSyncData(false);
1555
1556        // fluff up enough nodes to fill identifiers hash
1557
if (fIdElement != null) {
1558
1559            // REVISIT: There has to be a more efficient way of
1560
// doing this. But keep in mind that the
1561
// tree can have been altered and re-ordered
1562
// before all of the element nodes with ID
1563
// attributes have been registered. For now
1564
// this is reasonable and safe. -Ac
1565

1566            IntVector path = new IntVector();
1567            for (int i = 0; i < fIdCount; i++) {
1568
1569                // ignore if it's already been registered
1570
int elementNodeIndex = fIdElement[i];
1571                String JavaDoc idName = fIdName[i];
1572                if (idName == null) {
1573                    continue;
1574                }
1575
1576                // find path from this element to the root
1577
path.removeAllElements();
1578                int index = elementNodeIndex;
1579                do {
1580                    path.addElement(index);
1581                    int pchunk = index >> CHUNK_SHIFT;
1582                    int pindex = index & CHUNK_MASK;
1583                    index = getChunkIndex(fNodeParent, pchunk, pindex);
1584                } while (index != -1);
1585
1586                // Traverse path (backwards), fluffing the elements
1587
// along the way. When this loop finishes, "place"
1588
// will contain the reference to the element node
1589
// we're interested in. -Ac
1590
Node JavaDoc place = this;
1591                for (int j = path.size() - 2; j >= 0; j--) {
1592                    index = path.elementAt(j);
1593                    Node JavaDoc child = place.getLastChild();
1594                    while (child != null) {
1595                        if (child instanceof DeferredNode) {
1596                            int nodeIndex =
1597                                ((DeferredNode)child).getNodeIndex();
1598                            if (nodeIndex == index) {
1599                                place = child;
1600                                break;
1601                            }
1602                        }
1603                        child = child.getPreviousSibling();
1604                    }
1605                }
1606
1607                // register the element
1608
Element JavaDoc element = (Element JavaDoc)place;
1609                putIdentifier0(idName, element);
1610                fIdName[i] = null;
1611
1612                // see if there are more IDs on this element
1613
while (i + 1 < fIdCount &&
1614                    fIdElement[i + 1] == elementNodeIndex) {
1615                    idName = fIdName[++i];
1616                    if (idName == null) {
1617                        continue;
1618                    }
1619                    putIdentifier0(idName, element);
1620                }
1621            }
1622
1623        } // if identifiers
1624

1625    } // synchronizeData()
1626

1627    /**
1628     * Synchronizes the node's children with the internal structure.
1629     * Fluffing the children at once solves a lot of work to keep
1630     * the two structures in sync. The problem gets worse when
1631     * editing the tree -- this makes it a lot easier.
1632     */

1633    protected void synchronizeChildren() {
1634
1635        if (needsSyncData()) {
1636            synchronizeData();
1637            /*
1638             * when we have elements with IDs this method is being recursively
1639             * called from synchronizeData, in which case we've already gone
1640             * through the following and we can now simply stop here.
1641             */

1642            if (!needsSyncChildren()) {
1643                return;
1644            }
1645        }
1646
1647        // we don't want to generate any event for this so turn them off
1648
boolean orig = mutationEvents;
1649        mutationEvents = false;
1650
1651        // no need to sync in the future
1652
needsSyncChildren(false);
1653
1654        getNodeType(0);
1655
1656        // create children and link them as siblings
1657
ChildNode first = null;
1658        ChildNode last = null;
1659        for (int index = getLastChild(0);
1660             index != -1;
1661             index = getPrevSibling(index)) {
1662
1663            ChildNode node = (ChildNode)getNodeObject(index);
1664            if (last == null) {
1665                last = node;
1666            }
1667            else {
1668                first.previousSibling = node;
1669            }
1670            node.ownerNode = this;
1671            node.isOwned(true);
1672            node.nextSibling = first;
1673            first = node;
1674
1675            // save doctype and document type
1676
int type = node.getNodeType();
1677            if (type == Node.ELEMENT_NODE) {
1678                docElement = (ElementImpl)node;
1679            }
1680            else if (type == Node.DOCUMENT_TYPE_NODE) {
1681                docType = (DocumentTypeImpl)node;
1682            }
1683        }
1684
1685        if (first != null) {
1686            firstChild = first;
1687            first.isFirstChild(true);
1688            lastChild(last);
1689        }
1690
1691        // set mutation events flag back to its original value
1692
mutationEvents = orig;
1693
1694    } // synchronizeChildren()
1695

1696    /**
1697     * Synchronizes the node's children with the internal structure.
1698     * Fluffing the children at once solves a lot of work to keep
1699     * the two structures in sync. The problem gets worse when
1700     * editing the tree -- this makes it a lot easier.
1701     * This is not directly used in this class but this method is
1702     * here so that it can be shared by all deferred subclasses of AttrImpl.
1703     */

1704    protected final void synchronizeChildren(AttrImpl a, int nodeIndex) {
1705
1706        // we don't want to generate any event for this so turn them off
1707
boolean orig = getMutationEvents();
1708        setMutationEvents(false);
1709
1710        // no need to sync in the future
1711
a.needsSyncChildren(false);
1712
1713        // create children and link them as siblings or simply store the value
1714
// as a String if all we have is one piece of text
1715
int last = getLastChild(nodeIndex);
1716        int prev = getPrevSibling(last);
1717        if (prev == -1) {
1718            a.value = getNodeValueString(nodeIndex);
1719            a.hasStringValue(true);
1720        }
1721        else {
1722            ChildNode firstNode = null;
1723            ChildNode lastNode = null;
1724            for (int index = last; index != -1;
1725                 index = getPrevSibling(index)) {
1726
1727                ChildNode node = (ChildNode) getNodeObject(index);
1728                if (lastNode == null) {
1729                    lastNode = node;
1730                }
1731                else {
1732                    firstNode.previousSibling = node;
1733                }
1734                node.ownerNode = a;
1735                node.isOwned(true);
1736                node.nextSibling = firstNode;
1737                firstNode = node;
1738            }
1739            if (lastNode != null) {
1740                a.value = firstNode; // firstChild = firstNode
1741
firstNode.isFirstChild(true);
1742                a.lastChild(lastNode);
1743            }
1744            a.hasStringValue(false);
1745        }
1746
1747        // set mutation events flag back to its original value
1748
setMutationEvents(orig);
1749
1750    } // synchronizeChildren(AttrImpl,int):void
1751

1752
1753    /**
1754     * Synchronizes the node's children with the internal structure.
1755     * Fluffing the children at once solves a lot of work to keep
1756     * the two structures in sync. The problem gets worse when
1757     * editing the tree -- this makes it a lot easier.
1758     * This is not directly used in this class but this method is
1759     * here so that it can be shared by all deferred subclasses of ParentNode.
1760     */

1761    protected final void synchronizeChildren(ParentNode p, int nodeIndex) {
1762
1763        // we don't want to generate any event for this so turn them off
1764
boolean orig = getMutationEvents();
1765        setMutationEvents(false);
1766
1767        // no need to sync in the future
1768
p.needsSyncChildren(false);
1769
1770        // create children and link them as siblings
1771
ChildNode firstNode = null;
1772        ChildNode lastNode = null;
1773        for (int index = getLastChild(nodeIndex);
1774             index != -1;
1775             index = getPrevSibling(index)) {
1776
1777            ChildNode node = (ChildNode) getNodeObject(index);
1778            if (lastNode == null) {
1779                lastNode = node;
1780            }
1781            else {
1782                firstNode.previousSibling = node;
1783            }
1784            node.ownerNode = p;
1785            node.isOwned(true);
1786            node.nextSibling = firstNode;
1787            firstNode = node;
1788        }
1789        if (lastNode != null) {
1790            p.firstChild = firstNode;
1791            firstNode.isFirstChild(true);
1792            p.lastChild(lastNode);
1793        }
1794
1795        // set mutation events flag back to its original value
1796
setMutationEvents(orig);
1797
1798    } // synchronizeChildren(ParentNode,int):void
1799

1800    // utility methods
1801

1802    /** Ensures that the internal tables are large enough. */
1803    protected void ensureCapacity(int chunk) {
1804        if (fNodeType == null) {
1805            // create buffers
1806
fNodeType = new int[INITIAL_CHUNK_COUNT][];
1807            fNodeName = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
1808            fNodeValue = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
1809            fNodeParent = new int[INITIAL_CHUNK_COUNT][];
1810            fNodeLastChild = new int[INITIAL_CHUNK_COUNT][];
1811            fNodePrevSib = new int[INITIAL_CHUNK_COUNT][];
1812            fNodeURI = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
1813            fNodeExtra = new int[INITIAL_CHUNK_COUNT][];
1814        }
1815        else if (fNodeType.length <= chunk) {
1816            // resize the tables
1817
int newsize = chunk * 2;
1818
1819            int[][] newArray = new int[newsize][];
1820            System.arraycopy(fNodeType, 0, newArray, 0, chunk);
1821            fNodeType = newArray;
1822
1823            Object JavaDoc[][] newStrArray = new Object JavaDoc[newsize][];
1824            System.arraycopy(fNodeName, 0, newStrArray, 0, chunk);
1825            fNodeName = newStrArray;
1826
1827            newStrArray = new Object JavaDoc[newsize][];
1828            System.arraycopy(fNodeValue, 0, newStrArray, 0, chunk);
1829            fNodeValue = newStrArray;
1830
1831            newArray = new int[newsize][];
1832            System.arraycopy(fNodeParent, 0, newArray, 0, chunk);
1833            fNodeParent = newArray;
1834
1835            newArray = new int[newsize][];
1836            System.arraycopy(fNodeLastChild, 0, newArray, 0, chunk);
1837            fNodeLastChild = newArray;
1838
1839            newArray = new int[newsize][];
1840            System.arraycopy(fNodePrevSib, 0, newArray, 0, chunk);
1841            fNodePrevSib = newArray;
1842
1843            newStrArray = new Object JavaDoc[newsize][];
1844            System.arraycopy(fNodeURI, 0, newStrArray, 0, chunk);
1845            fNodeURI = newStrArray;
1846
1847            newArray = new int[newsize][];
1848            System.arraycopy(fNodeExtra, 0, newArray, 0, chunk);
1849            fNodeExtra = newArray;
1850        }
1851        else if (fNodeType[chunk] != null) {
1852            // Done - there's sufficient capacity
1853
return;
1854        }
1855
1856        // create new chunks
1857
createChunk(fNodeType, chunk);
1858        createChunk(fNodeName, chunk);
1859        createChunk(fNodeValue, chunk);
1860        createChunk(fNodeParent, chunk);
1861        createChunk(fNodeLastChild, chunk);
1862        createChunk(fNodePrevSib, chunk);
1863        createChunk(fNodeURI, chunk);
1864        createChunk(fNodeExtra, chunk);
1865
1866        // Done
1867
return;
1868
1869    } // ensureCapacity(int,int)
1870

1871    /** Creates a node of the specified type. */
1872    protected int createNode(short nodeType) {
1873        // ensure tables are large enough
1874
int chunk = fNodeCount >> CHUNK_SHIFT;
1875        int index = fNodeCount & CHUNK_MASK;
1876        ensureCapacity(chunk);
1877
1878        // initialize node
1879
setChunkIndex(fNodeType, nodeType, chunk, index);
1880
1881        // return node index number
1882
return fNodeCount++;
1883
1884    } // createNode(short):int
1885

1886    /**
1887     * Performs a binary search for a target value in an array of
1888     * values. The array of values must be in ascending sorted order
1889     * before calling this method and all array values must be
1890     * non-negative.
1891     *
1892     * @param values The array of values to search.
1893     * @param start The starting offset of the search.
1894     * @param end The ending offset of the search.
1895     * @param target The target value.
1896     *
1897     * @return This function will return the <i>first</i> occurrence
1898     * of the target value, or -1 if the target value cannot
1899     * be found.
1900     */

1901    protected static int binarySearch(final int values[],
1902                                      int start, int end, int target) {
1903
1904        if (DEBUG_IDS) {
1905            System.out.println("binarySearch(), target: "+target);
1906        }
1907
1908        // look for target value
1909
while (start <= end) {
1910
1911            // is this the one we're looking for?
1912
int middle = (start + end) / 2;
1913            int value = values[middle];
1914            if (DEBUG_IDS) {
1915                System.out.print(" value: "+value+", target: "+target+" // ");
1916                print(values, start, end, middle, target);
1917            }
1918            if (value == target) {
1919                while (middle > 0 && values[middle - 1] == target) {
1920                    middle--;
1921                }
1922                if (DEBUG_IDS) {
1923                    System.out.println("FOUND AT "+middle);
1924                }
1925                return middle;
1926            }
1927
1928            // is this point higher or lower?
1929
if (value > target) {
1930                end = middle - 1;
1931            }
1932            else {
1933                start = middle + 1;
1934            }
1935
1936        } // while
1937

1938        // not found
1939
if (DEBUG_IDS) {
1940            System.out.println("NOT FOUND!");
1941        }
1942        return -1;
1943
1944    } // binarySearch(int[],int,int,int):int
1945

1946    //
1947
// Private methods
1948
//
1949
private static final int[] INIT_ARRAY = new int[CHUNK_SIZE + 1];
1950    static {
1951        for (int i = 0; i < CHUNK_SIZE; i++) {
1952            INIT_ARRAY[i] = -1;
1953        }
1954    }
1955    /** Creates the specified chunk in the given array of chunks. */
1956    private final void createChunk(int data[][], int chunk) {
1957        data[chunk] = new int[CHUNK_SIZE + 1];
1958        System.arraycopy(INIT_ARRAY, 0, data[chunk], 0, CHUNK_SIZE);
1959    }
1960
1961    class RefCount {
1962        int fCount;
1963    }
1964
1965    private final void createChunk(Object JavaDoc data[][], int chunk) {
1966        data[chunk] = new Object JavaDoc[CHUNK_SIZE + 1];
1967        data[chunk][CHUNK_SIZE] = new RefCount();
1968    }
1969
1970    /**
1971     * Sets the specified value in the given of data at the chunk and index.
1972     *
1973     * @return Returns the old value.
1974     */

1975    private final int setChunkIndex(int data[][], int value,
1976                                    int chunk, int index) {
1977        if (value == -1) {
1978            return clearChunkIndex(data, chunk, index);
1979        }
1980        int ovalue = data[chunk][index];
1981        if (ovalue == -1) {
1982            data[chunk][CHUNK_SIZE]++;
1983        }
1984        data[chunk][index] = value;
1985        return ovalue;
1986    }
1987    private final String JavaDoc setChunkValue(Object JavaDoc data[][], Object JavaDoc value,
1988                                       int chunk, int index) {
1989        if (value == null) {
1990            return clearChunkValue(data, chunk, index);
1991        }
1992        String JavaDoc ovalue = (String JavaDoc) data[chunk][index];
1993        if (ovalue == null) {
1994            RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
1995            c.fCount++;
1996        }
1997        data[chunk][index] = value;
1998        return ovalue;
1999    }
2000
2001    /**
2002     * Returns the specified value in the given data at the chunk and index.
2003     */

2004    private final int getChunkIndex(int data[][], int chunk, int index) {
2005        return data[chunk] != null ? data[chunk][index] : -1;
2006    }
2007    private final String JavaDoc getChunkValue(Object JavaDoc data[][], int chunk, int index) {
2008        return data[chunk] != null ? (String JavaDoc) data[chunk][index] : null;
2009    }
2010    private final String JavaDoc getNodeValue(int chunk, int index) {
2011        Object JavaDoc data = fNodeValue[chunk][index];
2012        if (data == null){
2013            return null;
2014        }
2015        else if (data instanceof String JavaDoc){
2016            return (String JavaDoc)data;
2017        }
2018        else {
2019            // type information
2020
return data.toString();
2021        }
2022    }
2023    
2024
2025    /**
2026     * Clears the specified value in the given data at the chunk and index.
2027     * Note that this method will clear the given chunk if the reference
2028     * count becomes zero.
2029     *
2030     * @return Returns the old value.
2031     */

2032    private final int clearChunkIndex(int data[][], int chunk, int index) {
2033        int value = data[chunk] != null ? data[chunk][index] : -1;
2034        if (value != -1) {
2035            data[chunk][CHUNK_SIZE]--;
2036            data[chunk][index] = -1;
2037            if (data[chunk][CHUNK_SIZE] == 0) {
2038                data[chunk] = null;
2039            }
2040        }
2041        return value;
2042    }
2043    private final String JavaDoc clearChunkValue(Object JavaDoc data[][],
2044                                         int chunk, int index) {
2045        String JavaDoc value = data[chunk] != null ? (String JavaDoc)data[chunk][index] : null;
2046        if (value != null) {
2047            data[chunk][index] = null;
2048            RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
2049            c.fCount--;
2050            if (c.fCount == 0) {
2051                data[chunk] = null;
2052            }
2053        }
2054        return value;
2055    }
2056
2057    /**
2058     * This version of putIdentifier is needed to avoid fluffing
2059     * all of the paths to ID attributes when a node object is
2060     * created that contains an ID attribute.
2061     */

2062    private final void putIdentifier0(String JavaDoc idName, Element JavaDoc element) {
2063
2064        if (DEBUG_IDS) {
2065            System.out.println("putIdentifier0("+
2066                               idName+", "+
2067                               element+')');
2068        }
2069
2070        // create hashtable
2071
if (identifiers == null) {
2072            identifiers = new java.util.Hashtable JavaDoc();
2073        }
2074
2075        // save ID and its associated element
2076
identifiers.put(idName, element);
2077
2078    } // putIdentifier0(String,Element)
2079

2080    /** Prints the ID array. */
2081    private static void print(int values[], int start, int end,
2082                              int middle, int target) {
2083
2084        if (DEBUG_IDS) {
2085            System.out.print(start);
2086            System.out.print(" [");
2087            for (int i = start; i < end; i++) {
2088                if (middle == i) {
2089                    System.out.print("!");
2090                }
2091                System.out.print(values[i]);
2092                if (values[i] == target) {
2093                    System.out.print("*");
2094                }
2095                if (i < end - 1) {
2096                    System.out.print(" ");
2097                }
2098            }
2099            System.out.println("] "+end);
2100        }
2101
2102    } // print(int[],int,int,int,int)
2103

2104    //
2105
// Classes
2106
//
2107

2108    /**
2109     * A simple integer vector.
2110     */

2111    static class IntVector {
2112
2113        //
2114
// Data
2115
//
2116

2117        /** Data. */
2118        private int data[];
2119
2120        /** Size. */
2121        private int size;
2122
2123        //
2124
// Public methods
2125
//
2126

2127        /** Returns the length of this vector. */
2128        public int size() {
2129            return size;
2130        }
2131
2132        /** Returns the element at the specified index. */
2133        public int elementAt(int index) {
2134            return data[index];
2135        }
2136
2137        /** Appends an element to the end of the vector. */
2138        public void addElement(int element) {
2139            ensureCapacity(size + 1);
2140            data[size++] = element;
2141        }
2142
2143        /** Clears the vector. */
2144        public void removeAllElements() {
2145            size = 0;
2146        }
2147
2148        //
2149
// Private methods
2150
//
2151

2152        /** Makes sure that there is enough storage. */
2153        private void ensureCapacity(int newsize) {
2154
2155            if (data == null) {
2156                data = new int[newsize + 15];
2157            }
2158            else if (newsize > data.length) {
2159                int newdata[] = new int[newsize + 15];
2160                System.arraycopy(data, 0, newdata, 0, data.length);
2161                data = newdata;
2162            }
2163
2164        } // ensureCapacity(int)
2165

2166    } // class IntVector
2167

2168} // class DeferredDocumentImpl
2169
Popular Tags