View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.commons.collections.iterators;
18  
19  import java.lang.reflect.Array;
20  import java.util.ListIterator;
21  import java.util.NoSuchElementException;
22  
23  import org.apache.commons.collections.ResettableListIterator;
24  
25  /**
26   * Implements a {@link ListIterator} over an array. 
27   * <p>
28   * The array can be either an array of object or of primitives. If you know 
29   * that you have an object array, the {@link ObjectArrayListIterator}
30   * class is a better choice, as it will perform better.
31   * 
32   * <p>
33   * This iterator does not support {@link #add(Object)} or {@link #remove()}, as the array 
34   * cannot be changed in size. The {@link #set(Object)} method is supported however.
35   *
36   * @see org.apache.commons.collections.iterators.ArrayIterator
37   * @see java.util.Iterator
38   * @see java.util.ListIterator
39   *
40   * @since Commons Collections 3.0
41   * @version $Revision: 647116 $ $Date: 2008-04-11 12:23:08 +0100 (Fri, 11 Apr 2008) $
42   *
43   * @author Neil O'Toole
44   * @author Stephen Colebourne
45   * @author Phil Steitz
46   */
47  public class ArrayListIterator extends ArrayIterator
48          implements ListIterator, ResettableListIterator {
49  
50      /**
51       * Holds the index of the last item returned by a call to <code>next()</code>
52       * or <code>previous()</code>. This is set to <code>-1</code> if neither method
53       * has yet been invoked. <code>lastItemIndex</code> is used to to implement 
54       * the {@link #set} method.
55       *
56       */
57      protected int lastItemIndex = -1;
58  
59      // Constructors
60      // ----------------------------------------------------------------------
61      /**
62       * Constructor for use with <code>setArray</code>.
63       * <p>
64       * Using this constructor, the iterator is equivalent to an empty iterator
65       * until {@link #setArray(Object)} is  called to establish the array to iterate over.
66       */
67      public ArrayListIterator() {
68          super();
69      }
70  
71      /**
72       * Constructs an ArrayListIterator that will iterate over the values in the
73       * specified array.
74       *
75       * @param array the array to iterate over
76       * @throws IllegalArgumentException if <code>array</code> is not an array.
77       * @throws NullPointerException if <code>array</code> is <code>null</code>
78       */
79      public ArrayListIterator(Object array) {
80          super(array);
81      }
82  
83      /**
84       * Constructs an ArrayListIterator that will iterate over the values in the
85       * specified array from a specific start index.
86       *
87       * @param array  the array to iterate over
88       * @param startIndex  the index to start iterating at
89       * @throws IllegalArgumentException if <code>array</code> is not an array.
90       * @throws NullPointerException if <code>array</code> is <code>null</code>
91       * @throws IndexOutOfBoundsException if the start index is out of bounds
92       */
93      public ArrayListIterator(Object array, int startIndex) {
94          super(array, startIndex);
95          this.startIndex = startIndex;
96      }
97  
98      /**
99       * Construct an ArrayListIterator that will iterate over a range of values 
100      * in the specified array.
101      *
102      * @param array  the array to iterate over
103      * @param startIndex  the index to start iterating at
104      * @param endIndex  the index (exclusive) to finish iterating at
105      * @throws IllegalArgumentException if <code>array</code> is not an array.
106      * @throws IndexOutOfBoundsException if the start or end index is out of bounds
107      * @throws IllegalArgumentException if end index is before the start
108      * @throws NullPointerException if <code>array</code> is <code>null</code>
109      */
110     public ArrayListIterator(Object array, int startIndex, int endIndex) {
111         super(array, startIndex, endIndex);
112         this.startIndex = startIndex;
113     }
114 
115     // ListIterator interface
116     //-----------------------------------------------------------------------
117     /**
118      * Returns true if there are previous elements to return from the array.
119      *
120      * @return true if there is a previous element to return
121      */
122     public boolean hasPrevious() {
123         return (this.index > this.startIndex);
124     }
125 
126     /**
127      * Gets the previous element from the array.
128      * 
129      * @return the previous element
130      * @throws NoSuchElementException if there is no previous element
131      */
132     public Object previous() {
133         if (hasPrevious() == false) {
134             throw new NoSuchElementException();
135         }
136         this.lastItemIndex = --this.index;
137         return Array.get(this.array, this.index);
138     }
139 
140     /**
141      * Gets the next element from the array.
142      * 
143      * @return the next element
144      * @throws NoSuchElementException if there is no next element
145      */
146     public Object next() {
147         if (hasNext() == false) {
148             throw new NoSuchElementException();
149         }
150         this.lastItemIndex = this.index;
151         return Array.get(this.array, this.index++);
152     }
153 
154     /**
155      * Gets the next index to be retrieved.
156      * 
157      * @return the index of the item to be retrieved next
158      */
159     public int nextIndex() {
160         return this.index - this.startIndex;
161     }
162 
163     /**
164      * Gets the index of the item to be retrieved if {@link #previous()} is called.
165      * 
166      * @return the index of the item to be retrieved next
167      */
168     public int previousIndex() {
169         return this.index - this.startIndex - 1;
170     }
171 
172     /**
173      * This iterator does not support modification of its backing collection, and so will
174      * always throw an {@link UnsupportedOperationException} when this method is invoked.
175      *
176      * @throws UnsupportedOperationException always thrown.
177      * @see java.util.ListIterator#set
178      */
179     public void add(Object o) {
180         throw new UnsupportedOperationException("add() method is not supported");
181     }
182 
183     /**
184      * Sets the element under the cursor.
185      * <p>
186      * This method sets the element that was returned by the last call 
187      * to {@link #next()} of {@link #previous()}. 
188      * <p>
189      * <b>Note:</b> {@link ListIterator} implementations that support
190      * <code>add()</code> and <code>remove()</code> only allow <code>set()</code> to be called
191      * once per call to <code>next()</code> or <code>previous</code> (see the {@link ListIterator}
192      * javadoc for more details). Since this implementation does
193      * not support <code>add()</code> or <code>remove()</code>, <code>set()</code> may be
194      * called as often as desired.
195      *
196      * @see java.util.ListIterator#set
197      */
198     public void set(Object o) {
199         if (this.lastItemIndex == -1) {
200             throw new IllegalStateException("must call next() or previous() before a call to set()");
201         }
202 
203         Array.set(this.array, this.lastItemIndex, o);
204     }
205 
206     /**
207      * Resets the iterator back to the start index.
208      */
209     public void reset() {
210         super.reset();
211         this.lastItemIndex = -1;
212     }
213 
214 }