001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections.iterators;
017:
018: import java.lang.reflect.Array;
019: import java.util.NoSuchElementException;
020:
021: import org.apache.commons.collections.ResettableIterator;
022:
023: /**
024: * Implements an {@link java.util.Iterator Iterator} over any array.
025: * <p>
026: * The array can be either an array of object or of primitives. If you know
027: * that you have an object array, the
028: * {@link org.apache.commons.collections.iterators.ObjectArrayIterator ObjectArrayIterator}
029: * class is a better choice, as it will perform better.
030: * <p>
031: * The iterator implements a {@link #reset} method, allowing the reset of
032: * the iterator back to the start if required.
033: *
034: * @since Commons Collections 1.0
035: * @version $Revision: 155406 $ $Date: 2005-02-26 12:55:26 +0000 (Sat, 26 Feb 2005) $
036: *
037: * @author James Strachan
038: * @author Mauricio S. Moura
039: * @author Michael A. Smith
040: * @author Neil O'Toole
041: * @author Stephen Colebourne
042: */
043: public class ArrayIterator implements ResettableIterator {
044:
045: /** The array to iterate over */
046: protected Object array;
047: /** The start index to loop from */
048: protected int startIndex = 0;
049: /** The end index to loop to */
050: protected int endIndex = 0;
051: /** The current iterator index */
052: protected int index = 0;
053:
054: // Constructors
055: // ----------------------------------------------------------------------
056: /**
057: * Constructor for use with <code>setArray</code>.
058: * <p>
059: * Using this constructor, the iterator is equivalent to an empty iterator
060: * until {@link #setArray(Object)} is called to establish the array to iterate over.
061: */
062: public ArrayIterator() {
063: super ();
064: }
065:
066: /**
067: * Constructs an ArrayIterator that will iterate over the values in the
068: * specified array.
069: *
070: * @param array the array to iterate over.
071: * @throws IllegalArgumentException if <code>array</code> is not an array.
072: * @throws NullPointerException if <code>array</code> is <code>null</code>
073: */
074: public ArrayIterator(final Object array) {
075: super ();
076: setArray(array);
077: }
078:
079: /**
080: * Constructs an ArrayIterator that will iterate over the values in the
081: * specified array from a specific start index.
082: *
083: * @param array the array to iterate over.
084: * @param startIndex the index to start iterating at.
085: * @throws IllegalArgumentException if <code>array</code> is not an array.
086: * @throws NullPointerException if <code>array</code> is <code>null</code>
087: * @throws IndexOutOfBoundsException if the index is invalid
088: */
089: public ArrayIterator(final Object array, final int startIndex) {
090: super ();
091: setArray(array);
092: checkBound(startIndex, "start");
093: this .startIndex = startIndex;
094: this .index = startIndex;
095: }
096:
097: /**
098: * Construct an ArrayIterator that will iterate over a range of values
099: * in the specified array.
100: *
101: * @param array the array to iterate over.
102: * @param startIndex the index to start iterating at.
103: * @param endIndex the index to finish iterating at.
104: * @throws IllegalArgumentException if <code>array</code> is not an array.
105: * @throws NullPointerException if <code>array</code> is <code>null</code>
106: * @throws IndexOutOfBoundsException if either index is invalid
107: */
108: public ArrayIterator(final Object array, final int startIndex,
109: final int endIndex) {
110: super ();
111: setArray(array);
112: checkBound(startIndex, "start");
113: checkBound(endIndex, "end");
114: if (endIndex < startIndex) {
115: throw new IllegalArgumentException(
116: "End index must not be less than start index.");
117: }
118: this .startIndex = startIndex;
119: this .endIndex = endIndex;
120: this .index = startIndex;
121: }
122:
123: /**
124: * Checks whether the index is valid or not.
125: *
126: * @param bound the index to check
127: * @param type the index type (for error messages)
128: * @throws IndexOutOfBoundsException if the index is invalid
129: */
130: protected void checkBound(final int bound, final String type) {
131: if (bound > this .endIndex) {
132: throw new ArrayIndexOutOfBoundsException(
133: "Attempt to make an ArrayIterator that " + type
134: + "s beyond the end of the array. ");
135: }
136: if (bound < 0) {
137: throw new ArrayIndexOutOfBoundsException(
138: "Attempt to make an ArrayIterator that " + type
139: + "s before the start of the array. ");
140: }
141: }
142:
143: // Iterator interface
144: //-----------------------------------------------------------------------
145: /**
146: * Returns true if there are more elements to return from the array.
147: *
148: * @return true if there is a next element to return
149: */
150: public boolean hasNext() {
151: return (index < endIndex);
152: }
153:
154: /**
155: * Returns the next element in the array.
156: *
157: * @return the next element in the array
158: * @throws NoSuchElementException if all the elements in the array
159: * have already been returned
160: */
161: public Object next() {
162: if (hasNext() == false) {
163: throw new NoSuchElementException();
164: }
165: return Array.get(array, index++);
166: }
167:
168: /**
169: * Throws {@link UnsupportedOperationException}.
170: *
171: * @throws UnsupportedOperationException always
172: */
173: public void remove() {
174: throw new UnsupportedOperationException(
175: "remove() method is not supported");
176: }
177:
178: // Properties
179: //-----------------------------------------------------------------------
180: /**
181: * Gets the array that this iterator is iterating over.
182: *
183: * @return the array this iterator iterates over, or <code>null</code> if
184: * the no-arg constructor was used and {@link #setArray(Object)} has never
185: * been called with a valid array.
186: */
187: public Object getArray() {
188: return array;
189: }
190:
191: /**
192: * Sets the array that the ArrayIterator should iterate over.
193: * <p>
194: * If an array has previously been set (using the single-arg constructor
195: * or this method) then that array is discarded in favour of this one.
196: * Iteration is restarted at the start of the new array.
197: * Although this can be used to reset iteration, the {@link #reset()} method
198: * is a more effective choice.
199: *
200: * @param array the array that the iterator should iterate over.
201: * @throws IllegalArgumentException if <code>array</code> is not an array.
202: * @throws NullPointerException if <code>array</code> is <code>null</code>
203: */
204: public void setArray(final Object array) {
205: // Array.getLength throws IllegalArgumentException if the object is not
206: // an array or NullPointerException if the object is null. This call
207: // is made before saving the array and resetting the index so that the
208: // array iterator remains in a consistent state if the argument is not
209: // an array or is null.
210: this .endIndex = Array.getLength(array);
211: this .startIndex = 0;
212: this .array = array;
213: this .index = 0;
214: }
215:
216: /**
217: * Resets the iterator back to the start index.
218: */
219: public void reset() {
220: this.index = this.startIndex;
221: }
222:
223: }
|