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