package ch.akuhn.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
public abstract class Providable<E> implements Iterable<E>, Iterator<E>, Cloneable {
private enum State {
DONE, EMPTY, FAIL, READY, UNINITIALIZED
}
private E next = null;
private State state = State.UNINITIALIZED;
private final boolean computeNext() {
state = State.FAIL;
next = provide();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
public final E done() {
state = State.DONE;
return null;
}
public final boolean hasNext() {
if (state == State.EMPTY) return computeNext();
if (state == State.DONE) return false;
if (state == State.READY) return true;
throw new IllegalStateException(state.toString());
}
public abstract void initialize();
public final Iterator<E> iterator() {
Providable<E> clone = maybeClone();
clone.state = State.FAIL;
clone.initialize();
clone.state = State.EMPTY;
return clone;
}
@SuppressWarnings("unchecked")
private final Providable<E> maybeClone() {
if (state == State.UNINITIALIZED) return this;
try {
return (Providable<E>) super.clone();
} catch (CloneNotSupportedException ex) {
throw Throw.exception(ex);
}
}
public final E next() {
if (!hasNext()) throw new NoSuchElementException();
state = State.EMPTY;
return next;
}
public abstract E provide();
public final void remove() {
throw new UnsupportedOperationException();
}
}