Source Code Cross Referenced for NodeWrapper.java in  » XML » saxonb » net » sf » saxon » xom » 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 » saxonb » net.sf.saxon.xom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package net.sf.saxon.xom;
0002:
0003:        import net.sf.saxon.Configuration;
0004:        import net.sf.saxon.trans.XPathException;
0005:        import net.sf.saxon.event.Receiver;
0006:        import net.sf.saxon.om.*;
0007:        import net.sf.saxon.pattern.AnyNodeTest;
0008:        import net.sf.saxon.pattern.NameTest;
0009:        import net.sf.saxon.pattern.NodeKindTest;
0010:        import net.sf.saxon.pattern.NodeTest;
0011:        import net.sf.saxon.type.Type;
0012:        import net.sf.saxon.value.UntypedAtomicValue;
0013:        import net.sf.saxon.value.Value;
0014:        import nu.xom.*;
0015:
0016:        /**
0017:         * A node in the XML parse tree representing an XML element, character content,
0018:         * or attribute.
0019:         * <P>
0020:         * This is the implementation of the NodeInfo interface used as a wrapper for
0021:         * XOM nodes.
0022:         *
0023:         * @author Michael H. Kay
0024:         * @author Wolfgang Hoschek (ported net.sf.saxon.jdom to XOM)
0025:         */
0026:
0027:        public class NodeWrapper implements  NodeInfo, VirtualNode,
0028:                SiblingCountingNode {
0029:
0030:            protected Node node;
0031:
0032:            protected short nodeKind;
0033:
0034:            private NodeWrapper parent; // null means unknown
0035:
0036:            protected DocumentWrapper docWrapper;
0037:
0038:            protected int index; // -1 means unknown
0039:
0040:            /**
0041:             * This constructor is protected: nodes should be created using the wrap
0042:             * factory method on the DocumentWrapper class
0043:             *
0044:             * @param node
0045:             *            The XOM node to be wrapped
0046:             * @param parent
0047:             *            The NodeWrapper that wraps the parent of this node
0048:             * @param index
0049:             *            Position of this node among its siblings
0050:             */
0051:            protected NodeWrapper(Node node, NodeWrapper parent, int index) {
0052:                short kind;
0053:                if (node instanceof  Element) {
0054:                    kind = Type.ELEMENT;
0055:                } else if (node instanceof  Text) {
0056:                    kind = Type.TEXT;
0057:                } else if (node instanceof  Attribute) {
0058:                    kind = Type.ATTRIBUTE;
0059:                } else if (node instanceof  Comment) {
0060:                    kind = Type.COMMENT;
0061:                } else if (node instanceof  ProcessingInstruction) {
0062:                    kind = Type.PROCESSING_INSTRUCTION;
0063:                } else if (node instanceof  Document) {
0064:                    kind = Type.DOCUMENT;
0065:                } else {
0066:                    throwIllegalNode(node); // moved out of fast path to enable better inlining
0067:                    return; // keep compiler happy
0068:                }
0069:                this .nodeKind = kind;
0070:                this .node = node;
0071:                this .parent = parent;
0072:                this .index = index;
0073:            }
0074:
0075:            /**
0076:             * Factory method to wrap a XOM node with a wrapper that implements the
0077:             * Saxon NodeInfo interface.
0078:             *
0079:             * @param node
0080:             *            The XOM node
0081:             * @param docWrapper
0082:             *            The wrapper for the Document containing this node
0083:             * @return The new wrapper for the supplied node
0084:             */
0085:            protected final NodeWrapper makeWrapper(Node node,
0086:                    DocumentWrapper docWrapper) {
0087:                return makeWrapper(node, docWrapper, null, -1);
0088:            }
0089:
0090:            /**
0091:             * Factory method to wrap a XOM node with a wrapper that implements the
0092:             * Saxon NodeInfo interface.
0093:             *
0094:             * @param node
0095:             *            The XOM node
0096:             * @param docWrapper
0097:             *            The wrapper for the Document containing this node
0098:             * @param parent
0099:             *            The wrapper for the parent of the XOM node
0100:             * @param index
0101:             *            The position of this node relative to its siblings
0102:             * @return The new wrapper for the supplied node
0103:             */
0104:
0105:            protected final NodeWrapper makeWrapper(Node node,
0106:                    DocumentWrapper docWrapper, NodeWrapper parent, int index) {
0107:
0108:                if (node == docWrapper.node)
0109:                    return docWrapper;
0110:                NodeWrapper wrapper = new NodeWrapper(node, parent, index);
0111:                wrapper.docWrapper = docWrapper;
0112:                return wrapper;
0113:            }
0114:
0115:            private static void throwIllegalNode(Node node) {
0116:                String str = node == null ? "NULL" : node.getClass()
0117:                        + " instance " + node.toString();
0118:                throw new IllegalArgumentException("Bad node type in XOM! "
0119:                        + str);
0120:            }
0121:
0122:            /**
0123:             * Get the configuration
0124:             */
0125:
0126:            public Configuration getConfiguration() {
0127:                return docWrapper.getConfiguration();
0128:            }
0129:
0130:            /**
0131:             * Get the underlying XOM node, to implement the VirtualNode interface
0132:             */
0133:
0134:            public Object getUnderlyingNode() {
0135:                return node;
0136:            }
0137:
0138:            /**
0139:             * Get the name pool for this node
0140:             *
0141:             * @return the NamePool
0142:             */
0143:
0144:            public NamePool getNamePool() {
0145:                return docWrapper.getNamePool();
0146:            }
0147:
0148:            /**
0149:             * Return the type of node.
0150:             *
0151:             * @return one of the values Node.ELEMENT, Node.TEXT, Node.ATTRIBUTE, etc.
0152:             */
0153:
0154:            public int getNodeKind() {
0155:                return nodeKind;
0156:            }
0157:
0158:            /**
0159:             * Get the typed value of the item
0160:             */
0161:
0162:            public SequenceIterator getTypedValue() {
0163:                return SingletonIterator.makeIterator(new UntypedAtomicValue(
0164:                        getStringValueCS()));
0165:            }
0166:
0167:            /**
0168:             * Get the typed value. The result of this method will always be consistent
0169:             * with the method {@link net.sf.saxon.om.Item#getTypedValue()}. However,
0170:             * this method is often more convenient and may be more efficient,
0171:             * especially in the common case where the value is expected to be a
0172:             * singleton.
0173:             *
0174:             * @return the typed value. If requireSingleton is set to true, the result
0175:             *         will always be an AtomicValue. In other cases it may be a Value
0176:             *         representing a sequence whose items are atomic values.
0177:             * @since 8.5
0178:             */
0179:
0180:            public Value atomize() {
0181:                return new UntypedAtomicValue(getStringValueCS());
0182:            }
0183:
0184:            /**
0185:             * Get the type annotation of this node, if any. Returns -1 for kinds of
0186:             * nodes that have no annotation, and for elements annotated as untyped, and
0187:             * attributes annotated as untypedAtomic.
0188:             *
0189:             * @return -1 (there is no type annotation)
0190:             * @return the type annotation of the node.
0191:             * @see net.sf.saxon.type.Type
0192:             */
0193:
0194:            public int getTypeAnnotation() {
0195:                return -1;
0196:            }
0197:
0198:            /**
0199:             * Determine whether this is the same node as another node. <br />
0200:             * Note: a.isSameNode(b) if and only if generateId(a)==generateId(b)
0201:             *
0202:             * @return true if this Node object and the supplied Node object represent
0203:             *         the same node in the tree.
0204:             */
0205:
0206:            public boolean isSameNodeInfo(NodeInfo other) {
0207:                if (other instanceof  NodeWrapper) {
0208:                    return node == ((NodeWrapper) other).node; // In XOM equality means identity
0209:                }
0210:                return false;
0211:            }
0212:
0213:            /**
0214:             * Get the System ID for the node.
0215:             *
0216:             * @return the System Identifier of the entity in the source document
0217:             *         containing the node, or null if not known. Note this is not the
0218:             *         same as the base URI: the base URI can be modified by xml:base,
0219:             *         but the system ID cannot.
0220:             */
0221:
0222:            public String getSystemId() {
0223:                return docWrapper.baseURI;
0224:            }
0225:
0226:            public void setSystemId(String uri) {
0227:                docWrapper.baseURI = uri;
0228:            }
0229:
0230:            /**
0231:             * Get the Base URI for the node, that is, the URI used for resolving a
0232:             * relative URI contained in the node.
0233:             */
0234:
0235:            public String getBaseURI() {
0236:                return node.getBaseURI();
0237:            }
0238:
0239:            /**
0240:             * Get line number
0241:             *
0242:             * @return the line number of the node in its original source document; or
0243:             *         -1 if not available
0244:             */
0245:
0246:            public int getLineNumber() {
0247:                return -1;
0248:            }
0249:
0250:            /**
0251:             * Determine the relative position of this node and another node, in
0252:             * document order. The other node will always be in the same document.
0253:             *
0254:             * @param other
0255:             *            The other node, whose position is to be compared with this
0256:             *            node
0257:             * @return -1 if this node precedes the other node, +1 if it follows the
0258:             *         other node, or 0 if they are the same node. (In this case,
0259:             *         isSameNode() will always return true, and the two nodes will
0260:             *         produce the same result for generateId())
0261:             */
0262:
0263:            public int compareOrder(NodeInfo other) {
0264:                if (other instanceof  NodeWrapper) {
0265:                    return compareOrderFast(node, ((NodeWrapper) other).node);
0266:                    //		}
0267:                    //		if (other instanceof SiblingCountingNode) {
0268:                    //			return Navigator.compareOrder(this, (SiblingCountingNode) other);
0269:                } else {
0270:                    // it must be a namespace node
0271:                    return -other.compareOrder(this );
0272:                }
0273:            }
0274:
0275:            private static int compareOrderFast(Node first, Node second) {
0276:                /*
0277:                 * Unfortunately we do not have a sequence number for each node at hand;
0278:                 * this would allow to turn the comparison into a simple sequence number
0279:                 * subtraction. Walking the entire tree and batch-generating sequence
0280:                 * numbers on the fly is no good option either. However, this rewritten
0281:                 * implementation turns out to be more than fast enough.
0282:                 */
0283:
0284:                // assert first != null && second != null
0285:                // assert first and second MUST NOT be namespace nodes
0286:                if (first == second)
0287:                    return 0;
0288:
0289:                ParentNode firstParent = first.getParent();
0290:                ParentNode secondParent = second.getParent();
0291:                if (firstParent == null) {
0292:                    if (secondParent != null)
0293:                        return -1; // first node is the root
0294:                    // both nodes are parentless, use arbitrary but fixed order:
0295:                    return first.hashCode() - second.hashCode();
0296:                }
0297:
0298:                if (secondParent == null)
0299:                    return +1; // second node is the root
0300:
0301:                // do they have the same parent (common case)?
0302:                if (firstParent == secondParent) {
0303:                    int i1 = firstParent.indexOf(first);
0304:                    int i2 = firstParent.indexOf(second);
0305:
0306:                    // note that attributes and namespaces are not children
0307:                    // of their own parent (i = -1).
0308:                    // attribute (if any) comes before child
0309:                    if (i1 != -1)
0310:                        return (i2 != -1) ? i1 - i2 : +1;
0311:                    if (i2 != -1)
0312:                        return -1;
0313:
0314:                    // assert: i1 == -1 && i2 == -1
0315:                    // i.e. both nodes are attributes
0316:                    Element elem = (Element) firstParent;
0317:                    for (int i = elem.getAttributeCount(); --i >= 0;) {
0318:                        Attribute attr = elem.getAttribute(i);
0319:                        if (attr == second)
0320:                            return -1;
0321:                        if (attr == first)
0322:                            return +1;
0323:                    }
0324:                    throw new IllegalStateException("should be unreachable");
0325:                }
0326:
0327:                // find the depths of both nodes in the tree
0328:                int depth1 = 0;
0329:                int depth2 = 0;
0330:                Node p1 = first;
0331:                Node p2 = second;
0332:                while (p1 != null) {
0333:                    depth1++;
0334:                    p1 = p1.getParent();
0335:                    if (p1 == second)
0336:                        return +1;
0337:                }
0338:                while (p2 != null) {
0339:                    depth2++;
0340:                    p2 = p2.getParent();
0341:                    if (p2 == first)
0342:                        return -1;
0343:                }
0344:
0345:                // move up one branch of the tree so we have two nodes on the same level
0346:                p1 = first;
0347:                while (depth1 > depth2) {
0348:                    p1 = p1.getParent();
0349:                    depth1--;
0350:                }
0351:                p2 = second;
0352:                while (depth2 > depth1) {
0353:                    p2 = p2.getParent();
0354:                    depth2--;
0355:                }
0356:
0357:                // now move up both branches in sync until we find a common parent
0358:                while (true) {
0359:                    firstParent = p1.getParent();
0360:                    secondParent = p2.getParent();
0361:                    if (firstParent == null || secondParent == null) {
0362:                        // both nodes are documentless, use arbitrary but fixed order
0363:                        // based on their root elements
0364:                        return p1.hashCode() - p2.hashCode();
0365:                        // throw new NullPointerException("XOM tree compare - internal error");
0366:                    }
0367:                    if (firstParent == secondParent) {
0368:                        return firstParent.indexOf(p1)
0369:                                - firstParent.indexOf(p2);
0370:                    }
0371:                    p1 = firstParent;
0372:                    p2 = secondParent;
0373:                }
0374:            }
0375:
0376:            /**
0377:             * Return the string value of the node. The interpretation of this depends
0378:             * on the type of node. For an element it is the accumulated character
0379:             * content of the element, including descendant elements.
0380:             *
0381:             * @return the string value of the node
0382:             */
0383:
0384:            public String getStringValue() {
0385:                return node.getValue();
0386:            }
0387:
0388:            /**
0389:             * Get the value of the item as a CharSequence. This is in some cases more efficient than
0390:             * the version of the method that returns a String.
0391:             */
0392:
0393:            public CharSequence getStringValueCS() {
0394:                return node.getValue();
0395:            }
0396:
0397:            /**
0398:             * Get name code. The name code is a coded form of the node name: two nodes
0399:             * with the same name code have the same namespace URI, the same local name,
0400:             * and the same prefix. By masking the name code with &0xfffff, you get a
0401:             * fingerprint: two nodes with the same fingerprint have the same local name
0402:             * and namespace URI.
0403:             *
0404:             * @see net.sf.saxon.om.NamePool#allocate allocate
0405:             */
0406:
0407:            public int getNameCode() {
0408:                switch (nodeKind) {
0409:                case Type.ELEMENT:
0410:                case Type.ATTRIBUTE:
0411:                case Type.PROCESSING_INSTRUCTION:
0412:                    return docWrapper.getNamePool().allocate(getPrefix(),
0413:                            getURI(), getLocalPart());
0414:                default:
0415:                    return -1;
0416:                }
0417:            }
0418:
0419:            /**
0420:             * Get fingerprint. The fingerprint is a coded form of the expanded name of
0421:             * the node: two nodes with the same name code have the same namespace URI
0422:             * and the same local name. A fingerprint of -1 should be returned for a
0423:             * node with no name.
0424:             */
0425:
0426:            public int getFingerprint() {
0427:                int nc = getNameCode();
0428:                if (nc == -1)
0429:                    return -1;
0430:                return nc & 0xfffff;
0431:            }
0432:
0433:            /**
0434:             * Get the local part of the name of this node. This is the name after the
0435:             * ":" if any.
0436:             *
0437:             * @return the local part of the name. For an unnamed node, returns "".
0438:             */
0439:
0440:            public String getLocalPart() {
0441:                switch (nodeKind) {
0442:                case Type.ELEMENT:
0443:                    return ((Element) node).getLocalName();
0444:                case Type.ATTRIBUTE:
0445:                    return ((Attribute) node).getLocalName();
0446:                case Type.PROCESSING_INSTRUCTION:
0447:                    return ((ProcessingInstruction) node).getTarget();
0448:                default:
0449:                    return "";
0450:                }
0451:            }
0452:
0453:            /**
0454:             * Get the prefix of the name of the node. This is defined only for elements and attributes.
0455:             * If the node has no prefix, or for other kinds of node, return a zero-length string.
0456:             * @return The prefix of the name of the node.
0457:             */
0458:
0459:            public String getPrefix() {
0460:                switch (nodeKind) {
0461:                case Type.ELEMENT:
0462:                    return ((Element) node).getNamespacePrefix();
0463:                case Type.ATTRIBUTE:
0464:                    return ((Attribute) node).getNamespacePrefix();
0465:                default:
0466:                    return "";
0467:                }
0468:            }
0469:
0470:            /**
0471:             * Get the URI part of the name of this node. This is the URI corresponding
0472:             * to the prefix, or the URI of the default namespace if appropriate.
0473:             *
0474:             * @return The URI of the namespace of this node. For an unnamed node, or
0475:             *         for a node with an empty prefix, return an empty string.
0476:             */
0477:
0478:            public String getURI() {
0479:                switch (nodeKind) {
0480:                case Type.ELEMENT:
0481:                    return ((Element) node).getNamespaceURI();
0482:                case Type.ATTRIBUTE:
0483:                    return ((Attribute) node).getNamespaceURI();
0484:                default:
0485:                    return "";
0486:                }
0487:            }
0488:
0489:            /**
0490:             * Get the display name of this node. For elements and attributes this is
0491:             * [prefix:]localname. For unnamed nodes, it is an empty string.
0492:             *
0493:             * @return The display name of this node. For a node with no name, return an
0494:             *         empty string.
0495:             */
0496:
0497:            public String getDisplayName() {
0498:                switch (nodeKind) {
0499:                case Type.ELEMENT:
0500:                    return ((Element) node).getQualifiedName();
0501:                case Type.ATTRIBUTE:
0502:                    return ((Attribute) node).getQualifiedName();
0503:                case Type.PROCESSING_INSTRUCTION:
0504:                    return ((ProcessingInstruction) node).getTarget();
0505:                default:
0506:                    return "";
0507:                }
0508:            }
0509:
0510:            /**
0511:             * Get the NodeInfo object representing the parent of this node
0512:             */
0513:
0514:            public NodeInfo getParent() {
0515:                if (parent == null) {
0516:                    ParentNode p = node.getParent();
0517:                    if (p != null)
0518:                        parent = makeWrapper(p, docWrapper);
0519:                }
0520:                return parent;
0521:            }
0522:
0523:            /**
0524:             * Get the index position of this node among its siblings (starting from 0)
0525:             */
0526:
0527:            public int getSiblingPosition() {
0528:                if (index != -1)
0529:                    return index;
0530:                switch (nodeKind) {
0531:                case Type.ATTRIBUTE: {
0532:                    Attribute att = (Attribute) node;
0533:                    Element p = (Element) att.getParent();
0534:                    if (p == null)
0535:                        return 0;
0536:                    for (int i = p.getAttributeCount(); --i >= 0;) {
0537:                        if (p.getAttribute(i) == att) {
0538:                            index = i;
0539:                            return i;
0540:                        }
0541:                    }
0542:                    throw new IllegalStateException(
0543:                            "XOM node not linked to parent node");
0544:                }
0545:
0546:                default: {
0547:                    ParentNode p = node.getParent();
0548:                    int i = (p == null ? 0 : p.indexOf(node));
0549:                    if (i == -1)
0550:                        throw new IllegalStateException(
0551:                                "XOM node not linked to parent node");
0552:                    index = i;
0553:                    return index;
0554:                }
0555:                }
0556:            }
0557:
0558:            /**
0559:             * Return an iteration over the nodes reached by the given axis from this
0560:             * node
0561:             *
0562:             * @param axisNumber
0563:             *            the axis to be used
0564:             * @return a SequenceIterator that scans the nodes reached by the axis in
0565:             *         turn.
0566:             */
0567:
0568:            public AxisIterator iterateAxis(byte axisNumber) {
0569:                return iterateAxis(axisNumber, AnyNodeTest.getInstance());
0570:            }
0571:
0572:            /**
0573:             * Return an iteration over the nodes reached by the given axis from this
0574:             * node
0575:             *
0576:             * @param axisNumber
0577:             *            the axis to be used
0578:             * @param nodeTest
0579:             *            A pattern to be matched by the returned nodes
0580:             * @return a SequenceIterator that scans the nodes reached by the axis in
0581:             *         turn.
0582:             */
0583:
0584:            public AxisIterator iterateAxis(byte axisNumber, NodeTest nodeTest) {
0585:                // for clarifications, see the W3C specs or:
0586:                // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/xmrefaxes.asp
0587:                switch (axisNumber) {
0588:                case Axis.ANCESTOR:
0589:                    return new AncestorAxisIterator(this , false, nodeTest);
0590:
0591:                case Axis.ANCESTOR_OR_SELF:
0592:                    return new AncestorAxisIterator(this , true, nodeTest);
0593:
0594:                case Axis.ATTRIBUTE:
0595:                    if (nodeKind != Type.ELEMENT
0596:                            || ((Element) node).getAttributeCount() == 0) {
0597:                        return EmptyIterator.getInstance();
0598:                    } else {
0599:                        return new AttributeAxisIterator(this , nodeTest);
0600:                    }
0601:
0602:                case Axis.CHILD:
0603:                    if (hasChildNodes()) {
0604:                        return new ChildAxisIterator(this , true, true, nodeTest);
0605:                    } else {
0606:                        return EmptyIterator.getInstance();
0607:                    }
0608:
0609:                case Axis.DESCENDANT:
0610:                    if (hasChildNodes()) {
0611:                        return new DescendantAxisIterator(this , false, false,
0612:                                nodeTest);
0613:                    } else {
0614:                        return EmptyIterator.getInstance();
0615:                    }
0616:
0617:                case Axis.DESCENDANT_OR_SELF:
0618:                    if (hasChildNodes()) {
0619:                        return new DescendantAxisIterator(this , true, false,
0620:                                nodeTest);
0621:                    } else {
0622:                        return makeSingleIterator(this , nodeTest);
0623:                    }
0624:
0625:                case Axis.FOLLOWING:
0626:                    if (getParent() == null) {
0627:                        return EmptyIterator.getInstance();
0628:                    } else {
0629:                        return new DescendantAxisIterator(this , false, true,
0630:                                nodeTest);
0631:                    }
0632:
0633:                case Axis.FOLLOWING_SIBLING:
0634:                    if (nodeKind == Type.ATTRIBUTE || getParent() == null) {
0635:                        return EmptyIterator.getInstance();
0636:                    } else {
0637:                        return new ChildAxisIterator(this , false, true,
0638:                                nodeTest);
0639:                    }
0640:
0641:                case Axis.NAMESPACE:
0642:                    if (nodeKind == Type.ELEMENT) {
0643:                        return new NamespaceIterator(this , nodeTest);
0644:                    } else {
0645:                        return EmptyIterator.getInstance();
0646:                    }
0647:
0648:                case Axis.PARENT:
0649:                    if (getParent() == null) {
0650:                        return EmptyIterator.getInstance();
0651:                    } else {
0652:                        return makeSingleIterator(parent, nodeTest);
0653:                    }
0654:
0655:                case Axis.PRECEDING:
0656:                    return new PrecedingAxisIterator(this , false, nodeTest);
0657:                    //			return new Navigator.AxisFilter(
0658:                    //					new Navigator.PrecedingEnumeration(this, false), nodeTest);
0659:
0660:                case Axis.PRECEDING_SIBLING:
0661:                    if (nodeKind == Type.ATTRIBUTE || getParent() == null) {
0662:                        return EmptyIterator.getInstance();
0663:                    } else {
0664:                        return new ChildAxisIterator(this , false, false,
0665:                                nodeTest);
0666:                    }
0667:
0668:                case Axis.SELF:
0669:                    return makeSingleIterator(this , nodeTest);
0670:
0671:                case Axis.PRECEDING_OR_ANCESTOR:
0672:                    // This axis is used internally by saxon for the xsl:number implementation,
0673:                    // it returns the union of the preceding axis and the ancestor axis.
0674:                    return new PrecedingAxisIterator(this , true, nodeTest);
0675:                    //			return new Navigator.AxisFilter(new Navigator.PrecedingEnumeration(
0676:                    //					this, true), nodeTest);
0677:
0678:                default:
0679:                    throw new IllegalArgumentException("Unknown axis number "
0680:                            + axisNumber);
0681:                }
0682:            }
0683:
0684:            private static AxisIterator makeSingleIterator(NodeWrapper wrapper,
0685:                    NodeTest nodeTest) {
0686:                if (nodeTest == AnyNodeTest.getInstance()
0687:                        || nodeTest.matches(wrapper))
0688:                    return SingletonIterator.makeIterator(wrapper);
0689:                else
0690:                    return EmptyIterator.getInstance();
0691:            }
0692:
0693:            /**
0694:             * Get the value of a given attribute of this node
0695:             *
0696:             * @param fingerprint
0697:             *            The fingerprint of the attribute name
0698:             * @return the attribute value if it exists or null if not
0699:             */
0700:
0701:            public String getAttributeValue(int fingerprint) {
0702:                if (nodeKind == Type.ELEMENT) {
0703:                    NamePool pool = docWrapper.getNamePool();
0704:                    String localName = pool.getLocalName(fingerprint);
0705:                    String uri = pool.getURI(fingerprint);
0706:                    Attribute att = ((Element) node).getAttribute(localName,
0707:                            uri);
0708:                    if (att != null)
0709:                        return att.getValue();
0710:                }
0711:                return null;
0712:            }
0713:
0714:            /**
0715:             * Get the root node of the tree containing this node
0716:             *
0717:             * @return the NodeInfo representing the top-level ancestor of this node.
0718:             *     This will not necessarily be a document node
0719:             */
0720:
0721:            public NodeInfo getRoot() {
0722:                return docWrapper;
0723:            }
0724:
0725:            /**
0726:             * Get the root node, if it is a document node.
0727:             *
0728:             * @return the DocumentInfo representing the containing document.
0729:             */
0730:
0731:            public DocumentInfo getDocumentRoot() {
0732:                if (docWrapper.node instanceof  Document) {
0733:                    return docWrapper;
0734:                } else {
0735:                    return null;
0736:                }
0737:            }
0738:
0739:            /**
0740:             * Determine whether the node has any children. <br />
0741:             * Note: the result is equivalent to <br />
0742:             * getEnumeration(Axis.CHILD, AnyNodeTest.getInstance()).hasNext()
0743:             */
0744:
0745:            public boolean hasChildNodes() {
0746:                return node.getChildCount() > 0;
0747:            }
0748:
0749:            /**
0750:             * Get a character string that uniquely identifies this node. Note:
0751:             * a.isSameNode(b) if and only if generateId(a)==generateId(b)
0752:             *
0753:             * @return a string that uniquely identifies this node, across all documents
0754:             */
0755:
0756:            public String generateId() {
0757:                return Navigator.getSequentialKey(this );
0758:            }
0759:
0760:            /**
0761:             * Get the document number of the document containing this node. For a
0762:             * free-standing orphan node, just return the hashcode.
0763:             */
0764:
0765:            public int getDocumentNumber() {
0766:                return docWrapper.getDocumentNumber();
0767:            }
0768:
0769:            /**
0770:             * Copy this node to a given outputter (deep copy)
0771:             */
0772:
0773:            public void copy(Receiver out, int whichNamespaces,
0774:                    boolean copyAnnotations, int locationId)
0775:                    throws XPathException {
0776:                Navigator.copy(this , out, docWrapper.getNamePool(),
0777:                        whichNamespaces, copyAnnotations, locationId);
0778:            }
0779:
0780:            /**
0781:             * Output all namespace nodes associated with this element. Does nothing if
0782:             * the node is not an element.
0783:             *
0784:             * @param out
0785:             *            The relevant outputter
0786:             * @param includeAncestors
0787:             *            True if namespaces declared on ancestor elements must be
0788:             */
0789:
0790:            public void sendNamespaceDeclarations(Receiver out,
0791:                    boolean includeAncestors) throws XPathException {
0792:                Navigator
0793:                        .sendNamespaceDeclarations(this , out, includeAncestors);
0794:            }
0795:
0796:            /**
0797:             * Get all namespace undeclarations and undeclarations defined on this element.
0798:             *
0799:             * @param buffer If this is non-null, and the result array fits in this buffer, then the result
0800:             *               may overwrite the contents of this array, to avoid the cost of allocating a new array on the heap.
0801:             * @return An array of integers representing the namespace declarations and undeclarations present on
0802:             *         this element. For a node other than an element, return null. Otherwise, the returned array is a
0803:             *         sequence of namespace codes, whose meaning may be interpreted by reference to the name pool. The
0804:             *         top half word of each namespace code represents the prefix, the bottom half represents the URI.
0805:             *         If the bottom half is zero, then this is a namespace undeclaration rather than a declaration.
0806:             *         The XML namespace is never included in the list. If the supplied array is larger than required,
0807:             *         then the first unused entry will be set to -1.
0808:             *         <p/>
0809:             *         <p>For a node other than an element, the method returns null.</p>
0810:             */
0811:
0812:            public int[] getDeclaredNamespaces(int[] buffer) {
0813:                if (node instanceof  Element) {
0814:                    Element elem = (Element) node;
0815:                    int size = elem.getNamespaceDeclarationCount();
0816:                    if (size == 0) {
0817:                        return EMPTY_NAMESPACE_LIST;
0818:                    }
0819:                    int[] result = (size <= buffer.length ? buffer
0820:                            : new int[size]);
0821:                    NamePool pool = getNamePool();
0822:                    for (int i = 0; i < size; i++) {
0823:                        String prefix = elem.getNamespacePrefix(i);
0824:                        String uri = elem.getNamespaceURI(prefix);
0825:                        result[i] = pool.allocateNamespaceCode(prefix, uri);
0826:                    }
0827:                    if (size < result.length) {
0828:                        result[size] = -1;
0829:                    }
0830:                    return result;
0831:                } else {
0832:                    return null;
0833:                }
0834:            }
0835:
0836:            ///////////////////////////////////////////////////////////////////////////////
0837:            // Axis enumeration classes
0838:            ///////////////////////////////////////////////////////////////////////////////
0839:
0840:            /**
0841:             * Handles the ancestor axis in a rather direct manner.
0842:             */
0843:            private final class AncestorAxisIterator implements  AxisIterator {
0844:
0845:                private NodeWrapper start;
0846:                private boolean includeSelf;
0847:
0848:                private NodeInfo current;
0849:
0850:                private NodeTest nodeTest;
0851:                private int position;
0852:
0853:                public AncestorAxisIterator(NodeWrapper start,
0854:                        boolean includeSelf, NodeTest test) {
0855:                    // use lazy instead of eager materialization (performance)
0856:                    this .start = start;
0857:                    if (test == AnyNodeTest.getInstance())
0858:                        test = null;
0859:                    this .nodeTest = test;
0860:                    if (!includeSelf)
0861:                        this .current = start;
0862:                    this .includeSelf = includeSelf;
0863:                    this .position = 0;
0864:                }
0865:
0866:                public Item next() {
0867:                    NodeInfo curr;
0868:                    do { // until we find a match
0869:                        curr = advance();
0870:                    } while (curr != null && nodeTest != null
0871:                            && (!nodeTest.matches(curr)));
0872:
0873:                    if (curr != null)
0874:                        position++;
0875:                    current = curr;
0876:                    return curr;
0877:                }
0878:
0879:                private NodeInfo advance() {
0880:                    if (current == null)
0881:                        current = start;
0882:                    else
0883:                        current = current.getParent();
0884:
0885:                    return current;
0886:                }
0887:
0888:                public Item current() {
0889:                    return current;
0890:                }
0891:
0892:                public int position() {
0893:                    return position;
0894:                }
0895:
0896:                public SequenceIterator getAnother() {
0897:                    return new AncestorAxisIterator(start, includeSelf,
0898:                            nodeTest);
0899:                }
0900:
0901:                public int getProperties() {
0902:                    return 0;
0903:                }
0904:
0905:            } // end of class AncestorAxisIterator
0906:
0907:            /**
0908:             * Handles the attribute axis in a rather direct manner.
0909:             */
0910:            private final class AttributeAxisIterator implements  AxisIterator {
0911:
0912:                private NodeWrapper start;
0913:
0914:                private NodeInfo current;
0915:                private int cursor;
0916:
0917:                private NodeTest nodeTest;
0918:                private int position;
0919:
0920:                public AttributeAxisIterator(NodeWrapper start, NodeTest test) {
0921:                    // use lazy instead of eager materialization (performance)
0922:                    this .start = start;
0923:                    if (test == AnyNodeTest.getInstance())
0924:                        test = null;
0925:                    this .nodeTest = test;
0926:                    this .position = 0;
0927:                    this .cursor = 0;
0928:                }
0929:
0930:                public Item next() {
0931:                    NodeInfo curr;
0932:                    do { // until we find a match
0933:                        curr = advance();
0934:                    } while (curr != null && nodeTest != null
0935:                            && (!nodeTest.matches(curr)));
0936:
0937:                    if (curr != null)
0938:                        position++;
0939:                    current = curr;
0940:                    return curr;
0941:                }
0942:
0943:                private NodeInfo advance() {
0944:                    Element elem = (Element) start.node;
0945:                    if (cursor == elem.getAttributeCount())
0946:                        return null;
0947:                    NodeInfo curr = makeWrapper(elem.getAttribute(cursor),
0948:                            docWrapper, start, cursor);
0949:                    cursor++;
0950:                    return curr;
0951:                }
0952:
0953:                public Item current() {
0954:                    return current;
0955:                }
0956:
0957:                public int position() {
0958:                    return position;
0959:                }
0960:
0961:                public SequenceIterator getAnother() {
0962:                    return new AttributeAxisIterator(start, nodeTest);
0963:                }
0964:
0965:                public int getProperties() {
0966:                    return 0;
0967:                }
0968:
0969:            } // end of class AttributeAxisIterator
0970:
0971:            /**
0972:             * The class ChildAxisIterator handles not only the child axis, but also the
0973:             * following-sibling and preceding-sibling axes. It can also iterate the
0974:             * children of the start node in reverse order, something that is needed to
0975:             * support the preceding and preceding-or-ancestor axes (the latter being
0976:             * used by xsl:number)
0977:             */
0978:            private final class ChildAxisIterator implements  AxisIterator {
0979:
0980:                private NodeWrapper start;
0981:                private NodeWrapper commonParent;
0982:                private int ix;
0983:                private boolean downwards; // iterate children of start node (not siblings)
0984:                private boolean forwards; // iterate in document order (not reverse order)
0985:
0986:                private NodeInfo current;
0987:                private ParentNode par;
0988:                private int cursor;
0989:
0990:                private NodeTest nodeTest;
0991:                private int position;
0992:
0993:                private ChildAxisIterator(NodeWrapper start, boolean downwards,
0994:                        boolean forwards, NodeTest test) {
0995:                    this .start = start;
0996:                    this .downwards = downwards;
0997:                    this .forwards = forwards;
0998:
0999:                    if (test == AnyNodeTest.getInstance())
1000:                        test = null;
1001:                    this .nodeTest = test;
1002:                    this .position = 0;
1003:
1004:                    if (downwards)
1005:                        commonParent = start;
1006:                    else
1007:                        commonParent = (NodeWrapper) start.getParent();
1008:
1009:                    par = (ParentNode) commonParent.node;
1010:                    if (downwards) {
1011:                        ix = (forwards ? 0 : par.getChildCount());
1012:                    } else {
1013:                        // find the start node among the list of siblings
1014:                        //				ix = start.getSiblingPosition();
1015:                        ix = par.indexOf(start.node);
1016:                        if (forwards)
1017:                            ix++;
1018:                    }
1019:                    cursor = ix;
1020:                    if (!downwards && !forwards)
1021:                        ix--;
1022:                }
1023:
1024:                public Item next() {
1025:                    NodeInfo curr;
1026:                    do { // until we find a match
1027:                        curr = advance();
1028:                    } while (curr != null && nodeTest != null
1029:                            && (!nodeTest.matches(curr)));
1030:
1031:                    if (curr != null)
1032:                        position++;
1033:                    current = curr;
1034:                    return curr;
1035:                }
1036:
1037:                private NodeInfo advance() {
1038:                    Node nextChild;
1039:                    do {
1040:                        if (forwards) {
1041:                            if (cursor == par.getChildCount())
1042:                                return null;
1043:                            nextChild = par.getChild(cursor++);
1044:                        } else { // backwards
1045:                            if (cursor == 0)
1046:                                return null;
1047:                            nextChild = par.getChild(--cursor);
1048:                        }
1049:                    } while (nextChild instanceof  DocType);
1050:                    // DocType is not an XPath node; can occur for /child::node()
1051:
1052:                    NodeInfo curr = makeWrapper(nextChild, docWrapper,
1053:                            commonParent, ix);
1054:                    ix += (forwards ? 1 : -1);
1055:                    return curr;
1056:                }
1057:
1058:                public Item current() {
1059:                    return current;
1060:                }
1061:
1062:                public int position() {
1063:                    return position;
1064:                }
1065:
1066:                public SequenceIterator getAnother() {
1067:                    return new ChildAxisIterator(start, downwards, forwards,
1068:                            nodeTest);
1069:                }
1070:
1071:                public int getProperties() {
1072:                    return 0;
1073:                }
1074:            }
1075:
1076:            /**
1077:             * A bit of a misnomer; efficiently takes care of descendants,
1078:             * descentants-or-self as well as "following" axis.
1079:             * "includeSelf" must be false for the following axis.
1080:             * Uses simple and effective O(1) backtracking via indexOf().
1081:             */
1082:            private final class DescendantAxisIterator implements  AxisIterator {
1083:
1084:                private NodeWrapper start;
1085:                private boolean includeSelf;
1086:                private boolean following;
1087:
1088:                private Node anchor; // so we know where to stop the scan
1089:                private Node currNode;
1090:                private boolean moveToNextSibling;
1091:
1092:                private NodeInfo current;
1093:                private NodeTest nodeTest;
1094:                private int position;
1095:
1096:                private String testLocalName;
1097:                private String testURI;
1098:
1099:                public DescendantAxisIterator(NodeWrapper start,
1100:                        boolean includeSelf, boolean following, NodeTest test) {
1101:                    this .start = start;
1102:                    this .includeSelf = includeSelf;
1103:                    this .following = following;
1104:                    this .moveToNextSibling = following;
1105:
1106:                    if (!following)
1107:                        anchor = start.node;
1108:                    if (!includeSelf)
1109:                        currNode = start.node;
1110:
1111:                    if (test == AnyNodeTest.getInstance()) { // performance hack
1112:                        test = null; // mark as AnyNodeTest
1113:                    } else if (test instanceof  NameTest) {
1114:                        NameTest nt = (NameTest) test;
1115:                        if (nt.getPrimitiveType() == Type.ELEMENT) { // performance hack
1116:                            // mark as element name test
1117:                            NamePool pool = getNamePool();
1118:                            this .testLocalName = pool.getLocalName(nt
1119:                                    .getFingerprint());
1120:                            this .testURI = pool.getURI(nt.getFingerprint());
1121:                        }
1122:                    } else if (test instanceof  NodeKindTest) {
1123:                        if (test.getPrimitiveType() == Type.ELEMENT) { // performance hack
1124:                            // mark as element type test
1125:                            this .testLocalName = "";
1126:                            this .testURI = null;
1127:                        }
1128:                    }
1129:                    this .nodeTest = test;
1130:                    this .position = 0;
1131:                }
1132:
1133:                public Item next() {
1134:                    NodeInfo curr;
1135:                    do { // until we find a match
1136:                        curr = advance();
1137:                    } while (curr != null && nodeTest != null
1138:                            && (!nodeTest.matches(curr)));
1139:
1140:                    if (curr != null)
1141:                        position++;
1142:                    current = curr;
1143:                    return curr;
1144:                }
1145:
1146:                // might look expensive at first glance - but it's not
1147:                private NodeInfo advance() {
1148:                    if (currNode == null) { // if includeSelf
1149:                        currNode = start.node;
1150:                        return start;
1151:                    }
1152:
1153:                    int i;
1154:                    do {
1155:                        i = 0;
1156:                        Node p = currNode;
1157:
1158:                        if (p.getChildCount() == 0 || moveToNextSibling) { // move to next sibling
1159:
1160:                            moveToNextSibling = false; // do it just once
1161:                            while (true) {
1162:                                // if we've reached the root we're done scanning
1163:                                p = currNode.getParent();
1164:                                if (p == null)
1165:                                    return null;
1166:
1167:                                // Note: correct even if currNode is an attribute.
1168:                                // Performance is particularly good with the O(1) patch
1169:                                // for XOM's ParentNode.indexOf()
1170:                                i = currNode.getParent().indexOf(currNode) + 1;
1171:
1172:                                if (i < p.getChildCount()) {
1173:                                    break; // break out of while(true) loop; move to next sibling
1174:                                } else { // reached last sibling; move up
1175:                                    currNode = p;
1176:                                    // if we've come all the way back to the start anchor we're done
1177:                                    if (p == anchor)
1178:                                        return null;
1179:                                }
1180:                            }
1181:                        }
1182:                        currNode = p.getChild(i);
1183:                    } while (!conforms(currNode));
1184:
1185:                    // note the null here: makeNodeWrapper(parent, ...) is fast, so it
1186:                    // doesn't really matter that we don't keep a link to it.
1187:                    // In fact, it makes objects more short lived, easing pressure on
1188:                    // the VM allocator and collector for tenured heaps.
1189:                    return makeWrapper(currNode, docWrapper, null, i);
1190:                }
1191:
1192:                // avoids NodeWrapper allocation when there's clearly a mismatch (common case)
1193:                private boolean conforms(Node node) {
1194:                    if (this .testLocalName != null) { // element test?
1195:                        if (!(node instanceof  Element))
1196:                            return false;
1197:                        if (this .testURI == null)
1198:                            return true; // pure element type test
1199:
1200:                        // element name test
1201:                        Element elem = (Element) node;
1202:                        return this .testLocalName.equals(elem.getLocalName())
1203:                                && this .testURI.equals(elem.getNamespaceURI());
1204:                    } else { // DocType is not an XPath node; can occur for /descendants::node()
1205:                        return !(node instanceof  DocType);
1206:                    }
1207:                }
1208:
1209:                public Item current() {
1210:                    return current;
1211:                }
1212:
1213:                public int position() {
1214:                    return position;
1215:                }
1216:
1217:                public SequenceIterator getAnother() {
1218:                    return new DescendantAxisIterator(start, includeSelf,
1219:                            following, nodeTest);
1220:                }
1221:
1222:                public int getProperties() {
1223:                    return 0;
1224:                }
1225:            }
1226:
1227:            /**
1228:             * Efficiently takes care of preceding axis and Saxon internal preceding-or-ancestor axis.
1229:             * Uses simple and effective O(1) backtracking via indexOf().
1230:             * Implemented along similar lines as DescendantAxisIterator.
1231:             */
1232:            private final class PrecedingAxisIterator implements  AxisIterator {
1233:
1234:                private NodeWrapper start;
1235:                private boolean includeAncestors;
1236:
1237:                private Node currNode;
1238:                private ParentNode nextAncestor; // next ancestors to skip if !includeAncestors
1239:
1240:                private NodeInfo current;
1241:                private NodeTest nodeTest;
1242:                private int position;
1243:
1244:                private String testLocalName;
1245:                private String testURI;
1246:
1247:                public PrecedingAxisIterator(NodeWrapper start,
1248:                        boolean includeAncestors, NodeTest test) {
1249:                    this .start = start;
1250:                    this .includeAncestors = includeAncestors;
1251:                    this .currNode = start.node;
1252:                    if (includeAncestors)
1253:                        nextAncestor = null;
1254:                    else
1255:                        nextAncestor = start.node.getParent();
1256:
1257:                    if (test == AnyNodeTest.getInstance()) { // performance hack
1258:                        test = null; // mark as AnyNodeTest
1259:                    } else if (test instanceof  NameTest) {
1260:                        NameTest nt = (NameTest) test;
1261:                        if (nt.getPrimitiveType() == Type.ELEMENT) { // performance hack
1262:                            // mark as element name test
1263:                            NamePool pool = getNamePool();
1264:                            this .testLocalName = pool.getLocalName(nt
1265:                                    .getFingerprint());
1266:                            this .testURI = pool.getURI(nt.getFingerprint());
1267:                        }
1268:                    } else if (test instanceof  NodeKindTest) {
1269:                        if (test.getPrimitiveType() == Type.ELEMENT) { // performance hack
1270:                            // mark as element type test
1271:                            this .testLocalName = "";
1272:                            this .testURI = null;
1273:                        }
1274:                    }
1275:                    this .nodeTest = test;
1276:                    this .position = 0;
1277:                }
1278:
1279:                public Item next() {
1280:                    NodeInfo curr;
1281:                    do { // until we find a match
1282:                        curr = advance();
1283:                    } while (curr != null && nodeTest != null
1284:                            && (!nodeTest.matches(curr)));
1285:
1286:                    if (curr != null)
1287:                        position++;
1288:                    current = curr;
1289:                    return curr;
1290:                }
1291:
1292:                // might look expensive at first glance - but it's not
1293:                private NodeInfo advance() {
1294:                    int i;
1295:                    do {
1296:                        Node p = currNode;
1297:
1298:                        while (true) {
1299:                            // if we've reached the root we're done scanning
1300:                            //					System.out.println("p="+p);
1301:                            p = currNode.getParent();
1302:                            if (p == null)
1303:                                return null;
1304:
1305:                            // Note: correct even if currNode is an attribute.
1306:                            // Performance is particularly good with the O(1) patch
1307:                            // for XOM's ParentNode.indexOf()
1308:                            i = currNode.getParent().indexOf(currNode) - 1;
1309:
1310:                            if (i >= 0) { // move to next sibling's last descendant node
1311:                                p = p.getChild(i); // move to next sibling
1312:                                int j;
1313:                                while ((j = p.getChildCount() - 1) >= 0) { // move to last descendant node
1314:                                    p = p.getChild(j);
1315:                                    i = j;
1316:                                }
1317:                                break; // break out of while(true) loop
1318:                            } else { // there are no more siblings; move up
1319:                                // if !includeAncestors skip the ancestors of the start node
1320:                                // assert p != null
1321:                                if (p != nextAncestor)
1322:                                    break; // break out of while(true) loop
1323:
1324:                                nextAncestor = nextAncestor.getParent();
1325:                                currNode = p;
1326:                            }
1327:                        }
1328:                        currNode = p;
1329:
1330:                    } while (!conforms(currNode));
1331:
1332:                    // note the null here: makeNodeWrapper(parent, ...) is fast, so it
1333:                    // doesn't really matter that we don't keep a link to it.
1334:                    // In fact, it makes objects more short lived, easing pressure on
1335:                    // the VM allocator and collector for tenured heaps.
1336:                    return makeWrapper(currNode, docWrapper, null, i);
1337:                }
1338:
1339:                // avoids NodeWrapper allocation when there's clearly a mismatch (common case)
1340:                // same as for DescendantAxisIterator
1341:                private boolean conforms(Node node) {
1342:                    if (this .testLocalName != null) { // element test?
1343:                        if (!(node instanceof  Element))
1344:                            return false;
1345:                        if (this .testURI == null)
1346:                            return true; // pure element type test
1347:
1348:                        // element name test
1349:                        Element elem = (Element) node;
1350:                        return this .testLocalName.equals(elem.getLocalName())
1351:                                && this .testURI.equals(elem.getNamespaceURI());
1352:                    } else { // DocType is not an XPath node
1353:                        return !(node instanceof  DocType);
1354:                    }
1355:                }
1356:
1357:                public Item current() {
1358:                    return current;
1359:                }
1360:
1361:                public int position() {
1362:                    return position;
1363:                }
1364:
1365:                public SequenceIterator getAnother() {
1366:                    return new PrecedingAxisIterator(start, includeAncestors,
1367:                            nodeTest);
1368:                }
1369:
1370:                public int getProperties() {
1371:                    return 0;
1372:                }
1373:            }
1374:
1375:        }
1376:
1377:        //
1378:        // The contents of this file are subject to the Mozilla Public License Version
1379:        // 1.0 (the "License");
1380:        // you may not use this file except in compliance with the License. You may
1381:        // obtain a copy of the
1382:        // License at http://www.mozilla.org/MPL/
1383:        //
1384:        // Software distributed under the License is distributed on an "AS IS" basis,
1385:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
1386:        // See the License for the specific language governing rights and limitations
1387:        // under the License.
1388:        //
1389:        // The Original Code is: all this file.
1390:        //
1391:        // The Initial Developer of the Original Code is Michael Kay, with extensive
1392:        // rewriting by Wolfgang Hoschek
1393:        //
1394:        // Portions created by (your name) are Copyright (C) (your legal entity). All
1395:        // Rights Reserved.
1396:        //
1397:        // Contributor(s): none.
1398:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.