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.logging.log4j.core.util;
018
019import java.util.Iterator;
020import java.util.NoSuchElementException;
021
022/**
023 * An {@link java.util.Iterator Iterator} over an array of objects.
024 * <p>
025 * This iterator does not support {@link #remove}, as the object array cannot be
026 * structurally modified.
027 * <p>
028 * The iterator implements a {@link #reset} method, allowing the reset of the iterator
029 * back to the start if required.
030 *
031 * @param <E> the type to iterate over
032 * @since 3.0
033 * @version $Id: ObjectArrayIterator.java 1734648 2016-03-11 23:51:22Z ggregory $
034 */
035public class ObjectArrayIterator<E> implements /*Resettable*/ Iterator<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 = 0;
045
046    //-------------------------------------------------------------------------
047    /**
048     * Constructs an ObjectArrayIterator that will iterate over the values in the
049     * specified array.
050     *
051     * @param array the array to iterate over
052     * @throws NullPointerException if <code>array</code> is <code>null</code>
053     */
054    @SafeVarargs
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</code> is <code>null</code>
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     * Construct 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</code> is <code>null</code>
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        this.startIndex = start;
098        this.endIndex = end;
099        this.index = start;
100    }
101
102    // Iterator interface
103    //-------------------------------------------------------------------------
104
105    /**
106     * Returns true if there are more elements to return from the array.
107     *
108     * @return true if there is a next element to return
109     */
110    @Override
111    public boolean hasNext() {
112        return this.index < this.endIndex;
113    }
114
115    /**
116     * Returns the next element in the array.
117     *
118     * @return the next element in the array
119     * @throws NoSuchElementException if all the elements in the array
120     *    have already been returned
121     */
122    @Override
123    public E next() {
124        if (hasNext() == false) {
125            throw new NoSuchElementException();
126        }
127        return this.array[this.index++];
128    }
129
130    /**
131     * Throws {@link UnsupportedOperationException}.
132     *
133     * @throws UnsupportedOperationException always
134     */
135    @Override
136    public void remove() {
137        throw new UnsupportedOperationException("remove() method is not supported for an ObjectArrayIterator");
138    }
139
140    // Properties
141    //-------------------------------------------------------------------------
142
143    /**
144     * Gets the array that this iterator is iterating over.
145     *
146     * @return the array this iterator iterates over
147     */
148    public E[] getArray() {
149        return this.array;
150    }
151
152    /**
153     * Gets the start index to loop from.
154     *
155     * @return the start index
156     */
157    public int getStartIndex() {
158        return this.startIndex;
159    }
160
161    /**
162     * Gets the end index to loop to.
163     *
164     * @return the end index
165     */
166    public int getEndIndex() {
167        return this.endIndex;
168    }
169
170    /**
171     * Resets the iterator back to the start index.
172     */
173    //@Override
174    public void reset() {
175        this.index = this.startIndex;
176    }
177
178}