View Javadoc

1   package com.atlassian.plugin.util.collect;
2   
3   /*
4    *  Copyright 1999-2004,2006 The Apache Software Foundation
5    *
6    *  Licensed under the Apache License, Version 2.0 (the "License");
7    *  you may not use this file except in compliance with the License.
8    *  You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  import java.util.Iterator;
20  import java.util.NoSuchElementException;
21  
22  /** 
23   * Decorates another {@link Iterator} using a predicate to filter elements.
24   * <p>
25   * This iterator decorates the underlying iterator, only allowing through
26   * those elements that match the specified {@link Predicate Predicate}.
27   *
28   * @since Commons Collections 1.0
29   * @version $Revision: 366576 $ $Date: 2006-01-06 22:07:07 +0000 (Fri, 06 Jan 2006) $
30   * 
31   * @author James Strachan
32   * @author Jan Sorensen
33   * @author Ralph Wagner
34   * @author Stephen Colebourne
35   */
36  class FilteredIterator<T> implements Iterator<T>
37  {
38  
39      /** The iterator being used */
40      private final Iterator<T> iterator;
41      /** The predicate being used */
42      private final Predicate<T> predicate;
43      /** The next object in the iteration */
44      private T nextObject;
45      /** Whether the next object has been calculated yet */
46      private boolean nextObjectSet = false;
47  
48      //-----------------------------------------------------------------------
49  
50      /**
51       * Constructs a new <code>FilterIterator</code> that will use the
52       * given iterator and predicate.
53       *
54       * @param iterator  the iterator to use
55       * @param predicate  the predicate to use
56       */
57      FilteredIterator(final Iterator<T> iterator, final Predicate<T> predicate)
58      {
59          this.iterator = iterator;
60          this.predicate = predicate;
61      }
62  
63      //-----------------------------------------------------------------------
64      /** 
65       * Returns true if the underlying iterator contains an object that 
66       * matches the predicate.
67       *
68       * @return true if there is another object that matches the predicate
69       * @throws NullPointerException if either the iterator or predicate are null
70       */
71      public boolean hasNext()
72      {
73          if (nextObjectSet)
74          {
75              return true;
76          }
77          else
78          {
79              return setNextObject();
80          }
81      }
82  
83      /** 
84       * Returns the next object that matches the predicate.
85       *
86       * @return the next object which matches the given predicate
87       * @throws NullPointerException if either the iterator or predicate are null
88       * @throws NoSuchElementException if there are no more elements that
89       *  match the predicate 
90       */
91      public T next()
92      {
93          if (!nextObjectSet)
94          {
95              if (!setNextObject())
96              {
97                  throw new NoSuchElementException();
98              }
99          }
100         nextObjectSet = false;
101         return nextObject;
102     }
103 
104     /**
105      * Removes from the underlying collection of the base iterator the last
106      * element returned by this iterator.
107      * This method can only be called
108      * if <code>next()</code> was called, but not after
109      * <code>hasNext()</code>, because the <code>hasNext()</code> call
110      * changes the base iterator.
111      *
112      * @throws IllegalStateException if <code>hasNext()</code> has already
113      *  been called.
114      */
115     public void remove()
116     {
117         if (nextObjectSet)
118         {
119             throw new IllegalStateException("remove() cannot be called");
120         }
121         iterator.remove();
122     }
123 
124     //-----------------------------------------------------------------------
125 
126     /**
127      * Set nextObject to the next object. If there are no more 
128      * objects then return false. Otherwise, return true.
129      */
130     private boolean setNextObject()
131     {
132         while (iterator.hasNext())
133         {
134             final T object = iterator.next();
135             if (predicate.evaluate(object))
136             {
137                 nextObject = object;
138                 nextObjectSet = true;
139                 return true;
140             }
141         }
142         return false;
143     }
144 }