sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1790799 - in /sis/branches/JDK7: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/ core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/ core/sis-referencing/src/main/java/org/apache/si...
Date Mon, 10 Apr 2017 10:44:41 GMT
Author: desruisseaux
Date: Mon Apr 10 10:44:41 2017
New Revision: 1790799

URL: http://svn.apache.org/viewvc?rev=1790799&view=rev
Log:
Merge the new operation methods and the Quantity implementation from JDK8 branch.

Added:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AxisOrderReversal.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AxisOrderReversal.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AxisOrderReversal3D.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AxisOrderReversal3D.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicAndVerticalOffsets.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicAndVerticalOffsets.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Quantities.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Quantities.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java
      - copied, changed from r1790797, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/ScalarFactory.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ScalarFactory.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/ScalarFallback.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ScalarFallback.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/QuantitiesTest.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/QuantitiesTest.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/ScalarTest.java
      - copied unchanged from r1790797, sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ScalarTest.java
Modified:
    sis/branches/JDK7/   (props changed)
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetCode.java
    sis/branches/JDK7/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
    sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractConverter.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/UnitServices.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/FrequencySortedSet.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/collection/FrequencySortedSetTest.java
    sis/branches/JDK7/pom.xml

Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Apr 10 10:44:41 2017
@@ -1,5 +1,5 @@
 /sis/branches/Android:1430670-1480699
 /sis/branches/JDK6:1394913-1508480
-/sis/branches/JDK8:1584960-1790133
+/sis/branches/JDK8:1584960-1790797
 /sis/branches/JDK9:1773327-1789983
 /sis/trunk:1394364-1508466,1519089-1519674

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetCode.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetCode.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetCode.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetCode.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -39,6 +39,12 @@ import org.apache.sis.internal.jaxb.gmd.
  */
 public final class MD_CharacterSetCode extends XmlAdapter<MD_CharacterSetCode, Charset> {
     /**
+     * Empty constructor for JAXB only.
+     */
+    public MD_CharacterSetCode() {
+    }
+
+    /**
      * The value of the {@link org.opengis.util.CodeList}.
      */
     private CodeListUID identifier;

Modified: sis/branches/JDK7/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -230,7 +230,7 @@ final class FinalLocationType extends Ab
      *
      * @return property used as the defining characteristic of the location type.
      *
-     * @see ReferenceSystemUsingIdentifiers#getTheme()
+     * @see ReferencingByIdentifiers#getTheme()
      */
     @Override
     public InternationalString getTheme() {

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -87,7 +87,7 @@ public class GeographicOffsets extends G
     }
 
     /**
-     * For subclasses constructor only.
+     * For default constructors in this class and subclasses.
      */
     GeographicOffsets(int sourceDimensions, int targetDimensions,
             ParameterDescriptorGroup parameters, GeodeticOperation[] redimensioned)
@@ -96,6 +96,13 @@ public class GeographicOffsets extends G
     }
 
     /**
+     * Returns the parameter descriptor for the vertical axis.
+     */
+    ParameterDescriptor<Double> vertical() {
+        return TZ;
+    }
+
+    /**
      * Creates a transform from the specified group of parameter values.
      * The parameter values are unconditionally converted to degrees and metres.
      *
@@ -112,7 +119,7 @@ public class GeographicOffsets extends G
         final Matrix4 t = new Matrix4();
         t.m03 = pv.doubleValue(TX);
         t.m13 = pv.doubleValue(TY);
-        t.m23 = pv.doubleValue(TZ);
+        t.m23 = pv.doubleValue(vertical());
         return MathTransforms.linear(t);
     }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -329,7 +329,7 @@ final class CopyTransform extends Abstra
      * Creates the inverse transform of this object.
      */
     @Override
