Author: scolebourne Date: Sat May 6 09:10:31 2006 New Revision: 400329 URL: http://svn.apache.org/viewcvs?rev=400329&view=rev Log: Add ReverseListIterator rfe 39224, including code from Serge Knystautas
Added: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java (with props) jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java (with props) Modified: jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java Modified: jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html?rev=400329&r1=400328&r2=400329&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html (original) +++ jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html Sat May 6 09:10:31 2006 @@ -58,6 +58,7 @@ <li>DefaultedMap - Returns a default value when the key is not found, without adding the default value to the map itself [30911]</li> <li>GrowthList - Decorator that causes set and indexed add to expand the list rather than throw IndexOutOfBoundsException [34171]</li> <li>LoopingListIterator - When the end of the list is reached the iteration continues from the start [30166]</li> +<li>ReverseListIterator - A list iterator that returns the elements from the list in reverse order [39224]</li> <li>BoundedBuffer - A new wrapper class which can make any buffer bounded [37473]</li> </ul> Added: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java?rev=400329&view=auto ============================================================================== --- jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java (added) +++ jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java Sat May 6 09:10:31 2006 @@ -0,0 +1,174 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.collections.iterators; + +import java.util.List; +import java.util.ListIterator; + +import org.apache.commons.collections.ResettableListIterator; + +/** + * Iterates backwards through a List, starting with the last element + * and continuing to the first. This is useful for looping around + * a list in reverse order without needing to actually reverse the list. + * <p> + * The first call to <code>next()</code> will return the last element + * from the list, and so on. The <code>hasNext()</code> method works + * in concert with the <code>next()</code> method as expected. + * However, the <code>nextIndex()</code> method returns the correct + * index in the list, thus it starts high and reduces as the iteration + * continues. The previous methods work similarly. + * + * @author Serge Knystautas + * @author Stephen Colebourne + * @version $Revision: $ $Date$ + */ +public class ReverseListIterator implements ResettableListIterator { + + /** The list being wrapped. */ + private final List list; + /** The list iterator being wrapped. */ + private ListIterator iterator; + /** Flag to indicate if updating is possible at the moment. */ + private boolean validForUpdate = true; + + /** + * Constructor that wraps a list. + * + * @param list the list to create a reversed iterator for + * @throws NullPointerException if the list is null + */ + public ReverseListIterator(List list) { + super(); + this.list = list; + iterator = list.listIterator(list.size()); + } + + //----------------------------------------------------------------------- + /** + * Checks whether there is another element. + * + * @return true if there is another element + */ + public boolean hasNext() { + return iterator.hasPrevious(); + } + + /** + * Gets the next element. + * The next element is the previous in the list. + * + * @return the next element in the iterator + */ + public Object next() { + Object obj = iterator.previous(); + validForUpdate = true; + return obj; + } + + /** + * Gets the index of the next element. + * + * @return the index of the next element in the iterator + */ + public int nextIndex() { + return iterator.previousIndex(); + } + + /** + * Checks whether there is a previous element. + * + * @return true if there is a previous element + */ + public boolean hasPrevious() { + return iterator.hasNext(); + } + + /** + * Gets the previous element. + * The next element is the previous in the list. + * + * @return the previous element in the iterator + */ + public Object previous() { + Object obj = iterator.next(); + validForUpdate = true; + return obj; + } + + /** + * Gets the index of the previous element. + * + * @return the index of the previous element in the iterator + */ + public int previousIndex() { + return iterator.nextIndex(); + } + + /** + * Removes the last returned element. + * + * @throws UnsupportedOperationException if the list is unmodifiable + * @throws IllegalStateException if there is no element to remove + */ + public void remove() { + if (validForUpdate == false) { + throw new IllegalStateException("Cannot remove from list until next() or previous() called"); + } + iterator.remove(); + } + + /** + * Replaces the last returned element. + * + * @param obj the object to set + * @throws UnsupportedOperationException if the list is unmodifiable + * @throws IllegalStateException if the iterator is not in a valid state for set + */ + public void set(Object obj) { + if (validForUpdate == false) { + throw new IllegalStateException("Cannot set to list until next() or previous() called"); + } + iterator.set(obj); + } + + /** + * Adds a new element to the list between the next and previous elements. + * + * @param obj the object to add + * @throws UnsupportedOperationException if the list is unmodifiable + * @throws IllegalStateException if the iterator is not in a valid state for set + */ + public void add(Object obj) { + // the validForUpdate flag is needed as the necessary previous() + // method call re-enables remove and add + if (validForUpdate == false) { + throw new IllegalStateException("Cannot add to list until next() or previous() called"); + } + validForUpdate = false; + iterator.add(obj); + iterator.previous(); + } + + /** + * Resets the iterator back to the start (which is the + * end of the list as this is a reversed iterator) + */ + public void reset() { + iterator = list.listIterator(list.size()); + } + +} Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/ReverseListIterator.java ------------------------------------------------------------------------------ svn:keywords = "author date id revision" Modified: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java?rev=400329&r1=400328&r2=400329&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java (original) +++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestAll.java Sat May 6 09:10:31 2006 @@ -48,6 +48,7 @@ suite.addTest(TestListIteratorWrapper.suite()); suite.addTest(TestLoopingIterator.suite()); suite.addTest(TestLoopingListIterator.suite()); + suite.addTest(TestReverseListIterator.suite()); suite.addTest(TestSingletonIterator.suite()); suite.addTest(TestSingletonIterator2.suite()); suite.addTest(TestSingletonListIterator.suite()); Added: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java?rev=400329&view=auto ============================================================================== --- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java (added) +++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java Sat May 6 09:10:31 2006 @@ -0,0 +1,170 @@ +/* + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.collections.iterators; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +import junit.framework.Test; +import junit.framework.TestSuite; +import junit.textui.TestRunner; + +import org.apache.commons.collections.ResettableListIterator; + +/** + * Tests the ReverseListIterator. + * + * @version $Revision: $ $Date$ + */ +public class TestReverseListIterator extends AbstractTestListIterator { + + protected String[] testArray = { "One", "Two", "Three", "Four" }; + + public static void main(String args[]) { + String[] testCaseName = { TestReverseListIterator.class.getName() }; + TestRunner.main(testCaseName); + } + + public static Test suite() { + return new TestSuite(TestReverseListIterator.class); + } + + public TestReverseListIterator(String testName) { + super(testName); + } + + public ListIterator makeEmptyListIterator() { + List list = new ArrayList(); + return new ReverseListIterator(list); + } + + public ListIterator makeFullListIterator() { + List list = new ArrayList(Arrays.asList(testArray)); + return new ReverseListIterator(list); + } + + // overrides + //----------------------------------------------------------------------- + public void testEmptyListIteratorIsIndeedEmpty() { + ListIterator it = makeEmptyListIterator(); + + assertEquals(false, it.hasNext()); + assertEquals(-1, it.nextIndex()); // reversed index + assertEquals(false, it.hasPrevious()); + assertEquals(0, it.previousIndex()); // reversed index + + // next() should throw a NoSuchElementException + try { + it.next(); + fail("NoSuchElementException must be thrown from empty ListIterator"); + } catch (NoSuchElementException e) { + } + + // previous() should throw a NoSuchElementException + try { + it.previous(); + fail("NoSuchElementException must be thrown from empty ListIterator"); + } catch (NoSuchElementException e) { + } + } + + public void testWalkForwardAndBack() { + ArrayList list = new ArrayList(); + ListIterator it = makeFullListIterator(); + while (it.hasNext()) { + list.add(it.next()); + } + + // check state at end + assertEquals(false, it.hasNext()); + assertEquals(true, it.hasPrevious()); + + // this had to be commented out, as there is a bug in the JDK before JDK1.5 + // where calling previous at the start of an iterator would push the cursor + // back to an invalid negative value +// try { +// it.next(); +// fail("NoSuchElementException must be thrown from next at end of ListIterator"); +// } catch (NoSuchElementException e) { +// } + + // loop back through comparing + for (int i = list.size() - 1; i >= 0; i--) { + assertEquals("" + i, list.size() - i - 2, it.nextIndex()); // reversed index + assertEquals(list.size() - i - 1, it.previousIndex()); // reversed index + + Object obj = list.get(i); + assertEquals(obj, it.previous()); + } + + // check state at start + assertEquals(true, it.hasNext()); + assertEquals(false, it.hasPrevious()); + try { + it.previous(); + fail("NoSuchElementException must be thrown from previous at start of ListIterator"); + } catch (NoSuchElementException e) { + } + } + + //----------------------------------------------------------------------- + public void testReverse() { + ListIterator it = makeFullListIterator(); + assertEquals(true, it.hasNext()); + assertEquals(3, it.nextIndex()); + assertEquals(false, it.hasPrevious()); + assertEquals(4, it.previousIndex()); + assertEquals("Four", it.next()); + assertEquals(2, it.nextIndex()); + assertEquals(true, it.hasNext()); + assertEquals(3, it.previousIndex()); + assertEquals(true, it.hasPrevious()); + assertEquals("Three", it.next()); + assertEquals(true, it.hasNext()); + assertEquals(1, it.nextIndex()); + assertEquals(true, it.hasPrevious()); + assertEquals(2, it.previousIndex()); + assertEquals("Two", it.next()); + assertEquals(true, it.hasNext()); + assertEquals(0, it.nextIndex()); + assertEquals(true, it.hasPrevious()); + assertEquals(1, it.previousIndex()); + assertEquals("One", it.next()); + assertEquals(false, it.hasNext()); + assertEquals(-1, it.nextIndex()); + assertEquals(true, it.hasPrevious()); + assertEquals(0, it.previousIndex()); + assertEquals("One", it.previous()); + assertEquals("Two", it.previous()); + assertEquals("Three", it.previous()); + assertEquals("Four", it.previous()); + } + + public void testReset() { + ResettableListIterator it = (ResettableListIterator) makeFullListIterator(); + assertEquals("Four", it.next()); + it.reset(); + assertEquals("Four", it.next()); + it.next(); + it.next(); + it.reset(); + assertEquals("Four", it.next()); + } + +} Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestReverseListIterator.java ------------------------------------------------------------------------------ svn:keywords = "author date id revision" --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]