0001: /*
0002: * Copyright 1999-2004 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: DTMDefaultBaseTraversers.java,v 1.21 2005/01/24 00:34:35 mcnamara Exp $
0018: */
0019: package org.apache.xml.dtm.ref;
0020:
0021: import org.apache.xml.dtm.*;
0022:
0023: import javax.xml.transform.Source;
0024:
0025: import org.apache.xml.utils.XMLStringFactory;
0026:
0027: import org.apache.xml.res.XMLErrorResources;
0028: import org.apache.xml.res.XMLMessages;
0029: import org.apache.xalan.xsltc.dom.NodeCounter;
0030:
0031: /**
0032: * This class implements the traversers for DTMDefaultBase.
0033: *
0034: * PLEASE NOTE that the public interface for all traversers should be
0035: * in terms of DTM Node Handles... but they may use the internal node
0036: * identity indices within their logic, for efficiency's sake. Be very
0037: * careful to avoid confusing these when maintaining this code.
0038: * */
0039: public abstract class DTMDefaultBaseTraversers extends DTMDefaultBase {
0040:
0041: /**
0042: * Construct a DTMDefaultBaseTraversers object from a DOM node.
0043: *
0044: * @param mgr The DTMManager who owns this DTM.
0045: * @param source The object that is used to specify the construction source.
0046: * @param dtmIdentity The DTM identity ID for this DTM.
0047: * @param whiteSpaceFilter The white space filter for this DTM, which may
0048: * be null.
0049: * @param xstringfactory The factory to use for creating XMLStrings.
0050: * @param doIndexing true if the caller considers it worth it to use
0051: * indexing schemes.
0052: */
0053: public DTMDefaultBaseTraversers(DTMManager mgr, Source source,
0054: int dtmIdentity, DTMWSFilter whiteSpaceFilter,
0055: XMLStringFactory xstringfactory, boolean doIndexing) {
0056: super (mgr, source, dtmIdentity, whiteSpaceFilter,
0057: xstringfactory, doIndexing);
0058: }
0059:
0060: /**
0061: * Construct a DTMDefaultBaseTraversers object from a DOM node.
0062: *
0063: * @param mgr The DTMManager who owns this DTM.
0064: * @param source The object that is used to specify the construction source.
0065: * @param dtmIdentity The DTM identity ID for this DTM.
0066: * @param whiteSpaceFilter The white space filter for this DTM, which may
0067: * be null.
0068: * @param xstringfactory The factory to use for creating XMLStrings.
0069: * @param doIndexing true if the caller considers it worth it to use
0070: * indexing schemes.
0071: * @param blocksize The block size of the DTM.
0072: * @param usePrevsib true if we want to build the previous sibling node array.
0073: * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
0074: */
0075: public DTMDefaultBaseTraversers(DTMManager mgr, Source source,
0076: int dtmIdentity, DTMWSFilter whiteSpaceFilter,
0077: XMLStringFactory xstringfactory, boolean doIndexing,
0078: int blocksize, boolean usePrevsib, boolean newNameTable) {
0079: super (mgr, source, dtmIdentity, whiteSpaceFilter,
0080: xstringfactory, doIndexing, blocksize, usePrevsib,
0081: newNameTable);
0082: }
0083:
0084: /**
0085: * This returns a stateless "traverser", that can navigate
0086: * over an XPath axis, though perhaps not in document order.
0087: *
0088: * @param axis One of Axes.ANCESTORORSELF, etc.
0089: *
0090: * @return A DTMAxisTraverser, or null if the given axis isn't supported.
0091: */
0092: public DTMAxisTraverser getAxisTraverser(final int axis) {
0093:
0094: DTMAxisTraverser traverser;
0095:
0096: if (null == m_traversers) // Cache of stateless traversers for this DTM
0097: {
0098: m_traversers = new DTMAxisTraverser[Axis.getNamesLength()];
0099: traverser = null;
0100: } else {
0101: traverser = m_traversers[axis]; // Share/reuse existing traverser
0102:
0103: if (traverser != null)
0104: return traverser;
0105: }
0106:
0107: switch (axis) // Generate new traverser
0108: {
0109: case Axis.ANCESTOR:
0110: traverser = new AncestorTraverser();
0111: break;
0112: case Axis.ANCESTORORSELF:
0113: traverser = new AncestorOrSelfTraverser();
0114: break;
0115: case Axis.ATTRIBUTE:
0116: traverser = new AttributeTraverser();
0117: break;
0118: case Axis.CHILD:
0119: traverser = new ChildTraverser();
0120: break;
0121: case Axis.DESCENDANT:
0122: traverser = new DescendantTraverser();
0123: break;
0124: case Axis.DESCENDANTORSELF:
0125: traverser = new DescendantOrSelfTraverser();
0126: break;
0127: case Axis.FOLLOWING:
0128: traverser = new FollowingTraverser();
0129: break;
0130: case Axis.FOLLOWINGSIBLING:
0131: traverser = new FollowingSiblingTraverser();
0132: break;
0133: case Axis.NAMESPACE:
0134: traverser = new NamespaceTraverser();
0135: break;
0136: case Axis.NAMESPACEDECLS:
0137: traverser = new NamespaceDeclsTraverser();
0138: break;
0139: case Axis.PARENT:
0140: traverser = new ParentTraverser();
0141: break;
0142: case Axis.PRECEDING:
0143: traverser = new PrecedingTraverser();
0144: break;
0145: case Axis.PRECEDINGSIBLING:
0146: traverser = new PrecedingSiblingTraverser();
0147: break;
0148: case Axis.SELF:
0149: traverser = new SelfTraverser();
0150: break;
0151: case Axis.ALL:
0152: traverser = new AllFromRootTraverser();
0153: break;
0154: case Axis.ALLFROMNODE:
0155: traverser = new AllFromNodeTraverser();
0156: break;
0157: case Axis.PRECEDINGANDANCESTOR:
0158: traverser = new PrecedingAndAncestorTraverser();
0159: break;
0160: case Axis.DESCENDANTSFROMROOT:
0161: traverser = new DescendantFromRootTraverser();
0162: break;
0163: case Axis.DESCENDANTSORSELFFROMROOT:
0164: traverser = new DescendantOrSelfFromRootTraverser();
0165: break;
0166: case Axis.ROOT:
0167: traverser = new RootTraverser();
0168: break;
0169: case Axis.FILTEREDLIST:
0170: return null; // Don't want to throw an exception for this one.
0171: default:
0172: throw new DTMException(XMLMessages.createXMLMessage(
0173: XMLErrorResources.ER_UNKNOWN_AXIS_TYPE,
0174: new Object[] { Integer.toString(axis) })); //"Unknown axis traversal type: "+axis);
0175: }
0176:
0177: if (null == traverser)
0178: throw new DTMException(XMLMessages.createXMLMessage(
0179: XMLErrorResources.ER_AXIS_TRAVERSER_NOT_SUPPORTED,
0180: new Object[] { Axis.getNames(axis) }));
0181: // "Axis traverser not supported: "
0182: // + Axis.names[axis]);
0183:
0184: m_traversers[axis] = traverser;
0185:
0186: return traverser;
0187: }
0188:
0189: /**
0190: * Implements traversal of the Ancestor access, in reverse document order.
0191: */
0192: private class AncestorTraverser extends DTMAxisTraverser {
0193:
0194: /**
0195: * Traverse to the next node after the current node.
0196: *
0197: * @param context The context node if this iteration.
0198: * @param current The current node of the iteration.
0199: *
0200: * @return the next node in the iteration, or DTM.NULL.
0201: */
0202: public int next(int context, int current) {
0203: return getParent(current);
0204: }
0205:
0206: /**
0207: * Traverse to the next node after the current node that is matched
0208: * by the expanded type ID.
0209: *
0210: * @param context The context node of this iteration.
0211: * @param current The current node of the iteration.
0212: * @param expandedTypeID The expanded type ID that must match.
0213: *
0214: * @return the next node in the iteration, or DTM.NULL.
0215: */
0216: public int next(int context, int current, int expandedTypeID) {
0217: // Process using identities
0218: current = makeNodeIdentity(current);
0219:
0220: while (DTM.NULL != (current = m_parent.elementAt(current))) {
0221: if (m_exptype.elementAt(current) == expandedTypeID)
0222: return makeNodeHandle(current);
0223: }
0224:
0225: return NULL;
0226: }
0227: }
0228:
0229: /**
0230: * Implements traversal of the Ancestor access, in reverse document order.
0231: */
0232: private class AncestorOrSelfTraverser extends AncestorTraverser {
0233:
0234: /**
0235: * By the nature of the stateless traversal, the context node can not be
0236: * returned or the iteration will go into an infinate loop. To see if
0237: * the self node should be processed, use this function.
0238: *
0239: * @param context The context node of this traversal.
0240: *
0241: * @return the first node in the traversal.
0242: */
0243: public int first(int context) {
0244: return context;
0245: }
0246:
0247: /**
0248: * By the nature of the stateless traversal, the context node can not be
0249: * returned or the iteration will go into an infinate loop. To see if
0250: * the self node should be processed, use this function. If the context
0251: * node does not match the expanded type ID, this function will return
0252: * false.
0253: *
0254: * @param context The context node of this traversal.
0255: * @param expandedTypeID The expanded type ID that must match.
0256: *
0257: * @return the first node in the traversal.
0258: */
0259: public int first(int context, int expandedTypeID) {
0260: return (getExpandedTypeID(context) == expandedTypeID) ? context
0261: : next(context, context, expandedTypeID);
0262: }
0263: }
0264:
0265: /**
0266: * Implements traversal of the Attribute access
0267: */
0268: private class AttributeTraverser extends DTMAxisTraverser {
0269:
0270: /**
0271: * Traverse to the next node after the current node.
0272: *
0273: * @param context The context node of this iteration.
0274: * @param current The current node of the iteration.
0275: *
0276: * @return the next node in the iteration, or DTM.NULL.
0277: */
0278: public int next(int context, int current) {
0279: return (context == current) ? getFirstAttribute(context)
0280: : getNextAttribute(current);
0281: }
0282:
0283: /**
0284: * Traverse to the next node after the current node that is matched
0285: * by the expanded type ID.
0286: *
0287: * @param context The context node of this iteration.
0288: * @param current The current node of the iteration.
0289: * @param expandedTypeID The expanded type ID that must match.
0290: *
0291: * @return the next node in the iteration, or DTM.NULL.
0292: */
0293: public int next(int context, int current, int expandedTypeID) {
0294:
0295: current = (context == current) ? getFirstAttribute(context)
0296: : getNextAttribute(current);
0297:
0298: do {
0299: if (getExpandedTypeID(current) == expandedTypeID)
0300: return current;
0301: } while (DTM.NULL != (current = getNextAttribute(current)));
0302:
0303: return NULL;
0304: }
0305: }
0306:
0307: /**
0308: * Implements traversal of the Ancestor access, in reverse document order.
0309: */
0310: private class ChildTraverser extends DTMAxisTraverser {
0311:
0312: /**
0313: * Get the next indexed node that matches the expanded type ID. Before
0314: * calling this function, one should first call
0315: * {@link #isIndexed(int) isIndexed} to make sure that the index can
0316: * contain nodes that match the given expanded type ID.
0317: *
0318: * @param axisRoot The root identity of the axis.
0319: * @param nextPotential The node found must match or occur after this node.
0320: * @param expandedTypeID The expanded type ID for the request.
0321: *
0322: * @return The node ID or NULL if not found.
0323: */
0324: protected int getNextIndexed(int axisRoot, int nextPotential,
0325: int expandedTypeID) {
0326:
0327: int nsIndex = m_expandedNameTable
0328: .getNamespaceID(expandedTypeID);
0329: int lnIndex = m_expandedNameTable
0330: .getLocalNameID(expandedTypeID);
0331:
0332: for (;;) {
0333: int nextID = findElementFromIndex(nsIndex, lnIndex,
0334: nextPotential);
0335:
0336: if (NOTPROCESSED != nextID) {
0337: int parentID = m_parent.elementAt(nextID);
0338:
0339: // Is it a child?
0340: if (parentID == axisRoot)
0341: return nextID;
0342:
0343: // If the parent occured before the subtree root, then
0344: // we know it is past the child axis.
0345: if (parentID < axisRoot)
0346: return NULL;
0347:
0348: // Otherwise, it could be a descendant below the subtree root
0349: // children, or it could be after the subtree root. So we have
0350: // to climb up until the parent is less than the subtree root, in
0351: // which case we return NULL, or until it is equal to the subtree
0352: // root, in which case we continue to look.
0353: do {
0354: parentID = m_parent.elementAt(parentID);
0355: if (parentID < axisRoot)
0356: return NULL;
0357: } while (parentID > axisRoot);
0358:
0359: // System.out.println("Found node via index: "+first);
0360: nextPotential = nextID + 1;
0361: continue;
0362: }
0363:
0364: nextNode();
0365:
0366: if (!(m_nextsib.elementAt(axisRoot) == NOTPROCESSED))
0367: break;
0368: }
0369:
0370: return DTM.NULL;
0371: }
0372:
0373: /**
0374: * By the nature of the stateless traversal, the context node can not be
0375: * returned or the iteration will go into an infinate loop. So to traverse
0376: * an axis, the first function must be used to get the first node.
0377: *
0378: * <p>This method needs to be overloaded only by those axis that process
0379: * the self node. <\p>
0380: *
0381: * @param context The context node of this traversal. This is the point
0382: * that the traversal starts from.
0383: * @return the first node in the traversal.
0384: */
0385: public int first(int context) {
0386: return getFirstChild(context);
0387: }
0388:
0389: /**
0390: * By the nature of the stateless traversal, the context node can not be
0391: * returned or the iteration will go into an infinate loop. So to traverse
0392: * an axis, the first function must be used to get the first node.
0393: *
0394: * <p>This method needs to be overloaded only by those axis that process
0395: * the self node. <\p>
0396: *
0397: * @param context The context node of this traversal. This is the point
0398: * of origin for the traversal -- its "root node" or starting point.
0399: * @param expandedTypeID The expanded type ID that must match.
0400: *
0401: * @return the first node in the traversal.
0402: */
0403: public int first(int context, int expandedTypeID) {
0404: if (true) {
0405: int identity = makeNodeIdentity(context);
0406:
0407: int firstMatch = getNextIndexed(identity,
0408: _firstch(identity), expandedTypeID);
0409:
0410: return makeNodeHandle(firstMatch);
0411: } else {
0412: // %REVIEW% Dead code. Eliminate?
0413: for (int current = _firstch(makeNodeIdentity(context)); DTM.NULL != current; current = _nextsib(current)) {
0414: if (m_exptype.elementAt(current) == expandedTypeID)
0415: return makeNodeHandle(current);
0416: }
0417: return NULL;
0418: }
0419: }
0420:
0421: /**
0422: * Traverse to the next node after the current node.
0423: *
0424: * @param context The context node of this iteration.
0425: * @param current The current node of the iteration.
0426: *
0427: * @return the next node in the iteration, or DTM.NULL.
0428: */
0429: public int next(int context, int current) {
0430: return getNextSibling(current);
0431: }
0432:
0433: /**
0434: * Traverse to the next node after the current node that is matched
0435: * by the expanded type ID.
0436: *
0437: * @param context The context node of this iteration.
0438: * @param current The current node of the iteration.
0439: * @param expandedTypeID The expanded type ID that must match.
0440: *
0441: * @return the next node in the iteration, or DTM.NULL.
0442: */
0443: public int next(int context, int current, int expandedTypeID) {
0444: // Process in Identifier space
0445: for (current = _nextsib(makeNodeIdentity(current)); DTM.NULL != current; current = _nextsib(current)) {
0446: if (m_exptype.elementAt(current) == expandedTypeID)
0447: return makeNodeHandle(current);
0448: }
0449:
0450: return NULL;
0451: }
0452: }
0453:
0454: /**
0455: * Super class for derived classes that want a convenient way to access
0456: * the indexing mechanism.
0457: */
0458: private abstract class IndexedDTMAxisTraverser extends
0459: DTMAxisTraverser {
0460:
0461: /**
0462: * Tell if the indexing is on and the given expanded type ID matches
0463: * what is in the indexes. Derived classes should call this before
0464: * calling {@link #getNextIndexed(int, int, int) getNextIndexed} method.
0465: *
0466: * @param expandedTypeID The expanded type ID being requested.
0467: *
0468: * @return true if it is OK to call the
0469: * {@link #getNextIndexed(int, int, int) getNextIndexed} method.
0470: */
0471: protected final boolean isIndexed(int expandedTypeID) {
0472: return (m_indexing && ExpandedNameTable.ELEMENT == m_expandedNameTable
0473: .getType(expandedTypeID));
0474: }
0475:
0476: /**
0477: * Tell if a node is outside the axis being traversed. This method must be
0478: * implemented by derived classes, and must be robust enough to handle any
0479: * node that occurs after the axis root.
0480: *
0481: * @param axisRoot The root identity of the axis.
0482: * @param identity The node in question.
0483: *
0484: * @return true if the given node falls outside the axis being traversed.
0485: */
0486: protected abstract boolean isAfterAxis(int axisRoot,
0487: int identity);
0488:
0489: /**
0490: * Tell if the axis has been fully processed to tell if a the wait for
0491: * an arriving node should terminate. This method must be implemented
0492: * be a derived class.
0493: *
0494: * @param axisRoot The root identity of the axis.
0495: *
0496: * @return true if the axis has been fully processed.
0497: */
0498: protected abstract boolean axisHasBeenProcessed(int axisRoot);
0499:
0500: /**
0501: * Get the next indexed node that matches the expanded type ID. Before
0502: * calling this function, one should first call
0503: * {@link #isIndexed(int) isIndexed} to make sure that the index can
0504: * contain nodes that match the given expanded type ID.
0505: *
0506: * @param axisRoot The root identity of the axis.
0507: * @param nextPotential The node found must match or occur after this node.
0508: * @param expandedTypeID The expanded type ID for the request.
0509: *
0510: * @return The node ID or NULL if not found.
0511: */
0512: protected int getNextIndexed(int axisRoot, int nextPotential,
0513: int expandedTypeID) {
0514:
0515: int nsIndex = m_expandedNameTable
0516: .getNamespaceID(expandedTypeID);
0517: int lnIndex = m_expandedNameTable
0518: .getLocalNameID(expandedTypeID);
0519:
0520: while (true) {
0521: int next = findElementFromIndex(nsIndex, lnIndex,
0522: nextPotential);
0523:
0524: if (NOTPROCESSED != next) {
0525: if (isAfterAxis(axisRoot, next))
0526: return NULL;
0527:
0528: // System.out.println("Found node via index: "+first);
0529: return next;
0530: } else if (axisHasBeenProcessed(axisRoot))
0531: break;
0532:
0533: nextNode();
0534: }
0535:
0536: return DTM.NULL;
0537: }
0538: }
0539:
0540: /**
0541: * Implements traversal of the Ancestor access, in reverse document order.
0542: */
0543: private class DescendantTraverser extends IndexedDTMAxisTraverser {
0544: /**
0545: * Get the first potential identity that can be returned. This should
0546: * be overridded by classes that need to return the self node.
0547: *
0548: * @param identity The node identity of the root context of the traversal.
0549: *
0550: * @return The first potential node that can be in the traversal.
0551: */
0552: protected int getFirstPotential(int identity) {
0553: return identity + 1;
0554: }
0555:
0556: /**
0557: * Tell if the axis has been fully processed to tell if a the wait for
0558: * an arriving node should terminate.
0559: *
0560: * @param axisRoot The root identity of the axis.
0561: *
0562: * @return true if the axis has been fully processed.
0563: */
0564: protected boolean axisHasBeenProcessed(int axisRoot) {
0565: return !(m_nextsib.elementAt(axisRoot) == NOTPROCESSED);
0566: }
0567:
0568: /**
0569: * Get the subtree root identity from the handle that was passed in by
0570: * the caller. Derived classes may override this to change the root
0571: * context of the traversal.
0572: *
0573: * @param handle handle to the root context.
0574: * @return identity of the root of the subtree.
0575: */
0576: protected int getSubtreeRoot(int handle) {
0577: return makeNodeIdentity(handle);
0578: }
0579:
0580: /**
0581: * Tell if this node identity is a descendant. Assumes that
0582: * the node info for the element has already been obtained.
0583: *
0584: * %REVIEW% This is really parentFollowsRootInDocumentOrder ...
0585: * which fails if the parent starts after the root ends.
0586: * May be sufficient for this class's logic, but misleadingly named!
0587: *
0588: * @param subtreeRootIdentity The root context of the subtree in question.
0589: * @param identity The index number of the node in question.
0590: * @return true if the index is a descendant of _startNode.
0591: */
0592: protected boolean isDescendant(int subtreeRootIdentity,
0593: int identity) {
0594: return _parent(identity) >= subtreeRootIdentity;
0595: }
0596:
0597: /**
0598: * Tell if a node is outside the axis being traversed. This method must be
0599: * implemented by derived classes, and must be robust enough to handle any
0600: * node that occurs after the axis root.
0601: *
0602: * @param axisRoot The root identity of the axis.
0603: * @param identity The node in question.
0604: *
0605: * @return true if the given node falls outside the axis being traversed.
0606: */
0607: protected boolean isAfterAxis(int axisRoot, int identity) {
0608: // %REVIEW% Is there *any* cheaper way to do this?
0609: // Yes. In ID space, compare to axisRoot's successor
0610: // (next-sib or ancestor's-next-sib). Probably shallower search.
0611: do {
0612: if (identity == axisRoot)
0613: return false;
0614: identity = m_parent.elementAt(identity);
0615: } while (identity >= axisRoot);
0616:
0617: return true;
0618: }
0619:
0620: /**
0621: * By the nature of the stateless traversal, the context node can not be
0622: * returned or the iteration will go into an infinate loop. So to traverse
0623: * an axis, the first function must be used to get the first node.
0624: *
0625: * <p>This method needs to be overloaded only by those axis that process
0626: * the self node. <\p>
0627: *
0628: * @param context The context node of this traversal. This is the point
0629: * of origin for the traversal -- its "root node" or starting point.
0630: * @param expandedTypeID The expanded type ID that must match.
0631: *
0632: * @return the first node in the traversal.
0633: */
0634: public int first(int context, int expandedTypeID) {
0635:
0636: if (isIndexed(expandedTypeID)) {
0637: int identity = getSubtreeRoot(context);
0638: int firstPotential = getFirstPotential(identity);
0639:
0640: return makeNodeHandle(getNextIndexed(identity,
0641: firstPotential, expandedTypeID));
0642: }
0643:
0644: return next(context, context, expandedTypeID);
0645: }
0646:
0647: /**
0648: * Traverse to the next node after the current node.
0649: *
0650: * @param context The context node of this iteration.
0651: * @param current The current node of the iteration.
0652: *
0653: * @return the next node in the iteration, or DTM.NULL.
0654: */
0655: public int next(int context, int current) {
0656:
0657: int subtreeRootIdent = getSubtreeRoot(context);
0658:
0659: for (current = makeNodeIdentity(current) + 1;; current++) {
0660: int type = _type(current); // may call nextNode()
0661:
0662: if (!isDescendant(subtreeRootIdent, current))
0663: return NULL;
0664:
0665: if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
0666: continue;
0667:
0668: return makeNodeHandle(current); // make handle.
0669: }
0670: }
0671:
0672: /**
0673: * Traverse to the next node after the current node that is matched
0674: * by the expanded type ID.
0675: *
0676: * @param context The context node of this iteration.
0677: * @param current The current node of the iteration.
0678: * @param expandedTypeID The expanded type ID that must match.
0679: *
0680: * @return the next node in the iteration, or DTM.NULL.
0681: */
0682: public int next(int context, int current, int expandedTypeID) {
0683:
0684: int subtreeRootIdent = getSubtreeRoot(context);
0685:
0686: current = makeNodeIdentity(current) + 1;
0687:
0688: if (isIndexed(expandedTypeID)) {
0689: return makeNodeHandle(getNextIndexed(subtreeRootIdent,
0690: current, expandedTypeID));
0691: }
0692:
0693: for (;; current++) {
0694: int exptype = _exptype(current); // may call nextNode()
0695:
0696: if (!isDescendant(subtreeRootIdent, current))
0697: return NULL;
0698:
0699: if (exptype != expandedTypeID)
0700: continue;
0701:
0702: return makeNodeHandle(current); // make handle.
0703: }
0704: }
0705: }
0706:
0707: /**
0708: * Implements traversal of the Ancestor access, in reverse document order.
0709: */
0710: private class DescendantOrSelfTraverser extends DescendantTraverser {
0711:
0712: /**
0713: * Get the first potential identity that can be returned, which is the
0714: * axis context, in this case.
0715: *
0716: * @param identity The node identity of the root context of the traversal.
0717: *
0718: * @return The axis context.
0719: */
0720: protected int getFirstPotential(int identity) {
0721: return identity;
0722: }
0723:
0724: /**
0725: * By the nature of the stateless traversal, the context node can not be
0726: * returned or the iteration will go into an infinate loop. To see if
0727: * the self node should be processed, use this function.
0728: *
0729: * @param context The context node of this traversal.
0730: *
0731: * @return the first node in the traversal.
0732: */
0733: public int first(int context) {
0734: return context;
0735: }
0736: }
0737:
0738: /**
0739: * Implements traversal of the entire subtree, including the root node.
0740: */
0741: private class AllFromNodeTraverser extends
0742: DescendantOrSelfTraverser {
0743:
0744: /**
0745: * Traverse to the next node after the current node.
0746: *
0747: * @param context The context node of this iteration.
0748: * @param current The current node of the iteration.
0749: *
0750: * @return the next node in the iteration, or DTM.NULL.
0751: */
0752: public int next(int context, int current) {
0753:
0754: int subtreeRootIdent = makeNodeIdentity(context);
0755:
0756: for (current = makeNodeIdentity(current) + 1;; current++) {
0757: // Trickological code: _exptype() has the side-effect of
0758: // running nextNode until the specified node has been loaded,
0759: // and thus can be used to ensure that incremental construction of
0760: // the DTM has gotten this far. Using it just for that side-effect
0761: // is quite a kluge...
0762: _exptype(current); // make sure it's here.
0763:
0764: if (!isDescendant(subtreeRootIdent, current))
0765: return NULL;
0766:
0767: return makeNodeHandle(current); // make handle.
0768: }
0769: }
0770: }
0771:
0772: /**
0773: * Implements traversal of the following access, in document order.
0774: */
0775: private class FollowingTraverser extends DescendantTraverser {
0776:
0777: /**
0778: * Get the first of the following.
0779: *
0780: * @param context The context node of this traversal. This is the point
0781: * that the traversal starts from.
0782: * @return the first node in the traversal.
0783: */
0784: public int first(int context) {
0785: // Compute in ID space
0786: context = makeNodeIdentity(context);
0787:
0788: int first;
0789: int type = _type(context);
0790:
0791: if ((DTM.ATTRIBUTE_NODE == type)
0792: || (DTM.NAMESPACE_NODE == type)) {
0793: context = _parent(context);
0794: first = _firstch(context);
0795:
0796: if (NULL != first)
0797: return makeNodeHandle(first);
0798: }
0799:
0800: do {
0801: first = _nextsib(context);
0802:
0803: if (NULL == first)
0804: context = _parent(context);
0805: } while (NULL == first && NULL != context);
0806:
0807: return makeNodeHandle(first);
0808: }
0809:
0810: /**
0811: * Get the first of the following.
0812: *
0813: * @param context The context node of this traversal. This is the point
0814: * of origin for the traversal -- its "root node" or starting point.
0815: * @param expandedTypeID The expanded type ID that must match.
0816: *
0817: * @return the first node in the traversal.
0818: */
0819: public int first(int context, int expandedTypeID) {
0820: // %REVIEW% This looks like it might want shift into identity space
0821: // to avoid repeated conversion in the individual functions
0822: int first;
0823: int type = getNodeType(context);
0824:
0825: if ((DTM.ATTRIBUTE_NODE == type)
0826: || (DTM.NAMESPACE_NODE == type)) {
0827: context = getParent(context);
0828: first = getFirstChild(context);
0829:
0830: if (NULL != first) {
0831: if (getExpandedTypeID(first) == expandedTypeID)
0832: return first;
0833: else
0834: return next(context, first, expandedTypeID);
0835: }
0836: }
0837:
0838: do {
0839: first = getNextSibling(context);
0840:
0841: if (NULL == first)
0842: context = getParent(context);
0843: else {
0844: if (getExpandedTypeID(first) == expandedTypeID)
0845: return first;
0846: else
0847: return next(context, first, expandedTypeID);
0848: }
0849: } while (NULL == first && NULL != context);
0850:
0851: return first;
0852: }
0853:
0854: /**
0855: * Traverse to the next node after the current node.
0856: *
0857: * @param context The context node of this iteration.
0858: * @param current The current node of the iteration.
0859: *
0860: * @return the next node in the iteration, or DTM.NULL.
0861: */
0862: public int next(int context, int current) {
0863: // Compute in identity space
0864: current = makeNodeIdentity(current);
0865:
0866: while (true) {
0867: current++; // Only works on IDs, not handles.
0868:
0869: // %REVIEW% Are we using handles or indexes?
0870: int type = _type(current); // may call nextNode()
0871:
0872: if (NULL == type)
0873: return NULL;
0874:
0875: if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
0876: continue;
0877:
0878: return makeNodeHandle(current); // make handle.
0879: }
0880: }
0881:
0882: /**
0883: * Traverse to the next node after the current node that is matched
0884: * by the expanded type ID.
0885: *
0886: * @param context The context node of this iteration.
0887: * @param current The current node of the iteration.
0888: * @param expandedTypeID The expanded type ID that must match.
0889: *
0890: * @return the next node in the iteration, or DTM.NULL.
0891: */
0892: public int next(int context, int current, int expandedTypeID) {
0893: // Compute in ID space
0894: current = makeNodeIdentity(current);
0895:
0896: while (true) {
0897: current++;
0898:
0899: int etype = _exptype(current); // may call nextNode()
0900:
0901: if (NULL == etype)
0902: return NULL;
0903:
0904: if (etype != expandedTypeID)
0905: continue;
0906:
0907: return makeNodeHandle(current); // make handle.
0908: }
0909: }
0910: }
0911:
0912: /**
0913: * Implements traversal of the Ancestor access, in reverse document order.
0914: */
0915: private class FollowingSiblingTraverser extends DTMAxisTraverser {
0916:
0917: /**
0918: * Traverse to the next node after the current node.
0919: *
0920: * @param context The context node of this iteration.
0921: * @param current The current node of the iteration.
0922: *
0923: * @return the next node in the iteration, or DTM.NULL.
0924: */
0925: public int next(int context, int current) {
0926: return getNextSibling(current);
0927: }
0928:
0929: /**
0930: * Traverse to the next node after the current node that is matched
0931: * by the expanded type ID.
0932: *
0933: * @param context The context node of this iteration.
0934: * @param current The current node of the iteration.
0935: * @param expandedTypeID The expanded type ID that must match.
0936: *
0937: * @return the next node in the iteration, or DTM.NULL.
0938: */
0939: public int next(int context, int current, int expandedTypeID) {
0940:
0941: while (DTM.NULL != (current = getNextSibling(current))) {
0942: if (getExpandedTypeID(current) == expandedTypeID)
0943: return current;
0944: }
0945:
0946: return NULL;
0947: }
0948: }
0949:
0950: /**
0951: * Implements traversal of the Ancestor access, in reverse document order.
0952: */
0953: private class NamespaceDeclsTraverser extends DTMAxisTraverser {
0954:
0955: /**
0956: * Traverse to the next node after the current node.
0957: *
0958: * @param context The context node of this iteration.
0959: * @param current The current node of the iteration.
0960: *
0961: * @return the next node in the iteration, or DTM.NULL.
0962: */
0963: public int next(int context, int current) {
0964:
0965: return (context == current) ? getFirstNamespaceNode(
0966: context, false) : getNextNamespaceNode(context,
0967: current, false);
0968: }
0969:
0970: /**
0971: * Traverse to the next node after the current node that is matched
0972: * by the expanded type ID.
0973: *
0974: * @param context The context node of this iteration.
0975: * @param current The current node of the iteration.
0976: * @param expandedTypeID The expanded type ID that must match.
0977: *
0978: * @return the next node in the iteration, or DTM.NULL.
0979: */
0980: public int next(int context, int current, int expandedTypeID) {
0981:
0982: current = (context == current) ? getFirstNamespaceNode(
0983: context, false) : getNextNamespaceNode(context,
0984: current, false);
0985:
0986: do {
0987: if (getExpandedTypeID(current) == expandedTypeID)
0988: return current;
0989: } while (DTM.NULL != (current = getNextNamespaceNode(
0990: context, current, false)));
0991:
0992: return NULL;
0993: }
0994: }
0995:
0996: /**
0997: * Implements traversal of the Ancestor access, in reverse document order.
0998: */
0999: private class NamespaceTraverser extends DTMAxisTraverser {
1000:
1001: /**
1002: * Traverse to the next node after the current node.
1003: *
1004: * @param context The context node of this iteration.
1005: * @param current The current node of the iteration.
1006: *
1007: * @return the next node in the iteration, or DTM.NULL.
1008: */
1009: public int next(int context, int current) {
1010:
1011: return (context == current) ? getFirstNamespaceNode(
1012: context, true) : getNextNamespaceNode(context,
1013: current, true);
1014: }
1015:
1016: /**
1017: * Traverse to the next node after the current node that is matched
1018: * by the expanded type ID.
1019: *
1020: * @param context The context node of this iteration.
1021: * @param current The current node of the iteration.
1022: * @param expandedTypeID The expanded type ID that must match.
1023: *
1024: * @return the next node in the iteration, or DTM.NULL.
1025: */
1026: public int next(int context, int current, int expandedTypeID) {
1027:
1028: current = (context == current) ? getFirstNamespaceNode(
1029: context, true) : getNextNamespaceNode(context,
1030: current, true);
1031:
1032: do {
1033: if (getExpandedTypeID(current) == expandedTypeID)
1034: return current;
1035: } while (DTM.NULL != (current = getNextNamespaceNode(
1036: context, current, true)));
1037:
1038: return NULL;
1039: }
1040: }
1041:
1042: /**
1043: * Implements traversal of the Ancestor access, in reverse document order.
1044: */
1045: private class ParentTraverser extends DTMAxisTraverser {
1046: /**
1047: * By the nature of the stateless traversal, the context node can not be
1048: * returned or the iteration will go into an infinate loop. So to traverse
1049: * an axis, the first function must be used to get the first node.
1050: *
1051: * <p>This method needs to be overloaded only by those axis that process
1052: * the self node. <\p>
1053: *
1054: * @param context The context node of this traversal. This is the point
1055: * that the traversal starts from.
1056: * @return the first node in the traversal.
1057: */
1058: public int first(int context) {
1059: return getParent(context);
1060: }
1061:
1062: /**
1063: * By the nature of the stateless traversal, the context node can not be
1064: * returned or the iteration will go into an infinate loop. So to traverse
1065: * an axis, the first function must be used to get the first node.
1066: *
1067: * <p>This method needs to be overloaded only by those axis that process
1068: * the self node. <\p>
1069: *
1070: * @param context The context node of this traversal. This is the point
1071: * of origin for the traversal -- its "root node" or starting point.
1072: * @param expandedTypeID The expanded type ID that must match.
1073: *
1074: * @return the first node in the traversal.
1075: */
1076: public int first(int current, int expandedTypeID) {
1077: // Compute in ID space
1078: current = makeNodeIdentity(current);
1079:
1080: while (NULL != (current = m_parent.elementAt(current))) {
1081: if (m_exptype.elementAt(current) == expandedTypeID)
1082: return makeNodeHandle(current);
1083: }
1084:
1085: return NULL;
1086: }
1087:
1088: /**
1089: * Traverse to the next node after the current node.
1090: *
1091: * @param context The context node of this iteration.
1092: * @param current The current node of the iteration.
1093: *
1094: * @return the next node in the iteration, or DTM.NULL.
1095: */
1096: public int next(int context, int current) {
1097:
1098: return NULL;
1099: }
1100:
1101: /**
1102: * Traverse to the next node after the current node that is matched
1103: * by the expanded type ID.
1104: *
1105: * @param context The context node of this iteration.
1106: * @param current The current node of the iteration.
1107: * @param expandedTypeID The expanded type ID that must match.
1108: *
1109: * @return the next node in the iteration, or DTM.NULL.
1110: */
1111: public int next(int context, int current, int expandedTypeID) {
1112:
1113: return NULL;
1114: }
1115: }
1116:
1117: /**
1118: * Implements traversal of the Ancestor access, in reverse document order.
1119: */
1120: private class PrecedingTraverser extends DTMAxisTraverser {
1121:
1122: /**
1123: * Tell if the current identity is an ancestor of the context identity.
1124: * This is an expensive operation, made worse by the stateless traversal.
1125: * But the preceding axis is used fairly infrequently.
1126: *
1127: * @param contextIdent The context node of the axis traversal.
1128: * @param currentIdent The node in question.
1129: * @return true if the currentIdent node is an ancestor of contextIdent.
1130: */
1131: protected boolean isAncestor(int contextIdent, int currentIdent) {
1132: // %REVIEW% See comments in IsAfterAxis; using the "successor" of
1133: // contextIdent is probably more efficient.
1134: for (contextIdent = m_parent.elementAt(contextIdent); DTM.NULL != contextIdent; contextIdent = m_parent
1135: .elementAt(contextIdent)) {
1136: if (contextIdent == currentIdent)
1137: return true;
1138: }
1139:
1140: return false;
1141: }
1142:
1143: /**
1144: * Traverse to the next node after the current node.
1145: *
1146: * @param context The context node of this iteration.
1147: * @param current The current node of the iteration.
1148: *
1149: * @return the next node in the iteration, or DTM.NULL.
1150: */
1151: public int next(int context, int current) {
1152: // compute in ID space
1153: int subtreeRootIdent = makeNodeIdentity(context);
1154:
1155: for (current = makeNodeIdentity(current) - 1; current >= 0; current--) {
1156: short type = _type(current);
1157:
1158: if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type
1159: || isAncestor(subtreeRootIdent, current))
1160: continue;
1161:
1162: return makeNodeHandle(current); // make handle.
1163: }
1164:
1165: return NULL;
1166: }
1167:
1168: /**
1169: * Traverse to the next node after the current node that is matched
1170: * by the expanded type ID.
1171: *
1172: * @param context The context node of this iteration.
1173: * @param current The current node of the iteration.
1174: * @param expandedTypeID The expanded type ID that must match.
1175: *
1176: * @return the next node in the iteration, or DTM.NULL.
1177: */
1178: public int next(int context, int current, int expandedTypeID) {
1179: // Compute in ID space
1180: int subtreeRootIdent = makeNodeIdentity(context);
1181:
1182: for (current = makeNodeIdentity(current) - 1; current >= 0; current--) {
1183: int exptype = m_exptype.elementAt(current);
1184:
1185: if (exptype != expandedTypeID
1186: || isAncestor(subtreeRootIdent, current))
1187: continue;
1188:
1189: return makeNodeHandle(current); // make handle.
1190: }
1191:
1192: return NULL;
1193: }
1194: }
1195:
1196: /**
1197: * Implements traversal of the Ancestor and the Preceding axis,
1198: * in reverse document order.
1199: */
1200: private class PrecedingAndAncestorTraverser extends
1201: DTMAxisTraverser {
1202:
1203: /**
1204: * Traverse to the next node after the current node.
1205: *
1206: * @param context The context node of this iteration.
1207: * @param current The current node of the iteration.
1208: *
1209: * @return the next node in the iteration, or DTM.NULL.
1210: */
1211: public int next(int context, int current) {
1212: // Compute in ID space
1213: int subtreeRootIdent = makeNodeIdentity(context);
1214:
1215: for (current = makeNodeIdentity(current) - 1; current >= 0; current--) {
1216: short type = _type(current);
1217:
1218: if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
1219: continue;
1220:
1221: return makeNodeHandle(current); // make handle.
1222: }
1223:
1224: return NULL;
1225: }
1226:
1227: /**
1228: * Traverse to the next node after the current node that is matched
1229: * by the expanded type ID.
1230: *
1231: * @param context The context node of this iteration.
1232: * @param current The current node of the iteration.
1233: * @param expandedTypeID The expanded type ID that must match.
1234: *
1235: * @return the next node in the iteration, or DTM.NULL.
1236: */
1237: public int next(int context, int current, int expandedTypeID) {
1238: // Compute in ID space
1239: int subtreeRootIdent = makeNodeIdentity(context);
1240:
1241: for (current = makeNodeIdentity(current) - 1; current >= 0; current--) {
1242: int exptype = m_exptype.elementAt(current);
1243:
1244: if (exptype != expandedTypeID)
1245: continue;
1246:
1247: return makeNodeHandle(current); // make handle.
1248: }
1249:
1250: return NULL;
1251: }
1252: }
1253:
1254: /**
1255: * Implements traversal of the Ancestor access, in reverse document order.
1256: */
1257: private class PrecedingSiblingTraverser extends DTMAxisTraverser {
1258:
1259: /**
1260: * Traverse to the next node after the current node.
1261: *
1262: * @param context The context node of this iteration.
1263: * @param current The current node of the iteration.
1264: *
1265: * @return the next node in the iteration, or DTM.NULL.
1266: */
1267: public int next(int context, int current) {
1268: return getPreviousSibling(current);
1269: }
1270:
1271: /**
1272: * Traverse to the next node after the current node that is matched
1273: * by the expanded type ID.
1274: *
1275: * @param context The context node of this iteration.
1276: * @param current The current node of the iteration.
1277: * @param expandedTypeID The expanded type ID that must match.
1278: *
1279: * @return the next node in the iteration, or DTM.NULL.
1280: */
1281: public int next(int context, int current, int expandedTypeID) {
1282:
1283: while (DTM.NULL != (current = getPreviousSibling(current))) {
1284: if (getExpandedTypeID(current) == expandedTypeID)
1285: return current;
1286: }
1287:
1288: return NULL;
1289: }
1290: }
1291:
1292: /**
1293: * Implements traversal of the Self axis.
1294: */
1295: private class SelfTraverser extends DTMAxisTraverser {
1296:
1297: /**
1298: * By the nature of the stateless traversal, the context node can not be
1299: * returned or the iteration will go into an infinate loop. To see if
1300: * the self node should be processed, use this function.
1301: *
1302: * @param context The context node of this traversal.
1303: *
1304: * @return the first node in the traversal.
1305: */
1306: public int first(int context) {
1307: return context;
1308: }
1309:
1310: /**
1311: * By the nature of the stateless traversal, the context node can not be
1312: * returned or the iteration will go into an infinate loop. To see if
1313: * the self node should be processed, use this function. If the context
1314: * node does not match the expanded type ID, this function will return
1315: * false.
1316: *
1317: * @param context The context node of this traversal.
1318: * @param expandedTypeID The expanded type ID that must match.
1319: *
1320: * @return the first node in the traversal.
1321: */
1322: public int first(int context, int expandedTypeID) {
1323: return (getExpandedTypeID(context) == expandedTypeID) ? context
1324: : NULL;
1325: }
1326:
1327: /**
1328: * Traverse to the next node after the current node.
1329: *
1330: * @param context The context node of this iteration.
1331: * @param current The current node of the iteration.
1332: *
1333: * @return Always return NULL for this axis.
1334: */
1335: public int next(int context, int current) {
1336: return NULL;
1337: }
1338:
1339: /**
1340: * Traverse to the next node after the current node that is matched
1341: * by the expanded type ID.
1342: *
1343: * @param context The context node of this iteration.
1344: * @param current The current node of the iteration.
1345: * @param expandedTypeID The expanded type ID that must match.
1346: *
1347: * @return the next node in the iteration, or DTM.NULL.
1348: */
1349: public int next(int context, int current, int expandedTypeID) {
1350: return NULL;
1351: }
1352: }
1353:
1354: /**
1355: * Implements traversal of the Ancestor access, in reverse document order.
1356: */
1357: private class AllFromRootTraverser extends AllFromNodeTraverser {
1358:
1359: /**
1360: * Return the root.
1361: *
1362: * @param context The context node of this traversal.
1363: *
1364: * @return the first node in the traversal.
1365: */
1366: public int first(int context) {
1367: return getDocumentRoot(context);
1368: }
1369:
1370: /**
1371: * Return the root if it matches the expanded type ID.
1372: *
1373: * @param context The context node of this traversal.
1374: * @param expandedTypeID The expanded type ID that must match.
1375: *
1376: * @return the first node in the traversal.
1377: */
1378: public int first(int context, int expandedTypeID) {
1379: return (getExpandedTypeID(getDocumentRoot(context)) == expandedTypeID) ? context
1380: : next(context, context, expandedTypeID);
1381: }
1382:
1383: /**
1384: * Traverse to the next node after the current node.
1385: *
1386: * @param context The context node of this iteration.
1387: * @param current The current node of the iteration.
1388: *
1389: * @return the next node in the iteration, or DTM.NULL.
1390: */
1391: public int next(int context, int current) {
1392: // Compute in ID space
1393: int subtreeRootIdent = makeNodeIdentity(context);
1394:
1395: for (current = makeNodeIdentity(current) + 1;; current++) {
1396: // Kluge test: Just make sure +1 yielded a real node
1397: int type = _type(current); // may call nextNode()
1398: if (type == NULL)
1399: return NULL;
1400:
1401: return makeNodeHandle(current); // make handle.
1402: }
1403: }
1404:
1405: /**
1406: * Traverse to the next node after the current node that is matched
1407: * by the expanded type ID.
1408: *
1409: * @param context The context node of this iteration.
1410: * @param current The current node of the iteration.
1411: * @param expandedTypeID The expanded type ID that must match.
1412: *
1413: * @return the next node in the iteration, or DTM.NULL.
1414: */
1415: public int next(int context, int current, int expandedTypeID) {
1416: // Compute in ID space
1417: int subtreeRootIdent = makeNodeIdentity(context);
1418:
1419: for (current = makeNodeIdentity(current) + 1;; current++) {
1420: int exptype = _exptype(current); // may call nextNode()
1421:
1422: if (exptype == NULL)
1423: return NULL;
1424:
1425: if (exptype != expandedTypeID)
1426: continue;
1427:
1428: return makeNodeHandle(current); // make handle.
1429: }
1430: }
1431: }
1432:
1433: /**
1434: * Implements traversal of the Self axis.
1435: */
1436: private class RootTraverser extends AllFromRootTraverser {
1437: /**
1438: * Return the root if it matches the expanded type ID,
1439: * else return null (nothing found)
1440: *
1441: * @param context The context node of this traversal.
1442: * @param expandedTypeID The expanded type ID that must match.
1443: *
1444: * @return the first node in the traversal.
1445: */
1446: public int first(int context, int expandedTypeID) {
1447: int root = getDocumentRoot(context);
1448: return (getExpandedTypeID(root) == expandedTypeID) ? root
1449: : NULL;
1450: }
1451:
1452: /**
1453: * Traverse to the next node after the current node.
1454: *
1455: * @param context The context node of this iteration.
1456: * @param current The current node of the iteration.
1457: *
1458: * @return Always return NULL for this axis.
1459: */
1460: public int next(int context, int current) {
1461: return NULL;
1462: }
1463:
1464: /**
1465: * Traverse to the next node after the current node that is matched
1466: * by the expanded type ID.
1467: *
1468: * @param context The context node of this iteration.
1469: * @param current The current node of the iteration.
1470: * @param expandedTypeID The expanded type ID that must match.
1471: *
1472: * @return the next node in the iteration, or DTM.NULL.
1473: */
1474: public int next(int context, int current, int expandedTypeID) {
1475: return NULL;
1476: }
1477: }
1478:
1479: /**
1480: * A non-xpath axis, returns all nodes that aren't namespaces or attributes,
1481: * from and including the root.
1482: */
1483: private class DescendantOrSelfFromRootTraverser extends
1484: DescendantTraverser {
1485:
1486: /**
1487: * Get the first potential identity that can be returned, which is the axis
1488: * root context in this case.
1489: *
1490: * @param identity The node identity of the root context of the traversal.
1491: *
1492: * @return The identity argument.
1493: */
1494: protected int getFirstPotential(int identity) {
1495: return identity;
1496: }
1497:
1498: /**
1499: * Get the first potential identity that can be returned.
1500: * @param handle handle to the root context.
1501: * @return identity of the root of the subtree.
1502: */
1503: protected int getSubtreeRoot(int handle) {
1504: // %REVIEW% Shouldn't this always be 0?
1505: return makeNodeIdentity(getDocument());
1506: }
1507:
1508: /**
1509: * Return the root.
1510: *
1511: * @param context The context node of this traversal.
1512: *
1513: * @return the first node in the traversal.
1514: */
1515: public int first(int context) {
1516: return getDocumentRoot(context);
1517: }
1518:
1519: /**
1520: * By the nature of the stateless traversal, the context node can not be
1521: * returned or the iteration will go into an infinate loop. So to traverse
1522: * an axis, the first function must be used to get the first node.
1523: *
1524: * <p>This method needs to be overloaded only by those axis that process
1525: * the self node. <\p>
1526: *
1527: * @param context The context node of this traversal. This is the point
1528: * of origin for the traversal -- its "root node" or starting point.
1529: * @param expandedTypeID The expanded type ID that must match.
1530: *
1531: * @return the first node in the traversal.
1532: */
1533: public int first(int context, int expandedTypeID) {
1534: if (isIndexed(expandedTypeID)) {
1535: int identity = 0;
1536: int firstPotential = getFirstPotential(identity);
1537:
1538: return makeNodeHandle(getNextIndexed(identity,
1539: firstPotential, expandedTypeID));
1540: }
1541:
1542: int root = first(context);
1543: return next(root, root, expandedTypeID);
1544: }
1545: }
1546:
1547: /**
1548: * A non-xpath axis, returns all nodes that aren't namespaces or attributes,
1549: * from but not including the root.
1550: */
1551: private class DescendantFromRootTraverser extends
1552: DescendantTraverser {
1553:
1554: /**
1555: * Get the first potential identity that can be returned, which is the axis
1556: * root context in this case.
1557: *
1558: * @param identity The node identity of the root context of the traversal.
1559: *
1560: * @return The identity argument.
1561: */
1562: protected int getFirstPotential(int identity) {
1563: return _firstch(0);
1564: }
1565:
1566: /**
1567: * Get the first potential identity that can be returned.
1568: * @param handle handle to the root context.
1569: * @return identity of the root of the subtree.
1570: */
1571: protected int getSubtreeRoot(int handle) {
1572: return 0;
1573: }
1574:
1575: /**
1576: * Return the root.
1577: *
1578: * @param context The context node of this traversal.
1579: *
1580: * @return the first node in the traversal.
1581: */
1582: public int first(int context) {
1583: return makeNodeHandle(_firstch(0));
1584: }
1585:
1586: /**
1587: * By the nature of the stateless traversal, the context node can not be
1588: * returned or the iteration will go into an infinate loop. So to traverse
1589: * an axis, the first function must be used to get the first node.
1590: *
1591: * <p>This method needs to be overloaded only by those axis that process
1592: * the self node. <\p>
1593: *
1594: * @param context The context node of this traversal. This is the point
1595: * of origin for the traversal -- its "root node" or starting point.
1596: * @param expandedTypeID The expanded type ID that must match.
1597: *
1598: * @return the first node in the traversal.
1599: */
1600: public int first(int context, int expandedTypeID) {
1601: if (isIndexed(expandedTypeID)) {
1602: int identity = 0;
1603: int firstPotential = getFirstPotential(identity);
1604:
1605: return makeNodeHandle(getNextIndexed(identity,
1606: firstPotential, expandedTypeID));
1607: }
1608:
1609: int root = getDocumentRoot(context);
1610: return next(root, root, expandedTypeID);
1611: }
1612:
1613: }
1614:
1615: }
|