View Javadoc

1   /*
2    *  Copyright 1999-2004 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package net.sf.collections15.iterators;
17  
18  import java.util.Iterator;
19  import java.util.NoSuchElementException;
20  
21  import net.sf.collections15.Predicate;
22  
23  /*** 
24   * Decorates an <code>Iterator</code> such that only elements matching a
25   * predicate filter are returned.
26   *
27   * @since Commons Collections 1.0
28   * @version $Revision: 1.1 $ $Date: 2005/02/27 19:33:42 $
29   * 
30   * @author James Strachan
31   * @author Jan Sorensen
32   * @author Ralph Wagner
33   * @author Stephen Colebourne
34   * @author Mauro Franceschini (port to 5.0)
35   */
36  public class FilterIterator<E> implements Iterator<E> {
37  
38      // Instance fields
39      // -------------------------------------------------------------------------
40      
41      /*** The iterator being used */
42      private Iterator<E> iterator;
43      
44      /*** The predicate being used */
45      private Predicate<E> predicate;
46      
47      /*** The next object in the iteration */
48      private E nextObject;
49      
50      /*** Whether the next object has been calculated yet */
51      private boolean nextObjectSet = false;
52  
53      // Constructors
54      // -------------------------------------------------------------------------
55      
56      /***
57       * Constructs a new <code>FilterIterator</code> that will not function
58       * until {@link #setIterator(Iterator) setIterator} and
59       * {@link #setPredicate(Predicate) setPredicate} are invoked.
60       */
61      public FilterIterator() {
62          super();
63      }
64  
65      /***
66       * Constructs a new <code>FilterIterator</code> that will not function
67       * until {@link #setPredicate(Predicate) setPredicate} is invoked.
68       *
69       * @param iterator the iterator to use
70       */
71      public FilterIterator(Iterator<E> iterator) {
72          super();
73          this.iterator = iterator;
74      }
75  
76      /***
77       * Constructs a new <code>FilterIterator</code> that will use the
78       * given iterator and predicate.
79       *
80       * @param iterator the iterator to use
81       * @param predicate the predicate to use
82       */
83      public FilterIterator(Iterator<E> iterator, Predicate<E> predicate) {
84          super();
85          this.iterator = iterator;
86          this.predicate = predicate;
87      }
88  
89      // Iterator interface methods
90      // -------------------------------------------------------------------------
91      
92      /*** 
93       * Returns <code>true</code> if the underlying iterator contains an object
94       * that matches the predicate.
95       *
96       * @return <code>true</code> if there is another object that matches the
97       *  predicate 
98       */
99      public boolean hasNext() {
100         if (nextObjectSet) {
101             return true;
102         } else {
103             return setNextObject();
104         }
105     }
106 
107     /*** 
108      * Returns the next object that matches the predicate.
109      * 
110      * @return the next object which matches the given predicate
111      * 
112      * @throws NoSuchElementException if there are no more elements that match
113      *  the predicate 
114      */
115     public E next() {
116         if (!nextObjectSet) {
117             if (!setNextObject()) {
118                 throw new NoSuchElementException();
119             }
120         }
121         nextObjectSet = false;
122         return nextObject;
123     }
124 
125     /***
126      * Removes from the underlying collection of the base iterator the last
127      * element returned by this iterator.
128      * <p>
129      * This method can only be called if <code>next()</code> was called, but not
130      * after <code>hasNext()</code>, because the <code>hasNext()</code> call
131      * changes the base iterator.
132      * 
133      * @throws IllegalStateException if <code>hasNext()</code> has already
134      *  been called.
135      */
136     public void remove() {
137         if (nextObjectSet) {
138             throw new IllegalStateException("remove() cannot be called");
139         }
140         iterator.remove();
141     }
142 
143     // Properties
144     // -------------------------------------------------------------------------
145     
146     /*** 
147      * Gets the iterator this iterator is using.
148      * 
149      * @return the iterator.
150      */
151     public Iterator<E> getIterator() {
152         return iterator;
153     }
154 
155     /*** 
156      * Sets the iterator for this iterator to use.
157      * <p>
158      * If iteration has started, this effectively resets the iterator.
159      * 
160      * @param iterator the iterator to use
161      */
162     public void setIterator(Iterator<E> iterator) {
163         this.iterator = iterator;
164     }
165 
166     /*** 
167      * Gets the predicate this iterator is using.
168      * 
169      * @return the predicate.
170      */
171     public Predicate<E> getPredicate() {
172         return predicate;
173     }
174 
175     /*** 
176      * Sets the predicate this the iterator to use.
177      * 
178      * @param predicate the predicate to use
179      */
180     public void setPredicate(Predicate<E> predicate) {
181         this.predicate = predicate;
182     }
183 
184     // Private methods
185     // -------------------------------------------------------------------------
186     
187     /***
188      * Set nextObject to the next object.
189      * 
190      * @return <code>false</code> if there are no more objects and
191      *  <code>true</code> otherwise
192      */
193     private boolean setNextObject() {
194         while (iterator.hasNext()) {
195             E object = iterator.next();
196             if (predicate.evaluate(object)) {
197                 nextObject = object;
198                 nextObjectSet = true;
199                 return true;
200             }
201         }
202         return false;
203     }
204 }