FileDocCategorySizeDatePackage
DeferredDocumentImpl.javaAPI DocApache Xerces 3.0.177200Fri Sep 14 20:33:52 BST 2007org.apache.xerces.dom

DeferredDocumentImpl

public class DeferredDocumentImpl extends DocumentImpl implements DeferredNode
The Document interface represents the entire HTML or XML document. Conceptually, it is the root of the document tree, and provides the primary access to the document's data.

Since elements, text nodes, comments, processing instructions, etc. cannot exist outside the context of a Document, the Document interface also contains the factory methods needed to create these objects. The Node objects created have a ownerDocument attribute which associates them with the Document within whose context they were created.

xerces.internal
version
$Id: DeferredDocumentImpl.java 511134 2007-02-23 22:08:04Z mrglavas $
since
PR-DOM-Level-1-19980818.

Fields Summary
static final long
serialVersionUID
Serialization version.
private static final boolean
DEBUG_PRINT_REF_COUNTS
To include code for printing the ref count tables.
private static final boolean
DEBUG_PRINT_TABLES
To include code for printing the internal tables.
private static final boolean
DEBUG_IDS
To debug identifiers set to true and recompile.
protected static final int
CHUNK_SHIFT
Chunk shift.
protected static final int
CHUNK_SIZE
Chunk size.
protected static final int
CHUNK_MASK
Chunk mask.
protected static final int
INITIAL_CHUNK_COUNT
Initial chunk size.
protected transient int
fNodeCount
Node count.
protected transient int[]
fNodeType
Node types.
protected transient Object[]
fNodeName
Node names.
protected transient Object[]
fNodeValue
Node values.
protected transient int[]
fNodeParent
Node parents.
protected transient int[]
fNodeLastChild
Node first children.
protected transient int[]
fNodePrevSib
Node prev siblings.
protected transient Object[]
fNodeURI
Node namespace URI.
protected transient int[]
fNodeExtra
Extra data.
protected transient int
fIdCount
Identifier count.
protected transient String[]
fIdName
Identifier name indexes.
protected transient int[]
fIdElement
Identifier element indexes.
protected boolean
fNamespacesEnabled
DOM2: For namespace support in the deferred case.
private final transient StringBuffer
fBufferStr
private final transient Vector
fStrChunks
private static final int[]
INIT_ARRAY
Constructors Summary
public DeferredDocumentImpl()
NON-DOM: Actually creating a Document is outside the DOM's spec, since it has to operate in terms of a particular implementation.


    //
    // Constructors
    //

                              
      
        this(false);
    
public DeferredDocumentImpl(boolean namespacesEnabled)
NON-DOM: Actually creating a Document is outside the DOM's spec, since it has to operate in terms of a particular implementation.

        this(namespacesEnabled, false);
    
public DeferredDocumentImpl(boolean namespaces, boolean grammarAccess)
Experimental constructor.

        super(grammarAccess);

        needsSyncData(true);
        needsSyncChildren(true);

        fNamespacesEnabled = namespaces;

    
Methods Summary
public voidappendChild(int parentIndex, int childIndex)
Appends a child to the specified parent in the table.


        // append parent index
        int pchunk = parentIndex >> CHUNK_SHIFT;
        int pindex = parentIndex & CHUNK_MASK;
        int cchunk = childIndex >> CHUNK_SHIFT;
        int cindex = childIndex & CHUNK_MASK;
        setChunkIndex(fNodeParent, parentIndex, cchunk, cindex);

        // set previous sibling of new child
        int olast = getChunkIndex(fNodeLastChild, pchunk, pindex);
        setChunkIndex(fNodePrevSib, olast, cchunk, cindex);

        // update parent's last child
        setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);

    
protected static intbinarySearch(int[] values, int start, int end, int target)
Performs a binary search for a target value in an array of values. The array of values must be in ascending sorted order before calling this method and all array values must be non-negative.

param
values The array of values to search.
param
start The starting offset of the search.
param
end The ending offset of the search.
param
target The target value.
return
This function will return the first occurrence of the target value, or -1 if the target value cannot be found.


        if (DEBUG_IDS) {
            System.out.println("binarySearch(), target: "+target);
        }

        // look for target value
        while (start <= end) {

            // is this the one we're looking for?
            int middle = (start + end) / 2;
            int value  = values[middle];
            if (DEBUG_IDS) {
                System.out.print("  value: "+value+", target: "+target+" // ");
                print(values, start, end, middle, target);
            }
            if (value == target) {
                while (middle > 0 && values[middle - 1] == target) {
                    middle--;
                }
                if (DEBUG_IDS) {
                    System.out.println("FOUND AT "+middle);
                }
                return middle;
            }

            // is this point higher or lower?
            if (value > target) {
                end = middle - 1;
            }
            else {
                start = middle + 1;
            }

        } // while

        // not found
        if (DEBUG_IDS) {
            System.out.println("NOT FOUND!");
        }
        return -1;

    
private final intclearChunkIndex(int[][] data, int chunk, int index)
Clears the specified value in the given data at the chunk and index. Note that this method will clear the given chunk if the reference count becomes zero.

return
Returns the old value.

        int value = data[chunk] != null ? data[chunk][index] : -1;
        if (value != -1) {
            data[chunk][CHUNK_SIZE]--;
            data[chunk][index] = -1;
            if (data[chunk][CHUNK_SIZE] == 0) {
                data[chunk] = null;
            }
        }
        return value;
    
private final java.lang.StringclearChunkValue(java.lang.Object[][] data, int chunk, int index)

        String value = data[chunk] != null ? (String)data[chunk][index] : null;
        if (value != null) {
            data[chunk][index] = null;
            RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
            c.fCount--;
            if (c.fCount == 0) {
                data[chunk] = null;
            }
        }
        return value;
    
public intcloneNode(int nodeIndex, boolean deep)
Creates a clone of the specified node.


        // clone immediate node
        
        int nchunk = nodeIndex >> CHUNK_SHIFT;
        int nindex = nodeIndex & CHUNK_MASK;
        int nodeType = fNodeType[nchunk][nindex];
        int cloneIndex = createNode((short)nodeType);
        int cchunk = cloneIndex >> CHUNK_SHIFT;
        int cindex = cloneIndex & CHUNK_MASK;
        setChunkValue(fNodeName, fNodeName[nchunk][nindex], cchunk, cindex);
        setChunkValue(fNodeValue, fNodeValue[nchunk][nindex], cchunk, cindex);
        setChunkValue(fNodeURI, fNodeURI[nchunk][nindex], cchunk, cindex);
        int extraIndex = fNodeExtra[nchunk][nindex];
        if (extraIndex != -1) {
            if (nodeType != Node.ATTRIBUTE_NODE && nodeType != Node.TEXT_NODE) {
                extraIndex = cloneNode(extraIndex, false);
            }
            setChunkIndex(fNodeExtra, extraIndex, cchunk, cindex);
        }

        // clone and attach children
        if (deep) {
            int prevIndex = -1;
            int childIndex = getLastChild(nodeIndex, false);
            while (childIndex != -1) {
                int clonedChildIndex = cloneNode(childIndex, deep);
                insertBefore(cloneIndex, clonedChildIndex, prevIndex);
                prevIndex = clonedChildIndex;
                childIndex = getRealPrevSibling(childIndex, false);
            }
            

        }
        
        // return cloned node index
        return cloneIndex;

    
