package com.bigdata.striterator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import cutthecrap.utils.striterators.ICloseableIterator;
/**
* Allows pushback of the most recently visited element onto the iterator.
* <p>
* Note: There is no corresponding {@link IFilter} pattern for this class since
* you need the interface offered by the {@link PushbackIterator} in order to
* use pushback.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
* @version $Id$
* @param <E>
*/
public class PushbackIterator<E> implements Iterator<E>, ICloseableIterator<E> {
private final Iterator<E> src;
/**
* The most recent element visited by the iterator.
*/
private E current;
/**
* When non-<code>null</code>, this element was pushed back and is
* the next element to be visited.
*/
private E buffer;
public PushbackIterator(final Iterator<E> src) {
if (src == null)
throw new IllegalArgumentException();
this.src = src;
}
@Override
public boolean hasNext() {
return buffer != null || src.hasNext();
}
@Override
public E next() {
if (!hasNext())
throw new NoSuchElementException();
final E tmp;
if (buffer != null) {
tmp = buffer;
buffer = null;
} else {
tmp = src.next();
}
current = tmp;
return tmp;
}
/**
* Push the value onto the internal buffer. It will be returned by the
* next call to {@link #next()}.
*
* @param value
* The value.
*
* @throws IllegalStateException
* if there is already a value pushed back.
*/
public void pushback() {
if (buffer != null)
throw new IllegalStateException();
// pushback the last visited element.
buffer = current;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void close() {
if (src instanceof ICloseableIterator) {
((ICloseableIterator<E>) src).close();
}
}
}