/*
 * Copyright (C) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject.internal;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * This class provides a skeletal implementation of the {@code Iterator}
 * interface, to make this interface easier to implement for certain types of
 * data sources.
 *
 * <p>{@code Iterator} requires its implementations to support querying the
 * end-of-data status without changing the iterator's state, using the {@link
 * #hasNext} method. But many data sources, such as {@link
 * java.io.Reader#read()}), do not expose this information; the only way to
 * discover whether there is any data left is by trying to retrieve it. These
 * types of data sources are ordinarily difficult to write iterators for. But
 * using this class, one must implement only the {@link #computeNext} method,
 * and invoke the {@link #endOfData} method when appropriate.
 *
 * <p>Another example is an iterator that skips over null elements in a backing
 * iterator. This could be implemented as: <pre>   {@code
 *
 *   public static Iterator<String> skipNulls(final Iterator<String> in) {
 *     return new AbstractIterator<String>() {
 *       protected String computeNext() {
 *         while (in.hasNext()) {
 *           String s = in.next();
 *           if (s != null) {
 *             return s;
 *           }
 *         }
 *         return endOfData();
 *       }
 *     };
 *   }}</pre>
 *
 * This class supports iterators that include null elements. The {@link
 * #remove()} method throws an {@link UnsupportedOperationException}, but
 * this can be overridden to support removal.
 *
 * @author Kevin Bourrillion
 */
public abstract class AbstractIterator<T> implements Iterator<T> {
  private State state = State.NOT_READY;

  private enum State {
    /** We have computed the next element and haven't returned it yet. */
    READY,

    /** We haven't yet computed or have already returned the element. */
    NOT_READY,

    /** We have reached the end of the data and are finished. */
    DONE,

    /** We've suffered an exception and are kaput. */
    FAILED,
  }

  private T next;

  /**
   * Returns the next element. <b>Note:</b> the implementation must call {@link
   * #endOfData} when there are no elements left in the iteration. Failure to do
   * so could result in an infinite loop.
   *
   * <p>The initial invocation of {@link #hasNext()} or {@link #next()} calls
   * this method, as does the first invocation of {@code hasNext} or
   * {@code next} following each successful call to {@code next}. Once the
   * implementation either invokes {@code endOfData} or throws an exception,
   * {@code computeNext} is guaranteed to never be called again.
   *
   * <p>If this method throws an exception, it will propagate outward to the
   * {@code hasNext()} or {@code next()} invocation that invoked this method.
   * Any further attempts to use the iterator will result in an {@link
   * IllegalStateException}.
   *
   * @return the next element if there was one. If {@code endOfData} was called
   *     during execution, the return value will be ignored.
   * @throws RuntimeException if any unrecoverable error happens. This exception
   *     will propagate outward to the {@code hasNext()}, {@code next()}, or
   *     {@code peek()} invocation that invoked this method. Any further
   *     attempts to use the iterator will result in an
   *     {@link IllegalStateException}.
   */
  protected abstract T computeNext();

  /**
   * Implementations of {@code computeNext} <b>must</b> invoke this method when
   * there are no elements left in the iteration.
   *
   * @return {@code null}; a convenience so your {@link #computeNext}
   *     implementation can use the simple statement {@code return endOfData();}
   */
  protected final T endOfData() {
    state = State.DONE;
    return null;
  }

  public boolean hasNext() {
    Preconditions.checkState(state != State.FAILED);
    switch (state) {
      case DONE:
        return false;
      case READY:
        return true;
      default:
    }
    return tryToComputeNext();
  }

  private boolean tryToComputeNext() {
    state = State.FAILED; // temporary pessimism
    next = computeNext();
    if (state != State.DONE) {
      state = State.READY;
      return true;
    }
    return false;
  }

  public T next() {
    if (!hasNext()) {
      throw new NoSuchElementException();
    }
    state = State.NOT_READY;
    return next;
  }

  /**
   * This method is not supported.
   */
  public void remove() {
    throw new UnsupportedOperationException();
  }
}
