/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.cursors.filters; import java.util.Iterator; import java.util.NoSuchElementException; import xxl.core.cursors.SecureDecoratorCursor; /** * A taker is a {@link SecureDecoratorCursor decorator-cursor} that returns the * next <code>number</code> elements of a given iteration. The * <code>number</code> of elements that should be delivered from the given * iteration is defined by the user as well as the input iteration the elements * should be taken from. * * <p><b>Implementation details:</b> The taker only contains further elements, * i.e., its <code>hasNext</code> method returns <code>true</code>, if the * underlying iteration has more elements and the number of elements returned * by the taker is lower than the given <code>number</code>. If * <code>next</code> is called the next element in the iteration is returned * and the <code>number</code> of elements to be delivered from the underlying * input iteration is decremented.</p> * * <p><b>Note:</b> If the input iteration is given by an object of the class * {@link java.util.Iterator}, i.e., it does not support the <code>peek</code> * operation, it is internally wrapped to a cursor.</p> * * <p><b>Example usage:</b> * <code><pre> * Taker<Integer> taker = new Taker<Integer>(new Enumerator(11), 5); * * taker.open(); * * while (taker.hasNext()) * System.out.print(taker.next() +"; "); * System.out.flush(); * * taker.close(); * </pre></code> * This instance of a taker delivers the first five elements of the given * {@link xxl.core.cursors.sources.Enumerator enumerator} which contains the * elements 0,...,10. So the output that results after consuming the entire * taker is: * <pre> * 0; 1; 2; 3; 4; * </pre></p> * * @param <E> the type of the elements returned by this iteration. * @see java.util.Iterator * @see xxl.core.cursors.Cursor * @see xxl.core.cursors.SecureDecoratorCursor */ public class Taker<E> extends SecureDecoratorCursor<E> { /** * The number of elements that still have to be delivered. */ protected long number; /** * The initial number of elements to be delivered. */ protected long initialNumber; /** * Creates a new taker. * * @param iterator the iterator which contains the elements. * @param number the number of elements which should be delivered from the * given iterator. */ public Taker(Iterator<E> iterator, long number) { super(iterator); this.number = initialNumber = number; } /** * Returns <code>true</code> if the iteration has more elements. (In other * words, returns <code>true</code> if <code>next</code> or * <code>peek</code> would return an element rather than throwing an * exception.) * * <p>This operation is implemented idempotent, i.e., consequent calls to * <code>hasNext</code> do not have any effect.</p> * * <p>In this case <code>hasNext</code> returns <code>true</code> if the * underlying iteration has more elements and the number of elements * returned by the taker is lower than the given <code>number</code>.</p> * * @return <code>true</code> if the cursor has more elements. * @throws IllegalStateException if the cursor is already closed when this * method is called. */ public boolean hasNext() throws IllegalStateException { return super.hasNext() && number>0; } /** * Returns the next element in the iteration. This element will be * accessible by some of the cursor's methods, e.g., <code>update</code> or * <code>remove</code>, until a call to <code>next</code> or * <code>peek</code> occurs. This is calling <code>next</code> or * <code>peek</code> proceeds the iteration and therefore its previous * element will not be accessible any more. * * <p>In this case the number of elements that still have to be returned is * decremented.</p> * * @return the next element in the iteration. * @throws IllegalStateException if the cursor is already closed when this * method is called. * @throws NoSuchElementException if the iteration has no more elements. */ public E next() throws IllegalStateException, NoSuchElementException { number--; return super.next(); } /** * Resets the cursor to its initial state such that the caller is able to * traverse the underlying data structure again without constructing a new * cursor (optional operation). The modifications, removes and updates * concerning the underlying data structure, are still persistent. * * <p>Note, that this operation is optional and might not work for all * cursors.</p> * * <p>In this case the input iteration has to be reset and the number of * elements that have to be returned by this taker has to be set to its * initial value.</p> * * @throws UnsupportedOperationException if the <code>reset</code> * operation is not supported by the cursor. */ public void reset () throws UnsupportedOperationException { super.reset(); number = initialNumber; } }