package de.invesdwin.util.collections.iterable;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.annotation.concurrent.NotThreadSafe;
import de.invesdwin.util.error.FastNoSuchElementException;
import de.invesdwin.util.lang.Reflections;
@NotThreadSafe
public final class WrapperCloseableIterator<E> implements ICloseableIterator<E> {
private Iterator<? extends E> delegate;
private WrapperCloseableIterator(final Iterator<? extends E> delegate) {
this.delegate = delegate;
}
@Override
public boolean hasNext() {
final boolean hasNext = delegate.hasNext();
if (!hasNext) {
close();
}
return hasNext;
}
@Override
public E next() {
try {
return delegate.next();
} catch (final NoSuchElementException e) {
close();
throw FastNoSuchElementException.maybeReplace(e, "WrapperCloseableIterator: next threw");
}
}
@Override
public void remove() {
delegate.remove();
}
@Override
public void close() {
if (!(delegate instanceof EmptyCloseableIterator)) {
if (delegate instanceof Closeable) {
final Closeable cDelegate = (Closeable) delegate;
try {
cDelegate.close();
} catch (final IOException e) {
throw new RuntimeException(e);
}
} else {
final Method close = Reflections.findMethod(delegate.getClass(), "close");
if (close != null) {
Reflections.invokeMethod(close, delegate);
}
}
}
delegate = EmptyCloseableIterator.getInstance();
}
/**
* Please use WrapperCloseableIterable.maybeWrap instead if possible because it does some performance optimization
*/
@Deprecated
@SuppressWarnings("unchecked")
public static <T> ICloseableIterator<T> maybeWrap(final Iterator<? extends T> iterator) {
if (iterator instanceof ICloseableIterator) {
return (ICloseableIterator<T>) iterator;
} else {
return new WrapperCloseableIterator<T>(iterator);
}
}
}