-    @SuppressWarnings("DoubleCheckedLocking")  // Okay since 'inverse' is volatile.
+    @SuppressWarnings("DoubleCheckedLocking")                                   // Okay since 'inverse' is volatile.
     public LinearTransform inverse() throws NoninvertibleTransformException {
         LinearTransform inv = inverse;
         if (inv == null) {
@@ -379,8 +379,8 @@ final class CopyTransform extends Abstra
                     }
                     /*
                      * At this point, we know that we can create the inverse transform.
-                     * If this transform is the identity transform (we should never happen,
-                     * but we are paranoiac), then the old and new arrays would be equal.
+                     * If this transform is the identity transform or an anti-diagonal matrix except last row
+                     * (e.g. matrix used for swapping axis order), then the old and new arrays would be equal.
                      */
                     CopyTransform copyInverse = this;
                     if (!Arrays.equals(reverse, indices)) {

Modified: sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Mon Apr 10 10:44:41 2017
@@ -1,10 +1,13 @@
 # Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.
 # Heavier classes (e.g. having more dependencies) or classes less likely to be used, should be last.
 org.apache.sis.internal.referencing.provider.Affine
+org.apache.sis.internal.referencing.provider.AxisOrderReversal
+org.apache.sis.internal.referencing.provider.AxisOrderReversal3D
 org.apache.sis.internal.referencing.provider.Geographic3Dto2D
 org.apache.sis.internal.referencing.provider.Geographic2Dto3D
 org.apache.sis.internal.referencing.provider.GeographicOffsets
 org.apache.sis.internal.referencing.provider.GeographicOffsets2D
+org.apache.sis.internal.referencing.provider.GeographicAndVerticalOffsets
 org.apache.sis.internal.referencing.provider.VerticalOffset
 org.apache.sis.internal.referencing.provider.LongitudeRotation
 org.apache.sis.internal.referencing.provider.GeocentricTranslation

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -53,8 +53,11 @@ public final strictfp class ProvidersTes
     private static Class<?>[] methods() {
         return new Class<?>[] {
             Affine.class,
+            AxisOrderReversal.class,
+            AxisOrderReversal3D.class,
             GeographicOffsets.class,
             GeographicOffsets2D.class,
+            GeographicAndVerticalOffsets.class,
             VerticalOffset.class,
             LongitudeRotation.class,
             CoordinateFrameRotation.class,
@@ -114,6 +117,7 @@ public final strictfp class ProvidersTes
             LongitudeRotation.class,
             GeographicOffsets.class,
             GeographicOffsets2D.class,
+            GeographicAndVerticalOffsets.class,
             CoordinateFrameRotation2D.class,
             CoordinateFrameRotation3D.class,
             PositionVector7Param2D.class,

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractConverter.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractConverter.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractConverter.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -18,6 +18,7 @@ package org.apache.sis.measure;
 
 import java.io.Serializable;
 import javax.measure.UnitConverter;
+import org.apache.sis.math.DecimalFunctions;
 
 
 /**
@@ -67,4 +68,12 @@ abstract class AbstractConverter impleme
         }
         return Double.NaN;
     }
+
+    /**
+     * Returns the value of the given number, with special handling for {@link Float} value on the assumption
+     * that the original value was written in base 10. This is usually the case for unit conversion factors.
+     */
+    static double doubleValue(final Number n) {
+        return (n instanceof Float) ? DecimalFunctions.floatToDouble(n.floatValue()) : n.doubleValue();
+    }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -93,13 +93,25 @@ abstract class AbstractUnit<Q extends Qu
      *
      * <p>This information may be approximative since we can not always guess correctly whether the result of
      * an operation is part of SI or not. Values given to the field may be adjusted in any future version.</p>
+     *
+     * <p>This information is not serialized because {@link #readResolve()} will replace the deserialized instance
+     * by a hard-coded instance with appropriate value, if possible.</p>
+     *
+     * @see #equals(short, short)
      */
-    final byte scope;
+    final transient byte scope;
 
     /**
      * The EPSG code, or 0 if this unit has no EPSG code.
+     *
+     * <p>This information is not serialized because {@link #readResolve()} will replace the deserialized instance
+     * by a hard-coded instance with appropriate value, if possible. Note that EPSG codes are not included in the
+     * {@code sis-uom} module (a module containing a subset of {@code sis-utility} module), so we need to ignore
+     * this field at serialization time if we want compatible serialization forms.</p>
+     *
+     * @see #equals(short, short)
      */
-    final short epsg;
+    final transient short epsg;
 
     /**
      * Creates a new unit having the given symbol and EPSG code.
@@ -294,7 +306,18 @@ abstract class AbstractUnit<Q extends Qu
             return true;
         }
         final AbstractUnit<?> that = (AbstractUnit<?>) other;
-        return epsg == that.epsg && scope == that.scope && Objects.equals(symbol, that.symbol);
+        return equals(epsg, that.epsg) && equals(scope, that.scope) && Objects.equals(symbol, that.symbol);
+    }
+
+    /**
+     * Compares the given values only if both of them are non-zero. If at least one value is zero (meaning "unknown"),
+     * assume that values are equal. We do that because deserialized {@code AbstractUnit} instances have {@link #epsg}
+     * and {@link #scope} fields initialized to 0, and we need to ignore those values when comparing the deserialized
+     * instances with instances hard-coded in {@link Units} class. We should not have inconsistencies because there is
+     * no public way to set those fields; they can only be defined in the {@code Units} hard-coded constants.
+     */
+    private static boolean equals(final short a, final short b) {
+        return (a == 0) || (b == 0) || (a == b);
     }
 
     /**
@@ -302,7 +325,8 @@ abstract class AbstractUnit<Q extends Qu
      */
     @Override
     public int hashCode() {
-        return epsg + 31 * Objects.hashCode(symbol);
+        // Do not use EPSG code or scope because they are not serialized.
+        return 31 * Objects.hashCode(symbol);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -27,7 +27,6 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.StringBuilders;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.LenientComparable;
-import org.apache.sis.math.DecimalFunctions;
 import org.apache.sis.math.MathFunctions;
 import org.apache.sis.math.Fraction;
 import org.apache.sis.internal.util.Numerics;
@@ -333,14 +332,7 @@ final class LinearConverter extends Abst
                 }
                 value = ((BigDecimal) value).multiply(scale10).add(offset10);
             } else {
-                final double x;
-                if (value instanceof Float) {
-                    // Because unit conversion factors are usually defined in base 10.
-                    x = DecimalFunctions.floatToDouble((Float) value);
-                } else {
-                    x = value.doubleValue();
-                }
-                value = convert(x);
+                value = convert(doubleValue(value));
             }
         }
         return value;

Copied: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java (from r1790797, sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java?p2=sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java&p1=sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java&r1=1790797&r2=1790799&rev=1790799&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Scalar.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -289,7 +289,8 @@ abstract class Scalar<Q extends Quantity
      */
     @Override
     public final int hashCode() {
-        return Double.hashCode(value) ^ unit.hashCode();
+        final long bits = Double.doubleToLongBits(value);
+        return ((int) (bits ^ (bits >>> 32))) ^ unit.hashCode();
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -26,6 +26,7 @@ import javax.measure.Dimension;
 import javax.measure.UnitConverter;
 import javax.measure.UnconvertibleException;
 import javax.measure.IncommensurableException;
+import javax.measure.spi.QuantityFactory;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverters;
 import org.apache.sis.util.ComparisonMode;
@@ -48,7 +49,7 @@ import org.apache.sis.math.Fraction;
  * @since 0.8
  * @module
  */
-final class SystemUnit<Q extends Quantity<Q>> extends AbstractUnit<Q> {
+final class SystemUnit<Q extends Quantity<Q>> extends AbstractUnit<Q> implements QuantityFactory<Q> {
     /**
      * For cross-version compatibility.
      */
@@ -65,6 +66,13 @@ final class SystemUnit<Q extends Quantit
     final UnitDimension dimension;
 
     /**
+     * The factory to use for creating quantities, or {@code null} if none.
+     * This field does not need to be serialized because {@link AbstractUnit#readResolve()}
+     * replaces deserialized instances by corresponding {@link Units} hard-coded instances.
+     */
+    final transient ScalarFactory<Q> factory;
+
+    /**
      * Units for the same quantity but with scale factors that are not the SI one.
      * This is initialized by {@link Units} only and shall not change anymore after.
      * All units in this array shall use an instance of {@link LinearConverter}.
@@ -81,11 +89,15 @@ final class SystemUnit<Q extends Quantit
      * @param  symbol     the unit symbol, or {@code null} if this unit has no specific symbol.
      * @param  scope      {@link UnitRegistry#SI}, {@link UnitRegistry#ACCEPTED}, other constants or 0 if unknown.
      * @param  epsg       the EPSG code, or 0 if this unit has no EPSG code.
+     * @param  factory    the factory to use for creating quantities, or {@code null} if none.
      */
-    SystemUnit(final Class<Q> quantity, final UnitDimension dimension, final String symbol, final byte scope, final short epsg) {
+    SystemUnit(final Class<Q> quantity, final UnitDimension dimension, final String symbol,
+            final byte scope, final short epsg, final ScalarFactory<Q> factory)
+    {
         super(symbol, scope, epsg);
         this.quantity  = quantity;
         this.dimension = dimension;
+        this.factory   = factory;
     }
 
     /**
@@ -99,7 +111,7 @@ final class SystemUnit<Q extends Quantit
         }
         SystemUnit<?> result = Units.get(dim);
         if (result == null) {
-            result = new SystemUnit(null, dim, null, (byte) 0, (short) 0);
+            result = new SystemUnit(null, dim, null, (byte) 0, (short) 0, null);
         }
         return result;
     }
@@ -241,7 +253,7 @@ final class SystemUnit<Q extends Quantit
          */
         SystemUnit<T> unit = Units.get(type);
         if (unit == null) {
-            unit = new SystemUnit<>(type, dimension, null, (byte) 0, (short) 0);       // Intentionally no symbol.
+            unit = new SystemUnit<>(type, dimension, null, (byte) 0, (short) 0, null);  // Intentionally no symbol.
         }
         if (!dimension.equals(unit.dimension)) {
             throw new ClassCastException(Errors.format(Errors.Keys.IncompatibleUnitDimension_5, new Object[] {
@@ -358,7 +370,7 @@ final class SystemUnit<Q extends Quantit
         if (symbol.equals(getSymbol())) {
             return this;
         }
-        final SystemUnit<Q> alt = new SystemUnit<>(quantity, dimension, symbol, (byte) 0, (short) 0);
+        final SystemUnit<Q> alt = new SystemUnit<>(quantity, dimension, symbol, (byte) 0, (short) 0, factory);
         if (quantity != null) {
             /*
              * Use the cache only if this unit has a non-null quantity type. Do not use the cache even
@@ -509,4 +521,17 @@ final class SystemUnit<Q extends Quantit
     public int hashCode() {
         return super.hashCode() + 37 * dimension.hashCode();
     }
+
+    /**
+     * Creates a quantity for the given value and unit of measurement.
+     */
+    @Override
+    public Quantity<Q> create(final Number value, final Unit<Q> unit) {
+        final double v = AbstractConverter.doubleValue(value);
+        if (factory != null) {
+            return factory.create(v, unit);
+        } else {
+            return ScalarFallback.factory(v, unit, quantity);
+        }
+    }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/UnitServices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/UnitServices.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/UnitServices.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/UnitServices.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -20,6 +20,7 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Set;
+import javax.measure.Unit;
 import javax.measure.Quantity;
 import javax.measure.format.UnitFormat;
 import javax.measure.spi.QuantityFactory;
@@ -220,15 +221,31 @@ public class UnitServices extends Servic
     }
 
     /**
-     * Return a factory for the given {@code Quantity} type, or {@code null} if none.
-     * Current implementation returns {@code null}.
+     * Return a factory for the given {@code Quantity} type. In the particular case of Apache SIS implementation,
+     * {@link Quantities#create(double, Unit)} provides a more direct way to instantiate quantities.
      *
      * @param  <Q>   compile-time value of the {@code type} argument.
      * @param  type  type of the desired the quantity.
      * @return the service to obtain {@link Quantity} instances, or {@code null} if none.
+     *
+     * @see Quantities#create(double, Unit)
      */
     @Override
     public <Q extends Quantity<Q>> QuantityFactory<Q> getQuantityFactory(final Class<Q> type) {
-        return null;
+        QuantityFactory<Q> factory = Units.get(type);
+        if (factory == null) {
+            factory = new QuantityFactory<Q>() {
+                @Override
+                public Quantity<Q> create(final Number value, final Unit<Q> unit) {
+                    return ScalarFallback.factory(AbstractConverter.doubleValue(value), unit, type);
+                }
+
+                @Override
+                public Unit<Q> getSystemUnit() {
+                    return null;
+                }
+            };
+        }
+        return factory;
     }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -1060,15 +1060,17 @@ public final class Units extends Static
         final UnitDimension dimensionless = UnitDimension.NONE;
         /*
          * Base, derived or alternate units that we need to reuse more than once in this static initializer.
+         * Note: JDK8 branch uses much more compact method references instead than following inner classes.
          */
-        final SystemUnit<Length>        m   = add(Length.class,        length,        "m",   UnitRegistry.SI, Constants.EPSG_METRE);
-        final SystemUnit<Area>          m2  = add(Area.class,          area,          "m²",  UnitRegistry.SI, (short) 0);
-        final SystemUnit<Time>          s   = add(Time.class,          time,          "s",   UnitRegistry.SI, (short) 1040);
-        final SystemUnit<Temperature>   K   = add(Temperature.class,   temperature,   "K",   UnitRegistry.SI, (short) 0);
-        final SystemUnit<Speed>         mps = add(Speed.class,         speed,         "m∕s", UnitRegistry.SI, (short) 1026);
-        final SystemUnit<Pressure>      Pa  = add(Pressure.class,      pressure,      "Pa",  UnitRegistry.SI, (short) 0);
-        final SystemUnit<Angle>         rad = add(Angle.class,         dimensionless, "rad", UnitRegistry.SI, (short) 9101);
-        final SystemUnit<Dimensionless> one = add(Dimensionless.class, dimensionless, "",    UnitRegistry.SI, (short) 9201);
+        ScalarFactory<Dimensionless> dimensionlessFactory =            new ScalarFactory<Dimensionless>() {@Override public Dimensionless create(double value, Unit<Dimensionless> unit) {return new Scalar.Dimensionless(value, unit);}};
+        final SystemUnit<Length>        m   = add(Length.class,        new ScalarFactory<Length>       () {@Override public Length        create(double value, Unit<Length>        unit) {return new Scalar.Length       (value, unit);}}, length,        "m",   UnitRegistry.SI, Constants.EPSG_METRE);
+        final SystemUnit<Area>          m2  = add(Area.class,          new ScalarFactory<Area>         () {@Override public Area          create(double value, Unit<Area>          unit) {return new Scalar.Area         (value, unit);}}, area,          "m²",  UnitRegistry.SI, (short) 0);
+        final SystemUnit<Time>          s   = add(Time.class,          new ScalarFactory<Time>         () {@Override public Time          create(double value, Unit<Time>          unit) {return new Scalar.Time         (value, unit);}}, time,          "s",   UnitRegistry.SI, (short) 1040);
+        final SystemUnit<Temperature>   K   = add(Temperature.class,   new ScalarFactory<Temperature>  () {@Override public Temperature   create(double value, Unit<Temperature>   unit) {return new Scalar.Temperature  (value, unit);}}, temperature,   "K",   UnitRegistry.SI, (short) 0);
+        final SystemUnit<Speed>         mps = add(Speed.class,         new ScalarFactory<Speed>        () {@Override public Speed         create(double value, Unit<Speed>         unit) {return new Scalar.Speed        (value, unit);}}, speed,         "m∕s", UnitRegistry.SI, (short) 1026);
+        final SystemUnit<Pressure>      Pa  = add(Pressure.class,      new ScalarFactory<Pressure>     () {@Override public Pressure      create(double value, Unit<Pressure>      unit) {return new Scalar.Pressure     (value, unit);}}, pressure,      "Pa",  UnitRegistry.SI, (short) 0);
+        final SystemUnit<Angle>         rad = add(Angle.class,         new ScalarFactory<Angle>        () {@Override public Angle         create(double value, Unit<Angle>         unit) {return new Scalar.Angle        (value, unit);}}, dimensionless, "rad", UnitRegistry.SI, (short) 9101);
+        final SystemUnit<Dimensionless> one = add(Dimensionless.class, dimensionlessFactory, dimensionless, "", UnitRegistry.SI, (short) 9201);
         /*
          * All SI prefix to be used below, with additional converters to be used more than once.
          */
@@ -1144,39 +1146,41 @@ public final class Units extends Static
         /*
          * Electricity and magnetism.
          */
-        AMPERE  = add(ElectricCurrent.class,     current,                      "A",  UnitRegistry.SI, (short) 0);
-        COULOMB = add(ElectricCharge.class,      charge,                       "C",  UnitRegistry.SI, (short) 0);
-        VOLT    = add(ElectricPotential.class,   potential,                    "V",  UnitRegistry.SI, (short) 0);
-        FARAD   = add(ElectricCapacitance.class, charge.divide(potential),     "F",  UnitRegistry.SI, (short) 0);
-        SIEMENS = add(ElectricConductance.class, current.divide(potential),    "S",  UnitRegistry.SI, (short) 0);
-        OHM     = add(ElectricResistance.class,  potential.divide(current),    "Ω",  UnitRegistry.SI, (short) 0);
-        WEBER   = add(MagneticFlux.class,        magneticFlux,                 "Wb", UnitRegistry.SI, (short) 0);
-        TESLA   = add(MagneticFluxDensity.class, magneticFlux.divide(area),    "T",  UnitRegistry.SI, (short) 0);
-        HENRY   = add(ElectricInductance.class,  magneticFlux.divide(current), "H",  UnitRegistry.SI, (short) 0);
+        AMPERE  = add(ElectricCurrent.class,     null, current,                      "A",  UnitRegistry.SI, (short) 0);
+        COULOMB = add(ElectricCharge.class,      null, charge,                       "C",  UnitRegistry.SI, (short) 0);
+        VOLT    = add(ElectricPotential.class,   null, potential,                    "V",  UnitRegistry.SI, (short) 0);
+        FARAD   = add(ElectricCapacitance.class, null, charge.divide(potential),     "F",  UnitRegistry.SI, (short) 0);
+        SIEMENS = add(ElectricConductance.class, null, current.divide(potential),    "S",  UnitRegistry.SI, (short) 0);
+        OHM     = add(ElectricResistance.class,  null, potential.divide(current),    "Ω",  UnitRegistry.SI, (short) 0);
+        WEBER   = add(MagneticFlux.class,        null, magneticFlux,                 "Wb", UnitRegistry.SI, (short) 0);
+        TESLA   = add(MagneticFluxDensity.class, null, magneticFlux.divide(area),    "T",  UnitRegistry.SI, (short) 0);
+        HENRY   = add(ElectricInductance.class,  null, magneticFlux.divide(current), "H",  UnitRegistry.SI, (short) 0);
         /*
          * Other units.
+         * Note: JDK8 branch uses method references instead than inner classes.
          */
         SQUARE_METRE = m2;
-        HECTARE      = add(m2,  ten4,                                      "ha",  UnitRegistry.ACCEPTED, (short) 0);
-        CUBIC_METRE  = add(Volume.class,            length.pow(3),         "m³",  UnitRegistry.SI,       (short) 0);
-        HERTZ        = add(Frequency.class,         time.pow(-1),          "Hz",  UnitRegistry.SI,       (short) 0);
-        KILOGRAM     = add(Mass.class,              mass,                  "kg",  UnitRegistry.SI,       (short) 0);
-        NEWTON       = add(Force.class,             force,                 "N",   UnitRegistry.SI,       (short) 0);
-        JOULE        = add(Energy.class,            energy,                "J",   UnitRegistry.SI,       (short) 0);
-        WATT         = add(Power.class,             power,                 "W",   UnitRegistry.SI,       (short) 0);
-        LUX          = add(Illuminance.class,       luminous.divide(area), "lx",  UnitRegistry.SI,       (short) 0);
-        LUMEN        = add(LuminousFlux.class,      luminous,              "lm",  UnitRegistry.SI,       (short) 0);
-        CANDELA      = add(LuminousIntensity.class, luminous,              "cd",  UnitRegistry.SI,       (short) 0);    // Must be after Lumen.
-        MOLE         = add(AmountOfSubstance.class, amount,                "mol", UnitRegistry.SI,       (short) 0);
-        STERADIAN    = add(SolidAngle.class,        dimensionless,         "sr",  UnitRegistry.SI,       (short) 0);
+        HECTARE      = add(m2, ten4, "ha",  UnitRegistry.ACCEPTED, (short) 0);
+        CUBIC_METRE  = add(Volume.class,    new ScalarFactory<Volume>   () {@Override public Volume    create(double value, Unit<Volume>    unit) {return new Scalar.Volume   (value, unit);}}, length.pow(3), "m³", UnitRegistry.SI, (short) 0);
+        HERTZ        = add(Frequency.class, new ScalarFactory<Frequency>() {@Override public Frequency create(double value, Unit<Frequency> unit) {return new Scalar.Frequency(value, unit);}}, time.pow(-1),  "Hz", UnitRegistry.SI, (short) 0);
+        KILOGRAM     = add(Mass.class,      new ScalarFactory<Mass>     () {@Override public Mass      create(double value, Unit<Mass>      unit) {return new Scalar.Mass     (value, unit);}}, mass,          "kg", UnitRegistry.SI, (short) 0);
+        NEWTON       = add(Force.class,     new ScalarFactory<Force>    () {@Override public Force     create(double value, Unit<Force>     unit) {return new Scalar.Force    (value, unit);}}, force,         "N",  UnitRegistry.SI, (short) 0);
+        JOULE        = add(Energy.class,    new ScalarFactory<Energy>   () {@Override public Energy    create(double value, Unit<Energy>    unit) {return new Scalar.Energy   (value, unit);}}, energy,        "J",  UnitRegistry.SI, (short) 0);
+        WATT         = add(Power.class,     new ScalarFactory<Power>    () {@Override public Power     create(double value, Unit<Power>     unit) {return new Scalar.Power    (value, unit);}}, power,         "W",  UnitRegistry.SI, (short) 0);
+        LUX          = add(Illuminance.class,       null, luminous.divide(area), "lx",  UnitRegistry.SI, (short) 0);
+        LUMEN        = add(LuminousFlux.class,      null, luminous,              "lm",  UnitRegistry.SI, (short) 0);
+        CANDELA      = add(LuminousIntensity.class, null, luminous,              "cd",  UnitRegistry.SI, (short) 0);    // Must be after Lumen.
+        MOLE         = add(AmountOfSubstance.class, null, amount,                "mol", UnitRegistry.SI, (short) 0);
+        STERADIAN    = add(SolidAngle.class,        null, dimensionless,         "sr",  UnitRegistry.SI, (short) 0);
         /*
          * All Unit<Dimensionless>.
+         * Note: JDK8 branch uses method references instead than inner classes.
          */
-        PERCENT = add(one, centi,                         "%",     UnitRegistry.OTHER, (short) 0);
-        PPM     = add(one, micro,                         "ppm",   UnitRegistry.OTHER, (short) 9202);
-        PSU     = add(Dimensionless.class, dimensionless, "psu",   UnitRegistry.OTHER, (short) 0);
-        SIGMA   = add(Dimensionless.class, dimensionless, "sigma", UnitRegistry.OTHER, (short) 0);
-        PIXEL   = add(Dimensionless.class, dimensionless, "px",    UnitRegistry.OTHER, (short) 0);
+        PERCENT = add(one, centi,                                               "%",     UnitRegistry.OTHER, (short) 0);
+        PPM     = add(one, micro,                                               "ppm",   UnitRegistry.OTHER, (short) 9202);
+        PSU     = add(Dimensionless.class, dimensionlessFactory, dimensionless, "psu",   UnitRegistry.OTHER, (short) 0);
+        SIGMA   = add(Dimensionless.class, dimensionlessFactory, dimensionless, "sigma", UnitRegistry.OTHER, (short) 0);
+        PIXEL   = add(Dimensionless.class, dimensionlessFactory, dimensionless, "px",    UnitRegistry.OTHER, (short) 0);
         UNITY   = UnitRegistry.init(one);  // Must be last in order to take precedence over all other units associated to UnitDimension.NONE.
 
         UnitRegistry.alias(UNITY,       Short.valueOf((short) 9203));
@@ -1198,8 +1202,10 @@ public final class Units extends Static
      * Invoked by {@code Units} static class initializer for registering SI base and derived units.
      * This method shall be invoked in a single thread by the {@code Units} class initializer only.
      */
-    private static <Q extends Quantity<Q>> SystemUnit<Q> add(Class<Q> quantity, UnitDimension dimension, String symbol, byte scope, short epsg) {
-        return UnitRegistry.init(new SystemUnit<>(quantity, dimension, symbol, scope, epsg));
+    private static <Q extends Quantity<Q>> SystemUnit<Q> add(Class<Q> quantity, ScalarFactory<Q> factory,
+            UnitDimension dimension, String symbol, byte scope, short epsg)
+    {
+        return UnitRegistry.init(new SystemUnit<>(quantity, dimension, symbol, scope, epsg, factory));
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -46,6 +46,8 @@
  * In relation to units of measurement, this package also defines:
  *
  * <ul>
+ *   <li>{@linkplain org.apache.sis.measure.Quantities}
+ *       as a {@code double} value value associated to a {@code Unit} instance.</li>
  *   <li>{@link org.apache.sis.measure.Angle} and its subclasses
  *      ({@link org.apache.sis.measure.Longitude},
  *       {@link org.apache.sis.measure.Latitude},
@@ -54,9 +56,10 @@
  *      ({@link org.apache.sis.measure.NumberRange},
  *       {@link org.apache.sis.measure.MeasurementRange}) or annotation
  *      ({@link org.apache.sis.measure.ValueRange})</li>
- *   <li>Formatters
+ *   <li>Parsers and formatters
  *      ({@link org.apache.sis.measure.AngleFormat},
- *       {@link org.apache.sis.measure.RangeFormat})</li>
+ *       {@link org.apache.sis.measure.RangeFormat},
+ *       {@link org.apache.sis.measure.UnitFormat})</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (MPO, IRD, Geomatys)

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/FrequencySortedSet.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/FrequencySortedSet.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/FrequencySortedSet.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/FrequencySortedSet.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -31,9 +31,9 @@ import org.apache.sis.util.ArgumentCheck
 
 /**
  * A set with elements ordered by the amount of time they were {@linkplain #add added}.
- * Less frequently added elements are first, and most frequently added ones are last.
- * If some elements were added the same amount of time, then the iterator will traverse
- * them in their insertion order.
+ * By default, less frequently added elements are first and most frequently added elements are last.
+ * If some elements were added the same amount of time, then the iterator will traverse them in their
+ * insertion order.
  *
  * <p>An optional boolean argument in the constructor allows the construction of set in reversed order
  * (most frequently added elements first, less frequently added last). This is similar but not identical
@@ -46,7 +46,7 @@ import org.apache.sis.util.ArgumentCheck
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.8
  *
- * @param <E> the type of elements in the set.
+ * @param <E>  the type of elements in the set.
  *
  * @since 0.8
  * @module
@@ -64,8 +64,19 @@ public class FrequencySortedSet<E> exten
     private final Map<E,Integer> count;
 
     /**
-     * {@code +1} if the element should be sorted in the usual order, or {@code -1}
+     * {@code 0} if the element should be sorted in the usual order, or {@code -1}
      * if the elements should be sorted in reverse order (most frequent element first).
+     * This value is XORed with the number of times <var>n</var> that an element is added: {@code n ^ order}.
+     * The intend is to store negative numbers in the {@link #count} map if this {@code FrequencySortedSet}
+     * has been created for reverse order.
+     *
+     * <div class="note"><b>Implementation note:</b>
+     * we could have used {@code +1} and {@code -1} for the usual and reverse order respectively, and store the
+     * multiplication result {@code n * order} in the {@link #count} map. We rather use XOR for two reasons:
+     * first, XOR is a simpler operation for the CPU than multiplication. Second, XOR guarantees us that all
+     * negative numbers can be made positive in {@link #frequencies()}, by applying again {@code n ^ order}.
+     * By contrast, the multiplication approach (or just the {@code -n} negation) would fail to convert
+     * {@link Integer#MIN_VALUE}.</div>
      */
     private final int order;
 
@@ -84,17 +95,19 @@ public class FrequencySortedSet<E> exten
      * Creates an initially empty set with less frequent elements first.
      */
     public FrequencySortedSet() {
-        this(false);
+        count = new LinkedHashMap<>();      // Default constructor in JDK implementation applies lazy array allocation.
+        order = 0;
     }
 
     /**
      * Creates an initially empty set with the default initial capacity.
      *
      * @param  reversed  {@code true} if the elements should be sorted in reverse order
-     *                   (most frequent element first, less frequent last).
+     *                   (most frequent element first, less frequent element last).
      */
     public FrequencySortedSet(final boolean reversed) {
-        this(16, reversed);
+        count = new LinkedHashMap<>();
+        order = reversed ? -1 : 0;
     }
 
     /**
@@ -102,11 +115,11 @@ public class FrequencySortedSet<E> exten
      *
      * @param initialCapacity  the initial capacity.
      * @param reversed         {@code true} if the elements should be sorted in reverse order
-     *                         (most frequent element first, less frequent last).
+     *                         (most frequent element first, less frequent element last).
      */
     public FrequencySortedSet(final int initialCapacity, final boolean reversed) {
         count = new LinkedHashMap<>(initialCapacity);
-        order = reversed ? -1 : +1;
+        order = reversed ? -1 : 0;
     }
 
     /**
@@ -126,11 +139,11 @@ public class FrequencySortedSet<E> exten
     }
 
     /**
-     * Adds the specified element to this set. Returns {@code true} if this set changed as a result
-     * of this operation. Changes in element order are not notified by the returned value.
+     * Repetitively adds the specified element to this set. Returns {@code true} if this set changed
+     * as a result of this operation. Changes in element order are not notified by the returned value.
      *
-     * @param  element     the element to add.
-     * @param  occurrence  the number of time to add the given elements. The default value is 1.
+     * @param  element     the element to add (may be {@code null}).
+     * @param  occurrence  the number of time to add the given element. The default value is 1.
      * @return {@code true} if this set changed as a result of this operation.
      * @throws IllegalArgumentException if {@code occurrence} is negative.
      */
@@ -138,12 +151,12 @@ public class FrequencySortedSet<E> exten
         if (occurrence != 0) {
             ArgumentChecks.ensurePositive("occurrence", occurrence);
             sorted = null;
-            occurrence *= order;
-            final Integer n = count.put(element, occurrence);
-            if (n == null) {
+            occurrence ^= order;
+            final Integer old = count.put(element, occurrence);
+            if (old == null) {
                 return true;
             }
-            count.put(element, n + occurrence);
+            count.put(element, old + occurrence - order);
         }
         return false;
     }
@@ -152,7 +165,9 @@ public class FrequencySortedSet<E> exten
      * Adds the specified element to this set. Returns {@code true} if this set changed as a result
      * of this operation. Changes in element order are not notified by the returned value.
      *
-     * @param  element  the element to add.
+     * <p>The default implementation delegates to <code>{@linkplain #add(Object, int) add}(element, 1)</code>.</p>
+     *
+     * @param  element  the element to add (may be {@code null}).
      * @return {@code true} if this set changed as a result of this operation.
      */
     @Override
@@ -204,7 +219,7 @@ public class FrequencySortedSet<E> exten
     @Override
     public Iterator<E> iterator() {
         ensureSorted();
-        return new Iter();
+        return new Iter(sorted, 0, sorted.length);
     }
 
     /**
@@ -218,6 +233,12 @@ public class FrequencySortedSet<E> exten
         private final E[] elements;
 
         /**
+         * Index of the first element ({@code lower}) and index after the last element ({@code upper})
+         * on which to iterate.
+         */
+        private final int lower, upper;
+
+        /**
          * Index of the next element to return.
          */
         private int index;
@@ -225,8 +246,11 @@ public class FrequencySortedSet<E> exten
         /**
          * Creates an new iterator.
          */
-        Iter() {
+        Iter(final E[] sorted, final int lower, final int upper) {
             elements = sorted;
+            this.index = lower;
+            this.lower = lower;
+            this.upper = upper;
         }
 
         /**
@@ -234,7 +258,7 @@ public class FrequencySortedSet<E> exten
          */
         @Override
         public boolean hasNext() {
-            return index < elements.length;
+            return index < upper;
         }
 
         /**
@@ -242,10 +266,10 @@ public class FrequencySortedSet<E> exten
          */
         @Override
         public E next() {
-            if (index >= elements.length) {
-                throw new NoSuchElementException();
+            if (index < upper) {
+                return elements[index++];
             }
-            return elements[index++];
+            throw new NoSuchElementException();
         }
 
         /**
@@ -253,10 +277,7 @@ public class FrequencySortedSet<E> exten
          */
         @Override
         public void remove() {
-            if (index == 0) {
-                throw new IllegalStateException();
-            }
-            if (!FrequencySortedSet.this.remove(elements[index - 1])) {
+            if (index == lower || !FrequencySortedSet.this.remove(elements[index - 1])) {
                 // Could also be ConcurrentModificationException - we do not differentiate.
                 throw new IllegalStateException();
             }
@@ -264,27 +285,213 @@ public class FrequencySortedSet<E> exten
     }
 
     /**
-     * Not yet implemented.
+     * A view over a subset of {@link FrequencySortedSet}.
+     */
+    private final class SubSet extends AbstractSet<E> implements SortedSet<E>, Serializable {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = 6843072153603161179L;
+
+        /**
+         * Reference to the {@link FrequencySortedSet#sorted} array, used for detecting changes.
+         */
+        private transient E[] elements;
+
+        /**
+         * Low endpoint (inclusive) of the subset. May be {@code null}.
+         */
+        private final E fromElement;
+
+        /**
+         * High endpoint (exclusive) of the subset. May be {@code null}.
+         */
+        private final E toElement;
+
+        /**
+         * Whether the set should take in account {@link #fromElement} or {@link #toElement}.
+         * We have to use those booleans (we can not use {@code null} sentinel value instead)
+         * because {@code null} is a legal value for {@code from/toElement}.
+         */
+        private final boolean hasFrom, hasTo;
+
+        /**
+         * Lower and upper index computed from {@link #fromElement} and {@link #toElement}.
+         */
+        private transient int lower, upper;
+
+        /**
+         * Creates a new subset from the lower element (inclusive) to the upper element (exclusive).
+         * Each endpoint can be null.
+         */
+        SubSet(final boolean hasFrom, final E fromElement, final boolean hasTo, final E toElement) {
+            this.fromElement = fromElement;
+            this.toElement   = toElement;
+            this.hasFrom     = hasFrom;
+            this.hasTo       = hasTo;
+        }
+
+        /**
+         * Returns the comparator, which is the same than {@link FrequencySortedSet#comparator()}.
+         */
+        @Override
+        public Comparator<E> comparator() {
+            return FrequencySortedSet.this;
+        }
+
+        /**
+         * Ensures that {@link #lower} and {@link #upper} indices are valid.
+         */
+        private void ensureValidRange() {
+            if (elements == null || elements != sorted) {
+                ensureSorted();
+                elements = sorted;
+                if (hasFrom) {
+                    lower = Arrays.binarySearch(elements, fromElement, FrequencySortedSet.this);
+                    if (lower < 0) lower = ~lower;
+                }
+                if (hasTo) {
+                    upper = Arrays.binarySearch(elements, toElement, FrequencySortedSet.this);
+                    if (upper < 0)     upper = ~upper;
+                    if (upper < lower) upper =  lower;
+                } else {
+                    upper = elements.length;
+                }
+            }
+        }
+
+        /**
+         * Returns an iterator over the elements in this subset.
+         */
+        @Override
+        public Iterator<E> iterator() {
+            ensureValidRange();
+            return new Iter(elements, lower, upper);
+        }
+
+        /**
+         * Returns the number of elements in this subset.
+         */
+        @Override
+        public int size() {
+            ensureValidRange();
+            return upper - lower;
+        }
+
+        /**
+         * Returns the first element in this subset.
+         *
+         * @see FrequencySortedSet#first()
+         */
+        @Override
+        public E first() {
+            ensureValidRange();
+            if (lower != upper) {
+                return elements[lower];
+            } else {
+                throw new NoSuchElementException();
+            }
+        }
+
+        /**
+         * Returns the last element in this subset.
+         *
+         * @see FrequencySortedSet#last()
+         */
+        @Override
+        public E last() {
+            ensureValidRange();
+            if (lower != upper) {
+                return elements[upper - 1];
+            } else {
+                throw new NoSuchElementException();
+            }
+        }
+
+        /**
+         * Returns a view of the portion of this subset whose elements occur
+         * with a frequency strictly less than {@code toElement} frequency.
+         *
+         * @see FrequencySortedSet#headSet(Object)
+         */
+        @Override
+        public SortedSet<E> headSet(final E to) {
+            return subSet(fromElement, to, hasFrom ? 0 : 2);
+        }
+
+        /**
+         * Returns a view of the portion of this subset whose elements occur with
+         * a frequency equal or greater than {@code fromElement} frequency.
+         *
+         * @see FrequencySortedSet#tailSet(Object)
+         */
+        @Override
+        public SortedSet<E> tailSet(final E from) {
+            return subSet(from, toElement, hasTo ? 0 : 1);
+        }
+
+        /**
+         * Returns a view of the portion of this subset whose elements occur with a frequency in the
+         * range of {@code fromElement} frequency inclusive to {@code toElement} frequency exclusive.
+         *
+         * @see FrequencySortedSet#subSet(Object, Object)
+         */
+        @Override
+        public SortedSet<E> subSet(final E from, final E to) {
+            return subSet(from, to, 0);
+        }
+
+        /**
+         * Implementation of {@link #headSet(Object)}, {@link #tailSet(Object)} and {@link #subSet(Object, Object)}.
+         * The {@code bounds} argument tell which {@link FrequencySortedSet} method to delegate to.
+         */
+        private SortedSet<E> subSet(E from, E to, final int bounded) {
+            if (hasFrom && compare(from, fromElement) < 0) from = fromElement;
+            if (hasTo   && compare(to,     toElement) > 0) to   = toElement;
+            switch (bounded) {
+                default: throw new AssertionError(bounded);
+                case 0:  return FrequencySortedSet.this.subSet(from, to);
+                case 1:  return FrequencySortedSet.this.tailSet(from);
+                case 2:  return FrequencySortedSet.this.headSet(to);
+            }
+        }
+    }
+
+    /**
+     * Returns a view of the portion of this set whose elements occur with a frequency strictly less than
+     * {@code toElement} frequency.
+     *
+     * @param  toElement  high endpoint (exclusive) of the returned set. May be {@code null}.
+     * @return a view of the portion of this set delimited by the given endpoint.
      */
     @Override
-    public SortedSet<E> headSet(E toElement) {
-        throw new UnsupportedOperationException("Not supported yet.");
+    public SortedSet<E> headSet(final E toElement) {
+        return new SubSet(false, null, true, toElement);
     }
 
     /**
-     * Not yet implemented.
+     * Returns a view of the portion of this set whose elements occur with a frequency equal or greater than
+     * {@code fromElement} frequency.
+     *
+     * @param  fromElement  low endpoint (inclusive) of the returned set. May be {@code null}.
+     * @return a view of the portion of this set delimited by the given endpoint.
      */
     @Override
-    public SortedSet<E> tailSet(E fromElement) {
-        throw new UnsupportedOperationException("Not supported yet.");
+    public SortedSet<E> tailSet(final E fromElement) {
+        return new SubSet(true, fromElement, false, null);
     }
 
     /**
-     * Not yet implemented.
+     * Returns a view of the portion of this set whose elements occur with a frequency in the range of
+     * {@code fromElement} frequency inclusive to {@code toElement} frequency exclusive.
+     *
+     * @param  fromElement  low endpoint (inclusive) of the returned set. May be {@code null}.
+     * @param  toElement    high endpoint (exclusive) of the returned set. May be {@code null}.
+     * @return a view of the portion of this set delimited by the given endpoints.
      */
     @Override
-    public SortedSet<E> subSet(E fromElement, E toElement) {
-        throw new UnsupportedOperationException("Not supported yet.");
+    public SortedSet<E> subSet(final E fromElement, final E toElement) {
+        return new SubSet(true, fromElement, true, toElement);
     }
 
     /**
@@ -337,28 +544,27 @@ public class FrequencySortedSet<E> exten
     }
 
     /**
-     * Sorts the elements in frequency order, if not already done. The sorted array will contains
+     * Sorts the elements in frequency order, if not already done. The sorted array will contain
      * all elements without duplicated values, with the less frequent element first and the most
-     * frequent last (or the converse if this set has been created for reverse order).
+     * frequent element last (or the converse if this set has been created for reverse order).
      * If some elements appear at the same frequency, then their ordering will be preserved.
      */
     @SuppressWarnings("unchecked")
     private void ensureSorted() {
-        if (sorted != null) {
-            return;
-        }
-        @SuppressWarnings("rawtypes")                                   // Generic array creation.
-        final Map.Entry<E,Integer>[] entries = count.entrySet().toArray(new Map.Entry[count.size()]);
-        Arrays.sort(entries, COMPARATOR);
-        final int length = entries.length;
-        sorted = (E[]) new Object[length];
-        if (frequencies == null || frequencies.length != length) {
-            frequencies = new int[length];
-        }
-        for (int i=0; i<length; i++) {
-            final Map.Entry<E,Integer> entry = entries[i];
-            sorted[i] = entry.getKey();
-            frequencies[i] = Math.abs(entry.getValue());
+        if (sorted == null) {
+            @SuppressWarnings("rawtypes")                                   // Generic array creation.
+            final Map.Entry<E,Integer>[] entries = count.entrySet().toArray(new Map.Entry[count.size()]);
+            Arrays.sort(entries, COMPARATOR);
+            final int length = entries.length;
+            sorted = (E[]) new Object[length];
+            if (frequencies == null || frequencies.length != length) {
+                frequencies = new int[length];
+            }
+            for (int i=0; i<length; i++) {
+                final Map.Entry<E,Integer> entry = entries[i];
+                sorted[i] = entry.getKey();
+                frequencies[i] = entry.getValue() ^ order;
+            }
         }
     }
 
@@ -412,16 +618,16 @@ public class FrequencySortedSet<E> exten
      * Returns the frequency of the specified element in this set.
      *
      * @param  element  the element whose frequency is to be obtained.
-     * @return the frequency of the given element, or {@code 0} if it doesn't occur in this set.
+     * @return the frequency of the given element, or {@code 0} if it does not occur in this set.
      */
     public int frequency(final E element) {
-        return Math.abs(signedFrequency(element));
+        return signedFrequency(element) ^ order;
     }
 
     /**
-     * Returns the frequency of each element in this set, in iteration order.
+     * Returns the frequency of all elements in this set, in iteration order.
      *
-     * @return the frequency of each element in this set.
+     * @return the frequency of all elements in this set.
      */
     public int[] frequencies() {
         ensureSorted();

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -303,8 +303,8 @@ public final strictfp class SystemUnitTe
         /*
          * Test with units outside the pre-defined constants in the Units class.
          */
-        final Unit<Length> anonymous = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), null,  UnitRegistry.OTHER, (short) 0);
-        final Unit<Length> otherName = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), "Foo", UnitRegistry.OTHER, (short) 0);
+        final Unit<Length> anonymous = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), null,  UnitRegistry.OTHER, (short) 0, null);
+        final Unit<Length> otherName = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), "Foo", UnitRegistry.OTHER, (short) 0, null);
         assertSame(Units.METRE, anonymous.asType(Length.class));
         assertSame(otherName,   otherName.asType(Length.class));
         /*

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -110,6 +110,8 @@ import org.junit.BeforeClass;
     org.apache.sis.measure.ConventionalUnitTest.class,
     org.apache.sis.measure.UnitFormatTest.class,
     org.apache.sis.measure.UnitsTest.class,
+    org.apache.sis.measure.ScalarTest.class,
+    org.apache.sis.measure.QuantitiesTest.class,
     org.apache.sis.measure.UnitServicesTest.class,
     org.apache.sis.measure.RangeTest.class,
     org.apache.sis.measure.DateRangeTest.class,

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/collection/FrequencySortedSetTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/collection/FrequencySortedSetTest.java?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/collection/FrequencySortedSetTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/collection/FrequencySortedSetTest.java [UTF-8] Mon Apr 10 10:44:41 2017
@@ -16,7 +16,9 @@
  */
 package org.apache.sis.util.collection;
 
+import java.util.Arrays;
 import java.util.Collections;
+import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -51,6 +53,7 @@ public final strictfp class FrequencySor
      * Simple test with 2 elements.
      */
     @Test
+    @DependsOnMethod("testSimple")
     public void testTwoElements() {
         final FrequencySortedSet<Integer> set = new FrequencySortedSet<>(true);
         for (int i=0; i<10; i++) {
@@ -64,4 +67,30 @@ public final strictfp class FrequencySor
         assertEquals(Integer.valueOf(11), set.last());
         assertArrayEquals(new int[] {10, 4}, set.frequencies());
     }
+
+    /**
+     * Tests creation of various subsets.
+     */
+    @Test
+    @DependsOnMethod("testTwoElements")
+    public void testSubSet() {
+        final FrequencySortedSet<Integer> set = new FrequencySortedSet<>();
+        set.addAll(Arrays.asList(2, 5, 3, 2, 4, 2, 3, 6, 2));
+        assertArrayEquals(new Integer[] {5, 4, 6, 3, 2}, set.toArray());
+        assertArrayEquals(new int[] {1, 1, 1, 2, 4}, set.frequencies());
+
+        assertArrayEquals("Expected all elements occurring less often than 2.",
+                          new Integer[] {5, 4, 6, 3}, set.headSet(2).toArray());
+
+        assertArrayEquals("Expected all elements occurring less often than 3.",
+                          new Integer[] {5, 4, 6}, set.headSet(3).toArray());
+
+        assertArrayEquals("Expected all elements occurring at least as often than 3.",
+                          new Integer[] {3, 2}, set.tailSet(3).toArray());
+
+        assertArrayEquals("Expected all elements occurring at least as often than 3 but less than 2.",
+                          new Integer[] {3}, set.subSet(3, 2).toArray());
+
+        assertTrue(set.subSet(2, 3).isEmpty());
+    }
 }

Modified: sis/branches/JDK7/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/pom.xml?rev=1790799&r1=1790798&r2=1790799&view=diff
==============================================================================
--- sis/branches/JDK7/pom.xml (original)
+++ sis/branches/JDK7/pom.xml Mon Apr 10 10:44:41 2017
@@ -594,6 +594,7 @@ Apache SIS is a free software, Java lang
       <!-- Compile -->
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.6.1</version>
         <configuration>
           <source>${maven.compile.source}</source>
           <target>${maven.compile.target}</target>
@@ -609,6 +610,7 @@ Apache SIS is a free software, Java lang
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.19.1</version>
         <configuration>
           <includes>
             <include>**/*TestSuite.java</include>



Mime
View raw message