sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1448375 - in /sis/branches/JDK7/sis-utility/src: main/java/org/apache/sis/util/collection/ test/java/org/apache/sis/test/ test/java/org/apache/sis/test/suite/ test/java/org/apache/sis/util/collection/
Date Wed, 20 Feb 2013 20:19:14 GMT
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



Mime
View raw message