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