From 0543f907c1387ef775068d5c03a4659457d046ae Mon Sep 17 00:00:00 2001 From: Brent Worden Date: Tue, 24 May 2011 02:46:02 +0000 Subject: [PATCH] COLLECTIONS-213. Added IteratorIterable adaptor class. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1126836 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/collections/IteratorUtils.java | 15 ++++ .../iterators/IteratorIterable.java | 72 +++++++++++++++++++ .../collections/TestIteratorUtils.java | 29 ++++++++ .../iterators/TestIteratorIterable.java | 54 ++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 src/java/org/apache/commons/collections/iterators/IteratorIterable.java create mode 100644 src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java diff --git a/src/java/org/apache/commons/collections/IteratorUtils.java b/src/java/org/apache/commons/collections/IteratorUtils.java index a0b7d9134..c1b5f1cd8 100644 --- a/src/java/org/apache/commons/collections/IteratorUtils.java +++ b/src/java/org/apache/commons/collections/IteratorUtils.java @@ -41,6 +41,7 @@ import org.apache.commons.collections.iterators.FilterIterator; import org.apache.commons.collections.iterators.FilterListIterator; import org.apache.commons.collections.iterators.IteratorChain; import org.apache.commons.collections.iterators.IteratorEnumeration; +import org.apache.commons.collections.iterators.IteratorIterable; import org.apache.commons.collections.iterators.ListIteratorWrapper; import org.apache.commons.collections.iterators.LoopingIterator; import org.apache.commons.collections.iterators.LoopingListIterator; @@ -757,6 +758,20 @@ public class IteratorUtils { return new IteratorEnumeration(iterator); } + /** + * Gets an iterable that wraps an iterator. + * + * @param iterator the iterator to use, not null + * @return a new, single use iterable + * @throws NullPointerException if iterator is null + */ + public static Iterable asIterable(Iterator iterator) { + if (iterator == null) { + throw new NullPointerException("Iterator must not be null"); + } + return new IteratorIterable(iterator); + } + /** * Gets a list iterator based on a simple iterator. *

diff --git a/src/java/org/apache/commons/collections/iterators/IteratorIterable.java b/src/java/org/apache/commons/collections/iterators/IteratorIterable.java new file mode 100644 index 000000000..23e78b35c --- /dev/null +++ b/src/java/org/apache/commons/collections/iterators/IteratorIterable.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.Iterator; + +/** + * Adapter to make an {@link Iterator Iterator} instance appear to be an + * {@link Iterable Iterable} instance. Unlike normal iterable instance, the + * {@link #iterator()} method always returns the same iterator instance. This + * prohibits this iterator to be only usable for one iterative operation. + * + * @since Commons Collections 4.0 + * @version $Revision: $ $Date: $ + */ +public class IteratorIterable implements Iterable { + + /** + * Factory method to create an {@link Iterator Iterator} from another + * iterator over objects of a different subtype. + */ + private static Iterator createTypesafeIterator( + final Iterator iterator) { + return new Iterator() { + public boolean hasNext() { + return iterator.hasNext(); + } + + public E next() { + return iterator.next(); + } + + public void remove() { + iterator.remove(); + } + }; + } + + /** the iterator being used. */ + private final Iterator iterator; + + /** + * Constructs a new IteratorIterable that will use the given + * iterator. + * + * @param iterator the iterator to use. + */ + public IteratorIterable(Iterator iterator) { + super(); + this.iterator = createTypesafeIterator(iterator); + } + + /** + * Gets the iterator wrapped by this iterable. + * + * @return the iterator + */ + public Iterator iterator() { + return iterator; + } +} diff --git a/src/test/org/apache/commons/collections/TestIteratorUtils.java b/src/test/org/apache/commons/collections/TestIteratorUtils.java index f3ecfece0..1e437ac95 100644 --- a/src/test/org/apache/commons/collections/TestIteratorUtils.java +++ b/src/test/org/apache/commons/collections/TestIteratorUtils.java @@ -48,6 +48,35 @@ public class TestIteratorUtils extends BulkTest { return BulkTest.makeSuite(TestIteratorUtils.class); } + public void testAsIterable() { + List list = new ArrayList(); + list.add(Integer.valueOf(0)); + list.add(Integer.valueOf(1)); + list.add(Integer.valueOf(2)); + Iterator iterator = list.iterator(); + + Iterable iterable = IteratorUtils.asIterable(iterator); + int expected = 0; + for(Integer actual : iterable) { + assertEquals(expected, actual.intValue()); + ++expected; + } + + // single use iterator + for(Integer actual : iterable) { + fail("should not be able to iterate twice"); + } + } + + public void testAsIterableNull() { + try { + IteratorUtils.asIterable(null); + fail("Expecting NullPointerException"); + } catch (NullPointerException ex) { + // success + } + } + public void testToList() { List list = new ArrayList(); list.add(new Integer(1)); diff --git a/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java b/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java new file mode 100644 index 000000000..c811fc677 --- /dev/null +++ b/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.Iterator; +import java.util.List; + +import junit.framework.Test; + +import org.apache.commons.collections.BulkTest; + +/** + * Tests for IteratorIterable. + * + * @version $Revision: $ $Date: $ + */ +public class TestIteratorIterable extends BulkTest { + + public static Test suite() { + return BulkTest.makeSuite(TestIteratorIterable.class); + } + + public TestIteratorIterable(String name) { + super(name); + } + + public void testIterator() { + List list = new ArrayList(); + list.add(Integer.valueOf(0)); + list.add(Integer.valueOf(1)); + list.add(Integer.valueOf(2)); + Iterator iter = list.iterator(); + + Iterable iterable = new IteratorIterable(iter); + int expected = 0; + for (Number actual : iterable) { + assertEquals(expected, actual.intValue()); + ++expected; + } + } +} +