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 * An {@link java.util.Iterator Iterator} over an array of objects.
025 * <p>
026 * This iterator does not support {@link #remove}, as the object array cannot be
027 * structurally modified.
028 * <p>
029 * The iterator implements a {@link #reset} method, allowing the reset of the iterator
030 * back to the start if required.
031 *
032 * @param <E> the type of elements returned by this iterator.
033 * @since 3.0
034 */
035public class ObjectArrayIterator<E> implements ResettableIterator<E> {
036
037    /** The array */
038    final E[] array;
039    /** The start index to loop from */
040    final int startIndex;
041    /** The end index to loop to */
042    final int endIndex;
043    /** The current iterator index */
044    int index;
045
046    /**
047     * Constructs an ObjectArrayIterator that will iterate over the values in the
048     * specified array.
049     *
050     * @param array the array to iterate over
051     * @throws NullPointerException if {@code array} is {@code null}
052     */
053    public ObjectArrayIterator(final E... array) {
054        this(array, 0, array.length);
055    }
056
057    /**
058     * Constructs an ObjectArrayIterator that will iterate over the values in the
059     * specified array from a specific start index.
060     *
061     * @param array  the array to iterate over
062     * @param start  the index to start iterating at
063     * @throws NullPointerException if {@code array} is {@code null}
064     * @throws IndexOutOfBoundsException if the start index is out of bounds
065     */
066    public ObjectArrayIterator(final E[] array, final int start) {
067        this(array, start, array.length);
068    }
069
070    /**
071     * Constructs an ObjectArrayIterator that will iterate over a range of values
072     * in the specified array.
073     *
074     * @param array  the array to iterate over
075     * @param start  the index to start iterating at
076     * @param end  the index (exclusive) to finish iterating at
077     * @throws IndexOutOfBoundsException if the start or end index is out of bounds
078     * @throws IllegalArgumentException if end index is before the start
079     * @throws NullPointerException if {@code array} is {@code null}
080     */
081    public ObjectArrayIterator(final E[] array, final int start, final int end) {
082        if (start < 0) {
083            throw new ArrayIndexOutOfBoundsException("Start index must not be less than zero");
084        }
085        if (end > array.length) {
086            throw new ArrayIndexOutOfBoundsException("End index must not be greater than the array length");
087        }
088        if (start > array.length) {
089            throw new ArrayIndexOutOfBoundsException("Start index must not be greater than the array length");
090        }
091        if (end < start) {
092            throw new IllegalArgumentException("End index must not be less than start index");
093        }
094        this.array = array;
095        this.startIndex = start;
096        this.endIndex = end;
097        this.index = start;
098    }
099
100    /**
101     * Gets the array that this iterator is iterating over.
102     *
103     * @return the array this iterator iterates over
104     */
105    public E[] getArray() {
106        return this.array;
107    }
108
109    /**
110     * Gets the end index to loop to.
111     *
112     * @return the end index
113     */
114    public int getEndIndex() {
115        return this.endIndex;
116    }
117
118    /**
119     * Gets the start index to loop from.
120     *
121     * @return the start index
122     */
123    public int getStartIndex() {
124        return this.startIndex;
125    }
126
127    /**
128     * Returns true if there are more elements to return from the array.
129     *
130     * @return true if there is a next element to return
131     */
132    @Override
133    public boolean hasNext() {
134        return this.index < this.endIndex;
135    }
136
137    /**
138     * Returns the next element in the array.
139     *
140     * @return the next element in the array
141     * @throws NoSuchElementException if all the elements in the array
142     *    have already been returned
143     */
144    @Override
145    public E next() {
146        if (!hasNext()) {
147            throw new NoSuchElementException();
148        }
149        return this.array[this.index++];
150    }
151
152    /**
153     * Throws {@link UnsupportedOperationException}.
154     *
155     * @throws UnsupportedOperationException always
156     */
157    @Override
158    public void remove() {
159        throw new UnsupportedOperationException("remove() method is not supported for an ObjectArrayIterator");
160    }
161
162    /**
163     * Resets the iterator back to the start index.
164     */
165    @Override
166    public void reset() {
167        this.index = this.startIndex;
168    }
169
170}