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: DTMDefaultBaseIterators.java,v 1.23 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: public abstract class DTMDefaultBaseIterators extends
0035: DTMDefaultBaseTraversers {
0036:
0037: /**
0038: * Construct a DTMDefaultBaseTraversers object from a DOM node.
0039: *
0040: * @param mgr The DTMManager who owns this DTM.
0041: * @param source The object that is used to specify the construction source.
0042: * @param dtmIdentity The DTM identity ID for this DTM.
0043: * @param whiteSpaceFilter The white space filter for this DTM, which may
0044: * be null.
0045: * @param xstringfactory The factory to use for creating XMLStrings.
0046: * @param doIndexing true if the caller considers it worth it to use
0047: * indexing schemes.
0048: */
0049: public DTMDefaultBaseIterators(DTMManager mgr, Source source,
0050: int dtmIdentity, DTMWSFilter whiteSpaceFilter,
0051: XMLStringFactory xstringfactory, boolean doIndexing) {
0052: super (mgr, source, dtmIdentity, whiteSpaceFilter,
0053: xstringfactory, doIndexing);
0054: }
0055:
0056: /**
0057: * Construct a DTMDefaultBaseTraversers object from a DOM node.
0058: *
0059: * @param mgr The DTMManager who owns this DTM.
0060: * @param source The object that is used to specify the construction source.
0061: * @param dtmIdentity The DTM identity ID for this DTM.
0062: * @param whiteSpaceFilter The white space filter for this DTM, which may
0063: * be null.
0064: * @param xstringfactory The factory to use for creating XMLStrings.
0065: * @param doIndexing true if the caller considers it worth it to use
0066: * indexing schemes.
0067: * @param blocksize The block size of the DTM.
0068: * @param usePrevsib true if we want to build the previous sibling node array.
0069: * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
0070: */
0071: public DTMDefaultBaseIterators(DTMManager mgr, Source source,
0072: int dtmIdentity, DTMWSFilter whiteSpaceFilter,
0073: XMLStringFactory xstringfactory, boolean doIndexing,
0074: int blocksize, boolean usePrevsib, boolean newNameTable) {
0075: super (mgr, source, dtmIdentity, whiteSpaceFilter,
0076: xstringfactory, doIndexing, blocksize, usePrevsib,
0077: newNameTable);
0078: }
0079:
0080: /**
0081: * Get an iterator that can navigate over an XPath Axis, predicated by
0082: * the extended type ID.
0083: * Returns an iterator that must be initialized
0084: * with a start node (using iterator.setStartNode()).
0085: *
0086: * @param axis One of Axes.ANCESTORORSELF, etc.
0087: * @param type An extended type ID.
0088: *
0089: * @return A DTMAxisIterator, or null if the given axis isn't supported.
0090: */
0091: public DTMAxisIterator getTypedAxisIterator(int axis, int type) {
0092:
0093: DTMAxisIterator iterator = null;
0094:
0095: /* This causes an error when using patterns for elements that
0096: do not exist in the DOM (translet types which do not correspond
0097: to a DOM type are mapped to the DOM.ELEMENT type).
0098: */
0099:
0100: // if (type == NO_TYPE) {
0101: // return(EMPTYITERATOR);
0102: // }
0103: // else if (type == ELEMENT) {
0104: // iterator = new FilterIterator(getAxisIterator(axis),
0105: // getElementFilter());
0106: // }
0107: // else
0108: {
0109: switch (axis) {
0110: case Axis.SELF:
0111: iterator = new TypedSingletonIterator(type);
0112: break;
0113: case Axis.CHILD:
0114: iterator = new TypedChildrenIterator(type);
0115: break;
0116: case Axis.PARENT:
0117: return (new ParentIterator().setNodeType(type));
0118: case Axis.ANCESTOR:
0119: return (new TypedAncestorIterator(type));
0120: case Axis.ANCESTORORSELF:
0121: return ((new TypedAncestorIterator(type)).includeSelf());
0122: case Axis.ATTRIBUTE:
0123: return (new TypedAttributeIterator(type));
0124: case Axis.DESCENDANT:
0125: iterator = new TypedDescendantIterator(type);
0126: break;
0127: case Axis.DESCENDANTORSELF:
0128: iterator = (new TypedDescendantIterator(type))
0129: .includeSelf();
0130: break;
0131: case Axis.FOLLOWING:
0132: iterator = new TypedFollowingIterator(type);
0133: break;
0134: case Axis.PRECEDING:
0135: iterator = new TypedPrecedingIterator(type);
0136: break;
0137: case Axis.FOLLOWINGSIBLING:
0138: iterator = new TypedFollowingSiblingIterator(type);
0139: break;
0140: case Axis.PRECEDINGSIBLING:
0141: iterator = new TypedPrecedingSiblingIterator(type);
0142: break;
0143: case Axis.NAMESPACE:
0144: iterator = new TypedNamespaceIterator(type);
0145: break;
0146: case Axis.ROOT:
0147: iterator = new TypedRootIterator(type);
0148: break;
0149: default:
0150: throw new DTMException(
0151: XMLMessages
0152: .createXMLMessage(
0153: XMLErrorResources.ER_TYPED_ITERATOR_AXIS_NOT_IMPLEMENTED,
0154: new Object[] { Axis
0155: .getNames(axis) }));
0156: //"Error: typed iterator for axis "
0157: //+ Axis.names[axis] + "not implemented");
0158: }
0159: }
0160:
0161: return (iterator);
0162: }
0163:
0164: /**
0165: * This is a shortcut to the iterators that implement the
0166: * XPath axes.
0167: * Returns a bare-bones iterator that must be initialized
0168: * with a start node (using iterator.setStartNode()).
0169: *
0170: * @param axis One of Axes.ANCESTORORSELF, etc.
0171: *
0172: * @return A DTMAxisIterator, or null if the given axis isn't supported.
0173: */
0174: public DTMAxisIterator getAxisIterator(final int axis) {
0175:
0176: DTMAxisIterator iterator = null;
0177:
0178: switch (axis) {
0179: case Axis.SELF:
0180: iterator = new SingletonIterator();
0181: break;
0182: case Axis.CHILD:
0183: iterator = new ChildrenIterator();
0184: break;
0185: case Axis.PARENT:
0186: return (new ParentIterator());
0187: case Axis.ANCESTOR:
0188: return (new AncestorIterator());
0189: case Axis.ANCESTORORSELF:
0190: return ((new AncestorIterator()).includeSelf());
0191: case Axis.ATTRIBUTE:
0192: return (new AttributeIterator());
0193: case Axis.DESCENDANT:
0194: iterator = new DescendantIterator();
0195: break;
0196: case Axis.DESCENDANTORSELF:
0197: iterator = (new DescendantIterator()).includeSelf();
0198: break;
0199: case Axis.FOLLOWING:
0200: iterator = new FollowingIterator();
0201: break;
0202: case Axis.PRECEDING:
0203: iterator = new PrecedingIterator();
0204: break;
0205: case Axis.FOLLOWINGSIBLING:
0206: iterator = new FollowingSiblingIterator();
0207: break;
0208: case Axis.PRECEDINGSIBLING:
0209: iterator = new PrecedingSiblingIterator();
0210: break;
0211: case Axis.NAMESPACE:
0212: iterator = new NamespaceIterator();
0213: break;
0214: case Axis.ROOT:
0215: iterator = new RootIterator();
0216: break;
0217: default:
0218: throw new DTMException(XMLMessages.createXMLMessage(
0219: XMLErrorResources.ER_ITERATOR_AXIS_NOT_IMPLEMENTED,
0220: new Object[] { Axis.getNames(axis) }));
0221: //"Error: iterator for axis '" + Axis.names[axis]
0222: //+ "' not implemented");
0223: }
0224:
0225: return (iterator);
0226: }
0227:
0228: /**
0229: * Abstract superclass defining behaviors shared by all DTMDefault's
0230: * internal implementations of DTMAxisIterator. Subclass this (and
0231: * override, if necessary) to implement the specifics of an
0232: * individual axis iterator.
0233: *
0234: * Currently there isn't a lot here
0235: */
0236: public abstract class InternalAxisIteratorBase extends
0237: DTMAxisIteratorBase {
0238:
0239: // %REVIEW% We could opt to share _nodeType and setNodeType() as
0240: // well, and simply ignore them in iterators which don't use them.
0241: // But Scott's worried about the overhead involved in cloning
0242: // these, and wants them to have as few fields as possible. Note
0243: // that we can't create a TypedInternalAxisIteratorBase because
0244: // those are often based on the untyped versions and Java doesn't
0245: // support multiple inheritance. <sigh/>
0246:
0247: /**
0248: * Current iteration location. Usually this is the last location
0249: * returned (starting point for the next() search); for single-node
0250: * iterators it may instead be initialized to point to that single node.
0251: */
0252: protected int _currentNode;
0253:
0254: /**
0255: * Remembers the current node for the next call to gotoMark().
0256: *
0257: * %REVIEW% Should this save _position too?
0258: */
0259: public void setMark() {
0260: _markedNode = _currentNode;
0261: }
0262:
0263: /**
0264: * Restores the current node remembered by setMark().
0265: *
0266: * %REVEIW% Should this restore _position too?
0267: */
0268: public void gotoMark() {
0269: _currentNode = _markedNode;
0270: }
0271:
0272: } // end of InternalAxisIteratorBase
0273:
0274: /**
0275: * Iterator that returns all immediate children of a given node
0276: */
0277: public final class ChildrenIterator extends
0278: InternalAxisIteratorBase {
0279:
0280: /**
0281: * Setting start to END should 'close' the iterator,
0282: * i.e. subsequent call to next() should return END.
0283: *
0284: * If the iterator is not restartable, this has no effect.
0285: * %REVIEW% Should it return/throw something in that case,
0286: * or set current node to END, to indicate request-not-honored?
0287: *
0288: * @param node Sets the root of the iteration.
0289: *
0290: * @return A DTMAxisIterator set to the start of the iteration.
0291: */
0292: public DTMAxisIterator setStartNode(int node) {
0293: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0294: if (node == DTMDefaultBase.ROOTNODE)
0295: node = getDocument();
0296: if (_isRestartable) {
0297: _startNode = node;
0298: _currentNode = (node == DTM.NULL) ? DTM.NULL
0299: : _firstch(makeNodeIdentity(node));
0300:
0301: return resetPosition();
0302: }
0303:
0304: return this ;
0305: }
0306:
0307: /**
0308: * Get the next node in the iteration.
0309: *
0310: * @return The next node handle in the iteration, or END if no more
0311: * are available.
0312: */
0313: public int next() {
0314: if (_currentNode != NULL) {
0315: int node = _currentNode;
0316: _currentNode = _nextsib(node);
0317: return returnNode(makeNodeHandle(node));
0318: }
0319:
0320: return END;
0321: }
0322: } // end of ChildrenIterator
0323:
0324: /**
0325: * Iterator that returns the parent of a given node. Note that
0326: * this delivers only a single node; if you want all the ancestors,
0327: * see AncestorIterator.
0328: */
0329: public final class ParentIterator extends InternalAxisIteratorBase {
0330:
0331: /** The extended type ID that was requested. */
0332: private int _nodeType = -1;
0333:
0334: /**
0335: * Set start to END should 'close' the iterator,
0336: * i.e. subsequent call to next() should return END.
0337: *
0338: * @param node Sets the root of the iteration.
0339: *
0340: * @return A DTMAxisIterator set to the start of the iteration.
0341: */
0342: public DTMAxisIterator setStartNode(int node) {
0343: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0344: if (node == DTMDefaultBase.ROOTNODE)
0345: node = getDocument();
0346: if (_isRestartable) {
0347: _startNode = node;
0348: _currentNode = getParent(node);
0349:
0350: return resetPosition();
0351: }
0352:
0353: return this ;
0354: }
0355:
0356: /**
0357: * Set the node type of the parent that we're looking for.
0358: * Note that this does _not_ mean "find the nearest ancestor of
0359: * this type", but "yield the parent if it is of this type".
0360: *
0361: *
0362: * @param type extended type ID.
0363: *
0364: * @return ParentIterator configured with the type filter set.
0365: */
0366: public DTMAxisIterator setNodeType(final int type) {
0367:
0368: _nodeType = type;
0369:
0370: return this ;
0371: }
0372:
0373: /**
0374: * Get the next node in the iteration. In this case, we return
0375: * only the immediate parent, _if_ it matches the requested nodeType.
0376: *
0377: * @return The next node handle in the iteration, or END.
0378: */
0379: public int next() {
0380: int result = _currentNode;
0381:
0382: if (_nodeType >= DTM.NTYPES) {
0383: if (_nodeType != getExpandedTypeID(_currentNode)) {
0384: result = END;
0385: }
0386: } else if (_nodeType != NULL) {
0387: if (_nodeType != getNodeType(_currentNode)) {
0388: result = END;
0389: }
0390: }
0391:
0392: _currentNode = END;
0393:
0394: return returnNode(result);
0395: }
0396: } // end of ParentIterator
0397:
0398: /**
0399: * Iterator that returns children of a given type for a given node.
0400: * The functionality chould be achieved by putting a filter on top
0401: * of a basic child iterator, but a specialised iterator is used
0402: * for efficiency (both speed and size of translet).
0403: */
0404: public final class TypedChildrenIterator extends
0405: InternalAxisIteratorBase {
0406:
0407: /** The extended type ID that was requested. */
0408: private final int _nodeType;
0409:
0410: /**
0411: * Constructor TypedChildrenIterator
0412: *
0413: *
0414: * @param nodeType The extended type ID being requested.
0415: */
0416: public TypedChildrenIterator(int nodeType) {
0417: _nodeType = nodeType;
0418: }
0419:
0420: /**
0421: * Set start to END should 'close' the iterator,
0422: * i.e. subsequent call to next() should return END.
0423: *
0424: * @param node Sets the root of the iteration.
0425: *
0426: * @return A DTMAxisIterator set to the start of the iteration.
0427: */
0428: public DTMAxisIterator setStartNode(int node) {
0429: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0430: if (node == DTMDefaultBase.ROOTNODE)
0431: node = getDocument();
0432: if (_isRestartable) {
0433: _startNode = node;
0434: _currentNode = (node == DTM.NULL) ? DTM.NULL
0435: : _firstch(makeNodeIdentity(_startNode));
0436:
0437: return resetPosition();
0438: }
0439:
0440: return this ;
0441: }
0442:
0443: /**
0444: * Get the next node in the iteration.
0445: *
0446: * @return The next node handle in the iteration, or END.
0447: */
0448: public int next() {
0449: int eType;
0450: int node = _currentNode;
0451:
0452: int nodeType = _nodeType;
0453:
0454: if (nodeType >= DTM.NTYPES) {
0455: while (node != DTM.NULL && _exptype(node) != nodeType) {
0456: node = _nextsib(node);
0457: }
0458: } else {
0459: while (node != DTM.NULL) {
0460: eType = _exptype(node);
0461: if (eType < DTM.NTYPES) {
0462: if (eType == nodeType) {
0463: break;
0464: }
0465: } else if (m_expandedNameTable.getType(eType) == nodeType) {
0466: break;
0467: }
0468: node = _nextsib(node);
0469: }
0470: }
0471:
0472: if (node == DTM.NULL) {
0473: _currentNode = DTM.NULL;
0474: return DTM.NULL;
0475: } else {
0476: _currentNode = _nextsib(node);
0477: return returnNode(makeNodeHandle(node));
0478: }
0479:
0480: }
0481: } // end of TypedChildrenIterator
0482:
0483: /**
0484: * Iterator that returns children within a given namespace for a
0485: * given node. The functionality chould be achieved by putting a
0486: * filter on top of a basic child iterator, but a specialised
0487: * iterator is used for efficiency (both speed and size of translet).
0488: */
0489: public final class NamespaceChildrenIterator extends
0490: InternalAxisIteratorBase {
0491:
0492: /** The extended type ID being requested. */
0493: private final int _nsType;
0494:
0495: /**
0496: * Constructor NamespaceChildrenIterator
0497: *
0498: *
0499: * @param type The extended type ID being requested.
0500: */
0501: public NamespaceChildrenIterator(final int type) {
0502: _nsType = type;
0503: }
0504:
0505: /**
0506: * Set start to END should 'close' the iterator,
0507: * i.e. subsequent call to next() should return END.
0508: *
0509: * @param node Sets the root of the iteration.
0510: *
0511: * @return A DTMAxisIterator set to the start of the iteration.
0512: */
0513: public DTMAxisIterator setStartNode(int node) {
0514: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0515: if (node == DTMDefaultBase.ROOTNODE)
0516: node = getDocument();
0517: if (_isRestartable) {
0518: _startNode = node;
0519: _currentNode = (node == DTM.NULL) ? DTM.NULL
0520: : NOTPROCESSED;
0521:
0522: return resetPosition();
0523: }
0524:
0525: return this ;
0526: }
0527:
0528: /**
0529: * Get the next node in the iteration.
0530: *
0531: * @return The next node handle in the iteration, or END.
0532: */
0533: public int next() {
0534: if (_currentNode != DTM.NULL) {
0535: for (int node = (NOTPROCESSED == _currentNode) ? _firstch(makeNodeIdentity(_startNode))
0536: : _nextsib(_currentNode); node != END; node = _nextsib(node)) {
0537: if (m_expandedNameTable
0538: .getNamespaceID(_exptype(node)) == _nsType) {
0539: _currentNode = node;
0540:
0541: return returnNode(node);
0542: }
0543: }
0544: }
0545:
0546: return END;
0547: }
0548: } // end of NamespaceChildrenIterator
0549:
0550: /**
0551: * Iterator that returns the namespace nodes as defined by the XPath data model
0552: * for a given node.
0553: */
0554: public class NamespaceIterator extends InternalAxisIteratorBase {
0555:
0556: /**
0557: * Constructor NamespaceAttributeIterator
0558: */
0559: public NamespaceIterator() {
0560:
0561: super ();
0562: }
0563:
0564: /**
0565: * Set start to END should 'close' the iterator,
0566: * i.e. subsequent call to next() should return END.
0567: *
0568: * @param node Sets the root of the iteration.
0569: *
0570: * @return A DTMAxisIterator set to the start of the iteration.
0571: */
0572: public DTMAxisIterator setStartNode(int node) {
0573: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0574: if (node == DTMDefaultBase.ROOTNODE)
0575: node = getDocument();
0576: if (_isRestartable) {
0577: _startNode = node;
0578: _currentNode = getFirstNamespaceNode(node, true);
0579:
0580: return resetPosition();
0581: }
0582:
0583: return this ;
0584: }
0585:
0586: /**
0587: * Get the next node in the iteration.
0588: *
0589: * @return The next node handle in the iteration, or END.
0590: */
0591: public int next() {
0592:
0593: int node = _currentNode;
0594:
0595: if (DTM.NULL != node)
0596: _currentNode = getNextNamespaceNode(_startNode, node,
0597: true);
0598:
0599: return returnNode(node);
0600: }
0601: } // end of NamespaceIterator
0602:
0603: /**
0604: * Iterator that returns the namespace nodes as defined by the XPath data model
0605: * for a given node, filtered by extended type ID.
0606: */
0607: public class TypedNamespaceIterator extends NamespaceIterator {
0608:
0609: /** The extended type ID that was requested. */
0610: private final int _nodeType;
0611:
0612: /**
0613: * Constructor TypedNamespaceIterator
0614: *
0615: *
0616: * @param nodeType The extended type ID being requested.
0617: */
0618: public TypedNamespaceIterator(int nodeType) {
0619: super ();
0620: _nodeType = nodeType;
0621: }
0622:
0623: /**
0624: * Get the next node in the iteration.
0625: *
0626: * @return The next node handle in the iteration, or END.
0627: */
0628: public int next() {
0629: int node;
0630:
0631: for (node = _currentNode; node != END; node = getNextNamespaceNode(
0632: _startNode, node, true)) {
0633: if (getExpandedTypeID(node) == _nodeType
0634: || getNodeType(node) == _nodeType
0635: || getNamespaceType(node) == _nodeType) {
0636: _currentNode = node;
0637:
0638: return returnNode(node);
0639: }
0640: }
0641:
0642: return (_currentNode = END);
0643: }
0644: } // end of TypedNamespaceIterator
0645:
0646: /**
0647: * Iterator that returns the the root node as defined by the XPath data model
0648: * for a given node.
0649: */
0650: public class RootIterator extends InternalAxisIteratorBase {
0651:
0652: /**
0653: * Constructor RootIterator
0654: */
0655: public RootIterator() {
0656:
0657: super ();
0658: }
0659:
0660: /**
0661: * Set start to END should 'close' the iterator,
0662: * i.e. subsequent call to next() should return END.
0663: *
0664: * @param node Sets the root of the iteration.
0665: *
0666: * @return A DTMAxisIterator set to the start of the iteration.
0667: */
0668: public DTMAxisIterator setStartNode(int node) {
0669:
0670: if (_isRestartable) {
0671: _startNode = getDocumentRoot(node);
0672: _currentNode = NULL;
0673:
0674: return resetPosition();
0675: }
0676:
0677: return this ;
0678: }
0679:
0680: /**
0681: * Get the next node in the iteration.
0682: *
0683: * @return The next node handle in the iteration, or END.
0684: */
0685: public int next() {
0686: if (_startNode == _currentNode)
0687: return NULL;
0688:
0689: _currentNode = _startNode;
0690:
0691: return returnNode(_startNode);
0692: }
0693: } // end of RootIterator
0694:
0695: /**
0696: * Iterator that returns the namespace nodes as defined by the XPath data model
0697: * for a given node, filtered by extended type ID.
0698: */
0699: public class TypedRootIterator extends RootIterator {
0700:
0701: /** The extended type ID that was requested. */
0702: private final int _nodeType;
0703:
0704: /**
0705: * Constructor TypedRootIterator
0706: *
0707: * @param nodeType The extended type ID being requested.
0708: */
0709: public TypedRootIterator(int nodeType) {
0710: super ();
0711: _nodeType = nodeType;
0712: }
0713:
0714: /**
0715: * Get the next node in the iteration.
0716: *
0717: * @return The next node handle in the iteration, or END.
0718: */
0719: public int next() {
0720: if (_startNode == _currentNode)
0721: return NULL;
0722:
0723: int nodeType = _nodeType;
0724: int node = _startNode;
0725: int expType = getExpandedTypeID(node);
0726:
0727: _currentNode = node;
0728:
0729: if (nodeType >= DTM.NTYPES) {
0730: if (nodeType == expType) {
0731: return returnNode(node);
0732: }
0733: } else {
0734: if (expType < DTM.NTYPES) {
0735: if (expType == nodeType) {
0736: return returnNode(node);
0737: }
0738: } else {
0739: if (m_expandedNameTable.getType(expType) == nodeType) {
0740: return returnNode(node);
0741: }
0742: }
0743: }
0744:
0745: return END;
0746: }
0747: } // end of TypedRootIterator
0748:
0749: /**
0750: * Iterator that returns attributes within a given namespace for a node.
0751: */
0752: public final class NamespaceAttributeIterator extends
0753: InternalAxisIteratorBase {
0754:
0755: /** The extended type ID being requested. */
0756: private final int _nsType;
0757:
0758: /**
0759: * Constructor NamespaceAttributeIterator
0760: *
0761: *
0762: * @param nsType The extended type ID being requested.
0763: */
0764: public NamespaceAttributeIterator(int nsType) {
0765:
0766: super ();
0767:
0768: _nsType = nsType;
0769: }
0770:
0771: /**
0772: * Set start to END should 'close' the iterator,
0773: * i.e. subsequent call to next() should return END.
0774: *
0775: * @param node Sets the root of the iteration.
0776: *
0777: * @return A DTMAxisIterator set to the start of the iteration.
0778: */
0779: public DTMAxisIterator setStartNode(int node) {
0780: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0781: if (node == DTMDefaultBase.ROOTNODE)
0782: node = getDocument();
0783: if (_isRestartable) {
0784: _startNode = node;
0785: _currentNode = getFirstNamespaceNode(node, false);
0786:
0787: return resetPosition();
0788: }
0789:
0790: return this ;
0791: }
0792:
0793: /**
0794: * Get the next node in the iteration.
0795: *
0796: * @return The next node handle in the iteration, or END.
0797: */
0798: public int next() {
0799:
0800: int node = _currentNode;
0801:
0802: if (DTM.NULL != node)
0803: _currentNode = getNextNamespaceNode(_startNode, node,
0804: false);
0805:
0806: return returnNode(node);
0807: }
0808: } // end of NamespaceAttributeIterator
0809:
0810: /**
0811: * Iterator that returns all siblings of a given node.
0812: */
0813: public class FollowingSiblingIterator extends
0814: InternalAxisIteratorBase {
0815:
0816: /**
0817: * Set start to END should 'close' the iterator,
0818: * i.e. subsequent call to next() should return END.
0819: *
0820: * @param node Sets the root of the iteration.
0821: *
0822: * @return A DTMAxisIterator set to the start of the iteration.
0823: */
0824: public DTMAxisIterator setStartNode(int node) {
0825: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0826: if (node == DTMDefaultBase.ROOTNODE)
0827: node = getDocument();
0828: if (_isRestartable) {
0829: _startNode = node;
0830: _currentNode = makeNodeIdentity(node);
0831:
0832: return resetPosition();
0833: }
0834:
0835: return this ;
0836: }
0837:
0838: /**
0839: * Get the next node in the iteration.
0840: *
0841: * @return The next node handle in the iteration, or END.
0842: */
0843: public int next() {
0844: _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL
0845: : _nextsib(_currentNode);
0846: return returnNode(makeNodeHandle(_currentNode));
0847: }
0848: } // end of FollowingSiblingIterator
0849:
0850: /**
0851: * Iterator that returns all following siblings of a given node.
0852: */
0853: public final class TypedFollowingSiblingIterator extends
0854: FollowingSiblingIterator {
0855:
0856: /** The extended type ID that was requested. */
0857: private final int _nodeType;
0858:
0859: /**
0860: * Constructor TypedFollowingSiblingIterator
0861: *
0862: *
0863: * @param type The extended type ID being requested.
0864: */
0865: public TypedFollowingSiblingIterator(int type) {
0866: _nodeType = type;
0867: }
0868:
0869: /**
0870: * Get the next node in the iteration.
0871: *
0872: * @return The next node handle in the iteration, or END.
0873: */
0874: public int next() {
0875: if (_currentNode == DTM.NULL) {
0876: return DTM.NULL;
0877: }
0878:
0879: int node = _currentNode;
0880: int eType;
0881: int nodeType = _nodeType;
0882:
0883: if (nodeType >= DTM.NTYPES) {
0884: do {
0885: node = _nextsib(node);
0886: } while (node != DTM.NULL && _exptype(node) != nodeType);
0887: } else {
0888: while ((node = _nextsib(node)) != DTM.NULL) {
0889: eType = _exptype(node);
0890: if (eType < DTM.NTYPES) {
0891: if (eType == nodeType) {
0892: break;
0893: }
0894: } else if (m_expandedNameTable.getType(eType) == nodeType) {
0895: break;
0896: }
0897: }
0898: }
0899:
0900: _currentNode = node;
0901:
0902: return (_currentNode == DTM.NULL) ? DTM.NULL
0903: : returnNode(makeNodeHandle(_currentNode));
0904: }
0905: } // end of TypedFollowingSiblingIterator
0906:
0907: /**
0908: * Iterator that returns attribute nodes (of what nodes?)
0909: */
0910: public final class AttributeIterator extends
0911: InternalAxisIteratorBase {
0912:
0913: // assumes caller will pass element nodes
0914:
0915: /**
0916: * Set start to END should 'close' the iterator,
0917: * i.e. subsequent call to next() should return END.
0918: *
0919: * @param node Sets the root of the iteration.
0920: *
0921: * @return A DTMAxisIterator set to the start of the iteration.
0922: */
0923: public DTMAxisIterator setStartNode(int node) {
0924: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
0925: if (node == DTMDefaultBase.ROOTNODE)
0926: node = getDocument();
0927: if (_isRestartable) {
0928: _startNode = node;
0929: _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));
0930:
0931: return resetPosition();
0932: }
0933:
0934: return this ;
0935: }
0936:
0937: /**
0938: * Get the next node in the iteration.
0939: *
0940: * @return The next node handle in the iteration, or END.
0941: */
0942: public int next() {
0943:
0944: final int node = _currentNode;
0945:
0946: if (node != NULL) {
0947: _currentNode = getNextAttributeIdentity(node);
0948: return returnNode(makeNodeHandle(node));
0949: }
0950:
0951: return NULL;
0952: }
0953: } // end of AttributeIterator
0954:
0955: /**
0956: * Iterator that returns attribute nodes of a given type
0957: */
0958: public final class TypedAttributeIterator extends
0959: InternalAxisIteratorBase {
0960:
0961: /** The extended type ID that was requested. */
0962: private final int _nodeType;
0963:
0964: /**
0965: * Constructor TypedAttributeIterator
0966: *
0967: *
0968: * @param nodeType The extended type ID that is requested.
0969: */
0970: public TypedAttributeIterator(int nodeType) {
0971: _nodeType = nodeType;
0972: }
0973:
0974: // assumes caller will pass element nodes
0975:
0976: /**
0977: * Set start to END should 'close' the iterator,
0978: * i.e. subsequent call to next() should return END.
0979: *
0980: * @param node Sets the root of the iteration.
0981: *
0982: * @return A DTMAxisIterator set to the start of the iteration.
0983: */
0984: public DTMAxisIterator setStartNode(int node) {
0985: if (_isRestartable) {
0986: _startNode = node;
0987:
0988: _currentNode = getTypedAttribute(node, _nodeType);
0989:
0990: return resetPosition();
0991: }
0992:
0993: return this ;
0994: }
0995:
0996: /**
0997: * Get the next node in the iteration.
0998: *
0999: * @return The next node handle in the iteration, or END.
1000: */
1001: public int next() {
1002:
1003: final int node = _currentNode;
1004:
1005: // singleton iterator, since there can only be one attribute of
1006: // a given type.
1007: _currentNode = NULL;
1008:
1009: return returnNode(node);
1010: }
1011: } // end of TypedAttributeIterator
1012:
1013: /**
1014: * Iterator that returns preceding siblings of a given node
1015: */
1016: public class PrecedingSiblingIterator extends
1017: InternalAxisIteratorBase {
1018:
1019: /**
1020: * The node identity of _startNode for this iterator
1021: */
1022: protected int _startNodeID;
1023:
1024: /**
1025: * True if this iterator has a reversed axis.
1026: *
1027: * @return true.
1028: */
1029: public boolean isReverse() {
1030: return true;
1031: }
1032:
1033: /**
1034: * Set start to END should 'close' the iterator,
1035: * i.e. subsequent call to next() should return END.
1036: *
1037: * @param node Sets the root of the iteration.
1038: *
1039: * @return A DTMAxisIterator set to the start of the iteration.
1040: */
1041: public DTMAxisIterator setStartNode(int node) {
1042: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1043: if (node == DTMDefaultBase.ROOTNODE)
1044: node = getDocument();
1045: if (_isRestartable) {
1046: _startNode = node;
1047: node = _startNodeID = makeNodeIdentity(node);
1048:
1049: if (node == NULL) {
1050: _currentNode = node;
1051: return resetPosition();
1052: }
1053:
1054: int type = m_expandedNameTable.getType(_exptype(node));
1055: if (ExpandedNameTable.ATTRIBUTE == type
1056: || ExpandedNameTable.NAMESPACE == type) {
1057: _currentNode = node;
1058: } else {
1059: // Be careful to handle the Document node properly
1060: _currentNode = _parent(node);
1061: if (NULL != _currentNode)
1062: _currentNode = _firstch(_currentNode);
1063: else
1064: _currentNode = node;
1065: }
1066:
1067: return resetPosition();
1068: }
1069:
1070: return this ;
1071: }
1072:
1073: /**
1074: * Get the next node in the iteration.
1075: *
1076: * @return The next node handle in the iteration, or END.
1077: */
1078: public int next() {
1079:
1080: if (_currentNode == _startNodeID
1081: || _currentNode == DTM.NULL) {
1082: return NULL;
1083: } else {
1084: final int node = _currentNode;
1085: _currentNode = _nextsib(node);
1086:
1087: return returnNode(makeNodeHandle(node));
1088: }
1089: }
1090: } // end of PrecedingSiblingIterator
1091:
1092: /**
1093: * Iterator that returns preceding siblings of a given type for
1094: * a given node
1095: */
1096: public final class TypedPrecedingSiblingIterator extends
1097: PrecedingSiblingIterator {
1098:
1099: /** The extended type ID that was requested. */
1100: private final int _nodeType;
1101:
1102: /**
1103: * Constructor TypedPrecedingSiblingIterator
1104: *
1105: *
1106: * @param type The extended type ID being requested.
1107: */
1108: public TypedPrecedingSiblingIterator(int type) {
1109: _nodeType = type;
1110: }
1111:
1112: /**
1113: * Get the next node in the iteration.
1114: *
1115: * @return The next node handle in the iteration, or END.
1116: */
1117: public int next() {
1118: int node = _currentNode;
1119: int expType;
1120:
1121: int nodeType = _nodeType;
1122: int startID = _startNodeID;
1123:
1124: if (nodeType >= DTM.NTYPES) {
1125: while (node != NULL && node != startID
1126: && _exptype(node) != nodeType) {
1127: node = _nextsib(node);
1128: }
1129: } else {
1130: while (node != NULL && node != startID) {
1131: expType = _exptype(node);
1132: if (expType < DTM.NTYPES) {
1133: if (expType == nodeType) {
1134: break;
1135: }
1136: } else {
1137: if (m_expandedNameTable.getType(expType) == nodeType) {
1138: break;
1139: }
1140: }
1141: node = _nextsib(node);
1142: }
1143: }
1144:
1145: if (node == DTM.NULL || node == _startNodeID) {
1146: _currentNode = NULL;
1147: return NULL;
1148: } else {
1149: _currentNode = _nextsib(node);
1150: return returnNode(makeNodeHandle(node));
1151: }
1152: }
1153: } // end of TypedPrecedingSiblingIterator
1154:
1155: /**
1156: * Iterator that returns preceding nodes of a given node.
1157: * This includes the node set {root+1, start-1}, but excludes
1158: * all ancestors, attributes, and namespace nodes.
1159: */
1160: public class PrecedingIterator extends InternalAxisIteratorBase {
1161:
1162: /** The max ancestors, but it can grow... */
1163: private final int _maxAncestors = 8;
1164:
1165: /**
1166: * The stack of start node + ancestors up to the root of the tree,
1167: * which we must avoid.
1168: */
1169: protected int[] _stack = new int[_maxAncestors];
1170:
1171: /** (not sure yet... -sb) */
1172: protected int _sp, _oldsp;
1173:
1174: protected int _markedsp, _markedNode, _markedDescendant;
1175:
1176: /* _currentNode precedes candidates. This is the identity, not the handle! */
1177:
1178: /**
1179: * True if this iterator has a reversed axis.
1180: *
1181: * @return true since this iterator is a reversed axis.
1182: */
1183: public boolean isReverse() {
1184: return true;
1185: }
1186:
1187: /**
1188: * Returns a deep copy of this iterator. The cloned iterator is not reset.
1189: *
1190: * @return a deep copy of this iterator.
1191: */
1192: public DTMAxisIterator cloneIterator() {
1193: _isRestartable = false;
1194:
1195: try {
1196: final PrecedingIterator clone = (PrecedingIterator) super
1197: .clone();
1198: final int[] stackCopy = new int[_stack.length];
1199: System
1200: .arraycopy(_stack, 0, stackCopy, 0,
1201: _stack.length);
1202:
1203: clone._stack = stackCopy;
1204:
1205: // return clone.reset();
1206: return clone;
1207: } catch (CloneNotSupportedException e) {
1208: throw new DTMException(
1209: XMLMessages
1210: .createXMLMessage(
1211: XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED,
1212: null)); //"Iterator clone not supported.");
1213: }
1214: }
1215:
1216: /**
1217: * Set start to END should 'close' the iterator,
1218: * i.e. subsequent call to next() should return END.
1219: *
1220: * @param node Sets the root of the iteration.
1221: *
1222: * @return A DTMAxisIterator set to the start of the iteration.
1223: */
1224: public DTMAxisIterator setStartNode(int node) {
1225: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1226: if (node == DTMDefaultBase.ROOTNODE)
1227: node = getDocument();
1228: if (_isRestartable) {
1229: node = makeNodeIdentity(node);
1230:
1231: // iterator is not a clone
1232: int parent, index;
1233:
1234: if (_type(node) == DTM.ATTRIBUTE_NODE)
1235: node = _parent(node);
1236:
1237: _startNode = node;
1238: _stack[index = 0] = node;
1239:
1240: parent = node;
1241: while ((parent = _parent(parent)) != NULL) {
1242: if (++index == _stack.length) {
1243: final int[] stack = new int[index + 4];
1244: System.arraycopy(_stack, 0, stack, 0, index);
1245: _stack = stack;
1246: }
1247: _stack[index] = parent;
1248: }
1249: if (index > 0)
1250: --index; // Pop actual root node (if not start) back off the stack
1251:
1252: _currentNode = _stack[index]; // Last parent before root node
1253:
1254: _oldsp = _sp = index;
1255:
1256: return resetPosition();
1257: }
1258:
1259: return this ;
1260: }
1261:
1262: /**
1263: * Get the next node in the iteration.
1264: *
1265: * @return The next node handle in the iteration, or END.
1266: */
1267: public int next() {
1268: // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
1269: // Also recoded the loop controls for clarity and to flatten out
1270: // the tail-recursion.
1271: for (++_currentNode; _sp >= 0; ++_currentNode) {
1272: if (_currentNode < _stack[_sp]) {
1273: if (_type(_currentNode) != ATTRIBUTE_NODE
1274: && _type(_currentNode) != NAMESPACE_NODE)
1275: return returnNode(makeNodeHandle(_currentNode));
1276: } else
1277: --_sp;
1278: }
1279: return NULL;
1280: }
1281:
1282: // redefine DTMAxisIteratorBase's reset
1283:
1284: /**
1285: * Resets the iterator to the last start node.
1286: *
1287: * @return A DTMAxisIterator, which may or may not be the same as this
1288: * iterator.
1289: */
1290: public DTMAxisIterator reset() {
1291:
1292: _sp = _oldsp;
1293:
1294: return resetPosition();
1295: }
1296:
1297: public void setMark() {
1298: _markedsp = _sp;
1299: _markedNode = _currentNode;
1300: _markedDescendant = _stack[0];
1301: }
1302:
1303: public void gotoMark() {
1304: _sp = _markedsp;
1305: _currentNode = _markedNode;
1306: }
1307: } // end of PrecedingIterator
1308:
1309: /**
1310: * Iterator that returns preceding nodes of agiven type for a
1311: * given node. This includes the node set {root+1, start-1}, but
1312: * excludes all ancestors.
1313: */
1314: public final class TypedPrecedingIterator extends PrecedingIterator {
1315:
1316: /** The extended type ID that was requested. */
1317: private final int _nodeType;
1318:
1319: /**
1320: * Constructor TypedPrecedingIterator
1321: *
1322: *
1323: * @param type The extended type ID being requested.
1324: */
1325: public TypedPrecedingIterator(int type) {
1326: _nodeType = type;
1327: }
1328:
1329: /**
1330: * Get the next node in the iteration.
1331: *
1332: * @return The next node handle in the iteration, or END.
1333: */
1334: public int next() {
1335: int node = _currentNode;
1336: int nodeType = _nodeType;
1337:
1338: if (nodeType >= DTM.NTYPES) {
1339: while (true) {
1340: node = node + 1;
1341:
1342: if (_sp < 0) {
1343: node = NULL;
1344: break;
1345: } else if (node >= _stack[_sp]) {
1346: if (--_sp < 0) {
1347: node = NULL;
1348: break;
1349: }
1350: } else if (_exptype(node) == nodeType) {
1351: break;
1352: }
1353: }
1354: } else {
1355: int expType;
1356:
1357: while (true) {
1358: node = node + 1;
1359:
1360: if (_sp < 0) {
1361: node = NULL;
1362: break;
1363: } else if (node >= _stack[_sp]) {
1364: if (--_sp < 0) {
1365: node = NULL;
1366: break;
1367: }
1368: } else {
1369: expType = _exptype(node);
1370: if (expType < DTM.NTYPES) {
1371: if (expType == nodeType) {
1372: break;
1373: }
1374: } else {
1375: if (m_expandedNameTable.getType(expType) == nodeType) {
1376: break;
1377: }
1378: }
1379: }
1380: }
1381: }
1382:
1383: _currentNode = node;
1384:
1385: return (node == NULL) ? NULL
1386: : returnNode(makeNodeHandle(node));
1387: }
1388: } // end of TypedPrecedingIterator
1389:
1390: /**
1391: * Iterator that returns following nodes of for a given node.
1392: */
1393: public class FollowingIterator extends InternalAxisIteratorBase {
1394: DTMAxisTraverser m_traverser; // easier for now
1395:
1396: public FollowingIterator() {
1397: m_traverser = getAxisTraverser(Axis.FOLLOWING);
1398: }
1399:
1400: /**
1401: * Set start to END should 'close' the iterator,
1402: * i.e. subsequent call to next() should return END.
1403: *
1404: * @param node Sets the root of the iteration.
1405: *
1406: * @return A DTMAxisIterator set to the start of the iteration.
1407: */
1408: public DTMAxisIterator setStartNode(int node) {
1409: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1410: if (node == DTMDefaultBase.ROOTNODE)
1411: node = getDocument();
1412: if (_isRestartable) {
1413: _startNode = node;
1414:
1415: // ?? -sb
1416: // find rightmost descendant (or self)
1417: // int current;
1418: // while ((node = getLastChild(current = node)) != NULL){}
1419: // _currentNode = current;
1420: _currentNode = m_traverser.first(node);
1421:
1422: // _currentNode precedes possible following(node) nodes
1423: return resetPosition();
1424: }
1425:
1426: return this ;
1427: }
1428:
1429: /**
1430: * Get the next node in the iteration.
1431: *
1432: * @return The next node handle in the iteration, or END.
1433: */
1434: public int next() {
1435:
1436: int node = _currentNode;
1437:
1438: _currentNode = m_traverser.next(_startNode, _currentNode);
1439:
1440: return returnNode(node);
1441: }
1442: } // end of FollowingIterator
1443:
1444: /**
1445: * Iterator that returns following nodes of a given type for a given node.
1446: */
1447: public final class TypedFollowingIterator extends FollowingIterator {
1448:
1449: /** The extended type ID that was requested. */
1450: private final int _nodeType;
1451:
1452: /**
1453: * Constructor TypedFollowingIterator
1454: *
1455: *
1456: * @param type The extended type ID being requested.
1457: */
1458: public TypedFollowingIterator(int type) {
1459: _nodeType = type;
1460: }
1461:
1462: /**
1463: * Get the next node in the iteration.
1464: *
1465: * @return The next node handle in the iteration, or END.
1466: */
1467: public int next() {
1468:
1469: int node;
1470:
1471: do {
1472: node = _currentNode;
1473:
1474: _currentNode = m_traverser.next(_startNode,
1475: _currentNode);
1476:
1477: } while (node != DTM.NULL
1478: && (getExpandedTypeID(node) != _nodeType && getNodeType(node) != _nodeType));
1479:
1480: return (node == DTM.NULL ? DTM.NULL : returnNode(node));
1481: }
1482: } // end of TypedFollowingIterator
1483:
1484: /**
1485: * Iterator that returns the ancestors of a given node in document
1486: * order. (NOTE! This was changed from the XSLTC code!)
1487: */
1488: public class AncestorIterator extends InternalAxisIteratorBase {
1489: org.apache.xml.utils.NodeVector m_ancestors = new org.apache.xml.utils.NodeVector();
1490:
1491: int m_ancestorsPos;
1492:
1493: int m_markedPos;
1494:
1495: /** The real start node for this axes, since _startNode will be adjusted. */
1496: int m_realStartNode;
1497:
1498: /**
1499: * Get start to END should 'close' the iterator,
1500: * i.e. subsequent call to next() should return END.
1501: *
1502: * @return The root node of the iteration.
1503: */
1504: public int getStartNode() {
1505: return m_realStartNode;
1506: }
1507:
1508: /**
1509: * True if this iterator has a reversed axis.
1510: *
1511: * @return true since this iterator is a reversed axis.
1512: */
1513: public final boolean isReverse() {
1514: return true;
1515: }
1516:
1517: /**
1518: * Returns a deep copy of this iterator. The cloned iterator is not reset.
1519: *
1520: * @return a deep copy of this iterator.
1521: */
1522: public DTMAxisIterator cloneIterator() {
1523: _isRestartable = false; // must set to false for any clone
1524:
1525: try {
1526: final AncestorIterator clone = (AncestorIterator) super
1527: .clone();
1528:
1529: clone._startNode = _startNode;
1530:
1531: // return clone.reset();
1532: return clone;
1533: } catch (CloneNotSupportedException e) {
1534: throw new DTMException(
1535: XMLMessages
1536: .createXMLMessage(
1537: XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED,
1538: null)); //"Iterator clone not supported.");
1539: }
1540: }
1541:
1542: /**
1543: * Set start to END should 'close' the iterator,
1544: * i.e. subsequent call to next() should return END.
1545: *
1546: * @param node Sets the root of the iteration.
1547: *
1548: * @return A DTMAxisIterator set to the start of the iteration.
1549: */
1550: public DTMAxisIterator setStartNode(int node) {
1551: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1552: if (node == DTMDefaultBase.ROOTNODE)
1553: node = getDocument();
1554: m_realStartNode = node;
1555:
1556: if (_isRestartable) {
1557: int nodeID = makeNodeIdentity(node);
1558:
1559: if (!_includeSelf && node != DTM.NULL) {
1560: nodeID = _parent(nodeID);
1561: node = makeNodeHandle(nodeID);
1562: }
1563:
1564: _startNode = node;
1565:
1566: while (nodeID != END) {
1567: m_ancestors.addElement(node);
1568: nodeID = _parent(nodeID);
1569: node = makeNodeHandle(nodeID);
1570: }
1571: m_ancestorsPos = m_ancestors.size() - 1;
1572:
1573: _currentNode = (m_ancestorsPos >= 0) ? m_ancestors
1574: .elementAt(m_ancestorsPos) : DTM.NULL;
1575:
1576: return resetPosition();
1577: }
1578:
1579: return this ;
1580: }
1581:
1582: /**
1583: * Resets the iterator to the last start node.
1584: *
1585: * @return A DTMAxisIterator, which may or may not be the same as this
1586: * iterator.
1587: */
1588: public DTMAxisIterator reset() {
1589:
1590: m_ancestorsPos = m_ancestors.size() - 1;
1591:
1592: _currentNode = (m_ancestorsPos >= 0) ? m_ancestors
1593: .elementAt(m_ancestorsPos) : DTM.NULL;
1594:
1595: return resetPosition();
1596: }
1597:
1598: /**
1599: * Get the next node in the iteration.
1600: *
1601: * @return The next node handle in the iteration, or END.
1602: */
1603: public int next() {
1604:
1605: int next = _currentNode;
1606:
1607: int pos = --m_ancestorsPos;
1608:
1609: _currentNode = (pos >= 0) ? m_ancestors
1610: .elementAt(m_ancestorsPos) : DTM.NULL;
1611:
1612: return returnNode(next);
1613: }
1614:
1615: public void setMark() {
1616: m_markedPos = m_ancestorsPos;
1617: }
1618:
1619: public void gotoMark() {
1620: m_ancestorsPos = m_markedPos;
1621: _currentNode = m_ancestorsPos >= 0 ? m_ancestors
1622: .elementAt(m_ancestorsPos) : DTM.NULL;
1623: }
1624: } // end of AncestorIterator
1625:
1626: /**
1627: * Typed iterator that returns the ancestors of a given node.
1628: */
1629: public final class TypedAncestorIterator extends AncestorIterator {
1630:
1631: /** The extended type ID that was requested. */
1632: private final int _nodeType;
1633:
1634: /**
1635: * Constructor TypedAncestorIterator
1636: *
1637: *
1638: * @param type The extended type ID being requested.
1639: */
1640: public TypedAncestorIterator(int type) {
1641: _nodeType = type;
1642: }
1643:
1644: /**
1645: * Set start to END should 'close' the iterator,
1646: * i.e. subsequent call to next() should return END.
1647: *
1648: * @param node Sets the root of the iteration.
1649: *
1650: * @return A DTMAxisIterator set to the start of the iteration.
1651: */
1652: public DTMAxisIterator setStartNode(int node) {
1653: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1654: if (node == DTMDefaultBase.ROOTNODE)
1655: node = getDocument();
1656: m_realStartNode = node;
1657:
1658: if (_isRestartable) {
1659: int nodeID = makeNodeIdentity(node);
1660: int nodeType = _nodeType;
1661:
1662: if (!_includeSelf && node != DTM.NULL) {
1663: nodeID = _parent(nodeID);
1664: }
1665:
1666: _startNode = node;
1667:
1668: if (nodeType >= DTM.NTYPES) {
1669: while (nodeID != END) {
1670: int eType = _exptype(nodeID);
1671:
1672: if (eType == nodeType) {
1673: m_ancestors
1674: .addElement(makeNodeHandle(nodeID));
1675: }
1676: nodeID = _parent(nodeID);
1677: }
1678: } else {
1679: while (nodeID != END) {
1680: int eType = _exptype(nodeID);
1681:
1682: if ((eType >= DTM.NTYPES && m_expandedNameTable
1683: .getType(eType) == nodeType)
1684: || (eType < DTM.NTYPES && eType == nodeType)) {
1685: m_ancestors
1686: .addElement(makeNodeHandle(nodeID));
1687: }
1688: nodeID = _parent(nodeID);
1689: }
1690: }
1691: m_ancestorsPos = m_ancestors.size() - 1;
1692:
1693: _currentNode = (m_ancestorsPos >= 0) ? m_ancestors
1694: .elementAt(m_ancestorsPos) : DTM.NULL;
1695:
1696: return resetPosition();
1697: }
1698:
1699: return this ;
1700: }
1701: } // end of TypedAncestorIterator
1702:
1703: /**
1704: * Iterator that returns the descendants of a given node.
1705: */
1706: public class DescendantIterator extends InternalAxisIteratorBase {
1707:
1708: /**
1709: * Set start to END should 'close' the iterator,
1710: * i.e. subsequent call to next() should return END.
1711: *
1712: * @param node Sets the root of the iteration.
1713: *
1714: * @return A DTMAxisIterator set to the start of the iteration.
1715: */
1716: public DTMAxisIterator setStartNode(int node) {
1717: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1718: if (node == DTMDefaultBase.ROOTNODE)
1719: node = getDocument();
1720: if (_isRestartable) {
1721: node = makeNodeIdentity(node);
1722: _startNode = node;
1723:
1724: if (_includeSelf)
1725: node--;
1726:
1727: _currentNode = node;
1728:
1729: return resetPosition();
1730: }
1731:
1732: return this ;
1733: }
1734:
1735: /**
1736: * Tell if this node identity is a descendant. Assumes that
1737: * the node info for the element has already been obtained.
1738: *
1739: * This one-sided test works only if the parent has been
1740: * previously tested and is known to be a descendent. It fails if
1741: * the parent is the _startNode's next sibling, or indeed any node
1742: * that follows _startNode in document order. That may suffice
1743: * for this iterator, but it's not really an isDescendent() test.
1744: * %REVIEW% rename?
1745: *
1746: * @param identity The index number of the node in question.
1747: * @return true if the index is a descendant of _startNode.
1748: */
1749: protected boolean isDescendant(int identity) {
1750: return (_parent(identity) >= _startNode)
1751: || (_startNode == identity);
1752: }
1753:
1754: /**
1755: * Get the next node in the iteration.
1756: *
1757: * @return The next node handle in the iteration, or END.
1758: */
1759: public int next() {
1760: if (_startNode == NULL) {
1761: return NULL;
1762: }
1763:
1764: if (_includeSelf && (_currentNode + 1) == _startNode)
1765: return returnNode(makeNodeHandle(++_currentNode)); // | m_dtmIdent);
1766:
1767: int node = _currentNode;
1768: int type;
1769:
1770: do {
1771: node++;
1772: type = _type(node);
1773:
1774: if (NULL == type || !isDescendant(node)) {
1775: _currentNode = NULL;
1776: return END;
1777: }
1778: } while (ATTRIBUTE_NODE == type || TEXT_NODE == type
1779: || NAMESPACE_NODE == type);
1780:
1781: _currentNode = node;
1782: return returnNode(makeNodeHandle(node)); // make handle.
1783: }
1784:
1785: /**
1786: * Reset.
1787: *
1788: */
1789: public DTMAxisIterator reset() {
1790:
1791: final boolean temp = _isRestartable;
1792:
1793: _isRestartable = true;
1794:
1795: setStartNode(makeNodeHandle(_startNode));
1796:
1797: _isRestartable = temp;
1798:
1799: return this ;
1800: }
1801:
1802: } // end of DescendantIterator
1803:
1804: /**
1805: * Typed iterator that returns the descendants of a given node.
1806: */
1807: public final class TypedDescendantIterator extends
1808: DescendantIterator {
1809:
1810: /** The extended type ID that was requested. */
1811: private final int _nodeType;
1812:
1813: /**
1814: * Constructor TypedDescendantIterator
1815: *
1816: *
1817: * @param nodeType Extended type ID being requested.
1818: */
1819: public TypedDescendantIterator(int nodeType) {
1820: _nodeType = nodeType;
1821: }
1822:
1823: /**
1824: * Get the next node in the iteration.
1825: *
1826: * @return The next node handle in the iteration, or END.
1827: */
1828: public int next() {
1829: int node;
1830: int type;
1831:
1832: if (_startNode == NULL) {
1833: return NULL;
1834: }
1835:
1836: node = _currentNode;
1837:
1838: do {
1839: node++;
1840: type = _type(node);
1841:
1842: if (NULL == type || !isDescendant(node)) {
1843: _currentNode = NULL;
1844: return END;
1845: }
1846: } while (type != _nodeType && _exptype(node) != _nodeType);
1847:
1848: _currentNode = node;
1849: return returnNode(makeNodeHandle(node));
1850: }
1851: } // end of TypedDescendantIterator
1852:
1853: /**
1854: * Iterator that returns the descendants of a given node.
1855: * I'm not exactly clear about this one... -sb
1856: */
1857: public class NthDescendantIterator extends DescendantIterator {
1858:
1859: /** The current nth position. */
1860: int _pos;
1861:
1862: /**
1863: * Constructor NthDescendantIterator
1864: *
1865: *
1866: * @param pos The nth position being requested.
1867: */
1868: public NthDescendantIterator(int pos) {
1869: _pos = pos;
1870: }
1871:
1872: /**
1873: * Get the next node in the iteration.
1874: *
1875: * @return The next node handle in the iteration, or END.
1876: */
1877: public int next() {
1878:
1879: // I'm not exactly clear yet what this is doing... -sb
1880: int node;
1881:
1882: while ((node = super .next()) != END) {
1883: node = makeNodeIdentity(node);
1884:
1885: int parent = _parent(node);
1886: int child = _firstch(parent);
1887: int pos = 0;
1888:
1889: do {
1890: int type = _type(child);
1891:
1892: if (ELEMENT_NODE == type)
1893: pos++;
1894: } while ((pos < _pos)
1895: && (child = _nextsib(child)) != END);
1896:
1897: if (node == child)
1898: return node;
1899: }
1900:
1901: return (END);
1902: }
1903: } // end of NthDescendantIterator
1904:
1905: /**
1906: * Class SingletonIterator.
1907: */
1908: public class SingletonIterator extends InternalAxisIteratorBase {
1909:
1910: /** (not sure yet what this is. -sb) (sc & sb remove final to compile in JDK 1.1.8) */
1911: private boolean _isConstant;
1912:
1913: /**
1914: * Constructor SingletonIterator
1915: *
1916: */
1917: public SingletonIterator() {
1918: this (Integer.MIN_VALUE, false);
1919: }
1920:
1921: /**
1922: * Constructor SingletonIterator
1923: *
1924: *
1925: * @param node The node handle to return.
1926: */
1927: public SingletonIterator(int node) {
1928: this (node, false);
1929: }
1930:
1931: /**
1932: * Constructor SingletonIterator
1933: *
1934: *
1935: * @param node the node handle to return.
1936: * @param constant (Not sure what this is yet. -sb)
1937: */
1938: public SingletonIterator(int node, boolean constant) {
1939: _currentNode = _startNode = node;
1940: _isConstant = constant;
1941: }
1942:
1943: /**
1944: * Set start to END should 'close' the iterator,
1945: * i.e. subsequent call to next() should return END.
1946: *
1947: * @param node Sets the root of the iteration.
1948: *
1949: * @return A DTMAxisIterator set to the start of the iteration.
1950: */
1951: public DTMAxisIterator setStartNode(int node) {
1952: //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1953: if (node == DTMDefaultBase.ROOTNODE)
1954: node = getDocument();
1955: if (_isConstant) {
1956: _currentNode = _startNode;
1957:
1958: return resetPosition();
1959: } else if (_isRestartable) {
1960: if (_currentNode == Integer.MIN_VALUE) {
1961: _currentNode = _startNode = node;
1962: }
1963:
1964: return resetPosition();
1965: }
1966:
1967: return this ;
1968: }
1969:
1970: /**
1971: * Resets the iterator to the last start node.
1972: *
1973: * @return A DTMAxisIterator, which may or may not be the same as this
1974: * iterator.
1975: */
1976: public DTMAxisIterator reset() {
1977:
1978: if (_isConstant) {
1979: _currentNode = _startNode;
1980:
1981: return resetPosition();
1982: } else {
1983: final boolean temp = _isRestartable;
1984:
1985: _isRestartable = true;
1986:
1987: setStartNode(_startNode);
1988:
1989: _isRestartable = temp;
1990: }
1991:
1992: return this ;
1993: }
1994:
1995: /**
1996: * Get the next node in the iteration.
1997: *
1998: * @return The next node handle in the iteration, or END.
1999: */
2000: public int next() {
2001:
2002: final int result = _currentNode;
2003:
2004: _currentNode = END;
2005:
2006: return returnNode(result);
2007: }
2008: } // end of SingletonIterator
2009:
2010: /**
2011: * Iterator that returns a given node only if it is of a given type.
2012: */
2013: public final class TypedSingletonIterator extends SingletonIterator {
2014:
2015: /** The extended type ID that was requested. */
2016: private final int _nodeType;
2017:
2018: /**
2019: * Constructor TypedSingletonIterator
2020: *
2021: *
2022: * @param nodeType The extended type ID being requested.
2023: */
2024: public TypedSingletonIterator(int nodeType) {
2025: _nodeType = nodeType;
2026: }
2027:
2028: /**
2029: * Get the next node in the iteration.
2030: *
2031: * @return The next node handle in the iteration, or END.
2032: */
2033: public int next() {
2034:
2035: //final int result = super.next();
2036: final int result = _currentNode;
2037: int nodeType = _nodeType;
2038:
2039: _currentNode = END;
2040:
2041: if (nodeType >= DTM.NTYPES) {
2042: if (getExpandedTypeID(result) == nodeType) {
2043: return returnNode(result);
2044: }
2045: } else {
2046: if (getNodeType(result) == nodeType) {
2047: return returnNode(result);
2048: }
2049: }
2050:
2051: return NULL;
2052: }
2053: } // end of TypedSingletonIterator
2054: }
|