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.lang.reflect.Array; 020 import java.util.ListIterator; 021 import java.util.NoSuchElementException; 022 023 import org.apache.commons.collections.ResettableListIterator; 024 025 /** 026 * Implements a {@link ListIterator} over an array. 027 * <p> 028 * The array can be either an array of object or of primitives. If you know 029 * that you have an object array, the {@link ObjectArrayListIterator} 030 * class is a better choice, as it will perform better. 031 * 032 * <p> 033 * This iterator does not support {@link #add(Object)} or {@link #remove()}, as the array 034 * cannot be changed in size. The {@link #set(Object)} method is supported however. 035 * 036 * @see org.apache.commons.collections.iterators.ArrayIterator 037 * @see java.util.Iterator 038 * @see java.util.ListIterator 039 * 040 * @since Commons Collections 3.0 041 * @version $Revision: 647116 $ $Date: 2008-04-11 12:23:08 +0100 (Fri, 11 Apr 2008) $ 042 * 043 * @author Neil O'Toole 044 * @author Stephen Colebourne 045 * @author Phil Steitz 046 */ 047 public class ArrayListIterator extends ArrayIterator 048 implements ListIterator, ResettableListIterator { 049 050 /** 051 * Holds the index of the last item returned by a call to <code>next()</code> 052 * or <code>previous()</code>. This is set to <code>-1</code> if neither method 053 * has yet been invoked. <code>lastItemIndex</code> is used to to implement 054 * the {@link #set} method. 055 * 056 */ 057 protected int lastItemIndex = -1; 058 059 // Constructors 060 // ---------------------------------------------------------------------- 061 /** 062 * Constructor for use with <code>setArray</code>. 063 * <p> 064 * Using this constructor, the iterator is equivalent to an empty iterator 065 * until {@link #setArray(Object)} is called to establish the array to iterate over. 066 */ 067 public ArrayListIterator() { 068 super(); 069 } 070 071 /** 072 * Constructs an ArrayListIterator that will iterate over the values in the 073 * specified array. 074 * 075 * @param array the array to iterate over 076 * @throws IllegalArgumentException if <code>array</code> is not an array. 077 * @throws NullPointerException if <code>array</code> is <code>null</code> 078 */ 079 public ArrayListIterator(Object array) { 080 super(array); 081 } 082 083 /** 084 * Constructs an ArrayListIterator that will iterate over the values in the 085 * specified array from a specific start index. 086 * 087 * @param array the array to iterate over 088 * @param startIndex the index to start iterating at 089 * @throws IllegalArgumentException if <code>array</code> is not an array. 090 * @throws NullPointerException if <code>array</code> is <code>null</code> 091 * @throws IndexOutOfBoundsException if the start index is out of bounds 092 */ 093 public ArrayListIterator(Object array, int startIndex) { 094 super(array, startIndex); 095 this.startIndex = startIndex; 096 } 097 098 /** 099 * 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 }