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     */
017    package org.apache.commons.collections.iterators;
018    
019    import java.util.Iterator;
020    import java.util.NoSuchElementException;
021    
022    import org.apache.commons.collections.ResettableIterator;
023    
024    /** 
025     * <code>SingletonIterator</code> is an {@link Iterator} over a single 
026     * object instance.
027     *
028     * @since Commons Collections 2.0
029     * @version $Revision: 647116 $ $Date: 2008-04-11 12:23:08 +0100 (Fri, 11 Apr 2008) $
030     * 
031     * @author James Strachan
032     * @author Stephen Colebourne
033     * @author Rodney Waldhoff
034     */
035    public class SingletonIterator
036            implements Iterator, ResettableIterator {
037    
038        /** Whether remove is allowed */
039        private final boolean removeAllowed;
040        /** Is the cursor before the first element */
041        private boolean beforeFirst = true;
042        /** Has the element been removed */
043        private boolean removed = false;
044        /** The object */
045        private Object object;
046    
047        /**
048         * Constructs a new <code>SingletonIterator</code> where <code>remove</code>
049         * is a permitted operation.
050         *
051         * @param object  the single object to return from the iterator
052         */
053        public SingletonIterator(Object object) {
054            this(object, true);
055        }
056    
057        /**
058         * Constructs a new <code>SingletonIterator</code> optionally choosing if
059         * <code>remove</code> is a permitted operation.
060         *
061         * @param object  the single object to return from the iterator
062         * @param removeAllowed  true if remove is allowed
063         * @since Commons Collections 3.1
064         */
065        public SingletonIterator(Object object, boolean removeAllowed) {
066            super();
067            this.object = object;
068            this.removeAllowed = removeAllowed;
069        }
070    
071        //-----------------------------------------------------------------------
072        /**
073         * Is another object available from the iterator?
074         * <p>
075         * This returns true if the single object hasn't been returned yet.
076         * 
077         * @return true if the single object hasn't been returned yet
078         */
079        public boolean hasNext() {
080            return (beforeFirst && !removed);
081        }
082    
083        /**
084         * Get the next object from the iterator.
085         * <p>
086         * This returns the single object if it hasn't been returned yet.
087         *
088         * @return the single object
089         * @throws NoSuchElementException if the single object has already 
090         *    been returned
091         */
092        public Object next() {
093            if (!beforeFirst || removed) {
094                throw new NoSuchElementException();
095            }
096            beforeFirst = false;
097            return object;
098        }
099    
100        /**
101         * Remove the object from this iterator.
102         * 
103         * @throws IllegalStateException if the <tt>next</tt> method has not
104         *        yet been called, or the <tt>remove</tt> method has already
105         *        been called after the last call to the <tt>next</tt>
106         *        method.
107         * @throws UnsupportedOperationException if remove is not supported
108         */
109        public void remove() {
110            if (removeAllowed) {
111                if (removed || beforeFirst) {
112                    throw new IllegalStateException();
113                } else {
114                    object = null;
115                    removed = true;
116                }
117            } else {
118                throw new UnsupportedOperationException();
119            }
120        }
121        
122        /**
123         * Reset the iterator to the start.
124         */
125        public void reset() {
126            beforeFirst = true;
127        }
128        
129    }