KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > dom > DeferredDocumentImpl


1 /*
2  * Copyright 1999-2002,2004,2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.dom;
18
19 import org.w3c.dom.DOMImplementation JavaDoc;
20 import org.w3c.dom.Element JavaDoc;
21 import org.w3c.dom.Node JavaDoc;
22
23 import java.util.Vector JavaDoc;
24
25 /**
26  * The Document interface represents the entire HTML or XML document.
27  * Conceptually, it is the root of the document tree, and provides the
28  * primary access to the document's data.
29  * <P>
30  * Since elements, text nodes, comments, processing instructions,
31  * etc. cannot exist outside the context of a Document, the Document
32  * interface also contains the factory methods needed to create these
33  * objects. The Node objects created have a ownerDocument attribute
34  * which associates them with the Document within whose context they
35  * were created.
36  *
37  * @xerces.internal
38  *
39  * @version $Id: DeferredDocumentImpl.java,v 1.58 2005/03/07 23:28:40 mrglavas Exp $
40  * @since PR-DOM-Level-1-19980818.
41  */

42 public class DeferredDocumentImpl
43     extends DocumentImpl
44     implements DeferredNode {
45
46     //
47
// Constants
48
//
49

50     /** Serialization version. */
51     static final long serialVersionUID = 5186323580749626857L;
52
53     // debugging
54

55     /** To include code for printing the ref count tables. */
56     private static final boolean DEBUG_PRINT_REF_COUNTS = false;
57
58     /** To include code for printing the internal tables. */
59     private static final boolean DEBUG_PRINT_TABLES = false;
60
61     /** To debug identifiers set to true and recompile. */
62     private static final boolean DEBUG_IDS = false;
63
64     // protected
65

66     /** Chunk shift. */
67     protected static final int CHUNK_SHIFT = 11; // 2^11 = 2k
68

69     /** Chunk size. */
70     protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
71
72     /** Chunk mask. */
73     protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
74
75     /** Initial chunk size. */
76     protected static final int INITIAL_CHUNK_COUNT = (1 << (16 - CHUNK_SHIFT)); // 2^16 = 64k
77

78     //
79
// Data
80
//
81

82     // lazy-eval information
83
// To maximize memory consumption the actual semantic of these fields vary
84
// depending on the node type.
85

86     /** Node count. */
87     protected transient int fNodeCount = 0;
88
89     /** Node types. */
90     protected transient int fNodeType[][];
91
92     /** Node names. */
93     protected transient Object JavaDoc fNodeName[][];
94
95     /** Node values. */
96     protected transient Object JavaDoc fNodeValue[][];
97
98     /** Node parents. */
99     protected transient int fNodeParent[][];
100
101     /** Node first children. */
102     protected transient int fNodeLastChild[][];
103
104     /** Node prev siblings. */
105     protected transient int fNodePrevSib[][];
106
107     /** Node namespace URI. */
108     protected transient Object JavaDoc fNodeURI[][];
109
110     /** Extra data. */
111     protected transient int fNodeExtra[][];
112
113     /** Identifier count. */
114     protected transient int fIdCount;
115
116     /** Identifier name indexes. */
117     protected transient String JavaDoc fIdName[];
118
119     /** Identifier element indexes. */
120     protected transient int fIdElement[];
121
122     /** DOM2: For namespace support in the deferred case.
123      */

124     // Implementation Note: The deferred element and attribute must know how to
125
// interpret the int representing the qname.
126
protected boolean fNamespacesEnabled = false;
127     
128     //
129
// private data
130
//
131
private transient final StringBuffer JavaDoc fBufferStr = new StringBuffer JavaDoc();
132     private transient final Vector JavaDoc fStrChunks = new Vector JavaDoc();
133
134     //
135
// Constructors
136
//
137

138     /**
139      * NON-DOM: Actually creating a Document is outside the DOM's spec,
140      * since it has to operate in terms of a particular implementation.
141      */

142     public DeferredDocumentImpl() {
143         this(false);
144     } // <init>()
145

146     /**
147      * NON-DOM: Actually creating a Document is outside the DOM's spec,
148      * since it has to operate in terms of a particular implementation.
149      */

150     public DeferredDocumentImpl(boolean namespacesEnabled) {
151         this(namespacesEnabled, false);
152     } // <init>(boolean)
153

154     /** Experimental constructor. */
155     public DeferredDocumentImpl(boolean namespaces, boolean grammarAccess) {
156         super(grammarAccess);
157
158         needsSyncData(true);
159         needsSyncChildren(true);
160
161         fNamespacesEnabled = namespaces;
162
163     } // <init>(boolean,boolean)
164

165     //
166
// Public methods
167
//
168

169     /**
170      * Retrieve information describing the abilities of this particular
171      * DOM implementation. Intended to support applications that may be
172      * using DOMs retrieved from several different sources, potentially
173      * with different underlying representations.
174      */

175     public DOMImplementation JavaDoc getImplementation() {
176         // Currently implemented as a singleton, since it's hardcoded
177
// information anyway.
178
return DeferredDOMImplementationImpl.getDOMImplementation();
179     }
180     
181     /** Returns the cached parser.getNamespaces() value.*/
182     boolean getNamespacesEnabled() {
183         return fNamespacesEnabled;
184     }
185
186     void setNamespacesEnabled(boolean enable) {
187         fNamespacesEnabled = enable;
188     }
189
190     // internal factory methods
191

192     /** Creates a document node in the table. */
193     public int createDeferredDocument() {
194         int nodeIndex = createNode(Node.DOCUMENT_NODE);
195         return nodeIndex;
196     }
197
198     /** Creates a doctype. */
199     public int createDeferredDocumentType(String JavaDoc rootElementName,
200                                           String JavaDoc publicId, String JavaDoc systemId) {
201
202         // create node
203
int nodeIndex = createNode(Node.DOCUMENT_TYPE_NODE);
204         int chunk = nodeIndex >> CHUNK_SHIFT;
205         int index = nodeIndex & CHUNK_MASK;
206
207         // save name, public id, system id
208
setChunkValue(fNodeName, rootElementName, chunk, index);
209         setChunkValue(fNodeValue, publicId, chunk, index);
210         setChunkValue(fNodeURI, systemId, chunk, index);
211
212         // return node index
213
return nodeIndex;
214
215     } // createDeferredDocumentType(String,String,String):int
216

217     public void setInternalSubset(int doctypeIndex, String JavaDoc subset) {
218         int chunk = doctypeIndex >> CHUNK_SHIFT;
219         int index = doctypeIndex & CHUNK_MASK;
220
221         // create extra data node to store internal subset
222
int extraDataIndex = createNode(Node.DOCUMENT_TYPE_NODE);
223         int echunk = extraDataIndex >> CHUNK_SHIFT;
224         int eindex = extraDataIndex & CHUNK_MASK;
225         setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
226         setChunkValue(fNodeValue, subset, echunk, eindex);
227     }
228
229     /** Creates a notation in the table. */
230     public int createDeferredNotation(String JavaDoc notationName,
231                                       String JavaDoc publicId, String JavaDoc systemId, String JavaDoc baseURI) {
232
233         // create node
234
int nodeIndex = createNode(Node.NOTATION_NODE);
235         int chunk = nodeIndex >> CHUNK_SHIFT;
236         int index = nodeIndex & CHUNK_MASK;
237
238
239         // create extra data node
240
int extraDataIndex = createNode(Node.NOTATION_NODE);
241         int echunk = extraDataIndex >> CHUNK_SHIFT;
242         int eindex = extraDataIndex & CHUNK_MASK;
243
244         // save name, public id, system id, and notation name
245
setChunkValue(fNodeName, notationName, chunk, index);
246         setChunkValue(fNodeValue, publicId, chunk, index);
247         setChunkValue(fNodeURI, systemId, chunk, index);
248
249         // in extra data node set baseURI value
250
setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
251         setChunkValue(fNodeName, baseURI, echunk, eindex);
252
253         // return node index
254
return nodeIndex;
255
256     } // createDeferredNotation(String,String,String):int
257

258     /** Creates an entity in the table. */
259     public int createDeferredEntity(String JavaDoc entityName, String JavaDoc publicId,
260                                     String JavaDoc systemId, String JavaDoc notationName,
261                                     String JavaDoc baseURI) {
262         // create node
263
int nodeIndex = createNode(Node.ENTITY_NODE);
264         int chunk = nodeIndex >> CHUNK_SHIFT;
265         int index = nodeIndex & CHUNK_MASK;
266
267         // create extra data node
268
int extraDataIndex = createNode(Node.ENTITY_NODE);
269         int echunk = extraDataIndex >> CHUNK_SHIFT;
270         int eindex = extraDataIndex & CHUNK_MASK;
271
272         // save name, public id, system id, and notation name
273
setChunkValue(fNodeName, entityName, chunk, index);
274         setChunkValue(fNodeValue, publicId, chunk, index);
275         setChunkValue(fNodeURI, systemId, chunk, index);
276         setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
277         // set other values in the extra chunk
278
// notation
279
setChunkValue(fNodeName, notationName, echunk, eindex);
280         // version L3
281
setChunkValue(fNodeValue, null, echunk, eindex);
282         // encoding L3
283
setChunkValue(fNodeURI, null, echunk, eindex);
284
285
286         int extraDataIndex2 = createNode(Node.ENTITY_NODE);
287         int echunk2 = extraDataIndex2 >> CHUNK_SHIFT;
288         int eindex2 = extraDataIndex2 & CHUNK_MASK;
289
290         setChunkIndex(fNodeExtra, extraDataIndex2, echunk, eindex);
291
292         // baseURI
293
setChunkValue(fNodeName, baseURI, echunk2, eindex2);
294
295         // return node index
296
return nodeIndex;
297
298     } // createDeferredEntity(String,String,String,String):int
299

300     public String JavaDoc getDeferredEntityBaseURI (int entityIndex){
301         if (entityIndex != -1) {
302             int extraDataIndex = getNodeExtra(entityIndex, false);
303             extraDataIndex = getNodeExtra(extraDataIndex, false);
304             return getNodeName (extraDataIndex, false);
305         }
306         return null;
307     }
308
309     // DOM Level 3: setting encoding and version
310
public void setEntityInfo(int currentEntityDecl,
311                               String JavaDoc version, String JavaDoc encoding){
312         int eNodeIndex = getNodeExtra(currentEntityDecl, false);
313         if (eNodeIndex !=-1) {
314             int echunk = eNodeIndex >> CHUNK_SHIFT;
315             int eindex = eNodeIndex & CHUNK_MASK;
316             setChunkValue(fNodeValue, version, echunk, eindex);
317             setChunkValue(fNodeURI, encoding, echunk, eindex);
318         }
319     }
320
321
322     /**
323      * DOM Internal
324      *
325      * An attribute specifying the actual encoding of this document. This is
326      * <code>null</code> otherwise.
327      * <br> This attribute represents the property [character encoding scheme]
328      * defined in .
329      */

330     public void setInputEncoding(int currentEntityDecl, String JavaDoc value){
331         // get first extra data chunk
332
int nodeIndex = getNodeExtra(currentEntityDecl, false);
333         // get second extra data chunk
334
int extraDataIndex = getNodeExtra(nodeIndex, false);
335
336         int echunk = extraDataIndex >> CHUNK_SHIFT;
337         int eindex = extraDataIndex & CHUNK_MASK;
338         
339         setChunkValue(fNodeValue, value, echunk, eindex);
340         
341     }
342
343     /** Creates an entity reference node in the table. */
344     public int createDeferredEntityReference(String JavaDoc name, String JavaDoc baseURI) {
345
346         // create node
347
int nodeIndex = createNode(Node.ENTITY_REFERENCE_NODE);
348         int chunk = nodeIndex >> CHUNK_SHIFT;
349         int index = nodeIndex & CHUNK_MASK;
350         setChunkValue(fNodeName, name, chunk, index);
351         setChunkValue(fNodeValue, baseURI, chunk, index);
352
353         // return node index
354
return nodeIndex;
355
356     } // createDeferredEntityReference(String):int
357

358
359     /** Creates an element node with a URI in the table and type information. */
360     public int createDeferredElement(String JavaDoc elementURI, String JavaDoc elementName,
361                                       Object JavaDoc type) {
362
363         // create node
364
int elementNodeIndex = createNode(Node.ELEMENT_NODE);
365         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
366         int elementIndex = elementNodeIndex & CHUNK_MASK;
367         setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
368         setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
369         setChunkValue(fNodeValue, type, elementChunk, elementIndex);
370  
371         // return node index
372
return elementNodeIndex;
373
374     } // createDeferredElement(String,String):int
375

376     /** @deprecated. Creates an element node in the table. */
377     public int createDeferredElement(String JavaDoc elementName) {
378         return createDeferredElement(null, elementName);
379     }
380
381     /** @deprecated. Creates an element node with a URI in the table. */
382     public int createDeferredElement(String JavaDoc elementURI, String JavaDoc elementName) {
383
384         // create node
385
int elementNodeIndex = createNode(Node.ELEMENT_NODE);
386         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
387         int elementIndex = elementNodeIndex & CHUNK_MASK;
388         setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
389         setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
390  
391         // return node index
392
return elementNodeIndex;
393
394     } // createDeferredElement(String,String):int
395

396     
397     /**
398      * This method is used by the DOMParser to create attributes.
399      * @param elementNodeIndex
400      * @param attrName
401      * @param attrURI
402      * @param attrValue
403      * @param specified
404      * @param id
405      * @param type
406      * @return int
407      */

408     public int setDeferredAttribute(int elementNodeIndex,
409                                 String JavaDoc attrName,
410                                 String JavaDoc attrURI,
411                                 String JavaDoc attrValue,
412                                 boolean specified,
413                                 boolean id,
414                                 Object JavaDoc type) {
415                                     
416         // create attribute
417
int attrNodeIndex = createDeferredAttribute(attrName, attrURI, attrValue, specified);
418         int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
419         int attrIndex = attrNodeIndex & CHUNK_MASK;
420         // set attribute's parent to element
421
setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
422
423         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
424         int elementIndex = elementNodeIndex & CHUNK_MASK;
425
426         // get element's last attribute
427
int lastAttrNodeIndex = getChunkIndex(fNodeExtra, elementChunk, elementIndex);
428         if (lastAttrNodeIndex != 0) {
429             int lastAttrChunk = lastAttrNodeIndex >> CHUNK_SHIFT;
430             int lastAttrIndex = lastAttrNodeIndex & CHUNK_MASK;
431             // add link from new attribute to last attribute
432
setChunkIndex(fNodePrevSib, lastAttrNodeIndex, attrChunk, attrIndex);
433         }
434         // add link from element to new last attribute
435
setChunkIndex(fNodeExtra, attrNodeIndex, elementChunk, elementIndex);
436
437         int extra = getChunkIndex(fNodeExtra, attrChunk, attrIndex);
438         if (id) {
439             extra = extra | ID;
440             setChunkIndex(fNodeExtra, extra, attrChunk, attrIndex);
441             String JavaDoc value = getChunkValue(fNodeValue, attrChunk, attrIndex);
442             putIdentifier(value, elementNodeIndex);
443         }
444         // store type information
445
if (type != null) {
446             int extraDataIndex = createNode(DeferredNode.TYPE_NODE);
447             int echunk = extraDataIndex >> CHUNK_SHIFT;
448             int eindex = extraDataIndex & CHUNK_MASK;
449
450             setChunkIndex(fNodeLastChild, extraDataIndex, attrChunk, attrIndex);
451             setChunkValue(fNodeValue, type, echunk, eindex);
452         }
453
454         // return node index
455
return attrNodeIndex;
456     }
457     
458     /** @deprecated. Sets an attribute on an element node.*/
459     public int setDeferredAttribute(int elementNodeIndex,
460                                     String JavaDoc attrName, String JavaDoc attrURI,
461                                     String JavaDoc attrValue, boolean specified) {
462         // create attribute
463
int attrNodeIndex = createDeferredAttribute(attrName, attrURI,
464                                                     attrValue, specified);
465         int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
466         int attrIndex = attrNodeIndex & CHUNK_MASK;
467         // set attribute's parent to element
468
setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
469
470         int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
471         int elementIndex = elementNodeIndex & CHUNK_MASK;
472
473         // get element's last attribute
474
int lastAttrNodeIndex = getChunkIndex(fNodeExtra,
475                                               elementChunk, elementIndex);
476         if (lastAttrNodeIndex != 0) {
477             // add link from new attribute to last attribute
478
setChunkIndex(fNodePrevSib, lastAttrNodeIndex,
479                           attrChunk, attrIndex);
480         }
481         // add link from element to new last attribute
482
setChunkIndex(fNodeExtra, attrNodeIndex,
483                       elementChunk, elementIndex);
484  
485         // return node index
486
return attrNodeIndex;
487
488     } // setDeferredAttribute(int,String,String,String,boolean):int
489

490     /** Creates an attribute in the table. */
491     public int createDeferredAttribute(String JavaDoc attrName, String JavaDoc attrValue,
492                                        boolean specified) {
493         return createDeferredAttribute(attrName, null, attrValue, specified);
494     }
495
496     /** Creates an attribute with a URI in the table. */
497     public int createDeferredAttribute(String JavaDoc attrName, String JavaDoc attrURI,
498                                        String JavaDoc attrValue, boolean specified) {
499
500         // create node
501
int nodeIndex = createNode(NodeImpl.ATTRIBUTE_NODE);
502         int chunk = nodeIndex >> CHUNK_SHIFT;
503         int index = nodeIndex & CHUNK_MASK;
504         setChunkValue(fNodeName, attrName, chunk, index);
505         setChunkValue(fNodeURI, attrURI, chunk, index);
506         setChunkValue(fNodeValue, attrValue, chunk, index);
507         int extra = specified ? SPECIFIED : 0;
508         setChunkIndex(fNodeExtra, extra, chunk, index);
509
510         // return node index
511
return nodeIndex;
512
513     } // createDeferredAttribute(String,String,String,boolean):int
514

515     /** Creates an element definition in the table.*/
516     public int createDeferredElementDefinition(String JavaDoc elementName) {
517
518         // create node
519
int nodeIndex = createNode(NodeImpl.ELEMENT_DEFINITION_NODE);
520         int chunk = nodeIndex >> CHUNK_SHIFT;
521         int index = nodeIndex & CHUNK_MASK;
522         setChunkValue(fNodeName, elementName, chunk, index);
523
524         // return node index
525
return nodeIndex;
526
527     } // createDeferredElementDefinition(String):int
528

529     /** Creates a text node in the table. */
530     public int createDeferredTextNode(String JavaDoc data,
531                                       boolean ignorableWhitespace) {
532
533         // create node
534
int nodeIndex = createNode(Node.TEXT_NODE);
535         int chunk = nodeIndex >> CHUNK_SHIFT;
536         int index = nodeIndex & CHUNK_MASK;
537         setChunkValue(fNodeValue, data, chunk, index);
538         // use extra to store ignorableWhitespace info
539
setChunkIndex(fNodeExtra, ignorableWhitespace ? 1 : 0, chunk, index);
540
541         // return node index
542
return nodeIndex;
543
544     } // createDeferredTextNode(String,boolean):int
545

546     /** Creates a CDATA section node in the table. */
547     public int createDeferredCDATASection(String JavaDoc data) {
548
549         // create node
550
int nodeIndex = createNode(Node.CDATA_SECTION_NODE);
551         int chunk = nodeIndex >> CHUNK_SHIFT;
552         int index = nodeIndex & CHUNK_MASK;
553         setChunkValue(fNodeValue, data, chunk, index);
554
555         // return node index
556
return nodeIndex;
557
558     } // createDeferredCDATASection(String):int
559

560     /** Creates a processing instruction node in the table. */
561     public int createDeferredProcessingInstruction(String JavaDoc target,
562                                                    String JavaDoc data) {
563         // create node
564
int nodeIndex = createNode(Node.PROCESSING_INSTRUCTION_NODE);
565         int chunk = nodeIndex >> CHUNK_SHIFT;
566         int index = nodeIndex & CHUNK_MASK;
567         setChunkValue(fNodeName, target, chunk, index);
568         setChunkValue(fNodeValue, data, chunk, index);
569         // return node index
570
return nodeIndex;
571
572     } // createDeferredProcessingInstruction(String,String):int
573

574     /** Creates a comment node in the table. */
575     public int createDeferredComment(String JavaDoc data) {
576
577         // create node
578
int nodeIndex = createNode(Node.COMMENT_NODE);
579         int chunk = nodeIndex >> CHUNK_SHIFT;
580         int index = nodeIndex & CHUNK_MASK;
581         setChunkValue(fNodeValue, data, chunk, index);
582
583         // return node index
584
return nodeIndex;
585
586     } // createDeferredComment(String):int
587

588     /** Creates a clone of the specified node. */
589     public int cloneNode(int nodeIndex, boolean deep) {
590
591         // clone immediate node
592

593         int nchunk = nodeIndex >> CHUNK_SHIFT;
594         int nindex = nodeIndex & CHUNK_MASK;
595         int nodeType = fNodeType[nchunk][nindex];
596         int cloneIndex = createNode((short)nodeType);
597         int cchunk = cloneIndex >> CHUNK_SHIFT;
598         int cindex = cloneIndex & CHUNK_MASK;
599         setChunkValue(fNodeName, fNodeName[nchunk][nindex], cchunk, cindex);
600         setChunkValue(fNodeValue, fNodeValue[nchunk][nindex], cchunk, cindex);
601         setChunkValue(fNodeURI, fNodeURI[nchunk][nindex], cchunk, cindex);
602         int extraIndex = fNodeExtra[nchunk][nindex];
603         if (extraIndex != -1) {
604             if (nodeType != Node.ATTRIBUTE_NODE && nodeType != Node.TEXT_NODE) {
605                 extraIndex = cloneNode(extraIndex, false);
606             }
607             setChunkIndex(fNodeExtra, extraIndex, cchunk, cindex);
608         }
609
610         // clone and attach children
611
if (deep) {
612             int prevIndex = -1;
613             int childIndex = getLastChild(nodeIndex, false);
614             while (childIndex != -1) {
615                 int clonedChildIndex = cloneNode(childIndex, deep);
616                 insertBefore(cloneIndex, clonedChildIndex, prevIndex);
617                 prevIndex = clonedChildIndex;
618                 childIndex = getRealPrevSibling(childIndex, false);
619             }
620             
621
622         }
623         
624         // return cloned node index
625
return cloneIndex;
626
627     } // cloneNode(int,boolean):int
628

629     /** Appends a child to the specified parent in the table. */
630     public void appendChild(int parentIndex, int childIndex) {
631
632         // append parent index
633
int pchunk = parentIndex >> CHUNK_SHIFT;
634         int pindex = parentIndex & CHUNK_MASK;
635         int cchunk = childIndex >> CHUNK_SHIFT;
636         int cindex = childIndex & CHUNK_MASK;
637         setChunkIndex(fNodeParent, parentIndex, cchunk, cindex);
638
639         // set previous sibling of new child
640
int olast = getChunkIndex(fNodeLastChild, pchunk, pindex);
641         setChunkIndex(fNodePrevSib, olast, cchunk, cindex);
642
643         // update parent's last child
644
setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
645
646     } // appendChild(int,int)
647

648     /** Adds an attribute node to the specified element. */
649     public int setAttributeNode(int elemIndex, int attrIndex) {
650
651         int echunk = elemIndex >> CHUNK_SHIFT;
652         int eindex = elemIndex & CHUNK_MASK;
653         int achunk = attrIndex >> CHUNK_SHIFT;
654         int aindex = attrIndex & CHUNK_MASK;
655
656         // see if this attribute is already here
657
String JavaDoc attrName = getChunkValue(fNodeName, achunk, aindex);
658         int oldAttrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
659         int nextIndex = -1;
660         int oachunk = -1;
661         int oaindex = -1;
662         while (oldAttrIndex != -1) {
663             oachunk = oldAttrIndex >> CHUNK_SHIFT;
664             oaindex = oldAttrIndex & CHUNK_MASK;
665             String JavaDoc oldAttrName = getChunkValue(fNodeName, oachunk, oaindex);
666             if (oldAttrName.equals(attrName)) {
667                 break;
668             }
669             nextIndex = oldAttrIndex;
670             oldAttrIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
671         }
672
673         // remove old attribute
674
if (oldAttrIndex != -1) {
675
676             // patch links
677
int prevIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
678             if (nextIndex == -1) {
679                 setChunkIndex(fNodeExtra, prevIndex, echunk, eindex);
680             }
681             else {
682                 int pchunk = nextIndex >> CHUNK_SHIFT;
683                 int pindex = nextIndex & CHUNK_MASK;
684                 setChunkIndex(fNodePrevSib, prevIndex, pchunk, pindex);
685             }
686
687             // remove connections to siblings
688
clearChunkIndex(fNodeType, oachunk, oaindex);
689             clearChunkValue(fNodeName, oachunk, oaindex);
690             clearChunkValue(fNodeValue, oachunk, oaindex);
691             clearChunkIndex(fNodeParent, oachunk, oaindex);
692             clearChunkIndex(fNodePrevSib, oachunk, oaindex);
693             int attrTextIndex =
694                 clearChunkIndex(fNodeLastChild, oachunk, oaindex);
695             int atchunk = attrTextIndex >> CHUNK_SHIFT;
696             int atindex = attrTextIndex & CHUNK_MASK;
697             clearChunkIndex(fNodeType, atchunk, atindex);
698             clearChunkValue(fNodeValue, atchunk, atindex);
699             clearChunkIndex(fNodeParent, atchunk, atindex);
700             clearChunkIndex(fNodeLastChild, atchunk, atindex);
701         }
702
703         // add new attribute
704
int prevIndex = getChunkIndex(fNodeExtra, echunk, eindex);
705         setChunkIndex(fNodeExtra, attrIndex, echunk, eindex);
706         setChunkIndex(fNodePrevSib, prevIndex, achunk, aindex);
707
708         // return
709
return oldAttrIndex;
710
711     } // setAttributeNode(int,int):int
712

713
714     /** Adds an attribute node to the specified element. */
715     public void setIdAttributeNode(int elemIndex, int attrIndex) {
716
717         int chunk = attrIndex >> CHUNK_SHIFT;
718         int index = attrIndex & CHUNK_MASK;
719         int extra = getChunkIndex(fNodeExtra, chunk, index);
720         extra = extra | ID;
721         setChunkIndex(fNodeExtra, extra, chunk, index);
722
723         String JavaDoc value = getChunkValue(fNodeValue, chunk, index);
724         putIdentifier(value, elemIndex);
725     }
726
727
728     /** Sets type of attribute */
729     public void setIdAttribute(int attrIndex) {
730
731         int chunk = attrIndex >> CHUNK_SHIFT;
732         int index = attrIndex & CHUNK_MASK;
733         int extra = getChunkIndex(fNodeExtra, chunk, index);
734         extra = extra | ID;
735         setChunkIndex(fNodeExtra, extra, chunk, index);
736     }
737
738     /** Inserts a child before the specified node in the table. */
739     public int insertBefore(int parentIndex, int newChildIndex, int refChildIndex) {
740
741         if (refChildIndex == -1) {
742             appendChild(parentIndex, newChildIndex);
743             return newChildIndex;
744         }
745
746         int nchunk = newChildIndex >> CHUNK_SHIFT;
747         int nindex = newChildIndex & CHUNK_MASK;
748         int rchunk = refChildIndex >> CHUNK_SHIFT;
749         int rindex = refChildIndex & CHUNK_MASK;
750         int previousIndex = getChunkIndex(fNodePrevSib, rchunk, rindex);
751         setChunkIndex(fNodePrevSib, newChildIndex, rchunk, rindex);
752         setChunkIndex(fNodePrevSib, previousIndex, nchunk, nindex);
753
754         return newChildIndex;
755
756     } // insertBefore(int,int,int):int
757

758     /** Sets the last child of the parentIndex to childIndex. */
759     public void setAsLastChild(int parentIndex, int childIndex) {
760         int pchunk = parentIndex >> CHUNK_SHIFT;
761         int pindex = parentIndex & CHUNK_MASK;
762         setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
763     } // setAsLastChild(int,int)
764

765     /**
766      * Returns the parent node of the given node.
767      * <em>Calling this method does not free the parent index.</em>
768      */

769     public int getParentNode(int nodeIndex) {
770         return getParentNode(nodeIndex, false);
771     }
772
773     /**
774      * Returns the parent node of the given node.
775      * @param free True to free parent node.
776      */

777     public int getParentNode(int nodeIndex, boolean free) {
778
779         if (nodeIndex == -1) {
780             return -1;
781         }
782
783         int chunk = nodeIndex >> CHUNK_SHIFT;
784         int index = nodeIndex & CHUNK_MASK;
785         return free ? clearChunkIndex(fNodeParent, chunk, index)
786                     : getChunkIndex(fNodeParent, chunk, index);
787
788     } // getParentNode(int):int
789

790     /** Returns the last child of the given node. */
791     public int getLastChild(int nodeIndex) {
792         return getLastChild(nodeIndex, true);
793     }
794
795     /**
796      * Returns the last child of the given node.
797      * @param free True to free child index.
798      */

799     public int getLastChild(int nodeIndex, boolean free) {
800
801         if (nodeIndex == -1) {
802             return -1;
803         }
804
805         int chunk = nodeIndex >> CHUNK_SHIFT;
806         int index = nodeIndex & CHUNK_MASK;
807         return free ? clearChunkIndex(fNodeLastChild, chunk, index)
808                     : getChunkIndex(fNodeLastChild, chunk, index);
809
810     } // getLastChild(int,boolean):int
811

812     /**
813      * Returns the prev sibling of the given node.
814      * This is post-normalization of Text Nodes.
815      */

816     public int getPrevSibling(int nodeIndex) {
817         return getPrevSibling(nodeIndex, true);
818     }
819
820     /**
821      * Returns the prev sibling of the given node.
822      * @param free True to free sibling index.
823      */

824     public int getPrevSibling(int nodeIndex, boolean free) {
825
826         if (nodeIndex == -1) {
827             return -1;
828         }
829
830         int chunk = nodeIndex >> CHUNK_SHIFT;
831         int index = nodeIndex & CHUNK_MASK;
832         int type = getChunkIndex(fNodeType, chunk, index);
833         if (type == Node.TEXT_NODE) {
834             do {
835                 nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
836                 if (nodeIndex == -1) {
837                     break;
838                 }
839                 chunk = nodeIndex >> CHUNK_SHIFT;
840                 index = nodeIndex & CHUNK_MASK;
841                 type = getChunkIndex(fNodeType, chunk, index);
842             } while (type == Node.TEXT_NODE);
843         }
844         else {
845             nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
846         }
847
848         return nodeIndex;
849
850     } // getPrevSibling(int,boolean):int
851

852     /**
853      * Returns the <i>real</i> prev sibling of the given node,
854      * directly from the data structures. Used by TextImpl#getNodeValue()
855      * to normalize values.
856      */

857     public int getRealPrevSibling(int nodeIndex) {
858         return getRealPrevSibling(nodeIndex, true);
859     }
860
861     /**
862      * Returns the <i>real</i> prev sibling of the given node.
863      * @param free True to free sibling index.
864      */

865     public int getRealPrevSibling(int nodeIndex, boolean free) {
866
867         if (nodeIndex == -1) {
868             return -1;
869         }
870
871         int chunk = nodeIndex >> CHUNK_SHIFT;
872         int index = nodeIndex & CHUNK_MASK;
873         return free ? clearChunkIndex(fNodePrevSib, chunk, index)
874                     : getChunkIndex(fNodePrevSib, chunk, index);
875
876     } // getReadPrevSibling(int,boolean):int
877

878     /**
879      * Returns the index of the element definition in the table
880      * with the specified name index, or -1 if no such definition
881      * exists.
882      */

883     public int lookupElementDefinition(String JavaDoc elementName) {
884
885         if (fNodeCount > 1) {
886
887             // find doctype
888
int docTypeIndex = -1;
889             int nchunk = 0;
890             int nindex = 0;
891             for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
892                  index != -1;
893                  index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {
894
895                 nchunk = index >> CHUNK_SHIFT;
896                 nindex = index & CHUNK_MASK;
897                 if (getChunkIndex(fNodeType, nchunk, nindex) == Node.DOCUMENT_TYPE_NODE) {
898                     docTypeIndex = index;
899                     break;
900                 }
901             }
902
903             // find element definition
904
if (docTypeIndex == -1) {
905                 return -1;
906             }
907             nchunk = docTypeIndex >> CHUNK_SHIFT;
908             nindex = docTypeIndex & CHUNK_MASK;
909             for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
910                  index != -1;
911                  index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {
912
913                 nchunk = index >> CHUNK_SHIFT;
914                 nindex = index & CHUNK_MASK;
915                 if (getChunkIndex(fNodeType, nchunk, nindex) ==
916                                            NodeImpl.ELEMENT_DEFINITION_NODE
917                  && getChunkValue(fNodeName, nchunk, nindex) == elementName) {
918                     return index;
919                 }
920             }
921         }
922
923         return -1;
924
925     } // lookupElementDefinition(String):int
926

927     /** Instantiates the requested node object. */
928     public DeferredNode getNodeObject(int nodeIndex) {
929
930         // is there anything to do?
931
if (nodeIndex == -1) {
932             return null;
933         }
934
935         // get node type
936
int chunk = nodeIndex >> CHUNK_SHIFT;
937         int index = nodeIndex & CHUNK_MASK;
938         int type = getChunkIndex(fNodeType, chunk, index);
939         if (type != Node.TEXT_NODE && type != Node.CDATA_SECTION_NODE) {
940             clearChunkIndex(fNodeType, chunk, index);
941         }
942
943         // create new node
944
DeferredNode node = null;
945         switch (type) {
946
947             //
948
// Standard DOM node types
949
//
950

951             case Node.ATTRIBUTE_NODE: {
952                 if (fNamespacesEnabled) {
953                     node = new DeferredAttrNSImpl(this, nodeIndex);
954                 } else {
955                     node = new DeferredAttrImpl(this, nodeIndex);
956                 }
957                 break;
958             }
959
960             case Node.CDATA_SECTION_NODE: {
961                 node = new DeferredCDATASectionImpl(this, nodeIndex);
962                 break;
963             }
964
965             case Node.COMMENT_NODE: {
966                 node = new DeferredCommentImpl(this, nodeIndex);
967                 break;
968             }
969
970             // NOTE: Document fragments can never be "fast".
971
//
972
// The parser will never ask to create a document
973
// fragment during the parse. Document fragments
974
// are used by the application *after* the parse.
975
//
976
// case Node.DOCUMENT_FRAGMENT_NODE: { break; }
977
case Node.DOCUMENT_NODE: {
978                 // this node is never "fast"
979
node = this;
980                 break;
981             }
982
983             case Node.DOCUMENT_TYPE_NODE: {
984                 node = new DeferredDocumentTypeImpl(this, nodeIndex);
985                 // save the doctype node
986
docType = (DocumentTypeImpl)node;
987                 break;
988             }
989
990             case Node.ELEMENT_NODE: {
991
992                 if (DEBUG_IDS) {
993                     System.out.println("getNodeObject(ELEMENT_NODE): "+nodeIndex);
994                 }
995
996                 // create node
997
if (fNamespacesEnabled) {
998                     node = new DeferredElementNSImpl(this, nodeIndex);
999                 } else {
1000                    node = new DeferredElementImpl(this, nodeIndex);
1001                }
1002
1003                // save the document element node
1004
if (docElement == null) {
1005                    docElement = (ElementImpl)node;
1006                }
1007
1008                // check to see if this element needs to be
1009
// registered for its ID attributes
1010
if (fIdElement != null) {
1011                    int idIndex = binarySearch(fIdElement, 0,
1012                                               fIdCount-1, nodeIndex);
1013                    while (idIndex != -1) {
1014
1015                        if (DEBUG_IDS) {
1016                            System.out.println(" id index: "+idIndex);
1017                            System.out.println(" fIdName["+idIndex+
1018                                               "]: "+fIdName[idIndex]);
1019                        }
1020
1021                        // register ID
1022
String JavaDoc name = fIdName[idIndex];
1023                        if (name != null) {
1024                            if (DEBUG_IDS) {
1025                                System.out.println(" name: "+name);
1026                                System.out.print("getNodeObject()#");
1027                            }
1028                            putIdentifier0(name, (Element JavaDoc)node);
1029                            fIdName[idIndex] = null;
1030                        }
1031
1032                        // continue if there are more IDs for
1033
// this element
1034
if (idIndex + 1 < fIdCount &&
1035                            fIdElement[idIndex + 1] == nodeIndex) {
1036                            idIndex++;
1037                        }
1038                        else {
1039                            idIndex = -1;
1040                        }
1041                    }
1042                }
1043                break;
1044            }
1045
1046            case Node.ENTITY_NODE: {
1047                node = new DeferredEntityImpl(this, nodeIndex);
1048                break;
1049            }
1050
1051            case Node.ENTITY_REFERENCE_NODE: {
1052                node = new DeferredEntityReferenceImpl(this, nodeIndex);
1053                break;
1054            }
1055
1056            case Node.NOTATION_NODE: {
1057                node = new DeferredNotationImpl(this, nodeIndex);
1058                break;
1059            }
1060
1061            case Node.PROCESSING_INSTRUCTION_NODE: {
1062                node = new DeferredProcessingInstructionImpl(this, nodeIndex);
1063                break;
1064            }
1065
1066            case Node.TEXT_NODE: {
1067                node = new DeferredTextImpl(this, nodeIndex);
1068                break;
1069            }
1070
1071            //
1072
// non-standard DOM node types
1073
//
1074

1075            case NodeImpl.ELEMENT_DEFINITION_NODE: {
1076                node = new DeferredElementDefinitionImpl(this, nodeIndex);
1077                break;
1078            }
1079
1080            default: {
1081                throw new IllegalArgumentException JavaDoc("type: "+type);
1082            }
1083
1084        } // switch node type
1085

1086        // store and return
1087
if (node != null) {
1088            return node;
1089        }
1090
1091        // error
1092
throw new IllegalArgumentException JavaDoc();
1093
1094    } // createNodeObject(int):Node
1095

1096    /** Returns the name of the given node. */
1097    public String JavaDoc getNodeName(int nodeIndex) {
1098        return getNodeName(nodeIndex, true);
1099    } // getNodeNameString(int):String
1100

1101    /**
1102     * Returns the name of the given node.
1103     * @param free True to free the string index.
1104     */

1105    public String JavaDoc getNodeName(int nodeIndex, boolean free) {
1106
1107        if (nodeIndex == -1) {
1108            return null;
1109        }
1110
1111        int chunk = nodeIndex >> CHUNK_SHIFT;
1112        int index = nodeIndex & CHUNK_MASK;
1113        return free ? clearChunkValue(fNodeName, chunk, index)
1114                    : getChunkValue(fNodeName, chunk, index);
1115
1116    } // getNodeName(int,boolean):String
1117

1118    /** Returns the real value of the given node. */
1119    public String JavaDoc getNodeValueString(int nodeIndex) {
1120        return getNodeValueString(nodeIndex, true);
1121    } // getNodeValueString(int):String
1122

1123    /**
1124     * Returns the real value of the given node.
1125     * @param free True to free the string index.
1126     */

1127    public String JavaDoc getNodeValueString(int nodeIndex, boolean free) {
1128
1129        if (nodeIndex == -1) {
1130            return null;
1131        }
1132        
1133        int chunk = nodeIndex >> CHUNK_SHIFT;
1134        int index = nodeIndex & CHUNK_MASK;
1135        String JavaDoc value = free ? clearChunkValue(fNodeValue, chunk, index)
1136                            : getChunkValue(fNodeValue, chunk, index);
1137        if (value == null) {
1138            return null;
1139        }
1140        
1141        int type = getChunkIndex(fNodeType, chunk, index);
1142        if (type == Node.TEXT_NODE) {
1143            int prevSib = getRealPrevSibling(nodeIndex);
1144            if (prevSib != -1 &&
1145                getNodeType(prevSib, false) == Node.TEXT_NODE) {
1146                // append data that is stored in fNodeValue
1147
// REVISIT: for text nodes it works differently than for CDATA
1148
// nodes.
1149
fStrChunks.addElement(value);
1150                do {
1151                    // go in reverse order: find last child, then
1152
// its previous sibling, etc
1153
chunk = prevSib >> CHUNK_SHIFT;
1154                    index = prevSib & CHUNK_MASK;
1155                    value = getChunkValue(fNodeValue, chunk, index);
1156                    fStrChunks.addElement(value);
1157                    prevSib = getChunkIndex(fNodePrevSib, chunk, index);
1158                    if (prevSib == -1) {
1159                        break;
1160                    }
1161                } while (getNodeType(prevSib, false) == Node.TEXT_NODE);
1162                
1163                int chunkCount = fStrChunks.size();
1164
1165                // add to the buffer in the correct order.
1166
for (int i = chunkCount - 1; i >= 0; i--) {
1167                    fBufferStr.append((String JavaDoc)fStrChunks.elementAt(i));
1168                }
1169                
1170                value = fBufferStr.toString();
1171                fStrChunks.removeAllElements();
1172                fBufferStr.setLength(0);
1173                return value;
1174            }
1175        }
1176        else if (type == Node.CDATA_SECTION_NODE) {
1177            // find if any other data stored in children
1178
int child = getLastChild(nodeIndex, false);
1179            if (child !=-1) {
1180                // append data that is stored in fNodeValue
1181
fBufferStr.append(value);
1182                while (child !=-1) {
1183                    // go in reverse order: find last child, then
1184
// its previous sibling, etc
1185
chunk = child >> CHUNK_SHIFT;
1186                    index = child & CHUNK_MASK;
1187                    value = getChunkValue(fNodeValue, chunk, index);
1188                    fStrChunks.addElement(value);
1189                    child = getChunkIndex(fNodePrevSib, chunk, index);
1190                }
1191                // add to the buffer in the correct order.
1192
for (int i=fStrChunks.size()-1; i>=0; i--) {
1193                     fBufferStr.append((String JavaDoc)fStrChunks.elementAt(i));
1194                }
1195                                                         
1196                value = fBufferStr.toString();
1197                fStrChunks.setSize(0);
1198                fBufferStr.setLength(0);
1199                return value;
1200            }
1201        }
1202
1203        return value;
1204
1205    } // getNodeValueString(int,boolean):String
1206

1207    /**
1208     * Returns the value of the given node.
1209     */

1210    public String JavaDoc getNodeValue(int nodeIndex) {
1211        return getNodeValue(nodeIndex, true);
1212    }
1213    
1214    /**
1215     * Clears the type info that is stored in the fNodeValue array
1216     * @param nodeIndex
1217     * @return Object - type information for the attribute/element node
1218     */

1219    public Object JavaDoc getTypeInfo(int nodeIndex) {
1220        if (nodeIndex == -1) {
1221            return null;
1222        }
1223
1224        int chunk = nodeIndex >> CHUNK_SHIFT;
1225        int index = nodeIndex & CHUNK_MASK;
1226        
1227        
1228        Object JavaDoc value = fNodeValue[chunk] != null ? fNodeValue[chunk][index] : null;
1229        if (value != null) {
1230            fNodeValue[chunk][index] = null;
1231            RefCount c = (RefCount) fNodeValue[chunk][CHUNK_SIZE];
1232            c.fCount--;
1233            if (c.fCount == 0) {
1234                fNodeValue[chunk] = null;
1235            }
1236        }
1237        return value;
1238    }
1239
1240    /**
1241     * Returns the value of the given node.
1242     * @param free True to free the value index.
1243     */

1244    public String JavaDoc getNodeValue(int nodeIndex, boolean free) {
1245
1246        if (nodeIndex == -1) {
1247            return null;
1248        }
1249
1250        int chunk = nodeIndex >> CHUNK_SHIFT;
1251        int index = nodeIndex & CHUNK_MASK;
1252        return free ? clearChunkValue(fNodeValue, chunk, index)
1253                    : getChunkValue(fNodeValue, chunk, index);
1254
1255    } // getNodeValue(int,boolean):String
1256

1257    /**
1258     * Returns the extra info of the given node.
1259     * Used by AttrImpl to store specified value (1 == true).
1260     */

1261    public int getNodeExtra(int nodeIndex) {
1262        return getNodeExtra(nodeIndex, true);
1263    }
1264
1265    /**
1266     * Returns the extra info of the given node.
1267     * @param free True to free the value index.
1268     */

1269    public int getNodeExtra(int nodeIndex, boolean free) {
1270
1271        if (nodeIndex == -1) {
1272            return -1;
1273        }
1274
1275        int chunk = nodeIndex >> CHUNK_SHIFT;
1276        int index = nodeIndex & CHUNK_MASK;
1277        return free ? clearChunkIndex(fNodeExtra, chunk, index)
1278                    : getChunkIndex(fNodeExtra, chunk, index);
1279
1280    } // getNodeExtra(int,boolean):int
1281

1282    /** Returns the type of the given node. */
1283    public short getNodeType(int nodeIndex) {
1284        return getNodeType(nodeIndex, true);
1285    }
1286
1287    /**
1288     * Returns the type of the given node.
1289     * @param free True to free type index.
1290     */

1291    public short getNodeType(int nodeIndex, boolean free) {
1292
1293        if (nodeIndex == -1) {
1294            return -1;
1295        }
1296
1297        int chunk = nodeIndex >> CHUNK_SHIFT;
1298        int index = nodeIndex & CHUNK_MASK;
1299        return free ? (short)clearChunkIndex(fNodeType, chunk, index)
1300                    : (short)getChunkIndex(fNodeType, chunk, index);
1301
1302    } // getNodeType(int):int
1303

1304    /** Returns the attribute value of the given name. */
1305    public String JavaDoc getAttribute(int elemIndex, String JavaDoc name) {
1306        if (elemIndex == -1 || name == null) {
1307            return null;
1308        }
1309        int echunk = elemIndex >> CHUNK_SHIFT;
1310        int eindex = elemIndex & CHUNK_MASK;
1311        int attrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
1312        while (attrIndex != -1) {
1313            int achunk = attrIndex >> CHUNK_SHIFT;
1314            int aindex = attrIndex & CHUNK_MASK;
1315            if (getChunkValue(fNodeName, achunk, aindex) == name) {
1316                return getChunkValue(fNodeValue, achunk, aindex);
1317            }
1318            attrIndex = getChunkIndex(fNodePrevSib, achunk, aindex);
1319        }
1320        return null;
1321    }
1322
1323    /** Returns the URI of the given node. */
1324    public String JavaDoc getNodeURI(int nodeIndex) {
1325        return getNodeURI(nodeIndex, true);
1326    }
1327
1328    /**
1329     * Returns the URI of the given node.
1330     * @param free True to free URI index.
1331     */

1332    public String JavaDoc getNodeURI(int nodeIndex, boolean free) {
1333
1334        if (nodeIndex == -1) {
1335            return null;
1336        }
1337
1338        int chunk = nodeIndex >> CHUNK_SHIFT;
1339        int index = nodeIndex & CHUNK_MASK;
1340        return free ? clearChunkValue(fNodeURI, chunk, index)
1341                    : getChunkValue(fNodeURI, chunk, index);
1342
1343    } // getNodeURI(int,int):String
1344

1345    // identifier maintenance
1346

1347    /** Registers an identifier name with a specified element node. */
1348    public void putIdentifier(String JavaDoc name, int elementNodeIndex) {
1349
1350        if (DEBUG_IDS) {
1351            System.out.println("putIdentifier(" + name + ", "
1352                               + elementNodeIndex + ')' + " // " +
1353                               getChunkValue(fNodeName,
1354                                             elementNodeIndex >> CHUNK_SHIFT,
1355                                             elementNodeIndex & CHUNK_MASK));
1356        }
1357
1358        // initialize arrays
1359
if (fIdName == null) {
1360            fIdName = new String JavaDoc[64];
1361            fIdElement = new int[64];
1362        }
1363
1364        // resize arrays
1365
if (fIdCount == fIdName.length) {
1366            String JavaDoc idName[] = new String JavaDoc[fIdCount * 2];
1367            System.arraycopy(fIdName, 0, idName, 0, fIdCount);
1368            fIdName = idName;
1369
1370            int idElement[] = new int[idName.length];
1371            System.arraycopy(fIdElement, 0, idElement, 0, fIdCount);
1372            fIdElement = idElement;
1373        }
1374
1375        // store identifier
1376
fIdName[fIdCount] = name;
1377        fIdElement[fIdCount] = elementNodeIndex;
1378        fIdCount++;
1379
1380    } // putIdentifier(String,int)
1381

1382    //
1383
// DEBUG
1384
//
1385

1386    /** Prints out the tables. */
1387    public void print() {
1388
1389        if (DEBUG_PRINT_REF_COUNTS) {
1390            System.out.print("num\t");
1391            System.out.print("type\t");
1392            System.out.print("name\t");
1393            System.out.print("val\t");
1394            System.out.print("par\t");
1395            System.out.print("lch\t");
1396            System.out.print("psib");
1397            System.out.println();
1398            for (int i = 0; i < fNodeType.length; i++) {
1399                if (fNodeType[i] != null) {
1400                    // separator
1401
System.out.print("--------");
1402                    System.out.print("--------");
1403                    System.out.print("--------");
1404                    System.out.print("--------");
1405                    System.out.print("--------");
1406                    System.out.print("--------");
1407                    System.out.print("--------");
1408                    System.out.println();
1409
1410                    // ref count
1411
System.out.print(i);
1412                    System.out.print('\t');
1413                    switch (fNodeType[i][CHUNK_SIZE]) {
1414                        case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
1415                        case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
1416                        case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
1417                        case Node.COMMENT_NODE: { System.out.print("Com"); break; }
1418                        case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
1419                        case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
1420                        case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
1421                        case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
1422                        case Node.TEXT_NODE: { System.out.print("Text"); break; }
1423                        case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
1424                        case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
1425                        default: { System.out.print("?"+fNodeType[i][CHUNK_SIZE]); }
1426                    }
1427                    System.out.print('\t');
1428                    System.out.print(fNodeName[i][CHUNK_SIZE]);
1429                    System.out.print('\t');
1430                    System.out.print(fNodeValue[i][CHUNK_SIZE]);
1431                    System.out.print('\t');
1432                    System.out.print(fNodeURI[i][CHUNK_SIZE]);
1433                    System.out.print('\t');
1434                    System.out.print(fNodeParent[i][CHUNK_SIZE]);
1435                    System.out.print('\t');
1436                    System.out.print(fNodeLastChild[i][CHUNK_SIZE]);
1437                    System.out.print('\t');
1438                    System.out.print(fNodePrevSib[i][CHUNK_SIZE]);
1439                    System.out.print('\t');
1440                    System.out.print(fNodeExtra[i][CHUNK_SIZE]);
1441                    System.out.println();
1442                }
1443            }
1444        }
1445
1446        if (DEBUG_PRINT_TABLES) {
1447            // This assumes that the document is small
1448
System.out.println("# start table");
1449            for (int i = 0; i < fNodeCount; i++) {
1450                int chunk = i >> CHUNK_SHIFT;
1451                int index = i & CHUNK_MASK;
1452                if (i % 10 == 0) {
1453                    System.out.print("num\t");
1454                    System.out.print("type\t");
1455                    System.out.print("name\t");
1456                    System.out.print("val\t");
1457                    System.out.print("uri\t");
1458                    System.out.print("par\t");
1459                    System.out.print("lch\t");
1460                    System.out.print("psib\t");
1461                    System.out.print("xtra");
1462                    System.out.println();
1463                }
1464                System.out.print(i);
1465                System.out.print('\t');
1466                switch (getChunkIndex(fNodeType, chunk, index)) {
1467                    case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
1468                    case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
1469                    case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
1470                    case Node.COMMENT_NODE: { System.out.print("Com"); break; }
1471                    case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
1472                    case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
1473                    case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
1474                    case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
1475                    case Node.TEXT_NODE: { System.out.print("Text"); break; }
1476                    case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
1477                    case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
1478                    default: { System.out.print("?"+getChunkIndex(fNodeType, chunk, index)); }
1479                }
1480                System.out.print('\t');
1481                System.out.print(getChunkValue(fNodeName, chunk, index));
1482                System.out.print('\t');
1483                System.out.print(getNodeValue(chunk, index));
1484                System.out.print('\t');
1485                System.out.print(getChunkValue(fNodeURI, chunk, index));
1486                System.out.print('\t');
1487                System.out.print(getChunkIndex(fNodeParent, chunk, index));
1488                System.out.print('\t');
1489                System.out.print(getChunkIndex(fNodeLastChild, chunk, index));
1490                System.out.print('\t');
1491                System.out.print(getChunkIndex(fNodePrevSib, chunk, index));
1492                System.out.print('\t');
1493                System.out.print(getChunkIndex(fNodeExtra, chunk, index));
1494                System.out.println();
1495            }
1496            System.out.println("# end table");
1497        }
1498
1499    } // print()
1500

1501    //
1502
// DeferredNode methods
1503
//
1504

1505    /** Returns the node index. */
1506    public int getNodeIndex() {
1507        return 0;
1508    }
1509
1510    //
1511
// Protected methods
1512
//
1513

1514    /** Synchronizes the node's data. */
1515    protected void synchronizeData() {
1516
1517        // no need to sync in the future
1518
needsSyncData(false);
1519
1520        // fluff up enough nodes to fill identifiers hash
1521
if (fIdElement != null) {
1522
1523            // REVISIT: There has to be a more efficient way of
1524
// doing this. But keep in mind that the
1525
// tree can have been altered and re-ordered
1526
// before all of the element nodes with ID
1527
// attributes have been registered. For now
1528
// this is reasonable and safe. -Ac
1529

1530            IntVector path = new IntVector();
1531            for (int i = 0; i < fIdCount; i++) {
1532
1533                // ignore if it's already been registered
1534
int elementNodeIndex = fIdElement[i];
1535                String JavaDoc idName = fIdName[i];
1536                if (idName == null) {
1537                    continue;
1538                }
1539
1540                // find path from this element to the root
1541
path.removeAllElements();
1542                int index = elementNodeIndex;
1543                do {
1544                    path.addElement(index);
1545                    int pchunk = index >> CHUNK_SHIFT;
1546                    int pindex = index & CHUNK_MASK;
1547                    index = getChunkIndex(fNodeParent, pchunk, pindex);
1548                } while (index != -1);
1549
1550                // Traverse path (backwards), fluffing the elements
1551
// along the way. When this loop finishes, "place"
1552
// will contain the reference to the element node
1553
// we're interested in. -Ac
1554
Node JavaDoc place = this;
1555                for (int j = path.size() - 2; j >= 0; j--) {
1556                    index = path.elementAt(j);
1557                    Node JavaDoc child = place.getLastChild();
1558                    while (child != null) {
1559                        if (child instanceof DeferredNode) {
1560                            int nodeIndex =
1561                                ((DeferredNode)child).getNodeIndex();
1562                            if (nodeIndex == index) {
1563                                place = child;
1564                                break;
1565                            }
1566                        }
1567                        child = child.getPreviousSibling();
1568                    }
1569                }
1570
1571                // register the element
1572
Element JavaDoc element = (Element JavaDoc)place;
1573                putIdentifier0(idName, element);
1574                fIdName[i] = null;
1575
1576                // see if there are more IDs on this element
1577
while (i + 1 < fIdCount &&
1578                    fIdElement[i + 1] == elementNodeIndex) {
1579                    idName = fIdName[++i];
1580                    if (idName == null) {
1581                        continue;
1582                    }
1583                    putIdentifier0(idName, element);
1584                }
1585            }
1586
1587        } // if identifiers
1588

1589    } // synchronizeData()
1590

1591    /**
1592     * Synchronizes the node's children with the internal structure.
1593     * Fluffing the children at once solves a lot of work to keep
1594     * the two structures in sync. The problem gets worse when
1595     * editing the tree -- this makes it a lot easier.
1596     */

1597    protected void synchronizeChildren() {
1598
1599        if (needsSyncData()) {
1600            synchronizeData();
1601            /*
1602             * when we have elements with IDs this method is being recursively
1603             * called from synchronizeData, in which case we've already gone
1604             * through the following and we can now simply stop here.
1605             */

1606            if (!needsSyncChildren()) {
1607                return;
1608            }
1609        }
1610
1611        // we don't want to generate any event for this so turn them off
1612
boolean orig = mutationEvents;
1613        mutationEvents = false;
1614
1615        // no need to sync in the future
1616
needsSyncChildren(false);
1617
1618        getNodeType(0);
1619
1620        // create children and link them as siblings
1621
ChildNode first = null;
1622        ChildNode last = null;
1623        for (int index = getLastChild(0);
1624             index != -1;
1625             index = getPrevSibling(index)) {
1626
1627            ChildNode node = (ChildNode)getNodeObject(index);
1628            if (last == null) {
1629                last = node;
1630            }
1631            else {
1632                first.previousSibling = node;
1633            }
1634            node.ownerNode = this;
1635            node.isOwned(true);
1636            node.nextSibling = first;
1637            first = node;
1638
1639            // save doctype and document type
1640
int type = node.getNodeType();
1641            if (type == Node.ELEMENT_NODE) {
1642                docElement = (ElementImpl)node;
1643            }
1644            else if (type == Node.DOCUMENT_TYPE_NODE) {
1645                docType = (DocumentTypeImpl)node;
1646            }
1647        }
1648
1649        if (first != null) {
1650            firstChild = first;
1651            first.isFirstChild(true);
1652            lastChild(last);
1653        }
1654
1655        // set mutation events flag back to its original value
1656
mutationEvents = orig;
1657
1658    } // synchronizeChildren()
1659

1660    /**
1661     * Synchronizes the node's children with the internal structure.
1662     * Fluffing the children at once solves a lot of work to keep
1663     * the two structures in sync. The problem gets worse when
1664     * editing the tree -- this makes it a lot easier.
1665     * This is not directly used in this class but this method is
1666     * here so that it can be shared by all deferred subclasses of AttrImpl.
1667     */

1668    protected final void synchronizeChildren(AttrImpl a, int nodeIndex) {
1669
1670        // we don't want to generate any event for this so turn them off
1671
boolean orig = getMutationEvents();
1672        setMutationEvents(false);
1673
1674        // no need to sync in the future
1675
a.needsSyncChildren(false);
1676
1677        // create children and link them as siblings or simply store the value
1678
// as a String if all we have is one piece of text
1679
int last = getLastChild(nodeIndex);
1680        int prev = getPrevSibling(last);
1681        if (prev == -1) {
1682            a.value = getNodeValueString(nodeIndex);
1683            a.hasStringValue(true);
1684        }
1685        else {
1686            ChildNode firstNode = null;
1687            ChildNode lastNode = null;
1688            for (int index = last; index != -1;
1689                 index = getPrevSibling(index)) {
1690
1691                ChildNode node = (ChildNode) getNodeObject(index);
1692                if (lastNode == null) {
1693                    lastNode = node;
1694                }
1695                else {
1696                    firstNode.previousSibling = node;
1697                }
1698                node.ownerNode = a;
1699                node.isOwned(true);
1700                node.nextSibling = firstNode;
1701                firstNode = node;
1702            }
1703            if (lastNode != null) {
1704                a.value = firstNode; // firstChild = firstNode
1705
firstNode.isFirstChild(true);
1706                a.lastChild(lastNode);
1707            }
1708            a.hasStringValue(false);
1709        }
1710
1711        // set mutation events flag back to its original value
1712
setMutationEvents(orig);
1713
1714    } // synchronizeChildren(AttrImpl,int):void
1715

1716
1717    /**
1718     * Synchronizes the node's children with the internal structure.
1719     * Fluffing the children at once solves a lot of work to keep
1720     * the two structures in sync. The problem gets worse when
1721     * editing the tree -- this makes it a lot easier.
1722     * This is not directly used in this class but this method is
1723     * here so that it can be shared by all deferred subclasses of ParentNode.
1724     */

1725    protected final void synchronizeChildren(ParentNode p, int nodeIndex) {
1726
1727        // we don't want to generate any event for this so turn them off
1728
boolean orig = getMutationEvents();
1729        setMutationEvents(false);
1730
1731        // no need to sync in the future
1732
p.needsSyncChildren(false);
1733
1734        // create children and link them as siblings
1735
ChildNode firstNode = null;
1736        ChildNode lastNode = null;
1737        for (int index = getLastChild(nodeIndex);
1738             index != -1;
1739             index = getPrevSibling(index)) {
1740
1741            ChildNode node = (ChildNode) getNodeObject(index);
1742            if (lastNode == null) {
1743                lastNode = node;
1744            }
1745            else {
1746                firstNode.previousSibling = node;
1747            }
1748            node.ownerNode = p;
1749            node.isOwned(true);
1750            node.nextSibling = firstNode;
1751            firstNode = node;
1752        }
1753        if (lastNode != null) {
1754            p.firstChild = firstNode;
1755            firstNode.isFirstChild(true);
1756            p.lastChild(lastNode);
1757        }
1758
1759        // set mutation events flag back to its original value
1760
setMutationEvents(orig);
1761
1762    } // synchronizeChildren(ParentNode,int):void
1763

1764    // utility methods
1765

1766    /** Ensures that the internal tables are large enough. */
1767    protected void ensureCapacity(int chunk) {
1768        if (fNodeType == null) {
1769            // create buffers
1770
fNodeType = new int[INITIAL_CHUNK_COUNT][];
1771            fNodeName = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
1772            fNodeValue = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
1773            fNodeParent = new int[INITIAL_CHUNK_COUNT][];
1774            fNodeLastChild = new int[INITIAL_CHUNK_COUNT][];
1775            fNodePrevSib = new int[INITIAL_CHUNK_COUNT][];
1776            fNodeURI = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
1777            fNodeExtra = new int[INITIAL_CHUNK_COUNT][];
1778        }
1779        else if (fNodeType.length <= chunk) {
1780            // resize the tables
1781
int newsize = chunk * 2;
1782
1783            int[][] newArray = new int[newsize][];
1784            System.arraycopy(fNodeType, 0, newArray, 0, chunk);
1785            fNodeType = newArray;
1786
1787            Object JavaDoc[][] newStrArray = new Object JavaDoc[newsize][];
1788            System.arraycopy(fNodeName, 0, newStrArray, 0, chunk);
1789            fNodeName = newStrArray;
1790
1791            newStrArray = new Object JavaDoc[newsize][];
1792            System.arraycopy(fNodeValue, 0, newStrArray, 0, chunk);
1793            fNodeValue = newStrArray;
1794
1795            newArray = new int[newsize][];
1796            System.arraycopy(fNodeParent, 0, newArray, 0, chunk);
1797            fNodeParent = newArray;
1798
1799            newArray = new int[newsize][];
1800            System.arraycopy(fNodeLastChild, 0, newArray, 0, chunk);
1801            fNodeLastChild = newArray;
1802
1803            newArray = new int[newsize][];
1804            System.arraycopy(fNodePrevSib, 0, newArray, 0, chunk);
1805            fNodePrevSib = newArray;
1806
1807            newStrArray = new Object JavaDoc[newsize][];
1808            System.arraycopy(fNodeURI, 0, newStrArray, 0, chunk);
1809            fNodeURI = newStrArray;
1810
1811            newArray = new int[newsize][];
1812            System.arraycopy(fNodeExtra, 0, newArray, 0, chunk);
1813            fNodeExtra = newArray;
1814        }
1815        else if (fNodeType[chunk] != null) {
1816            // Done - there's sufficient capacity
1817
return;
1818        }
1819
1820        // create new chunks
1821
createChunk(fNodeType, chunk);
1822        createChunk(fNodeName, chunk);
1823        createChunk(fNodeValue, chunk);
1824        createChunk(fNodeParent, chunk);
1825        createChunk(fNodeLastChild, chunk);
1826        createChunk(fNodePrevSib, chunk);
1827        createChunk(fNodeURI, chunk);
1828        createChunk(fNodeExtra, chunk);
1829
1830        // Done
1831
return;
1832
1833    } // ensureCapacity(int,int)
1834

1835    /** Creates a node of the specified type. */
1836    protected int createNode(short nodeType) {
1837        // ensure tables are large enough
1838
int chunk = fNodeCount >> CHUNK_SHIFT;
1839        int index = fNodeCount & CHUNK_MASK;
1840        ensureCapacity(chunk);
1841
1842        // initialize node
1843
setChunkIndex(fNodeType, nodeType, chunk, index);
1844
1845        // return node index number
1846
return fNodeCount++;
1847
1848    } // createNode(short):int
1849

1850    /**
1851     * Performs a binary search for a target value in an array of
1852     * values. The array of values must be in ascending sorted order
1853     * before calling this method and all array values must be
1854     * non-negative.
1855     *
1856     * @param values The array of values to search.
1857     * @param start The starting offset of the search.
1858     * @param end The ending offset of the search.
1859     * @param target The target value.
1860     *
1861     * @return This function will return the <i>first</i> occurrence
1862     * of the target value, or -1 if the target value cannot
1863     * be found.
1864     */

1865    protected static int binarySearch(final int values[],
1866                                      int start, int end, int target) {
1867
1868        if (DEBUG_IDS) {
1869            System.out.println("binarySearch(), target: "+target);
1870        }
1871
1872        // look for target value
1873
while (start <= end) {
1874
1875            // is this the one we're looking for?
1876
int middle = (start + end) / 2;
1877            int value = values[middle];
1878            if (DEBUG_IDS) {
1879                System.out.print(" value: "+value+", target: "+target+" // ");
1880                print(values, start, end, middle, target);
1881            }
1882            if (value == target) {
1883                while (middle > 0 && values[middle - 1] == target) {
1884                    middle--;
1885                }
1886                if (DEBUG_IDS) {
1887                    System.out.println("FOUND AT "+middle);
1888                }
1889                return middle;
1890            }
1891
1892            // is this point higher or lower?
1893
if (value > target) {
1894                end = middle - 1;
1895            }
1896            else {
1897                start = middle + 1;
1898            }
1899
1900        } // while
1901

1902        // not found
1903
if (DEBUG_IDS) {
1904            System.out.println("NOT FOUND!");
1905        }
1906        return -1;
1907
1908    } // binarySearch(int[],int,int,int):int
1909

1910    //
1911
// Private methods
1912
//
1913
private static final int[] INIT_ARRAY = new int[CHUNK_SIZE + 1];
1914    static {
1915        for (int i = 0; i < CHUNK_SIZE; i++) {
1916            INIT_ARRAY[i] = -1;
1917        }
1918    }
1919    /** Creates the specified chunk in the given array of chunks. */
1920    private final void createChunk(int data[][], int chunk) {
1921        data[chunk] = new int[CHUNK_SIZE + 1];
1922        System.arraycopy(INIT_ARRAY, 0, data[chunk], 0, CHUNK_SIZE);
1923    }
1924
1925    class RefCount {
1926        int fCount;
1927    }
1928
1929    private final void createChunk(Object JavaDoc data[][], int chunk) {
1930        data[chunk] = new Object JavaDoc[CHUNK_SIZE + 1];
1931        data[chunk][CHUNK_SIZE] = new RefCount();
1932    }
1933
1934    /**
1935     * Sets the specified value in the given of data at the chunk and index.
1936     *
1937     * @return Returns the old value.
1938     */

1939    private final int setChunkIndex(int data[][], int value,
1940                                    int chunk, int index) {
1941        if (value == -1) {
1942            return clearChunkIndex(data, chunk, index);
1943        }
1944        int ovalue = data[chunk][index];
1945        if (ovalue == -1) {
1946            data[chunk][CHUNK_SIZE]++;
1947        }
1948        data[chunk][index] = value;
1949        return ovalue;
1950    }
1951    private final String JavaDoc setChunkValue(Object JavaDoc data[][], Object JavaDoc value,
1952                                       int chunk, int index) {
1953        if (value == null) {
1954            return clearChunkValue(data, chunk, index);
1955        }
1956        String JavaDoc ovalue = (String JavaDoc) data[chunk][index];
1957        if (ovalue == null) {
1958            RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
1959            c.fCount++;
1960        }
1961        data[chunk][index] = value;
1962        return ovalue;
1963    }
1964
1965    /**
1966     * Returns the specified value in the given data at the chunk and index.
1967     */

1968    private final int getChunkIndex(int data[][], int chunk, int index) {
1969        return data[chunk] != null ? data[chunk][index] : -1;
1970    }
1971    private final String JavaDoc getChunkValue(Object JavaDoc data[][], int chunk, int index) {
1972        return data[chunk] != null ? (String JavaDoc) data[chunk][index] : null;
1973    }
1974    private final String JavaDoc getNodeValue(int chunk, int index) {
1975        Object JavaDoc data = fNodeValue[chunk][index];
1976        if (data == null){
1977            return null;
1978        }
1979        else if (data instanceof String JavaDoc){
1980            return (String JavaDoc)data;
1981        }
1982        else {
1983            // type information
1984
return data.toString();
1985        }
1986    }
1987    
1988
1989    /**
1990     * Clears the specified value in the given data at the chunk and index.
1991     * Note that this method will clear the given chunk if the reference
1992     * count becomes zero.
1993     *
1994     * @return Returns the old value.
1995     */

1996    private final int clearChunkIndex(int data[][], int chunk, int index) {
1997        int value = data[chunk] != null ? data[chunk][index] : -1;
1998        if (value != -1) {
1999            data[chunk][CHUNK_SIZE]--;
2000            data[chunk][index] = -1;
2001            if (data[chunk][CHUNK_SIZE] == 0) {
2002                data[chunk] = null;
2003            }
2004        }
2005        return value;
2006    }
2007    private final String JavaDoc clearChunkValue(Object JavaDoc data[][],
2008                                         int chunk, int index) {
2009        String JavaDoc value = data[chunk] != null ? (String JavaDoc)data[chunk][index] : null;
2010        if (value != null) {
2011            data[chunk][index] = null;
2012            RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
2013            c.fCount--;
2014            if (c.fCount == 0) {
2015                data[chunk] = null;
2016            }
2017        }
2018        return value;
2019    }
2020
2021    /**
2022     * This version of putIdentifier is needed to avoid fluffing
2023     * all of the paths to ID attributes when a node object is
2024     * created that contains an ID attribute.
2025     */

2026    private final void putIdentifier0(String JavaDoc idName, Element JavaDoc element) {
2027
2028        if (DEBUG_IDS) {
2029            System.out.println("putIdentifier0("+
2030                               idName+", "+
2031                               element+')');
2032        }
2033
2034        // create hashtable
2035
if (identifiers == null) {
2036            identifiers = new java.util.Hashtable JavaDoc();
2037        }
2038
2039        // save ID and its associated element
2040
identifiers.put(idName, element);
2041
2042    } // putIdentifier0(String,Element)
2043

2044    /** Prints the ID array. */
2045    private static void print(int values[], int start, int end,
2046                              int middle, int target) {
2047
2048        if (DEBUG_IDS) {
2049            System.out.print(start);
2050            System.out.print(" [");
2051            for (int i = start; i < end; i++) {
2052                if (middle == i) {
2053                    System.out.print("!");
2054                }
2055                System.out.print(values[i]);
2056                if (values[i] == target) {
2057                    System.out.print("*");
2058                }
2059                if (i < end - 1) {
2060                    System.out.print(" ");
2061                }
2062            }
2063            System.out.println("] "+end);
2064        }
2065
2066    } // print(int[],int,int,int,int)
2067

2068    //
2069
// Classes
2070
//
2071

2072    /**
2073     * A simple integer vector.
2074     */

2075    static class IntVector {
2076
2077        //
2078
// Data
2079
//
2080

2081        /** Data. */
2082        private int data[];
2083
2084        /** Size. */
2085        private int size;
2086
2087        //
2088
// Public methods
2089
//
2090

2091        /** Returns the length of this vector. */
2092        public int size() {
2093            return size;
2094        }
2095
2096        /** Returns the element at the specified index. */
2097        public int elementAt(int index) {
2098            return data[index];
2099        }
2100
2101        /** Appends an element to the end of the vector. */
2102        public void addElement(int element) {
2103            ensureCapacity(size + 1);
2104            data[size++] = element;
2105        }
2106
2107        /** Clears the vector. */
2108        public void removeAllElements() {
2109            size = 0;
2110        }
2111
2112        //
2113
// Private methods
2114
//
2115

2116        /** Makes sure that there is enough storage. */
2117        private void ensureCapacity(int newsize) {
2118
2119            if (data == null) {
2120                data = new int[newsize + 15];
2121            }
2122            else if (newsize > data.length) {
2123                int newdata[] = new int[newsize + 15];
2124                System.arraycopy(data, 0, newdata, 0, data.length);
2125                data = newdata;
2126            }
2127
2128        } // ensureCapacity(int)
2129

2130    } // class IntVector
2131

2132} // class DeferredDocumentImpl
2133
Popular Tags