Author: desruisseaux
Date: Wed Feb 20 20:19:14 2013
New Revision: 1448375
URL: http://svn.apache.org/r1448375
Log:
Initial port of RangeSetTest, excluding the testRangeRemoval() method for legal
reasons.
Added:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java
(with props)
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java
(with props)
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/RangeSet.java
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/RangeSet.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/RangeSet.java?rev=1448375&r1=1448374&r2=1448375&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/RangeSet.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/RangeSet.java
Wed Feb 20 20:19:14 2013
@@ -30,6 +30,7 @@ import java.util.AbstractSet;
import java.util.NoSuchElementException;
import java.util.ConcurrentModificationException;
import net.jcip.annotations.NotThreadSafe;
+import org.apache.sis.measure.NumberRange;
import org.apache.sis.measure.Range;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.ArgumentChecks;
@@ -37,9 +38,6 @@ import org.apache.sis.util.resources.Err
import static org.apache.sis.util.Numbers.*;
-// Related to JDK7
-import java.util.Objects;
-
/**
* An ordered set of ranges where overlapping ranges are merged.
@@ -161,7 +159,7 @@ public class RangeSet<E extends Comparab
*
* @see #getElementType()
*/
- private final Class<E> elementType;
+ final Class<E> elementType;
/**
* The primitive type, as one of {@code DOUBLE}, {@code FLOAT}, {@code
LONG}, {@code INTEGER},
@@ -194,10 +192,12 @@ public class RangeSet<E extends Comparab
/**
* Constructs an initially empty set of ranges.
+ * This constructor is provided for sub-classing only.
+ * Client code should use the static {@link #create(Class)} method instead.
*
* @param elementType The type of the range elements.
*/
- public RangeSet(final Class<E> elementType) {
+ protected RangeSet(final Class<E> elementType) {
ArgumentChecks.ensureNonNull("elementType", elementType);
// Following assertion may fail only if the user bypass the
parameterized type checks.
assert Comparable.class.isAssignableFrom(elementType) : elementType;
@@ -206,6 +206,22 @@ public class RangeSet<E extends Comparab
}
/**
+ * Constructs an initially empty set of ranges.
+ *
+ * @param <E> The type of range elements.
+ * @param elementType The type of the range elements.
+ * @return A new range set for range elements of the given type.
+ */
+ @SuppressWarnings("unchecked")
+ public static <E extends Comparable<? super E>> RangeSet<E> create(final
Class<E> elementType) {
+ ArgumentChecks.ensureNonNull("elementType", elementType);
+ if (Number.class.isAssignableFrom(elementType)) {
+ return new Numeric(elementType);
+ }
+ return new RangeSet<>(elementType);
+ }
+
+ /**
* Returns the type of elements in this collection.
*/
@Override
@@ -245,21 +261,16 @@ public class RangeSet<E extends Comparab
}
/**
- * Unconditionally copies the internal array in a new array of the given
length.
- * If the new length is less than the current {@linkplain #length}, then
the last
- * elements are lost.
- *
- * @param size The new array length (twice the number of elements).
+ * Unconditionally copies the internal array in a new array having just
the required length.
*/
- private void resize(final int size) {
- if (size == 0) {
+ private void reallocate() {
+ if (length == 0) {
array = null;
} else {
final Object oldArray = array;
- array = Array.newInstance(oldArray.getClass().getComponentType(),
size);
- System.arraycopy(oldArray, 0, array, 0, Math.min(size, length));
+ array = Array.newInstance(oldArray.getClass().getComponentType(),
length);
+ System.arraycopy(oldArray, 0, array, 0, length);
}
- length = size;
}
/**
@@ -270,7 +281,7 @@ public class RangeSet<E extends Comparab
public final void trimToSize() {
// This method is final because equals(Object) and other methods rely
on this behavior.
if (array != null && Array.getLength(array) != length) {
- resize(length); // Will set the array to null if length == 0.
+ reallocate(); // Will set the array to null if length == 0.
assert isSorted();
}
}
@@ -792,31 +803,32 @@ public class RangeSet<E extends Comparab
* @return The new range for the given values.
*/
protected Range<E> newRange(final E lower, final E upper) {
- return new Range<>(elementType, lower, true, upper, true);
+ return new Range<>(elementType, lower, true, upper, false);
}
/**
- * Returns a hash value for this set of ranges.
- * This value need not remain consistent between
- * different implementations of the same class.
+ * A {@link RangeSet} implementation for {@link NumberRange} elements.
+ *
+ * @see RangeSet#create(Class)
*/
- @Override
- public int hashCode() {
- trimToSize();
- final int code;
- switch (elementCode) {
- case DOUBLE: code = Arrays.hashCode((double[]) array); break;
- case FLOAT: code = Arrays.hashCode((float[]) array); break;
- case LONG: code = Arrays.hashCode((long[]) array); break;
- case INTEGER: code = Arrays.hashCode((int[]) array); break;
- case SHORT: code = Arrays.hashCode((short[]) array); break;
- case BYTE: code = Arrays.hashCode((byte[]) array); break;
- case CHARACTER: code = Arrays.hashCode((char[]) array); break;
- default: code = Arrays.hashCode((Object[]) array); break;
+ private static final class Numeric<E extends Number & Comparable<? super
E>> extends RangeSet<E> {
+ private static final long serialVersionUID = 934107071458551753L;
+
+ Numeric(final Class<E> elementType) {
+ super(elementType);
+ }
+
+ @Override
+ protected Range<E> newRange(final E lower, final E upper) {
+ return new NumberRange<>(elementType, lower, true, upper, false);
}
- return code ^ elementType.hashCode();
}
+ /*
+ * Do not override hash code - or if we do, we shall make sure than the
+ * hash code value is computed as documented in the Set interface.
+ */
+
/**
* Compares the specified object with this set of ranges for equality.
*
@@ -828,26 +840,27 @@ public class RangeSet<E extends Comparab
if (object == this) {
return true;
}
- if (object != null && object.getClass() == getClass()) {
+ if (object instanceof RangeSet<?>) {
final RangeSet<?> that = (RangeSet<?>) object;
- if (length == that.length && Objects.equals(elementType,
that.elementType)) {
- this.trimToSize();
- that.trimToSize();
- final Object a1 = this.array;
- final Object a2 = that.array;
- switch (elementCode) {
- case DOUBLE: return Arrays.equals((double[]) a1,
(double[]) a2);
- case FLOAT: return Arrays.equals((float []) a1, (
float[]) a2);
- case LONG: return Arrays.equals((long []) a1, (
long[]) a2);
- case INTEGER: return Arrays.equals((int []) a1, (
int[]) a2);
- case SHORT: return Arrays.equals((short []) a1, (
short[]) a2);
- case BYTE: return Arrays.equals((byte []) a1, (
byte[]) a2);
- case CHARACTER: return Arrays.equals((char []) a1, (
char[]) a2);
- default: return Arrays.equals((Object[]) a1,
(Object[]) a2);
- }
+ if (length != that.length || elementType != that.elementType) {
+ return false;
+ }
+ this.trimToSize();
+ that.trimToSize();
+ final Object a1 = this.array;
+ final Object a2 = that.array;
+ switch (elementCode) {
+ case DOUBLE: return Arrays.equals((double[]) a1, (double[])
a2);
+ case FLOAT: return Arrays.equals((float []) a1, ( float[])
a2);
+ case LONG: return Arrays.equals((long []) a1, ( long[])
a2);
+ case INTEGER: return Arrays.equals((int []) a1, ( int[])
a2);
+ case SHORT: return Arrays.equals((short []) a1, ( short[])
a2);
+ case BYTE: return Arrays.equals((byte []) a1, ( byte[])
a2);
+ case CHARACTER: return Arrays.equals((char []) a1, ( char[])
a2);
+ default: return Arrays.equals((Object[]) a1, (Object[])
a2);
}
}
- return false;
+ return super.equals(object); // Allow comparison with other Set
implementations.
}
/**
@@ -865,7 +878,7 @@ public class RangeSet<E extends Comparab
// Should not happen, since we are cloneable.
throw new AssertionError(exception);
}
- set.resize(length);
+ set.reallocate();
return set;
}
Added:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java?rev=1448375&view=auto
==============================================================================
---
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java
(added)
+++
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java
Wed Feb 20 20:19:14 2013
@@ -0,0 +1,41 @@
+/*
+ * 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.sis.test;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotates methods that are used only for testing the performance of a class.
+ * The annotated methods are not executed in normal SIS build. They are rather
+ * executed manually before and after an implementation change, in order to
test
+ * the impact on performance.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3 (derived from geotk-3.17)
+ * @version 0.3
+ * @module
+ */
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface Performance {
+}
Propchange:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/Performance.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1448375&r1=1448374&r2=1448375&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
(original)
+++
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
Wed Feb 20 20:19:14 2013
@@ -87,6 +87,7 @@ import org.junit.runners.Suite;
org.apache.sis.io.WordWrapWithLineSeparatorTest.class,
org.apache.sis.io.TableAppenderTest.class,
org.apache.sis.util.collection.TreeTableFormatTest.class,
+ org.apache.sis.util.collection.RangeSetTest.class,
// XML most basic types.
org.apache.sis.xml.XLinkTest.class,
Added:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java?rev=1448375&view=auto
==============================================================================
---
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java
(added)
+++
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java
Wed Feb 20 20:19:14 2013
@@ -0,0 +1,202 @@
+/*
+ * 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.sis.util.collection;
+
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Random;
+import org.apache.sis.measure.Range;
+import org.apache.sis.measure.NumberRange;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.Performance;
+import org.junit.Test;
+
+import static org.apache.sis.test.Assert.*;
+
+
+/**
+ * Tests the {@link RangeSet} implementation.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3 (derived from geotk-2.0)
+ * @version 0.3
+ * @module
+ */
+@DependsOn(org.apache.sis.measure.RangeTest.class)
+public final strictfp class RangeSetTest extends TestCase {
+ /**
+ * Tests {@link RangeSet#add(Range)} using integer values.
+ */
+ @Test
+ public void testIntegers() {
+ final RangeSet<Integer> ranges = RangeSet.create(Integer.class);
+ assertTrue(ranges.isEmpty());
+ /*
+ * Add a singleton element.
+ */
+ assertTrue(ranges.add(10, 22));
+ assertEquals(1, ranges.size());
+ assertTrue (ranges.contains(NumberRange.create(10, true, 22, false)));
+ assertFalse(ranges.contains(NumberRange.create(10, true, 20, false)));
+ /*
+ * Add a new element which should be merged with the previous one.
+ */
+ assertTrue(ranges.add(14, 25));
+ assertEquals(1, ranges.size());
+ assertFalse(ranges.contains(NumberRange.create(10, true, 22, false)));
+ assertTrue (ranges.contains(NumberRange.create(10, true, 25, false)));
+ /*
+ * Add a new element which is disjoint with other element.
+ */
+ assertTrue(ranges.add(-5, 5));
+ assertEquals(2, ranges.size());
+ assertTrue(ranges.contains(NumberRange.create(10, true, 25, false)));
+ assertTrue(ranges.contains(NumberRange.create(-5, true, 5, false)));
+ /*
+ * Merge the two ranges together.
+ */
+ assertTrue(ranges.add(NumberRange.create(5, true, 10, false)));
+ assertEquals(1, ranges.size());
+ assertFalse(ranges.contains(NumberRange.create(10, true, 25, false)));
+ assertFalse(ranges.contains(NumberRange.create(-5, true, 5, false)));
+ assertTrue (ranges.contains(NumberRange.create(-5, true, 25, false)));
+ /*
+ * Add more ranges.
+ */
+ assertTrue(ranges.add(40, 50));
+ assertTrue(ranges.add(30, 35));
+ assertTrue(ranges.add(NumberRange.create(28, true, 32, false)));
+ assertTrue(ranges.add(-20, -10));
+ assertTrue(ranges.add(60, 70));
+ assertEquals(5, ranges.size());
+ /*
+ * Verify the RangeSet content.
+ */
+ final Iterator<Range<Integer>> it = ranges.iterator();
+ assertEquals(NumberRange.create(-20, true, -10, false), it.next());
+ assertEquals(NumberRange.create( -5, true, 25, false), it.next());
+ assertEquals(NumberRange.create( 28, true, 35, false), it.next());
+ assertEquals(NumberRange.create( 40, true, 50, false), it.next());
+ assertEquals(NumberRange.create( 60, true, 70, false), it.next());
+ assertFalse(it.hasNext());
+ }
+
+ /**
+ * Tests {@link RangeSet} using date values.
+ */
+ @Test
+ public void testDates() {
+ final RangeSet<Date> ranges = RangeSet.create(Date.class);
+ assertTrue(ranges.isEmpty());
+ /*
+ * Add a singleton range.
+ */
+ final long day = 24*60*60*1000L;
+ final Date now = new Date();
+ final Date yesterday = new Date(now.getTime() - day);
+ assertTrue(ranges.add(yesterday, now));
+ assertEquals(1, ranges.size());
+ assertTrue(ranges.contains(new Range<>(Date.class, yesterday, true,
now, false)));
+ /*
+ * Add a disjoint range.
+ */
+ final Date lastWeek = new Date(now.getTime() - 7*day);
+ final Date other = new Date(lastWeek.getTime() + 2*day);
+ assertTrue(ranges.add(new Range<>(Date.class, lastWeek, true, other,
false)));
+ assertEquals(2, ranges.size());
+ /*
+ * Verify the RangeSet content.
+ */
+ final Iterator<Range<Date>> it = ranges.iterator();
+ assertEquals(new Range<>(Date.class, lastWeek, true, other, false),
it.next());
+ assertEquals(new Range<>(Date.class, yesterday, true, now, false),
it.next());
+ assertFalse(it.hasNext());
+ }
+
+ /**
+ * Tests {@link RangeSet} using string values.
+ */
+ @Test
+ public void testStrings() {
+ final RangeSet<String> ranges = RangeSet.create(String.class);
+ assertTrue(ranges.isEmpty());
+ assertTrue(ranges.add("FAA", "FBB"));
+ assertEquals(1, ranges.size());
+ assertTrue(ranges.contains(new Range<>(String.class, "FAA", true,
"FBB", false)));
+ /*
+ * Merge the singleton range with the given range.
+ */
+ assertTrue(ranges.add("FAZ", "FCC"));
+ assertEquals(1, ranges.size());
+ assertTrue(ranges.contains(new Range<>(String.class, "FAA", true,
"FCC", false)));
+ /*
+ * Add a disjoint range.
+ */
+ assertTrue(ranges.add("GAA", "GBB"));
+ assertEquals(2, ranges.size());
+ /*
+ * Verify the RangeSet content.
+ */
+ final Iterator<Range<String>> it = ranges.iterator();
+ assertEquals(new Range<>(String.class, "FAA", true, "FCC", false),
it.next());
+ assertEquals(new Range<>(String.class, "GAA", true, "GBB", false),
it.next());
+ assertFalse(it.hasNext());
+ }
+
+ /**
+ * Tests serialization.
+ */
+ @Test
+ public void testSerialization() {
+ final RangeSet<Double> ranges = RangeSet.create(Double.class);
+ assertTrue(ranges.add(12.0, 12.5));
+ assertTrue(ranges.add(18.0, 18.5));
+ assertTrue(ranges.add(19.0, 20.0));
+ assertNotSame(ranges, assertSerializedEquals(ranges));
+ }
+
+ /**
+ * Tests the performance of {@link RangeSet} implementation. This test is
not executed
+ * in normal SIS build. We run this test only when the {@link RangeSet}
implementation
+ * changed, and we want to test the impact of that change on the
performance.
+ *
+ * @throws InterruptedException If the test has been interrupted.
+ */
+ @Performance
+ public void testPerformance() throws InterruptedException {
+ final Random r = new Random(5638743);
+ for (int p=0; p<10; p++) {
+ final long start = System.nanoTime();
+ final RangeSet<Integer> set = RangeSet.create(Integer.class);
+ for (int i=0; i<100000; i++) {
+ final int lower = r.nextInt(1000000) - 500;
+ final int upper = lower + r.nextInt(100) + 1;
+ if (r.nextBoolean()) {
+ set.add(lower, upper);
+ } else {
+ set.remove(lower, upper);
+ }
+ }
+ if (out != null) {
+ final long end = System.nanoTime();
+ out.println((end - start) / 1E9 + " " + set.size());
+ }
+ Thread.sleep(1000);
+ }
+ }
+}
Propchange:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/RangeSetTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain