/*
* (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Hewlett-Packard
* Development Company, LP All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. The name of the author may not
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package net.enilink.commons.iterator;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Creates a sub-Iterator by filtering. This class should not be used directly
* any more; the subclasses FilterKeepIterator and FilterDropIterator should be
* used instead.
*
*/
public class FilterIterator<T> extends WrappedIterator<T> {
protected final Filter<? super T> f;
protected T current;
protected boolean canRemove;
protected boolean hasCurrent;
/**
* Initialises a FilterIterator with its filter and base.
*
* @param fl
* An object is included if it is accepted by this Filter.
* @param e
* The base Iterator.
*/
public FilterIterator(Filter<? super T> f, Iterator<? extends T> e) {
super(e);
this.f = f;
}
/**
* Answer true iff there is at least one more acceptable object. [Stores
* reference into <code>current</code>, sets <code>canRemove</code> false;
* answer preserved in `hasCurrent`]
*/
synchronized public boolean hasNext() {
while (!hasCurrent && super.hasNext()) {
hasCurrent = accept(current = super.next());
}
canRemove = false;
return hasCurrent;
}
/**
* Overridden in Drop/Keep as appropriate. Answer true if the object is to
* be kept in the output, false if it is to be dropped.
*/
protected boolean accept(T x) {
return f.accept(x);
}
/**
* Remove the current member from the underlying iterator. Legal only after
* a .next() but before any subsequent .hasNext(), because that may advance
* the underlying iterator.
*/
synchronized public void remove() {
if (!canRemove)
throw new IllegalStateException(
"FilterIterators do not permit calls to hasNext between calls to next and remove.");
super.remove();
}
/**
* Answer the next acceptable object from the base iterator. The redundant
* test of `hasCurrent` appears to make a detectable speed difference.
* Crazy.
*/
synchronized public T next() {
if (hasCurrent || hasNext()) {
canRemove = true;
hasCurrent = false;
return current;
}
throw new NoSuchElementException();
}
}