View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.iterators;
18  
19  import static org.apache.commons.collections4.functors.TruePredicate.truePredicate;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.NoSuchElementException;
27  
28  import org.apache.commons.collections4.Predicate;
29  import org.apache.commons.collections4.functors.NotNullPredicate;
30  
31  /**
32   * Test the filter iterator.
33   *
34   */
35  public class FilterIteratorTest<E> extends AbstractIteratorTest<E> {
36  
37      /** Creates new TestFilterIterator */
38      public FilterIteratorTest(final String name) {
39          super(name);
40      }
41  
42      private String[] array;
43      private List<E> list;
44      private FilterIterator<E> iterator;
45  
46      /**
47       * Set up instance variables required by this test case.
48       */
49      @Override
50      public void setUp() {
51          array = new String[] { "a", "b", "c" };
52          initIterator();
53      }
54  
55      /**
56       * Tear down instance variables required by this test case.
57       */
58      @Override
59      public void tearDown() throws Exception {
60          iterator = null;
61      }
62  
63      /**
64       * Returns an full iterator wrapped in a
65       * FilterIterator that blocks all the elements
66       *
67       * @return "empty" FilterIterator
68       */
69      @Override
70      public FilterIterator<E> makeEmptyIterator() {
71          return makeBlockAllFilter(new ArrayIterator<E>(array));
72      }
73  
74      /**
75       * Returns an array with elements wrapped in a pass-through
76       * FilterIterator
77       *
78       * @return a filtered iterator
79       */
80      @Override
81      @SuppressWarnings("unchecked")
82      public FilterIterator<E> makeObject() {
83          list = new ArrayList<>(Arrays.asList((E[]) array));
84          return makePassThroughFilter(list.iterator());
85      }
86  
87      public void testRepeatedHasNext() {
88          for (int i = 0; i <= array.length; i++) {
89              assertTrue(iterator.hasNext());
90          }
91      }
92  
93      @SuppressWarnings("unused")
94      public void testRepeatedNext() {
95          for (final String element : array) {
96              iterator.next();
97          }
98          verifyNoMoreElements();
99      }
100 
101     public void testReturnValues() {
102         verifyElementsInPredicate(new String[0]);
103         verifyElementsInPredicate(new String[] { "a" });
104         verifyElementsInPredicate(new String[] { "b" });
105         verifyElementsInPredicate(new String[] { "c" });
106         verifyElementsInPredicate(new String[] { "a", "b" });
107         verifyElementsInPredicate(new String[] { "a", "c" });
108         verifyElementsInPredicate(new String[] { "b", "c" });
109         verifyElementsInPredicate(new String[] { "a", "b", "c" });
110     }
111 
112     /**
113      * Test that when the iterator is changed, the hasNext method returns the
114      * correct response for the new iterator.
115      */
116     @SuppressWarnings("unchecked")
117     public void testSetIterator() {
118         final Iterator<E> iter1 = Collections.singleton((E) new Object()).iterator();
119         final Iterator<E> iter2 = Collections.<E>emptyList().iterator();
120 
121         final FilterIterator<E> filterIterator = new FilterIterator<>(iter1);
122         filterIterator.setPredicate(truePredicate());
123         // this iterator has elements
124         assertEquals(true, filterIterator.hasNext());
125 
126         // this iterator has no elements
127         filterIterator.setIterator(iter2);
128         assertEquals(false, filterIterator.hasNext());
129     }
130 
131     /**
132      * Test that when the predicate is changed, the hasNext method returns the
133      * correct response for the new predicate.
134      */
135     public void testSetPredicate() {
136         final Iterator<E> iter = Collections.singleton((E) null).iterator();
137 
138         final FilterIterator<E> filterIterator = new FilterIterator<>(iter);
139         filterIterator.setPredicate(truePredicate());
140         // this predicate matches
141         assertEquals(true, filterIterator.hasNext());
142 
143         // this predicate doesn't match
144         filterIterator.setPredicate(NotNullPredicate.notNullPredicate());
145         assertEquals(false, filterIterator.hasNext());
146     }
147 
148     private void verifyNoMoreElements() {
149         assertTrue(!iterator.hasNext());
150         try {
151             iterator.next();
152             fail("NoSuchElementException expected");
153         }
154         catch (final NoSuchElementException e) {
155             // success
156         }
157     }
158 
159     private void verifyElementsInPredicate(final String[] elements) {
160         final Predicate<E> pred = new Predicate<E>() {
161             @Override
162             public boolean evaluate(final E x) {
163                 for (final String element : elements) {
164                     if (element.equals(x)) {
165                         return true;
166                     }
167                 }
168                 return false;
169             }
170         };
171         initIterator();
172         iterator.setPredicate(pred);
173         for (int i = 0; i < elements.length; i++) {
174             final String s = (String)iterator.next();
175             assertEquals(elements[i], s);
176             assertTrue(i == elements.length - 1 ? !iterator.hasNext() : iterator.hasNext());
177         }
178         verifyNoMoreElements();
179 
180         // test removal
181         initIterator();
182         iterator.setPredicate(pred);
183         if (iterator.hasNext()) {
184             final Object last = iterator.next();
185             iterator.remove();
186             assertTrue("Base of FilterIterator still contains removed element.", !list.contains(last));
187         }
188     }
189 
190     private void initIterator() {
191         iterator = makeObject();
192     }
193 
194     /**
195      * Returns a FilterIterator that does not filter
196      * any of its elements
197      *
198      * @param i      the Iterator to "filter"
199      * @return "filtered" iterator
200      */
201     protected FilterIterator<E> makePassThroughFilter(final Iterator<E> i) {
202         final Predicate<E> pred = new Predicate<E>() {
203                 @Override
204                 public boolean evaluate(final E x) { return true; }
205         };
206         return new FilterIterator<>(i, pred);
207     }
208 
209     /**
210      * Returns a FilterIterator that blocks
211      * all of its elements
212      *
213      * @param i      the Iterator to "filter"
214      * @return "filtered" iterator
215      */
216     protected FilterIterator<E> makeBlockAllFilter(final Iterator<E> i) {
217         final Predicate<E> pred = new Predicate<E>() {
218                 @Override
219                 public boolean evaluate(final E x) { return false; }
220         };
221         return new FilterIterator<>(i, pred);
222     }
223 }
224