Source Code Cross Referenced for DeferredDocumentImpl.java in  » XML » xerces-2_9_1 » org » apache » xerces » dom » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » xerces 2_9_1 » org.apache.xerces.dom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.xerces.dom;
0019:
0020:        import org.w3c.dom.DOMImplementation;
0021:        import org.w3c.dom.Element;
0022:        import org.w3c.dom.Node;
0023:
0024:        import java.util.Vector;
0025:
0026:        /**
0027:         * The Document interface represents the entire HTML or XML document.
0028:         * Conceptually, it is the root of the document tree, and provides the
0029:         * primary access to the document's data.
0030:         * <P>
0031:         * Since elements, text nodes, comments, processing instructions,
0032:         * etc. cannot exist outside the context of a Document, the Document
0033:         * interface also contains the factory methods needed to create these
0034:         * objects. The Node objects created have a ownerDocument attribute
0035:         * which associates them with the Document within whose context they
0036:         * were created.
0037:         * 
0038:         * @xerces.internal
0039:         *
0040:         * @version $Id: DeferredDocumentImpl.java 511134 2007-02-23 22:08:04Z mrglavas $
0041:         * @since  PR-DOM-Level-1-19980818.
0042:         */
0043:        public class DeferredDocumentImpl extends DocumentImpl implements 
0044:                DeferredNode {
0045:
0046:            //
0047:            // Constants
0048:            //
0049:
0050:            /** Serialization version. */
0051:            static final long serialVersionUID = 5186323580749626857L;
0052:
0053:            // debugging
0054:
0055:            /** To include code for printing the ref count tables. */
0056:            private static final boolean DEBUG_PRINT_REF_COUNTS = false;
0057:
0058:            /** To include code for printing the internal tables. */
0059:            private static final boolean DEBUG_PRINT_TABLES = false;
0060:
0061:            /** To debug identifiers set to true and recompile. */
0062:            private static final boolean DEBUG_IDS = false;
0063:
0064:            // protected
0065:
0066:            /** Chunk shift. */
0067:            protected static final int CHUNK_SHIFT = 11; // 2^11 = 2k
0068:
0069:            /** Chunk size. */
0070:            protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
0071:
0072:            /** Chunk mask. */
0073:            protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
0074:
0075:            /** Initial chunk size. */
0076:            protected static final int INITIAL_CHUNK_COUNT = (1 << (16 - CHUNK_SHIFT)); // 2^16 = 64k
0077:
0078:            //
0079:            // Data
0080:            //
0081:
0082:            // lazy-eval information
0083:            // To maximize memory consumption the actual semantic of these fields vary
0084:            // depending on the node type.
0085:
0086:            /** Node count. */
0087:            protected transient int fNodeCount = 0;
0088:
0089:            /** Node types. */
0090:            protected transient int fNodeType[][];
0091:
0092:            /** Node names. */
0093:            protected transient Object fNodeName[][];
0094:
0095:            /** Node values. */
0096:            protected transient Object fNodeValue[][];
0097:
0098:            /** Node parents. */
0099:            protected transient int fNodeParent[][];
0100:
0101:            /** Node first children. */
0102:            protected transient int fNodeLastChild[][];
0103:
0104:            /** Node prev siblings. */
0105:            protected transient int fNodePrevSib[][];
0106:
0107:            /** Node namespace URI. */
0108:            protected transient Object fNodeURI[][];
0109:
0110:            /** Extra data. */
0111:            protected transient int fNodeExtra[][];
0112:
0113:            /** Identifier count. */
0114:            protected transient int fIdCount;
0115:
0116:            /** Identifier name indexes. */
0117:            protected transient String fIdName[];
0118:
0119:            /** Identifier element indexes. */
0120:            protected transient int fIdElement[];
0121:
0122:            /** DOM2: For namespace support in the deferred case.
0123:             */
0124:            // Implementation Note: The deferred element and attribute must know how to
0125:            // interpret the int representing the qname.
0126:            protected boolean fNamespacesEnabled = false;
0127:
0128:            //
0129:            // private data
0130:            //
0131:            private transient final StringBuffer fBufferStr = new StringBuffer();
0132:            private transient final Vector fStrChunks = new Vector();
0133:
0134:            //
0135:            // Constructors
0136:            //
0137:
0138:            /**
0139:             * NON-DOM: Actually creating a Document is outside the DOM's spec,
0140:             * since it has to operate in terms of a particular implementation.
0141:             */
0142:            public DeferredDocumentImpl() {
0143:                this (false);
0144:            } // <init>()
0145:
0146:            /**
0147:             * NON-DOM: Actually creating a Document is outside the DOM's spec,
0148:             * since it has to operate in terms of a particular implementation.
0149:             */
0150:            public DeferredDocumentImpl(boolean namespacesEnabled) {
0151:                this (namespacesEnabled, false);
0152:            } // <init>(boolean)
0153:
0154:            /** Experimental constructor. */
0155:            public DeferredDocumentImpl(boolean namespaces,
0156:                    boolean grammarAccess) {
0157:                super (grammarAccess);
0158:
0159:                needsSyncData(true);
0160:                needsSyncChildren(true);
0161:
0162:                fNamespacesEnabled = namespaces;
0163:
0164:            } // <init>(boolean,boolean)
0165:
0166:            //
0167:            // Public methods
0168:            //
0169:
0170:            /**
0171:             * Retrieve information describing the abilities of this particular
0172:             * DOM implementation. Intended to support applications that may be
0173:             * using DOMs retrieved from several different sources, potentially
0174:             * with different underlying representations.
0175:             */
0176:            public DOMImplementation getImplementation() {
0177:                // Currently implemented as a singleton, since it's hardcoded
0178:                // information anyway.
0179:                return DeferredDOMImplementationImpl.getDOMImplementation();
0180:            }
0181:
0182:            /** Returns the cached parser.getNamespaces() value.*/
0183:            boolean getNamespacesEnabled() {
0184:                return fNamespacesEnabled;
0185:            }
0186:
0187:            void setNamespacesEnabled(boolean enable) {
0188:                fNamespacesEnabled = enable;
0189:            }
0190:
0191:            // internal factory methods
0192:
0193:            /** Creates a document node in the table. */
0194:            public int createDeferredDocument() {
0195:                int nodeIndex = createNode(Node.DOCUMENT_NODE);
0196:                return nodeIndex;
0197:            }
0198:
0199:            /** Creates a doctype. */
0200:            public int createDeferredDocumentType(String rootElementName,
0201:                    String publicId, String systemId) {
0202:
0203:                // create node
0204:                int nodeIndex = createNode(Node.DOCUMENT_TYPE_NODE);
0205:                int chunk = nodeIndex >> CHUNK_SHIFT;
0206:                int index = nodeIndex & CHUNK_MASK;
0207:
0208:                // save name, public id, system id
0209:                setChunkValue(fNodeName, rootElementName, chunk, index);
0210:                setChunkValue(fNodeValue, publicId, chunk, index);
0211:                setChunkValue(fNodeURI, systemId, chunk, index);
0212:
0213:                // return node index
0214:                return nodeIndex;
0215:
0216:            } // createDeferredDocumentType(String,String,String):int
0217:
0218:            public void setInternalSubset(int doctypeIndex, String subset) {
0219:                int chunk = doctypeIndex >> CHUNK_SHIFT;
0220:                int index = doctypeIndex & CHUNK_MASK;
0221:
0222:                // create extra data node to store internal subset
0223:                int extraDataIndex = createNode(Node.DOCUMENT_TYPE_NODE);
0224:                int echunk = extraDataIndex >> CHUNK_SHIFT;
0225:                int eindex = extraDataIndex & CHUNK_MASK;
0226:                setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
0227:                setChunkValue(fNodeValue, subset, echunk, eindex);
0228:            }
0229:
0230:            /** Creates a notation in the table. */
0231:            public int createDeferredNotation(String notationName,
0232:                    String publicId, String systemId, String baseURI) {
0233:
0234:                // create node
0235:                int nodeIndex = createNode(Node.NOTATION_NODE);
0236:                int chunk = nodeIndex >> CHUNK_SHIFT;
0237:                int index = nodeIndex & CHUNK_MASK;
0238:
0239:                // create extra data node
0240:                int extraDataIndex = createNode(Node.NOTATION_NODE);
0241:                int echunk = extraDataIndex >> CHUNK_SHIFT;
0242:                int eindex = extraDataIndex & CHUNK_MASK;
0243:
0244:                // save name, public id, system id, and notation name
0245:                setChunkValue(fNodeName, notationName, chunk, index);
0246:                setChunkValue(fNodeValue, publicId, chunk, index);
0247:                setChunkValue(fNodeURI, systemId, chunk, index);
0248:
0249:                // in extra data node set baseURI value
0250:                setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
0251:                setChunkValue(fNodeName, baseURI, echunk, eindex);
0252:
0253:                // return node index
0254:                return nodeIndex;
0255:
0256:            } // createDeferredNotation(String,String,String):int
0257:
0258:            /** Creates an entity in the table. */
0259:            public int createDeferredEntity(String entityName, String publicId,
0260:                    String systemId, String notationName, String baseURI) {
0261:                // create node
0262:                int nodeIndex = createNode(Node.ENTITY_NODE);
0263:                int chunk = nodeIndex >> CHUNK_SHIFT;
0264:                int index = nodeIndex & CHUNK_MASK;
0265:
0266:                // create extra data node
0267:                int extraDataIndex = createNode(Node.ENTITY_NODE);
0268:                int echunk = extraDataIndex >> CHUNK_SHIFT;
0269:                int eindex = extraDataIndex & CHUNK_MASK;
0270:
0271:                // save name, public id, system id, and notation name
0272:                setChunkValue(fNodeName, entityName, chunk, index);
0273:                setChunkValue(fNodeValue, publicId, chunk, index);
0274:                setChunkValue(fNodeURI, systemId, chunk, index);
0275:                setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
0276:                // set other values in the extra chunk
0277:                // notation
0278:                setChunkValue(fNodeName, notationName, echunk, eindex);
0279:                // version  L3
0280:                setChunkValue(fNodeValue, null, echunk, eindex);
0281:                // encoding L3
0282:                setChunkValue(fNodeURI, null, echunk, eindex);
0283:
0284:                int extraDataIndex2 = createNode(Node.ENTITY_NODE);
0285:                int echunk2 = extraDataIndex2 >> CHUNK_SHIFT;
0286:                int eindex2 = extraDataIndex2 & CHUNK_MASK;
0287:
0288:                setChunkIndex(fNodeExtra, extraDataIndex2, echunk, eindex);
0289:
0290:                // baseURI
0291:                setChunkValue(fNodeName, baseURI, echunk2, eindex2);
0292:
0293:                // return node index
0294:                return nodeIndex;
0295:
0296:            } // createDeferredEntity(String,String,String,String):int
0297:
0298:            public String getDeferredEntityBaseURI(int entityIndex) {
0299:                if (entityIndex != -1) {
0300:                    int extraDataIndex = getNodeExtra(entityIndex, false);
0301:                    extraDataIndex = getNodeExtra(extraDataIndex, false);
0302:                    return getNodeName(extraDataIndex, false);
0303:                }
0304:                return null;
0305:            }
0306:
0307:            // DOM Level 3: setting encoding and version
0308:            public void setEntityInfo(int currentEntityDecl, String version,
0309:                    String encoding) {
0310:                int eNodeIndex = getNodeExtra(currentEntityDecl, false);
0311:                if (eNodeIndex != -1) {
0312:                    int echunk = eNodeIndex >> CHUNK_SHIFT;
0313:                    int eindex = eNodeIndex & CHUNK_MASK;
0314:                    setChunkValue(fNodeValue, version, echunk, eindex);
0315:                    setChunkValue(fNodeURI, encoding, echunk, eindex);
0316:                }
0317:            }
0318:
0319:            // DOM Level 3: sets element TypeInfo
0320:            public void setTypeInfo(int elementNodeIndex, Object type) {
0321:                int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
0322:                int elementIndex = elementNodeIndex & CHUNK_MASK;
0323:                setChunkValue(fNodeValue, type, elementChunk, elementIndex);
0324:            }
0325:
0326:            /**
0327:             * DOM Internal 
0328:             *
0329:             * An attribute specifying the actual encoding of this document. This is
0330:             * <code>null</code> otherwise.
0331:             * <br> This attribute represents the property [character encoding scheme]
0332:             * defined in .
0333:             */
0334:            public void setInputEncoding(int currentEntityDecl, String value) {
0335:                // get first extra data chunk
0336:                int nodeIndex = getNodeExtra(currentEntityDecl, false);
0337:                // get second extra data chunk
0338:                int extraDataIndex = getNodeExtra(nodeIndex, false);
0339:
0340:                int echunk = extraDataIndex >> CHUNK_SHIFT;
0341:                int eindex = extraDataIndex & CHUNK_MASK;
0342:
0343:                setChunkValue(fNodeValue, value, echunk, eindex);
0344:
0345:            }
0346:
0347:            /** Creates an entity reference node in the table. */
0348:            public int createDeferredEntityReference(String name, String baseURI) {
0349:
0350:                // create node
0351:                int nodeIndex = createNode(Node.ENTITY_REFERENCE_NODE);
0352:                int chunk = nodeIndex >> CHUNK_SHIFT;
0353:                int index = nodeIndex & CHUNK_MASK;
0354:                setChunkValue(fNodeName, name, chunk, index);
0355:                setChunkValue(fNodeValue, baseURI, chunk, index);
0356:
0357:                // return node index
0358:                return nodeIndex;
0359:
0360:            } // createDeferredEntityReference(String):int
0361:
0362:            /** 
0363:             * Creates an element node with a URI in the table and type information.
0364:             * @deprecated
0365:             */
0366:            public int createDeferredElement(String elementURI,
0367:                    String elementName, Object type) {
0368:
0369:                // create node
0370:                int elementNodeIndex = createNode(Node.ELEMENT_NODE);
0371:                int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
0372:                int elementIndex = elementNodeIndex & CHUNK_MASK;
0373:                setChunkValue(fNodeName, elementName, elementChunk,
0374:                        elementIndex);
0375:                setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
0376:                setChunkValue(fNodeValue, type, elementChunk, elementIndex);
0377:
0378:                // return node index
0379:                return elementNodeIndex;
0380:
0381:            } // createDeferredElement(String,String,Object):int
0382:
0383:            /** 
0384:             * Creates an element node in the table.
0385:             * @deprecated 
0386:             */
0387:            public int createDeferredElement(String elementName) {
0388:                return createDeferredElement(null, elementName);
0389:            }
0390:
0391:            /** 
0392:             * Creates an element node with a URI in the table. 
0393:             */
0394:            public int createDeferredElement(String elementURI,
0395:                    String elementName) {
0396:
0397:                // create node
0398:                int elementNodeIndex = createNode(Node.ELEMENT_NODE);
0399:                int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
0400:                int elementIndex = elementNodeIndex & CHUNK_MASK;
0401:                setChunkValue(fNodeName, elementName, elementChunk,
0402:                        elementIndex);
0403:                setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
0404:
0405:                // return node index
0406:                return elementNodeIndex;
0407:
0408:            } // createDeferredElement(String,String):int
0409:
0410:            /**
0411:             * This method is used by the DOMParser to create attributes.
0412:             * @param elementNodeIndex
0413:             * @param attrName
0414:             * @param attrURI
0415:             * @param attrValue
0416:             * @param specified
0417:             * @param id
0418:             * @param type
0419:             * @return int
0420:             */
0421:            public int setDeferredAttribute(int elementNodeIndex,
0422:                    String attrName, String attrURI, String attrValue,
0423:                    boolean specified, boolean id, Object type) {
0424:
0425:                // create attribute
0426:                int attrNodeIndex = createDeferredAttribute(attrName, attrURI,
0427:                        attrValue, specified);
0428:                int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
0429:                int attrIndex = attrNodeIndex & CHUNK_MASK;
0430:                // set attribute's parent to element
0431:                setChunkIndex(fNodeParent, elementNodeIndex, attrChunk,
0432:                        attrIndex);
0433:
0434:                int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
0435:                int elementIndex = elementNodeIndex & CHUNK_MASK;
0436:
0437:                // get element's last attribute
0438:                int lastAttrNodeIndex = getChunkIndex(fNodeExtra, elementChunk,
0439:                        elementIndex);
0440:                if (lastAttrNodeIndex != 0) {
0441:                    // add link from new attribute to last attribute
0442:                    setChunkIndex(fNodePrevSib, lastAttrNodeIndex, attrChunk,
0443:                            attrIndex);
0444:                }
0445:                // add link from element to new last attribute
0446:                setChunkIndex(fNodeExtra, attrNodeIndex, elementChunk,
0447:                        elementIndex);
0448:
0449:                int extra = getChunkIndex(fNodeExtra, attrChunk, attrIndex);
0450:                if (id) {
0451:                    extra = extra | ID;
0452:                    setChunkIndex(fNodeExtra, extra, attrChunk, attrIndex);
0453:                    String value = getChunkValue(fNodeValue, attrChunk,
0454:                            attrIndex);
0455:                    putIdentifier(value, elementNodeIndex);
0456:                }
0457:                // store type information
0458:                if (type != null) {
0459:                    int extraDataIndex = createNode(DeferredNode.TYPE_NODE);
0460:                    int echunk = extraDataIndex >> CHUNK_SHIFT;
0461:                    int eindex = extraDataIndex & CHUNK_MASK;
0462:
0463:                    setChunkIndex(fNodeLastChild, extraDataIndex, attrChunk,
0464:                            attrIndex);
0465:                    setChunkValue(fNodeValue, type, echunk, eindex);
0466:                }
0467:
0468:                // return node index
0469:                return attrNodeIndex;
0470:            }
0471:
0472:            /**  
0473:             * Sets an attribute on an element node.
0474:             * @deprecated
0475:             */
0476:            public int setDeferredAttribute(int elementNodeIndex,
0477:                    String attrName, String attrURI, String attrValue,
0478:                    boolean specified) {
0479:                // create attribute
0480:                int attrNodeIndex = createDeferredAttribute(attrName, attrURI,
0481:                        attrValue, specified);
0482:                int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
0483:                int attrIndex = attrNodeIndex & CHUNK_MASK;
0484:                // set attribute's parent to element
0485:                setChunkIndex(fNodeParent, elementNodeIndex, attrChunk,
0486:                        attrIndex);
0487:
0488:                int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
0489:                int elementIndex = elementNodeIndex & CHUNK_MASK;
0490:
0491:                // get element's last attribute
0492:                int lastAttrNodeIndex = getChunkIndex(fNodeExtra, elementChunk,
0493:                        elementIndex);
0494:                if (lastAttrNodeIndex != 0) {
0495:                    // add link from new attribute to last attribute
0496:                    setChunkIndex(fNodePrevSib, lastAttrNodeIndex, attrChunk,
0497:                            attrIndex);
0498:                }
0499:                // add link from element to new last attribute
0500:                setChunkIndex(fNodeExtra, attrNodeIndex, elementChunk,
0501:                        elementIndex);
0502:
0503:                // return node index
0504:                return attrNodeIndex;
0505:
0506:            } // setDeferredAttribute(int,String,String,String,boolean):int
0507:
0508:            /** Creates an attribute in the table. */
0509:            public int createDeferredAttribute(String attrName,
0510:                    String attrValue, boolean specified) {
0511:                return createDeferredAttribute(attrName, null, attrValue,
0512:                        specified);
0513:            }
0514:
0515:            /** Creates an attribute with a URI in the table. */
0516:            public int createDeferredAttribute(String attrName, String attrURI,
0517:                    String attrValue, boolean specified) {
0518:
0519:                // create node
0520:                int nodeIndex = createNode(NodeImpl.ATTRIBUTE_NODE);
0521:                int chunk = nodeIndex >> CHUNK_SHIFT;
0522:                int index = nodeIndex & CHUNK_MASK;
0523:                setChunkValue(fNodeName, attrName, chunk, index);
0524:                setChunkValue(fNodeURI, attrURI, chunk, index);
0525:                setChunkValue(fNodeValue, attrValue, chunk, index);
0526:                int extra = specified ? SPECIFIED : 0;
0527:                setChunkIndex(fNodeExtra, extra, chunk, index);
0528:
0529:                // return node index
0530:                return nodeIndex;
0531:
0532:            } // createDeferredAttribute(String,String,String,boolean):int
0533:
0534:            /** Creates an element definition in the table.*/
0535:            public int createDeferredElementDefinition(String elementName) {
0536:
0537:                // create node
0538:                int nodeIndex = createNode(NodeImpl.ELEMENT_DEFINITION_NODE);
0539:                int chunk = nodeIndex >> CHUNK_SHIFT;
0540:                int index = nodeIndex & CHUNK_MASK;
0541:                setChunkValue(fNodeName, elementName, chunk, index);
0542:
0543:                // return node index
0544:                return nodeIndex;
0545:
0546:            } // createDeferredElementDefinition(String):int
0547:
0548:            /** Creates a text node in the table. */
0549:            public int createDeferredTextNode(String data,
0550:                    boolean ignorableWhitespace) {
0551:
0552:                // create node
0553:                int nodeIndex = createNode(Node.TEXT_NODE);
0554:                int chunk = nodeIndex >> CHUNK_SHIFT;
0555:                int index = nodeIndex & CHUNK_MASK;
0556:                setChunkValue(fNodeValue, data, chunk, index);
0557:                // use extra to store ignorableWhitespace info
0558:                setChunkIndex(fNodeExtra, ignorableWhitespace ? 1 : 0, chunk,
0559:                        index);
0560:
0561:                // return node index
0562:                return nodeIndex;
0563:
0564:            } // createDeferredTextNode(String,boolean):int
0565:
0566:            /** Creates a CDATA section node in the table. */
0567:            public int createDeferredCDATASection(String data) {
0568:
0569:                // create node
0570:                int nodeIndex = createNode(Node.CDATA_SECTION_NODE);
0571:                int chunk = nodeIndex >> CHUNK_SHIFT;
0572:                int index = nodeIndex & CHUNK_MASK;
0573:                setChunkValue(fNodeValue, data, chunk, index);
0574:
0575:                // return node index
0576:                return nodeIndex;
0577:
0578:            } // createDeferredCDATASection(String):int
0579:
0580:            /** Creates a processing instruction node in the table. */
0581:            public int createDeferredProcessingInstruction(String target,
0582:                    String data) {
0583:                // create node
0584:                int nodeIndex = createNode(Node.PROCESSING_INSTRUCTION_NODE);
0585:                int chunk = nodeIndex >> CHUNK_SHIFT;
0586:                int index = nodeIndex & CHUNK_MASK;
0587:                setChunkValue(fNodeName, target, chunk, index);
0588:                setChunkValue(fNodeValue, data, chunk, index);
0589:                // return node index
0590:                return nodeIndex;
0591:
0592:            } // createDeferredProcessingInstruction(String,String):int
0593:
0594:            /** Creates a comment node in the table. */
0595:            public int createDeferredComment(String data) {
0596:
0597:                // create node
0598:                int nodeIndex = createNode(Node.COMMENT_NODE);
0599:                int chunk = nodeIndex >> CHUNK_SHIFT;
0600:                int index = nodeIndex & CHUNK_MASK;
0601:                setChunkValue(fNodeValue, data, chunk, index);
0602:
0603:                // return node index
0604:                return nodeIndex;
0605:
0606:            } // createDeferredComment(String):int
0607:
0608:            /** Creates a clone of the specified node. */
0609:            public int cloneNode(int nodeIndex, boolean deep) {
0610:
0611:                // clone immediate node
0612:
0613:                int nchunk = nodeIndex >> CHUNK_SHIFT;
0614:                int nindex = nodeIndex & CHUNK_MASK;
0615:                int nodeType = fNodeType[nchunk][nindex];
0616:                int cloneIndex = createNode((short) nodeType);
0617:                int cchunk = cloneIndex >> CHUNK_SHIFT;
0618:                int cindex = cloneIndex & CHUNK_MASK;
0619:                setChunkValue(fNodeName, fNodeName[nchunk][nindex], cchunk,
0620:                        cindex);
0621:                setChunkValue(fNodeValue, fNodeValue[nchunk][nindex], cchunk,
0622:                        cindex);
0623:                setChunkValue(fNodeURI, fNodeURI[nchunk][nindex], cchunk,
0624:                        cindex);
0625:                int extraIndex = fNodeExtra[nchunk][nindex];
0626:                if (extraIndex != -1) {
0627:                    if (nodeType != Node.ATTRIBUTE_NODE
0628:                            && nodeType != Node.TEXT_NODE) {
0629:                        extraIndex = cloneNode(extraIndex, false);
0630:                    }
0631:                    setChunkIndex(fNodeExtra, extraIndex, cchunk, cindex);
0632:                }
0633:
0634:                // clone and attach children
0635:                if (deep) {
0636:                    int prevIndex = -1;
0637:                    int childIndex = getLastChild(nodeIndex, false);
0638:                    while (childIndex != -1) {
0639:                        int clonedChildIndex = cloneNode(childIndex, deep);
0640:                        insertBefore(cloneIndex, clonedChildIndex, prevIndex);
0641:                        prevIndex = clonedChildIndex;
0642:                        childIndex = getRealPrevSibling(childIndex, false);
0643:                    }
0644:
0645:                }
0646:
0647:                // return cloned node index
0648:                return cloneIndex;
0649:
0650:            } // cloneNode(int,boolean):int
0651:
0652:            /** Appends a child to the specified parent in the table. */
0653:            public void appendChild(int parentIndex, int childIndex) {
0654:
0655:                // append parent index
0656:                int pchunk = parentIndex >> CHUNK_SHIFT;
0657:                int pindex = parentIndex & CHUNK_MASK;
0658:                int cchunk = childIndex >> CHUNK_SHIFT;
0659:                int cindex = childIndex & CHUNK_MASK;
0660:                setChunkIndex(fNodeParent, parentIndex, cchunk, cindex);
0661:
0662:                // set previous sibling of new child
0663:                int olast = getChunkIndex(fNodeLastChild, pchunk, pindex);
0664:                setChunkIndex(fNodePrevSib, olast, cchunk, cindex);
0665:
0666:                // update parent's last child
0667:                setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
0668:
0669:            } // appendChild(int,int)
0670:
0671:            /** Adds an attribute node to the specified element. */
0672:            public int setAttributeNode(int elemIndex, int attrIndex) {
0673:
0674:                int echunk = elemIndex >> CHUNK_SHIFT;
0675:                int eindex = elemIndex & CHUNK_MASK;
0676:                int achunk = attrIndex >> CHUNK_SHIFT;
0677:                int aindex = attrIndex & CHUNK_MASK;
0678:
0679:                // see if this attribute is already here
0680:                String attrName = getChunkValue(fNodeName, achunk, aindex);
0681:                int oldAttrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
0682:                int nextIndex = -1;
0683:                int oachunk = -1;
0684:                int oaindex = -1;
0685:                while (oldAttrIndex != -1) {
0686:                    oachunk = oldAttrIndex >> CHUNK_SHIFT;
0687:                    oaindex = oldAttrIndex & CHUNK_MASK;
0688:                    String oldAttrName = getChunkValue(fNodeName, oachunk,
0689:                            oaindex);
0690:                    if (oldAttrName.equals(attrName)) {
0691:                        break;
0692:                    }
0693:                    nextIndex = oldAttrIndex;
0694:                    oldAttrIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
0695:                }
0696:
0697:                // remove old attribute
0698:                if (oldAttrIndex != -1) {
0699:
0700:                    // patch links
0701:                    int prevIndex = getChunkIndex(fNodePrevSib, oachunk,
0702:                            oaindex);
0703:                    if (nextIndex == -1) {
0704:                        setChunkIndex(fNodeExtra, prevIndex, echunk, eindex);
0705:                    } else {
0706:                        int pchunk = nextIndex >> CHUNK_SHIFT;
0707:                        int pindex = nextIndex & CHUNK_MASK;
0708:                        setChunkIndex(fNodePrevSib, prevIndex, pchunk, pindex);
0709:                    }
0710:
0711:                    // remove connections to siblings
0712:                    clearChunkIndex(fNodeType, oachunk, oaindex);
0713:                    clearChunkValue(fNodeName, oachunk, oaindex);
0714:                    clearChunkValue(fNodeValue, oachunk, oaindex);
0715:                    clearChunkIndex(fNodeParent, oachunk, oaindex);
0716:                    clearChunkIndex(fNodePrevSib, oachunk, oaindex);
0717:                    int attrTextIndex = clearChunkIndex(fNodeLastChild,
0718:                            oachunk, oaindex);
0719:                    int atchunk = attrTextIndex >> CHUNK_SHIFT;
0720:                    int atindex = attrTextIndex & CHUNK_MASK;
0721:                    clearChunkIndex(fNodeType, atchunk, atindex);
0722:                    clearChunkValue(fNodeValue, atchunk, atindex);
0723:                    clearChunkIndex(fNodeParent, atchunk, atindex);
0724:                    clearChunkIndex(fNodeLastChild, atchunk, atindex);
0725:                }
0726:
0727:                // add new attribute
0728:                int prevIndex = getChunkIndex(fNodeExtra, echunk, eindex);
0729:                setChunkIndex(fNodeExtra, attrIndex, echunk, eindex);
0730:                setChunkIndex(fNodePrevSib, prevIndex, achunk, aindex);
0731:
0732:                // return
0733:                return oldAttrIndex;
0734:
0735:            } // setAttributeNode(int,int):int
0736:
0737:            /** Adds an attribute node to the specified element. */
0738:            public void setIdAttributeNode(int elemIndex, int attrIndex) {
0739:
0740:                int chunk = attrIndex >> CHUNK_SHIFT;
0741:                int index = attrIndex & CHUNK_MASK;
0742:                int extra = getChunkIndex(fNodeExtra, chunk, index);
0743:                extra = extra | ID;
0744:                setChunkIndex(fNodeExtra, extra, chunk, index);
0745:
0746:                String value = getChunkValue(fNodeValue, chunk, index);
0747:                putIdentifier(value, elemIndex);
0748:            }
0749:
0750:            /** Sets type of attribute */
0751:            public void setIdAttribute(int attrIndex) {
0752:
0753:                int chunk = attrIndex >> CHUNK_SHIFT;
0754:                int index = attrIndex & CHUNK_MASK;
0755:                int extra = getChunkIndex(fNodeExtra, chunk, index);
0756:                extra = extra | ID;
0757:                setChunkIndex(fNodeExtra, extra, chunk, index);
0758:            }
0759:
0760:            /** Inserts a child before the specified node in the table. */
0761:            public int insertBefore(int parentIndex, int newChildIndex,
0762:                    int refChildIndex) {
0763:
0764:                if (refChildIndex == -1) {
0765:                    appendChild(parentIndex, newChildIndex);
0766:                    return newChildIndex;
0767:                }
0768:
0769:                int nchunk = newChildIndex >> CHUNK_SHIFT;
0770:                int nindex = newChildIndex & CHUNK_MASK;
0771:                int rchunk = refChildIndex >> CHUNK_SHIFT;
0772:                int rindex = refChildIndex & CHUNK_MASK;
0773:                int previousIndex = getChunkIndex(fNodePrevSib, rchunk, rindex);
0774:                setChunkIndex(fNodePrevSib, newChildIndex, rchunk, rindex);
0775:                setChunkIndex(fNodePrevSib, previousIndex, nchunk, nindex);
0776:
0777:                return newChildIndex;
0778:
0779:            } // insertBefore(int,int,int):int
0780:
0781:            /** Sets the last child of the parentIndex to childIndex. */
0782:            public void setAsLastChild(int parentIndex, int childIndex) {
0783:                int pchunk = parentIndex >> CHUNK_SHIFT;
0784:                int pindex = parentIndex & CHUNK_MASK;
0785:                setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
0786:            } // setAsLastChild(int,int)
0787:
0788:            /**
0789:             * Returns the parent node of the given node.
0790:             * <em>Calling this method does not free the parent index.</em>
0791:             */
0792:            public int getParentNode(int nodeIndex) {
0793:                return getParentNode(nodeIndex, false);
0794:            }
0795:
0796:            /**
0797:             * Returns the parent node of the given node.
0798:             * @param free True to free parent node.
0799:             */
0800:            public int getParentNode(int nodeIndex, boolean free) {
0801:
0802:                if (nodeIndex == -1) {
0803:                    return -1;
0804:                }
0805:
0806:                int chunk = nodeIndex >> CHUNK_SHIFT;
0807:                int index = nodeIndex & CHUNK_MASK;
0808:                return free ? clearChunkIndex(fNodeParent, chunk, index)
0809:                        : getChunkIndex(fNodeParent, chunk, index);
0810:
0811:            } // getParentNode(int):int
0812:
0813:            /** Returns the last child of the given node. */
0814:            public int getLastChild(int nodeIndex) {
0815:                return getLastChild(nodeIndex, true);
0816:            }
0817:
0818:            /**
0819:             * Returns the last child of the given node.
0820:             * @param free True to free child index.
0821:             */
0822:            public int getLastChild(int nodeIndex, boolean free) {
0823:
0824:                if (nodeIndex == -1) {
0825:                    return -1;
0826:                }
0827:
0828:                int chunk = nodeIndex >> CHUNK_SHIFT;
0829:                int index = nodeIndex & CHUNK_MASK;
0830:                return free ? clearChunkIndex(fNodeLastChild, chunk, index)
0831:                        : getChunkIndex(fNodeLastChild, chunk, index);
0832:
0833:            } // getLastChild(int,boolean):int
0834:
0835:            /**
0836:             * Returns the prev sibling of the given node.
0837:             * This is post-normalization of Text Nodes.
0838:             */
0839:            public int getPrevSibling(int nodeIndex) {
0840:                return getPrevSibling(nodeIndex, true);
0841:            }
0842:
0843:            /**
0844:             * Returns the prev sibling of the given node.
0845:             * @param free True to free sibling index.
0846:             */
0847:            public int getPrevSibling(int nodeIndex, boolean free) {
0848:
0849:                if (nodeIndex == -1) {
0850:                    return -1;
0851:                }
0852:
0853:                int chunk = nodeIndex >> CHUNK_SHIFT;
0854:                int index = nodeIndex & CHUNK_MASK;
0855:                int type = getChunkIndex(fNodeType, chunk, index);
0856:                if (type == Node.TEXT_NODE) {
0857:                    do {
0858:                        nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
0859:                        if (nodeIndex == -1) {
0860:                            break;
0861:                        }
0862:                        chunk = nodeIndex >> CHUNK_SHIFT;
0863:                        index = nodeIndex & CHUNK_MASK;
0864:                        type = getChunkIndex(fNodeType, chunk, index);
0865:                    } while (type == Node.TEXT_NODE);
0866:                } else {
0867:                    nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
0868:                }
0869:
0870:                return nodeIndex;
0871:
0872:            } // getPrevSibling(int,boolean):int
0873:
0874:            /**
0875:             * Returns the <i>real</i> prev sibling of the given node,
0876:             * directly from the data structures. Used by TextImpl#getNodeValue()
0877:             * to normalize values.
0878:             */
0879:            public int getRealPrevSibling(int nodeIndex) {
0880:                return getRealPrevSibling(nodeIndex, true);
0881:            }
0882:
0883:            /**
0884:             * Returns the <i>real</i> prev sibling of the given node.
0885:             * @param free True to free sibling index.
0886:             */
0887:            public int getRealPrevSibling(int nodeIndex, boolean free) {
0888:
0889:                if (nodeIndex == -1) {
0890:                    return -1;
0891:                }
0892:
0893:                int chunk = nodeIndex >> CHUNK_SHIFT;
0894:                int index = nodeIndex & CHUNK_MASK;
0895:                return free ? clearChunkIndex(fNodePrevSib, chunk, index)
0896:                        : getChunkIndex(fNodePrevSib, chunk, index);
0897:
0898:            } // getReadPrevSibling(int,boolean):int
0899:
0900:            /**
0901:             * Returns the index of the element definition in the table
0902:             * with the specified name index, or -1 if no such definition
0903:             * exists.
0904:             */
0905:            public int lookupElementDefinition(String elementName) {
0906:
0907:                if (fNodeCount > 1) {
0908:
0909:                    // find doctype
0910:                    int docTypeIndex = -1;
0911:                    int nchunk = 0;
0912:                    int nindex = 0;
0913:                    for (int index = getChunkIndex(fNodeLastChild, nchunk,
0914:                            nindex); index != -1; index = getChunkIndex(
0915:                            fNodePrevSib, nchunk, nindex)) {
0916:
0917:                        nchunk = index >> CHUNK_SHIFT;
0918:                        nindex = index & CHUNK_MASK;
0919:                        if (getChunkIndex(fNodeType, nchunk, nindex) == Node.DOCUMENT_TYPE_NODE) {
0920:                            docTypeIndex = index;
0921:                            break;
0922:                        }
0923:                    }
0924:
0925:                    // find element definition
0926:                    if (docTypeIndex == -1) {
0927:                        return -1;
0928:                    }
0929:                    nchunk = docTypeIndex >> CHUNK_SHIFT;
0930:                    nindex = docTypeIndex & CHUNK_MASK;
0931:                    for (int index = getChunkIndex(fNodeLastChild, nchunk,
0932:                            nindex); index != -1; index = getChunkIndex(
0933:                            fNodePrevSib, nchunk, nindex)) {
0934:
0935:                        nchunk = index >> CHUNK_SHIFT;
0936:                        nindex = index & CHUNK_MASK;
0937:                        if (getChunkIndex(fNodeType, nchunk, nindex) == NodeImpl.ELEMENT_DEFINITION_NODE
0938:                                && getChunkValue(fNodeName, nchunk, nindex) == elementName) {
0939:                            return index;
0940:                        }
0941:                    }
0942:                }
0943:
0944:                return -1;
0945:
0946:            } // lookupElementDefinition(String):int
0947:
0948:            /** Instantiates the requested node object. */
0949:            public DeferredNode getNodeObject(int nodeIndex) {
0950:
0951:                // is there anything to do?
0952:                if (nodeIndex == -1) {
0953:                    return null;
0954:                }
0955:
0956:                // get node type
0957:                int chunk = nodeIndex >> CHUNK_SHIFT;
0958:                int index = nodeIndex & CHUNK_MASK;
0959:                int type = getChunkIndex(fNodeType, chunk, index);
0960:                if (type != Node.TEXT_NODE && type != Node.CDATA_SECTION_NODE) {
0961:                    clearChunkIndex(fNodeType, chunk, index);
0962:                }
0963:
0964:                // create new node
0965:                DeferredNode node = null;
0966:                switch (type) {
0967:
0968:                //
0969:                // Standard DOM node types
0970:                //
0971:
0972:                case Node.ATTRIBUTE_NODE: {
0973:                    if (fNamespacesEnabled) {
0974:                        node = new DeferredAttrNSImpl(this , nodeIndex);
0975:                    } else {
0976:                        node = new DeferredAttrImpl(this , nodeIndex);
0977:                    }
0978:                    break;
0979:                }
0980:
0981:                case Node.CDATA_SECTION_NODE: {
0982:                    node = new DeferredCDATASectionImpl(this , nodeIndex);
0983:                    break;
0984:                }
0985:
0986:                case Node.COMMENT_NODE: {
0987:                    node = new DeferredCommentImpl(this , nodeIndex);
0988:                    break;
0989:                }
0990:
0991:                    // NOTE: Document fragments can never be "fast".
0992:                    //
0993:                    //       The parser will never ask to create a document
0994:                    //       fragment during the parse. Document fragments
0995:                    //       are used by the application *after* the parse.
0996:                    //
0997:                    // case Node.DOCUMENT_FRAGMENT_NODE: { break; }
0998:                case Node.DOCUMENT_NODE: {
0999:                    // this node is never "fast"
1000:                    node = this ;
1001:                    break;
1002:                }
1003:
1004:                case Node.DOCUMENT_TYPE_NODE: {
1005:                    node = new DeferredDocumentTypeImpl(this , nodeIndex);
1006:                    // save the doctype node
1007:                    docType = (DocumentTypeImpl) node;
1008:                    break;
1009:                }
1010:
1011:                case Node.ELEMENT_NODE: {
1012:
1013:                    if (DEBUG_IDS) {
1014:                        System.out.println("getNodeObject(ELEMENT_NODE): "
1015:                                + nodeIndex);
1016:                    }
1017:
1018:                    // create node
1019:                    if (fNamespacesEnabled) {
1020:                        node = new DeferredElementNSImpl(this , nodeIndex);
1021:                    } else {
1022:                        node = new DeferredElementImpl(this , nodeIndex);
1023:                    }
1024:
1025:                    // check to see if this element needs to be
1026:                    // registered for its ID attributes
1027:                    if (fIdElement != null) {
1028:                        int idIndex = binarySearch(fIdElement, 0, fIdCount - 1,
1029:                                nodeIndex);
1030:                        while (idIndex != -1) {
1031:
1032:                            if (DEBUG_IDS) {
1033:                                System.out.println("  id index: " + idIndex);
1034:                                System.out.println("  fIdName[" + idIndex
1035:                                        + "]: " + fIdName[idIndex]);
1036:                            }
1037:
1038:                            // register ID
1039:                            String name = fIdName[idIndex];
1040:                            if (name != null) {
1041:                                if (DEBUG_IDS) {
1042:                                    System.out.println("  name: " + name);
1043:                                    System.out.print("getNodeObject()#");
1044:                                }
1045:                                putIdentifier0(name, (Element) node);
1046:                                fIdName[idIndex] = null;
1047:                            }
1048:
1049:                            // continue if there are more IDs for
1050:                            // this element
1051:                            if (idIndex + 1 < fIdCount
1052:                                    && fIdElement[idIndex + 1] == nodeIndex) {
1053:                                idIndex++;
1054:                            } else {
1055:                                idIndex = -1;
1056:                            }
1057:                        }
1058:                    }
1059:                    break;
1060:                }
1061:
1062:                case Node.ENTITY_NODE: {
1063:                    node = new DeferredEntityImpl(this , nodeIndex);
1064:                    break;
1065:                }
1066:
1067:                case Node.ENTITY_REFERENCE_NODE: {
1068:                    node = new DeferredEntityReferenceImpl(this , nodeIndex);
1069:                    break;
1070:                }
1071:
1072:                case Node.NOTATION_NODE: {
1073:                    node = new DeferredNotationImpl(this , nodeIndex);
1074:                    break;
1075:                }
1076:
1077:                case Node.PROCESSING_INSTRUCTION_NODE: {
1078:                    node = new DeferredProcessingInstructionImpl(this ,
1079:                            nodeIndex);
1080:                    break;
1081:                }
1082:
1083:                case Node.TEXT_NODE: {
1084:                    node = new DeferredTextImpl(this , nodeIndex);
1085:                    break;
1086:                }
1087:
1088:                    //
1089:                    // non-standard DOM node types
1090:                    //
1091:
1092:                case NodeImpl.ELEMENT_DEFINITION_NODE: {
1093:                    node = new DeferredElementDefinitionImpl(this , nodeIndex);
1094:                    break;
1095:                }
1096:
1097:                default: {
1098:                    throw new IllegalArgumentException("type: " + type);
1099:                }
1100:
1101:                } // switch node type
1102:
1103:                // store and return
1104:                if (node != null) {
1105:                    return node;
1106:                }
1107:
1108:                // error
1109:                throw new IllegalArgumentException();
1110:
1111:            } // createNodeObject(int):Node
1112:
1113:            /** Returns the name of the given node. */
1114:            public String getNodeName(int nodeIndex) {
1115:                return getNodeName(nodeIndex, true);
1116:            } // getNodeNameString(int):String
1117:
1118:            /**
1119:             * Returns the name of the given node.
1120:             * @param free True to free the string index.
1121:             */
1122:            public String getNodeName(int nodeIndex, boolean free) {
1123:
1124:                if (nodeIndex == -1) {
1125:                    return null;
1126:                }
1127:
1128:                int chunk = nodeIndex >> CHUNK_SHIFT;
1129:                int index = nodeIndex & CHUNK_MASK;
1130:                return free ? clearChunkValue(fNodeName, chunk, index)
1131:                        : getChunkValue(fNodeName, chunk, index);
1132:
1133:            } // getNodeName(int,boolean):String
1134:
1135:            /** Returns the real value of the given node. */
1136:            public String getNodeValueString(int nodeIndex) {
1137:                return getNodeValueString(nodeIndex, true);
1138:            } // getNodeValueString(int):String
1139:
1140:            /**
1141:             * Returns the real value of the given node.
1142:             * @param free True to free the string index.
1143:             */
1144:            public String getNodeValueString(int nodeIndex, boolean free) {
1145:
1146:                if (nodeIndex == -1) {
1147:                    return null;
1148:                }
1149:
1150:                int chunk = nodeIndex >> CHUNK_SHIFT;
1151:                int index = nodeIndex & CHUNK_MASK;
1152:                String value = free ? clearChunkValue(fNodeValue, chunk, index)
1153:                        : getChunkValue(fNodeValue, chunk, index);
1154:                if (value == null) {
1155:                    return null;
1156:                }
1157:
1158:                int type = getChunkIndex(fNodeType, chunk, index);
1159:                if (type == Node.TEXT_NODE) {
1160:                    int prevSib = getRealPrevSibling(nodeIndex);
1161:                    if (prevSib != -1
1162:                            && getNodeType(prevSib, false) == Node.TEXT_NODE) {
1163:                        // append data that is stored in fNodeValue
1164:                        // REVISIT: for text nodes it works differently than for CDATA
1165:                        //          nodes.
1166:                        fStrChunks.addElement(value);
1167:                        do {
1168:                            // go in reverse order: find last child, then
1169:                            // its previous sibling, etc
1170:                            chunk = prevSib >> CHUNK_SHIFT;
1171:                            index = prevSib & CHUNK_MASK;
1172:                            value = getChunkValue(fNodeValue, chunk, index);
1173:                            fStrChunks.addElement(value);
1174:                            prevSib = getChunkIndex(fNodePrevSib, chunk, index);
1175:                            if (prevSib == -1) {
1176:                                break;
1177:                            }
1178:                        } while (getNodeType(prevSib, false) == Node.TEXT_NODE);
1179:
1180:                        int chunkCount = fStrChunks.size();
1181:
1182:                        // add to the buffer in the correct order.
1183:                        for (int i = chunkCount - 1; i >= 0; i--) {
1184:                            fBufferStr.append((String) fStrChunks.elementAt(i));
1185:                        }
1186:
1187:                        value = fBufferStr.toString();
1188:                        fStrChunks.removeAllElements();
1189:                        fBufferStr.setLength(0);
1190:                        return value;
1191:                    }
1192:                } else if (type == Node.CDATA_SECTION_NODE) {
1193:                    // find if any other data stored in children
1194:                    int child = getLastChild(nodeIndex, false);
1195:                    if (child != -1) {
1196:                        // append data that is stored in fNodeValue
1197:                        fBufferStr.append(value);
1198:                        while (child != -1) {
1199:                            // go in reverse order: find last child, then
1200:                            // its previous sibling, etc
1201:                            chunk = child >> CHUNK_SHIFT;
1202:                            index = child & CHUNK_MASK;
1203:                            value = getChunkValue(fNodeValue, chunk, index);
1204:                            fStrChunks.addElement(value);
1205:                            child = getChunkIndex(fNodePrevSib, chunk, index);
1206:                        }
1207:                        // add to the buffer in the correct order.
1208:                        for (int i = fStrChunks.size() - 1; i >= 0; i--) {
1209:                            fBufferStr.append((String) fStrChunks.elementAt(i));
1210:                        }
1211:
1212:                        value = fBufferStr.toString();
1213:                        fStrChunks.setSize(0);
1214:                        fBufferStr.setLength(0);
1215:                        return value;
1216:                    }
1217:                }
1218:
1219:                return value;
1220:
1221:            } // getNodeValueString(int,boolean):String
1222:
1223:            /**
1224:             * Returns the value of the given node.
1225:             */
1226:            public String getNodeValue(int nodeIndex) {
1227:                return getNodeValue(nodeIndex, true);
1228:            }
1229:
1230:            /**
1231:             * Clears the type info that is stored in the fNodeValue array
1232:             * @param nodeIndex
1233:             * @return Object - type information for the attribute/element node
1234:             */
1235:            public Object getTypeInfo(int nodeIndex) {
1236:                if (nodeIndex == -1) {
1237:                    return null;
1238:                }
1239:
1240:                int chunk = nodeIndex >> CHUNK_SHIFT;
1241:                int index = nodeIndex & CHUNK_MASK;
1242:
1243:                Object value = fNodeValue[chunk] != null ? fNodeValue[chunk][index]
1244:                        : null;
1245:                if (value != null) {
1246:                    fNodeValue[chunk][index] = null;
1247:                    RefCount c = (RefCount) fNodeValue[chunk][CHUNK_SIZE];
1248:                    c.fCount--;
1249:                    if (c.fCount == 0) {
1250:                        fNodeValue[chunk] = null;
1251:                    }
1252:                }
1253:                return value;
1254:            }
1255:
1256:            /**
1257:             * Returns the value of the given node.
1258:             * @param free True to free the value index.
1259:             */
1260:            public String getNodeValue(int nodeIndex, boolean free) {
1261:
1262:                if (nodeIndex == -1) {
1263:                    return null;
1264:                }
1265:
1266:                int chunk = nodeIndex >> CHUNK_SHIFT;
1267:                int index = nodeIndex & CHUNK_MASK;
1268:                return free ? clearChunkValue(fNodeValue, chunk, index)
1269:                        : getChunkValue(fNodeValue, chunk, index);
1270:
1271:            } // getNodeValue(int,boolean):String
1272:
1273:            /**
1274:             * Returns the extra info of the given node.
1275:             * Used by AttrImpl to store specified value (1 == true).
1276:             */
1277:            public int getNodeExtra(int nodeIndex) {
1278:                return getNodeExtra(nodeIndex, true);
1279:            }
1280:
1281:            /**
1282:             * Returns the extra info of the given node.
1283:             * @param free True to free the value index.
1284:             */
1285:            public int getNodeExtra(int nodeIndex, boolean free) {
1286:
1287:                if (nodeIndex == -1) {
1288:                    return -1;
1289:                }
1290:
1291:                int chunk = nodeIndex >> CHUNK_SHIFT;
1292:                int index = nodeIndex & CHUNK_MASK;
1293:                return free ? clearChunkIndex(fNodeExtra, chunk, index)
1294:                        : getChunkIndex(fNodeExtra, chunk, index);
1295:
1296:            } // getNodeExtra(int,boolean):int
1297:
1298:            /** Returns the type of the given node. */
1299:            public short getNodeType(int nodeIndex) {
1300:                return getNodeType(nodeIndex, true);
1301:            }
1302:
1303:            /**
1304:             * Returns the type of the given node.
1305:             * @param free True to free type index.
1306:             */
1307:            public short getNodeType(int nodeIndex, boolean free) {
1308:
1309:                if (nodeIndex == -1) {
1310:                    return -1;
1311:                }
1312:
1313:                int chunk = nodeIndex >> CHUNK_SHIFT;
1314:                int index = nodeIndex & CHUNK_MASK;
1315:                return free ? (short) clearChunkIndex(fNodeType, chunk, index)
1316:                        : (short) getChunkIndex(fNodeType, chunk, index);
1317:
1318:            } // getNodeType(int):int
1319:
1320:            /** Returns the attribute value of the given name. */
1321:            public String getAttribute(int elemIndex, String name) {
1322:                if (elemIndex == -1 || name == null) {
1323:                    return null;
1324:                }
1325:                int echunk = elemIndex >> CHUNK_SHIFT;
1326:                int eindex = elemIndex & CHUNK_MASK;
1327:                int attrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
1328:                while (attrIndex != -1) {
1329:                    int achunk = attrIndex >> CHUNK_SHIFT;
1330:                    int aindex = attrIndex & CHUNK_MASK;
1331:                    if (getChunkValue(fNodeName, achunk, aindex) == name) {
1332:                        return getChunkValue(fNodeValue, achunk, aindex);
1333:                    }
1334:                    attrIndex = getChunkIndex(fNodePrevSib, achunk, aindex);
1335:                }
1336:                return null;
1337:            }
1338:
1339:            /** Returns the URI of the given node. */
1340:            public String getNodeURI(int nodeIndex) {
1341:                return getNodeURI(nodeIndex, true);
1342:            }
1343:
1344:            /**
1345:             * Returns the URI of the given node.
1346:             * @param free True to free URI index.
1347:             */
1348:            public String getNodeURI(int nodeIndex, boolean free) {
1349:
1350:                if (nodeIndex == -1) {
1351:                    return null;
1352:                }
1353:
1354:                int chunk = nodeIndex >> CHUNK_SHIFT;
1355:                int index = nodeIndex & CHUNK_MASK;
1356:                return free ? clearChunkValue(fNodeURI, chunk, index)
1357:                        : getChunkValue(fNodeURI, chunk, index);
1358:
1359:            } // getNodeURI(int,int):String
1360:
1361:            // identifier maintenance
1362:
1363:            /** Registers an identifier name with a specified element node. */
1364:            public void putIdentifier(String name, int elementNodeIndex) {
1365:
1366:                if (DEBUG_IDS) {
1367:                    System.out.println("putIdentifier("
1368:                            + name
1369:                            + ", "
1370:                            + elementNodeIndex
1371:                            + ')'
1372:                            + " // "
1373:                            + getChunkValue(fNodeName,
1374:                                    elementNodeIndex >> CHUNK_SHIFT,
1375:                                    elementNodeIndex & CHUNK_MASK));
1376:                }
1377:
1378:                // initialize arrays
1379:                if (fIdName == null) {
1380:                    fIdName = new String[64];
1381:                    fIdElement = new int[64];
1382:                }
1383:
1384:                // resize arrays
1385:                if (fIdCount == fIdName.length) {
1386:                    String idName[] = new String[fIdCount * 2];
1387:                    System.arraycopy(fIdName, 0, idName, 0, fIdCount);
1388:                    fIdName = idName;
1389:
1390:                    int idElement[] = new int[idName.length];
1391:                    System.arraycopy(fIdElement, 0, idElement, 0, fIdCount);
1392:                    fIdElement = idElement;
1393:                }
1394:
1395:                // store identifier
1396:                fIdName[fIdCount] = name;
1397:                fIdElement[fIdCount] = elementNodeIndex;
1398:                fIdCount++;
1399:
1400:            } // putIdentifier(String,int)
1401:
1402:            //
1403:            // DEBUG
1404:            //
1405:
1406:            /** Prints out the tables. */
1407:            public void print() {
1408:
1409:                if (DEBUG_PRINT_REF_COUNTS) {
1410:                    System.out.print("num\t");
1411:                    System.out.print("type\t");
1412:                    System.out.print("name\t");
1413:                    System.out.print("val\t");
1414:                    System.out.print("par\t");
1415:                    System.out.print("lch\t");
1416:                    System.out.print("psib");
1417:                    System.out.println();
1418:                    for (int i = 0; i < fNodeType.length; i++) {
1419:                        if (fNodeType[i] != null) {
1420:                            // separator
1421:                            System.out.print("--------");
1422:                            System.out.print("--------");
1423:                            System.out.print("--------");
1424:                            System.out.print("--------");
1425:                            System.out.print("--------");
1426:                            System.out.print("--------");
1427:                            System.out.print("--------");
1428:                            System.out.println();
1429:
1430:                            // ref count
1431:                            System.out.print(i);
1432:                            System.out.print('\t');
1433:                            switch (fNodeType[i][CHUNK_SIZE]) {
1434:                            case DocumentImpl.ELEMENT_DEFINITION_NODE: {
1435:                                System.out.print("EDef");
1436:                                break;
1437:                            }
1438:                            case Node.DOCUMENT_NODE: {
1439:                                System.out.print("Doc");
1440:                                break;
1441:                            }
1442:                            case Node.DOCUMENT_TYPE_NODE: {
1443:                                System.out.print("DType");
1444:                                break;
1445:                            }
1446:                            case Node.COMMENT_NODE: {
1447:                                System.out.print("Com");
1448:                                break;
1449:                            }
1450:                            case Node.PROCESSING_INSTRUCTION_NODE: {
1451:                                System.out.print("PI");
1452:                                break;
1453:                            }
1454:                            case Node.ELEMENT_NODE: {
1455:                                System.out.print("Elem");
1456:                                break;
1457:                            }
1458:                            case Node.ENTITY_NODE: {
1459:                                System.out.print("Ent");
1460:                                break;
1461:                            }
1462:                            case Node.ENTITY_REFERENCE_NODE: {
1463:                                System.out.print("ERef");
1464:                                break;
1465:                            }
1466:                            case Node.TEXT_NODE: {
1467:                                System.out.print("Text");
1468:                                break;
1469:                            }
1470:                            case Node.ATTRIBUTE_NODE: {
1471:                                System.out.print("Attr");
1472:                                break;
1473:                            }
1474:                            case DeferredNode.TYPE_NODE: {
1475:                                System.out.print("TypeInfo");
1476:                                break;
1477:                            }
1478:                            default: {
1479:                                System.out
1480:                                        .print("?" + fNodeType[i][CHUNK_SIZE]);
1481:                            }
1482:                            }
1483:                            System.out.print('\t');
1484:                            System.out.print(fNodeName[i][CHUNK_SIZE]);
1485:                            System.out.print('\t');
1486:                            System.out.print(fNodeValue[i][CHUNK_SIZE]);
1487:                            System.out.print('\t');
1488:                            System.out.print(fNodeURI[i][CHUNK_SIZE]);
1489:                            System.out.print('\t');
1490:                            System.out.print(fNodeParent[i][CHUNK_SIZE]);
1491:                            System.out.print('\t');
1492:                            System.out.print(fNodeLastChild[i][CHUNK_SIZE]);
1493:                            System.out.print('\t');
1494:                            System.out.print(fNodePrevSib[i][CHUNK_SIZE]);
1495:                            System.out.print('\t');
1496:                            System.out.print(fNodeExtra[i][CHUNK_SIZE]);
1497:                            System.out.println();
1498:                        }
1499:                    }
1500:                }
1501:
1502:                if (DEBUG_PRINT_TABLES) {
1503:                    // This assumes that the document is small
1504:                    System.out.println("# start table");
1505:                    for (int i = 0; i < fNodeCount; i++) {
1506:                        int chunk = i >> CHUNK_SHIFT;
1507:                        int index = i & CHUNK_MASK;
1508:                        if (i % 10 == 0) {
1509:                            System.out.print("num\t");
1510:                            System.out.print("type\t");
1511:                            System.out.print("name\t");
1512:                            System.out.print("val\t");
1513:                            System.out.print("uri\t");
1514:                            System.out.print("par\t");
1515:                            System.out.print("lch\t");
1516:                            System.out.print("psib\t");
1517:                            System.out.print("xtra");
1518:                            System.out.println();
1519:                        }
1520:                        System.out.print(i);
1521:                        System.out.print('\t');
1522:                        switch (getChunkIndex(fNodeType, chunk, index)) {
1523:                        case DocumentImpl.ELEMENT_DEFINITION_NODE: {
1524:                            System.out.print("EDef");
1525:                            break;
1526:                        }
1527:                        case Node.DOCUMENT_NODE: {
1528:                            System.out.print("Doc");
1529:                            break;
1530:                        }
1531:                        case Node.DOCUMENT_TYPE_NODE: {
1532:                            System.out.print("DType");
1533:                            break;
1534:                        }
1535:                        case Node.COMMENT_NODE: {
1536:                            System.out.print("Com");
1537:                            break;
1538:                        }
1539:                        case Node.PROCESSING_INSTRUCTION_NODE: {
1540:                            System.out.print("PI");
1541:                            break;
1542:                        }
1543:                        case Node.ELEMENT_NODE: {
1544:                            System.out.print("Elem");
1545:                            break;
1546:                        }
1547:                        case Node.ENTITY_NODE: {
1548:                            System.out.print("Ent");
1549:                            break;
1550:                        }
1551:                        case Node.ENTITY_REFERENCE_NODE: {
1552:                            System.out.print("ERef");
1553:                            break;
1554:                        }
1555:                        case Node.TEXT_NODE: {
1556:                            System.out.print("Text");
1557:                            break;
1558:                        }
1559:                        case Node.ATTRIBUTE_NODE: {
1560:                            System.out.print("Attr");
1561:                            break;
1562:                        }
1563:                        case DeferredNode.TYPE_NODE: {
1564:                            System.out.print("TypeInfo");
1565:                            break;
1566:                        }
1567:                        default: {
1568:                            System.out.print("?"
1569:                                    + getChunkIndex(fNodeType, chunk, index));
1570:                        }
1571:                        }
1572:                        System.out.print('\t');
1573:                        System.out
1574:                                .print(getChunkValue(fNodeName, chunk, index));
1575:                        System.out.print('\t');
1576:                        System.out.print(getNodeValue(chunk, index));
1577:                        System.out.print('\t');
1578:                        System.out.print(getChunkValue(fNodeURI, chunk, index));
1579:                        System.out.print('\t');
1580:                        System.out.print(getChunkIndex(fNodeParent, chunk,
1581:                                index));
1582:                        System.out.print('\t');
1583:                        System.out.print(getChunkIndex(fNodeLastChild, chunk,
1584:                                index));
1585:                        System.out.print('\t');
1586:                        System.out.print(getChunkIndex(fNodePrevSib, chunk,
1587:                                index));
1588:                        System.out.print('\t');
1589:                        System.out
1590:                                .print(getChunkIndex(fNodeExtra, chunk, index));
1591:                        System.out.println();
1592:                    }
1593:                    System.out.println("# end table");
1594:                }
1595:
1596:            } // print()
1597:
1598:            //
1599:            // DeferredNode methods
1600:            //
1601:
1602:            /** Returns the node index. */
1603:            public int getNodeIndex() {
1604:                return 0;
1605:            }
1606:
1607:            //
1608:            // Protected methods
1609:            //
1610:
1611:            /** Synchronizes the node's data. */
1612:            protected void synchronizeData() {
1613:
1614:                // no need to sync in the future
1615:                needsSyncData(false);
1616:
1617:                // fluff up enough nodes to fill identifiers hash
1618:                if (fIdElement != null) {
1619:
1620:                    // REVISIT: There has to be a more efficient way of
1621:                    //          doing this. But keep in mind that the
1622:                    //          tree can have been altered and re-ordered
1623:                    //          before all of the element nodes with ID
1624:                    //          attributes have been registered. For now
1625:                    //          this is reasonable and safe. -Ac
1626:
1627:                    IntVector path = new IntVector();
1628:                    for (int i = 0; i < fIdCount; i++) {
1629:
1630:                        // ignore if it's already been registered
1631:                        int elementNodeIndex = fIdElement[i];
1632:                        String idName = fIdName[i];
1633:                        if (idName == null) {
1634:                            continue;
1635:                        }
1636:
1637:                        // find path from this element to the root
1638:                        path.removeAllElements();
1639:                        int index = elementNodeIndex;
1640:                        do {
1641:                            path.addElement(index);
1642:                            int pchunk = index >> CHUNK_SHIFT;
1643:                            int pindex = index & CHUNK_MASK;
1644:                            index = getChunkIndex(fNodeParent, pchunk, pindex);
1645:                        } while (index != -1);
1646:
1647:                        // Traverse path (backwards), fluffing the elements
1648:                        // along the way. When this loop finishes, "place"
1649:                        // will contain the reference to the element node
1650:                        // we're interested in. -Ac
1651:                        Node place = this ;
1652:                        for (int j = path.size() - 2; j >= 0; j--) {
1653:                            index = path.elementAt(j);
1654:                            Node child = place.getLastChild();
1655:                            while (child != null) {
1656:                                if (child instanceof  DeferredNode) {
1657:                                    int nodeIndex = ((DeferredNode) child)
1658:                                            .getNodeIndex();
1659:                                    if (nodeIndex == index) {
1660:                                        place = child;
1661:                                        break;
1662:                                    }
1663:                                }
1664:                                child = child.getPreviousSibling();
1665:                            }
1666:                        }
1667:
1668:                        // register the element
1669:                        Element element = (Element) place;
1670:                        putIdentifier0(idName, element);
1671:                        fIdName[i] = null;
1672:
1673:                        // see if there are more IDs on this element
1674:                        while (i + 1 < fIdCount
1675:                                && fIdElement[i + 1] == elementNodeIndex) {
1676:                            idName = fIdName[++i];
1677:                            if (idName == null) {
1678:                                continue;
1679:                            }
1680:                            putIdentifier0(idName, element);
1681:                        }
1682:                    }
1683:
1684:                } // if identifiers
1685:
1686:            } // synchronizeData()
1687:
1688:            /**
1689:             * Synchronizes the node's children with the internal structure.
1690:             * Fluffing the children at once solves a lot of work to keep
1691:             * the two structures in sync. The problem gets worse when
1692:             * editing the tree -- this makes it a lot easier.
1693:             */
1694:            protected void synchronizeChildren() {
1695:
1696:                if (needsSyncData()) {
1697:                    synchronizeData();
1698:                    /*
1699:                     * when we have elements with IDs this method is being recursively
1700:                     * called from synchronizeData, in which case we've already gone
1701:                     * through the following and we can now simply stop here.
1702:                     */
1703:                    if (!needsSyncChildren()) {
1704:                        return;
1705:                    }
1706:                }
1707:
1708:                // we don't want to generate any event for this so turn them off
1709:                boolean orig = mutationEvents;
1710:                mutationEvents = false;
1711:
1712:                // no need to sync in the future
1713:                needsSyncChildren(false);
1714:
1715:                getNodeType(0);
1716:
1717:                // create children and link them as siblings
1718:                ChildNode first = null;
1719:                ChildNode last = null;
1720:                for (int index = getLastChild(0); index != -1; index = getPrevSibling(index)) {
1721:
1722:                    ChildNode node = (ChildNode) getNodeObject(index);
1723:                    if (last == null) {
1724:                        last = node;
1725:                    } else {
1726:                        first.previousSibling = node;
1727:                    }
1728:                    node.ownerNode = this ;
1729:                    node.isOwned(true);
1730:                    node.nextSibling = first;
1731:                    first = node;
1732:
1733:                    // save doctype and document type
1734:                    int type = node.getNodeType();
1735:                    if (type == Node.ELEMENT_NODE) {
1736:                        docElement = (ElementImpl) node;
1737:                    } else if (type == Node.DOCUMENT_TYPE_NODE) {
1738:                        docType = (DocumentTypeImpl) node;
1739:                    }
1740:                }
1741:
1742:                if (first != null) {
1743:                    firstChild = first;
1744:                    first.isFirstChild(true);
1745:                    lastChild(last);
1746:                }
1747:
1748:                // set mutation events flag back to its original value
1749:                mutationEvents = orig;
1750:
1751:            } // synchronizeChildren()
1752:
1753:            /**
1754:             * Synchronizes the node's children with the internal structure.
1755:             * Fluffing the children at once solves a lot of work to keep
1756:             * the two structures in sync. The problem gets worse when
1757:             * editing the tree -- this makes it a lot easier.
1758:             * This is not directly used in this class but this method is
1759:             * here so that it can be shared by all deferred subclasses of AttrImpl.
1760:             */
1761:            protected final void synchronizeChildren(AttrImpl a, int nodeIndex) {
1762:
1763:                // we don't want to generate any event for this so turn them off
1764:                boolean orig = getMutationEvents();
1765:                setMutationEvents(false);
1766:
1767:                // no need to sync in the future
1768:                a.needsSyncChildren(false);
1769:
1770:                // create children and link them as siblings or simply store the value
1771:                // as a String if all we have is one piece of text
1772:                int last = getLastChild(nodeIndex);
1773:                int prev = getPrevSibling(last);
1774:                if (prev == -1) {
1775:                    a.value = getNodeValueString(nodeIndex);
1776:                    a.hasStringValue(true);
1777:                } else {
1778:                    ChildNode firstNode = null;
1779:                    ChildNode lastNode = null;
1780:                    for (int index = last; index != -1; index = getPrevSibling(index)) {
1781:
1782:                        ChildNode node = (ChildNode) getNodeObject(index);
1783:                        if (lastNode == null) {
1784:                            lastNode = node;
1785:                        } else {
1786:                            firstNode.previousSibling = node;
1787:                        }
1788:                        node.ownerNode = a;
1789:                        node.isOwned(true);
1790:                        node.nextSibling = firstNode;
1791:                        firstNode = node;
1792:                    }
1793:                    if (lastNode != null) {
1794:                        a.value = firstNode; // firstChild = firstNode
1795:                        firstNode.isFirstChild(true);
1796:                        a.lastChild(lastNode);
1797:                    }
1798:                    a.hasStringValue(false);
1799:                }
1800:
1801:                // set mutation events flag back to its original value
1802:                setMutationEvents(orig);
1803:
1804:            } // synchronizeChildren(AttrImpl,int):void
1805:
1806:            /**
1807:             * Synchronizes the node's children with the internal structure.
1808:             * Fluffing the children at once solves a lot of work to keep
1809:             * the two structures in sync. The problem gets worse when
1810:             * editing the tree -- this makes it a lot easier.
1811:             * This is not directly used in this class but this method is
1812:             * here so that it can be shared by all deferred subclasses of ParentNode.
1813:             */
1814:            protected final void synchronizeChildren(ParentNode p, int nodeIndex) {
1815:
1816:                // we don't want to generate any event for this so turn them off
1817:                boolean orig = getMutationEvents();
1818:                setMutationEvents(false);
1819:
1820:                // no need to sync in the future
1821:                p.needsSyncChildren(false);
1822:
1823:                // create children and link them as siblings
1824:                ChildNode firstNode = null;
1825:                ChildNode lastNode = null;
1826:                for (int index = getLastChild(nodeIndex); index != -1; index = getPrevSibling(index)) {
1827:
1828:                    ChildNode node = (ChildNode) getNodeObject(index);
1829:                    if (lastNode == null) {
1830:                        lastNode = node;
1831:                    } else {
1832:                        firstNode.previousSibling = node;
1833:                    }
1834:                    node.ownerNode = p;
1835:                    node.isOwned(true);
1836:                    node.nextSibling = firstNode;
1837:                    firstNode = node;
1838:                }
1839:                if (lastNode != null) {
1840:                    p.firstChild = firstNode;
1841:                    firstNode.isFirstChild(true);
1842:                    p.lastChild(lastNode);
1843:                }
1844:
1845:                // set mutation events flag back to its original value
1846:                setMutationEvents(orig);
1847:
1848:            } // synchronizeChildren(ParentNode,int):void
1849:
1850:            // utility methods
1851:
1852:            /** Ensures that the internal tables are large enough. */
1853:            protected void ensureCapacity(int chunk) {
1854:                if (fNodeType == null) {
1855:                    // create buffers
1856:                    fNodeType = new int[INITIAL_CHUNK_COUNT][];
1857:                    fNodeName = new Object[INITIAL_CHUNK_COUNT][];
1858:                    fNodeValue = new Object[INITIAL_CHUNK_COUNT][];
1859:                    fNodeParent = new int[INITIAL_CHUNK_COUNT][];
1860:                    fNodeLastChild = new int[INITIAL_CHUNK_COUNT][];
1861:                    fNodePrevSib = new int[INITIAL_CHUNK_COUNT][];
1862:                    fNodeURI = new Object[INITIAL_CHUNK_COUNT][];
1863:                    fNodeExtra = new int[INITIAL_CHUNK_COUNT][];
1864:                } else if (fNodeType.length <= chunk) {
1865:                    // resize the tables
1866:                    int newsize = chunk * 2;
1867:
1868:                    int[][] newArray = new int[newsize][];
1869:                    System.arraycopy(fNodeType, 0, newArray, 0, chunk);
1870:                    fNodeType = newArray;
1871:
1872:                    Object[][] newStrArray = new Object[newsize][];
1873:                    System.arraycopy(fNodeName, 0, newStrArray, 0, chunk);
1874:                    fNodeName = newStrArray;
1875:
1876:                    newStrArray = new Object[newsize][];
1877:                    System.arraycopy(fNodeValue, 0, newStrArray, 0, chunk);
1878:                    fNodeValue = newStrArray;
1879:
1880:                    newArray = new int[newsize][];
1881:                    System.arraycopy(fNodeParent, 0, newArray, 0, chunk);
1882:                    fNodeParent = newArray;
1883:
1884:                    newArray = new int[newsize][];
1885:                    System.arraycopy(fNodeLastChild, 0, newArray, 0, chunk);
1886:                    fNodeLastChild = newArray;
1887:
1888:                    newArray = new int[newsize][];
1889:                    System.arraycopy(fNodePrevSib, 0, newArray, 0, chunk);
1890:                    fNodePrevSib = newArray;
1891:
1892:                    newStrArray = new Object[newsize][];
1893:                    System.arraycopy(fNodeURI, 0, newStrArray, 0, chunk);
1894:                    fNodeURI = newStrArray;
1895:
1896:                    newArray = new int[newsize][];
1897:                    System.arraycopy(fNodeExtra, 0, newArray, 0, chunk);
1898:                    fNodeExtra = newArray;
1899:                } else if (fNodeType[chunk] != null) {
1900:                    // Done - there's sufficient capacity
1901:                    return;
1902:                }
1903:
1904:                // create new chunks
1905:                createChunk(fNodeType, chunk);
1906:                createChunk(fNodeName, chunk);
1907:                createChunk(fNodeValue, chunk);
1908:                createChunk(fNodeParent, chunk);
1909:                createChunk(fNodeLastChild, chunk);
1910:                createChunk(fNodePrevSib, chunk);
1911:                createChunk(fNodeURI, chunk);
1912:                createChunk(fNodeExtra, chunk);
1913:
1914:                // Done
1915:                return;
1916:
1917:            } // ensureCapacity(int,int)
1918:
1919:            /** Creates a node of the specified type. */
1920:            protected int createNode(short nodeType) {
1921:                // ensure tables are large enough
1922:                int chunk = fNodeCount >> CHUNK_SHIFT;
1923:                int index = fNodeCount & CHUNK_MASK;
1924:                ensureCapacity(chunk);
1925:
1926:                // initialize node
1927:                setChunkIndex(fNodeType, nodeType, chunk, index);
1928:
1929:                // return node index number
1930:                return fNodeCount++;
1931:
1932:            } // createNode(short):int
1933:
1934:            /**
1935:             * Performs a binary search for a target value in an array of
1936:             * values. The array of values must be in ascending sorted order
1937:             * before calling this method and all array values must be
1938:             * non-negative.
1939:             *
1940:             * @param values  The array of values to search.
1941:             * @param start   The starting offset of the search.
1942:             * @param end     The ending offset of the search.
1943:             * @param target  The target value.
1944:             *
1945:             * @return This function will return the <i>first</i> occurrence
1946:             *         of the target value, or -1 if the target value cannot
1947:             *         be found.
1948:             */
1949:            protected static int binarySearch(final int values[], int start,
1950:                    int end, int target) {
1951:
1952:                if (DEBUG_IDS) {
1953:                    System.out.println("binarySearch(), target: " + target);
1954:                }
1955:
1956:                // look for target value
1957:                while (start <= end) {
1958:
1959:                    // is this the one we're looking for?
1960:                    int middle = (start + end) / 2;
1961:                    int value = values[middle];
1962:                    if (DEBUG_IDS) {
1963:                        System.out.print("  value: " + value + ", target: "
1964:                                + target + " // ");
1965:                        print(values, start, end, middle, target);
1966:                    }
1967:                    if (value == target) {
1968:                        while (middle > 0 && values[middle - 1] == target) {
1969:                            middle--;
1970:                        }
1971:                        if (DEBUG_IDS) {
1972:                            System.out.println("FOUND AT " + middle);
1973:                        }
1974:                        return middle;
1975:                    }
1976:
1977:                    // is this point higher or lower?
1978:                    if (value > target) {
1979:                        end = middle - 1;
1980:                    } else {
1981:                        start = middle + 1;
1982:                    }
1983:
1984:                } // while
1985:
1986:                // not found
1987:                if (DEBUG_IDS) {
1988:                    System.out.println("NOT FOUND!");
1989:                }
1990:                return -1;
1991:
1992:            } // binarySearch(int[],int,int,int):int
1993:
1994:            //
1995:            // Private methods
1996:            //
1997:            private static final int[] INIT_ARRAY = new int[CHUNK_SIZE + 1];
1998:            static {
1999:                for (int i = 0; i < CHUNK_SIZE; i++) {
2000:                    INIT_ARRAY[i] = -1;
2001:                }
2002:            }
2003:
2004:            /** Creates the specified chunk in the given array of chunks. */
2005:            private final void createChunk(int data[][], int chunk) {
2006:                data[chunk] = new int[CHUNK_SIZE + 1];
2007:                System.arraycopy(INIT_ARRAY, 0, data[chunk], 0, CHUNK_SIZE);
2008:            }
2009:
2010:            static final class RefCount {
2011:                int fCount;
2012:            }
2013:
2014:            private final void createChunk(Object data[][], int chunk) {
2015:                data[chunk] = new Object[CHUNK_SIZE + 1];
2016:                data[chunk][CHUNK_SIZE] = new RefCount();
2017:            }
2018:
2019:            /**
2020:             * Sets the specified value in the given of data at the chunk and index.
2021:             *
2022:             * @return Returns the old value.
2023:             */
2024:            private final int setChunkIndex(int data[][], int value, int chunk,
2025:                    int index) {
2026:                if (value == -1) {
2027:                    return clearChunkIndex(data, chunk, index);
2028:                }
2029:                int[] dataChunk = data[chunk];
2030:                // Re-create chunk if it was deleted.
2031:                if (dataChunk == null) {
2032:                    createChunk(data, chunk);
2033:                    dataChunk = data[chunk];
2034:                }
2035:                int ovalue = dataChunk[index];
2036:                if (ovalue == -1) {
2037:                    dataChunk[CHUNK_SIZE]++;
2038:                }
2039:                dataChunk[index] = value;
2040:                return ovalue;
2041:            }
2042:
2043:            private final String setChunkValue(Object data[][], Object value,
2044:                    int chunk, int index) {
2045:                if (value == null) {
2046:                    return clearChunkValue(data, chunk, index);
2047:                }
2048:                Object[] dataChunk = data[chunk];
2049:                // Re-create chunk if it was deleted.
2050:                if (dataChunk == null) {
2051:                    createChunk(data, chunk);
2052:                    dataChunk = data[chunk];
2053:                }
2054:                String ovalue = (String) dataChunk[index];
2055:                if (ovalue == null) {
2056:                    RefCount c = (RefCount) dataChunk[CHUNK_SIZE];
2057:                    c.fCount++;
2058:                }
2059:                dataChunk[index] = value;
2060:                return ovalue;
2061:            }
2062:
2063:            /**
2064:             * Returns the specified value in the given data at the chunk and index.
2065:             */
2066:            private final int getChunkIndex(int data[][], int chunk, int index) {
2067:                return data[chunk] != null ? data[chunk][index] : -1;
2068:            }
2069:
2070:            private final String getChunkValue(Object data[][], int chunk,
2071:                    int index) {
2072:                return data[chunk] != null ? (String) data[chunk][index] : null;
2073:            }
2074:
2075:            private final String getNodeValue(int chunk, int index) {
2076:                Object data = fNodeValue[chunk][index];
2077:                if (data == null) {
2078:                    return null;
2079:                } else if (data instanceof  String) {
2080:                    return (String) data;
2081:                } else {
2082:                    // type information
2083:                    return data.toString();
2084:                }
2085:            }
2086:
2087:            /**
2088:             * Clears the specified value in the given data at the chunk and index.
2089:             * Note that this method will clear the given chunk if the reference
2090:             * count becomes zero.
2091:             *
2092:             * @return Returns the old value.
2093:             */
2094:            private final int clearChunkIndex(int data[][], int chunk, int index) {
2095:                int value = data[chunk] != null ? data[chunk][index] : -1;
2096:                if (value != -1) {
2097:                    data[chunk][CHUNK_SIZE]--;
2098:                    data[chunk][index] = -1;
2099:                    if (data[chunk][CHUNK_SIZE] == 0) {
2100:                        data[chunk] = null;
2101:                    }
2102:                }
2103:                return value;
2104:            }
2105:
2106:            private final String clearChunkValue(Object data[][], int chunk,
2107:                    int index) {
2108:                String value = data[chunk] != null ? (String) data[chunk][index]
2109:                        : null;
2110:                if (value != null) {
2111:                    data[chunk][index] = null;
2112:                    RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
2113:                    c.fCount--;
2114:                    if (c.fCount == 0) {
2115:                        data[chunk] = null;
2116:                    }
2117:                }
2118:                return value;
2119:            }
2120:
2121:            /**
2122:             * This version of putIdentifier is needed to avoid fluffing
2123:             * all of the paths to ID attributes when a node object is
2124:             * created that contains an ID attribute.
2125:             */
2126:            private final void putIdentifier0(String idName, Element element) {
2127:
2128:                if (DEBUG_IDS) {
2129:                    System.out.println("putIdentifier0(" + idName + ", "
2130:                            + element + ')');
2131:                }
2132:
2133:                // create hashtable
2134:                if (identifiers == null) {
2135:                    identifiers = new java.util.Hashtable();
2136:                }
2137:
2138:                // save ID and its associated element
2139:                identifiers.put(idName, element);
2140:
2141:            } // putIdentifier0(String,Element)
2142:
2143:            /** Prints the ID array. */
2144:            private static void print(int values[], int start, int end,
2145:                    int middle, int target) {
2146:
2147:                if (DEBUG_IDS) {
2148:                    System.out.print(start);
2149:                    System.out.print(" [");
2150:                    for (int i = start; i < end; i++) {
2151:                        if (middle == i) {
2152:                            System.out.print("!");
2153:                        }
2154:                        System.out.print(values[i]);
2155:                        if (values[i] == target) {
2156:                            System.out.print("*");
2157:                        }
2158:                        if (i < end - 1) {
2159:                            System.out.print(" ");
2160:                        }
2161:                    }
2162:                    System.out.println("] " + end);
2163:                }
2164:
2165:            } // print(int[],int,int,int,int)
2166:
2167:            //
2168:            // Classes
2169:            //
2170:
2171:            /**
2172:             * A simple integer vector.
2173:             */
2174:            static final class IntVector {
2175:
2176:                //
2177:                // Data
2178:                //
2179:
2180:                /** Data. */
2181:                private int data[];
2182:
2183:                /** Size. */
2184:                private int size;
2185:
2186:                //
2187:                // Public methods
2188:                //
2189:
2190:                /** Returns the length of this vector. */
2191:                public int size() {
2192:                    return size;
2193:                }
2194:
2195:                /** Returns the element at the specified index. */
2196:                public int elementAt(int index) {
2197:                    return data[index];
2198:                }
2199:
2200:                /** Appends an element to the end of the vector. */
2201:                public void addElement(int element) {
2202:                    ensureCapacity(size + 1);
2203:                    data[size++] = element;
2204:                }
2205:
2206:                /** Clears the vector. */
2207:                public void removeAllElements() {
2208:                    size = 0;
2209:                }
2210:
2211:                //
2212:                // Private methods
2213:                //
2214:
2215:                /** Makes sure that there is enough storage. */
2216:                private void ensureCapacity(int newsize) {
2217:
2218:                    if (data == null) {
2219:                        data = new int[newsize + 15];
2220:                    } else if (newsize > data.length) {
2221:                        int newdata[] = new int[newsize + 15];
2222:                        System.arraycopy(data, 0, newdata, 0, data.length);
2223:                        data = newdata;
2224:                    }
2225:
2226:                } // ensureCapacity(int)
2227:
2228:            } // class IntVector
2229:
2230:        } // class DeferredDocumentImpl
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.