sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1443029 - in /sis/branches/JDK7/sis-utility/src: main/java/org/apache/sis/measure/Range.java test/java/org/apache/sis/measure/RangeTest.java
Date Wed, 06 Feb 2013 15:52:00 GMT
Author: desruisseaux
Date: Wed Feb  6 15:52:00 2013
New Revision: 1443029

URL: http://svn.apache.org/viewvc?rev=1443029&view=rev
Log:
Initial commit of Range implementation, provided by Joseph White (SIS-66).

Added:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java   (with
props)
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java   (with
props)

Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java?rev=1443029&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java (added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java Wed Feb
 6 15:52:00 2013
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2012 The Apache Software Foundation.
+ *
+ * Licensed 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.sis.measure;
+
+/**
+ * A range is a set of minimum and maximum values of a certain class, allowing
+ * a user to determine if a value of the same class is contained inside the range.
+ * The minimum and maximum values do not have to be included in the range, and
+ * can be null.  If the minimum or maximum values are null, the range is said to
+ * be unbounded on that extreme. If both the minimum and maximum are null,
+ * the range is completely unbounded and all values of that class are contained
+ * within the range.
+ *
+ * To be a member of a Range, the class type defining the Range must implement
+ * the Comparable interface.
+ *
+ * @author Joe White
+ */
+public class Range
+{
+
+    private Comparable minimumValue;
+    private Comparable maximumValue;
+    private Class rangeType;
+    private boolean isMinimumIncluded;
+    private boolean isMaximumIncluded;
+    private static String INVALID_TYPE_ERROR = "Type to be compared does not match the Range
type.";
+
+    public Range(Class elementClass, Comparable minValue, boolean isMinIncluded,
+          Comparable maxValue, boolean isMaxIncluded) throws IllegalArgumentException
+    {
+        if(!checkConstructorArgs(elementClass, minValue, maxValue))
+        {
+            throw new IllegalArgumentException();
+        }
+        rangeType = elementClass;
+        minimumValue = minValue;
+        isMinimumIncluded = isMinIncluded;
+        maximumValue = maxValue;
+        isMaximumIncluded = isMaxIncluded;
+    }
+
+    public Range(Class elementClass, Comparable minValue,
+            Comparable maxValue) throws IllegalArgumentException
+    {
+        if(!checkConstructorArgs(elementClass, minValue, maxValue))
+        {
+            throw new IllegalArgumentException();
+        }
+
+        rangeType = elementClass;
+        minimumValue = minValue;
+        isMinimumIncluded = true;
+        maximumValue = maxValue;
+        isMaximumIncluded = true;
+    }
+
+    public boolean contains(Comparable value) throws IllegalArgumentException
+    {
+
+        boolean unbounded = (minimumValue == null && maximumValue == null);
+        //safety check
+        if (value == null)
+        {
+            if (unbounded)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        //first check
+        if (value.getClass() != rangeType)
+        {
+            throw new IllegalArgumentException(INVALID_TYPE_ERROR);
+        }
+
+        //set unbounded on both ends
+        if (unbounded)
+        {
+            return true;
+        }
+
+        int minimumValueCheck = 1;
+        if (minimumValue != null)
+        {
+            minimumValueCheck = value.compareTo(minimumValue);
+        }
+        int maximumValueCheck = -1;
+        if (maximumValue != null)
+        {
+            maximumValueCheck = value.compareTo(maximumValue);
+        }
+
+        //set unbounded on lower end
+        if (minimumValue == null && maximumValueCheck <= 0)
+        {
+            if (isMaximumIncluded && minimumValueCheck > 0)
+            {
+                return true;
+            }
+            else if (!isMaximumIncluded)
+            {
+                return true;
+            }
+
+        }
+
+        //set unbounded on upper end
+        if (maximumValue == null && minimumValueCheck >= 0)
+        {
+            if (isMinimumIncluded && minimumValueCheck > 0)
+            {
+                return true;
+            }
+            else if (!isMinimumIncluded)
+            {
+                return true;
+            }
+        }
+
+        //set bounded on both ends
+        if (minimumValueCheck >= 0 && maximumValueCheck <= 0)
+        {
+            //both min and max are included
+            if (isMinimumIncluded && isMaximumIncluded)
+            {
+                return true;
+            }
+            //only min is included
+            else if (!isMinimumIncluded && minimumValueCheck > 0)
+            {
+                return true;
+            }
+            //only max is included
+            else if (!isMaximumIncluded && maximumValueCheck < 0)
+            {
+                return true;
+            }
+            //neither is included
+            else
+            {
+                return (minimumValueCheck > 0 && maximumValueCheck < 0);
+            }
+
+        }
+        return false;
+
+    }
+
+
+    public boolean contains(Range value) throws IllegalArgumentException
+    {
+        if (!checkMethodArgs(value))
+        {
+            throw new IllegalArgumentException(INVALID_TYPE_ERROR);
+        }
+        return this.contains(value.getMinValue()) && this.contains(value.getMaxValue());
+    }
+
+
+    public boolean intersects(Range value) throws IllegalArgumentException
+    {
+        if (!checkMethodArgs(value))
+        {
+            throw new IllegalArgumentException(INVALID_TYPE_ERROR);
+        }
+
+        return this.contains(value.getMinValue()) || this.contains(value.getMaxValue());
+    }
+
+    public Range union(Range value) throws IllegalArgumentException
+    {
+        if (!checkMethodArgs(value))
+        {
+            throw new IllegalArgumentException(INVALID_TYPE_ERROR);
+        }
+
+        //if they are both the same, return either one
+        if (this.equals(value))
+        {
+            return value;
+        }
+
+        //get the min and max value of both sets, compare them, then take
+        //the smallest of either and the largest of either and create
+        //a new Range with them.
+        Comparable rangeMin, rangeMax;
+        if (value.getMinValue().compareTo(minimumValue) <= 0)
+        {
+            rangeMin = value.getMinValue();
+        }
+        else
+        {
+            rangeMin = minimumValue;
+        }
+
+        if (value.getMaxValue().compareTo(maximumValue) >= 0)
+        {
+            rangeMax = value.getMaxValue();
+        }
+        else
+        {
+            rangeMax = maximumValue;
+        }
+        return new Range(this.rangeType, rangeMin, rangeMax );
+    }
+
+    public Range intersect(Range value) throws IllegalArgumentException
+    {
+        if (!checkMethodArgs(value))
+        {
+            throw new IllegalArgumentException(INVALID_TYPE_ERROR);
+        }
+
+        //return empty set if the Ranges don't intersect
+        if (!this.intersects(value))
+        {
+            return new Range(rangeType, maximumValue, minimumValue);
+        }
+
+        //if they are equal, return the passed in value
+        if (this.equals(value))
+        {
+            return value;
+        }
+
+        //we knkow they intersect, the question is where.
+        Comparable rangeMin, rangeMax;
+        if (this.contains(value.getMinValue()))
+        {
+            rangeMin = value.getMinValue();
+        }
+        else
+        {
+            rangeMin = minimumValue;
+        }
+
+        if (this.contains(value.getMaxValue()))
+        {
+            rangeMax = value.getMaxValue();
+        }
+        else
+        {
+            rangeMax = maximumValue;
+        }
+
+        return new Range(this.rangeType, rangeMin, rangeMax );
+
+    }
+
+    //TODO: implement this
+    public Range[] subtract(Range value) throws IllegalArgumentException
+    {
+        if (!checkMethodArgs(value))
+        {
+            throw new IllegalArgumentException(INVALID_TYPE_ERROR);
+        }
+        Range[] ranges = new Range[1];
+        ranges[0] = null;
+        return ranges;
+    }
+
+    public boolean isEmpty()
+    {
+        if (isMinimumIncluded && isMaximumIncluded)
+        {
+            if (minimumValue.compareTo(maximumValue) > 0)
+            {
+                return true;
+            }
+        }
+        else
+        {
+            if (minimumValue.compareTo(maximumValue) >= 0)
+            {
+                return true;
+            }
+
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object object)
+    {
+        //make sure it's not null
+        if (object == null)
+        {
+            return false;
+        }
+
+
+        Range value = (Range)object;
+        if (value == null)
+        {
+            return false;
+        }
+
+        boolean retVal = true;
+        retVal &= this.rangeType == value.getElementClass();
+        if (value.isEmpty() && this.isEmpty())
+        {
+            return retVal;
+        }
+
+        retVal &= this.maximumValue == value.getMaxValue();
+        retVal &= this.minimumValue == value.getMinValue();
+        retVal &= this.isMaximumIncluded == value.isMaxIncluded();
+        retVal &= this.isMinimumIncluded == value.isMinIncluded();
+        return retVal;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = 7;
+        hash = 13 * hash + (this.minimumValue != null ? this.minimumValue.hashCode() : 0);
+        hash = 13 * hash + (this.maximumValue != null ? this.maximumValue.hashCode() : 0);
+        hash = 13 * hash + (this.rangeType != null ? this.rangeType.hashCode() : 0);
+        hash = 13 * hash + (this.isMinimumIncluded ? 1 : 0);
+        hash = 13 * hash + (this.isMaximumIncluded ? 1 : 0);
+        return hash;
+    }
+
+    public boolean isMinIncluded()
+    {
+        return isMinimumIncluded;
+    }
+
+    public boolean isMaxIncluded()
+    {
+        return isMaximumIncluded;
+    }
+
+    public Class getElementClass()
+    {
+        return rangeType;
+    }
+
+    public Comparable getMinValue()
+    {
+        return minimumValue;
+    }
+
+    public Comparable getMaxValue()
+    {
+        return maximumValue;
+    }
+
+
+    private boolean checkConstructorArgs(Class elementClass, Comparable minValue,
+            Comparable maxValue)
+    {
+        boolean retVal = true;
+        if (minValue != null)
+        {
+            boolean minimumOk = minValue.getClass() == elementClass;
+            retVal &= minimumOk;
+        }
+
+        if (maxValue != null)
+        {
+            boolean maximumOk = maxValue.getClass() == elementClass;
+            retVal &= maximumOk;
+        }
+
+        if (minValue == null && maxValue == null)
+        {
+            Class[] interfaces = elementClass.getInterfaces();
+            boolean comparableFound = false;
+            for (Class interf : interfaces)
+            {
+                if (interf == Comparable.class)
+                {
+                    comparableFound = true;
+                }
+            }
+            retVal &= comparableFound;
+        }
+        return retVal;
+    }
+
+    private boolean checkMethodArgs(Range value)
+    {
+        if (value == null)
+        {
+            return false;
+        }
+        else if (  value.getElementClass() != rangeType)
+        {
+            return false;
+        }
+        return true;
+
+    }
+}

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Range.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java?rev=1443029&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java (added)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java Wed
Feb  6 15:52:00 2013
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2012 The Apache Software Foundation.
+ *
+ * Licensed 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.sis.measure;
+
+import org.apache.sis.test.TestCase;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * Tests the @link Range class
+ *
+ * @author Joe White
+ */
+public final strictfp class RangeTest extends TestCase {
+
+    @Test
+    public void testCtor()
+    {
+        Range intRange = new Range(Integer.class, new Integer(3), new Integer(5));
+        assertTrue(intRange.isMaxIncluded());
+        assertTrue(intRange.isMinIncluded());
+        assertFalse(intRange.isEmpty());
+
+        Range intRange1 = new Range(Integer.class, 3, false, 5, true);
+        assertTrue(intRange1.isMaxIncluded());
+        assertFalse(intRange1.isMinIncluded());
+        assertFalse(intRange1.isEmpty());
+
+        Range intRange2 = new Range(Integer.class, 2, true, 7, false);
+        assertFalse(intRange2.isMaxIncluded());
+        assertTrue(intRange2.isMinIncluded());
+        assertFalse(intRange2.isEmpty());
+
+        Range intRange3 = new Range(Integer.class, 3, false, 10, false);
+        assertFalse(intRange3.isMaxIncluded());
+        assertFalse(intRange3.isMinIncluded());
+        assertFalse(intRange3.isEmpty());
+
+        Range intRange4 = new Range(Integer.class, 10, 2);
+        assertTrue(intRange4.isEmpty());
+    }
+
+    @Test (expected=IllegalArgumentException.class)
+    public void testCtorErrors00()
+    {
+        Range doubleRange = new Range(Double.class, "error", "blast");
+    }
+
+    @Test (expected=IllegalArgumentException.class)
+    public void testCtorErrors01()
+    {
+        Range stringRange = new Range(String.class, 123.233, 8740.09);
+    }
+
+    @Test
+    public void testContains()
+    {
+        Range intRange = new Range(Integer.class, new Integer(3), new Integer(5));
+        assertTrue(intRange.contains(4));
+        assertFalse(intRange.contains(6));
+        assertFalse(intRange.contains(2));
+        assertTrue(intRange.contains(3));
+        assertTrue(intRange.contains(5));
+    }
+
+
+    @Test
+    public void testContainsNotInclusiveMinimum()
+    {
+        Range intRange = new Range(Integer.class, new Integer(2), false, new Integer(5),
true);
+        assertTrue(intRange.contains(4));
+        assertFalse(intRange.contains(6));
+        assertFalse(intRange.contains(2));
+        assertTrue(intRange.contains(3));
+        assertTrue(intRange.contains(5));
+
+    }
+
+    @Test
+    public void testContainsNotInclusiveMaximum()
+    {
+        Range intRange = new Range(Integer.class, new Integer(3), true, new Integer(6), false);
+        assertTrue(intRange.contains(4));
+        assertFalse(intRange.contains(6));
+        assertFalse(intRange.contains(2));
+        assertTrue(intRange.contains(3));
+        assertTrue(intRange.contains(5));
+    }
+
+    @Test
+    public void testContainsNoLowerBound()
+    {
+        Range intRange = new Range(Integer.class, null, new Integer(5));
+        assertTrue(intRange.contains(-555));
+        assertTrue(intRange.contains(5));
+        assertFalse(intRange.contains(6));
+    }
+
+    @Test
+    public void testContainsNoUpperBound()
+    {
+        Range intRange = new Range(Integer.class, new Integer(3), null);
+        assertFalse(intRange.contains(1));
+        assertTrue(intRange.contains(3));
+        assertTrue(intRange.contains(10000));
+    }
+
+    @Test
+    public void testContainsNoBounds()
+    {
+        Range intRange = new Range(Integer.class, null, null);
+        assertTrue(intRange.contains(-55555));
+        assertTrue(intRange.contains(100000));
+    }
+
+    @Test
+    public void testContainsRange()
+    {
+        Range intRange = new Range(Integer.class, -10, 10);
+        Range testRange = new Range(Integer.class, -5, 5);
+
+        assertTrue(intRange.contains(testRange));
+        assertFalse(testRange.contains(intRange));
+    }
+
+    @Test
+    public void testContainsRangeNoLowerBound()
+    {
+        Range intRange = new Range(Integer.class, null, new Integer(500));
+        Range testRange = new Range(Integer.class, -2500, 305);
+
+        assertTrue(intRange.contains(testRange));
+        assertFalse(testRange.contains(intRange));
+    }
+
+    @Test
+    public void testContainsRangeNoUpperBound()
+    {
+        Range intRange = new Range(Integer.class, new Integer(-2500), null);
+        Range testRange = new Range(Integer.class, 17, 305);
+
+        assertTrue(intRange.contains(testRange));
+        assertFalse(testRange.contains(intRange));
+    }
+
+    @Test (expected = IllegalArgumentException.class)
+    public void testIncompatibleTypeRangeContains()
+    {
+        Range intRange = new Range(Integer.class, new Integer(0), new Integer(10));
+        Range doubleRange = new Range(Double.class, new Double(2.0), new Double(5.0));
+
+        intRange.contains(doubleRange);
+    }
+
+    @Test (expected = IllegalArgumentException.class)
+    public void testIncompatibleTypeContains()
+    {
+        Range intRange = new Range(Integer.class, new Integer(0), new Integer(10));
+        Range doubleRange = new Range(Double.class, new Double(2.0), new Double(5.0));
+
+        intRange.contains(doubleRange);
+    }
+
+    @Test
+    public void testIntersects()
+    {
+        Range range1 = new Range(Character.class, 'a', 'g');
+        Range range2 = new Range(Character.class, 'c', 'm');
+
+        assertTrue(range1.intersects(range2));
+        assertTrue(range2.intersects(range1));
+
+        Range range3 = new Range(Character.class, 'o', 'z');
+        assertFalse(range1.intersects(range3));
+        assertFalse(range3.intersects(range1));
+    }
+
+    @Test (expected=IllegalArgumentException.class)
+    public void testIntersectsIncompatibleTypes()
+    {
+        Range range1 = new Range(Character.class, 'a', 'g');
+        Range range2 = new Range(Integer.class, 5, 7);
+
+        boolean ok = range1.intersects(range2);
+
+    }
+
+    @Test
+    public void testIntersection()
+    {
+        Range range1 = new Range(Integer.class, 1, 5);
+        Range range2 = new Range(Integer.class, 4, 6);
+
+        Range intersection1 = range1.intersect(range2);
+        assertTrue(intersection1.getElementClass() == Integer.class);
+        assertTrue((Integer)intersection1.getMinValue() == 4);
+        assertTrue((Integer)intersection1.getMaxValue() == 5);
+    }
+
+    @Test
+    public void testIntersectionOfNonIntersectingRanges()
+    {
+        Range range1 = new Range(Integer.class, 1, 5);
+        Range range2 = new Range(Integer.class, 8, 10);
+
+        Range intersection1 = range1.intersect(range2);
+        assertTrue(intersection1.getElementClass() == Integer.class);
+        assertTrue(intersection1.isEmpty());
+    }
+
+    @Test
+    public void testUnion()
+    {
+        Range range1 = new Range(Character.class, 'a', 'f');
+        Range range2 = new Range(Character.class, 'd', 'h');
+
+        Range unionRange = range1.union(range2);
+        assertFalse(unionRange.isEmpty());
+        assertTrue((Character)unionRange.getMinValue() == 'a');
+        assertTrue((Character)unionRange.getMaxValue() == 'h');
+    }
+
+    @Test
+    public void testDisjointUnion()
+    {
+        Range range1 = new Range(Character.class, 'a', 'f');
+        Range range2 = new Range(Character.class, 'm', 'v');
+
+        Range unionRange = range1.union(range2);
+        assertFalse(unionRange.isEmpty());
+        assertTrue((Character)unionRange.getMinValue() == 'a');
+        assertTrue((Character)unionRange.getMaxValue() == 'v');
+    }
+
+    @Test
+    public void testEquality()
+    {
+        //positive test - success case
+        Range range1 = new Range(Character.class, 'a', 'f');
+        Range range2 = new Range(Character.class, 'a', 'f');
+        assertTrue(range1.equals(range2));
+
+        //positive test - failure case
+        Range range3 = new Range(Character.class, 'a', 'g');
+        assertFalse(range1.equals(range3));
+
+        //failure due to type incompatibility
+        Range range4 = new Range(String.class, "a", "g");
+        assertFalse(range3.equals(range4));
+
+        Range range5 = new Range(Character.class, 'g', 'a');
+        Range range6 = new Range(Character.class, 'g', 'a');
+        assertTrue(range5.isEmpty());
+        assertTrue(range6.isEmpty());
+        assertTrue(range5.equals(range6));
+
+
+    }
+}

Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message