private final voidcreateChunk(int[][] data, int chunk)
Creates the specified chunk in the given array of chunks.

     
        for (int i = 0; i < CHUNK_SIZE; i++) {
            INIT_ARRAY[i] = -1;
        }
    
        data[chunk] = new int[CHUNK_SIZE + 1];
        System.arraycopy(INIT_ARRAY, 0, data[chunk], 0, CHUNK_SIZE);
    
private final voidcreateChunk(java.lang.Object[][] data, int chunk)

        data[chunk] = new Object[CHUNK_SIZE + 1];
        data[chunk][CHUNK_SIZE] = new RefCount();
    
public intcreateDeferredAttribute(java.lang.String attrName, java.lang.String attrValue, boolean specified)
Creates an attribute in the table.

        return createDeferredAttribute(attrName, null, attrValue, specified);
    
public intcreateDeferredAttribute(java.lang.String attrName, java.lang.String attrURI, java.lang.String attrValue, boolean specified)
Creates an attribute with a URI in the table.


        // create node
        int nodeIndex = createNode(NodeImpl.ATTRIBUTE_NODE);
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeName, attrName, chunk, index);
        setChunkValue(fNodeURI, attrURI, chunk, index);
        setChunkValue(fNodeValue, attrValue, chunk, index);
        int extra = specified ? SPECIFIED : 0;
        setChunkIndex(fNodeExtra, extra, chunk, index);

        // return node index
        return nodeIndex;

    
public intcreateDeferredCDATASection(java.lang.String data)
Creates a CDATA section node in the table.


        // create node
        int nodeIndex = createNode(Node.CDATA_SECTION_NODE);
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeValue, data, chunk, index);

        // return node index
        return nodeIndex;

    
public intcreateDeferredComment(java.lang.String data)
Creates a comment node in the table.


        // create node
        int nodeIndex = createNode(Node.COMMENT_NODE);
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeValue, data, chunk, index);

        // return node index
        return nodeIndex;

    
public intcreateDeferredDocument()
Creates a document node in the table.

        int nodeIndex = createNode(Node.DOCUMENT_NODE);
        return nodeIndex;
    
public intcreateDeferredDocumentType(java.lang.String rootElementName, java.lang.String publicId, java.lang.String systemId)
Creates a doctype.


        // create node
        int nodeIndex = createNode(Node.DOCUMENT_TYPE_NODE);
        int chunk     = nodeIndex >> CHUNK_SHIFT;
        int index     = nodeIndex & CHUNK_MASK;

        // save name, public id, system id
        setChunkValue(fNodeName, rootElementName, chunk, index);
        setChunkValue(fNodeValue, publicId, chunk, index);
        setChunkValue(fNodeURI, systemId, chunk, index);

        // return node index
        return nodeIndex;

    
public intcreateDeferredElement(java.lang.String elementURI, java.lang.String elementName, java.lang.Object type)
Creates an element node with a URI in the table and type information.

deprecated


        // create node
        int elementNodeIndex = createNode(Node.ELEMENT_NODE);
        int elementChunk     = elementNodeIndex >> CHUNK_SHIFT;
        int elementIndex     = elementNodeIndex & CHUNK_MASK;
        setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
        setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
        setChunkValue(fNodeValue, type, elementChunk, elementIndex);
 
        // return node index
        return elementNodeIndex;

    
public intcreateDeferredElement(java.lang.String elementName)
Creates an element node in the table.

deprecated

        return createDeferredElement(null, elementName);
    
public intcreateDeferredElement(java.lang.String elementURI, java.lang.String elementName)
Creates an element node with a URI in the table.


        // create node
        int elementNodeIndex = createNode(Node.ELEMENT_NODE);
        int elementChunk     = elementNodeIndex >> CHUNK_SHIFT;
        int elementIndex     = elementNodeIndex & CHUNK_MASK;
        setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
        setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
 
        // return node index
        return elementNodeIndex;

    
public intcreateDeferredElementDefinition(java.lang.String elementName)
Creates an element definition in the table.


        // create node
        int nodeIndex = createNode(NodeImpl.ELEMENT_DEFINITION_NODE);
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeName, elementName, chunk, index);

        // return node index
        return nodeIndex;

    
public intcreateDeferredEntity(java.lang.String entityName, java.lang.String publicId, java.lang.String systemId, java.lang.String notationName, java.lang.String baseURI)
Creates an entity in the table.

        // create node
        int nodeIndex = createNode(Node.ENTITY_NODE);
        int chunk     = nodeIndex >> CHUNK_SHIFT;
        int index     = nodeIndex & CHUNK_MASK;

        // create extra data node
        int extraDataIndex = createNode(Node.ENTITY_NODE); 
        int echunk = extraDataIndex >> CHUNK_SHIFT;
        int eindex = extraDataIndex & CHUNK_MASK;

        // save name, public id, system id, and notation name
        setChunkValue(fNodeName, entityName, chunk, index);
        setChunkValue(fNodeValue, publicId, chunk, index);
        setChunkValue(fNodeURI, systemId, chunk, index);
        setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
        // set other values in the extra chunk
        // notation
        setChunkValue(fNodeName, notationName, echunk, eindex);
        // version  L3
        setChunkValue(fNodeValue, null, echunk, eindex);
        // encoding L3
        setChunkValue(fNodeURI, null, echunk, eindex);


        int extraDataIndex2 = createNode(Node.ENTITY_NODE);
        int echunk2 = extraDataIndex2 >> CHUNK_SHIFT;
        int eindex2 = extraDataIndex2 & CHUNK_MASK;

        setChunkIndex(fNodeExtra, extraDataIndex2, echunk, eindex);

        // baseURI
        setChunkValue(fNodeName, baseURI, echunk2, eindex2);

        // return node index
        return nodeIndex;

    
public intcreateDeferredEntityReference(java.lang.String name, java.lang.String baseURI)
Creates an entity reference node in the table.


        // create node
        int nodeIndex = createNode(Node.ENTITY_REFERENCE_NODE);
        int chunk     = nodeIndex >> CHUNK_SHIFT;
        int index     = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeName, name, chunk, index);
        setChunkValue(fNodeValue, baseURI, chunk, index);

        // return node index
        return nodeIndex;

    
public intcreateDeferredNotation(java.lang.String notationName, java.lang.String publicId, java.lang.String systemId, java.lang.String baseURI)
Creates a notation in the table.


        // create node
        int nodeIndex = createNode(Node.NOTATION_NODE);
        int chunk     = nodeIndex >> CHUNK_SHIFT;
        int index     = nodeIndex & CHUNK_MASK;


        // create extra data node
        int extraDataIndex = createNode(Node.NOTATION_NODE); 
        int echunk = extraDataIndex >> CHUNK_SHIFT;
        int eindex = extraDataIndex & CHUNK_MASK;

        // save name, public id, system id, and notation name
        setChunkValue(fNodeName, notationName, chunk, index);
        setChunkValue(fNodeValue, publicId, chunk, index);
        setChunkValue(fNodeURI, systemId, chunk, index);

        // in extra data node set baseURI value
        setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
        setChunkValue(fNodeName, baseURI, echunk, eindex);

        // return node index
        return nodeIndex;

    
