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     * An {@link Iterator} over an array of objects.
026     * <p>
027     * This iterator does not support {@link #remove}, as the object array cannot be
028     * structurally modified.
029     * <p>
030     * The iterator implements a {@link #reset} method, allowing the reset of the iterator
031     * back to the start if required.
032     *
033     * @since Commons Collections 3.0
034     * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
035     * 
036     * @author James Strachan
037     * @author Mauricio S. Moura
038     * @author Michael A. Smith
039     * @author Neil O'Toole
040     * @author Stephen Colebourne
041     * @author Phil Steitz
042     */
043    public class ObjectArrayIterator
044            implements Iterator, ResettableIterator {
045    
046        /** The array */
047        protected Object[] array = null;
048        /** The start index to loop from */
049        protected int startIndex = 0;
050        /** The end index to loop to */
051        protected int endIndex = 0;
052        /** The current iterator index */
053        protected int index = 0;
054    
055        /**
056         * Constructor for use with <code>setArray</code>.
057         * <p>
058         * Using this constructor, the iterator is equivalent to an empty iterator
059         * until {@link #setArray} is  called to establish the array to iterate over.
060         */
061        public ObjectArrayIterator() {
062            super();
063        }
064    
065        /**
066         * Constructs an ObjectArrayIterator that will iterate over the values in the
067         * specified array.
068         *
069         * @param array the array to iterate over
070         * @throws NullPointerException if <code>array</code> is <code>null</code>
071         */
072        public ObjectArrayIterator(Object[] array) {
073            this(array, 0, array.length);
074        }
075    
076        /**
077         * Constructs an ObjectArrayIterator that will iterate over the values in the
078         * specified array from a specific start index.
079         *
080         * @param array  the array to iterate over
081         * @param start  the index to start iterating at
082         * @throws NullPointerException if <code>array</code> is <code>null</code>
083         * @throws IndexOutOfBoundsException if the start index is out of bounds
084         */
085        public ObjectArrayIterator(Object array[], int start) {
086            this(array, start, array.length);
087        }
088    
089        /**
090         * Construct an ObjectArrayIterator that will iterate over a range of values 
091         * in the specified array.
092         *
093         * @param array  the array to iterate over
094         * @param start  the index to start iterating at
095         * @param end  the index (exclusive) to finish iterating at
096         * @throws IndexOutOfBoundsException if the start or end index is out of bounds
097         * @throws IllegalArgumentException if end index is before the start
098         * @throws NullPointerException if <code>array</code> is <code>null</code>
099         */
100        public ObjectArrayIterator(Object array[], int start, int end) {
101            super();
102            if (start < 0) {
103                throw new ArrayIndexOutOfBoundsException("Start index must not be less than zero");
104            }
105            if (end > array.length) {
106                throw new ArrayIndexOutOfBoundsException("End index must not be greater than the array length");
107            }
108            if (start > array.length) {
109                throw new ArrayIndexOutOfBoundsException("Start index must not be greater than the array length");
110            }
111            if (end < start) {
112                throw new IllegalArgumentException("End index must not be less than start index");
113            }
114            this.array = array;
115            this.startIndex = start;
116            this.endIndex = end;
117            this.index = start;
118        }
119    
120        // Iterator interface
121        //-------------------------------------------------------------------------
122    
123        /**
124         * Returns true if there are more elements to return from the array.
125         *
126         * @return true if there is a next element to return
127         */
128        public boolean hasNext() {
129            return (this.index < this.endIndex);
130        }
131    
132        /**
133         * Returns the next element in the array.
134         *
135         * @return the next element in the array
136         * @throws NoSuchElementException if all the elements in the array
137         *    have already been returned
138         */
139        public Object next() {
140            if (hasNext() == false) {
141                throw new NoSuchElementException();
142            }
143            return this.array[this.index++];
144        }
145    
146        /**
147         * Throws {@link UnsupportedOperationException}.
148         *
149         * @throws UnsupportedOperationException always
150         */
151        public void remove() {
152            throw new UnsupportedOperationException("remove() method is not supported for an ObjectArrayIterator");
153        }
154    
155        // Properties
156        //-------------------------------------------------------------------------
157    
158        /**
159         * Gets the array that this iterator is iterating over. 
160         *
161         * @return the array this iterator iterates over, or <code>null</code> if
162         * the no-arg constructor was used and {@link #setArray} has never
163         * been called with a valid array.
164         */
165        public Object[] getArray() {
166            return this.array;
167        }
168    
169        /**
170         * Sets the array that the ArrayIterator should iterate over.
171         * <p>
172         * This method may only be called once, otherwise an IllegalStateException
173         * will occur.
174         * <p>
175         * The {@link #reset} method can be used to reset the iterator if required.
176         *
177         * @param array  the array that the iterator should iterate over
178         * @throws IllegalStateException if the <code>array</code> was set in the constructor
179         * @throws NullPointerException if <code>array</code> is <code>null</code>
180         */
181        public void setArray(Object[] array) {
182            if (this.array != null) {
183                throw new IllegalStateException("The array to iterate over has already been set");
184            }
185            this.array = array;
186            this.startIndex = 0;
187            this.endIndex = array.length;
188            this.index = 0;
189        }
190    
191        /**
192         * Gets the start index to loop from.
193         * 
194         * @return the start index
195         */
196        public int getStartIndex() {
197            return this.startIndex;
198        }
199    
200        /**
201         * Gets the end index to loop to.
202         * 
203         * @return the end index
204         */
205        public int getEndIndex() {
206            return this.endIndex;
207        }
208    
209        /**
210         * Resets the iterator back to the start index.
211         */
212        public void reset() {
213            this.index = this.startIndex;
214        }
215    
216    }