001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections.iterators;
017:
018: import java.util.Collection;
019: import java.util.Iterator;
020: import java.util.NoSuchElementException;
021:
022: import org.apache.commons.collections.ResettableIterator;
023:
024: /**
025: * An Iterator that restarts when it reaches the end.
026: * <p>
027: * The iterator will loop continuously around the provided elements, unless
028: * there are no elements in the collection to begin with, or all the elements
029: * have been {@link #remove removed}.
030: * <p>
031: * Concurrent modifications are not directly supported, and for most collection
032: * implementations will throw a ConcurrentModificationException.
033: *
034: * @since Commons Collections 3.0
035: * @version $Revision: 155406 $ $Date: 2005-02-26 12:55:26 +0000 (Sat, 26 Feb 2005) $
036: *
037: * @author <a href="mailto:joncrlsn@users.sf.net">Jonathan Carlson</a>
038: * @author Stephen Colebourne
039: */
040: public class LoopingIterator implements ResettableIterator {
041:
042: /** The collection to base the iterator on */
043: private Collection collection;
044: /** The current iterator */
045: private Iterator iterator;
046:
047: /**
048: * Constructor that wraps a collection.
049: * <p>
050: * There is no way to reset an Iterator instance without recreating it from
051: * the original source, so the Collection must be passed in.
052: *
053: * @param coll the collection to wrap
054: * @throws NullPointerException if the collection is null
055: */
056: public LoopingIterator(Collection coll) {
057: if (coll == null) {
058: throw new NullPointerException(
059: "The collection must not be null");
060: }
061: collection = coll;
062: reset();
063: }
064:
065: /**
066: * Has the iterator any more elements.
067: * <p>
068: * Returns false only if the collection originally had zero elements, or
069: * all the elements have been {@link #remove removed}.
070: *
071: * @return <code>true</code> if there are more elements
072: */
073: public boolean hasNext() {
074: return (collection.size() > 0);
075: }
076:
077: /**
078: * Returns the next object in the collection.
079: * <p>
080: * If at the end of the collection, return the first element.
081: *
082: * @throws NoSuchElementException if there are no elements
083: * at all. Use {@link #hasNext} to avoid this error.
084: */
085: public Object next() {
086: if (collection.size() == 0) {
087: throw new NoSuchElementException(
088: "There are no elements for this iterator to loop on");
089: }
090: if (iterator.hasNext() == false) {
091: reset();
092: }
093: return iterator.next();
094: }
095:
096: /**
097: * Removes the previously retrieved item from the underlying collection.
098: * <p>
099: * This feature is only supported if the underlying collection's
100: * {@link Collection#iterator iterator} method returns an implementation
101: * that supports it.
102: * <p>
103: * This method can only be called after at least one {@link #next} method call.
104: * After a removal, the remove method may not be called again until another
105: * next has been performed. If the {@link #reset} is called, then remove may
106: * not be called until {@link #next} is called again.
107: */
108: public void remove() {
109: iterator.remove();
110: }
111:
112: /**
113: * Resets the iterator back to the start of the collection.
114: */
115: public void reset() {
116: iterator = collection.iterator();
117: }
118:
119: /**
120: * Gets the size of the collection underlying the iterator.
121: *
122: * @return the current collection size
123: */
124: public int size() {
125: return collection.size();
126: }
127:
128: }
|