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.ArrayList; 020 import java.util.Iterator; 021 import java.util.List; 022 import java.util.NoSuchElementException; 023 024 import org.apache.commons.collections.ResettableListIterator; 025 026 /** 027 * Converts an iterator into a list iterator by caching the returned entries. 028 * <p> 029 * The <code>ListIterator</code> interface has additional useful methods 030 * for navigation - <code>previous()</code> and the index methods. 031 * This class allows a regular <code>Iterator</code> to behave as a 032 * <code>ListIterator</code>. It achieves this by building a list internally 033 * of as the underlying iterator is traversed. 034 * <p> 035 * The optional operations of <code>ListIterator</code> are not supported. 036 * <p> 037 * This class implements ResettableListIterator from Commons Collections 3.2. 038 * 039 * @since Commons Collections 2.1 040 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ 041 * 042 * @author Morgan Delagrange 043 * @author Stephen Colebourne 044 */ 045 public class ListIteratorWrapper implements ResettableListIterator { 046 047 /** Message used when remove, set or add are called. */ 048 private static final String UNSUPPORTED_OPERATION_MESSAGE = 049 "ListIteratorWrapper does not support optional operations of ListIterator."; 050 051 /** The underlying iterator being decorated. */ 052 private final Iterator iterator; 053 /** The list being used to cache the iterator. */ 054 private final List list = new ArrayList(); 055 056 /** The current index of this iterator. */ 057 private int currentIndex = 0; 058 /** The current index of the wrapped iterator. */ 059 private int wrappedIteratorIndex = 0; 060 061 // Constructor 062 //------------------------------------------------------------------------- 063 /** 064 * Constructs a new <code>ListIteratorWrapper</code> that will wrap 065 * the given iterator. 066 * 067 * @param iterator the iterator to wrap 068 * @throws NullPointerException if the iterator is null 069 */ 070 public ListIteratorWrapper(Iterator iterator) { 071 super(); 072 if (iterator == null) { 073 throw new NullPointerException("Iterator must not be null"); 074 } 075 this.iterator = iterator; 076 } 077 078 // ListIterator interface 079 //------------------------------------------------------------------------- 080 /** 081 * Throws {@link UnsupportedOperationException}. 082 * 083 * @param obj the object to add, ignored 084 * @throws UnsupportedOperationException always 085 */ 086 public void add(Object obj) throws UnsupportedOperationException { 087 throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_MESSAGE); 088 } 089 090 /** 091 * Returns true if there are more elements in the iterator. 092 * 093 * @return true if there are more elements 094 */ 095 public boolean hasNext() { 096 if (currentIndex == wrappedIteratorIndex) { 097 return iterator.hasNext(); 098 } 099 return true; 100 } 101 102 /** 103 * Returns true if there are previous elements in the iterator. 104 * 105 * @return true if there are previous elements 106 */ 107 public boolean hasPrevious() { 108 if (currentIndex == 0) { 109 return false; 110 } 111 return true; 112 } 113 114 /** 115 * Returns the next element from the iterator. 116 * 117 * @return the next element from the iterator 118 * @throws NoSuchElementException if there are no more elements 119 */ 120 public Object next() throws NoSuchElementException { 121 if (currentIndex < wrappedIteratorIndex) { 122 ++currentIndex; 123 return list.get(currentIndex - 1); 124 } 125 126 Object retval = iterator.next(); 127 list.add(retval); 128 ++currentIndex; 129 ++wrappedIteratorIndex; 130 return retval; 131 } 132 133 /** 134 * Returns in the index of the next element. 135 * 136 * @return the index of the next element 137 */ 138 public int nextIndex() { 139 return currentIndex; 140 } 141 142 /** 143 * Returns the the previous element. 144 * 145 * @return the previous element 146 * @throws NoSuchElementException if there are no previous elements 147 */ 148 public Object previous() throws NoSuchElementException { 149 if (currentIndex == 0) { 150 throw new NoSuchElementException(); 151 } 152 --currentIndex; 153 return list.get(currentIndex); 154 } 155 156 /** 157 * Returns the index of the previous element. 158 * 159 * @return the index of the previous element 160 */ 161 public int previousIndex() { 162 return currentIndex - 1; 163 } 164 165 /** 166 * Throws {@link UnsupportedOperationException}. 167 * 168 * @throws UnsupportedOperationException always 169 */ 170 public void remove() throws UnsupportedOperationException { 171 throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_MESSAGE); 172 } 173 174 /** 175 * Throws {@link UnsupportedOperationException}. 176 * 177 * @param obj the object to set, ignored 178 * @throws UnsupportedOperationException always 179 */ 180 public void set(Object obj) throws UnsupportedOperationException { 181 throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_MESSAGE); 182 } 183 184 // ResettableIterator interface 185 //------------------------------------------------------------------------- 186 /** 187 * Resets this iterator back to the position at which the iterator 188 * was created. 189 * 190 * @since Commons Collections 3.2 191 */ 192 public void reset() { 193 currentIndex = 0; 194 } 195 196 }