Source Code Cross Referenced for SAX2DTM2.java in  » XML » xalan » org » apache » xml » dtm » ref » sax2dtm » 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 » xalan » org.apache.xml.dtm.ref.sax2dtm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999-2005 The Apache Software Foundation.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *     http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        /*
0017:         * $Id: SAX2DTM2.java,v 1.15 2005/01/27 15:28:02 zongaro Exp $
0018:         */
0019:        package org.apache.xml.dtm.ref.sax2dtm;
0020:
0021:        import org.apache.xml.dtm.*;
0022:        import org.apache.xml.dtm.ref.*;
0023:        import org.apache.xml.utils.FastStringBuffer;
0024:        import org.apache.xml.utils.XMLString;
0025:        import org.apache.xml.utils.XMLStringDefault;
0026:        import org.apache.xml.utils.XMLStringFactory;
0027:        import org.apache.xml.res.XMLMessages;
0028:        import org.apache.xml.res.XMLErrorResources;
0029:        import org.apache.xml.serializer.SerializationHandler;
0030:
0031:        import javax.xml.transform.Source;
0032:        import java.util.Vector;
0033:        import org.apache.xml.utils.SuballocatedIntVector;
0034:        import org.xml.sax.*;
0035:
0036:        /**
0037:         * SAX2DTM2 is an optimized version of SAX2DTM which is used in non-incremental situation.
0038:         * It is used as the super class of the XSLTC SAXImpl. Many of the interfaces in SAX2DTM
0039:         * and DTMDefaultBase are overridden in SAX2DTM2 in order to allow fast, efficient
0040:         * access to the DTM model. Some nested iterators in DTMDefaultBaseIterators
0041:         * are also overridden in SAX2DTM2 for performance reasons.
0042:         * <p>
0043:         * Performance is the biggest consideration in the design of SAX2DTM2. To make the code most
0044:         * efficient, the incremental support is dropped in SAX2DTM2, which means that you should not
0045:         * use it in incremental situation. To reduce the overhead of pulling data from the DTM model,
0046:         * a few core interfaces in SAX2DTM2 have direct access to the internal arrays of the
0047:         * SuballocatedIntVectors.
0048:         * <p>
0049:         * The design of SAX2DTM2 may limit its extensibilty. If you have a reason to extend the
0050:         * SAX2DTM model, please extend from SAX2DTM instead of this class.
0051:         * <p>
0052:         * TODO: This class is currently only used by XSLTC. We need to investigate the possibility
0053:         * of also using it in Xalan-J Interpretive. Xalan's performance is likely to get an instant
0054:         * boost if we use SAX2DTM2 instead of SAX2DTM in non-incremental case.
0055:         * <p>
0056:         * %MK% The code in this class is critical to the XSLTC_DTM performance. Be very careful
0057:         * when making changes here!
0058:         */
0059:        public class SAX2DTM2 extends SAX2DTM {
0060:
0061:            /****************************************************************
0062:             *       Optimized version of the nested iterators
0063:             ****************************************************************/
0064:
0065:            /**
0066:             * Iterator that returns all immediate children of a given node
0067:             */
0068:            public final class ChildrenIterator extends
0069:                    InternalAxisIteratorBase {
0070:
0071:                /**
0072:                 * Setting start to END should 'close' the iterator,
0073:                 * i.e. subsequent call to next() should return END.
0074:                 * <p>
0075:                 * If the iterator is not restartable, this has no effect.
0076:                 * %REVIEW% Should it return/throw something in that case,
0077:                 * or set current node to END, to indicate request-not-honored?
0078:                 *
0079:                 * @param node Sets the root of the iteration.
0080:                 *
0081:                 * @return A DTMAxisIterator set to the start of the iteration.
0082:                 */
0083:                public DTMAxisIterator setStartNode(int node) {
0084:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0085:                    if (node == DTMDefaultBase.ROOTNODE)
0086:                        node = getDocument();
0087:                    if (_isRestartable) {
0088:                        _startNode = node;
0089:                        _currentNode = (node == DTM.NULL) ? DTM.NULL
0090:                                : _firstch2(makeNodeIdentity(node));
0091:
0092:                        return resetPosition();
0093:                    }
0094:
0095:                    return this ;
0096:                }
0097:
0098:                /**
0099:                 * Get the next node in the iteration.
0100:                 *
0101:                 * @return The next node handle in the iteration, or END if no more
0102:                 * are available.
0103:                 */
0104:                public int next() {
0105:                    if (_currentNode != NULL) {
0106:                        int node = _currentNode;
0107:                        _currentNode = _nextsib2(node);
0108:                        return returnNode(makeNodeHandle(node));
0109:                    }
0110:
0111:                    return END;
0112:                }
0113:            } // end of ChildrenIterator
0114:
0115:            /**
0116:             * Iterator that returns the parent of a given node. Note that
0117:             * this delivers only a single node; if you want all the ancestors,
0118:             * see AncestorIterator.
0119:             */
0120:            public final class ParentIterator extends InternalAxisIteratorBase {
0121:
0122:                /** The extended type ID that was requested. */
0123:                private int _nodeType = DTM.NULL;
0124:
0125:                /**
0126:                 * Set start to END should 'close' the iterator,
0127:                 * i.e. subsequent call to next() should return END.
0128:                 *
0129:                 * @param node Sets the root of the iteration.
0130:                 *
0131:                 * @return A DTMAxisIterator set to the start of the iteration.
0132:                 */
0133:                public DTMAxisIterator setStartNode(int node) {
0134:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0135:                    if (node == DTMDefaultBase.ROOTNODE)
0136:                        node = getDocument();
0137:                    if (_isRestartable) {
0138:                        _startNode = node;
0139:
0140:                        if (node != DTM.NULL)
0141:                            _currentNode = _parent2(makeNodeIdentity(node));
0142:                        else
0143:                            _currentNode = DTM.NULL;
0144:
0145:                        return resetPosition();
0146:                    }
0147:
0148:                    return this ;
0149:                }
0150:
0151:                /**
0152:                 * Set the node type of the parent that we're looking for.
0153:                 * Note that this does _not_ mean "find the nearest ancestor of
0154:                 * this type", but "yield the parent if it is of this type".
0155:                 *
0156:                 *
0157:                 * @param type extended type ID.
0158:                 *
0159:                 * @return ParentIterator configured with the type filter set.
0160:                 */
0161:                public DTMAxisIterator setNodeType(final int type) {
0162:
0163:                    _nodeType = type;
0164:
0165:                    return this ;
0166:                }
0167:
0168:                /**
0169:                 * Get the next node in the iteration. In this case, we return
0170:                 * only the immediate parent, _if_ it matches the requested nodeType.
0171:                 *
0172:                 * @return The next node handle in the iteration, or END.
0173:                 */
0174:                public int next() {
0175:                    int result = _currentNode;
0176:                    if (result == END)
0177:                        return DTM.NULL;
0178:
0179:                    // %OPT% The most common case is handled first.
0180:                    if (_nodeType == NULL) {
0181:                        _currentNode = END;
0182:                        return returnNode(makeNodeHandle(result));
0183:                    } else if (_nodeType >= DTM.NTYPES) {
0184:                        if (_nodeType == _exptype2(result)) {
0185:                            _currentNode = END;
0186:                            return returnNode(makeNodeHandle(result));
0187:                        }
0188:                    } else {
0189:                        if (_nodeType == _type2(result)) {
0190:                            _currentNode = END;
0191:                            return returnNode(makeNodeHandle(result));
0192:                        }
0193:                    }
0194:
0195:                    return DTM.NULL;
0196:                }
0197:            } // end of ParentIterator
0198:
0199:            /**
0200:             * Iterator that returns children of a given type for a given node.
0201:             * The functionality chould be achieved by putting a filter on top
0202:             * of a basic child iterator, but a specialised iterator is used
0203:             * for efficiency (both speed and size of translet).
0204:             */
0205:            public final class TypedChildrenIterator extends
0206:                    InternalAxisIteratorBase {
0207:
0208:                /** The extended type ID that was requested. */
0209:                private final int _nodeType;
0210:
0211:                /**
0212:                 * Constructor TypedChildrenIterator
0213:                 *
0214:                 *
0215:                 * @param nodeType The extended type ID being requested.
0216:                 */
0217:                public TypedChildrenIterator(int nodeType) {
0218:                    _nodeType = nodeType;
0219:                }
0220:
0221:                /**
0222:                 * Set start to END should 'close' the iterator,
0223:                 * i.e. subsequent call to next() should return END.
0224:                 *
0225:                 * @param node Sets the root of the iteration.
0226:                 *
0227:                 * @return A DTMAxisIterator set to the start of the iteration.
0228:                 */
0229:                public DTMAxisIterator setStartNode(int node) {
0230:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0231:                    if (node == DTMDefaultBase.ROOTNODE)
0232:                        node = getDocument();
0233:                    if (_isRestartable) {
0234:                        _startNode = node;
0235:                        _currentNode = (node == DTM.NULL) ? DTM.NULL
0236:                                : _firstch2(makeNodeIdentity(_startNode));
0237:
0238:                        return resetPosition();
0239:                    }
0240:
0241:                    return this ;
0242:                }
0243:
0244:                /**
0245:                 * Get the next node in the iteration.
0246:                 *
0247:                 * @return The next node handle in the iteration, or END.
0248:                 */
0249:                public int next() {
0250:                    int node = _currentNode;
0251:                    if (node == DTM.NULL)
0252:                        return DTM.NULL;
0253:
0254:                    final int nodeType = _nodeType;
0255:
0256:                    if (nodeType != DTM.ELEMENT_NODE) {
0257:                        while (node != DTM.NULL && _exptype2(node) != nodeType) {
0258:                            node = _nextsib2(node);
0259:                        }
0260:                    }
0261:                    // %OPT% If the nodeType is element (matching child::*), we only
0262:                    // need to compare the expType with DTM.NTYPES. A child node of
0263:                    // an element can be either an element, text, comment or
0264:                    // processing instruction node. Only element node has an extended
0265:                    // type greater than or equal to DTM.NTYPES.
0266:                    else {
0267:                        int eType;
0268:                        while (node != DTM.NULL) {
0269:                            eType = _exptype2(node);
0270:                            if (eType >= DTM.NTYPES)
0271:                                break;
0272:                            else
0273:                                node = _nextsib2(node);
0274:                        }
0275:                    }
0276:
0277:                    if (node == DTM.NULL) {
0278:                        _currentNode = DTM.NULL;
0279:                        return DTM.NULL;
0280:                    } else {
0281:                        _currentNode = _nextsib2(node);
0282:                        return returnNode(makeNodeHandle(node));
0283:                    }
0284:
0285:                }
0286:
0287:                /**
0288:                 * Return the node at the given position.
0289:                 */
0290:                public int getNodeByPosition(int position) {
0291:                    if (position <= 0)
0292:                        return DTM.NULL;
0293:
0294:                    int node = _currentNode;
0295:                    int pos = 0;
0296:
0297:                    final int nodeType = _nodeType;
0298:                    if (nodeType != DTM.ELEMENT_NODE) {
0299:                        while (node != DTM.NULL) {
0300:                            if (_exptype2(node) == nodeType) {
0301:                                pos++;
0302:                                if (pos == position)
0303:                                    return makeNodeHandle(node);
0304:                            }
0305:
0306:                            node = _nextsib2(node);
0307:                        }
0308:                        return NULL;
0309:                    } else {
0310:                        while (node != DTM.NULL) {
0311:                            if (_exptype2(node) >= DTM.NTYPES) {
0312:                                pos++;
0313:                                if (pos == position)
0314:                                    return makeNodeHandle(node);
0315:                            }
0316:                            node = _nextsib2(node);
0317:                        }
0318:                        return NULL;
0319:                    }
0320:                }
0321:
0322:            } // end of TypedChildrenIterator
0323:
0324:            /**
0325:             * Iterator that returns the namespace nodes as defined by the XPath data model
0326:             * for a given node, filtered by extended type ID.
0327:             */
0328:            public class TypedRootIterator extends RootIterator {
0329:
0330:                /** The extended type ID that was requested. */
0331:                private final int _nodeType;
0332:
0333:                /**
0334:                 * Constructor TypedRootIterator
0335:                 *
0336:                 * @param nodeType The extended type ID being requested.
0337:                 */
0338:                public TypedRootIterator(int nodeType) {
0339:                    super ();
0340:                    _nodeType = nodeType;
0341:                }
0342:
0343:                /**
0344:                 * Get the next node in the iteration.
0345:                 *
0346:                 * @return The next node handle in the iteration, or END.
0347:                 */
0348:                public int next() {
0349:                    if (_startNode == _currentNode)
0350:                        return NULL;
0351:
0352:                    final int node = _startNode;
0353:                    int expType = _exptype2(makeNodeIdentity(node));
0354:
0355:                    _currentNode = node;
0356:
0357:                    if (_nodeType >= DTM.NTYPES) {
0358:                        if (_nodeType == expType) {
0359:                            return returnNode(node);
0360:                        }
0361:                    } else {
0362:                        if (expType < DTM.NTYPES) {
0363:                            if (expType == _nodeType) {
0364:                                return returnNode(node);
0365:                            }
0366:                        } else {
0367:                            if (m_extendedTypes[expType].getNodeType() == _nodeType) {
0368:                                return returnNode(node);
0369:                            }
0370:                        }
0371:                    }
0372:
0373:                    return NULL;
0374:                }
0375:            } // end of TypedRootIterator
0376:
0377:            /**
0378:             * Iterator that returns all siblings of a given node.
0379:             */
0380:            public class FollowingSiblingIterator extends
0381:                    InternalAxisIteratorBase {
0382:
0383:                /**
0384:                 * Set start to END should 'close' the iterator,
0385:                 * i.e. subsequent call to next() should return END.
0386:                 *
0387:                 * @param node Sets the root of the iteration.
0388:                 *
0389:                 * @return A DTMAxisIterator set to the start of the iteration.
0390:                 */
0391:                public DTMAxisIterator setStartNode(int node) {
0392:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0393:                    if (node == DTMDefaultBase.ROOTNODE)
0394:                        node = getDocument();
0395:                    if (_isRestartable) {
0396:                        _startNode = node;
0397:                        _currentNode = makeNodeIdentity(node);
0398:
0399:                        return resetPosition();
0400:                    }
0401:
0402:                    return this ;
0403:                }
0404:
0405:                /**
0406:                 * Get the next node in the iteration.
0407:                 *
0408:                 * @return The next node handle in the iteration, or END.
0409:                 */
0410:                public int next() {
0411:                    _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL
0412:                            : _nextsib2(_currentNode);
0413:                    return returnNode(makeNodeHandle(_currentNode));
0414:                }
0415:            } // end of FollowingSiblingIterator
0416:
0417:            /**
0418:             * Iterator that returns all following siblings of a given node.
0419:             */
0420:            public final class TypedFollowingSiblingIterator extends
0421:                    FollowingSiblingIterator {
0422:
0423:                /** The extended type ID that was requested. */
0424:                private final int _nodeType;
0425:
0426:                /**
0427:                 * Constructor TypedFollowingSiblingIterator
0428:                 *
0429:                 *
0430:                 * @param type The extended type ID being requested.
0431:                 */
0432:                public TypedFollowingSiblingIterator(int type) {
0433:                    _nodeType = type;
0434:                }
0435:
0436:                /**
0437:                 * Get the next node in the iteration.
0438:                 *
0439:                 * @return The next node handle in the iteration, or END.
0440:                 */
0441:                public int next() {
0442:                    if (_currentNode == DTM.NULL) {
0443:                        return DTM.NULL;
0444:                    }
0445:
0446:                    int node = _currentNode;
0447:                    final int nodeType = _nodeType;
0448:
0449:                    if (nodeType != DTM.ELEMENT_NODE) {
0450:                        while ((node = _nextsib2(node)) != DTM.NULL
0451:                                && _exptype2(node) != nodeType) {
0452:                        }
0453:                    } else {
0454:                        while ((node = _nextsib2(node)) != DTM.NULL
0455:                                && _exptype2(node) < DTM.NTYPES) {
0456:                        }
0457:                    }
0458:
0459:                    _currentNode = node;
0460:
0461:                    return (node == DTM.NULL) ? DTM.NULL
0462:                            : returnNode(makeNodeHandle(node));
0463:                }
0464:
0465:            } // end of TypedFollowingSiblingIterator
0466:
0467:            /**
0468:             * Iterator that returns attribute nodes (of what nodes?)
0469:             */
0470:            public final class AttributeIterator extends
0471:                    InternalAxisIteratorBase {
0472:
0473:                // assumes caller will pass element nodes
0474:
0475:                /**
0476:                 * Set start to END should 'close' the iterator,
0477:                 * i.e. subsequent call to next() should return END.
0478:                 *
0479:                 * @param node Sets the root of the iteration.
0480:                 *
0481:                 * @return A DTMAxisIterator set to the start of the iteration.
0482:                 */
0483:                public DTMAxisIterator setStartNode(int node) {
0484:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0485:                    if (node == DTMDefaultBase.ROOTNODE)
0486:                        node = getDocument();
0487:                    if (_isRestartable) {
0488:                        _startNode = node;
0489:                        _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));
0490:
0491:                        return resetPosition();
0492:                    }
0493:
0494:                    return this ;
0495:                }
0496:
0497:                /**
0498:                 * Get the next node in the iteration.
0499:                 *
0500:                 * @return The next node handle in the iteration, or END.
0501:                 */
0502:                public int next() {
0503:
0504:                    final int node = _currentNode;
0505:
0506:                    if (node != NULL) {
0507:                        _currentNode = getNextAttributeIdentity(node);
0508:                        return returnNode(makeNodeHandle(node));
0509:                    }
0510:
0511:                    return NULL;
0512:                }
0513:            } // end of AttributeIterator
0514:
0515:            /**
0516:             * Iterator that returns attribute nodes of a given type
0517:             */
0518:            public final class TypedAttributeIterator extends
0519:                    InternalAxisIteratorBase {
0520:
0521:                /** The extended type ID that was requested. */
0522:                private final int _nodeType;
0523:
0524:                /**
0525:                 * Constructor TypedAttributeIterator
0526:                 *
0527:                 *
0528:                 * @param nodeType The extended type ID that is requested.
0529:                 */
0530:                public TypedAttributeIterator(int nodeType) {
0531:                    _nodeType = nodeType;
0532:                }
0533:
0534:                // assumes caller will pass element nodes
0535:
0536:                /**
0537:                 * Set start to END should 'close' the iterator,
0538:                 * i.e. subsequent call to next() should return END.
0539:                 *
0540:                 * @param node Sets the root of the iteration.
0541:                 *
0542:                 * @return A DTMAxisIterator set to the start of the iteration.
0543:                 */
0544:                public DTMAxisIterator setStartNode(int node) {
0545:                    if (_isRestartable) {
0546:                        _startNode = node;
0547:
0548:                        _currentNode = getTypedAttribute(node, _nodeType);
0549:
0550:                        return resetPosition();
0551:                    }
0552:
0553:                    return this ;
0554:                }
0555:
0556:                /**
0557:                 * Get the next node in the iteration.
0558:                 *
0559:                 * @return The next node handle in the iteration, or END.
0560:                 */
0561:                public int next() {
0562:
0563:                    final int node = _currentNode;
0564:
0565:                    // singleton iterator, since there can only be one attribute of
0566:                    // a given type.
0567:                    _currentNode = NULL;
0568:
0569:                    return returnNode(node);
0570:                }
0571:            } // end of TypedAttributeIterator
0572:
0573:            /**
0574:             * Iterator that returns preceding siblings of a given node
0575:             */
0576:            public class PrecedingSiblingIterator extends
0577:                    InternalAxisIteratorBase {
0578:
0579:                /**
0580:                 * The node identity of _startNode for this iterator
0581:                 */
0582:                protected int _startNodeID;
0583:
0584:                /**
0585:                 * True if this iterator has a reversed axis.
0586:                 *
0587:                 * @return true.
0588:                 */
0589:                public boolean isReverse() {
0590:                    return true;
0591:                }
0592:
0593:                /**
0594:                 * Set start to END should 'close' the iterator,
0595:                 * i.e. subsequent call to next() should return END.
0596:                 *
0597:                 * @param node Sets the root of the iteration.
0598:                 *
0599:                 * @return A DTMAxisIterator set to the start of the iteration.
0600:                 */
0601:                public DTMAxisIterator setStartNode(int node) {
0602:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0603:                    if (node == DTMDefaultBase.ROOTNODE)
0604:                        node = getDocument();
0605:                    if (_isRestartable) {
0606:                        _startNode = node;
0607:                        node = _startNodeID = makeNodeIdentity(node);
0608:
0609:                        if (node == NULL) {
0610:                            _currentNode = node;
0611:                            return resetPosition();
0612:                        }
0613:
0614:                        int type = _type2(node);
0615:                        if (ExpandedNameTable.ATTRIBUTE == type
0616:                                || ExpandedNameTable.NAMESPACE == type) {
0617:                            _currentNode = node;
0618:                        } else {
0619:                            // Be careful to handle the Document node properly
0620:                            _currentNode = _parent2(node);
0621:                            if (NULL != _currentNode)
0622:                                _currentNode = _firstch2(_currentNode);
0623:                            else
0624:                                _currentNode = node;
0625:                        }
0626:
0627:                        return resetPosition();
0628:                    }
0629:
0630:                    return this ;
0631:                }
0632:
0633:                /**
0634:                 * Get the next node in the iteration.
0635:                 *
0636:                 * @return The next node handle in the iteration, or END.
0637:                 */
0638:                public int next() {
0639:
0640:                    if (_currentNode == _startNodeID
0641:                            || _currentNode == DTM.NULL) {
0642:                        return NULL;
0643:                    } else {
0644:                        final int node = _currentNode;
0645:                        _currentNode = _nextsib2(node);
0646:
0647:                        return returnNode(makeNodeHandle(node));
0648:                    }
0649:                }
0650:            } // end of PrecedingSiblingIterator
0651:
0652:            /**
0653:             * Iterator that returns preceding siblings of a given type for
0654:             * a given node
0655:             */
0656:            public final class TypedPrecedingSiblingIterator extends
0657:                    PrecedingSiblingIterator {
0658:
0659:                /** The extended type ID that was requested. */
0660:                private final int _nodeType;
0661:
0662:                /**
0663:                 * Constructor TypedPrecedingSiblingIterator
0664:                 *
0665:                 *
0666:                 * @param type The extended type ID being requested.
0667:                 */
0668:                public TypedPrecedingSiblingIterator(int type) {
0669:                    _nodeType = type;
0670:                }
0671:
0672:                /**
0673:                 * Get the next node in the iteration.
0674:                 *
0675:                 * @return The next node handle in the iteration, or END.
0676:                 */
0677:                public int next() {
0678:                    int node = _currentNode;
0679:
0680:                    final int nodeType = _nodeType;
0681:                    final int startNodeID = _startNodeID;
0682:
0683:                    if (nodeType != DTM.ELEMENT_NODE) {
0684:                        while (node != NULL && node != startNodeID
0685:                                && _exptype2(node) != nodeType) {
0686:                            node = _nextsib2(node);
0687:                        }
0688:                    } else {
0689:                        while (node != NULL && node != startNodeID
0690:                                && _exptype2(node) < DTM.NTYPES) {
0691:                            node = _nextsib2(node);
0692:                        }
0693:                    }
0694:
0695:                    if (node == DTM.NULL || node == startNodeID) {
0696:                        _currentNode = NULL;
0697:                        return NULL;
0698:                    } else {
0699:                        _currentNode = _nextsib2(node);
0700:                        return returnNode(makeNodeHandle(node));
0701:                    }
0702:                }
0703:
0704:                /**
0705:                 * Return the index of the last node in this iterator.
0706:                 */
0707:                public int getLast() {
0708:                    if (_last != -1)
0709:                        return _last;
0710:
0711:                    setMark();
0712:
0713:                    int node = _currentNode;
0714:                    final int nodeType = _nodeType;
0715:                    final int startNodeID = _startNodeID;
0716:
0717:                    int last = 0;
0718:                    if (nodeType != DTM.ELEMENT_NODE) {
0719:                        while (node != NULL && node != startNodeID) {
0720:                            if (_exptype2(node) == nodeType) {
0721:                                last++;
0722:                            }
0723:                            node = _nextsib2(node);
0724:                        }
0725:                    } else {
0726:                        while (node != NULL && node != startNodeID) {
0727:                            if (_exptype2(node) >= DTM.NTYPES) {
0728:                                last++;
0729:                            }
0730:                            node = _nextsib2(node);
0731:                        }
0732:                    }
0733:
0734:                    gotoMark();
0735:
0736:                    return (_last = last);
0737:                }
0738:            } // end of TypedPrecedingSiblingIterator
0739:
0740:            /**
0741:             * Iterator that returns preceding nodes of a given node.
0742:             * This includes the node set {root+1, start-1}, but excludes
0743:             * all ancestors, attributes, and namespace nodes.
0744:             */
0745:            public class PrecedingIterator extends InternalAxisIteratorBase {
0746:
0747:                /** The max ancestors, but it can grow... */
0748:                private final int _maxAncestors = 8;
0749:
0750:                /**
0751:                 * The stack of start node + ancestors up to the root of the tree,
0752:                 *  which we must avoid.
0753:                 */
0754:                protected int[] _stack = new int[_maxAncestors];
0755:
0756:                /** (not sure yet... -sb) */
0757:                protected int _sp, _oldsp;
0758:
0759:                protected int _markedsp, _markedNode, _markedDescendant;
0760:
0761:                /* _currentNode precedes candidates.  This is the identity, not the handle! */
0762:
0763:                /**
0764:                 * True if this iterator has a reversed axis.
0765:                 *
0766:                 * @return true since this iterator is a reversed axis.
0767:                 */
0768:                public boolean isReverse() {
0769:                    return true;
0770:                }
0771:
0772:                /**
0773:                 * Returns a deep copy of this iterator.   The cloned iterator is not reset.
0774:                 *
0775:                 * @return a deep copy of this iterator.
0776:                 */
0777:                public DTMAxisIterator cloneIterator() {
0778:                    _isRestartable = false;
0779:
0780:                    try {
0781:                        final PrecedingIterator clone = (PrecedingIterator) super 
0782:                                .clone();
0783:                        final int[] stackCopy = new int[_stack.length];
0784:                        System
0785:                                .arraycopy(_stack, 0, stackCopy, 0,
0786:                                        _stack.length);
0787:
0788:                        clone._stack = stackCopy;
0789:
0790:                        // return clone.reset();
0791:                        return clone;
0792:                    } catch (CloneNotSupportedException e) {
0793:                        throw new DTMException(
0794:                                XMLMessages
0795:                                        .createXMLMessage(
0796:                                                XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED,
0797:                                                null)); //"Iterator clone not supported.");
0798:                    }
0799:                }
0800:
0801:                /**
0802:                 * Set start to END should 'close' the iterator,
0803:                 * i.e. subsequent call to next() should return END.
0804:                 *
0805:                 * @param node Sets the root of the iteration.
0806:                 *
0807:                 * @return A DTMAxisIterator set to the start of the iteration.
0808:                 */
0809:                public DTMAxisIterator setStartNode(int node) {
0810:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0811:                    if (node == DTMDefaultBase.ROOTNODE)
0812:                        node = getDocument();
0813:                    if (_isRestartable) {
0814:                        node = makeNodeIdentity(node);
0815:
0816:                        // iterator is not a clone
0817:                        int parent, index;
0818:
0819:                        if (_type2(node) == DTM.ATTRIBUTE_NODE)
0820:                            node = _parent2(node);
0821:
0822:                        _startNode = node;
0823:                        _stack[index = 0] = node;
0824:
0825:                        parent = node;
0826:                        while ((parent = _parent2(parent)) != NULL) {
0827:                            if (++index == _stack.length) {
0828:                                final int[] stack = new int[index * 2];
0829:                                System.arraycopy(_stack, 0, stack, 0, index);
0830:                                _stack = stack;
0831:                            }
0832:                            _stack[index] = parent;
0833:                        }
0834:
0835:                        if (index > 0)
0836:                            --index; // Pop actual root node (if not start) back off the stack
0837:
0838:                        _currentNode = _stack[index]; // Last parent before root node
0839:
0840:                        _oldsp = _sp = index;
0841:
0842:                        return resetPosition();
0843:                    }
0844:
0845:                    return this ;
0846:                }
0847:
0848:                /**
0849:                 * Get the next node in the iteration.
0850:                 *
0851:                 * @return The next node handle in the iteration, or END.
0852:                 */
0853:                public int next() {
0854:                    // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
0855:                    // Also recoded the loop controls for clarity and to flatten out
0856:                    // the tail-recursion.
0857:                    for (++_currentNode; _sp >= 0; ++_currentNode) {
0858:                        if (_currentNode < _stack[_sp]) {
0859:                            int type = _type2(_currentNode);
0860:                            if (type != ATTRIBUTE_NODE
0861:                                    && type != NAMESPACE_NODE)
0862:                                return returnNode(makeNodeHandle(_currentNode));
0863:                        } else
0864:                            --_sp;
0865:                    }
0866:                    return NULL;
0867:                }
0868:
0869:                // redefine DTMAxisIteratorBase's reset
0870:
0871:                /**
0872:                 * Resets the iterator to the last start node.
0873:                 *
0874:                 * @return A DTMAxisIterator, which may or may not be the same as this
0875:                 *         iterator.
0876:                 */
0877:                public DTMAxisIterator reset() {
0878:
0879:                    _sp = _oldsp;
0880:
0881:                    return resetPosition();
0882:                }
0883:
0884:                public void setMark() {
0885:                    _markedsp = _sp;
0886:                    _markedNode = _currentNode;
0887:                    _markedDescendant = _stack[0];
0888:                }
0889:
0890:                public void gotoMark() {
0891:                    _sp = _markedsp;
0892:                    _currentNode = _markedNode;
0893:                }
0894:            } // end of PrecedingIterator
0895:
0896:            /**
0897:             * Iterator that returns preceding nodes of agiven type for a
0898:             * given node. This includes the node set {root+1, start-1}, but
0899:             * excludes all ancestors.
0900:             */
0901:            public final class TypedPrecedingIterator extends PrecedingIterator {
0902:
0903:                /** The extended type ID that was requested. */
0904:                private final int _nodeType;
0905:
0906:                /**
0907:                 * Constructor TypedPrecedingIterator
0908:                 *
0909:                 *
0910:                 * @param type The extended type ID being requested.
0911:                 */
0912:                public TypedPrecedingIterator(int type) {
0913:                    _nodeType = type;
0914:                }
0915:
0916:                /**
0917:                 * Get the next node in the iteration.
0918:                 *
0919:                 * @return The next node handle in the iteration, or END.
0920:                 */
0921:                public int next() {
0922:                    int node = _currentNode;
0923:                    final int nodeType = _nodeType;
0924:
0925:                    if (nodeType >= DTM.NTYPES) {
0926:                        while (true) {
0927:                            node++;
0928:
0929:                            if (_sp < 0) {
0930:                                node = NULL;
0931:                                break;
0932:                            } else if (node >= _stack[_sp]) {
0933:                                if (--_sp < 0) {
0934:                                    node = NULL;
0935:                                    break;
0936:                                }
0937:                            } else if (_exptype2(node) == nodeType) {
0938:                                break;
0939:                            }
0940:                        }
0941:                    } else {
0942:                        int expType;
0943:
0944:                        while (true) {
0945:                            node++;
0946:
0947:                            if (_sp < 0) {
0948:                                node = NULL;
0949:                                break;
0950:                            } else if (node >= _stack[_sp]) {
0951:                                if (--_sp < 0) {
0952:                                    node = NULL;
0953:                                    break;
0954:                                }
0955:                            } else {
0956:                                expType = _exptype2(node);
0957:                                if (expType < DTM.NTYPES) {
0958:                                    if (expType == nodeType) {
0959:                                        break;
0960:                                    }
0961:                                } else {
0962:                                    if (m_extendedTypes[expType].getNodeType() == nodeType) {
0963:                                        break;
0964:                                    }
0965:                                }
0966:                            }
0967:                        }
0968:                    }
0969:
0970:                    _currentNode = node;
0971:
0972:                    return (node == NULL) ? NULL
0973:                            : returnNode(makeNodeHandle(node));
0974:                }
0975:            } // end of TypedPrecedingIterator
0976:
0977:            /**
0978:             * Iterator that returns following nodes of for a given node.
0979:             */
0980:            public class FollowingIterator extends InternalAxisIteratorBase {
0981:                //DTMAxisTraverser m_traverser; // easier for now
0982:
0983:                public FollowingIterator() {
0984:                    //m_traverser = getAxisTraverser(Axis.FOLLOWING);
0985:                }
0986:
0987:                /**
0988:                 * Set start to END should 'close' the iterator,
0989:                 * i.e. subsequent call to next() should return END.
0990:                 *
0991:                 * @param node Sets the root of the iteration.
0992:                 *
0993:                 * @return A DTMAxisIterator set to the start of the iteration.
0994:                 */
0995:                public DTMAxisIterator setStartNode(int node) {
0996:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0997:                    if (node == DTMDefaultBase.ROOTNODE)
0998:                        node = getDocument();
0999:                    if (_isRestartable) {
1000:                        _startNode = node;
1001:
1002:                        //_currentNode = m_traverser.first(node);
1003:
1004:                        node = makeNodeIdentity(node);
1005:
1006:                        int first;
1007:                        int type = _type2(node);
1008:
1009:                        if ((DTM.ATTRIBUTE_NODE == type)
1010:                                || (DTM.NAMESPACE_NODE == type)) {
1011:                            node = _parent2(node);
1012:                            first = _firstch2(node);
1013:
1014:                            if (NULL != first) {
1015:                                _currentNode = makeNodeHandle(first);
1016:                                return resetPosition();
1017:                            }
1018:                        }
1019:
1020:                        do {
1021:                            first = _nextsib2(node);
1022:
1023:                            if (NULL == first)
1024:                                node = _parent2(node);
1025:                        } while (NULL == first && NULL != node);
1026:
1027:                        _currentNode = makeNodeHandle(first);
1028:
1029:                        // _currentNode precedes possible following(node) nodes
1030:                        return resetPosition();
1031:                    }
1032:
1033:                    return this ;
1034:                }
1035:
1036:                /**
1037:                 * Get the next node in the iteration.
1038:                 *
1039:                 * @return The next node handle in the iteration, or END.
1040:                 */
1041:                public int next() {
1042:
1043:                    int node = _currentNode;
1044:
1045:                    //_currentNode = m_traverser.next(_startNode, _currentNode);
1046:                    int current = makeNodeIdentity(node);
1047:
1048:                    while (true) {
1049:                        current++;
1050:
1051:                        int type = _type2(current);
1052:                        if (NULL == type) {
1053:                            _currentNode = NULL;
1054:                            return returnNode(node);
1055:                        }
1056:
1057:                        if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
1058:                            continue;
1059:
1060:                        _currentNode = makeNodeHandle(current);
1061:                        return returnNode(node);
1062:                    }
1063:                }
1064:
1065:            } // end of FollowingIterator
1066:
1067:            /**
1068:             * Iterator that returns following nodes of a given type for a given node.
1069:             */
1070:            public final class TypedFollowingIterator extends FollowingIterator {
1071:
1072:                /** The extended type ID that was requested. */
1073:                private final int _nodeType;
1074:
1075:                /**
1076:                 * Constructor TypedFollowingIterator
1077:                 *
1078:                 *
1079:                 * @param type The extended type ID being requested.
1080:                 */
1081:                public TypedFollowingIterator(int type) {
1082:                    _nodeType = type;
1083:                }
1084:
1085:                /**
1086:                 * Get the next node in the iteration.
1087:                 *
1088:                 * @return The next node handle in the iteration, or END.
1089:                 */
1090:                public int next() {
1091:                    int current;
1092:                    int node;
1093:                    int type;
1094:
1095:                    final int nodeType = _nodeType;
1096:                    int currentNodeID = makeNodeIdentity(_currentNode);
1097:
1098:                    if (nodeType >= DTM.NTYPES) {
1099:                        do {
1100:                            node = currentNodeID;
1101:                            current = node;
1102:
1103:                            do {
1104:                                current++;
1105:                                type = _type2(current);
1106:                            } while (type != NULL
1107:                                    && (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type));
1108:
1109:                            currentNodeID = (type != NULL) ? current : NULL;
1110:                        } while (node != DTM.NULL
1111:                                && _exptype2(node) != nodeType);
1112:                    } else {
1113:                        do {
1114:                            node = currentNodeID;
1115:                            current = node;
1116:
1117:                            do {
1118:                                current++;
1119:                                type = _type2(current);
1120:                            } while (type != NULL
1121:                                    && (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type));
1122:
1123:                            currentNodeID = (type != NULL) ? current : NULL;
1124:                        } while (node != DTM.NULL
1125:                                && (_exptype2(node) != nodeType && _type2(node) != nodeType));
1126:                    }
1127:
1128:                    _currentNode = makeNodeHandle(currentNodeID);
1129:                    return (node == DTM.NULL ? DTM.NULL
1130:                            : returnNode(makeNodeHandle(node)));
1131:                }
1132:            } // end of TypedFollowingIterator
1133:
1134:            /**
1135:             * Iterator that returns the ancestors of a given node in document
1136:             * order.  (NOTE!  This was changed from the XSLTC code!)
1137:             */
1138:            public class AncestorIterator extends InternalAxisIteratorBase {
1139:                // The initial size of the ancestor array
1140:                private static final int m_blocksize = 32;
1141:
1142:                // The array for ancestor nodes. This array will grow dynamically.
1143:                int[] m_ancestors = new int[m_blocksize];
1144:
1145:                // Number of ancestor nodes in the array
1146:                int m_size = 0;
1147:
1148:                int m_ancestorsPos;
1149:
1150:                int m_markedPos;
1151:
1152:                /** The real start node for this axes, since _startNode will be adjusted. */
1153:                int m_realStartNode;
1154:
1155:                /**
1156:                 * Get start to END should 'close' the iterator,
1157:                 * i.e. subsequent call to next() should return END.
1158:                 *
1159:                 * @return The root node of the iteration.
1160:                 */
1161:                public int getStartNode() {
1162:                    return m_realStartNode;
1163:                }
1164:
1165:                /**
1166:                 * True if this iterator has a reversed axis.
1167:                 *
1168:                 * @return true since this iterator is a reversed axis.
1169:                 */
1170:                public final boolean isReverse() {
1171:                    return true;
1172:                }
1173:
1174:                /**
1175:                 * Returns a deep copy of this iterator.  The cloned iterator is not reset.
1176:                 *
1177:                 * @return a deep copy of this iterator.
1178:                 */
1179:                public DTMAxisIterator cloneIterator() {
1180:                    _isRestartable = false; // must set to false for any clone
1181:
1182:                    try {
1183:                        final AncestorIterator clone = (AncestorIterator) super 
1184:                                .clone();
1185:
1186:                        clone._startNode = _startNode;
1187:
1188:                        // return clone.reset();
1189:                        return clone;
1190:                    } catch (CloneNotSupportedException e) {
1191:                        throw new DTMException(
1192:                                XMLMessages
1193:                                        .createXMLMessage(
1194:                                                XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED,
1195:                                                null)); //"Iterator clone not supported.");
1196:                    }
1197:                }
1198:
1199:                /**
1200:                 * Set start to END should 'close' the iterator,
1201:                 * i.e. subsequent call to next() should return END.
1202:                 *
1203:                 * @param node Sets the root of the iteration.
1204:                 *
1205:                 * @return A DTMAxisIterator set to the start of the iteration.
1206:                 */
1207:                public DTMAxisIterator setStartNode(int node) {
1208:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1209:                    if (node == DTMDefaultBase.ROOTNODE)
1210:                        node = getDocument();
1211:                    m_realStartNode = node;
1212:
1213:                    if (_isRestartable) {
1214:                        int nodeID = makeNodeIdentity(node);
1215:                        m_size = 0;
1216:
1217:                        if (nodeID == DTM.NULL) {
1218:                            _currentNode = DTM.NULL;
1219:                            m_ancestorsPos = 0;
1220:                            return this ;
1221:                        }
1222:
1223:                        // Start from the current node's parent if
1224:                        // _includeSelf is false.
1225:                        if (!_includeSelf) {
1226:                            nodeID = _parent2(nodeID);
1227:                            node = makeNodeHandle(nodeID);
1228:                        }
1229:
1230:                        _startNode = node;
1231:
1232:                        while (nodeID != END) {
1233:                            //m_ancestors.addElement(node);
1234:                            if (m_size >= m_ancestors.length) {
1235:                                int[] newAncestors = new int[m_size * 2];
1236:                                System.arraycopy(m_ancestors, 0, newAncestors,
1237:                                        0, m_ancestors.length);
1238:                                m_ancestors = newAncestors;
1239:                            }
1240:
1241:                            m_ancestors[m_size++] = node;
1242:                            nodeID = _parent2(nodeID);
1243:                            node = makeNodeHandle(nodeID);
1244:                        }
1245:
1246:                        m_ancestorsPos = m_size - 1;
1247:
1248:                        _currentNode = (m_ancestorsPos >= 0) ? m_ancestors[m_ancestorsPos]
1249:                                : DTM.NULL;
1250:
1251:                        return resetPosition();
1252:                    }
1253:
1254:                    return this ;
1255:                }
1256:
1257:                /**
1258:                 * Resets the iterator to the last start node.
1259:                 *
1260:                 * @return A DTMAxisIterator, which may or may not be the same as this
1261:                 *         iterator.
1262:                 */
1263:                public DTMAxisIterator reset() {
1264:
1265:                    m_ancestorsPos = m_size - 1;
1266:
1267:                    _currentNode = (m_ancestorsPos >= 0) ? m_ancestors[m_ancestorsPos]
1268:                            : DTM.NULL;
1269:
1270:                    return resetPosition();
1271:                }
1272:
1273:                /**
1274:                 * Get the next node in the iteration.
1275:                 *
1276:                 * @return The next node handle in the iteration, or END.
1277:                 */
1278:                public int next() {
1279:
1280:                    int next = _currentNode;
1281:
1282:                    int pos = --m_ancestorsPos;
1283:
1284:                    _currentNode = (pos >= 0) ? m_ancestors[m_ancestorsPos]
1285:                            : DTM.NULL;
1286:
1287:                    return returnNode(next);
1288:                }
1289:
1290:                public void setMark() {
1291:                    m_markedPos = m_ancestorsPos;
1292:                }
1293:
1294:                public void gotoMark() {
1295:                    m_ancestorsPos = m_markedPos;
1296:                    _currentNode = m_ancestorsPos >= 0 ? m_ancestors[m_ancestorsPos]
1297:                            : DTM.NULL;
1298:                }
1299:            } // end of AncestorIterator
1300:
1301:            /**
1302:             * Typed iterator that returns the ancestors of a given node.
1303:             */
1304:            public final class TypedAncestorIterator extends AncestorIterator {
1305:
1306:                /** The extended type ID that was requested. */
1307:                private final int _nodeType;
1308:
1309:                /**
1310:                 * Constructor TypedAncestorIterator
1311:                 *
1312:                 *
1313:                 * @param type The extended type ID being requested.
1314:                 */
1315:                public TypedAncestorIterator(int type) {
1316:                    _nodeType = type;
1317:                }
1318:
1319:                /**
1320:                 * Set start to END should 'close' the iterator,
1321:                 * i.e. subsequent call to next() should return END.
1322:                 *
1323:                 * @param node Sets the root of the iteration.
1324:                 *
1325:                 * @return A DTMAxisIterator set to the start of the iteration.
1326:                 */
1327:                public DTMAxisIterator setStartNode(int node) {
1328:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1329:                    if (node == DTMDefaultBase.ROOTNODE)
1330:                        node = getDocument();
1331:                    m_realStartNode = node;
1332:
1333:                    if (_isRestartable) {
1334:                        int nodeID = makeNodeIdentity(node);
1335:                        m_size = 0;
1336:
1337:                        if (nodeID == DTM.NULL) {
1338:                            _currentNode = DTM.NULL;
1339:                            m_ancestorsPos = 0;
1340:                            return this ;
1341:                        }
1342:
1343:                        final int nodeType = _nodeType;
1344:
1345:                        if (!_includeSelf) {
1346:                            nodeID = _parent2(nodeID);
1347:                            node = makeNodeHandle(nodeID);
1348:                        }
1349:
1350:                        _startNode = node;
1351:
1352:                        if (nodeType >= DTM.NTYPES) {
1353:                            while (nodeID != END) {
1354:                                int eType = _exptype2(nodeID);
1355:
1356:                                if (eType == nodeType) {
1357:                                    if (m_size >= m_ancestors.length) {
1358:                                        int[] newAncestors = new int[m_size * 2];
1359:                                        System.arraycopy(m_ancestors, 0,
1360:                                                newAncestors, 0,
1361:                                                m_ancestors.length);
1362:                                        m_ancestors = newAncestors;
1363:                                    }
1364:                                    m_ancestors[m_size++] = makeNodeHandle(nodeID);
1365:                                }
1366:                                nodeID = _parent2(nodeID);
1367:                            }
1368:                        } else {
1369:                            while (nodeID != END) {
1370:                                int eType = _exptype2(nodeID);
1371:
1372:                                if ((eType < DTM.NTYPES && eType == nodeType)
1373:                                        || (eType >= DTM.NTYPES && m_extendedTypes[eType]
1374:                                                .getNodeType() == nodeType)) {
1375:                                    if (m_size >= m_ancestors.length) {
1376:                                        int[] newAncestors = new int[m_size * 2];
1377:                                        System.arraycopy(m_ancestors, 0,
1378:                                                newAncestors, 0,
1379:                                                m_ancestors.length);
1380:                                        m_ancestors = newAncestors;
1381:                                    }
1382:                                    m_ancestors[m_size++] = makeNodeHandle(nodeID);
1383:                                }
1384:                                nodeID = _parent2(nodeID);
1385:                            }
1386:                        }
1387:                        m_ancestorsPos = m_size - 1;
1388:
1389:                        _currentNode = (m_ancestorsPos >= 0) ? m_ancestors[m_ancestorsPos]
1390:                                : DTM.NULL;
1391:
1392:                        return resetPosition();
1393:                    }
1394:
1395:                    return this ;
1396:                }
1397:
1398:                /**
1399:                 * Return the node at the given position.
1400:                 */
1401:                public int getNodeByPosition(int position) {
1402:                    if (position > 0 && position <= m_size) {
1403:                        return m_ancestors[position - 1];
1404:                    } else
1405:                        return DTM.NULL;
1406:                }
1407:
1408:                /**
1409:                 * Returns the position of the last node within the iteration, as
1410:                 * defined by XPath.
1411:                 */
1412:                public int getLast() {
1413:                    return m_size;
1414:                }
1415:            } // end of TypedAncestorIterator
1416:
1417:            /**
1418:             * Iterator that returns the descendants of a given node.
1419:             */
1420:            public class DescendantIterator extends InternalAxisIteratorBase {
1421:
1422:                /**
1423:                 * Set start to END should 'close' the iterator,
1424:                 * i.e. subsequent call to next() should return END.
1425:                 *
1426:                 * @param node Sets the root of the iteration.
1427:                 *
1428:                 * @return A DTMAxisIterator set to the start of the iteration.
1429:                 */
1430:                public DTMAxisIterator setStartNode(int node) {
1431:                    //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1432:                    if (node == DTMDefaultBase.ROOTNODE)
1433:                        node = getDocument();
1434:                    if (_isRestartable) {
1435:                        node = makeNodeIdentity(node);
1436:                        _startNode = node;
1437:
1438:                        if (_includeSelf)
1439:                            node--;
1440:
1441:                        _currentNode = node;
1442:
1443:                        return resetPosition();
1444:                    }
1445:
1446:                    return this ;
1447:                }
1448:
1449:                /**
1450:                 * Tell if this node identity is a descendant.  Assumes that
1451:                 * the node info for the element has already been obtained.
1452:                 *
1453:                 * This one-sided test works only if the parent has been
1454:                 * previously tested and is known to be a descendent. It fails if
1455:                 * the parent is the _startNode's next sibling, or indeed any node
1456:                 * that follows _startNode in document order.  That may suffice
1457:                 * for this iterator, but it's not really an isDescendent() test.
1458:                 * %REVIEW% rename?
1459:                 *
1460:                 * @param identity The index number of the node in question.
1461:                 * @return true if the index is a descendant of _startNode.
1462:                 */
1463:                protected final boolean isDescendant(int identity) {
1464:                    return (_parent2(identity) >= _startNode)
1465:                            || (_startNode == identity);
1466:                }
1467:
1468:                /**
1469:                 * Get the next node in the iteration.
1470:                 *
1471:                 * @return The next node handle in the iteration, or END.
1472:                 */
1473:                public int next() {
1474:                    final int startNode = _startNode;
1475:                    if (startNode == NULL) {
1476:                        return NULL;
1477:                    }
1478:
1479:                    if (_includeSelf && (_currentNode + 1) == startNode)
1480:                        return returnNode(makeNodeHandle(++_currentNode)); // | m_dtmIdent);
1481:
1482:                    int node = _currentNode;
1483:                    int type;
1484:
1485:                    // %OPT% If the startNode is the root node, do not need
1486:                    // to do the isDescendant() check.
1487:                    if (startNode == ROOTNODE) {
1488:                        int eType;
1489:                        do {
1490:                            node++;
1491:                            eType = _exptype2(node);
1492:
1493:                            if (NULL == eType) {
1494:                                _currentNode = NULL;
1495:                                return END;
1496:                            }
1497:                        } while (eType == TEXT_NODE
1498:                                || (type = m_extendedTypes[eType].getNodeType()) == ATTRIBUTE_NODE
1499:                                || type == NAMESPACE_NODE);
1500:                    } else {
1501:                        do {
1502:                            node++;
1503:                            type = _type2(node);
1504:
1505:                            if (NULL == type || !isDescendant(node)) {
1506:                                _currentNode = NULL;
1507:                                return END;
1508:                            }
1509:                        } while (ATTRIBUTE_NODE == type || TEXT_NODE == type
1510:                                || NAMESPACE_NODE == type);
1511:                    }
1512:
1513:                    _currentNode = node;
1514:                    return returnNode(makeNodeHandle(node)); // make handle.
1515:                }
1516:
1517:                /**
1518:                 * Reset.
1519:                 *
1520:                 */
1521:                public DTMAxisIterator reset() {
1522:
1523:                    final boolean temp = _isRestartable;
1524:
1525:                    _isRestartable = true;
1526:
1527:                    setStartNode(makeNodeHandle(_startNode));
1528:
1529:                    _isRestartable = temp;
1530:
1531:                    return this ;
1532:                }
1533:
1534:            } // end of DescendantIterator
1535:
1536:            /**
1537:             * Typed iterator that returns the descendants of a given node.
1538:             */
1539:            public final class TypedDescendantIterator extends
1540:                    DescendantIterator {
1541:
1542:                /** The extended type ID that was requested. */
1543:                private final int _nodeType;
1544:
1545:                /**
1546:                 * Constructor TypedDescendantIterator
1547:                 *
1548:                 *
1549:                 * @param nodeType Extended type ID being requested.
1550:                 */
1551:                public TypedDescendantIterator(int nodeType) {
1552:                    _nodeType = nodeType;
1553:                }
1554:
1555:                /**
1556:                 * Get the next node in the iteration.
1557:                 *
1558:                 * @return The next node handle in the iteration, or END.
1559:                 */
1560:                public int next() {
1561:                    final int startNode = _startNode;
1562:                    if (_startNode == NULL) {
1563:                        return NULL;
1564:                    }
1565:
1566:                    int node = _currentNode;
1567:
1568:                    int expType;
1569:                    final int nodeType = _nodeType;
1570:
1571:                    if (nodeType != DTM.ELEMENT_NODE) {
1572:                        do {
1573:                            node++;
1574:                            expType = _exptype2(node);
1575:
1576:                            if (NULL == expType || _parent2(node) < startNode
1577:                                    && startNode != node) {
1578:                                _currentNode = NULL;
1579:                                return END;
1580:                            }
1581:                        } while (expType != nodeType);
1582:                    }
1583:                    // %OPT% If the start node is root (e.g. in the case of //node),
1584:                    // we can save the isDescendant() check, because all nodes are
1585:                    // descendants of root.
1586:                    else if (startNode == DTMDefaultBase.ROOTNODE) {
1587:                        do {
1588:                            node++;
1589:                            expType = _exptype2(node);
1590:
1591:                            if (NULL == expType) {
1592:                                _currentNode = NULL;
1593:                                return END;
1594:                            }
1595:                        } while (expType < DTM.NTYPES
1596:                                || m_extendedTypes[expType].getNodeType() != DTM.ELEMENT_NODE);
1597:                    } else {
1598:                        do {
1599:                            node++;
1600:                            expType = _exptype2(node);
1601:
1602:                            if (NULL == expType || _parent2(node) < startNode
1603:                                    && startNode != node) {
1604:                                _currentNode = NULL;
1605:                                return END;
1606:                            }
1607:                        } while (expType < DTM.NTYPES
1608:                                || m_extendedTypes[expType].getNodeType() != DTM.ELEMENT_NODE);
1609:                    }
1610:
1611:                    _currentNode = node;
1612:                    return returnNode(makeNodeHandle(node));
1613:                }
1614:            } // end of TypedDescendantIterator
1615:
1616:            /**
1617:             * Iterator that returns a given node only if it is of a given type.
1618:             */
1619:            public final class TypedSingletonIterator extends SingletonIterator {
1620:
1621:                /** The extended type ID that was requested. */
1622:                private final int _nodeType;
1623:
1624:                /**
1625:                 * Constructor TypedSingletonIterator
1626:                 *
1627:                 *
1628:                 * @param nodeType The extended type ID being requested.
1629:                 */
1630:                public TypedSingletonIterator(int nodeType) {
1631:                    _nodeType = nodeType;
1632:                }
1633:
1634:                /**
1635:                 * Get the next node in the iteration.
1636:                 *
1637:                 * @return The next node handle in the iteration, or END.
1638:                 */
1639:                public int next() {
1640:
1641:                    final int result = _currentNode;
1642:                    if (result == END)
1643:                        return DTM.NULL;
1644:
1645:                    _currentNode = END;
1646:
1647:                    if (_nodeType >= DTM.NTYPES) {
1648:                        if (_exptype2(makeNodeIdentity(result)) == _nodeType) {
1649:                            return returnNode(result);
1650:                        }
1651:                    } else {
1652:                        if (_type2(makeNodeIdentity(result)) == _nodeType) {
1653:                            return returnNode(result);
1654:                        }
1655:                    }
1656:
1657:                    return NULL;
1658:                }
1659:            } // end of TypedSingletonIterator
1660:
1661:            /*******************************************************************
1662:             *                End of nested iterators
1663:             *******************************************************************/
1664:
1665:            // %OPT% Array references which are used to cache the map0 arrays in
1666:            // SuballocatedIntVectors. Using the cached arrays reduces the level
1667:            // of indirection and results in better performance than just calling
1668:            // SuballocatedIntVector.elementAt().
1669:            private int[] m_exptype_map0;
1670:            private int[] m_nextsib_map0;
1671:            private int[] m_firstch_map0;
1672:            private int[] m_parent_map0;
1673:
1674:            // Double array references to the map arrays in SuballocatedIntVectors.
1675:            private int[][] m_exptype_map;
1676:            private int[][] m_nextsib_map;
1677:            private int[][] m_firstch_map;
1678:            private int[][] m_parent_map;
1679:
1680:            // %OPT% Cache the array of extended types in this class
1681:            protected ExtendedType[] m_extendedTypes;
1682:
1683:            // A Vector which is used to store the values of attribute, namespace,
1684:            // comment and PI nodes.
1685:            //
1686:            // %OPT% These values are unlikely to be equal. Storing
1687:            // them in a plain Vector is more efficient than storing in the
1688:            // DTMStringPool because we can save the cost for hash calculation.
1689:            //
1690:            // %REVISIT% Do we need a custom class (e.g. StringVector) here?
1691:            protected Vector m_values;
1692:
1693:            // The current index into the m_values Vector.
1694:            private int m_valueIndex = 0;
1695:
1696:            // The maximum value of the current node index.
1697:            private int m_maxNodeIndex;
1698:
1699:            // Cache the shift and mask values for the SuballocatedIntVectors.
1700:            protected int m_SHIFT;
1701:            protected int m_MASK;
1702:            protected int m_blocksize;
1703:
1704:            /** %OPT% If the offset and length of a Text node are within certain limits,
1705:             * we store a bitwise encoded value into an int, using 10 bits (max. 1024)
1706:             * for length and 21 bits for offset. We can save two SuballocatedIntVector
1707:             * calls for each getStringValueX() and dispatchCharacterEvents() call by
1708:             * doing this.
1709:             */
1710:            // The number of bits for the length of a Text node.
1711:            protected final static int TEXT_LENGTH_BITS = 10;
1712:
1713:            // The number of bits for the offset of a Text node.
1714:            protected final static int TEXT_OFFSET_BITS = 21;
1715:
1716:            // The maximum length value
1717:            protected final static int TEXT_LENGTH_MAX = (1 << TEXT_LENGTH_BITS) - 1;
1718:
1719:            // The maximum offset value
1720:            protected final static int TEXT_OFFSET_MAX = (1 << TEXT_OFFSET_BITS) - 1;
1721:
1722:            // True if we want to build the ID index table.
1723:            protected boolean m_buildIdIndex = true;
1724:
1725:            // Constant for empty String
1726:            private static final String EMPTY_STR = "";
1727:
1728:            // Constant for empty XMLString
1729:            private static final XMLString EMPTY_XML_STR = new XMLStringDefault(
1730:                    "");
1731:
1732:            /**
1733:             * Construct a SAX2DTM2 object using the default block size.
1734:             */
1735:            public SAX2DTM2(DTMManager mgr, Source source, int dtmIdentity,
1736:                    DTMWSFilter whiteSpaceFilter,
1737:                    XMLStringFactory xstringfactory, boolean doIndexing) {
1738:
1739:                this (mgr, source, dtmIdentity, whiteSpaceFilter,
1740:                        xstringfactory, doIndexing, DEFAULT_BLOCKSIZE, true,
1741:                        true, false);
1742:            }
1743:
1744:            /**
1745:             * Construct a SAX2DTM2 object using the given block size.
1746:             */
1747:            public SAX2DTM2(DTMManager mgr, Source source, int dtmIdentity,
1748:                    DTMWSFilter whiteSpaceFilter,
1749:                    XMLStringFactory xstringfactory, boolean doIndexing,
1750:                    int blocksize, boolean usePrevsib, boolean buildIdIndex,
1751:                    boolean newNameTable) {
1752:
1753:                super (mgr, source, dtmIdentity, whiteSpaceFilter,
1754:                        xstringfactory, doIndexing, blocksize, usePrevsib,
1755:                        newNameTable);
1756:
1757:                // Initialize the values of m_SHIFT and m_MASK.
1758:                int shift;
1759:                for (shift = 0; (blocksize >>>= 1) != 0; ++shift)
1760:                    ;
1761:
1762:                m_blocksize = 1 << shift;
1763:                m_SHIFT = shift;
1764:                m_MASK = m_blocksize - 1;
1765:
1766:                m_buildIdIndex = buildIdIndex;
1767:
1768:                // Some documents do not have attribute nodes. That is why
1769:                // we set the initial size of this Vector to be small and set
1770:                // the increment to a bigger number.
1771:                m_values = new Vector(32, 512);
1772:
1773:                m_maxNodeIndex = 1 << DTMManager.IDENT_DTM_NODE_BITS;
1774:
1775:                // Set the map0 values in the constructor.
1776:                m_exptype_map0 = m_exptype.getMap0();
1777:                m_nextsib_map0 = m_nextsib.getMap0();
1778:                m_firstch_map0 = m_firstch.getMap0();
1779:                m_parent_map0 = m_parent.getMap0();
1780:            }
1781:
1782:            /**
1783:             * Override DTMDefaultBase._exptype() by dropping the incremental code.
1784:             *
1785:             * <p>This one is less efficient than _exptype2. It is only used during
1786:             * DTM building. _exptype2 is used after the document is fully built.
1787:             */
1788:            public final int _exptype(int identity) {
1789:                return m_exptype.elementAt(identity);
1790:            }
1791:
1792:            /************************************************************************
1793:             *             DTM base accessor interfaces
1794:             *
1795:             * %OPT% The code in the following interfaces (e.g. _exptype2, etc.) are
1796:             * very important to the DTM performance. To have the best performace,
1797:             * these several interfaces have direct access to the internal arrays of
1798:             * the SuballocatedIntVectors. The final modifier also has a noticeable
1799:             * impact on performance.
1800:             ***********************************************************************/
1801:
1802:            /**
1803:             * The optimized version of DTMDefaultBase._exptype().
1804:             *
1805:             * @param identity A node identity, which <em>must not</em> be equal to
1806:             *        <code>DTM.NULL</code>
1807:             */
1808:            public final int _exptype2(int identity) {
1809:                //return m_exptype.elementAt(identity);
1810:
1811:                if (identity < m_blocksize)
1812:                    return m_exptype_map0[identity];
1813:                else
1814:                    return m_exptype_map[identity >>> m_SHIFT][identity
1815:                            & m_MASK];
1816:            }
1817:
1818:            /**
1819:             * The optimized version of DTMDefaultBase._nextsib().
1820:             *
1821:             * @param identity A node identity, which <em>must not</em> be equal to
1822:             *        <code>DTM.NULL</code>
1823:             */
1824:            public final int _nextsib2(int identity) {
1825:                //return m_nextsib.elementAt(identity);
1826:
1827:                if (identity < m_blocksize)
1828:                    return m_nextsib_map0[identity];
1829:                else
1830:                    return m_nextsib_map[identity >>> m_SHIFT][identity
1831:                            & m_MASK];
1832:            }
1833:
1834:            /**
1835:             * The optimized version of DTMDefaultBase._firstch().
1836:             *
1837:             * @param identity A node identity, which <em>must not</em> be equal to
1838:             *        <code>DTM.NULL</code>
1839:             */
1840:            public final int _firstch2(int identity) {
1841:                //return m_firstch.elementAt(identity);
1842:
1843:                if (identity < m_blocksize)
1844:                    return m_firstch_map0[identity];
1845:                else
1846:                    return m_firstch_map[identity >>> m_SHIFT][identity
1847:                            & m_MASK];
1848:            }
1849:
1850:            /**
1851:             * The optimized version of DTMDefaultBase._parent().
1852:             *
1853:             * @param identity A node identity, which <em>must not</em> be equal to
1854:             *        <code>DTM.NULL</code>
1855:             */
1856:            public final int _parent2(int identity) {
1857:                //return m_parent.elementAt(identity);
1858:
1859:                if (identity < m_blocksize)
1860:                    return m_parent_map0[identity];
1861:                else
1862:                    return m_parent_map[identity >>> m_SHIFT][identity & m_MASK];
1863:            }
1864:
1865:            /**
1866:             * The optimized version of DTMDefaultBase._type().
1867:             *
1868:             * @param identity A node identity, which <em>must not</em> be equal to
1869:             *        <code>DTM.NULL</code>
1870:             */
1871:            public final int _type2(int identity) {
1872:                //int eType = _exptype2(identity);
1873:                int eType;
1874:                if (identity < m_blocksize)
1875:                    eType = m_exptype_map0[identity];
1876:                else
1877:                    eType = m_exptype_map[identity >>> m_SHIFT][identity
1878:                            & m_MASK];
1879:
1880:                if (NULL != eType)
1881:                    return m_extendedTypes[eType].getNodeType();
1882:                else
1883:                    return NULL;
1884:            }
1885:
1886:            /**
1887:             * The optimized version of DTMDefaultBase.getExpandedTypeID(int).
1888:             *
1889:             * <p>This one is only used by DOMAdapter.getExpandedTypeID(int), which
1890:             * is mostly called from the compiled translets.
1891:             */
1892:            public final int getExpandedTypeID2(int nodeHandle) {
1893:                int nodeID = makeNodeIdentity(nodeHandle);
1894:
1895:                //return (nodeID != NULL) ? _exptype2(nodeID) : NULL;
1896:
1897:                if (nodeID != NULL) {
1898:                    if (nodeID < m_blocksize)
1899:                        return m_exptype_map0[nodeID];
1900:                    else
1901:                        return m_exptype_map[nodeID >>> m_SHIFT][nodeID
1902:                                & m_MASK];
1903:                } else
1904:                    return NULL;
1905:            }
1906:
1907:            /*************************************************************************
1908:             *                 END of DTM base accessor interfaces
1909:             *************************************************************************/
1910:
1911:            /**
1912:             * Return the node type from the expanded type
1913:             */
1914:            public final int _exptype2Type(int exptype) {
1915:                if (NULL != exptype)
1916:                    return m_extendedTypes[exptype].getNodeType();
1917:                else
1918:                    return NULL;
1919:            }
1920:
1921:            /**
1922:             * Get a prefix either from the uri mapping, or just make
1923:             * one up!
1924:             *
1925:             * @param uri The namespace URI, which may be null.
1926:             *
1927:             * @return The prefix if there is one, or null.
1928:             */
1929:            public int getIdForNamespace(String uri) {
1930:                int index = m_values.indexOf(uri);
1931:                if (index < 0) {
1932:                    m_values.addElement(uri);
1933:                    return m_valueIndex++;
1934:                } else
1935:                    return index;
1936:            }
1937:
1938:            /**
1939:             * Override SAX2DTM.startElement()
1940:             *
1941:             * <p>Receive notification of the start of an element.
1942:             *
1943:             * <p>By default, do nothing.  Application writers may override this
1944:             * method in a subclass to take specific actions at the start of
1945:             * each element (such as allocating a new tree node or writing
1946:             * output to a file).</p>
1947:             *
1948:             * @param uri The Namespace URI, or the empty string if the
1949:             *        element has no Namespace URI or if Namespace
1950:             *        processing is not being performed.
1951:             * @param localName The local name (without prefix), or the
1952:             *        empty string if Namespace processing is not being
1953:             *        performed.
1954:             * @param qName The qualified name (with prefix), or the
1955:             *        empty string if qualified names are not available.
1956:             * @param attributes The specified or defaulted attributes.
1957:             * @throws SAXException Any SAX exception, possibly
1958:             *            wrapping another exception.
1959:             * @see org.xml.sax.ContentHandler#startElement
1960:             */
1961:            public void startElement(String uri, String localName,
1962:                    String qName, Attributes attributes) throws SAXException {
1963:
1964:                charactersFlush();
1965:
1966:                int exName = m_expandedNameTable.getExpandedTypeID(uri,
1967:                        localName, DTM.ELEMENT_NODE);
1968:
1969:                int prefixIndex = (qName.length() != localName.length()) ? m_valuesOrPrefixes
1970:                        .stringToIndex(qName)
1971:                        : 0;
1972:
1973:                int elemNode = addNode(DTM.ELEMENT_NODE, exName, m_parents
1974:                        .peek(), m_previous, prefixIndex, true);
1975:
1976:                if (m_indexing)
1977:                    indexNode(exName, elemNode);
1978:
1979:                m_parents.push(elemNode);
1980:
1981:                int startDecls = m_contextIndexes.peek();
1982:                int nDecls = m_prefixMappings.size();
1983:                String prefix;
1984:
1985:                if (!m_pastFirstElement) {
1986:                    // SPECIAL CASE: Implied declaration at root element
1987:                    prefix = "xml";
1988:                    String declURL = "http://www.w3.org/XML/1998/namespace";
1989:                    exName = m_expandedNameTable.getExpandedTypeID(null,
1990:                            prefix, DTM.NAMESPACE_NODE);
1991:                    m_values.addElement(declURL);
1992:                    int val = m_valueIndex++;
1993:                    addNode(DTM.NAMESPACE_NODE, exName, elemNode, DTM.NULL,
1994:                            val, false);
1995:                    m_pastFirstElement = true;
1996:                }
1997:
1998:                for (int i = startDecls; i < nDecls; i += 2) {
1999:                    prefix = (String) m_prefixMappings.elementAt(i);
2000:
2001:                    if (prefix == null)
2002:                        continue;
2003:
2004:                    String declURL = (String) m_prefixMappings.elementAt(i + 1);
2005:
2006:                    exName = m_expandedNameTable.getExpandedTypeID(null,
2007:                            prefix, DTM.NAMESPACE_NODE);
2008:
2009:                    m_values.addElement(declURL);
2010:                    int val = m_valueIndex++;
2011:
2012:                    addNode(DTM.NAMESPACE_NODE, exName, elemNode, DTM.NULL,
2013:                            val, false);
2014:                }
2015:
2016:                int n = attributes.getLength();
2017:
2018:                for (int i = 0; i < n; i++) {
2019:                    String attrUri = attributes.getURI(i);
2020:                    String attrQName = attributes.getQName(i);
2021:                    String valString = attributes.getValue(i);
2022:
2023:                    int nodeType;
2024:
2025:                    String attrLocalName = attributes.getLocalName(i);
2026:
2027:                    if ((null != attrQName)
2028:                            && (attrQName.equals("xmlns") || attrQName
2029:                                    .startsWith("xmlns:"))) {
2030:                        prefix = getPrefix(attrQName, attrUri);
2031:                        if (declAlreadyDeclared(prefix))
2032:                            continue; // go to the next attribute.
2033:
2034:                        nodeType = DTM.NAMESPACE_NODE;
2035:                    } else {
2036:                        nodeType = DTM.ATTRIBUTE_NODE;
2037:
2038:                        if (m_buildIdIndex
2039:                                && attributes.getType(i).equalsIgnoreCase("ID"))
2040:                            setIDAttribute(valString, elemNode);
2041:                    }
2042:
2043:                    // Bit of a hack... if somehow valString is null, stringToIndex will
2044:                    // return -1, which will make things very unhappy.
2045:                    if (null == valString)
2046:                        valString = "";
2047:
2048:                    m_values.addElement(valString);
2049:                    int val = m_valueIndex++;
2050:
2051:                    if (attrLocalName.length() != attrQName.length()) {
2052:
2053:                        prefixIndex = m_valuesOrPrefixes
2054:                                .stringToIndex(attrQName);
2055:
2056:                        int dataIndex = m_data.size();
2057:
2058:                        m_data.addElement(prefixIndex);
2059:                        m_data.addElement(val);
2060:
2061:                        val = -dataIndex;
2062:                    }
2063:
2064:                    exName = m_expandedNameTable.getExpandedTypeID(attrUri,
2065:                            attrLocalName, nodeType);
2066:                    addNode(nodeType, exName, elemNode, DTM.NULL, val, false);
2067:                }
2068:
2069:                if (null != m_wsfilter) {
2070:                    short wsv = m_wsfilter.getShouldStripSpace(
2071:                            makeNodeHandle(elemNode), this );
2072:                    boolean shouldStrip = (DTMWSFilter.INHERIT == wsv) ? getShouldStripWhitespace()
2073:                            : (DTMWSFilter.STRIP == wsv);
2074:
2075:                    pushShouldStripWhitespace(shouldStrip);
2076:                }
2077:
2078:                m_previous = DTM.NULL;
2079:
2080:                m_contextIndexes.push(m_prefixMappings.size()); // for the children.
2081:            }
2082:
2083:            /**
2084:             * Receive notification of the end of an element.
2085:             *
2086:             * <p>By default, do nothing.  Application writers may override this
2087:             * method in a subclass to take specific actions at the end of
2088:             * each element (such as finalising a tree node or writing
2089:             * output to a file).</p>
2090:             *
2091:             * @param uri The Namespace URI, or the empty string if the
2092:             *        element has no Namespace URI or if Namespace
2093:             *        processing is not being performed.
2094:             * @param localName The local name (without prefix), or the
2095:             *        empty string if Namespace processing is not being
2096:             *        performed.
2097:             * @param qName The qualified XML 1.0 name (with prefix), or the
2098:             *        empty string if qualified names are not available.
2099:             * @throws SAXException Any SAX exception, possibly
2100:             *            wrapping another exception.
2101:             * @see org.xml.sax.ContentHandler#endElement
2102:             */
2103:            public void endElement(String uri, String localName, String qName)
2104:                    throws SAXException {
2105:                charactersFlush();
2106:
2107:                // If no one noticed, startPrefixMapping is a drag.
2108:                // Pop the context for the last child (the one pushed by startElement)
2109:                m_contextIndexes.quickPop(1);
2110:
2111:                // Do it again for this one (the one pushed by the last endElement).
2112:                int topContextIndex = m_contextIndexes.peek();
2113:                if (topContextIndex != m_prefixMappings.size()) {
2114:                    m_prefixMappings.setSize(topContextIndex);
2115:                }
2116:
2117:                m_previous = m_parents.pop();
2118:
2119:                popShouldStripWhitespace();
2120:            }
2121:
2122:            /**
2123:             * Report an XML comment anywhere in the document.
2124:             *
2125:             * <p>This callback will be used for comments inside or outside the
2126:             * document element, including comments in the external DTD
2127:             * subset (if read).</p>
2128:             *
2129:             * @param ch An array holding the characters in the comment.
2130:             * @param start The starting position in the array.
2131:             * @param length The number of characters to use from the array.
2132:             * @throws SAXException The application may raise an exception.
2133:             */
2134:            public void comment(char ch[], int start, int length)
2135:                    throws SAXException {
2136:
2137:                if (m_insideDTD) // ignore comments if we're inside the DTD
2138:                    return;
2139:
2140:                charactersFlush();
2141:
2142:                // %OPT% Saving the comment string in a Vector has a lower cost than
2143:                // saving it in DTMStringPool.
2144:                m_values.addElement(new String(ch, start, length));
2145:                int dataIndex = m_valueIndex++;
2146:
2147:                m_previous = addNode(DTM.COMMENT_NODE, DTM.COMMENT_NODE,
2148:                        m_parents.peek(), m_previous, dataIndex, false);
2149:            }
2150:
2151:            /**
2152:             * Receive notification of the beginning of the document.
2153:             *
2154:             * @throws SAXException Any SAX exception, possibly
2155:             *            wrapping another exception.
2156:             * @see org.xml.sax.ContentHandler#startDocument
2157:             */
2158:            public void startDocument() throws SAXException {
2159:
2160:                int doc = addNode(DTM.DOCUMENT_NODE, DTM.DOCUMENT_NODE,
2161:                        DTM.NULL, DTM.NULL, 0, true);
2162:
2163:                m_parents.push(doc);
2164:                m_previous = DTM.NULL;
2165:
2166:                m_contextIndexes.push(m_prefixMappings.size()); // for the next element.
2167:            }
2168:
2169:            /**
2170:             * Receive notification of the end of the document.
2171:             *
2172:             * @throws SAXException Any SAX exception, possibly
2173:             *            wrapping another exception.
2174:             * @see org.xml.sax.ContentHandler#endDocument
2175:             */
2176:            public void endDocument() throws SAXException {
2177:                super .endDocument();
2178:
2179:                // Add a NULL entry to the end of the node arrays as
2180:                // the end indication.
2181:                m_exptype.addElement(NULL);
2182:                m_parent.addElement(NULL);
2183:                m_nextsib.addElement(NULL);
2184:                m_firstch.addElement(NULL);
2185:
2186:                // Set the cached references after the document is built.
2187:                m_extendedTypes = m_expandedNameTable.getExtendedTypes();
2188:                m_exptype_map = m_exptype.getMap();
2189:                m_nextsib_map = m_nextsib.getMap();
2190:                m_firstch_map = m_firstch.getMap();
2191:                m_parent_map = m_parent.getMap();
2192:            }
2193:
2194:            /**
2195:             * Construct the node map from the node.
2196:             *
2197:             * @param type raw type ID, one of DTM.XXX_NODE.
2198:             * @param expandedTypeID The expended type ID.
2199:             * @param parentIndex The current parent index.
2200:             * @param previousSibling The previous sibling index.
2201:             * @param dataOrPrefix index into m_data table, or string handle.
2202:             * @param canHaveFirstChild true if the node can have a first child, false
2203:             *                          if it is atomic.
2204:             *
2205:             * @return The index identity of the node that was added.
2206:             */
2207:            protected final int addNode(int type, int expandedTypeID,
2208:                    int parentIndex, int previousSibling, int dataOrPrefix,
2209:                    boolean canHaveFirstChild) {
2210:                // Common to all nodes:
2211:                int nodeIndex = m_size++;
2212:
2213:                // Have we overflowed a DTM Identity's addressing range?
2214:                //if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
2215:                if (nodeIndex == m_maxNodeIndex) {
2216:                    addNewDTMID(nodeIndex);
2217:                    m_maxNodeIndex += (1 << DTMManager.IDENT_DTM_NODE_BITS);
2218:                }
2219:
2220:                m_firstch.addElement(DTM.NULL);
2221:                m_nextsib.addElement(DTM.NULL);
2222:                m_parent.addElement(parentIndex);
2223:                m_exptype.addElement(expandedTypeID);
2224:                m_dataOrQName.addElement(dataOrPrefix);
2225:
2226:                if (m_prevsib != null) {
2227:                    m_prevsib.addElement(previousSibling);
2228:                }
2229:
2230:                if (m_locator != null && m_useSourceLocationProperty) {
2231:                    setSourceLocation();
2232:                }
2233:
2234:                // Note that nextSibling is not processed until charactersFlush()
2235:                // is called, to handle successive characters() events.
2236:
2237:                // Special handling by type: Declare namespaces, attach first child
2238:                switch (type) {
2239:                case DTM.NAMESPACE_NODE:
2240:                    declareNamespaceInContext(parentIndex, nodeIndex);
2241:                    break;
2242:                case DTM.ATTRIBUTE_NODE:
2243:                    break;
2244:                default:
2245:                    if (DTM.NULL != previousSibling) {
2246:                        m_nextsib.setElementAt(nodeIndex, previousSibling);
2247:                    } else if (DTM.NULL != parentIndex) {
2248:                        m_firstch.setElementAt(nodeIndex, parentIndex);
2249:                    }
2250:                    break;
2251:                }
2252:
2253:                return nodeIndex;
2254:            }
2255:
2256:            /**
2257:             * Check whether accumulated text should be stripped; if not,
2258:             * append the appropriate flavor of text/cdata node.
2259:             */
2260:            protected final void charactersFlush() {
2261:
2262:                if (m_textPendingStart >= 0) // -1 indicates no-text-in-progress
2263:                {
2264:                    int length = m_chars.size() - m_textPendingStart;
2265:                    boolean doStrip = false;
2266:
2267:                    if (getShouldStripWhitespace()) {
2268:                        doStrip = m_chars.isWhitespace(m_textPendingStart,
2269:                                length);
2270:                    }
2271:
2272:                    if (doStrip) {
2273:                        m_chars.setLength(m_textPendingStart); // Discard accumulated text
2274:                    } else {
2275:                        // Guard against characters/ignorableWhitespace events that
2276:                        // contained no characters.  They should not result in a node.
2277:                        if (length > 0) {
2278:                            // If the offset and length do not exceed the given limits
2279:                            // (offset < 2^21 and length < 2^10), then save both the offset
2280:                            // and length in a bitwise encoded value.
2281:                            if (length <= TEXT_LENGTH_MAX
2282:                                    && m_textPendingStart <= TEXT_OFFSET_MAX) {
2283:                                m_previous = addNode(
2284:                                        m_coalescedTextType,
2285:                                        DTM.TEXT_NODE,
2286:                                        m_parents.peek(),
2287:                                        m_previous,
2288:                                        length
2289:                                                + (m_textPendingStart << TEXT_LENGTH_BITS),
2290:                                        false);
2291:
2292:                            } else {
2293:                                // Store offset and length in the m_data array if one exceeds 
2294:                                // the given limits. Use a negative dataIndex as an indication.
2295:                                int dataIndex = m_data.size();
2296:                                m_previous = addNode(m_coalescedTextType,
2297:                                        DTM.TEXT_NODE, m_parents.peek(),
2298:                                        m_previous, -dataIndex, false);
2299:
2300:                                m_data.addElement(m_textPendingStart);
2301:                                m_data.addElement(length);
2302:                            }
2303:                        }
2304:                    }
2305:
2306:                    // Reset for next text block
2307:                    m_textPendingStart = -1;
2308:                    m_textType = m_coalescedTextType = DTM.TEXT_NODE;
2309:                }
2310:            }
2311:
2312:            /**
2313:             * Override the processingInstruction() interface in SAX2DTM2.
2314:             * <p>
2315:             * %OPT% This one is different from SAX2DTM.processingInstruction()
2316:             * in that we do not use extended types for PI nodes. The name of
2317:             * the PI is saved in the DTMStringPool.
2318:             *
2319:             * Receive notification of a processing instruction.
2320:             *
2321:             * @param target The processing instruction target.
2322:             * @param data The processing instruction data, or null if
2323:             *             none is supplied.
2324:             * @throws SAXException Any SAX exception, possibly
2325:             *            wrapping another exception.
2326:             * @see org.xml.sax.ContentHandler#processingInstruction
2327:             */
2328:            public void processingInstruction(String target, String data)
2329:                    throws SAXException {
2330:
2331:                charactersFlush();
2332:
2333:                int dataIndex = m_data.size();
2334:                m_previous = addNode(DTM.PROCESSING_INSTRUCTION_NODE,
2335:                        DTM.PROCESSING_INSTRUCTION_NODE, m_parents.peek(),
2336:                        m_previous, -dataIndex, false);
2337:
2338:                m_data.addElement(m_valuesOrPrefixes.stringToIndex(target));
2339:                m_values.addElement(data);
2340:                m_data.addElement(m_valueIndex++);
2341:
2342:            }
2343:
2344:            /**
2345:             * The optimized version of DTMDefaultBase.getFirstAttribute().
2346:             * <p>
2347:             * Given a node handle, get the index of the node's first attribute.
2348:             *
2349:             * @param nodeHandle int Handle of the node.
2350:             * @return Handle of first attribute, or DTM.NULL to indicate none exists.
2351:             */
2352:            public final int getFirstAttribute(int nodeHandle) {
2353:                int nodeID = makeNodeIdentity(nodeHandle);
2354:
2355:                if (nodeID == DTM.NULL)
2356:                    return DTM.NULL;
2357:
2358:                int type = _type2(nodeID);
2359:
2360:                if (DTM.ELEMENT_NODE == type) {
2361:                    // Assume that attributes and namespaces immediately follow the element.
2362:                    while (true) {
2363:                        nodeID++;
2364:                        // Assume this can not be null.
2365:                        type = _type2(nodeID);
2366:
2367:                        if (type == DTM.ATTRIBUTE_NODE) {
2368:                            return makeNodeHandle(nodeID);
2369:                        } else if (DTM.NAMESPACE_NODE != type) {
2370:                            break;
2371:                        }
2372:                    }
2373:                }
2374:
2375:                return DTM.NULL;
2376:            }
2377:
2378:            /**
2379:             * The optimized version of DTMDefaultBase.getFirstAttributeIdentity(int).
2380:             * <p>
2381:             * Given a node identity, get the index of the node's first attribute.
2382:             *
2383:             * @param identity int identity of the node.
2384:             * @return Identity of first attribute, or DTM.NULL to indicate none exists.
2385:             */
2386:            protected int getFirstAttributeIdentity(int identity) {
2387:                if (identity == NULL) {
2388:                    return NULL;
2389:                }
2390:                int type = _type2(identity);
2391:
2392:                if (DTM.ELEMENT_NODE == type) {
2393:                    // Assume that attributes and namespaces immediately follow the element.
2394:                    while (true) {
2395:                        identity++;
2396:
2397:                        // Assume this can not be null.
2398:                        type = _type2(identity);
2399:
2400:                        if (type == DTM.ATTRIBUTE_NODE) {
2401:                            return identity;
2402:                        } else if (DTM.NAMESPACE_NODE != type) {
2403:                            break;
2404:                        }
2405:                    }
2406:                }
2407:
2408:                return DTM.NULL;
2409:            }
2410:
2411:            /**
2412:             * The optimized version of DTMDefaultBase.getNextAttributeIdentity(int).
2413:             * <p>
2414:             * Given a node identity for an attribute, advance to the next attribute.
2415:             *
2416:             * @param identity int identity of the attribute node.  This
2417:             * <strong>must</strong> be an attribute node.
2418:             *
2419:             * @return int DTM node-identity of the resolved attr,
2420:             * or DTM.NULL to indicate none exists.
2421:             *
2422:             */
2423:            protected int getNextAttributeIdentity(int identity) {
2424:                // Assume that attributes and namespace nodes immediately follow the element
2425:                while (true) {
2426:                    identity++;
2427:                    int type = _type2(identity);
2428:
2429:                    if (type == DTM.ATTRIBUTE_NODE) {
2430:                        return identity;
2431:                    } else if (type != DTM.NAMESPACE_NODE) {
2432:                        break;
2433:                    }
2434:                }
2435:
2436:                return DTM.NULL;
2437:            }
2438:
2439:            /**
2440:             * The optimized version of DTMDefaultBase.getTypedAttribute(int, int).
2441:             * <p>
2442:             * Given a node handle and an expanded type ID, get the index of the node's
2443:             * attribute of that type, if any.
2444:             *
2445:             * @param nodeHandle int Handle of the node.
2446:             * @param attType int expanded type ID of the required attribute.
2447:             * @return Handle of attribute of the required type, or DTM.NULL to indicate
2448:             * none exists.
2449:             */
2450:            protected final int getTypedAttribute(int nodeHandle, int attType) {
2451:
2452:                int nodeID = makeNodeIdentity(nodeHandle);
2453:
2454:                if (nodeID == DTM.NULL)
2455:                    return DTM.NULL;
2456:
2457:                int type = _type2(nodeID);
2458:
2459:                if (DTM.ELEMENT_NODE == type) {
2460:                    int expType;
2461:                    while (true) {
2462:                        nodeID++;
2463:                        expType = _exptype2(nodeID);
2464:
2465:                        if (expType != DTM.NULL)
2466:                            type = m_extendedTypes[expType].getNodeType();
2467:                        else
2468:                            return DTM.NULL;
2469:
2470:                        if (type == DTM.ATTRIBUTE_NODE) {
2471:                            if (expType == attType)
2472:                                return makeNodeHandle(nodeID);
2473:                        } else if (DTM.NAMESPACE_NODE != type) {
2474:                            break;
2475:                        }
2476:                    }
2477:                }
2478:
2479:                return DTM.NULL;
2480:            }
2481:
2482:            /**
2483:             * Override SAX2DTM.getLocalName() in SAX2DTM2.
2484:             * <p>Processing for PIs is different.
2485:             *
2486:             * Given a node handle, return its XPath- style localname. (As defined in
2487:             * Namespaces, this is the portion of the name after any colon character).
2488:             *
2489:             * @param nodeHandle the id of the node.
2490:             * @return String Local name of this node.
2491:             */
2492:            public String getLocalName(int nodeHandle) {
2493:                int expType = _exptype(makeNodeIdentity(nodeHandle));
2494:
2495:                if (expType == DTM.PROCESSING_INSTRUCTION_NODE) {
2496:                    int dataIndex = _dataOrQName(makeNodeIdentity(nodeHandle));
2497:                    dataIndex = m_data.elementAt(-dataIndex);
2498:                    return m_valuesOrPrefixes.indexToString(dataIndex);
2499:                } else
2500:                    return m_expandedNameTable.getLocalName(expType);
2501:            }
2502:
2503:            /**
2504:             * The optimized version of SAX2DTM.getNodeNameX().
2505:             * <p>
2506:             * Given a node handle, return the XPath node name. This should be the name
2507:             * as described by the XPath data model, NOT the DOM- style name.
2508:             *
2509:             * @param nodeHandle the id of the node.
2510:             * @return String Name of this node, which may be an empty string.
2511:             */
2512:            public final String getNodeNameX(int nodeHandle) {
2513:
2514:                int nodeID = makeNodeIdentity(nodeHandle);
2515:                int eType = _exptype2(nodeID);
2516:
2517:                if (eType == DTM.PROCESSING_INSTRUCTION_NODE) {
2518:                    int dataIndex = _dataOrQName(nodeID);
2519:                    dataIndex = m_data.elementAt(-dataIndex);
2520:                    return m_valuesOrPrefixes.indexToString(dataIndex);
2521:                }
2522:
2523:                final ExtendedType extType = m_extendedTypes[eType];
2524:
2525:                if (extType.getNamespace().length() == 0) {
2526:                    return extType.getLocalName();
2527:                } else {
2528:                    int qnameIndex = m_dataOrQName.elementAt(nodeID);
2529:
2530:                    if (qnameIndex == 0)
2531:                        return extType.getLocalName();
2532:
2533:                    if (qnameIndex < 0) {
2534:                        qnameIndex = -qnameIndex;
2535:                        qnameIndex = m_data.elementAt(qnameIndex);
2536:                    }
2537:
2538:                    return m_valuesOrPrefixes.indexToString(qnameIndex);
2539:                }
2540:            }
2541:
2542:            /**
2543:             * The optimized version of SAX2DTM.getNodeName().
2544:             * <p>
2545:             * Given a node handle, return its DOM-style node name. This will include
2546:             * names such as #text or #document.
2547:             *
2548:             * @param nodeHandle the id of the node.
2549:             * @return String Name of this node, which may be an empty string.
2550:             * %REVIEW% Document when empty string is possible...
2551:             * %REVIEW-COMMENT% It should never be empty, should it?
2552:             */
2553:            public String getNodeName(int nodeHandle) {
2554:
2555:                int nodeID = makeNodeIdentity(nodeHandle);
2556:                int eType = _exptype2(nodeID);
2557:
2558:                final ExtendedType extType = m_extendedTypes[eType];
2559:                if (extType.getNamespace().length() == 0) {
2560:                    int type = extType.getNodeType();
2561:
2562:                    String localName = extType.getLocalName();
2563:                    if (type == DTM.NAMESPACE_NODE) {
2564:                        if (localName.length() == 0)
2565:                            return "xmlns";
2566:                        else
2567:                            return "xmlns:" + localName;
2568:                    } else if (type == DTM.PROCESSING_INSTRUCTION_NODE) {
2569:                        int dataIndex = _dataOrQName(nodeID);
2570:                        dataIndex = m_data.elementAt(-dataIndex);
2571:                        return m_valuesOrPrefixes.indexToString(dataIndex);
2572:                    } else if (localName.length() == 0) {
2573:                        return getFixedNames(type);
2574:                    } else
2575:                        return localName;
2576:                } else {
2577:                    int qnameIndex = m_dataOrQName.elementAt(nodeID);
2578:
2579:                    if (qnameIndex == 0)
2580:                        return extType.getLocalName();
2581:
2582:                    if (qnameIndex < 0) {
2583:                        qnameIndex = -qnameIndex;
2584:                        qnameIndex = m_data.elementAt(qnameIndex);
2585:                    }
2586:
2587:                    return m_valuesOrPrefixes.indexToString(qnameIndex);
2588:                }
2589:            }
2590:
2591:            /**
2592:             * Override SAX2DTM.getStringValue(int)
2593:             * <p>
2594:             * This method is only used by Xalan-J Interpretive. It is not used by XSLTC.
2595:             * <p>
2596:             * If the caller supplies an XMLStringFactory, the getStringValue() interface
2597:             * in SAX2DTM will be called. Otherwise just calls getStringValueX() and
2598:             * wraps the returned String in an XMLString.
2599:             *
2600:             * Get the string-value of a node as a String object
2601:             * (see http://www.w3.org/TR/xpath#data-model
2602:             * for the definition of a node's string-value).
2603:             *
2604:             * @param nodeHandle The node ID.
2605:             *
2606:             * @return A string object that represents the string-value of the given node.
2607:             */
2608:            public XMLString getStringValue(int nodeHandle) {
2609:                int identity = makeNodeIdentity(nodeHandle);
2610:                if (identity == DTM.NULL)
2611:                    return EMPTY_XML_STR;
2612:
2613:                int type = _type2(identity);
2614:
2615:                if (type == DTM.ELEMENT_NODE || type == DTM.DOCUMENT_NODE) {
2616:                    int startNode = identity;
2617:                    identity = _firstch2(identity);
2618:                    if (DTM.NULL != identity) {
2619:                        int offset = -1;
2620:                        int length = 0;
2621:
2622:                        do {
2623:                            type = _exptype2(identity);
2624:
2625:                            if (type == DTM.TEXT_NODE
2626:                                    || type == DTM.CDATA_SECTION_NODE) {
2627:                                int dataIndex = m_dataOrQName
2628:                                        .elementAt(identity);
2629:                                if (dataIndex >= 0) {
2630:                                    if (-1 == offset) {
2631:                                        offset = dataIndex >>> TEXT_LENGTH_BITS;
2632:                                    }
2633:
2634:                                    length += dataIndex & TEXT_LENGTH_MAX;
2635:                                } else {
2636:                                    if (-1 == offset) {
2637:                                        offset = m_data.elementAt(-dataIndex);
2638:                                    }
2639:
2640:                                    length += m_data.elementAt(-dataIndex + 1);
2641:                                }
2642:                            }
2643:
2644:                            identity++;
2645:                        } while (_parent2(identity) >= startNode);
2646:
2647:                        if (length > 0) {
2648:                            if (m_xstrf != null)
2649:                                return m_xstrf.newstr(m_chars, offset, length);
2650:                            else
2651:                                return new XMLStringDefault(m_chars.getString(
2652:                                        offset, length));
2653:                        } else
2654:                            return EMPTY_XML_STR;
2655:                    } else
2656:                        return EMPTY_XML_STR;
2657:                } else if (DTM.TEXT_NODE == type
2658:                        || DTM.CDATA_SECTION_NODE == type) {
2659:                    int dataIndex = m_dataOrQName.elementAt(identity);
2660:                    if (dataIndex >= 0) {
2661:                        if (m_xstrf != null)
2662:                            return m_xstrf.newstr(m_chars,
2663:                                    dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2664:                                            & TEXT_LENGTH_MAX);
2665:                        else
2666:                            return new XMLStringDefault(m_chars.getString(
2667:                                    dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2668:                                            & TEXT_LENGTH_MAX));
2669:                    } else {
2670:                        if (m_xstrf != null)
2671:                            return m_xstrf.newstr(m_chars, m_data
2672:                                    .elementAt(-dataIndex), m_data
2673:                                    .elementAt(-dataIndex + 1));
2674:                        else
2675:                            return new XMLStringDefault(m_chars.getString(
2676:                                    m_data.elementAt(-dataIndex), m_data
2677:                                            .elementAt(-dataIndex + 1)));
2678:                    }
2679:                } else {
2680:                    int dataIndex = m_dataOrQName.elementAt(identity);
2681:
2682:                    if (dataIndex < 0) {
2683:                        dataIndex = -dataIndex;
2684:                        dataIndex = m_data.elementAt(dataIndex + 1);
2685:                    }
2686:
2687:                    if (m_xstrf != null)
2688:                        return m_xstrf.newstr((String) m_values
2689:                                .elementAt(dataIndex));
2690:                    else
2691:                        return new XMLStringDefault((String) m_values
2692:                                .elementAt(dataIndex));
2693:                }
2694:            }
2695:
2696:            /**
2697:             * The optimized version of SAX2DTM.getStringValue(int).
2698:             * <p>
2699:             * %OPT% This is one of the most often used interfaces. Performance is
2700:             * critical here. This one is different from SAX2DTM.getStringValue(int) in
2701:             * that it returns a String instead of a XMLString.
2702:             *
2703:             * Get the string- value of a node as a String object (see http: //www. w3.
2704:             * org/TR/xpath#data- model for the definition of a node's string- value).
2705:             *
2706:             * @param nodeHandle The node ID.
2707:             *
2708:             * @return A string object that represents the string-value of the given node.
2709:             */
2710:            public final String getStringValueX(final int nodeHandle) {
2711:                int identity = makeNodeIdentity(nodeHandle);
2712:                if (identity == DTM.NULL)
2713:                    return EMPTY_STR;
2714:
2715:                int type = _type2(identity);
2716:
2717:                if (type == DTM.ELEMENT_NODE || type == DTM.DOCUMENT_NODE) {
2718:                    int startNode = identity;
2719:                    identity = _firstch2(identity);
2720:                    if (DTM.NULL != identity) {
2721:                        int offset = -1;
2722:                        int length = 0;
2723:
2724:                        do {
2725:                            type = _exptype2(identity);
2726:
2727:                            if (type == DTM.TEXT_NODE
2728:                                    || type == DTM.CDATA_SECTION_NODE) {
2729:                                int dataIndex = m_dataOrQName
2730:                                        .elementAt(identity);
2731:                                if (dataIndex >= 0) {
2732:                                    if (-1 == offset) {
2733:                                        offset = dataIndex >>> TEXT_LENGTH_BITS;
2734:                                    }
2735:
2736:                                    length += dataIndex & TEXT_LENGTH_MAX;
2737:                                } else {
2738:                                    if (-1 == offset) {
2739:                                        offset = m_data.elementAt(-dataIndex);
2740:                                    }
2741:
2742:                                    length += m_data.elementAt(-dataIndex + 1);
2743:                                }
2744:                            }
2745:
2746:                            identity++;
2747:                        } while (_parent2(identity) >= startNode);
2748:
2749:                        if (length > 0) {
2750:                            return m_chars.getString(offset, length);
2751:                        } else
2752:                            return EMPTY_STR;
2753:                    } else
2754:                        return EMPTY_STR;
2755:                } else if (DTM.TEXT_NODE == type
2756:                        || DTM.CDATA_SECTION_NODE == type) {
2757:                    int dataIndex = m_dataOrQName.elementAt(identity);
2758:                    if (dataIndex >= 0) {
2759:                        return m_chars.getString(
2760:                                dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2761:                                        & TEXT_LENGTH_MAX);
2762:                    } else {
2763:                        return m_chars.getString(m_data.elementAt(-dataIndex),
2764:                                m_data.elementAt(-dataIndex + 1));
2765:                    }
2766:                } else {
2767:                    int dataIndex = m_dataOrQName.elementAt(identity);
2768:
2769:                    if (dataIndex < 0) {
2770:                        dataIndex = -dataIndex;
2771:                        dataIndex = m_data.elementAt(dataIndex + 1);
2772:                    }
2773:
2774:                    return (String) m_values.elementAt(dataIndex);
2775:                }
2776:            }
2777:
2778:            /**
2779:             * Returns the string value of the entire tree
2780:             */
2781:            public String getStringValue() {
2782:                int child = _firstch2(ROOTNODE);
2783:                if (child == DTM.NULL)
2784:                    return EMPTY_STR;
2785:
2786:                // optimization: only create StringBuffer if > 1 child
2787:                if ((_exptype2(child) == DTM.TEXT_NODE)
2788:                        && (_nextsib2(child) == DTM.NULL)) {
2789:                    int dataIndex = m_dataOrQName.elementAt(child);
2790:                    if (dataIndex >= 0)
2791:                        return m_chars.getString(
2792:                                dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2793:                                        & TEXT_LENGTH_MAX);
2794:                    else
2795:                        return m_chars.getString(m_data.elementAt(-dataIndex),
2796:                                m_data.elementAt(-dataIndex + 1));
2797:                } else
2798:                    return getStringValueX(getDocument());
2799:
2800:            }
2801:
2802:            /**
2803:             * The optimized version of SAX2DTM.dispatchCharactersEvents(int, ContentHandler, boolean).
2804:             * <p>
2805:             * Directly call the
2806:             * characters method on the passed ContentHandler for the
2807:             * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
2808:             * for the definition of a node's string-value). Multiple calls to the
2809:             * ContentHandler's characters methods may well occur for a single call to
2810:             * this method.
2811:             *
2812:             * @param nodeHandle The node ID.
2813:             * @param ch A non-null reference to a ContentHandler.
2814:             * @param normalize true if the content should be normalized according to
2815:             * the rules for the XPath
2816:             * <a href="http://www.w3.org/TR/xpath#function-normalize-space">normalize-space</a>
2817:             * function.
2818:             *
2819:             * @throws SAXException
2820:             */
2821:            public final void dispatchCharactersEvents(int nodeHandle,
2822:                    ContentHandler ch, boolean normalize) throws SAXException {
2823:
2824:                int identity = makeNodeIdentity(nodeHandle);
2825:
2826:                if (identity == DTM.NULL)
2827:                    return;
2828:
2829:                int type = _type2(identity);
2830:
2831:                if (type == DTM.ELEMENT_NODE || type == DTM.DOCUMENT_NODE) {
2832:                    int startNode = identity;
2833:                    identity = _firstch2(identity);
2834:                    if (DTM.NULL != identity) {
2835:                        int offset = -1;
2836:                        int length = 0;
2837:
2838:                        do {
2839:                            type = _exptype2(identity);
2840:
2841:                            if (type == DTM.TEXT_NODE
2842:                                    || type == DTM.CDATA_SECTION_NODE) {
2843:                                int dataIndex = m_dataOrQName
2844:                                        .elementAt(identity);
2845:
2846:                                if (dataIndex >= 0) {
2847:                                    if (-1 == offset) {
2848:                                        offset = dataIndex >>> TEXT_LENGTH_BITS;
2849:                                    }
2850:
2851:                                    length += dataIndex & TEXT_LENGTH_MAX;
2852:                                } else {
2853:                                    if (-1 == offset) {
2854:                                        offset = m_data.elementAt(-dataIndex);
2855:                                    }
2856:
2857:                                    length += m_data.elementAt(-dataIndex + 1);
2858:                                }
2859:                            }
2860:
2861:                            identity++;
2862:                        } while (_parent2(identity) >= startNode);
2863:
2864:                        if (length > 0) {
2865:                            if (normalize)
2866:                                m_chars.sendNormalizedSAXcharacters(ch, offset,
2867:                                        length);
2868:                            else
2869:                                m_chars.sendSAXcharacters(ch, offset, length);
2870:                        }
2871:                    }
2872:                } else if (DTM.TEXT_NODE == type
2873:                        || DTM.CDATA_SECTION_NODE == type) {
2874:                    int dataIndex = m_dataOrQName.elementAt(identity);
2875:
2876:                    if (dataIndex >= 0) {
2877:                        if (normalize)
2878:                            m_chars.sendNormalizedSAXcharacters(ch,
2879:                                    dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2880:                                            & TEXT_LENGTH_MAX);
2881:                        else
2882:                            m_chars.sendSAXcharacters(ch,
2883:                                    dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2884:                                            & TEXT_LENGTH_MAX);
2885:                    } else {
2886:                        if (normalize)
2887:                            m_chars.sendNormalizedSAXcharacters(ch, m_data
2888:                                    .elementAt(-dataIndex), m_data
2889:                                    .elementAt(-dataIndex + 1));
2890:                        else
2891:                            m_chars.sendSAXcharacters(ch, m_data
2892:                                    .elementAt(-dataIndex), m_data
2893:                                    .elementAt(-dataIndex + 1));
2894:                    }
2895:                } else {
2896:                    int dataIndex = m_dataOrQName.elementAt(identity);
2897:
2898:                    if (dataIndex < 0) {
2899:                        dataIndex = -dataIndex;
2900:                        dataIndex = m_data.elementAt(dataIndex + 1);
2901:                    }
2902:
2903:                    String str = (String) m_values.elementAt(dataIndex);
2904:
2905:                    if (normalize)
2906:                        FastStringBuffer.sendNormalizedSAXcharacters(str
2907:                                .toCharArray(), 0, str.length(), ch);
2908:                    else
2909:                        ch.characters(str.toCharArray(), 0, str.length());
2910:                }
2911:            }
2912:
2913:            /**
2914:             * Given a node handle, return its node value. This is mostly
2915:             * as defined by the DOM, but may ignore some conveniences.
2916:             * <p>
2917:             *
2918:             * @param nodeHandle The node id.
2919:             * @return String Value of this node, or null if not
2920:             * meaningful for this node type.
2921:             */
2922:            public String getNodeValue(int nodeHandle) {
2923:
2924:                int identity = makeNodeIdentity(nodeHandle);
2925:                int type = _type2(identity);
2926:
2927:                if (type == DTM.TEXT_NODE || type == DTM.CDATA_SECTION_NODE) {
2928:                    int dataIndex = _dataOrQName(identity);
2929:                    if (dataIndex > 0) {
2930:                        return m_chars.getString(
2931:                                dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2932:                                        & TEXT_LENGTH_MAX);
2933:                    } else {
2934:                        return m_chars.getString(m_data.elementAt(-dataIndex),
2935:                                m_data.elementAt(-dataIndex + 1));
2936:                    }
2937:                } else if (DTM.ELEMENT_NODE == type
2938:                        || DTM.DOCUMENT_FRAGMENT_NODE == type
2939:                        || DTM.DOCUMENT_NODE == type) {
2940:                    return null;
2941:                } else {
2942:                    int dataIndex = m_dataOrQName.elementAt(identity);
2943:
2944:                    if (dataIndex < 0) {
2945:                        dataIndex = -dataIndex;
2946:                        dataIndex = m_data.elementAt(dataIndex + 1);
2947:                    }
2948:
2949:                    return (String) m_values.elementAt(dataIndex);
2950:                }
2951:            }
2952:
2953:            /**
2954:             * Copy the String value of a Text node to a SerializationHandler
2955:             */
2956:            protected final void copyTextNode(final int nodeID,
2957:                    SerializationHandler handler) throws SAXException {
2958:                if (nodeID != DTM.NULL) {
2959:                    int dataIndex = m_dataOrQName.elementAt(nodeID);
2960:                    if (dataIndex >= 0) {
2961:                        m_chars.sendSAXcharacters(handler,
2962:                                dataIndex >>> TEXT_LENGTH_BITS, dataIndex
2963:                                        & TEXT_LENGTH_MAX);
2964:                    } else {
2965:                        m_chars.sendSAXcharacters(handler, m_data
2966:                                .elementAt(-dataIndex), m_data
2967:                                .elementAt(-dataIndex + 1));
2968:                    }
2969:                }
2970:            }
2971:
2972:            /**
2973:             * Copy an Element node to a SerializationHandler.
2974:             *
2975:             * @param nodeID The node identity
2976:             * @param exptype The expanded type of the Element node
2977:             * @param handler The SerializationHandler
2978:             * @return The qualified name of the Element node.
2979:             */
2980:            protected final String copyElement(int nodeID, int exptype,
2981:                    SerializationHandler handler) throws SAXException {
2982:                final ExtendedType extType = m_extendedTypes[exptype];
2983:                String uri = extType.getNamespace();
2984:                String name = extType.getLocalName();
2985:
2986:                if (uri.length() == 0) {
2987:                    handler.startElement(name);
2988:                    return name;
2989:                } else {
2990:                    int qnameIndex = m_dataOrQName.elementAt(nodeID);
2991:
2992:                    if (qnameIndex == 0) {
2993:                        handler.startElement(name);
2994:                        handler.namespaceAfterStartElement(EMPTY_STR, uri);
2995:                        return name;
2996:                    }
2997:
2998:                    if (qnameIndex < 0) {
2999:                        qnameIndex = -qnameIndex;
3000:                        qnameIndex = m_data.elementAt(qnameIndex);
3001:                    }
3002:
3003:                    String qName = m_valuesOrPrefixes.indexToString(qnameIndex);
3004:                    handler.startElement(qName);
3005:                    int prefixIndex = qName.indexOf(':');
3006:                    String prefix;
3007:                    if (prefixIndex > 0) {
3008:                        prefix = qName.substring(0, prefixIndex);
3009:                    } else {
3010:                        prefix = null;
3011:                    }
3012:                    handler.namespaceAfterStartElement(prefix, uri);
3013:                    return qName;
3014:                }
3015:
3016:            }
3017:
3018:            /**
3019:             * Copy  namespace nodes.
3020:             *
3021:             * @param nodeID The Element node identity
3022:             * @param handler The SerializationHandler
3023:             * @param inScope  true if all namespaces in scope should be copied,
3024:             *  false if only the namespace declarations should be copied.
3025:             */
3026:            protected final void copyNS(final int nodeID,
3027:                    SerializationHandler handler, boolean inScope)
3028:                    throws SAXException {
3029:                // %OPT% Optimization for documents which does not have any explicit
3030:                // namespace nodes. For these documents, there is an implicit
3031:                // namespace node (xmlns:xml="http://www.w3.org/XML/1998/namespace")
3032:                // declared on the root element node. In this case, there is no
3033:                // need to do namespace copying. We can safely return without
3034:                // doing anything.
3035:                if (m_namespaceDeclSetElements != null
3036:                        && m_namespaceDeclSetElements.size() == 1
3037:                        && m_namespaceDeclSets != null
3038:                        && ((SuballocatedIntVector) m_namespaceDeclSets
3039:                                .elementAt(0)).size() == 1)
3040:                    return;
3041:
3042:                SuballocatedIntVector nsContext = null;
3043:                int nextNSNode;
3044:
3045:                // Find the first namespace node
3046:                if (inScope) {
3047:                    nsContext = findNamespaceContext(nodeID);
3048:                    if (nsContext == null || nsContext.size() < 1)
3049:                        return;
3050:                    else
3051:                        nextNSNode = makeNodeIdentity(nsContext.elementAt(0));
3052:                } else
3053:                    nextNSNode = getNextNamespaceNode2(nodeID);
3054:
3055:                int nsIndex = 1;
3056:                while (nextNSNode != DTM.NULL) {
3057:                    // Retrieve the name of the namespace node
3058:                    int eType = _exptype2(nextNSNode);
3059:                    String nodeName = m_extendedTypes[eType].getLocalName();
3060:
3061:                    // Retrieve the node value of the namespace node
3062:                    int dataIndex = m_dataOrQName.elementAt(nextNSNode);
3063:
3064:                    if (dataIndex < 0) {
3065:                        dataIndex = -dataIndex;
3066:                        dataIndex = m_data.elementAt(dataIndex + 1);
3067:                    }
3068:
3069:                    String nodeValue = (String) m_values.elementAt(dataIndex);
3070:
3071:                    handler.namespaceAfterStartElement(nodeName, nodeValue);
3072:
3073:                    if (inScope) {
3074:                        if (nsIndex < nsContext.size()) {
3075:                            nextNSNode = makeNodeIdentity(nsContext
3076:                                    .elementAt(nsIndex));
3077:                            nsIndex++;
3078:                        } else
3079:                            return;
3080:                    } else
3081:                        nextNSNode = getNextNamespaceNode2(nextNSNode);
3082:                }
3083:            }
3084:
3085:            /**
3086:             * Return the next namespace node following the given base node.
3087:             *
3088:             * @baseID The node identity of the base node, which can be an
3089:             * element, attribute or namespace node.
3090:             * @return The namespace node immediately following the base node.
3091:             */
3092:            protected final int getNextNamespaceNode2(int baseID) {
3093:                int type;
3094:                while ((type = _type2(++baseID)) == DTM.ATTRIBUTE_NODE)
3095:                    ;
3096:
3097:                if (type == DTM.NAMESPACE_NODE)
3098:                    return baseID;
3099:                else
3100:                    return NULL;
3101:            }
3102:
3103:            /**
3104:             * Copy  attribute nodes from an element .
3105:             *
3106:             * @param nodeID The Element node identity
3107:             * @param handler The SerializationHandler
3108:             */
3109:            protected final void copyAttributes(final int nodeID,
3110:                    SerializationHandler handler) throws SAXException {
3111:
3112:                for (int current = getFirstAttributeIdentity(nodeID); current != DTM.NULL; current = getNextAttributeIdentity(current)) {
3113:                    int eType = _exptype2(current);
3114:                    copyAttribute(current, eType, handler);
3115:                }
3116:            }
3117:
3118:            /**
3119:             * Copy an Attribute node to a SerializationHandler
3120:             *
3121:             * @param nodeID The node identity
3122:             * @param exptype The expanded type of the Element node
3123:             * @param handler The SerializationHandler
3124:             */
3125:            protected final void copyAttribute(int nodeID, int exptype,
3126:                    SerializationHandler handler) throws SAXException {
3127:                /*
3128:                    final String uri = getNamespaceName(node);
3129:                    if (uri.length() != 0) {
3130:                        final String prefix = getPrefix(node);
3131:                        handler.namespaceAfterStartElement(prefix, uri);
3132:                    }
3133:                    handler.addAttribute(getNodeName(node), getNodeValue(node));
3134:                 */
3135:                final ExtendedType extType = m_extendedTypes[exptype];
3136:                final String uri = extType.getNamespace();
3137:                final String localName = extType.getLocalName();
3138:
3139:                String prefix = null;
3140:                String qname = null;
3141:                int dataIndex = _dataOrQName(nodeID);
3142:                int valueIndex = dataIndex;
3143:                if (dataIndex <= 0) {
3144:                    int prefixIndex = m_data.elementAt(-dataIndex);
3145:                    valueIndex = m_data.elementAt(-dataIndex + 1);
3146:                    qname = m_valuesOrPrefixes.indexToString(prefixIndex);
3147:                    int colonIndex = qname.indexOf(':');
3148:                    if (colonIndex > 0) {
3149:                        prefix = qname.substring(0, colonIndex);
3150:                    }
3151:                }
3152:                if (uri.length() != 0) {
3153:                    handler.namespaceAfterStartElement(prefix, uri);
3154:                }
3155:
3156:                String nodeName = (prefix != null) ? qname : localName;
3157:                String nodeValue = (String) m_values.elementAt(valueIndex);
3158:
3159:                handler.addAttribute(nodeName, nodeValue);
3160:            }
3161:
3162:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.