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.functor;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertSame;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.HashSet;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.NoSuchElementException;
32  import java.util.Set;
33  
34  import org.apache.commons.functor.adapter.LeftBoundPredicate;
35  import org.apache.commons.functor.core.Identity;
36  import org.apache.commons.functor.core.IsEqual;
37  import org.apache.commons.functor.core.Limit;
38  import org.apache.commons.functor.core.Offset;
39  import org.apache.commons.functor.core.algorithm.DoUntil;
40  import org.apache.commons.functor.core.algorithm.DoWhile;
41  import org.apache.commons.functor.core.algorithm.FindWithinGenerator;
42  import org.apache.commons.functor.core.algorithm.FoldLeft;
43  import org.apache.commons.functor.core.algorithm.FoldRight;
44  import org.apache.commons.functor.core.algorithm.GeneratorContains;
45  import org.apache.commons.functor.core.algorithm.InPlaceTransform;
46  import org.apache.commons.functor.core.algorithm.RecursiveEvaluation;
47  import org.apache.commons.functor.core.algorithm.RemoveMatching;
48  import org.apache.commons.functor.core.algorithm.RetainMatching;
49  import org.apache.commons.functor.core.algorithm.UntilDo;
50  import org.apache.commons.functor.core.algorithm.WhileDo;
51  import org.apache.commons.functor.core.composite.UnaryNot;
52  import org.apache.commons.functor.generator.FilteredGenerator;
53  import org.apache.commons.functor.generator.Generator;
54  import org.apache.commons.functor.generator.IteratorToGeneratorAdapter;
55  import org.apache.commons.functor.generator.TransformedGenerator;
56  import org.apache.commons.functor.generator.util.IntegerRange;
57  import org.junit.After;
58  import org.junit.Before;
59  import org.junit.Test;
60  
61  /**
62   * @version $Revision: 1171255 $ $Date: 2011-09-15 22:27:39 +0200 (Thu, 15 Sep 2011) $
63   * @author Rodney Waldhoff
64   */
65  @SuppressWarnings("unchecked")
66  public class TestAlgorithms {
67  
68      // Lifecycle
69      // ------------------------------------------------------------------------
70  
71      @Before
72      public void setUp() throws Exception {
73          list = new ArrayList();
74          evens = new ArrayList();
75          doubled = new ArrayList();
76          listWithDuplicates = new ArrayList();
77          sum = 0;
78          for (int i=0;i<10;i++) {
79              list.add(new Integer(i));
80              doubled.add(new Integer(i*2));
81              listWithDuplicates.add(new Integer(i));
82              listWithDuplicates.add(new Integer(i));
83              sum += i;
84              if (i%2 == 0) {
85                  evens.add(new Integer(i));
86              }
87          }
88      }
89  
90      @After
91      public void tearDown() throws Exception {
92          list = null;
93          evens = null;
94          listWithDuplicates = null;
95          sum = 0;
96      }
97  
98      // Tests
99      // ------------------------------------------------------------------------
100 
101     @Test
102     public void testDetect() {
103         assertEquals(new Integer(3),FindWithinGenerator.instance().evaluate(IteratorToGeneratorAdapter.adapt(list.iterator()),equalsThree));
104         try {
105             FindWithinGenerator.instance().evaluate(IteratorToGeneratorAdapter.adapt(list.iterator()),equalsTwentyThree);
106             fail("Expected NoSuchElementException");
107         } catch(NoSuchElementException e) {
108             // expected
109         }
110     }
111 
112     @Test
113     public void testDetectIfNone() {
114         assertEquals(new Integer(3),new FindWithinGenerator("Xyzzy").evaluate(IteratorToGeneratorAdapter.adapt(list.iterator()),equalsThree));
115         assertEquals("Xyzzy",new FindWithinGenerator("Xyzzy").evaluate(IteratorToGeneratorAdapter.adapt(list.iterator()),equalsTwentyThree));
116     }
117 
118     @Test
119     public void testRun() {
120         Summer summer = new Summer();
121         IteratorToGeneratorAdapter.adapt(list.iterator()).run(summer);
122         assertEquals(sum,summer.sum);
123     }
124 
125     @Test
126     public void testSelect1() {
127         Collection result = new FilteredGenerator(IteratorToGeneratorAdapter.adapt(list.iterator()),isEven).toCollection();
128         assertNotNull(result);
129         assertEquals(evens,result);
130     }
131 
132     @Test
133     public void testSelect2() {
134         ArrayList result = new ArrayList();
135         assertSame(result,new FilteredGenerator(IteratorToGeneratorAdapter.adapt(list.iterator()),isEven).to(result));
136         assertEquals(evens,result);
137     }
138 
139     @Test
140     public void testReject1() {
141         Collection result = new FilteredGenerator(IteratorToGeneratorAdapter.adapt(list.iterator()),new UnaryNot(isOdd)).toCollection();
142         assertNotNull(result);
143         assertEquals(evens,result);
144     }
145 
146     @Test
147     public void testReject2() {
148         ArrayList result = new ArrayList();
149         assertSame(result,new FilteredGenerator(IteratorToGeneratorAdapter.adapt(list.iterator()),new UnaryNot(isOdd)).to(result));
150         assertEquals(evens,result);
151     }
152 
153     @Test
154     public void testRetain() {
155         RetainMatching.instance().run(list.iterator(),isEven);
156         assertEquals(evens,list);
157     }
158 
159     @Test
160     public void testRemove() {
161         RemoveMatching.instance().run(list.iterator(),isOdd);
162         assertEquals(evens,list);
163     }
164 
165     @Test
166     public void testTransform() {
167         InPlaceTransform.instance().run(
168             list.listIterator(),
169             new UnaryFunction() {
170                 public Object evaluate(Object obj) {
171                     return new Integer(((Number) obj).intValue()*2);
172                 }
173             }
174         );
175         assertEquals(doubled,list);
176     }
177 
178     @Test
179     public void testApplyToGenerator() {
180         Generator gen = new IntegerRange(1,5);
181         Summer summer = new Summer();
182 
183         new TransformedGenerator(gen, new Doubler()).run(summer);
184 
185         assertEquals(2*(1+2+3+4),summer.sum);
186     }
187 
188     @Test
189     public void testApply() {
190         Collection result = new TransformedGenerator(IteratorToGeneratorAdapter.adapt(list.iterator()), new Doubler())
191                 .toCollection();
192         assertNotNull(result);
193         assertEquals(doubled,result);
194     }
195 
196     @Test
197     public void testApply2() {
198         Set set = new HashSet();
199         assertSame(set, new TransformedGenerator(IteratorToGeneratorAdapter.adapt(list.iterator()), Identity.instance())
200                 .to(set));
201         assertEquals(list.size(),set.size());
202         for (Iterator iter = list.iterator(); iter.hasNext(); ) {
203             assertTrue(set.contains(iter.next()));
204         }
205     }
206 
207     @Test
208     public void testApply3() {
209         Set set = new HashSet();
210         assertSame(set, new TransformedGenerator(IteratorToGeneratorAdapter.adapt(listWithDuplicates.iterator()),
211                 Identity.instance()).to(set));
212         assertTrue(listWithDuplicates.size() > set.size());
213         for (Iterator iter = listWithDuplicates.iterator(); iter.hasNext(); ) {
214             assertTrue(set.contains(iter.next()));
215         }
216     }
217 
218     @Test
219     public void testContains() {
220         assertTrue(GeneratorContains.instance().test(IteratorToGeneratorAdapter.adapt(list.iterator()),equalsThree));
221         assertFalse(GeneratorContains.instance().test(IteratorToGeneratorAdapter.adapt(list.iterator()),equalsTwentyThree));
222     }
223 
224     @Test
225     public void testFoldLeft() {
226         FoldLeft foldLeft = new FoldLeft(new BinaryFunction() {
227             public Object evaluate(Object a, Object b) {
228                 return new Integer(((Number) a).intValue() + ((Number) b).intValue());
229             }
230         });
231         assertEquals(new Integer(sum), foldLeft.evaluate(IteratorToGeneratorAdapter.adapt(list.iterator())));
232         assertEquals(new Integer(sum), foldLeft.evaluate(IteratorToGeneratorAdapter.adapt(list.iterator()), new Integer(0)));
233     }
234 
235     @Test
236     public void testFoldRight() {
237         FoldRight foldRight = new FoldRight(new BinaryFunction() {
238             public Object evaluate(Object left, Object right) {
239                 StringBuffer buf = left instanceof StringBuffer ? (StringBuffer) left : new StringBuffer().append(left);
240                 return buf.append(right);
241             }
242         });
243         assertEquals("0123456789", foldRight.evaluate(IteratorToGeneratorAdapter.adapt(list.iterator())).toString());
244         assertEquals("0123456789x", foldRight.evaluate(IteratorToGeneratorAdapter.adapt(list.iterator()), "x").toString());
245     }
246 
247     @Test
248     public void testDoUntil() {
249         for (int i=0;i<3;i++){
250             Counter counter = new Counter();
251             new DoUntil(counter, new Offset(i)).run();
252             assertEquals(i+1,counter.count);
253         }
254     }
255 
256     @Test
257     public void testDoWhile() {
258         for (int i=0;i<3;i++){
259             Counter counter = new Counter();
260             new DoWhile(counter, new Limit(i)).run();
261             assertEquals(i+1,counter.count);
262         }
263     }
264 
265     @Test
266     public void testUntilDo() {
267         for (int i=0;i<3;i++){
268             Counter counter = new Counter();
269             new UntilDo(new Offset(i), counter).run();
270             assertEquals(i,counter.count);
271         }
272     }
273 
274     @Test
275     public void testWhileDo() {
276         for (int i=0;i<3;i++){
277             Counter counter = new Counter();
278             new WhileDo(new Limit(i),counter).run();
279             assertEquals(i,counter.count);
280         }
281     }
282 
283     @Test
284     public void testRecurse() {
285         assertEquals(new Integer(5), new RecursiveEvaluation(new RecFunc(0, false)).evaluate());
286 
287         // this version will return a function. since it is not the same type
288         // as RecFunc recursion will end.
289         Function func = (Function) new RecursiveEvaluation(new RecFunc(0, true)).evaluate();
290         assertEquals(new Integer(5), func.evaluate());
291     }
292 
293     /** Recursive function for test. */
294     class RecFunc implements Function {
295         int times = 0; boolean returnFunc = false;
296 
297         public RecFunc(int times, boolean returnFunc) {
298             this.times = times;
299             this.returnFunc = returnFunc;
300         }
301 
302         public Object evaluate() {
303             if (times < 5) {
304                 return new RecFunc(++times, returnFunc);
305             } else {
306                 if (returnFunc) {
307                     return new Function() {
308                         public Object evaluate() {
309                             return new Integer(times);
310                         }
311                     };
312                 } else {
313                     return new Integer(times);
314                 }
315             }
316         }
317     }
318 
319     // Attributes
320     // ------------------------------------------------------------------------
321     private List list = null;
322     private List doubled = null;
323     private List evens = null;
324     private List listWithDuplicates = null;
325     private int sum = 0;
326     private UnaryPredicate equalsThree = LeftBoundPredicate.bind(IsEqual.instance(),new Integer(3));
327     private UnaryPredicate equalsTwentyThree = LeftBoundPredicate.bind(IsEqual.instance(),new Integer(23));
328     private UnaryPredicate isEven = new UnaryPredicate() {
329         public boolean test(Object obj) {
330             return ((Number) obj).intValue() % 2 == 0;
331         }
332     };
333     private UnaryPredicate isOdd = new UnaryPredicate() {
334         public boolean test(Object obj) {
335             return ((Number) obj).intValue() % 2 != 0;
336         }
337     };
338 
339     // Classes
340     // ------------------------------------------------------------------------
341 
342     static class Counter implements Procedure {
343         public void run() {
344             count++;
345         }
346         public int count = 0;
347     }
348 
349     static class Summer implements UnaryProcedure {
350         public void run(Object that) {
351             sum += ((Number) that).intValue();
352         }
353         public int sum = 0;
354     }
355 
356     static class Doubler implements UnaryFunction {
357         public Object evaluate(Object obj) {
358             return new Integer(2*((Number) obj).intValue());
359         }
360     }
361 }