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.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.NoSuchElementException;
28  
29  import org.apache.commons.collections4.IteratorUtils;
30  import org.apache.commons.collections4.Predicate;
31  import org.junit.jupiter.api.BeforeEach;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Tests the LazyIteratorChain class.
36   */
37  public class LazyIteratorChainTest extends AbstractIteratorTest<String> {
38  
39      protected String[] testArray = {
40          "One", "Two", "Three", "Four", "Five", "Six"
41      };
42  
43      protected List<String> list1;
44      protected List<String> list2;
45      protected List<String> list3;
46  
47      @Override
48      public LazyIteratorChain<String> makeEmptyIterator() {
49          return new LazyIteratorChain<String>() {
50              @Override
51              protected Iterator<String> nextIterator(final int count) {
52                  return null;
53              }
54          };
55      }
56  
57      @Override
58      public LazyIteratorChain<String> makeObject() {
59          return new LazyIteratorChain<String>() {
60              @Override
61              protected Iterator<String> nextIterator(final int count) {
62                  switch (count) {
63                  case 1:
64                      return list1.iterator();
65                  case 2:
66                      return list2.iterator();
67                  case 3:
68                      return list3.iterator();
69                  }
70                  return null;
71              }
72          };
73      }
74  
75      @BeforeEach
76      public void setUp() {
77          list1 = new ArrayList<>();
78          list1.add("One");
79          list1.add("Two");
80          list1.add("Three");
81          list2 = new ArrayList<>();
82          list2.add("Four");
83          list3 = new ArrayList<>();
84          list3.add("Five");
85          list3.add("Six");
86      }
87  
88      @Test
89      public void testEmptyChain() {
90          final LazyIteratorChain<String> chain = makeEmptyIterator();
91          assertFalse(chain.hasNext());
92          assertThrows(NoSuchElementException.class, () -> chain.next());
93          assertThrows(IllegalStateException.class, () -> chain.remove());
94      }
95  
96      @Test
97      public void testFirstIteratorIsEmptyBug() {
98          final List<String> empty = new ArrayList<>();
99          final List<String> notEmpty = new ArrayList<>();
100         notEmpty.add("A");
101         notEmpty.add("B");
102         notEmpty.add("C");
103         final LazyIteratorChain<String> chain = new LazyIteratorChain<String>() {
104             @Override
105             protected Iterator<String> nextIterator(final int count) {
106                 switch (count) {
107                 case 1:
108                     return empty.iterator();
109                 case 2:
110                     return notEmpty.iterator();
111                 }
112                 return null;
113             }
114         };
115         assertTrue(chain.hasNext(), "should have next");
116         assertEquals("A", chain.next());
117         assertTrue(chain.hasNext(), "should have next");
118         assertEquals("B", chain.next());
119         assertTrue(chain.hasNext(), "should have next");
120         assertEquals("C", chain.next());
121         assertFalse(chain.hasNext(), "should not have next");
122     }
123 
124     @Test
125     public void testIterator() {
126         final Iterator<String> iter = makeObject();
127         for (final String testValue : testArray) {
128             final Object iterValue = iter.next();
129             assertEquals(testValue, iterValue, "Iteration value is correct");
130         }
131         assertFalse(iter.hasNext(), "Iterator should now be empty");
132         assertThrows(NoSuchElementException.class, iter::next);
133     }
134 
135     @Test
136     @Override
137     public void testRemove() {
138         final Iterator<String> iter = makeObject();
139 
140         assertThrows(IllegalStateException.class, () -> iter.remove(),
141                 "Calling remove before the first call to next() should throw an exception");
142 
143         for (final String testValue : testArray) {
144             final String iterValue = iter.next();
145 
146             assertEquals(testValue, iterValue, "Iteration value is correct");
147 
148             if (!iterValue.equals("Four")) {
149                 iter.remove();
150             }
151         }
152 
153         assertTrue(list1.isEmpty(), "List is empty");
154         assertEquals(1, list2.size(), "List is empty");
155         assertTrue(list3.isEmpty(), "List is empty");
156     }
157 
158     @Test
159     public void testRemoveFromFilteredIterator() {
160 
161         final Predicate<Integer> myPredicate = i -> i.compareTo(Integer.valueOf(4)) < 0;
162 
163         final List<Integer> list1 = new ArrayList<>();
164         final List<Integer> list2 = new ArrayList<>();
165 
166         list1.add(Integer.valueOf(1));
167         list1.add(Integer.valueOf(2));
168         list2.add(Integer.valueOf(3));
169         list2.add(Integer.valueOf(4)); // will be ignored by the predicate
170 
171         final Iterator<Integer> it1 = IteratorUtils.filteredIterator(list1.iterator(), myPredicate);
172         final Iterator<Integer> it2 = IteratorUtils.filteredIterator(list2.iterator(), myPredicate);
173 
174         final Iterator<Integer> it = IteratorUtils.chainedIterator(it1, it2);
175         while (it.hasNext()) {
176             it.next();
177             it.remove();
178         }
179         assertEquals(0, list1.size());
180         assertEquals(1, list2.size());
181     }
182 
183 }