Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 42787 invoked from network); 17 Jul 2004 21:02:56 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 17 Jul 2004 21:02:56 -0000 Received: (qmail 90173 invoked by uid 500); 17 Jul 2004 21:02:54 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 89751 invoked by uid 500); 17 Jul 2004 21:02:52 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 89738 invoked by uid 500); 17 Jul 2004 21:02:52 -0000 Received: (qmail 89735 invoked by uid 99); 17 Jul 2004 21:02:52 -0000 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.27.1) with SMTP; Sat, 17 Jul 2004 14:02:48 -0700 Received: (qmail 42724 invoked by uid 1529); 17 Jul 2004 21:02:48 -0000 Date: 17 Jul 2004 21:02:48 -0000 Message-ID: <20040717210248.42723.qmail@minotaur.apache.org> From: scolebourne@apache.org To: jakarta-commons-cvs@apache.org Subject: cvs commit: jakarta-commons/collections/src/java/org/apache/commons/collections/iterators LoopingListIterator.java X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N scolebourne 2004/07/17 14:02:48 Modified: collections/src/test/org/apache/commons/collections/iterators TestAll.java collections RELEASE-NOTES.html Added: collections/src/test/org/apache/commons/collections/iterators TestLoopingListIterator.java collections/src/java/org/apache/commons/collections/iterators LoopingListIterator.java Log: Add LoopingListIterator bug 30166, from Eric Crampton Revision Changes Path 1.16 +2 -1 jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/TestAll.java Index: TestAll.java =================================================================== RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/TestAll.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- TestAll.java 9 Apr 2004 14:38:47 -0000 1.15 +++ TestAll.java 17 Jul 2004 21:02:47 -0000 1.16 @@ -47,6 +47,7 @@ suite.addTest(TestIteratorChain.suite()); suite.addTest(TestListIteratorWrapper.suite()); suite.addTest(TestLoopingIterator.suite()); + suite.addTest(TestLoopingListIterator.suite()); suite.addTest(TestSingletonIterator.suite()); suite.addTest(TestSingletonIterator2.suite()); suite.addTest(TestSingletonListIterator.suite()); 1.1 jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/TestLoopingListIterator.java Index: TestLoopingListIterator.java =================================================================== /* * Copyright 2004 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.NoSuchElementException; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Tests the LoopingListIterator class. * * @version $Revision: 1.1 $ $Date: 2004/07/17 21:02:47 $ * * @author Eric Crampton */ public class TestLoopingListIterator extends TestCase { public TestLoopingListIterator(String testName) { super(testName); } public static Test suite() { return new TestSuite(TestLoopingListIterator.class); } /** * Tests constructor exception. */ public void testConstructorEx() throws Exception { try { new LoopingListIterator(null); fail(); } catch (NullPointerException ex) { } } /** * Tests whether an empty looping list iterator works. */ public void testLooping0() throws Exception { List list = new ArrayList(); LoopingListIterator loop = new LoopingListIterator(list); assertFalse(loop.hasNext()); assertFalse(loop.hasPrevious()); try { loop.next(); fail(); } catch (NoSuchElementException ex) { } try { loop.previous(); fail(); } catch (NoSuchElementException ex) { } } /** * Tests whether a looping list iterator works on a list with only * one element. */ public void testLooping1() throws Exception { List list = new ArrayList(Arrays.asList(new String[] { "a" })); LoopingListIterator loop = new LoopingListIterator(list); // assertTrue(loop.hasNext()); assertEquals("a", loop.next()); // assertTrue(loop.hasNext()); assertEquals("a", loop.next()); // assertTrue(loop.hasNext()); assertEquals("a", loop.next()); // assertTrue(loop.hasPrevious()); assertEquals("a", loop.previous()); // assertTrue(loop.hasPrevious()); assertEquals("a", loop.previous()); // assertTrue(loop.hasPrevious()); assertEquals("a", loop.previous()); // } /** * Tests whether a looping list iterator works on a list with two * elements. */ public void testLooping2() throws Exception { List list = new ArrayList(Arrays.asList(new String[] { "a", "b" })); LoopingListIterator loop = new LoopingListIterator(list); // b assertTrue(loop.hasNext()); assertEquals("a", loop.next()); // a assertTrue(loop.hasNext()); assertEquals("b", loop.next()); // b assertTrue(loop.hasNext()); assertEquals("a", loop.next()); // a // Reset the iterator and try using previous. loop.reset(); // b assertTrue(loop.hasPrevious()); assertEquals("b", loop.previous()); // a assertTrue(loop.hasPrevious()); assertEquals("a", loop.previous()); // b assertTrue(loop.hasPrevious()); assertEquals("b", loop.previous()); // a } /** * Tests jogging back and forth between two elements, but not over * the begin/end boundary of the list. */ public void testJoggingNotOverBoundary() { List list = new ArrayList(Arrays.asList(new String[] { "a", "b" })); LoopingListIterator loop = new LoopingListIterator(list); // b // Try jogging back and forth between the elements, but not // over the begin/end boundary. loop.reset(); assertEquals("a", loop.next()); // a assertEquals("a", loop.previous()); // b assertEquals("a", loop.next()); // a assertEquals("b", loop.next()); // b assertEquals("b", loop.previous()); // a assertEquals("b", loop.next()); // b } /** * Tests jogging back and forth between two elements over the * begin/end boundary of the list. */ public void testJoggingOverBoundary() { List list = new ArrayList(Arrays.asList(new String[] { "a", "b" })); LoopingListIterator loop = new LoopingListIterator(list); // b // Try jogging back and forth between the elements, but not // over the begin/end boundary. assertEquals("b", loop.previous()); // a assertEquals("b", loop.next()); // b assertEquals("b", loop.previous()); // a assertEquals("a", loop.previous()); // b assertEquals("a", loop.next()); // a assertEquals("a", loop.previous()); // b } /** * Tests removing an element from a wrapped ArrayList. */ public void testRemovingElementsAndIteratingForward() { List list = new ArrayList(Arrays.asList(new String[] { "a", "b", "c" })); LoopingListIterator loop = new LoopingListIterator(list); // b c assertTrue(loop.hasNext()); assertEquals("a", loop.next()); // a c loop.remove(); // c assertEquals(2, list.size()); assertTrue(loop.hasNext()); assertEquals("b", loop.next()); // b loop.remove(); // assertEquals(1, list.size()); assertTrue(loop.hasNext()); assertEquals("c", loop.next()); // loop.remove(); // --- assertEquals(0, list.size()); assertFalse(loop.hasNext()); try { loop.next(); fail(); } catch (NoSuchElementException ex) { } } /** * Tests removing an element from a wrapped ArrayList. */ public void testRemovingElementsAndIteratingBackwards() { List list = new ArrayList(Arrays.asList(new String[] { "a", "b", "c" })); LoopingListIterator loop = new LoopingListIterator(list); // b c assertTrue(loop.hasPrevious()); assertEquals("c", loop.previous()); // a b loop.remove(); // b assertEquals(2, list.size()); assertTrue(loop.hasPrevious()); assertEquals("b", loop.previous()); // a loop.remove(); // assertEquals(1, list.size()); assertTrue(loop.hasPrevious()); assertEquals("a", loop.previous()); // loop.remove(); // --- assertEquals(0, list.size()); assertFalse(loop.hasPrevious()); try { loop.previous(); fail(); } catch (NoSuchElementException ex) { } } /** * Tests the reset method. */ public void testReset() { List list = new ArrayList(Arrays.asList(new String[] { "a", "b", "c" })); LoopingListIterator loop = new LoopingListIterator(list); // b c assertEquals("a", loop.next()); // a c assertEquals("b", loop.next()); // a b loop.reset(); // b c assertEquals("a", loop.next()); // a c loop.reset(); // b c assertEquals("a", loop.next()); // a c assertEquals("b", loop.next()); // a b assertEquals("c", loop.next()); // b c loop.reset(); // b c assertEquals("c", loop.previous()); // a b assertEquals("b", loop.previous()); // a c loop.reset(); // b c assertEquals("c", loop.previous()); // a b loop.reset(); // b c assertEquals("c", loop.previous()); // a b assertEquals("b", loop.previous()); // a c assertEquals("a", loop.previous()); // b c } /** * Tests the add method. */ public void testAdd() { List list = new ArrayList(Arrays.asList(new String[] { "b", "e", "f" })); LoopingListIterator loop = new LoopingListIterator(list); // e f loop.add("a"); // b e f assertEquals("b", loop.next()); // a e f loop.reset(); // b e f assertEquals("a", loop.next()); // a e f assertEquals("b", loop.next()); // a b f loop.add("c"); // a b c f assertEquals("e", loop.next()); // a b c e assertEquals("e", loop.previous()); // a b c f assertEquals("c", loop.previous()); // a b e f assertEquals("c", loop.next()); // a b c f loop.add("d"); // a b c d f loop.reset(); // b c d e f assertEquals("a", loop.next()); // a c d e f assertEquals("b", loop.next()); // a b d e f assertEquals("c", loop.next()); // a b c e f assertEquals("d", loop.next()); // a b c d f assertEquals("e", loop.next()); // a b c d e assertEquals("f", loop.next()); // b c d e f assertEquals("a", loop.next()); // a c d e f list = new ArrayList(Arrays.asList(new String[] { "b", "e", "f" })); loop = new LoopingListIterator(list); // e f loop.add("a"); // a e f assertEquals("a", loop.previous()); // a b e loop.reset(); // b e f assertEquals("f", loop.previous()); // a b e assertEquals("e", loop.previous()); // a b f loop.add("d"); // a b d f assertEquals("d", loop.previous()); // a b e f loop.add("c"); // a b c e f assertEquals("c", loop.previous()); // a b d e f loop.reset(); assertEquals("a", loop.next()); // a c d e f assertEquals("b", loop.next()); // a b d e f assertEquals("c", loop.next()); // a b c e f assertEquals("d", loop.next()); // a b c d f assertEquals("e", loop.next()); // a b c d e assertEquals("f", loop.next()); // b c d e f assertEquals("a", loop.next()); // a c d e f } /** * Tests nextIndex and previousIndex. */ public void testNextAndPreviousIndex() { List list = new ArrayList(Arrays.asList(new String[] { "a", "b", "c" })); LoopingListIterator loop = new LoopingListIterator(list); // b c assertEquals(0, loop.nextIndex()); assertEquals(2, loop.previousIndex()); assertEquals("a", loop.next()); // a c assertEquals(1, loop.nextIndex()); assertEquals(0, loop.previousIndex()); assertEquals("a", loop.previous()); // b c assertEquals(0, loop.nextIndex()); assertEquals(2, loop.previousIndex()); assertEquals("c", loop.previous()); // a b assertEquals(2, loop.nextIndex()); assertEquals(1, loop.previousIndex()); assertEquals("b", loop.previous()); // a c assertEquals(1, loop.nextIndex()); assertEquals(0, loop.previousIndex()); assertEquals("a", loop.previous()); // b c assertEquals(0, loop.nextIndex()); assertEquals(2, loop.previousIndex()); } /** * Tests using the set method to change elements. */ public void testSet() { List list = new ArrayList(Arrays.asList(new String[] { "q", "r", "z" })); LoopingListIterator loop = new LoopingListIterator(list); // r z assertEquals("z", loop.previous()); // q r loop.set("c"); // q r loop.reset(); // r c assertEquals("q", loop.next()); // q c loop.set("a"); // a c assertEquals("r", loop.next()); // a r loop.set("b"); // a b loop.reset(); // b c assertEquals("a", loop.next()); // a c assertEquals("b", loop.next()); // a b assertEquals("c", loop.next()); // b c } } 1.68 +1 -1 jakarta-commons/collections/RELEASE-NOTES.html Index: RELEASE-NOTES.html =================================================================== RCS file: /home/cvs/jakarta-commons/collections/RELEASE-NOTES.html,v retrieving revision 1.67 retrieving revision 1.68 diff -u -r1.67 -r1.68 --- RELEASE-NOTES.html 28 Jun 2004 23:26:33 -0000 1.67 +++ RELEASE-NOTES.html 17 Jul 2004 21:02:47 -0000 1.68 @@ -34,7 +34,7 @@

NEW CLASSES

    -
  • ........
  • +
  • LoopingListIterator - When the end of the list is reached the iteration continues from the start

ENHANCEMENTS

1.1 jakarta-commons/collections/src/java/org/apache/commons/collections/iterators/LoopingListIterator.java Index: LoopingListIterator.java =================================================================== /* * Copyright 2004 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 java.util.NoSuchElementException; import org.apache.commons.collections.ResettableIterator; /** * A ListIterator that restarts when it reaches the end or when it * reaches the beginning. *

* The iterator will loop continuously around the provided list, * unless there are no elements in the collection to begin with, or * all of the elements have been {@link #remove removed}. *

* Concurrent modifications are not directly supported, and for most * collection implementations will throw a * ConcurrentModificationException. * * @since Commons Collections 3.2 * @version $Revision: 1.1 $ $Date: 2004/07/17 21:02:47 $ * * @author Eric Crampton */ public class LoopingListIterator implements ResettableIterator { /** The list to base the iterator on */ private List list; /** The current list iterator */ private ListIterator iterator; /** * Constructor that wraps a list. *

* There is no way to reset a ListIterator instance without * recreating it from the original source, so the List must be * passed in and a reference to it held. * * @param list the list to wrap * @throws NullPointerException if the list it null */ public LoopingListIterator(List list) { if (list == null) { throw new NullPointerException("The list must not be null"); } this.list = list; reset(); } /** * Returns whether this iterator has any more elements. *

* Returns false only if the list originally had zero elements, or * all elements have been {@link #remove removed}. * * @return true if there are more elements */ public boolean hasNext() { return !list.isEmpty(); } /** * Returns the next object in the list. *

* If at the end of the list, returns the first element. * * @return the object after the last element returned * @throws NoSuchElementException if there are no elements in the list */ public Object next() { if (list.isEmpty()) { throw new NoSuchElementException( "There are no elements for this iterator to loop on"); } if (iterator.hasNext() == false) { reset(); } return iterator.next(); } /** * Returns the index of the element that would be returned by a * subsequent call to {@link #next}. *

* As would be expected, if the iterator is at the physical end of * the underlying list, 0 is returned, signifying the beginning of * the list. * * @return the index of the element that would be returned if next() were called * @throws NoSuchElementException if there are no elements in the list */ public int nextIndex() { if (list.isEmpty()) { throw new NoSuchElementException( "There are no elements for this iterator to loop on"); } if (iterator.hasNext() == false) { return 0; } else { return iterator.nextIndex(); } } /** * Returns whether this iterator has any more previous elements. *

* Returns false only if the list originally had zero elements, or * all elements have been {@link #remove removed}. * * @return true if there are more elements */ public boolean hasPrevious() { return !list.isEmpty(); } /** * Returns the previous object in the list. *

* If at the beginning of the list, return the last element. Note * that in this case, traversal to find that element takes linear time. * * @return the object before the last element returned * @throws NoSuchElementException if there are no elements in the list */ public Object previous() { if (list.isEmpty()) { throw new NoSuchElementException( "There are no elements for this iterator to loop on"); } if (iterator.hasPrevious() == false) { Object result = null; while (iterator.hasNext()) { result = iterator.next(); } iterator.previous(); return result; } else { return iterator.previous(); } } /** * Returns the index of the element that would be returned by a * subsequent call to {@link #previous}. *

* As would be expected, if at the iterator is at the physical * beginning of the underlying list, the list's size minus one is * returned, signifying the end of the list. * * @return the index of the element that would be returned if previous() were called * @throws NoSuchElementException if there are no elements in the list */ public int previousIndex() { if (list.isEmpty()) { throw new NoSuchElementException( "There are no elements for this iterator to loop on"); } if (iterator.hasPrevious() == false) { return list.size() - 1; } else { return iterator.previousIndex(); } } /** * Removes the previously retrieved item from the underlying list. *

* This feature is only supported if the underlying list's * {@link List#iterator iterator} method returns an implementation * that supports it. *

* This method can only be called after at least one {@link #next} * or {@link #previous} method call. After a removal, the remove * method may not be called again until another {@link #next} or * {@link #previous} has been performed. If the {@link #reset} is * called, then remove may not be called until {@link #next} or * {@link #previous} is called again. * * @throws UnsupportedOperationException if the remove method is * not supported by the iterator implementation of the underlying * list */ public void remove() { iterator.remove(); } /** * Inserts the specified element into the underlying list. *

* The element is inserted before the next element that would be * returned by {@link #next}, if any, and after the next element * that would be returned by {@link #previous}, if any. *

* This feature is only supported if the underlying list's * {@link List#listIterator} method returns an implementation * that supports it. * * @param obj the element to insert * @throws UnsupportedOperationException if the add method is not * supported by the iterator implementation of the underlying list */ public void add(Object obj) { iterator.add(obj); } /** * Replaces the last element that was returned by {@link #next} or * {@link #previous}. *

* This feature is only supported if the underlying list's * {@link List#listIterator} method returns an implementation * that supports it. * * @param obj the element with which to replace the last element returned * @throws UnsupportedOperationException if the set method is not * supported by the iterator implementation of the underlying list */ public void set(Object obj) { iterator.set(obj); } /** * Resets the iterator back to the start of the list. */ public void reset() { iterator = list.listIterator(); } /** * Gets the size of the list underlying the iterator. * * @return the current list size */ public int size() { return list.size(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org