You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ki...@apache.org on 2013/09/12 06:29:48 UTC

svn commit: r1522355 [5/5] - in /commons/proper/functor/trunk: core/src/main/java/org/apache/commons/functor/adapter/ core/src/main/java/org/apache/commons/functor/core/algorithm/ core/src/main/java/org/apache/commons/functor/generator/ core/src/main/j...

Added: commons/proper/functor/trunk/core/src/test/java/org/apache/commons/functor/range/TestLongRange.java
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/core/src/test/java/org/apache/commons/functor/range/TestLongRange.java?rev=1522355&view=auto
==============================================================================
--- commons/proper/functor/trunk/core/src/test/java/org/apache/commons/functor/range/TestLongRange.java (added)
+++ commons/proper/functor/trunk/core/src/test/java/org/apache/commons/functor/range/TestLongRange.java Thu Sep 12 04:29:46 2013
@@ -0,0 +1,740 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.functor.range;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.functor.BaseFunctorTest;
+import org.apache.commons.functor.Function;
+import org.apache.commons.functor.generator.Generator;
+import org.apache.commons.functor.generator.loop.IteratorToGeneratorAdapter;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @version $Revision: 1515264 $ $Date: 2013-08-18 23:51:41 -0300 (Sun, 18 Aug 2013) $
+ */
+public class TestLongRange extends BaseFunctorTest {
+
+    // A base range with all longs between -6 and 6
+    private final List<Long> fullRange = Collections.unmodifiableList(Arrays
+        .asList(-6L, -5L, -4L, -3L, -2L, -1L, 0L, 1L, 2L, 3L, 4L, 5L, 6L));
+
+    // Attributes
+    // ------------------------------------------------------------------------
+    private LongRange ascLongRange = null;
+    private LongRange descLongRange = null;
+    private Collection<Long> expectedAsc = null;
+    private Collection<Long> expectedDesc = null;
+    
+    // Test set up
+    // ------------------------------------------------------------------------
+    @Before
+    public void setUp() {
+        ascLongRange = Ranges.longRange(0L, 10L);
+        descLongRange = Ranges.longRange(10L, 0L);
+        expectedAsc = Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L);
+        expectedDesc = Arrays.asList(10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L);
+    }
+
+    @After
+    public void tearDown() {
+        ascLongRange = null;
+        descLongRange = null;
+    }
+
+    @Override
+    protected Object makeFunctor()
+        throws Exception {
+        return Ranges.longRange(10, 20);
+    }
+
+    // Generator tests
+    // ------------------------------------------------------------------------
+
+    @Test
+    public void testGenerateListExample() {
+        // generates a collection of Integers from 0 (inclusive) to 10 (exclusive)
+        {
+            LongRange range = Ranges.longRange(0, 10);
+            for (int i=0;i<10;i++) {
+                assertEquals(new Long(i), range.next());
+            }
+        }
+
+        // generates a collection of Integers from 10 (inclusive) to 0 (exclusive)
+        {
+            LongRange range = Ranges.longRange(10, 0);
+            for (int i=10;i>0;i--) {
+                assertEquals(new Long(i), range.next());
+            }
+        }
+    }
+
+    @Test
+    public void testStepChecking() {
+        {
+            Ranges.longRange(2, 2, 0); // step of 0 is ok when range is empty
+        }
+        {
+            Ranges.longRange(2, 2, 1); // positive step is ok when range is empty
+        }
+        {
+            Ranges.longRange(2, 2, -1); // negative step is ok when range is empty
+        }
+        {
+            Ranges.longRange(0, 1, 10); // big steps are ok
+        }
+        {
+            Ranges.longRange(1, 0, -10); // big steps are ok
+        }
+        try {
+            Ranges.longRange(0, 1, 0);
+            fail("Expected IllegalArgumentException");
+        } catch(IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            Ranges.longRange(0, 1, -1);
+            fail("Expected IllegalArgumentException");
+        } catch(IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            Ranges.longRange(0, -1, 1);
+            fail("Expected IllegalArgumentException");
+        } catch(IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testObjectConstructor() {
+        LongRange range = Ranges.longRange(new Long(0), new Long(5));
+        assertEquals("[0, 1, 2, 3, 4]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+        range = Ranges.longRange(new Integer(0), new Long(5), new Long(1));
+        assertEquals("[0, 1, 2, 3, 4]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+    }
+
+
+    @Test
+    public void testReverseStep() {
+        LongRange range = Ranges.longRange(10, 0, -2);
+        assertEquals("[10, 8, 6, 4, 2]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+    }
+
+    @Test
+    public void testStep() {
+        LongRange range = Ranges.longRange(0, 10, 2);
+        assertEquals("[0, 2, 4, 6, 8]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+    }
+
+    @Test
+    public void testForwardRange() {
+        LongRange range = Ranges.longRange(0, 5);
+        assertEquals("[0, 1, 2, 3, 4]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+    }
+
+    @Test
+    public void testReverseRange() {
+        LongRange range = Ranges.longRange(5, 0);
+        assertEquals("[5, 4, 3, 2, 1]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+    }
+
+    @Test
+    public void testEdgeCase() {
+        LongRange range = Ranges.longRange(Long.MAX_VALUE - 3L, Long.MAX_VALUE);
+        assertEquals("[9223372036854775804, 9223372036854775805, 9223372036854775806]", IteratorToGeneratorAdapter.adapt(range).toCollection().toString());
+    }
+    
+    @Test
+    public void testClosedClosedAscending() {
+        // [-5L, 5L], 3L = -5L, -2L, 1L, 4L
+        LongRange range = Ranges.longRange(-5L, BoundType.CLOSED, 5L,
+                                        BoundType.CLOSED, 3L);
+        // [-5L, 5L], 3L = -5L, -2L, 1L, 4L
+        List<Long> expected = Arrays.asList(-5L, -2L, 1L, 4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testOpenClosedAscending() {
+        // (-5L, 5L], 3L = -2L, 1L, 4L
+        LongRange range = Ranges.longRange(-5L, BoundType.OPEN, 5L,
+                                        BoundType.CLOSED, 3L);
+        // (-5L, 5L], 3L = -2L, 1L, 4L
+        List<Long> expected = Arrays.asList(-2L, 1L, 4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testClosedOpenAscending() {
+        // [-5L, 5L), 3L = -5L, -2L, 1L, 4L
+        LongRange range = Ranges.longRange(-5L, BoundType.CLOSED, 5L,
+                                        BoundType.OPEN, 3L);
+        // (-5L, 5L], 3L = -5L, -2L, 1L, 4L
+        List<Long> expected = Arrays.asList(-5L, -2L, 1L, 4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testOpenOpenAscending() {
+        // (-5L, 5L), 3L = -2L, 1L, 4L
+        LongRange range = Ranges.longRange(-5L, BoundType.OPEN, 5L,
+                                        BoundType.OPEN, 3L);
+        // (-5L, 5L), 3L = -2L, 1L, 4L
+        List<Long> expected = Arrays.asList(-2L, 1L, 4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testSingleStepAscending() {
+        // (-2L, 2L], 1L = -1L, 0L, 1L, 2L
+        LongRange range = Ranges.longRange(-2L, BoundType.OPEN, 2L,
+                                        BoundType.CLOSED, 1L);
+        // (-2L, 2L], 1L = -1L, 0L, 1L, 2L
+        List<Long> expected = Arrays.asList(-1L, 0L, 1L, 2L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testClosedClosedDescending() {
+        // [5L, -5L], -3L = 5L, 2L, -1L, -4L
+        LongRange range = Ranges.longRange(5L, BoundType.CLOSED, -5L,
+                                        BoundType.CLOSED, -3L);
+        // [5L, -5L], -3L = 5L, 2L, -1L, -4L
+        List<Long> expected = Arrays.asList(5L, 2L, -1L, -4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testOpenClosedDescending() {
+        // (5L, -5L], -3L = 2L, -1L, -4L
+        LongRange range = Ranges.longRange(5L, BoundType.OPEN, -5L,
+                                        BoundType.CLOSED, -3L);
+        // (5L, -5L], -3L = 2L, -1L, -4L
+        List<Long> expected = Arrays.asList(2L, -1L, -4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testClosedOpenDescending() {
+        // [5L, -5L), -3L = 5L, 2L, -1L, -4L
+        LongRange range = Ranges.longRange(5L, BoundType.CLOSED, -5L,
+                                        BoundType.OPEN, -3L);
+        // [5L, -5L), -3L = 5L, 2L, -1L, -4L
+        List<Long> expected = Arrays.asList(5L, 2L, -1L, -4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testOpenOpenDescending() {
+        // (5L, -5L), -3L = 2L, -1L, -4L
+        LongRange range = Ranges.longRange(5L, BoundType.OPEN, -5L,
+                                        BoundType.OPEN, -3L);
+        // (5L, -5L), -3L = 2L, -1L, -4L
+        List<Long> expected = Arrays.asList(2L, -1L, -4L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testSingleStepDescending() {
+        // [2L, -2L), -1L = 2L, 1L, 0L, -1L
+        LongRange range = Ranges.longRange(2L, BoundType.CLOSED, -2L,
+                                        BoundType.OPEN, -1L);
+        // [2L, -2L), -1L = 2L, 1L, 0L, -1L
+        List<Long> expected = Arrays.asList(2L, 1L, 0L, -1L);
+        Collection<Long> elements = IteratorToGeneratorAdapter.adapt(range).toCollection();
+        assertEquals(expected, elements);
+    }
+
+    @Test
+    public void testAscending() {
+        final List<Long> list = new ArrayList<Long>();
+        for (Long l : ascLongRange) {
+            list.add(l);
+        }
+        assertTrue(expectedAsc.containsAll(list));
+    }
+
+    @Test
+    public void testDescending() {
+        final List<Long> list = new ArrayList<Long>();
+        for (Long l : descLongRange) {
+            list.add(l);
+        }
+        assertTrue(expectedDesc.containsAll(list));
+    }
+
+    @Test
+    public void testToCollection() {
+        Collection<Long> ascCol = IteratorToGeneratorAdapter.adapt(ascLongRange).toCollection();
+        assertEquals("Different collections", expectedAsc, ascCol);
+        Collection<Long> descCol = IteratorToGeneratorAdapter.adapt(descLongRange).toCollection();
+        assertEquals("Different collections", expectedDesc, descCol);
+    }
+
+    @Test
+    public void testTransformedGenerator() {
+        long expected = 45L;
+        long total = IteratorToGeneratorAdapter.adapt(ascLongRange)
+            .to(new Function<Generator<? extends Long>, Long>() {
+
+                public Long evaluate(Generator<? extends Long> obj) {
+                    long total = 0L;
+                    for (Object element : obj.toCollection()) {
+                        total += (Long) element;
+                    }
+                    return total;
+                }
+            });
+        assertEquals(expected, total);
+        expected = 55L;
+        total = IteratorToGeneratorAdapter.adapt(descLongRange)
+            .to(new Function<Generator<? extends Long>, Long>() {
+
+                public Long evaluate(Generator<? extends Long> obj) {
+                    long total = 0L;
+                    for (Object element : obj.toCollection()) {
+                        total += (Long) element;
+                    }
+                    return total;
+                }
+            });
+        assertEquals(expected, total);
+    }
+
+    // Range tests
+    // ------------------------------------------------------------------------
+
+    @Test
+    public void testEmptyRanges() {
+        LongRange empty1 = Ranges.longRange(-2, BoundType.OPEN, -1,
+                                         BoundType.OPEN, 2);
+        assertTrue("The range was expected to be empty.", empty1.isEmpty());
+        LongRange empty2 = Ranges.longRange(2, BoundType.OPEN, 0, BoundType.OPEN,
+                                         -2);
+        assertTrue("The range was expected to be empty.", empty2.isEmpty());
+        LongRange empty3 = Ranges.longRange(0, BoundType.OPEN, 1,
+                                         BoundType.CLOSED, 2);
+        assertTrue("The range was expected to be empty.", empty3.isEmpty());
+        LongRange empty4 = Ranges.longRange(-3, BoundType.OPEN, -3,
+                                         BoundType.OPEN, 1);
+        assertTrue("The range was expected to be empty.", empty4.isEmpty());
+        LongRange empty5 = Ranges.longRange(-3, BoundType.CLOSED, -3,
+                                         BoundType.OPEN, 1);
+        assertTrue("The range was expected to be empty.", empty5.isEmpty());
+        LongRange empty6 = Ranges.longRange(1, BoundType.OPEN, 0,
+                                         BoundType.CLOSED, -2);
+        assertTrue("The range was expected to be empty.", empty6.isEmpty());
+        LongRange notEmpty1 = Ranges.longRange(-3, BoundType.CLOSED, -3,
+                                            BoundType.CLOSED, 1);
+        assertFalse("The range was not expected to be empty.",
+                    notEmpty1.isEmpty());
+        LongRange notEmpty2 = Ranges.longRange(-3, BoundType.OPEN, -2,
+                                            BoundType.CLOSED, 1);
+        assertFalse("The range was not expected to be empty.",
+                    notEmpty2.isEmpty());
+        LongRange notEmpty3 = Ranges.longRange(2, BoundType.OPEN, 1,
+                                            BoundType.CLOSED, -1);
+        assertFalse("The range was not expected to be empty.",
+                    notEmpty3.isEmpty());
+        LongRange notEmpty4 = Ranges.longRange(2, BoundType.CLOSED, 1,
+                                            BoundType.OPEN, -1);
+        assertFalse("The range was not expected to be empty.",
+                    notEmpty4.isEmpty());
+        LongRange notEmpty5 = Ranges.longRange(1, BoundType.CLOSED, 2,
+                                            BoundType.OPEN, 1);
+        assertFalse("The range was not expected to be empty.",
+                    notEmpty5.isEmpty());
+    }
+
+    @Test
+    public void testBoundaries() {
+        LongRange range = Ranges.longRange(0L, 10L);
+        assertEquals(new Endpoint<Comparable<?>>(0L, BoundType.CLOSED),
+                     range.getLeftEndpoint());
+        assertEquals(new Endpoint<Comparable<?>>(10L, BoundType.OPEN),
+                     range.getRightEndpoint());
+    }
+
+    @Test
+    public void testClosedClosedAscendingContains() {
+        // [-5, 5], 3 = -5, -2, 1, 4
+        LongRange range = Ranges.longRange(-5, BoundType.CLOSED, 5,
+                                        BoundType.CLOSED, 3);
+        // [-5, 5], 3 = -5, -2, 1, 4
+        List<Long> arr = Arrays.asList(-5L, -2L, 1L, 4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testOpenClosedAscendingContains() {
+        // (-5, 5], 3 = -2, 1, 4
+        LongRange range = Ranges.longRange(-5, BoundType.OPEN, 5,
+                                        BoundType.CLOSED, 3);
+        // (-5, 5], 3 = -2, 1, 4
+        List<Long> arr = Arrays.asList(-2L, 1L, 4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testClosedOpenAscendingContains() {
+        // [-5, 5), 3 = -5, -2, 1, 4
+        LongRange range = Ranges.longRange(-5, BoundType.CLOSED, 5,
+                                        BoundType.OPEN, 3);
+        // (-5, 5], 3 = -5, -2, 1, 4
+        List<Long> arr = Arrays.asList(-5L, -2L, 1L, 4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testOpenOpenAscendingContains() {
+        // (-5, 5), 3 = -2, 1, 4
+        LongRange range = Ranges.longRange(-5, BoundType.OPEN, 5, BoundType.OPEN,
+                                        3);
+        // (-5, 5), 3 = -2, 1, 4
+        List<Long> arr = Arrays.asList(-2L, 1L, 4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testContainsSingleStepAscending() {
+        // (-2, 2], 1 = -1, 0, 1, 2
+        LongRange ascendingRange = Ranges.longRange(-2, BoundType.OPEN, 2,
+                                                 BoundType.CLOSED, 1);
+        // (-2, 2], 1 = -1, 0, 1, 2
+        List<Long> arr = Arrays.asList(-1L, 0L, 1L, 2L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + ascendingRange + "]",
+                       ascendingRange.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + ascendingRange +
+                                "]",
+                        ascendingRange.contains(element));
+        }
+    }
+
+    @Test
+    public void testClosedClosedDescendingContains() {
+        // [5, -5], -3 = 5, 2, -1, -4
+        LongRange range = Ranges.longRange(5, BoundType.CLOSED, -5,
+                                        BoundType.CLOSED, -3);
+        // [5, -5], -3 = 5, 2, -1, -4
+        List<Long> arr = Arrays.asList(5L, 2L, -1L, -4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testOpenClosedDescendingContains() {
+        // (5, -5], -3 = 2, -1, -4
+        LongRange range = Ranges.longRange(5, BoundType.OPEN, -5,
+                                        BoundType.CLOSED, -3);
+        // (5, -5], -3 = 2, -1, -4
+        List<Long> arr = Arrays.asList(2L, -1L, -4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testClosedOpenDescendingContains() {
+        // [5, -5), -3 = 5, 2, -1, -4
+        LongRange range = Ranges.longRange(5, BoundType.CLOSED, -5,
+                                        BoundType.OPEN, -3);
+        // [5, -5), -3 = 5, 2, -1, -4
+        List<Long> arr = Arrays.asList(5L, 2L, -1L, -4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testOpenOpenDescendingContains() {
+        // (5, -5), -3 = 2, -1, -4
+        LongRange range = Ranges.longRange(5, BoundType.OPEN, -5, BoundType.OPEN,
+                                        -3);
+        // (5, -5), -3 = 2, -1, -4
+        List<Long> arr = Arrays.asList(2L, -1L, -4L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + range + "]",
+                       range.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + range + "]",
+                        range.contains(element));
+        }
+    }
+
+    @Test
+    public void testContainsSingleStepDescending() {
+        // [2, -2), -1 = 2, 1, 0, -1
+        LongRange descendingRange = Ranges.longRange(2, BoundType.CLOSED, -2,
+                                                  BoundType.OPEN, -1);
+        // [2, -2), -1 = 2, 1, 0, -1
+        List<Long> arr = Arrays.asList(2L, 1L, 0L, -1L);
+        for (Long element : arr) {
+            assertTrue("Expected element [" + element +
+                               "] is missing in range [" + descendingRange +
+                               "]",
+                       descendingRange.contains(element));
+        }
+        List<Long> elementsNotPresent = new ArrayList<Long>(fullRange);
+        elementsNotPresent.removeAll(arr);
+        for (Long element : elementsNotPresent) {
+            assertFalse("Unexpected element [" + element +
+                                "] is present in range [" + descendingRange +
+                                "]",
+                        descendingRange.contains(element));
+        }
+    }
+
+    @Test
+    public void testContainsNullOrEmpty() {
+        LongRange range = Ranges.longRange(-2, BoundType.OPEN, 2,
+                                        BoundType.CLOSED, 1);
+        assertFalse(range.contains(null));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testContainsAll() {
+        // (-2, 2], 1 = -1, 0, 1, 2
+        LongRange range = Ranges.longRange(-2, BoundType.OPEN, 2,
+                                        BoundType.CLOSED, 1);
+        List<Long> list = Arrays.asList(-1L, 0L, 1L, 2L);
+        assertTrue("Range [" + range +
+                   "] was expected to contain all elements from list [" + list +
+                   "]", range.containsAll(list));
+        List<Long> listWithExtraElements = Arrays.asList(2L, -1L, 0L, 1L, 2L,
+                                                         3L);
+        assertFalse("Range [" + range + "] has more elements than expected",
+                    range.containsAll(listWithExtraElements));
+        assertFalse(range.containsAll(null));
+        assertFalse(range.containsAll(Collections.EMPTY_LIST));
+    }
+
+    @Test
+    public void testEquals()
+        throws Exception {
+        // equals basic properties
+        LongRange range = Ranges.longRange(-2, BoundType.CLOSED, 2,
+                                        BoundType.OPEN, 1);
+        assertEquals("equals must be reflexive", range, range);
+        assertEquals("hashCode must be reflexive", range.hashCode(),
+                     range.hashCode());
+        assertTrue(!range.equals(null)); // should be able to compare to null
+
+        Object range2 = Ranges.longRange(-2, BoundType.CLOSED, 2, BoundType.OPEN,
+                                      1);
+        if (range.equals(range2)) {
+            assertEquals("equals implies hash equals", range.hashCode(),
+                         range2.hashCode());
+            assertEquals("equals must be symmetric", range2, range);
+        } else {
+            assertTrue("equals must be symmetric", !range2.equals(range));
+        }
+
+        // Changing attributes
+        Object range3 = Ranges.longRange(-1, BoundType.CLOSED, 2, BoundType.OPEN,
+                                      1);
+        assertFalse("Invalid equals after changing attributes",
+                    range.equals(range3));
+
+        Object range4 = Ranges.longRange(-2, BoundType.OPEN, 2, BoundType.OPEN, 1);
+        assertFalse("Invalid equals after changing attributes",
+                    range.equals(range4));
+
+        Object range5 = Ranges.longRange(-2, BoundType.CLOSED, 1, BoundType.OPEN,
+                                      1);
+        assertFalse("Invalid equals after changing attributes",
+                    range.equals(range5));
+
+        Object range6 = Ranges.longRange(-2, BoundType.CLOSED, 2,
+                                      BoundType.CLOSED, 1);
+        assertFalse("Invalid equals after changing attributes",
+                    range.equals(range6));
+
+        Object range7 = Ranges.longRange(-2, BoundType.CLOSED, 2, BoundType.OPEN,
+                                      2);
+        assertFalse("Invalid equals after changing attributes",
+                    range.equals(range7));
+
+        // Using different constructors
+        LongRange range8 = Ranges.longRange(Integer.valueOf(-2), Integer.valueOf(2),
+                                            Integer.valueOf(1));
+        assertEquals("Invalid equals using different constructor", range,
+                     range8);
+
+        LongRange range9 = Ranges.longRange(Integer.valueOf(-2),Integer.valueOf(2));
+        assertEquals("Invalid equals using different constructor", range,
+                     range9);
+
+        Endpoint<Long> leftEndpoint = new Endpoint<Long>(-2L, BoundType.CLOSED);
+        Endpoint<Long> rightEndpoint = new Endpoint<Long>(2L, BoundType.OPEN);
+        LongRange range10 = Ranges.longRange(leftEndpoint, rightEndpoint, 1L);
+        assertEquals("Invalid equals using different constructor", range,
+                     range10);
+    }
+
+    @Test
+    public void testToString() {
+        LongRange range = Ranges.longRange(-2, BoundType.OPEN, 2,
+                                        BoundType.CLOSED, 1);
+        assertEquals("Wrong string value", "LongRange<(-2, 2], 1>",
+                     range.toString());
+    }
+
+    @Test
+    public void testConstructorUsingSameEndpoint() {
+        Endpoint<Long> uniqueEndpoint = new Endpoint<Long>(10L,
+                                                           BoundType.CLOSED);
+        try {
+            Ranges.longRange(uniqueEndpoint, uniqueEndpoint, 1L);
+        } catch (IllegalArgumentException e) {
+            fail("Not expected to get here");
+        }
+    }
+
+    @Test
+    public void testInvalidRange() {
+        try {
+            Ranges.longRange(10, BoundType.OPEN, -5, BoundType.CLOSED, 10);
+            fail("Not expected to get here");
+        } catch (IllegalArgumentException e) {
+            // Do nothing
+        }
+        Endpoint<Long> leftEndpoint = new Endpoint<Long>(10L, BoundType.CLOSED);
+        Endpoint<Long> rightEndpoint = new Endpoint<Long>(-5L, BoundType.OPEN);
+        try {
+            Ranges.longRange(leftEndpoint, rightEndpoint, 1L);
+            fail("Not expected to get here");
+        } catch (IllegalArgumentException e) {
+            // Do nothing
+        }
+    }
+
+    @Test
+    public void testDefaultStep() {
+        assertEquals("Invalid default step", Long.valueOf(-1L),
+                     LongRange.DEFAULT_STEP.evaluate(10L, 1L));
+        assertEquals("Invalid default step", Long.valueOf(1L),
+                     LongRange.DEFAULT_STEP.evaluate(1L, 10L));
+    }
+
+}
\ No newline at end of file

Modified: commons/proper/functor/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/changes/changes.xml?rev=1522355&r1=1522354&r2=1522355&view=diff
==============================================================================
--- commons/proper/functor/trunk/src/changes/changes.xml (original)
+++ commons/proper/functor/trunk/src/changes/changes.xml Thu Sep 12 04:29:46 2013
@@ -23,6 +23,9 @@
   </properties>
   <body>
     <release version="1.0" date="2012-??-??" description="First release.">
+      <action issue="FUNCTOR-14" dev="kinow">
+        Enhancements on the Generator API
+      </action>
       <action issue="FUNCTOR-28" dev="kinow">
         Fix checkstyle errors in the generator package
       </action>

Modified: commons/proper/functor/trunk/src/site/xdoc/examples.xml
URL: http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/site/xdoc/examples.xml?rev=1522355&r1=1522354&r2=1522355&view=diff
==============================================================================
--- commons/proper/functor/trunk/src/site/xdoc/examples.xml (original)
+++ commons/proper/functor/trunk/src/site/xdoc/examples.xml Thu Sep 12 04:29:46 2013
@@ -29,7 +29,8 @@
          This page contains basic examples using <a href="apidocs/org/apache/commons/functor/Predicate.html">Predicates</a>, 
          <a href="apidocs/org/apache/commons/functor/Function.html">Functions</a>, 
          <a href="apidocs/org/apache/commons/functor/Procedure.html">Procedures</a>, 
-         <a href="apidocs/org/apache/commons/functor/generator/Generator.html">Generators</a> and 
+         <a href="apidocs/org/apache/commons/functor/generator/Generator.html">Generators</a>, 
+         <a href="apidocs/org/apache/commons/functor/range/Range.html">Ranges</a> and
          <a href="apidocs/org/apache/commons/functor/aggregator/Aggregator.html">Aggregators</a>. 
          There are also examples using composition and more practical examples 
          at the bottom of this page.
@@ -105,6 +106,129 @@ for( Integer number : numbers ) {
     </p>
     </subsection>
 
+    <subsection name="Generators">
+       <p>
+         Apache Functor includes other objects that you can can use to code in
+         a less imperative way, like <em>Generators</em>. In the following
+         example, we create an <em>Integer Generator</em> that generates
+         integers from 1 to 4 (the right argument is non-inclusive). The
+         generator is wrapped within a <em>Filtered Generator</em> that applies
+         the isEven predicate to each integer generated by the former generator.
+         Finally, we execute a <em>Composite Unary Procedure</em> that uses
+         a function to double the value of the integer before printing it.
+       </p>
+<source>
+Generator&lt;Integer&gt; integerGenerator = new IntegerRange(1, 5); // inclusive, exclusive
+    
+UnaryPredicate&lt;Integer&gt; isEven = new UnaryPredicate&lt;Integer&gt;() {
+    public boolean test(Integer obj) {
+        return obj % 2 == 0;
+    }
+};
+
+FilteredGenerator&lt;Integer&gt; filteredGenerator = 
+        new FilteredGenerator&lt;Integer&gt;(integerGenerator, isEven);
+
+UnaryFunction&lt;Integer, Integer&gt; doubler = new UnaryFunction&lt;Integer, Integer&gt;() {
+    public Integer evaluate(Integer obj) {
+        return obj * 2;
+    }
+};
+
+UnaryProcedure&lt;Integer&gt; print = new UnaryProcedure&lt;Integer&gt;() {
+    public void run(Integer obj) {
+        System.out.print(obj + " ");
+    }
+};
+
+CompositeUnaryProcedure&lt;Integer&gt; compositeProcedure =
+        new CompositeUnaryProcedure&lt;Integer&gt;(print);
+
+filteredGenerator.run(compositeProcedure.of(doubler));
+</source>
+       <p>
+         The <a href="http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/test/java/org/apache/commons/functor/example/lines/">lines</a>
+         package demonstrates a functional approach to IO using Generators and the Algorithms class.
+       </p>
+    </subsection>
+
+    <subsection name="Ranges">
+        <p>
+         Using <em>Ranges</em> you are able to create a series of elements of 
+         a certain type. The distance between each element is called 
+         <em>step</em>. And the <em>left</em> and <em>right</em> limits are 
+         <em>endpoints</em>.
+        </p>
+        <p>
+         By default, in numeric ranges the left value is inclusive and the 
+         right is exclusive. The range below creates a series of Integers 
+         between <em>0</em> and <em>10</em>, with a default step of <em>1</em>.
+        </p>
+<source>
+// [0, 10), 1 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
+IntegerRange range = new IntegerRange(0, 10);
+</source>
+        <p>
+         The step value can be changed, altering the distance between each 
+         element in the range. As shown below.
+        </p>
+<source>
+// [0, 10), 2 = 0, 2, 4, 6, 8
+IntegerRange range = new IntegerRange(0, 10, 2);
+</source>
+        <p>
+         It is possible, too, to define the <em>bound type</em> of each endpoint. 
+         It is similar to mathematical intervals, where a 
+         <em>closed</em> endpoint means that the value is included in the 
+         series of elements in the range. On the other hand, an <em>open</em> 
+         endpoint means that the value is not included.
+        </p>
+<source>
+// (0, 10], 2 = 2, 4, 6, 8, 10
+IntegerRange range = new IntegerRange(0, BoundType.OPEN, 10, BoundType.CLOSED, 2);
+</source>
+        <p>
+         A Range is also by nature a Generator, so you can use it for executing 
+         procedures for each of its elements.
+        </p>
+<source>
+// [0, 10), 1 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
+IntegerRange range = new IntegerRange(0, 10);
+UnaryProcedure&lt;Integer&gt; printProcedure = new UnaryProcedure&lt;Integer&gt;() {
+    
+    public void run(Integer obj) {
+        System.out.print(obj + " ");
+    }
+};
+range.run(printProcedure);
+</source>
+        <p>
+        The code above produces the following output: 0 1 2 3 4 5 6 7 8 9 
+        </p>
+    </subsection>
+
+    <subsection name="Aggregators">
+      <p>
+         There are some code snippets / examples for the <code>org.apache.commons.functor.aggregator</code> package
+         available on <a href="aggregator.html">this page</a>. Also, to exemplify the usage of the <code>Aggregator</code>
+         classes, there are code examples in the test section.
+      </p>
+      <p>
+         First such set of example involves the usage of the <i>nostore</i> <code>Aggregator</code>. Code can be found in
+         <a href="http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/test/java/org/apache/commons/functor/example/aggregator/nostore/">org.apache.commons.functor.example.aggregator.nostore</a>.
+         This shows how can you use an aggregator which doesn't store the data series and processes them on the fly.
+         Also, there are examples provided which show how can you implement your own aggregation function
+         to be used with this <code>Aggregator</code> type.
+      </p>
+      <p>
+         For using an <code>Aggregator</code> which stores the data series in a list, examples are in
+         <a href="http://svn.apache.org/viewvc/commons/proper/functor/trunk/src/test/java/org/apache/commons/functor/example/aggregator/list/">org.apache.commons.functor.example.aggregator.list</a>.
+         This shows how can you use the <code>ArrayList</code>-backed aggregator or provide your own <code>List</code>-based implementation.
+         Also, there are examples provided which show how can you implement your own aggregation function
+         to be used with this <code>Aggregator</code> type.
+      </p>
+    </subsection>
+
     <subsection name="Reuse Through Composition">
        <p>
           The <em>Functor</em> package, and more generally, a functional approach