    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.collections4.iterators;
    018
    019import java.util.NoSuchElementException;
    020
    021import org.apache.commons.collections4.ResettableIterator;
    022
    023/**
    024 * {@code SingletonIterator} is an {@link java.util.Iterator} over a single
    025 * object instance.
    026 *
    027 * @param <E> the type of elements returned by this iterator.
    028 * @since 2.0
    029 */
    030public class SingletonIterator<E>
    031        implements ResettableIterator<E> {
    032
    033    /** Whether remove is allowed */
    034    private final boolean removeAllowed;
    035    /** Is the cursor before the first element */
    036    private boolean beforeFirst = true;
    037    /** Has the element been removed */
    038    private boolean removed;
    039    /** The object */
    040    private E object;
    041
    042    /**
    043     * Constructs a new {@code SingletonIterator} where {@code remove}
    044     * is a permitted operation.
    045     *
    046     * @param object  the single object to return from the iterator
    047     */
    048    public SingletonIterator(final E object) {
    049        this(object, true);
    050    }
    051
    052    /**
    053     * Constructs a new {@code SingletonIterator} optionally choosing if
    054     * {@code remove} is a permitted operation.
    055     *
    056     * @param object  the single object to return from the iterator
    057     * @param removeAllowed  true if remove is allowed
    058     * @since 3.1
    059     */
    060    public SingletonIterator(final E object, final boolean removeAllowed) {
    061        this.object = object;
    062        this.removeAllowed = removeAllowed;
    063    }
    064
    065    /**
    066     * Is another object available from the iterator?
    067     * <p>
    068     * This returns true if the single object hasn't been returned yet.
    069     *
    070     * @return true if the single object hasn't been returned yet
    071     */
    072    @Override
    073    public boolean hasNext() {
    074        return beforeFirst && !removed;
    075    }
    076
    077    /**
    078     * Gets the next object from the iterator.
    079     * <p>
    080     * This returns the single object if it hasn't been returned yet.
    081     *
    082     * @return the single object
    083     * @throws NoSuchElementException if the single object has already
    084     *    been returned
    085     */
    086    @Override
    087    public E next() {
    088        if (!beforeFirst || removed) {
    089            throw new NoSuchElementException();
    090        }
    091        beforeFirst = false;
    092        return object;
    093    }
    094
    095    /**
    096     * Remove the object from this iterator.
    097     *
    098     * @throws IllegalStateException if the {@code next} method has not
    099     *        yet been called, or the {@code remove} method has already
    100     *        been called after the last call to the {@code next}
    101     *        method.
    102     * @throws UnsupportedOperationException if remove is not supported
    103     */
    104    @Override
    105    public void remove() {
    106        if (!removeAllowed) {
    107            throw new UnsupportedOperationException();
    108        }
    109        if (removed || beforeFirst) {
    110            throw new IllegalStateException();
    111        }
    112        object = null;
    113        removed = true;
    114    }
    115
    116    /**
    117     * Reset the iterator to the start.
    118     */
    119    @Override
    120    public void reset() {
    121        beforeFirst = true;
    122    }
    123
    124}