public intcreateDeferredProcessingInstruction(java.lang.String target, java.lang.String data)
Creates a processing instruction node in the table.

        // create node
        int nodeIndex = createNode(Node.PROCESSING_INSTRUCTION_NODE);
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeName, target, chunk, index);
        setChunkValue(fNodeValue, data, chunk, index);
        // return node index
        return nodeIndex;

    
public intcreateDeferredTextNode(java.lang.String data, boolean ignorableWhitespace)
Creates a text node in the table.


        // create node
        int nodeIndex = createNode(Node.TEXT_NODE);
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        setChunkValue(fNodeValue, data, chunk, index);
        // use extra to store ignorableWhitespace info
        setChunkIndex(fNodeExtra, ignorableWhitespace ?  1 : 0, chunk, index);

        // return node index
        return nodeIndex;

    
protected intcreateNode(short nodeType)
Creates a node of the specified type.

        // ensure tables are large enough
        int chunk = fNodeCount >> CHUNK_SHIFT;
        int index = fNodeCount & CHUNK_MASK;
        ensureCapacity(chunk);

        // initialize node
        setChunkIndex(fNodeType, nodeType, chunk, index);

        // return node index number
        return fNodeCount++;

    
protected voidensureCapacity(int chunk)
Ensures that the internal tables are large enough.

        if (fNodeType == null) {
            // create buffers
            fNodeType       = new int[INITIAL_CHUNK_COUNT][];
            fNodeName       = new Object[INITIAL_CHUNK_COUNT][];
            fNodeValue      = new Object[INITIAL_CHUNK_COUNT][];
            fNodeParent     = new int[INITIAL_CHUNK_COUNT][];
            fNodeLastChild  = new int[INITIAL_CHUNK_COUNT][];
            fNodePrevSib    = new int[INITIAL_CHUNK_COUNT][];
            fNodeURI        = new Object[INITIAL_CHUNK_COUNT][];
            fNodeExtra      = new int[INITIAL_CHUNK_COUNT][];
        }
        else if (fNodeType.length <= chunk) {
            // resize the tables
            int newsize = chunk * 2;

            int[][] newArray = new int[newsize][];
            System.arraycopy(fNodeType, 0, newArray, 0, chunk);
            fNodeType = newArray;

            Object[][] newStrArray = new Object[newsize][];
            System.arraycopy(fNodeName, 0, newStrArray, 0, chunk);
            fNodeName = newStrArray;

            newStrArray = new Object[newsize][];
            System.arraycopy(fNodeValue, 0, newStrArray, 0, chunk);
            fNodeValue = newStrArray;

            newArray = new int[newsize][];
            System.arraycopy(fNodeParent, 0, newArray, 0, chunk);
            fNodeParent = newArray;

            newArray = new int[newsize][];
            System.arraycopy(fNodeLastChild, 0, newArray, 0, chunk);
            fNodeLastChild = newArray;

            newArray = new int[newsize][];
            System.arraycopy(fNodePrevSib, 0, newArray, 0, chunk);
            fNodePrevSib = newArray;

            newStrArray = new Object[newsize][];
            System.arraycopy(fNodeURI, 0, newStrArray, 0, chunk);
            fNodeURI = newStrArray;

            newArray = new int[newsize][];
            System.arraycopy(fNodeExtra, 0, newArray, 0, chunk);
            fNodeExtra = newArray;
        }
        else if (fNodeType[chunk] != null) {
            // Done - there's sufficient capacity
            return;
        }

        // create new chunks
        createChunk(fNodeType, chunk);
        createChunk(fNodeName, chunk);
        createChunk(fNodeValue, chunk);
        createChunk(fNodeParent, chunk);
        createChunk(fNodeLastChild, chunk);
        createChunk(fNodePrevSib, chunk);
        createChunk(fNodeURI, chunk);
        createChunk(fNodeExtra, chunk);

        // Done
        return;

    
public java.lang.StringgetAttribute(int elemIndex, java.lang.String name)
Returns the attribute value of the given name.

        if (elemIndex == -1 || name == null) {
            return null;
        }
        int echunk = elemIndex >> CHUNK_SHIFT;
        int eindex = elemIndex & CHUNK_MASK;
        int attrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
        while (attrIndex != -1) {
            int achunk = attrIndex >> CHUNK_SHIFT;
            int aindex = attrIndex & CHUNK_MASK;
            if (getChunkValue(fNodeName, achunk, aindex) == name) {
                return getChunkValue(fNodeValue, achunk, aindex);
            }
            attrIndex = getChunkIndex(fNodePrevSib, achunk, aindex);
        }
        return null;
    
private final intgetChunkIndex(int[][] data, int chunk, int index)
Returns the specified value in the given data at the chunk and index.

        return data[chunk] != null ? data[chunk][index] : -1;
    
private final java.lang.StringgetChunkValue(java.lang.Object[][] data, int chunk, int index)

        return data[chunk] != null ? (String) data[chunk][index] : null;
    
public java.lang.StringgetDeferredEntityBaseURI(int entityIndex)

        if (entityIndex != -1) {
            int extraDataIndex = getNodeExtra(entityIndex, false);
            extraDataIndex = getNodeExtra(extraDataIndex, false);
            return getNodeName (extraDataIndex, false);
        }
        return null;
    
public org.w3c.dom.DOMImplementationgetImplementation()
Retrieve information describing the abilities of this particular DOM implementation. Intended to support applications that may be using DOMs retrieved from several different sources, potentially with different underlying representations.

        // Currently implemented as a singleton, since it's hardcoded
        // information anyway.
        return DeferredDOMImplementationImpl.getDOMImplementation();
    
public intgetLastChild(int nodeIndex)
Returns the last child of the given node.

        return getLastChild(nodeIndex, true);
    
public intgetLastChild(int nodeIndex, boolean free)
Returns the last child of the given node.

