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 */
017 package org.apache.commons.collections.iterators;
018
019 import java.util.ListIterator;
020 import java.util.NoSuchElementException;
021
022 import org.apache.commons.collections.ResettableListIterator;
023
024 /**
025 * Implements a {@link ListIterator} over an array of objects.
026 * <p>
027 * This iterator does not support {@link #add} or {@link #remove}, as the object array
028 * cannot be structurally modified. The {@link #set} method is supported however.
029 * <p>
030 * The iterator implements a {@link #reset} method, allowing the reset of the iterator
031 * back to the start if required.
032 *
033 * @see org.apache.commons.collections.iterators.ObjectArrayIterator
034 * @see java.util.Iterator
035 * @see java.util.ListIterator
036 *
037 * @since Commons Collections 3.0
038 * @version $Revision: 647116 $ $Date: 2008-04-11 12:23:08 +0100 (Fri, 11 Apr 2008) $
039 *
040 * @author Neil O'Toole
041 * @author Stephen Colebourne
042 * @author Phil Steitz
043 */
044 public class ObjectArrayListIterator extends ObjectArrayIterator
045 implements ListIterator, ResettableListIterator {
046
047 /**
048 * Holds the index of the last item returned by a call to <code>next()</code>
049 * or <code>previous()</code>. This is set to <code>-1</code> if neither method
050 * has yet been invoked. <code>lastItemIndex</code> is used to to implement the
051 * {@link #set} method.
052 */
053 protected int lastItemIndex = -1;
054
055 /**
056 * Constructor for use with <code>setArray</code>.
057 * <p>
058 * Using this constructor, the iterator is equivalent to an empty iterator
059 * until {@link #setArray} is called to establish the array to iterate over.
060 */
061 public ObjectArrayListIterator() {
062 super();
063 }
064
065 /**
066 * Constructs an ObjectArrayListIterator that will iterate over the values in the
067 * specified array.
068 *
069 * @param array the array to iterate over
070 * @throws NullPointerException if <code>array</code> is <code>null</code>
071 */
072 public ObjectArrayListIterator(Object[] array) {
073 super(array);
074 }
075
076 /**
077 * Constructs an ObjectArrayListIterator that will iterate over the values in the
078 * specified array from a specific start index.
079 *
080 * @param array the array to iterate over
081 * @param start the index to start iterating at
082 * @throws NullPointerException if <code>array</code> is <code>null</code>
083 * @throws IndexOutOfBoundsException if the start index is out of bounds
084 */
085 public ObjectArrayListIterator(Object[] array, int start) {
086 super(array, start);
087 }
088
089 /**
090 * Construct an ObjectArrayListIterator that will iterate over a range of values
091 * in the specified array.
092 *
093 * @param array the array to iterate over
094 * @param start the index to start iterating at
095 * @param end the index (exclusive) to finish iterating at
096 * @throws IndexOutOfBoundsException if the start or end index is out of bounds
097 * @throws IllegalArgumentException if end index is before the start
098 * @throws NullPointerException if <code>array</code> is <code>null</code>
099 */
100 public ObjectArrayListIterator(Object[] array, int start, int end) {
101 super(array, start, end);
102 }
103
104 // ListIterator interface
105 //-------------------------------------------------------------------------
106
107 /**
108 * Returns true if there are previous elements to return from the array.
109 *
110 * @return true if there is a previous element to return
111 */
112 public boolean hasPrevious() {
113 return (this.index > this.startIndex);
114 }
115
116 /**
117 * Gets the previous element from the array.
118 *
119 * @return the previous element
120 * @throws NoSuchElementException if there is no previous element
121 */
122 public Object previous() {
123 if (hasPrevious() == false) {
124 throw new NoSuchElementException();
125 }
126 this.lastItemIndex = --this.index;
127 return this.array[this.index];
128 }
129
130 /**
131 * Gets the next element from the array.
132 *
133 * @return the next element
134 * @throws NoSuchElementException if there is no next element
135 */
136 public Object next() {
137 if (hasNext() == false) {
138 throw new NoSuchElementException();
139 }
140 this.lastItemIndex = this.index;
141 return this.array[this.index++];
142 }
143
144 /**
145 * Gets the next index to be retrieved.
146 *
147 * @return the index of the item to be retrieved next
148 */
149 public int nextIndex() {
150 return this.index - this.startIndex;
151 }
152
153 /**
154 * Gets the index of the item to be retrieved if {@link #previous()} is called.
155 *
156 * @return the index of the item to be retrieved next
157 */
158 public int previousIndex() {
159 return this.index - this.startIndex - 1;
160 }
161
162 /**
163 * This iterator does not support modification of its backing array's size, and so will
164 * always throw an {@link UnsupportedOperationException} when this method is invoked.
165 *
166 * @param obj the object to add
167 * @throws UnsupportedOperationException always thrown.
168 */
169 public void add(Object obj) {
170 throw new UnsupportedOperationException("add() method is not supported");
171 }
172
173 /**
174 * Sets the element under the cursor.
175 * <p>
176 * This method sets the element that was returned by the last call
177 * to {@link #next()} of {@link #previous()}.
178 *
179 * <b>Note:</b> {@link ListIterator} implementations that support <code>add()</code>
180 * and <code>remove()</code> only allow <code>set()</code> to be called once per call
181 * to <code>next()</code> or <code>previous</code> (see the {@link ListIterator}
182 * javadoc for more details). Since this implementation does not support
183 * <code>add()</code> or <code>remove()</code>, <code>set()</code> may be
184 * called as often as desired.
185 *
186 * @param obj the object to set into the array
187 * @throws IllegalStateException if next() has not yet been called.
188 * @throws ClassCastException if the object type is unsuitable for the array
189 */
190 public void set(Object obj) {
191 if (this.lastItemIndex == -1) {
192 throw new IllegalStateException("must call next() or previous() before a call to set()");
193 }
194
195 this.array[this.lastItemIndex] = obj;
196 }
197
198 /**
199 * Resets the iterator back to the start index.
200 */
201 public void reset() {
202 super.reset();
203 this.lastItemIndex = -1;
204 }
205
206 }