001: package net.sf.saxon.expr;
002:
003: import net.sf.saxon.om.ArrayIterator;
004: import net.sf.saxon.om.Item;
005: import net.sf.saxon.om.LookaheadIterator;
006: import net.sf.saxon.om.SequenceIterator;
007: import net.sf.saxon.trans.XPathException;
008:
009: /**
010: * A PositionIterator selects a subsequence of a sequence
011: */
012:
013: public class PositionIterator implements SequenceIterator,
014: LookaheadIterator {
015:
016: /**
017: * Static factory method. Creates a PositionIterator, unless the base Iterator is an
018: * ArrayIterator, in which case it optimizes by creating a new ArrayIterator directly over the
019: * underlying array. This optimization is important when doing recursion over a node-set using
020: * repeated calls of $nodes[position()>1]
021: * @param base An iteration of the items to be filtered
022: * @param min The position of the first item to be included (base 1)
023: * @param max The position of the last item to be included (base 1)
024: */
025:
026: public static SequenceIterator make(SequenceIterator base, int min,
027: int max) throws XPathException {
028: // System.err.println("PositionIterator.make base=" + base.getClass() + " min=" + min + " max=" + max);
029: if (base instanceof ArrayIterator) {
030: return ((ArrayIterator) base).makeSliceIterator(min, max);
031: } else {
032: return new PositionIterator(base, min, max);
033: }
034: }
035:
036: private SequenceIterator base;
037: private int position = 0;
038: private int min = 1;
039: private int max = Integer.MAX_VALUE;
040: private Item nextItem = null;
041: private Item current = null;
042:
043: /**
044: * Private Constructor: use the factory method instead!
045: * @param base An iteration of the items to be filtered
046: * @param min The position of the first item to be included
047: * @param max The position of the last item to be included
048: */
049:
050: private PositionIterator(SequenceIterator base, int min, int max)
051: throws XPathException {
052: this .base = base;
053: this .min = min;
054: if (min < 1)
055: min = 1;
056: this .max = max;
057: if (max < min) {
058: nextItem = null;
059: return;
060: }
061: int i = 1;
062: while (i++ <= min) {
063: nextItem = base.next();
064: if (nextItem == null) {
065: break;
066: }
067: }
068: current = nextItem;
069: }
070:
071: /**
072: * Test whether there are any more items available in the enumeration
073: */
074:
075: public boolean hasNext() {
076: return nextItem != null;
077: }
078:
079: /**
080: * Get the next item if there is one
081: */
082:
083: public Item next() throws XPathException {
084: if (nextItem == null) {
085: current = null;
086: position = -1;
087: return null;
088: }
089: current = nextItem;
090: position++;
091: if (base.position() < max) {
092: nextItem = base.next();
093: } else {
094: nextItem = null;
095: }
096: return current;
097: }
098:
099: public Item current() {
100: return current;
101: }
102:
103: public int position() {
104: return position;
105: }
106:
107: /**
108: * Get another iterator to return the same nodes
109: */
110:
111: public SequenceIterator getAnother() throws XPathException {
112: return new PositionIterator(base.getAnother(), min, max);
113: }
114:
115: /**
116: * Get properties of this iterator, as a bit-significant integer.
117: *
118: * @return the properties of this iterator. This will be some combination of
119: * properties such as {@link #GROUNDED}, {@link #LAST_POSITION_FINDER},
120: * and {@link #LOOKAHEAD}. It is always
121: * acceptable to return the value zero, indicating that there are no known special properties.
122: * It is acceptable for the properties of the iterator to change depending on its state.
123: */
124:
125: public int getProperties() {
126: return LOOKAHEAD;
127: }
128:
129: }
130:
131: //
132: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
133: // you may not use this file except in compliance with the License. You may obtain a copy of the
134: // License at http://www.mozilla.org/MPL/
135: //
136: // Software distributed under the License is distributed on an "AS IS" basis,
137: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
138: // See the License for the specific language governing rights and limitations under the License.
139: //
140: // The Original Code is: all this file.
141: //
142: // The Initial Developer of the Original Code is Michael H. Kay.
143: //
144: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
145: //
146: // Contributor(s): none.
147: //
|