param
free True to free child index.


        if (nodeIndex == -1) {
            return -1;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkIndex(fNodeLastChild, chunk, index)
                    : getChunkIndex(fNodeLastChild, chunk, index);

    
booleangetNamespacesEnabled()
Returns the cached parser.getNamespaces() value.

        return fNamespacesEnabled;
    
public intgetNodeExtra(int nodeIndex)
Returns the extra info of the given node. Used by AttrImpl to store specified value (1 == true).

        return getNodeExtra(nodeIndex, true);
    
public intgetNodeExtra(int nodeIndex, boolean free)
Returns the extra info of the given node.

param
free True to free the value index.


        if (nodeIndex == -1) {
            return -1;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkIndex(fNodeExtra, chunk, index)
                    : getChunkIndex(fNodeExtra, chunk, index);

    
public intgetNodeIndex()
Returns the node index.

        return 0;
    
public java.lang.StringgetNodeName(int nodeIndex)
Returns the name of the given node.

        return getNodeName(nodeIndex, true);
    
public java.lang.StringgetNodeName(int nodeIndex, boolean free)
Returns the name of the given node.

param
free True to free the string index.


        if (nodeIndex == -1) {
            return null;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkValue(fNodeName, chunk, index)
                    : getChunkValue(fNodeName, chunk, index);

    
public DeferredNodegetNodeObject(int nodeIndex)
Instantiates the requested node object.


        // is there anything to do?
        if (nodeIndex == -1) {
            return null;
        }

        // get node type
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        int type = getChunkIndex(fNodeType, chunk, index);
        if (type != Node.TEXT_NODE && type != Node.CDATA_SECTION_NODE) {
            clearChunkIndex(fNodeType, chunk, index);
        }

        // create new node
        DeferredNode node = null;
        switch (type) {

            //
            // Standard DOM node types
            //

            case Node.ATTRIBUTE_NODE: {
                if (fNamespacesEnabled) {
                    node = new DeferredAttrNSImpl(this, nodeIndex);
                } else {
                    node = new DeferredAttrImpl(this, nodeIndex);
                }
                break;
            }

            case Node.CDATA_SECTION_NODE: {
                node = new DeferredCDATASectionImpl(this, nodeIndex);
                break;
            }

            case Node.COMMENT_NODE: {
                node = new DeferredCommentImpl(this, nodeIndex);
                break;
            }

            // NOTE: Document fragments can never be "fast".
            //
            //       The parser will never ask to create a document
            //       fragment during the parse. Document fragments
            //       are used by the application *after* the parse.
            //
            // case Node.DOCUMENT_FRAGMENT_NODE: { break; }
            case Node.DOCUMENT_NODE: {
                // this node is never "fast"
                node = this;
                break;
            }

            case Node.DOCUMENT_TYPE_NODE: {
                node = new DeferredDocumentTypeImpl(this, nodeIndex);
                // save the doctype node
                docType = (DocumentTypeImpl)node;
                break;
            }

            case Node.ELEMENT_NODE: {

                if (DEBUG_IDS) {
                    System.out.println("getNodeObject(ELEMENT_NODE): "+nodeIndex);
                }

                // create node
                if (fNamespacesEnabled) {
                    node = new DeferredElementNSImpl(this, nodeIndex);
                } else {
                    node = new DeferredElementImpl(this, nodeIndex);
                }

                // check to see if this element needs to be
                // registered for its ID attributes
                if (fIdElement != null) {
                    int idIndex = binarySearch(fIdElement, 0,
                                               fIdCount-1, nodeIndex);
                    while (idIndex != -1) {

                        if (DEBUG_IDS) {
                            System.out.println("  id index: "+idIndex);
                            System.out.println("  fIdName["+idIndex+
                                               "]: "+fIdName[idIndex]);
                        }

                        // register ID
                        String name = fIdName[idIndex];
                        if (name != null) {
                            if (DEBUG_IDS) {
                                System.out.println("  name: "+name);
                                System.out.print("getNodeObject()#");
                            }
                            putIdentifier0(name, (Element)node);
                            fIdName[idIndex] = null;
                        }

                        // continue if there are more IDs for
                        // this element
                        if (idIndex + 1 < fIdCount &&
                            fIdElement[idIndex + 1] == nodeIndex) {
                            idIndex++;
                        }
                        else {
                            idIndex = -1;
                        }
                    }
                }
                break;
            }

            case Node.ENTITY_NODE: {
                node = new DeferredEntityImpl(this, nodeIndex);
                break;
            }

            case Node.ENTITY_REFERENCE_NODE: {
                node = new DeferredEntityReferenceImpl(this, nodeIndex);
                break;
            }

            case Node.NOTATION_NODE: {
                node = new DeferredNotationImpl(this, nodeIndex);
                break;
            }

            case Node.PROCESSING_INSTRUCTION_NODE: {
                node = new DeferredProcessingInstructionImpl(this, nodeIndex);
                break;
            }

            case Node.TEXT_NODE: {
                node = new DeferredTextImpl(this, nodeIndex);
                break;
            }

            //
            // non-standard DOM node types
            //

            case NodeImpl.ELEMENT_DEFINITION_NODE: {
                node = new DeferredElementDefinitionImpl(this, nodeIndex);
                break;
            }

            default: {
                throw new IllegalArgumentException("type: "+type);
            }

        } // switch node type

        // store and return
        if (node != null) {
            return node;
        }

        // error
        throw new IllegalArgumentException();

    
public shortgetNodeType(int nodeIndex)
Returns the type of the given node.

        return getNodeType(nodeIndex, true);
    
public shortgetNodeType(int nodeIndex, boolean free)
Returns the type of the given node.

param
free True to free type index.


        if (nodeIndex == -1) {
            return -1;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? (short)clearChunkIndex(fNodeType, chunk, index)
                    : (short)getChunkIndex(fNodeType, chunk, index);

    
public java.lang.StringgetNodeURI(int nodeIndex)
Returns the URI of the given node.

        return getNodeURI(nodeIndex, true);
    
public java.lang.StringgetNodeURI(int nodeIndex, boolean free)
Returns the URI of the given node.

param
free True to free URI index.


        if (nodeIndex == -1) {
            return null;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkValue(fNodeURI, chunk, index)
                    : getChunkValue(fNodeURI, chunk, index);

    
public java.lang.StringgetNodeValue(int nodeIndex)
Returns the value of the given node.

        return getNodeValue(nodeIndex, true);
    
public java.lang.StringgetNodeValue(int nodeIndex, boolean free)
Returns the value of the given node.

param
free True to free the value index.


        if (nodeIndex == -1) {
            return null;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkValue(fNodeValue, chunk, index)
                    : getChunkValue(fNodeValue, chunk, index);

    
private final java.lang.StringgetNodeValue(int chunk, int index)

        Object data = fNodeValue[chunk][index];
        if (data == null){
            return null;
        }
        else if (data instanceof String){
            return (String)data;
        }
        else {
            // type information
            return data.toString();
        }
    
public java.lang.StringgetNodeValueString(int nodeIndex)
Returns the real value of the given node.

        return getNodeValueString(nodeIndex, true);
    
public java.lang.StringgetNodeValueString(int nodeIndex, boolean free)
Returns the real value of the given node.

param
free True to free the string index.


        if (nodeIndex == -1) {
            return null;
        }
        
        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        String value = free ? clearChunkValue(fNodeValue, chunk, index)
                            : getChunkValue(fNodeValue, chunk, index);
        if (value == null) {
            return null;
        }
        
        int type  = getChunkIndex(fNodeType, chunk, index);
        if (type == Node.TEXT_NODE) {
            int prevSib = getRealPrevSibling(nodeIndex);
            if (prevSib != -1 &&
                getNodeType(prevSib, false) == Node.TEXT_NODE) {
                // append data that is stored in fNodeValue
                // REVISIT: for text nodes it works differently than for CDATA
                //          nodes.
                fStrChunks.addElement(value);
                do {
                    // go in reverse order: find last child, then
                    // its previous sibling, etc
                    chunk = prevSib >> CHUNK_SHIFT;
                    index = prevSib & CHUNK_MASK;
                    value = getChunkValue(fNodeValue, chunk, index);
                    fStrChunks.addElement(value);
                    prevSib = getChunkIndex(fNodePrevSib, chunk, index);
                    if (prevSib == -1) {
                        break;
                    }
                } while (getNodeType(prevSib, false) == Node.TEXT_NODE);
                
                int chunkCount = fStrChunks.size();

                // add to the buffer in the correct order.
                for (int i = chunkCount - 1; i >= 0; i--) {                                                               
                    fBufferStr.append((String)fStrChunks.elementAt(i));
                }
                
                value = fBufferStr.toString();
                fStrChunks.removeAllElements();
                fBufferStr.setLength(0);
                return value;
            }
        }
        else if (type == Node.CDATA_SECTION_NODE) {
            // find if any other data stored in children
            int child = getLastChild(nodeIndex, false);
            if (child !=-1) {
                // append data that is stored in fNodeValue
                fBufferStr.append(value);
                while (child !=-1) {
                    // go in reverse order: find last child, then
                    // its previous sibling, etc
                   chunk = child >> CHUNK_SHIFT;
                    index = child & CHUNK_MASK;
                    value = getChunkValue(fNodeValue, chunk, index);
                    fStrChunks.addElement(value);
                    child = getChunkIndex(fNodePrevSib, chunk, index);
                }
                // add to the buffer in the correct order.
                for (int i=fStrChunks.size()-1; i>=0; i--) {                                                               
                     fBufferStr.append((String)fStrChunks.elementAt(i));
                }
                                                         
                value = fBufferStr.toString();
                fStrChunks.setSize(0);
                fBufferStr.setLength(0);
                return value;
            }
        }

        return value;

    
public intgetParentNode(int nodeIndex)
Returns the parent node of the given node. Calling this method does not free the parent index.

        return getParentNode(nodeIndex, false);
    
public intgetParentNode(int nodeIndex, boolean free)
Returns the parent node of the given node.

param
free True to free parent node.


        if (nodeIndex == -1) {
            return -1;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkIndex(fNodeParent, chunk, index)
                    : getChunkIndex(fNodeParent, chunk, index);

    
public intgetPrevSibling(int nodeIndex)
Returns the prev sibling of the given node. This is post-normalization of Text Nodes.

        return getPrevSibling(nodeIndex, true);
    
public intgetPrevSibling(int nodeIndex, boolean free)
Returns the prev sibling of the given node.

param
free True to free sibling index.


        if (nodeIndex == -1) {
            return -1;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        int type = getChunkIndex(fNodeType, chunk, index);
        if (type == Node.TEXT_NODE) {
            do {
                nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
                if (nodeIndex == -1) {
                    break;
                }
                chunk = nodeIndex >> CHUNK_SHIFT;
                index = nodeIndex & CHUNK_MASK;
                type = getChunkIndex(fNodeType, chunk, index);
            } while (type == Node.TEXT_NODE);
        }
        else {
            nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
        }

        return nodeIndex;

    
public intgetRealPrevSibling(int nodeIndex)
Returns the real prev sibling of the given node, directly from the data structures. Used by TextImpl#getNodeValue() to normalize values.

        return getRealPrevSibling(nodeIndex, true);
    
public intgetRealPrevSibling(int nodeIndex, boolean free)
Returns the real prev sibling of the given node.

param
free True to free sibling index.


        if (nodeIndex == -1) {
            return -1;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        return free ? clearChunkIndex(fNodePrevSib, chunk, index)
                    : getChunkIndex(fNodePrevSib, chunk, index);

    
public java.lang.ObjectgetTypeInfo(int nodeIndex)
Clears the type info that is stored in the fNodeValue array

param
nodeIndex
return
Object - type information for the attribute/element node

        if (nodeIndex == -1) {
            return null;
        }

        int chunk = nodeIndex >> CHUNK_SHIFT;
        int index = nodeIndex & CHUNK_MASK;
        
        
        Object value = fNodeValue[chunk] != null ? fNodeValue[chunk][index] : null;
        if (value != null) {
            fNodeValue[chunk][index] = null;
            RefCount c = (RefCount) fNodeValue[chunk][CHUNK_SIZE];
            c.fCount--;
            if (c.fCount == 0) {
                fNodeValue[chunk] = null;
            }
        }
        return value;
    
public intinsertBefore(int parentIndex, int newChildIndex, int refChildIndex)
Inserts a child before the specified node in the table.


        if (refChildIndex == -1) {
            appendChild(parentIndex, newChildIndex);
            return newChildIndex;
        }

        int nchunk = newChildIndex >> CHUNK_SHIFT;
        int nindex = newChildIndex & CHUNK_MASK;
        int rchunk = refChildIndex >> CHUNK_SHIFT;
        int rindex = refChildIndex & CHUNK_MASK;
        int previousIndex = getChunkIndex(fNodePrevSib, rchunk, rindex);
        setChunkIndex(fNodePrevSib, newChildIndex, rchunk, rindex);
        setChunkIndex(fNodePrevSib, previousIndex, nchunk, nindex);

        return newChildIndex;

    
public intlookupElementDefinition(java.lang.String elementName)
Returns the index of the element definition in the table with the specified name index, or -1 if no such definition exists.


        if (fNodeCount > 1) {

            // find doctype
            int docTypeIndex = -1;
            int nchunk = 0;
            int nindex = 0;
            for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
                 index != -1;
                 index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {

                nchunk = index >> CHUNK_SHIFT;
                nindex = index  & CHUNK_MASK;
                if (getChunkIndex(fNodeType, nchunk, nindex) == Node.DOCUMENT_TYPE_NODE) {
                    docTypeIndex = index;
                    break;
                }
            }

            // find element definition
            if (docTypeIndex == -1) {
                return -1;
            }
            nchunk = docTypeIndex >> CHUNK_SHIFT;
            nindex = docTypeIndex & CHUNK_MASK;
            for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
                 index != -1;
                 index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {

                nchunk = index >> CHUNK_SHIFT;
                nindex = index & CHUNK_MASK;
                if (getChunkIndex(fNodeType, nchunk, nindex) ==
                                           NodeImpl.ELEMENT_DEFINITION_NODE
                 && getChunkValue(fNodeName, nchunk, nindex) == elementName) {
                    return index;
                }
            }
        }

        return -1;

    
public voidprint()
Prints out the tables.


        if (DEBUG_PRINT_REF_COUNTS) {
            System.out.print("num\t");
            System.out.print("type\t");
            System.out.print("name\t");
            System.out.print("val\t");
            System.out.print("par\t");
            System.out.print("lch\t");
            System.out.print("psib");
            System.out.println();
            for (int i = 0; i < fNodeType.length; i++) {
                if (fNodeType[i] != null) {
                    // separator
                    System.out.print("--------");
                    System.out.print("--------");
                    System.out.print("--------");
                    System.out.print("--------");
                    System.out.print("--------");
                    System.out.print("--------");
                    System.out.print("--------");
                    System.out.println();

                    // ref count
                    System.out.print(i);
                    System.out.print('\t");
                    switch (fNodeType[i][CHUNK_SIZE]) {
                        case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
                        case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
                        case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
                        case Node.COMMENT_NODE: { System.out.print("Com"); break; }
                        case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
                        case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
                        case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
                        case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
                        case Node.TEXT_NODE: { System.out.print("Text"); break; }
                        case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
                        case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
                        default: { System.out.print("?"+fNodeType[i][CHUNK_SIZE]); }
                    }
                    System.out.print('\t");
                    System.out.print(fNodeName[i][CHUNK_SIZE]);
                    System.out.print('\t");
                    System.out.print(fNodeValue[i][CHUNK_SIZE]);
                    System.out.print('\t");
                    System.out.print(fNodeURI[i][CHUNK_SIZE]);
                    System.out.print('\t");
                    System.out.print(fNodeParent[i][CHUNK_SIZE]);
                    System.out.print('\t");
                    System.out.print(fNodeLastChild[i][CHUNK_SIZE]);
                    System.out.print('\t");
                    System.out.print(fNodePrevSib[i][CHUNK_SIZE]);
                    System.out.print('\t");
                    System.out.print(fNodeExtra[i][CHUNK_SIZE]);
                    System.out.println();
                }
            }
        }

        if (DEBUG_PRINT_TABLES) {
            // This assumes that the document is small
            System.out.println("# start table");
            for (int i = 0; i < fNodeCount; i++) {
                int chunk = i >> CHUNK_SHIFT;
                int index = i & CHUNK_MASK;
                if (i % 10 == 0) {
                    System.out.print("num\t");
                    System.out.print("type\t");
                    System.out.print("name\t");
                    System.out.print("val\t");
                    System.out.print("uri\t");
                    System.out.print("par\t");
                    System.out.print("lch\t");
                    System.out.print("psib\t");
                    System.out.print("xtra");
                    System.out.println();
                }
                System.out.print(i);
                System.out.print('\t");
                switch (getChunkIndex(fNodeType, chunk, index)) {
                    case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
                    case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
                    case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
                    case Node.COMMENT_NODE: { System.out.print("Com"); break; }
                    case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
                    case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
                    case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
                    case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
                    case Node.TEXT_NODE: { System.out.print("Text"); break; }
                    case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
                    case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
                    default: { System.out.print("?"+getChunkIndex(fNodeType, chunk, index)); }
                }
                System.out.print('\t");
                System.out.print(getChunkValue(fNodeName, chunk, index));
                System.out.print('\t");
                System.out.print(getNodeValue(chunk, index));
                System.out.print('\t");
                System.out.print(getChunkValue(fNodeURI, chunk, index));
                System.out.print('\t");
                System.out.print(getChunkIndex(fNodeParent, chunk, index));
                System.out.print('\t");
                System.out.print(getChunkIndex(fNodeLastChild, chunk, index));
                System.out.print('\t");
                System.out.print(getChunkIndex(fNodePrevSib, chunk, index));
                System.out.print('\t");
                System.out.print(getChunkIndex(fNodeExtra, chunk, index));
                System.out.println();
            }
            System.out.println("# end table");
        }

    
private static voidprint(int[] values, int start, int end, int middle, int target)
Prints the ID array.


        if (DEBUG_IDS) {
            System.out.print(start);
            System.out.print(" [");
            for (int i = start; i < end; i++) {
                if (middle == i) {
                    System.out.print("!");
                }
                System.out.print(values[i]);
                if (values[i] == target) {
                    System.out.print("*");
                }
                if (i < end - 1) {
                    System.out.print(" ");
                }
            }
            System.out.println("] "+end);
        }

    
public voidputIdentifier(java.lang.String name, int elementNodeIndex)
Registers an identifier name with a specified element node.


        if (DEBUG_IDS) {
            System.out.println("putIdentifier(" + name + ", "
                               + elementNodeIndex + ')" + " // " +
                               getChunkValue(fNodeName,
                                             elementNodeIndex >> CHUNK_SHIFT,
                                             elementNodeIndex & CHUNK_MASK));
        }

        // initialize arrays
        if (fIdName == null) {
            fIdName    = new String[64];
            fIdElement = new int[64];
        }

        // resize arrays
        if (fIdCount == fIdName.length) {
            String idName[] = new String[fIdCount * 2];
            System.arraycopy(fIdName, 0, idName, 0, fIdCount);
            fIdName = idName;

            int idElement[] = new int[idName.length];
            System.arraycopy(fIdElement, 0, idElement, 0, fIdCount);
            fIdElement = idElement;
        }

        // store identifier
        fIdName[fIdCount] = name;
        fIdElement[fIdCount] = elementNodeIndex;
        fIdCount++;

    
private final voidputIdentifier0(java.lang.String idName, org.w3c.dom.Element element)
This version of putIdentifier is needed to avoid fluffing all of the paths to ID attributes when a node object is created that contains an ID attribute.


        if (DEBUG_IDS) {
            System.out.println("putIdentifier0("+
                               idName+", "+
                               element+')");
        }

        // create hashtable
        if (identifiers == null) {
            identifiers = new java.util.Hashtable();
        }

        // save ID and its associated element
        identifiers.put(idName, element);

    
public voidsetAsLastChild(int parentIndex, int childIndex)
Sets the last child of the parentIndex to childIndex.

        int pchunk = parentIndex >> CHUNK_SHIFT;
        int pindex = parentIndex & CHUNK_MASK;
        setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
    
public intsetAttributeNode(int elemIndex, int attrIndex)
Adds an attribute node to the specified element.


        int echunk = elemIndex >> CHUNK_SHIFT;
        int eindex = elemIndex & CHUNK_MASK;
        int achunk = attrIndex >> CHUNK_SHIFT;
        int aindex = attrIndex & CHUNK_MASK;

        // see if this attribute is already here
        String attrName = getChunkValue(fNodeName, achunk, aindex);
        int oldAttrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
        int nextIndex = -1;
        int oachunk = -1;
        int oaindex = -1;
        while (oldAttrIndex != -1) {
            oachunk = oldAttrIndex >> CHUNK_SHIFT;
            oaindex = oldAttrIndex & CHUNK_MASK;
            String oldAttrName = getChunkValue(fNodeName, oachunk, oaindex);
            if (oldAttrName.equals(attrName)) {
                break;
            }
            nextIndex = oldAttrIndex;
            oldAttrIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
        }

        // remove old attribute
        if (oldAttrIndex != -1) {

            // patch links
            int prevIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
            if (nextIndex == -1) {
                setChunkIndex(fNodeExtra, prevIndex, echunk, eindex);
            }
            else {
                int pchunk = nextIndex >> CHUNK_SHIFT;
                int pindex = nextIndex & CHUNK_MASK;
                setChunkIndex(fNodePrevSib, prevIndex, pchunk, pindex);
            }

            // remove connections to siblings
            clearChunkIndex(fNodeType, oachunk, oaindex);
            clearChunkValue(fNodeName, oachunk, oaindex);
            clearChunkValue(fNodeValue, oachunk, oaindex);
            clearChunkIndex(fNodeParent, oachunk, oaindex);
            clearChunkIndex(fNodePrevSib, oachunk, oaindex);
            int attrTextIndex =
                clearChunkIndex(fNodeLastChild, oachunk, oaindex);
            int atchunk = attrTextIndex >> CHUNK_SHIFT;
            int atindex = attrTextIndex & CHUNK_MASK;
            clearChunkIndex(fNodeType, atchunk, atindex);
            clearChunkValue(fNodeValue, atchunk, atindex);
            clearChunkIndex(fNodeParent, atchunk, atindex);
            clearChunkIndex(fNodeLastChild, atchunk, atindex);
        }

        // add new attribute
        int prevIndex = getChunkIndex(fNodeExtra, echunk, eindex);
        setChunkIndex(fNodeExtra, attrIndex, echunk, eindex);
        setChunkIndex(fNodePrevSib, prevIndex, achunk, aindex);

        // return
        return oldAttrIndex;

    
private final intsetChunkIndex(int[][] data, int value, int chunk, int index)
Sets the specified value in the given of data at the chunk and index.

return
Returns the old value.

        if (value == -1) {
            return clearChunkIndex(data, chunk, index);
        }
        int [] dataChunk = data[chunk];
        // Re-create chunk if it was deleted.
        if (dataChunk == null) {
            createChunk(data, chunk);
            dataChunk = data[chunk];
        }
        int ovalue = dataChunk[index];
        if (ovalue == -1) {
            dataChunk[CHUNK_SIZE]++;
        }
        dataChunk[index] = value;
        return ovalue;
    
private final java.lang.StringsetChunkValue(java.lang.Object[][] data, java.lang.Object value, int chunk, int index)

        if (value == null) {
            return clearChunkValue(data, chunk, index);
        }
        Object [] dataChunk = data[chunk];
        // Re-create chunk if it was deleted.
        if (dataChunk == null) {
            createChunk(data, chunk);
            dataChunk = data[chunk];
        }
        String ovalue = (String) dataChunk[index];
        if (ovalue == null) {
            RefCount c = (RefCount) dataChunk[CHUNK_SIZE];
            c.fCount++;
        }
        dataChunk[index] = value;
        return ovalue;
    
public intsetDeferredAttribute(int elementNodeIndex, java.lang.String attrName, java.lang.String attrURI, java.lang.String attrValue, boolean specified, boolean id, java.lang.Object type)
This method is used by the DOMParser to create attributes.

param
elementNodeIndex
param
attrName
param
attrURI
param
attrValue
param
specified
param
id
param
type
return
int

                                    
		// create attribute
		int attrNodeIndex = createDeferredAttribute(attrName, attrURI, attrValue, specified);
		int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
		int attrIndex = attrNodeIndex & CHUNK_MASK;
		// set attribute's parent to element
		setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);

		int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
		int elementIndex = elementNodeIndex & CHUNK_MASK;

		// get element's last attribute
		int lastAttrNodeIndex = getChunkIndex(fNodeExtra, elementChunk, elementIndex);
		if (lastAttrNodeIndex != 0) {
			// add link from new attribute to last attribute
			setChunkIndex(fNodePrevSib, lastAttrNodeIndex, attrChunk, attrIndex);
		}
		// add link from element to new last attribute
		setChunkIndex(fNodeExtra, attrNodeIndex, elementChunk, elementIndex);

		int extra = getChunkIndex(fNodeExtra, attrChunk, attrIndex);
		if (id) {
			extra = extra | ID;
			setChunkIndex(fNodeExtra, extra, attrChunk, attrIndex);
			String value = getChunkValue(fNodeValue, attrChunk, attrIndex);
			putIdentifier(value, elementNodeIndex);
		}
		// store type information
		if (type != null) {
			int extraDataIndex = createNode(DeferredNode.TYPE_NODE);
			int echunk = extraDataIndex >> CHUNK_SHIFT;
			int eindex = extraDataIndex & CHUNK_MASK;

			setChunkIndex(fNodeLastChild, extraDataIndex, attrChunk, attrIndex);
			setChunkValue(fNodeValue, type, echunk, eindex);
		}

		// return node index
		return attrNodeIndex;
	
public intsetDeferredAttribute(int elementNodeIndex, java.lang.String attrName, java.lang.String attrURI, java.lang.String attrValue, boolean specified)
Sets an attribute on an element node.

deprecated

        // create attribute
        int attrNodeIndex = createDeferredAttribute(attrName, attrURI,
                                                    attrValue, specified);
        int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
        int attrIndex  = attrNodeIndex & CHUNK_MASK;
        // set attribute's parent to element
        setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);

        int elementChunk     = elementNodeIndex >> CHUNK_SHIFT;
        int elementIndex     = elementNodeIndex & CHUNK_MASK;

        // get element's last attribute
        int lastAttrNodeIndex = getChunkIndex(fNodeExtra,
                                              elementChunk, elementIndex);
        if (lastAttrNodeIndex != 0) {
            // add link from new attribute to last attribute
            setChunkIndex(fNodePrevSib, lastAttrNodeIndex,
                          attrChunk, attrIndex);
        }
        // add link from element to new last attribute
        setChunkIndex(fNodeExtra, attrNodeIndex,
                      elementChunk, elementIndex);
 
        // return node index
        return attrNodeIndex;

    
public voidsetEntityInfo(int currentEntityDecl, java.lang.String version, java.lang.String encoding)

        int eNodeIndex = getNodeExtra(currentEntityDecl, false);
        if (eNodeIndex !=-1) {
            int echunk = eNodeIndex >> CHUNK_SHIFT;
            int eindex = eNodeIndex & CHUNK_MASK;
            setChunkValue(fNodeValue, version, echunk, eindex);
            setChunkValue(fNodeURI, encoding, echunk, eindex);
        }
    
public voidsetIdAttribute(int attrIndex)
Sets type of attribute


        int chunk = attrIndex >> CHUNK_SHIFT;
        int index = attrIndex & CHUNK_MASK;
        int extra = getChunkIndex(fNodeExtra, chunk, index);
        extra = extra | ID;
        setChunkIndex(fNodeExtra, extra, chunk, index);
    
public voidsetIdAttributeNode(int elemIndex, int attrIndex)
Adds an attribute node to the specified element.


        int chunk = attrIndex >> CHUNK_SHIFT;
        int index = attrIndex & CHUNK_MASK;
        int extra = getChunkIndex(fNodeExtra, chunk, index);
        extra = extra | ID;
        setChunkIndex(fNodeExtra, extra, chunk, index);

        String value = getChunkValue(fNodeValue, chunk, index);
        putIdentifier(value, elemIndex);
    
public voidsetInputEncoding(int currentEntityDecl, java.lang.String value)
DOM Internal An attribute specifying the actual encoding of this document. This is null otherwise.
This attribute represents the property [character encoding scheme] defined in .

        // get first extra data chunk
        int nodeIndex = getNodeExtra(currentEntityDecl, false);
        // get second extra data chunk
        int extraDataIndex = getNodeExtra(nodeIndex, false);

        int echunk = extraDataIndex >> CHUNK_SHIFT;
        int eindex = extraDataIndex & CHUNK_MASK;
        
        setChunkValue(fNodeValue, value, echunk, eindex);
        
    
public voidsetInternalSubset(int doctypeIndex, java.lang.String subset)

        int chunk     = doctypeIndex >> CHUNK_SHIFT;
        int index     = doctypeIndex & CHUNK_MASK;

        // create extra data node to store internal subset
        int extraDataIndex = createNode(Node.DOCUMENT_TYPE_NODE); 
        int echunk = extraDataIndex >> CHUNK_SHIFT;
        int eindex = extraDataIndex & CHUNK_MASK;
        setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);        
        setChunkValue(fNodeValue, subset, echunk, eindex);
    
voidsetNamespacesEnabled(boolean enable)

        fNamespacesEnabled = enable;
    
public voidsetTypeInfo(int elementNodeIndex, java.lang.Object type)

        int elementChunk     = elementNodeIndex >> CHUNK_SHIFT;
        int elementIndex     = elementNodeIndex & CHUNK_MASK;
        setChunkValue(fNodeValue, type, elementChunk, elementIndex);
    
protected voidsynchronizeChildren()
Synchronizes the node's children with the internal structure. Fluffing the children at once solves a lot of work to keep the two structures in sync. The problem gets worse when editing the tree -- this makes it a lot easier.


        if (needsSyncData()) {
            synchronizeData();
            /*
             * when we have elements with IDs this method is being recursively
             * called from synchronizeData, in which case we've already gone
             * through the following and we can now simply stop here.
             */
            if (!needsSyncChildren()) {
                return;
            }
        }

        // we don't want to generate any event for this so turn them off
        boolean orig = mutationEvents;
        mutationEvents = false;

        // no need to sync in the future
        needsSyncChildren(false);

        getNodeType(0);

        // create children and link them as siblings
        ChildNode first = null;
        ChildNode last = null;
        for (int index = getLastChild(0);
             index != -1;
             index = getPrevSibling(index)) {

            ChildNode node = (ChildNode)getNodeObject(index);
            if (last == null) {
                last = node;
            }
            else {
                first.previousSibling = node;
            }
            node.ownerNode = this;
            node.isOwned(true);
            node.nextSibling = first;
            first = node;

            // save doctype and document type
            int type = node.getNodeType();
            if (type == Node.ELEMENT_NODE) {
                docElement = (ElementImpl)node;
            }
            else if (type == Node.DOCUMENT_TYPE_NODE) {
                docType = (DocumentTypeImpl)node;
            }
        }

        if (first != null) {
            firstChild = first;
            first.isFirstChild(true);
            lastChild(last);
        }

        // set mutation events flag back to its original value
        mutationEvents = orig;

    
protected final voidsynchronizeChildren(AttrImpl a, int nodeIndex)
Synchronizes the node's children with the internal structure. Fluffing the children at once solves a lot of work to keep the two structures in sync. The problem gets worse when editing the tree -- this makes it a lot easier. This is not directly used in this class but this method is here so that it can be shared by all deferred subclasses of AttrImpl.


        // we don't want to generate any event for this so turn them off
        boolean orig = getMutationEvents();
        setMutationEvents(false);

        // no need to sync in the future
        a.needsSyncChildren(false);

        // create children and link them as siblings or simply store the value
        // as a String if all we have is one piece of text
        int last = getLastChild(nodeIndex);
        int prev = getPrevSibling(last);
        if (prev == -1) {
            a.value = getNodeValueString(nodeIndex);
            a.hasStringValue(true);
        }
        else {
            ChildNode firstNode = null;
            ChildNode lastNode = null;
            for (int index = last; index != -1;
                 index = getPrevSibling(index)) {

                ChildNode node = (ChildNode) getNodeObject(index);
                if (lastNode == null) {
                    lastNode = node;
                }
                else {
                    firstNode.previousSibling = node;
                }
                node.ownerNode = a;
                node.isOwned(true);
                node.nextSibling = firstNode;
                firstNode = node;
            }
            if (lastNode != null) {
                a.value = firstNode; // firstChild = firstNode
                firstNode.isFirstChild(true);
                a.lastChild(lastNode);
            }
            a.hasStringValue(false);
        }

        // set mutation events flag back to its original value
        setMutationEvents(orig);

    
protected final voidsynchronizeChildren(ParentNode p, int nodeIndex)
Synchronizes the node's children with the internal structure. Fluffing the children at once solves a lot of work to keep the two structures in sync. The problem gets worse when editing the tree -- this makes it a lot easier. This is not directly used in this class but this method is here so that it can be shared by all deferred subclasses of ParentNode.


        // we don't want to generate any event for this so turn them off
        boolean orig = getMutationEvents();
        setMutationEvents(false);

        // no need to sync in the future
        p.needsSyncChildren(false);

        // create children and link them as siblings
        ChildNode firstNode = null;
        ChildNode lastNode = null;
        for (int index = getLastChild(nodeIndex);
             index != -1;
             index = getPrevSibling(index)) {

            ChildNode node = (ChildNode) getNodeObject(index);
            if (lastNode == null) {
                lastNode = node;
            }
            else {
                firstNode.previousSibling = node;
            }
            node.ownerNode = p;
            node.isOwned(true);
            node.nextSibling = firstNode;
            firstNode = node;
        }
        if (lastNode != null) {
            p.firstChild = firstNode;
            firstNode.isFirstChild(true);
            p.lastChild(lastNode);
        }

        // set mutation events flag back to its original value
        setMutationEvents(orig);

    
protected voidsynchronizeData()
Synchronizes the node's data.


        // no need to sync in the future
        needsSyncData(false);

        // fluff up enough nodes to fill identifiers hash
        if (fIdElement != null) {

            // REVISIT: There has to be a more efficient way of
            //          doing this. But keep in mind that the
            //          tree can have been altered and re-ordered
            //          before all of the element nodes with ID
            //          attributes have been registered. For now
            //          this is reasonable and safe. -Ac

            IntVector path = new IntVector();
            for (int i = 0; i < fIdCount; i++) {

                // ignore if it's already been registered
                int elementNodeIndex = fIdElement[i];
                String idName      = fIdName[i];
                if (idName == null) {
                    continue;
                }

                // find path from this element to the root
                path.removeAllElements();
                int index = elementNodeIndex;
                do {
                    path.addElement(index);
                    int pchunk = index >> CHUNK_SHIFT;
                    int pindex = index & CHUNK_MASK;
                    index = getChunkIndex(fNodeParent, pchunk, pindex);
                } while (index != -1);

                // Traverse path (backwards), fluffing the elements
                // along the way. When this loop finishes, "place"
                // will contain the reference to the element node
                // we're interested in. -Ac
                Node place = this;
                for (int j = path.size() - 2; j >= 0; j--) {
                    index = path.elementAt(j);
                    Node child = place.getLastChild();
                    while (child != null) {
                        if (child instanceof DeferredNode) {
                            int nodeIndex =
                                ((DeferredNode)child).getNodeIndex();
                            if (nodeIndex == index) {
                                place = child;
                                break;
                            }
                        }
                        child = child.getPreviousSibling();
                    }
                }

                // register the element
                Element element = (Element)place;
                putIdentifier0(idName, element);
                fIdName[i] = null;

                // see if there are more IDs on this element
                while (i + 1 < fIdCount &&
                    fIdElement[i + 1] == elementNodeIndex) {
                    idName = fIdName[++i];
                    if (idName == null) {
                        continue;
                    }
                    putIdentifier0(idName, element);
                }
            }

        } // if identifiers