package org.xbib.datastructures.immutable;

import java.util.Iterator;
import java.util.Objects;

/**
 * An iterator that does not support {@link #remove}.
 *
 * <p>{@code UnmodifiableIterator} is used primarily in conjunction with implementations of {@link
 * ImmutableCollection}, such as {@link ImmutableList}. You can, however, convert an existing
 * iterator to an {@code UnmodifiableIterator} using {@link #unmodifiableIterator}.
 */
public abstract class UnmodifiableIterator<E extends Object> implements Iterator<E> {
    /**
     * Constructor for use by subclasses.
     */
    protected UnmodifiableIterator() {
    }

    /**
     * Guaranteed to throw an exception and leave the underlying data unmodified.
     *
     * @throws UnsupportedOperationException always
     */
    @Override
    public final void remove() {
        throw new UnsupportedOperationException();
    }

    public static <T extends Object> UnmodifiableIterator<T> unmodifiableIterator(Iterator<? extends T> iterator) {
        Objects.requireNonNull(iterator);
        if (iterator instanceof UnmodifiableIterator) {
            @SuppressWarnings("unchecked") // Since it's unmodifiable, the covariant cast is safe
            UnmodifiableIterator<T> result = (UnmodifiableIterator<T>) iterator;
            return result;
        }
        return new UnmodifiableIterator<T>() {
            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public T next() {
                return iterator.next();
            }
        };
    }
}
