001: /*
002: * Copyright 1999-2004,2006 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.Iterator;
019: import java.util.NoSuchElementException;
020:
021: import org.apache.commons.collections.Predicate;
022:
023: /**
024: * Decorates another {@link Iterator} using a predicate to filter elements.
025: * <p>
026: * This iterator decorates the underlying iterator, only allowing through
027: * those elements that match the specified {@link Predicate Predicate}.
028: *
029: * @since Commons Collections 1.0
030: * @version $Revision: 366576 $ $Date: 2006-01-06 22:07:07 +0000 (Fri, 06 Jan 2006) $
031: *
032: * @author James Strachan
033: * @author Jan Sorensen
034: * @author Ralph Wagner
035: * @author Stephen Colebourne
036: */
037: public class FilterIterator implements Iterator {
038:
039: /** The iterator being used */
040: private Iterator iterator;
041: /** The predicate being used */
042: private Predicate predicate;
043: /** The next object in the iteration */
044: private Object nextObject;
045: /** Whether the next object has been calculated yet */
046: private boolean nextObjectSet = false;
047:
048: //-----------------------------------------------------------------------
049: /**
050: * Constructs a new <code>FilterIterator</code> that will not function
051: * until {@link #setIterator(Iterator) setIterator} is invoked.
052: */
053: public FilterIterator() {
054: super ();
055: }
056:
057: /**
058: * Constructs a new <code>FilterIterator</code> that will not function
059: * until {@link #setPredicate(Predicate) setPredicate} is invoked.
060: *
061: * @param iterator the iterator to use
062: */
063: public FilterIterator(Iterator iterator) {
064: super ();
065: this .iterator = iterator;
066: }
067:
068: /**
069: * Constructs a new <code>FilterIterator</code> that will use the
070: * given iterator and predicate.
071: *
072: * @param iterator the iterator to use
073: * @param predicate the predicate to use
074: */
075: public FilterIterator(Iterator iterator, Predicate predicate) {
076: super ();
077: this .iterator = iterator;
078: this .predicate = predicate;
079: }
080:
081: //-----------------------------------------------------------------------
082: /**
083: * Returns true if the underlying iterator contains an object that
084: * matches the predicate.
085: *
086: * @return true if there is another object that matches the predicate
087: * @throws NullPointerException if either the iterator or predicate are null
088: */
089: public boolean hasNext() {
090: if (nextObjectSet) {
091: return true;
092: } else {
093: return setNextObject();
094: }
095: }
096:
097: /**
098: * Returns the next object that matches the predicate.
099: *
100: * @return the next object which matches the given predicate
101: * @throws NullPointerException if either the iterator or predicate are null
102: * @throws NoSuchElementException if there are no more elements that
103: * match the predicate
104: */
105: public Object next() {
106: if (!nextObjectSet) {
107: if (!setNextObject()) {
108: throw new NoSuchElementException();
109: }
110: }
111: nextObjectSet = false;
112: return nextObject;
113: }
114:
115: /**
116: * Removes from the underlying collection of the base iterator the last
117: * element returned by this iterator.
118: * This method can only be called
119: * if <code>next()</code> was called, but not after
120: * <code>hasNext()</code>, because the <code>hasNext()</code> call
121: * changes the base iterator.
122: *
123: * @throws IllegalStateException if <code>hasNext()</code> has already
124: * been called.
125: */
126: public void remove() {
127: if (nextObjectSet) {
128: throw new IllegalStateException("remove() cannot be called");
129: }
130: iterator.remove();
131: }
132:
133: //-----------------------------------------------------------------------
134: /**
135: * Gets the iterator this iterator is using.
136: *
137: * @return the iterator
138: */
139: public Iterator getIterator() {
140: return iterator;
141: }
142:
143: /**
144: * Sets the iterator for this iterator to use.
145: * If iteration has started, this effectively resets the iterator.
146: *
147: * @param iterator the iterator to use
148: */
149: public void setIterator(Iterator iterator) {
150: this .iterator = iterator;
151: nextObject = null;
152: nextObjectSet = false;
153: }
154:
155: //-----------------------------------------------------------------------
156: /**
157: * Gets the predicate this iterator is using.
158: *
159: * @return the predicate
160: */
161: public Predicate getPredicate() {
162: return predicate;
163: }
164:
165: /**
166: * Sets the predicate this the iterator to use.
167: *
168: * @param predicate the predicate to use
169: */
170: public void setPredicate(Predicate predicate) {
171: this .predicate = predicate;
172: nextObject = null;
173: nextObjectSet = false;
174: }
175:
176: //-----------------------------------------------------------------------
177: /**
178: * Set nextObject to the next object. If there are no more
179: * objects then return false. Otherwise, return true.
180: */
181: private boolean setNextObject() {
182: while (iterator.hasNext()) {
183: Object object = iterator.next();
184: if (predicate.evaluate(object)) {
185: nextObject = object;
186: nextObjectSet = true;
187: return true;
188: }
189: }
190: return false;
191: }
192:
193: }
|