001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.functor;
018    
019    import static org.junit.Assert.assertEquals;
020    import static org.junit.Assert.assertFalse;
021    import static org.junit.Assert.assertNotNull;
022    import static org.junit.Assert.assertSame;
023    import static org.junit.Assert.assertTrue;
024    import static org.junit.Assert.fail;
025    
026    import java.util.ArrayList;
027    import java.util.Collection;
028    import java.util.HashSet;
029    import java.util.Iterator;
030    import java.util.List;
031    import java.util.NoSuchElementException;
032    import java.util.Set;
033    
034    import org.apache.commons.functor.adapter.LeftBoundPredicate;
035    import org.apache.commons.functor.core.Identity;
036    import org.apache.commons.functor.core.IsEqual;
037    import org.apache.commons.functor.core.Limit;
038    import org.apache.commons.functor.core.Offset;
039    import org.apache.commons.functor.core.algorithm.DoUntil;
040    import org.apache.commons.functor.core.algorithm.DoWhile;
041    import org.apache.commons.functor.core.algorithm.FindWithinGenerator;
042    import org.apache.commons.functor.core.algorithm.FoldLeft;
043    import org.apache.commons.functor.core.algorithm.FoldRight;
044    import org.apache.commons.functor.core.algorithm.GeneratorContains;
045    import org.apache.commons.functor.core.algorithm.InPlaceTransform;
046    import org.apache.commons.functor.core.algorithm.RecursiveEvaluation;
047    import org.apache.commons.functor.core.algorithm.RemoveMatching;
048    import org.apache.commons.functor.core.algorithm.RetainMatching;
049    import org.apache.commons.functor.core.algorithm.UntilDo;
050    import org.apache.commons.functor.core.algorithm.WhileDo;
051    import org.apache.commons.functor.core.composite.UnaryNot;
052    import org.apache.commons.functor.generator.FilteredGenerator;
053    import org.apache.commons.functor.generator.Generator;
054    import org.apache.commons.functor.generator.IteratorToGeneratorAdapter;
055    import org.apache.commons.functor.generator.TransformedGenerator;
056    import org.apache.commons.functor.generator.util.IntegerRange;
057    import org.junit.After;
058    import org.junit.Before;
059    import org.junit.Test;
060    
061    /**
062     * @version $Revision: 1171255 $ $Date: 2011-09-15 22:27:39 +0200 (Thu, 15 Sep 2011) $
063     * @author Rodney Waldhoff
064     */
065    @SuppressWarnings("unchecked")
066    public class TestAlgorithms {
067    
068        // Lifecycle
069        // ------------------------------------------------------------------------
070    
071        @Before
072        public void setUp() throws Exception {
073            list = new ArrayList();
074            evens = new ArrayList();
075            doubled = new ArrayList();
076            listWithDuplicates = new ArrayList();
077            sum = 0;
078            for (int i=0;i<10;i++) {
079                list.add(new Integer(i));
080                doubled.add(new Integer(i*2));
081                listWithDuplicates.add(new Integer(i));
082                listWithDuplicates.add(new Integer(i));
083                sum += i;
084                if (i%2 == 0) {
085                    evens.add(new Integer(i));
086                }
087            }
088        }
089    
090        @After
091        public void tearDown() throws Exception {
092            list = null;
093            evens = null;
094            listWithDuplicates = null;
095            sum = 0;
096        }
097    
098        // Tests
099        // ------------------------------------------------------------------------
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    }