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 org.apache.commons.collections.iterators;
  17. import java.util.Iterator;
  18. import java.util.NoSuchElementException;
  19. import org.apache.commons.collections.Predicate;
  20. /**
  21. * Decorates an iterator such that only elements matching a predicate filter
  22. * are returned.
  23. *
  24. * @since Commons Collections 1.0
  25. * @version $Revision: 1.8 $ $Date: 2004/02/18 00:59:50 $
  26. *
  27. * @author James Strachan
  28. * @author Jan Sorensen
  29. * @author Ralph Wagner
  30. * @author Stephen Colebourne
  31. */
  32. public class FilterIterator implements Iterator {
  33. /** The iterator being used */
  34. private Iterator iterator;
  35. /** The predicate being used */
  36. private Predicate predicate;
  37. /** The next object in the iteration */
  38. private Object nextObject;
  39. /** Whether the next object has been calculated yet */
  40. private boolean nextObjectSet = false;
  41. //-----------------------------------------------------------------------
  42. /**
  43. * Constructs a new <code>FilterIterator</code> that will not function
  44. * until {@link #setIterator(Iterator) setIterator} is invoked.
  45. */
  46. public FilterIterator() {
  47. super();
  48. }
  49. /**
  50. * Constructs a new <code>FilterIterator</code> that will not function
  51. * until {@link #setPredicate(Predicate) setPredicate} is invoked.
  52. *
  53. * @param iterator the iterator to use
  54. */
  55. public FilterIterator(Iterator iterator) {
  56. super();
  57. this.iterator = iterator;
  58. }
  59. /**
  60. * Constructs a new <code>FilterIterator</code> that will use the
  61. * given iterator and predicate.
  62. *
  63. * @param iterator the iterator to use
  64. * @param predicate the predicate to use
  65. */
  66. public FilterIterator(Iterator iterator, Predicate predicate) {
  67. super();
  68. this.iterator = iterator;
  69. this.predicate = predicate;
  70. }
  71. //-----------------------------------------------------------------------
  72. /**
  73. * Returns true if the underlying iterator contains an object that
  74. * matches the predicate.
  75. *
  76. * @return true if there is another object that matches the predicate
  77. */
  78. public boolean hasNext() {
  79. if (nextObjectSet) {
  80. return true;
  81. } else {
  82. return setNextObject();
  83. }
  84. }
  85. /**
  86. * Returns the next object that matches the predicate.
  87. *
  88. * @return the next object which matches the given predicate
  89. * @throws NoSuchElementException if there are no more elements that
  90. * match the predicate
  91. */
  92. public Object next() {
  93. if (!nextObjectSet) {
  94. if (!setNextObject()) {
  95. throw new NoSuchElementException();
  96. }
  97. }
  98. nextObjectSet = false;
  99. return nextObject;
  100. }
  101. /**
  102. * Removes from the underlying collection of the base iterator the last
  103. * element returned by this iterator.
  104. * This method can only be called
  105. * if <code>next()</code> was called, but not after
  106. * <code>hasNext()</code>, because the <code>hasNext()</code> call
  107. * changes the base iterator.
  108. *
  109. * @throws IllegalStateException if <code>hasNext()</code> has already
  110. * been called.
  111. */
  112. public void remove() {
  113. if (nextObjectSet) {
  114. throw new IllegalStateException("remove() cannot be called");
  115. }
  116. iterator.remove();
  117. }
  118. //-----------------------------------------------------------------------
  119. /**
  120. * Gets the iterator this iterator is using.
  121. *
  122. * @return the iterator.
  123. */
  124. public Iterator getIterator() {
  125. return iterator;
  126. }
  127. /**
  128. * Sets the iterator for this iterator to use.
  129. * If iteration has started, this effectively resets the iterator.
  130. *
  131. * @param iterator the iterator to use
  132. */
  133. public void setIterator(Iterator iterator) {
  134. this.iterator = iterator;
  135. }
  136. //-----------------------------------------------------------------------
  137. /**
  138. * Gets the predicate this iterator is using.
  139. *
  140. * @return the predicate.
  141. */
  142. public Predicate getPredicate() {
  143. return predicate;
  144. }
  145. /**
  146. * Sets the predicate this the iterator to use.
  147. *
  148. * @param predicate the transformer to use
  149. */
  150. public void setPredicate(Predicate predicate) {
  151. this.predicate = predicate;
  152. }
  153. //-----------------------------------------------------------------------
  154. /**
  155. * Set nextObject to the next object. If there are no more
  156. * objects then return false. Otherwise, return true.
  157. */
  158. private boolean setNextObject() {
  159. while (iterator.hasNext()) {
  160. Object object = iterator.next();
  161. if (predicate.evaluate(object)) {
  162. nextObject = object;
  163. nextObjectSet = true;
  164. return true;
  165. }
  166. }
  167. return false;
  168. }
  169. }