001: package net.sf.saxon.om;
002:
003: import net.sf.saxon.trans.XPathException;
004:
005: /**
006: * A closing iterator returns the items delivered by an underlying iterator unchanged, and
007: * calls a user-supplied function when the underlying iterator hits the end of the sequence.
008: */
009:
010: public class ClosingIterator implements SequenceIterator {
011:
012: private SequenceIterator base;
013: private ClosingAction closingAction;
014:
015: public ClosingIterator(SequenceIterator base,
016: ClosingAction closingAction) {
017: this .base = base;
018: this .closingAction = closingAction;
019: }
020:
021: /**
022: * Get the current value in the sequence (the one returned by the
023: * most recent call on next()). This will be null before the first
024: * call of next(). This method does not change the state of the iterator.
025: *
026: * @return the current item, the one most recently returned by a call on
027: * next(). Returns null if next() has not been called, or if the end
028: * of the sequence has been reached.
029: * @since 8.4
030: */
031:
032: public Item current() {
033: return base.current();
034: }
035:
036: /**
037: * Get another SequenceIterator that iterates over the same items as the original,
038: * but which is repositioned at the start of the sequence.
039: * <p/>
040: * This method allows access to all the items in the sequence without disturbing the
041: * current position of the iterator. Internally, its main use is in evaluating the last()
042: * function.
043: * <p/>
044: * This method does not change the state of the iterator.
045: *
046: * @return a SequenceIterator that iterates over the same items,
047: * positioned before the first item
048: * @throws net.sf.saxon.trans.XPathException
049: * if any error occurs
050: * @since 8.4
051: */
052:
053: public SequenceIterator getAnother() throws XPathException {
054: return new ClosingIterator(base.getAnother(), closingAction);
055: }
056:
057: /**
058: * Get properties of this iterator, as a bit-significant integer.
059: *
060: * @return the properties of this iterator. This will be some combination of
061: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
062: * and {@link LOOKAHEAD}. It is always
063: * acceptable to return the value zero, indicating that there are no known special properties.
064: * It is acceptable for the properties of the iterator to change depending on its state.
065: * @since 8.6
066: */
067:
068: public int getProperties() {
069: return 0;
070: }
071:
072: /**
073: * Get the next item in the sequence. This method changes the state of the
074: * iterator, in particular it affects the result of subsequent calls of
075: * position() and current().
076: *
077: * @return the next item, or null if there are no more items. Once a call
078: * on next() has returned null, no further calls should be made. The preferred
079: * action for an iterator if subsequent calls on next() are made is to return
080: * null again, and all implementations within Saxon follow this rule.
081: * @throws net.sf.saxon.trans.XPathException
082: * if an error occurs retrieving the next item
083: * @since 8.4
084: */
085:
086: public Item next() throws XPathException {
087: int count = base.position();
088: Item next = base.next();
089: if (next == null) {
090: closingAction.close(base, count);
091: }
092: return next;
093: }
094:
095: /**
096: * Get the current position. This will usually be zero before the first call
097: * on next(), otherwise it will be the number of times that next() has
098: * been called. Once next() has returned null, the preferred action is
099: * for subsequent calls on position() to return -1, but not all existing
100: * implementations follow this practice. (In particular, the EmptyIterator
101: * is stateless, and always returns 0 as the value of position(), whether
102: * or not next() has been called.)
103: * <p/>
104: * This method does not change the state of the iterator.
105: *
106: * @return the current position, the position of the item returned by the
107: * most recent call of next(). This is 1 after next() has been successfully
108: * called once, 2 after it has been called twice, and so on. If next() has
109: * never been called, the method returns zero. If the end of the sequence
110: * has been reached, the value returned will always be <= 0; the preferred
111: * value is -1.
112: * @since 8.4
113: */
114:
115: public int position() {
116: return base.position();
117: }
118: }
119:
120: //
121: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
122: // you may not use this file except in compliance with the License. You may obtain a copy of the
123: // License at http://www.mozilla.org/MPL/
124: //
125: // Software distributed under the License is distributed on an "AS IS" basis,
126: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
127: // See the License for the specific language governing rights and limitations under the License.
128: //
129: // The Original Code is: all this file.
130: //
131: // The Initial Developer of the Original Code is Michael H. Kay
132: //
133: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
134: //
135: // Contributor(s): none.
136: //
|