Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GIGS3005.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GIGS3005.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GIGS3005.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GIGS3005.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -19,8 +19,10 @@ package org.apache.sis.referencing.facto
 import org.opengis.referencing.operation.CoordinateOperationFactory;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.test.DependsOn;
+import org.junit.FixMethodOrder;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.junit.runners.MethodSorters;
 
 
 /**
@@ -32,10 +34,11 @@ import org.junit.runners.JUnit4;
  * @version 0.6
  * @module
  */
-@RunWith(JUnit4.class)
 @DependsOn({
     org.apache.sis.referencing.operation.DefaultConversionTest.class
 })
+@RunWith(JUnit4.class)
+@FixMethodOrder(MethodSorters.JVM)      // Intentionally want some randomness
 public final strictfp class GIGS3005 extends 
org.opengis.test.referencing.gigs.GIGS3005 {
     /**
      * Creates a new test suite using the singleton factory instance.

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GeodeticObjectFactoryTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GeodeticObjectFactoryTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GeodeticObjectFactoryTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/GeodeticObjectFactoryTest.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -16,21 +16,46 @@
  */
 package org.apache.sis.referencing.factory;
 
+import java.util.Map;
+import java.util.Collections;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+import javax.measure.unit.NonSI;
+import javax.measure.quantity.Angle;
+import javax.measure.quantity.Length;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.cs.CSFactory;
+import org.opengis.referencing.cs.CartesianCS;
+import org.opengis.referencing.cs.EllipsoidalCS;
+import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.crs.CRSFactory;
 import org.opengis.referencing.crs.GeodeticCRS;
+import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.datum.DatumFactory;
+import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
-import org.opengis.test.referencing.ObjectFactoryTest;
-import org.opengis.util.FactoryException;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.Conversion;
+import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.referencing.operation.DefaultConversion;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.io.wkt.Convention;
+
+// Test dependencies
+import org.opengis.test.referencing.ObjectFactoryTest;
 import org.apache.sis.test.DependsOn;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.apache.sis.test.MetadataAssert.*;
 
 
 /**
@@ -39,7 +64,7 @@ import static org.junit.Assert.*;
  *
  * @author  Cédric Briançon (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @RunWith(JUnit4.class)
@@ -84,4 +109,116 @@ public final strictfp class GeodeticObje
         assertEquals("name",  "WGS 84", crs.getName().getCode());
         assertEquals("datum", "World Geodetic System 1984", 
crs.getDatum().getName().getCode());
     }
+
+    /**
+     * Convenience method creating a map with only the "{@code name"} property.
+     * This is the only mandatory property for object creation.
+     */
+    private static Map<String,?> name(final String name) {
+        return Collections.singletonMap(IdentifiedObject.NAME_KEY, name);
+    }
+
+    /**
+     * Tests step-by-step the creation of a new projected coordinate reference 
systems.
+     * This test creates every objects itself and compares with expected WKT 1 
after each step.
+     *
+     * <p>Note that practical applications may use existing constants declared 
in the
+     * {@link CommonCRS} class instead than creating everything like this test 
does.</p>
+     *
+     * @throws FactoryException if the creation of a geodetic component failed.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testStepByStepCreation() throws FactoryException {
+        /*
+         * List of all objects to be created in this test.
+         */
+        final Unit<Length>         linearUnit;
+        final Unit<Angle>          angularUnit;
+        final Ellipsoid            ellipsoid;
+        final PrimeMeridian        meridian;
+        final GeodeticDatum        datum;
+        final CoordinateSystemAxis longitude, latitude, easting, northing;
+        final EllipsoidalCS        geographicCS;
+        final GeographicCRS        geographicCRS;
+        final OperationMethod      method;
+        final ParameterValueGroup  parameters;
+        final Conversion           projection;
+        final CartesianCS          projectedCS;
+        final ProjectedCRS         projectedCRS;
+        /*
+         * Prime meridian
+         */
+        angularUnit = NonSI.DEGREE_ANGLE;
+        meridian = datumFactory.createPrimeMeridian(name("Greenwich"), 0, 
angularUnit);
+        assertWktEquals(Convention.WKT1,
+                "PRIMEM[“Greenwich”, 0.0]", meridian);
+        /*
+         * Ellipsoid
+         */
+        linearUnit = SI.METRE;
+        ellipsoid = datumFactory.createEllipsoid(name("Airy1830"), 
6377563.396, 6356256.910, linearUnit);
+        assertWktEquals(Convention.WKT1,
+                "SPHEROID[“Airy1830”, 6377563.396, 299.3249753150345]", 
ellipsoid);
+        /*
+         * Geodetic datum
+         */
+        datum = datumFactory.createGeodeticDatum(name("Airy1830"), ellipsoid, 
meridian);
+        assertWktEquals(Convention.WKT1,
+                "DATUM[“Airy1830”,\n" +
+                "  SPHEROID[“Airy1830”, 6377563.396, 299.3249753150345]]", 
datum);
+        /*
+         * Base coordinate reference system
+         */
+        longitude     =  
csFactory.createCoordinateSystemAxis(name("Longitude"), "long", 
AxisDirection.EAST,  angularUnit);
+        latitude      =  
csFactory.createCoordinateSystemAxis(name("Latitude"),  "lat",  
AxisDirection.NORTH, angularUnit);
+        geographicCS  =  csFactory.createEllipsoidalCS(name("Ellipsoidal"), 
longitude, latitude);
+        geographicCRS = crsFactory.createGeographicCRS(name("Airy1830"), 
datum, geographicCS);
+        assertWktEquals(Convention.WKT1,
+                "GEOGCS[“Airy1830”,\n" +
+                "  DATUM[“Airy1830”,\n" +
+                "    SPHEROID[“Airy1830”, 6377563.396, 299.3249753150345]],\n" 
+
+                "    PRIMEM[“Greenwich”, 0.0],\n" +
+                "  UNIT[“degree”, 0.017453292519943295],\n" +
+                "  AXIS[“Longitude”, EAST],\n" +
+                "  AXIS[“Latitude”, NORTH]]", geographicCRS);
+        /*
+         * Defining conversion
+         */
+        method = copFactory.getOperationMethod("Transverse_Mercator");
+        parameters = method.getParameters().createValue();
+        parameters.parameter("semi_major")        
.setValue(ellipsoid.getSemiMajorAxis());
+        parameters.parameter("semi_minor")        
.setValue(ellipsoid.getSemiMinorAxis());
+        parameters.parameter("central_meridian")  .setValue(     49);
+        parameters.parameter("latitude_of_origin").setValue(     -2);
+        parameters.parameter("false_easting")     .setValue( 400000);
+        parameters.parameter("false_northing")    .setValue(-100000);
+        projection = new DefaultConversion(name("GBN grid"), method, null, 
parameters);
+        /*
+         * Projected coordinate reference system
+         */
+        easting      =  csFactory.createCoordinateSystemAxis(name("Easting"),  
"x", AxisDirection.EAST,  linearUnit);
+        northing     =  csFactory.createCoordinateSystemAxis(name("Northing"), 
"y", AxisDirection.NORTH, linearUnit);
+        projectedCS  =  csFactory.createCartesianCS(name("Cartesian"), 
easting, northing);
+        projectedCRS = 
crsFactory.createProjectedCRS(name("Great_Britian_National_Grid"), 
geographicCRS, projection, projectedCS);
+        assertWktEquals(Convention.WKT1,
+                "PROJCS[“Great_Britian_National_Grid”,\n" +
+                "  GEOGCS[“Airy1830”,\n" +
+                "    DATUM[“Airy1830”,\n" +
+                "      SPHEROID[“Airy1830”, 6377563.396, 
299.3249753150345]],\n" +
+                "      PRIMEM[“Greenwich”, 0.0],\n" +
+                "    UNIT[“degree”, 0.017453292519943295],\n" +
+                "    AXIS[“Longitude”, EAST],\n" +
+                "    AXIS[“Latitude”, NORTH]],\n" +
+                "  PROJECTION[“Transverse_Mercator”, AUTHORITY[“EPSG”, 
“9807”]],\n" +
+                "  PARAMETER[“latitude_of_origin”, -2.0],\n" +
+                "  PARAMETER[“central_meridian”, 49.0],\n" +
+                "  PARAMETER[“scale_factor”, 1.0],\n" +
+                "  PARAMETER[“false_easting”, 400000.0],\n" +
+                "  PARAMETER[“false_northing”, -100000.0],\n" +
+                "  UNIT[“metre”, 1],\n" +
+                "  AXIS[“Easting”, EAST],\n" +
+                "  AXIS[“Northing”, NORTH]]", projectedCRS);
+    }
 }

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -100,7 +100,7 @@ public abstract strictfp class MatrixTes
      *
      * @see NonSquareMatrixTest#printStatistics()
      */
-    static final Statistics statistics = verbose ? new Statistics("|SIS - 
JAMA|") : null;
+    static final Statistics statistics = VERBOSE ? new Statistics("|SIS - 
JAMA|") : null;
 
     /**
      * Random number generator, created by {@link #initialize(long)} as the 
first operation of

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -106,7 +106,7 @@ public final strictfp class LambertConic
         assertWktEqualsRegex("(?m)\\Q" +
                 "PARAM_MT[“Lambert conic conformal”,\n" +
                 "  PARAMETER[“eccentricity”, 0.0818191908426215],\n" +
-                "  PARAMETER[“n”, 0.64278760968653\\E\\d*\\]\\]");  // 
0.6427876096865393 in the original test.
+                "  PARAMETER[“n”, 0.64278760968653\\E\\d*\\Q]]\\E");  // 
0.6427876096865393 in the original test.
     }
 
     /**

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactoryTest.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -16,7 +16,10 @@
  */
 package org.apache.sis.referencing.operation.transform;
 
+import java.util.Map;
 import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.referencing.operation.Conversion;
@@ -25,11 +28,21 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.parameter.ParameterValueGroup;
+import org.apache.sis.parameter.Parameterized;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.operation.DefaultConversion;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
+import org.apache.sis.referencing.crs.DefaultProjectedCRS;
+import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.internal.referencing.provider.Affine;
 import org.apache.sis.internal.referencing.provider.Mercator1SP;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.util.CharSequences;
+
+// Test dependencies
+import org.apache.sis.referencing.cs.HardCodedCS;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -45,7 +58,7 @@ import static org.opengis.test.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @DependsOn({
@@ -162,4 +175,68 @@ public final strictfp class DefaultMathT
                 1, 7,
                 0, 1), MathTransforms.getMatrix(tr), STRICT);
     }
+
+    /**
+     * Tests the creation of all registered map projections.
+     * Only the semi-axis lengths are specified. For the rest, we rely on 
default values.
+     *
+     * @throws FactoryException if the construction of a map projection failed.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testAllMapProjections() throws FactoryException {
+        /*
+         * Gets all map projections and creates a projection using the WGS84 
ellipsoid
+         * and default parameter values.
+         */
+        final Map<String,?> dummyName = 
Collections.singletonMap(DefaultProjectedCRS.NAME_KEY, "Test");
+        final MathTransformFactory mtFactory = 
DefaultFactories.forBuildin(MathTransformFactory.class);
+        final Collection<OperationMethod> methods = 
mtFactory.getAvailableMethods(Projection.class);
+        for (final OperationMethod method : methods) {
+            final String classification = method.getName().getCode();
+            ParameterValueGroup param = 
mtFactory.getDefaultParameters(classification);
+            param.parameter("semi_major").setValue(6377563.396);
+            param.parameter("semi_minor").setValue(6356256.909237285);
+            final MathTransform mt;
+            try {
+                mt = mtFactory.createParameterizedTransform(param);
+            } catch (InvalidGeodeticParameterException e) {
+                // Some map projections have mandatory parameters which we 
ignore for now
+                // except for a few well-known projection that we know should 
not fail.
+                if (classification.contains("Mercator")) {
+                    throw e;
+                }
+                out.print(classification);
+                out.print(CharSequences.spaces(42 - classification.length()));
+                out.print(": ");
+                out.println(e.getLocalizedMessage());
+                continue;
+            }
+            /*
+             * Verifies that the map projection properties are the ones that 
we specified.
+             * Note that the Equirectangular projection has been optimized as 
an affine transform, which we skip.
+             */
+            if (mt instanceof LinearTransform) {
+                continue;
+            }
+            assertInstanceOf(classification, Parameterized.class, mt);
+            param = ((Parameterized) mt).getParameterValues();
+            assertEquals(classification, 
param.getDescriptor().getName().getCode());
+            assertEquals(classification, 6377563.396,       
param.parameter("semi_major").doubleValue(), 1E-4);
+            assertEquals(classification, 6356256.909237285, 
param.parameter("semi_minor").doubleValue(), 1E-4);
+            /*
+             * Creates a ProjectedCRS from the map projection. This part is 
more an integration test than
+             * a DefaultMathTransformFactory test. Again, the intend is to 
verify that the properties are
+             * the one that we specified.
+             */
+            final DefaultProjectedCRS crs = new DefaultProjectedCRS(dummyName,
+                    CommonCRS.WGS84.normalizedGeographic(),
+                    new DefaultConversion(dummyName, method, mt, null),
+                    HardCodedCS.PROJECTED);
+            final Conversion projection = crs.getConversionFromBase();
+            assertSame(classification, mt, projection.getMathTransform());
+            assertEquals(classification, 
projection.getMethod().getName().getCode());
+        }
+    }
 }

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -60,11 +60,7 @@ public final strictfp class EllipsoidToC
      */
     private void createGeodeticConversion(final Ellipsoid ellipsoid, boolean 
is3D) throws FactoryException {
         transform = EllipsoidToCentricTransform.createGeodeticConversion(
-                DefaultFactories.forBuildin(MathTransformFactory.class),
-                ellipsoid.getSemiMajorAxis(),
-                ellipsoid.getSemiMinorAxis(),
-                ellipsoid.getAxisUnit(), is3D,
-                EllipsoidToCentricTransform.TargetType.CARTESIAN);
+                DefaultFactories.forBuildin(MathTransformFactory.class), 
ellipsoid, is3D);
     }
 
     /**

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -396,6 +396,19 @@ public abstract strictfp class MathTrans
     }
 
     /**
+     * Asserts that the current {@linkplain #transform transform} produces an 
internal WKT
+     * matching the given regular expression.
+     *
+     * @param expected A regular expression for the expected internal WKT.
+     *
+     * @since 0.7
+     */
+    protected final void assertInternalWktEqualsRegex(final String expected) {
+        assertNotNull("The 'transform' field shall be assigned a value.", 
transform);
+        ReferencingAssert.assertWktEqualsRegex(Convention.INTERNAL, expected, 
transform);
+    }
+
+    /**
      * Prints the current {@linkplain #transform transform} as normal and 
internal WKT.
      * This method is for debugging purpose only.
      *

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MolodenskyTransformTest.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -16,26 +16,36 @@
  */
 package org.apache.sis.referencing.operation.transform;
 
+import java.util.Arrays;
+import java.io.IOException;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.parameter.ParameterValueGroup;
+import 
org.apache.sis.internal.referencing.provider.FranceGeocentricInterpolation;
 import org.apache.sis.internal.referencing.provider.AbridgedMolodensky;
 import org.apache.sis.internal.referencing.provider.Molodensky;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.measure.Longitude;
+import org.apache.sis.math.StatisticsFormat;
+import org.apache.sis.math.Statistics;
 
-import static java.lang.StrictMath.toRadians;
+import static java.lang.StrictMath.*;
+import static 
org.apache.sis.internal.metadata.ReferencingServices.NAUTICAL_MILE;
 
 // Test dependencies
+import 
org.apache.sis.internal.referencing.provider.FranceGeocentricInterpolationTest;
 import org.apache.sis.internal.referencing.provider.GeocentricTranslationTest;
+import org.apache.sis.referencing.datum.HardCodedDatum;
 import org.apache.sis.test.mock.MathTransformFactoryMock;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestUtilities;
+import org.apache.sis.test.TestCase;
+import org.opengis.test.CalculationType;
 import org.opengis.test.ToleranceModifier;
 import org.opengis.test.ToleranceModifiers;
 import org.opengis.test.referencing.ParameterizedTransformTest;
@@ -45,7 +55,10 @@ import static org.apache.sis.test.Assert
 
 
 /**
- * Tests {@link MolodenskyTransform}.
+ * Tests {@link MolodenskyTransform}. The {@link 
#compareWithGeocentricTranslation()}
+ * method uses {@link EllipsoidToCentricTransform} as a reference 
implementation.
+ * The errors compared to geocentric translations should not be greater than
+ * approximatively 1 centimetre.
  *
  * @author  Tara Athan
  * @author  Martin Desruisseaux (Geomatys)
@@ -56,10 +69,82 @@ import static org.apache.sis.test.Assert
  */
 @DependsOn({
     CoordinateDomainTest.class,
-    ContextualParametersTest.class
+    ContextualParametersTest.class,
+    EllipsoidToCentricTransformTest.class   // Used as a reference 
implementation
 })
 public final strictfp class MolodenskyTransformTest extends 
MathTransformTestCase {
     /**
+     * Creates a new test case.
+     */
+    public MolodenskyTransformTest() {
+        final double delta = toRadians(100.0 / 60) / 1852;      // 
Approximatively 100 metres
+        derivativeDeltas   = new double[] {delta, delta, 100};  // (Δλ, Δφ, Δh)
+        λDimension         = new int[] {0};                     // Dimension 
for which to ignore ±360° differences.
+        zDimension         = new int[] {2};                     // Dimension 
of h where to apply zTolerance
+        zTolerance         = Formulas.LINEAR_TOLERANCE;         // Tolerance 
for ellipsoidal heights (h)
+        tolerance          = Formulas.ANGULAR_TOLERANCE;        // Tolerance 
for longitude and latitude in degrees
+    }
+
+    /**
+     * Compares the Molodensky (non-abridged) transform with a geocentric 
translation.
+     * Molodensky is an approximation of geocentric translation, so we test 
here how good this approximation is.
+     * If {@link TestCase#verbose} is {@code true}, then this method will 
print error statistics.
+     *
+     * @throws FactoryException if an error occurred while creating a 
transform step.
+     * @throws TransformException if a transformation failed.
+     * @throws IOException should never happen.
+     *
+     * @see #compareWithGeocentricTranslation()
+     */
+    @SuppressWarnings("fallthrough")
+    private void compareWithGeocentricTranslation(
+            final Ellipsoid source, final Ellipsoid target,
+            final double tX,   final double tY,   final double tZ,
+            final double xmin, final double ymin, final double zmin,
+            final double xmax, final double ymax, final double zmax)
+            throws FactoryException, TransformException, IOException
+    {
+        final MathTransform reference;
+        final MathTransformFactory factory = 
DefaultFactories.forBuildin(MathTransformFactory.class);
+        transform = MolodenskyTransform.createGeodeticTransformation(factory, 
source, true, target, true, tX, tY, tZ, false);
+        reference = 
GeocentricTranslationTest.createDatumShiftForGeographic3D(factory, source, 
target, tX, tY, tZ);
+        final float[] srcPts = verifyInDomain(
+                new double[] {xmin, ymin, zmin},
+                new double[] {xmax, ymax, zmax},
+                new int[]    {  10,   10,   10},
+                
TestUtilities.createRandomNumberGenerator(103627524044558476L));
+        /*
+         * Transform the same input coordinates using Molodensky transform 
(actual) and using the reference
+         * implementation (expected). If we were asked to print statistics, 
compute them before to test the
+         * values since the statistics may be a useful information in case of 
problem.
+         */
+        final double[] actual   = new double[srcPts.length];
+        final double[] expected = new double[srcPts.length];
+        transform.transform(srcPts, 0, actual,   0, srcPts.length / 3);
+        reference.transform(srcPts, 0, expected, 0, srcPts.length / 3);
+        if (TestCase.VERBOSE) {
+            final Statistics[] stats = {
+                new Statistics("|Δλ| (~cm)"),
+                new Statistics("|Δφ| (~cm)"),
+                new Statistics("|Δh| (cm)")
+            };
+            for (int i=0; i<srcPts.length; i++) {
+                double Δ = actual[i] - expected[i];
+                final int j = i % stats.length;
+                switch (j) {
+                    case 0: Δ *= cos(toRadians(expected[i+1]));     // Fall 
through
+                    case 1: Δ *= 60 * NAUTICAL_MILE; break;         // 
Approximative conversion to metres
+                }
+                Δ *= 100;   // Conversion to centimetres.
+                stats[j].accept(abs(Δ));
+            }
+            StatisticsFormat.getInstance().format(stats, TestCase.out);
+        }
+        assertCoordinatesEqual("Comparison of Molodensky and geocentric 
translation", 3,
+                expected, 0, actual, 0, expected.length / 3, 
CalculationType.DIRECT_TRANSFORM);
+    }
+
+    /**
      * Creates a Molodensky transform for a datum shift from WGS84 to ED50.
      * Tolerance thresholds are also initialized.
      *
@@ -70,13 +155,14 @@ public final strictfp class MolodenskyTr
         final Ellipsoid target = CommonCRS.ED50.ellipsoid();
         transform = MolodenskyTransform.createGeodeticTransformation(
                 DefaultFactories.forBuildin(MathTransformFactory.class),
-                source, true, target, true, 84.87, 96.49, 116.95, abridged);
+                source, true, target, true,
+                GeocentricTranslationTest.TX,
+                GeocentricTranslationTest.TY,
+                GeocentricTranslationTest.TZ,
+                abridged);
 
-        final double delta = toRadians(100.0 / 60) / 1852;          // 
Approximatively 100 metres
-        derivativeDeltas = new double[] {delta, delta, 100};        // (Δλ, 
Δφ, Δh)
         tolerance  = GeocentricTranslationTest.precision(1);        // Half 
the precision of target sample point
         zTolerance = GeocentricTranslationTest.precision(3);        // 
Required precision for h
-        zDimension = new int[] {2};                                 // 
Dimension of h where to apply zTolerance
         assertFalse(transform.isIdentity());
         validate();
     }
@@ -169,9 +255,84 @@ public final strictfp class MolodenskyTr
     }
 
     /**
+     * Tests the point used in {@link FranceGeocentricInterpolationTest}. We 
use this test for measuring the
+     * errors induced by the use of the Molodensky approximation instead than 
a real geocentric translation.
+     * The error is approximatively 1 centimetre, which is about 6 times more 
than the accuracy of the point
+     * given in {@code FranceGeocentricInterpolationTest}.
+     *
+     * @throws FactoryException if an error occurred while creating the 
transform.
+     * @throws TransformException if transformation of a point failed.
+     *
+     * @see GeocentricTranslationTest#testFranceGeocentricInterpolationPoint()
+     */
+    @Test
+    @DependsOnMethod("testMolodensky")
+    public void testFranceGeocentricInterpolationPoint() throws 
FactoryException, TransformException {
+        transform = MolodenskyTransform.createGeodeticTransformation(
+                DefaultFactories.forBuildin(MathTransformFactory.class),
+                HardCodedDatum.NTF.getEllipsoid(), true,        // Clarke 1880 
(IGN)
+                CommonCRS.ETRS89.ellipsoid(), true,             // GRS 1980 
ellipsoid
+               -FranceGeocentricInterpolation.TX,
+               -FranceGeocentricInterpolation.TY,
+               -FranceGeocentricInterpolation.TZ,
+                false);
+        /*
+         * Code below is a copy-and-paste of 
GeocentricTranslationTest.testFranceGeocentricInterpolationPoint(),
+         * but with the tolerance threshold increased. We do not let the error 
goes beyond 1 cm however.
+         */
+        tolerance = min(Formulas.ANGULAR_TOLERANCE, 
FranceGeocentricInterpolationTest.ANGULAR_TOLERANCE * 6);
+        final double[] source   = 
Arrays.copyOf(FranceGeocentricInterpolationTest.samplePoint(1), 3);
+        final double[] expected = 
Arrays.copyOf(FranceGeocentricInterpolationTest.samplePoint(2), 3);
+        expected[2] = 43.15;  // Anti-regression (this value is not provided 
in NTG_88 guidance note).
+        verifyTransform(source, expected);
+        validate();
+    }
+
+    /**
+     * Compares the Molodensky (non-abridged) transforms with geocentric 
translations.
+     * Molodensky is an approximation of geocentric translation, so we test 
here how good this
+     * approximation is. This test performs the comparison for the following 
transformations:
+     *
+     * <ul>
+     *   <li>Transformation from NTF to RGF93. Those CRS are the source and 
target of <cite>"France geocentric
+     *       interpolation"</cite> (ESPG:9655). This test allows us to verify 
the accuracy documented in
+     *       {@link InterpolatedGeocentricTransform}.</li>
+     *   <li>(More areas may be added later).</li>
+     * </ul>
+     *
+     * If {@link TestCase#verbose} is {@code true}, then this method will 
print error statistics.
+     *
+     * @throws FactoryException if an error occurred while creating a 
transform step.
+     * @throws TransformException if a transformation failed.
+     * @throws IOException should never happen.
+     *
+     * @see #testFranceGeocentricInterpolationPoint()
+     */
+    @Test
+    @DependsOnMethod("testFranceGeocentricInterpolationPoint")
+    public void compareWithGeocentricTranslation() throws FactoryException, 
TransformException, IOException {
+        /*
+         * Disable the test for inverse transformations because they are not 
the purpose of this test.
+         * Errors of inverse transformations are added to the error of forward 
transformations, which
+         * would force us to double the tolerance threshold.
+         */
+        isInverseTransformSupported = false;
+        tolerance         = 3*Formulas.LINEAR_TOLERANCE; // To be converted in 
degrees by ToleranceModifier.GEOGRAPHIC
+        zTolerance        = 4*Formulas.LINEAR_TOLERANCE;
+        toleranceModifier = 
ToleranceModifiers.concatenate(ToleranceModifier.GEOGRAPHIC, toleranceModifier);
+        compareWithGeocentricTranslation(HardCodedDatum.NTF.getEllipsoid(),   
// Clarke 1880 (IGN)
+                                         CommonCRS.ETRS89.ellipsoid(),        
// GRS 1980 ellipsoid
+                                         FranceGeocentricInterpolation.TX,
+                                         FranceGeocentricInterpolation.TY,
+                                         FranceGeocentricInterpolation.TZ,
+                                         -5.5, 41.0, -200,   // Geographic 
area of GR2DF97A datum shift grid.
+                                         10.0, 52.0, +200);
+    }
+
+    /**
      * Tests conversion of random points. The test is performed with the 
Molodensky transform,
-     * not the abridged one, because the errors caused by the abridged 
Molondeky method is too
-     * high for this test.
+     * not the abridged one, because the errors caused by the abridged 
Molodensky method are
+     * too high for this test.
      *
      * @throws FactoryException if an error occurred while creating a 
transform step.
      * @throws TransformException if a transformation failed.
@@ -183,9 +344,9 @@ public final strictfp class MolodenskyTr
         tolerance  = Formulas.LINEAR_TOLERANCE * 3;     // To be converted in 
degrees by ToleranceModifier.GEOGRAPHIC
         zTolerance = Formulas.LINEAR_TOLERANCE * 2;
         toleranceModifier = 
ToleranceModifiers.concatenate(ToleranceModifier.GEOGRAPHIC, toleranceModifier);
-        verifyInDomain(new double[] {Longitude.MIN_VALUE, -85, -500},
-                       new double[] {Longitude.MIN_VALUE, +85, +500},
-                       new int[] {8, 8, 8},
+        verifyInDomain(new double[] {-179, -85, -500},
+                       new double[] {+179, +85, +500},
+                       new int[]    {   8,   8,    8},
                        TestUtilities.createRandomNumberGenerator(208129394));
     }
 
@@ -211,11 +372,8 @@ public final strictfp class MolodenskyTr
         transform = factory.createParameterizedTransform(parameters);
         assertEquals(3, transform.getSourceDimensions());
         assertEquals(3, transform.getTargetDimensions());
-        final double delta = toRadians(100.0 / 60) / 1852;          // 
Approximatively 100 metres
-        derivativeDeltas = new double[] {delta, delta, 100};        // (Δλ, 
Δφ, Δh)
-        tolerance = Formulas.ANGULAR_TOLERANCE * 5;
-        zTolerance = Formulas.LINEAR_TOLERANCE * 5;
-        zDimension = new int[] {2};
+        tolerance  = Formulas.ANGULAR_TOLERANCE * 5;
+        zTolerance = Formulas.LINEAR_TOLERANCE  * 5;
         verifyInDomain(CoordinateDomain.RANGE_10, ORDINATE_COUNT);
     }
 
@@ -259,28 +417,28 @@ public final strictfp class MolodenskyTr
         create(true);
         assertWktEquals("PARAM_MT[“Abridged_Molodenski”,\n" +
                         "  PARAMETER[“dim”, 3],\n" +
+                        "  PARAMETER[“src_semi_major”, 6378137.0],\n" +
+                        "  PARAMETER[“src_semi_minor”, 6356752.314245179],\n" +
+                        "  PARAMETER[“tgt_semi_major”, 6378388.0],\n" +
+                        "  PARAMETER[“tgt_semi_minor”, 6356911.9461279465],\n" 
+
                         "  PARAMETER[“dx”, 84.87],\n" +
                         "  PARAMETER[“dy”, 96.49],\n" +
                         "  PARAMETER[“dz”, 116.95],\n" +
                         "  PARAMETER[“Semi-major axis length difference”, 
251.0],\n" +
-                        "  PARAMETER[“Flattening difference”, 
1.4192702255886284E-5],\n" +
-                        "  PARAMETER[“src_semi_major”, 6378137.0],\n" +
-                        "  PARAMETER[“src_semi_minor”, 6356752.314245179],\n" +
-                        "  PARAMETER[“tgt_semi_major”, 6378388.0],\n" +
-                        "  PARAMETER[“tgt_semi_minor”, 6356911.9461279465]]");
+                        "  PARAMETER[“Flattening difference”, 
1.4192702255886284E-5]]");
 
         transform = transform.inverse();
         assertWktEquals("PARAM_MT[“Abridged_Molodenski”,\n" +
                         "  PARAMETER[“dim”, 3],\n" +
+                        "  PARAMETER[“src_semi_major”, 6378388.0],\n" +
+                        "  PARAMETER[“src_semi_minor”, 6356911.9461279465],\n" 
+
+                        "  PARAMETER[“tgt_semi_major”, 6378137.0],\n" +
+                        "  PARAMETER[“tgt_semi_minor”, 6356752.314245179],\n" +
                         "  PARAMETER[“dx”, -84.87],\n" +
                         "  PARAMETER[“dy”, -96.49],\n" +
                         "  PARAMETER[“dz”, -116.95],\n" +
                         "  PARAMETER[“Semi-major axis length difference”, 
-251.0],\n" +
-                        "  PARAMETER[“Flattening difference”, 
-1.4192702255886284E-5],\n" +
-                        "  PARAMETER[“src_semi_major”, 6378388.0],\n" +
-                        "  PARAMETER[“src_semi_minor”, 6356911.9461279465],\n" 
+
-                        "  PARAMETER[“tgt_semi_major”, 6378137.0],\n" +
-                        "  PARAMETER[“tgt_semi_minor”, 6356752.314245179]]");
+                        "  PARAMETER[“Flattening difference”, 
-1.4192702255886284E-5]]");
     }
 
     /**
@@ -302,13 +460,13 @@ public final strictfp class MolodenskyTr
                 "    Parameter[“elt_0_0”, 0.017453292519943295],\n" +       // 
Degrees to radians conversion
                 "    Parameter[“elt_1_1”, 0.017453292519943295]],\n" +
                 "  Param_MT[“Molodensky”,\n" +
+                "    Parameter[“src_semi_major”, 6378137.0],\n" +
+                "    Parameter[“src_semi_minor”, 6356752.314245179],\n" +
+                "    Parameter[“Semi-major axis length difference”, 251.0],\n" 
+
+                "    Parameter[“Flattening difference”, 
1.4192702255886284E-5],\n" +
                 "    Parameter[“X-axis translation”, 84.87],\n" +
                 "    Parameter[“Y-axis translation”, 96.49],\n" +
                 "    Parameter[“Z-axis translation”, 116.95],\n" +
-                "    Parameter[“Semi-major axis length difference”, 251.0],\n" 
+
-                "    Parameter[“Flattening difference”, 
1.4192702255886284E-5],\n" +
-                "    Parameter[“src_semi_major”, 6378137.0],\n" +
-                "    Parameter[“eccentricity”, 0.0818191908426215],\n" +
                 "    Parameter[“abridged”, TRUE],\n" +
                 "    Parameter[“dim”, 3]],\n" +
                 "  Param_MT[“Affine”,\n" +

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ProjectiveTransformTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ProjectiveTransformTest.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ProjectiveTransformTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ProjectiveTransformTest.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -77,7 +77,7 @@ public strictfp class ProjectiveTransfor
                      * Opportunistically tests ScaledTransform together with 
ProjectiveTransform.
                      * We takes ScaledTransform as a reference implementation 
since it is simpler.
                      */
-                    tr = new TransformResultComparator(tr, pt);
+                    tr = new TransformResultComparator(tr, pt, 0);
                 }
                 return tr;
             }

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransformResultComparator.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransformResultComparator.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransformResultComparator.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/TransformResultComparator.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -48,16 +48,17 @@ final strictfp class TransformResultComp
     final MathTransform tested;
 
     /**
-     * The tolerance threshold, which is zero by default.
+     * The tolerance threshold.
      */
-    double tolerance;
+    private final double tolerance;
 
     /**
      * Creates a transform which will compare the results of the two given 
transforms.
      */
-    TransformResultComparator(final MathTransform reference, final 
MathTransform tested) {
+    TransformResultComparator(final MathTransform reference, final 
MathTransform tested, final double tolerance) {
         this.reference = reference;
         this.tested    = tested;
+        this.tolerance = tolerance;
     }
 
     /**
@@ -173,7 +174,7 @@ final strictfp class TransformResultComp
      */
     @Override
     public MathTransform inverse() throws NoninvertibleTransformException {
-        return new TransformResultComparator(reference.inverse(), 
tested.inverse());
+        return new TransformResultComparator(reference.inverse(), 
tested.inverse(), tolerance);
     }
 
     /**

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -44,6 +44,9 @@ import org.apache.sis.internal.util.Cons
 
 import static java.lang.StrictMath.*;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Assertion methods used by the {@code sis-referencing} module in addition of 
the ones inherited
@@ -371,7 +374,7 @@ public strictfp class ReferencingAssert
             assertFalse("e2.contains(e1)",   ae.contains  (e1, true));
         }
         final int dimension = e1.getDimension();
-        final int numCases = (int) round(pow(3, dimension));
+        final int numCases = JDK8.toIntExact(round(pow(3, dimension)));
         final GeneralDirectPosition pos = new GeneralDirectPosition(dimension);
         for (int index=0; index<numCases; index++) {
             int n = index;

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/integration/package-info.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/integration/package-info.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/integration/package-info.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/integration/package-info.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -17,11 +17,14 @@
 
 
 /**
- * Tests the integration between two ore more SIS modules.
+ * Tests the integration between two ore more SIS modules or integration with 
larger data.
+ * The larger data (e.g. datum shift grids) are not distributed with SIS. If 
desired, they
+ * must be downloaded by the user and stored in the directory identified by 
the {@code SIS_DATA}
+ * environment variable.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 package org.apache.sis.test.integration;

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -52,7 +52,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.operation.matrix.Matrix2Test.class,
     org.apache.sis.referencing.operation.matrix.Matrix3Test.class,
     org.apache.sis.referencing.operation.matrix.Matrix4Test.class,
-    org.apache.sis.referencing.operation.matrix.NonSquareMatrixTest.class, // 
Expected to be last MatrixTestCase - see javadoc.
+    org.apache.sis.referencing.operation.matrix.NonSquareMatrixTest.class,     
     // Expected to be last MatrixTestCase - see javadoc.
     org.apache.sis.referencing.operation.matrix.MatricesTest.class,
     org.apache.sis.referencing.operation.matrix.AffineTransforms2DTest.class,
 
@@ -62,6 +62,7 @@ import org.junit.BeforeClass;
     org.apache.sis.parameter.DefaultParameterValueTest.class,
     org.apache.sis.parameter.DefaultParameterValueGroupTest.class,
     org.apache.sis.parameter.UnmodifiableParameterValueTest.class,
+    org.apache.sis.parameter.UnmodifiableParameterValueGroupTest.class,
     org.apache.sis.parameter.ParametersTest.class,
     org.apache.sis.parameter.ParameterBuilderTest.class,
     org.apache.sis.parameter.ParameterFormatTest.class,
@@ -113,6 +114,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.operation.transform.CopyTransformTest.class,
     
org.apache.sis.referencing.operation.transform.PassThroughTransformTest.class,
     
org.apache.sis.referencing.operation.transform.ConcatenatedTransformTest.class,
+    
org.apache.sis.referencing.operation.transform.TransformSeparatorTest.class,
     org.apache.sis.referencing.operation.transform.TransferFunctionTest.class,
     org.apache.sis.referencing.operation.transform.MathTransformsTest.class,
     
org.apache.sis.referencing.operation.transform.ContextualParametersTest.class,
@@ -131,8 +133,15 @@ import org.junit.BeforeClass;
     
org.apache.sis.internal.referencing.provider.GeocentricTranslationTest.class,
     
org.apache.sis.internal.referencing.provider.PositionVector7ParamTest.class,
     
org.apache.sis.internal.referencing.provider.CoordinateFrameRotationTest.class,
+    org.apache.sis.internal.referencing.provider.MolodenskyTest.class,
+    
org.apache.sis.internal.referencing.provider.FranceGeocentricInterpolationTest.class,
+    org.apache.sis.internal.referencing.provider.NTv2Test.class,
+    org.apache.sis.internal.referencing.provider.NADCONTest.class,
     org.apache.sis.internal.referencing.provider.MapProjectionTest.class,
     org.apache.sis.internal.referencing.provider.AllProvidersTest.class,
+    
org.apache.sis.referencing.operation.transform.InterpolatedTransformTest.class,
+    
org.apache.sis.referencing.operation.transform.InterpolatedGeocentricTransformTest.class,
+    
org.apache.sis.referencing.operation.transform.InterpolatedMolodenskyTransformTest.class,
     
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactoryTest.class,
 
     // Test map projections. Those tests need the providers tested above.
@@ -158,14 +167,27 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.crs.DefaultCompoundCRSTest.class,
     org.apache.sis.referencing.crs.HardCodedCRSTest.class,
 
+    org.apache.sis.referencing.StandardDefinitionsTest.class,
+    org.apache.sis.referencing.CommonCRSTest.class,
+    org.apache.sis.referencing.CRSTest.class,
     org.apache.sis.referencing.factory.GIGS3002.class,
     org.apache.sis.referencing.factory.GIGS3003.class,
     org.apache.sis.referencing.factory.GIGS3004.class,
     org.apache.sis.referencing.factory.GIGS3005.class,
     org.apache.sis.referencing.factory.GeodeticObjectFactoryTest.class,
-    org.apache.sis.referencing.StandardDefinitionsTest.class,
-    org.apache.sis.referencing.CommonCRSTest.class,
-    org.apache.sis.referencing.CRSTest.class,
+    org.apache.sis.referencing.factory.CommonAuthorityFactoryTest.class,
+    org.apache.sis.referencing.factory.AuthorityFactoryProxyTest.class,
+    org.apache.sis.referencing.factory.IdentifiedObjectFinderTest.class,
+    org.apache.sis.referencing.factory.GIGS2001.class,
+    org.apache.sis.referencing.factory.GIGS2002.class,
+    org.apache.sis.referencing.factory.GIGS2003.class,
+    org.apache.sis.referencing.factory.GIGS2004.class,
+    org.apache.sis.referencing.factory.GIGS2005.class,
+    org.apache.sis.referencing.factory.GIGS2006.class,
+    org.apache.sis.referencing.factory.GIGS2007.class,
+    org.apache.sis.referencing.factory.GIGS2008.class,
+    org.apache.sis.referencing.factory.GIGS2009.class,
+    org.apache.sis.referencing.factory.sql.EPSGFactoryTest.class,
 
     org.apache.sis.io.wkt.MathTransformParserTest.class,
     org.apache.sis.io.wkt.GeodeticObjectParserTest.class,
@@ -188,6 +210,7 @@ import org.junit.BeforeClass;
 
     
org.apache.sis.referencing.operation.builder.LinearTransformBuilderTest.class,
     org.apache.sis.internal.referencing.ServicesForMetadataTest.class,
+    org.apache.sis.test.integration.DatumShiftTest.class,
     org.apache.sis.test.integration.ReferencingInMetadataTest.class,
     org.apache.sis.test.integration.DefaultMetadataTest.class
 })

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/PathConverter.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -27,6 +27,10 @@ import org.apache.sis.math.FunctionPrope
 import org.apache.sis.util.ObjectConverter;
 import org.apache.sis.util.UnconvertibleObjectException;
 
+// Branch-specific import
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
 
 /**
  * Handles conversions between {@link Path}, {@link File}, {@link URI} and 
{@link URL} objects.
@@ -36,7 +40,7 @@ import org.apache.sis.util.Unconvertible
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 abstract class PathConverter<S,T> extends SystemConverter<S,T> {
@@ -92,13 +96,73 @@ abstract class PathConverter<S,T> extend
     abstract T doConvert(S source) throws Exception;
 
     /**
+     * Converter from {@link Path} to {@link URI}.
+     */
+    public static final class PathURI extends PathConverter<Path,URI> {
+        private static final long serialVersionUID = 740202123888081482L;
+        static final PathURI INSTANCE = new PathURI();
+        public PathURI() {super(Path.class, URI.class);}        // 
Instantiated by ServiceLoader.
+
+        @Override public ObjectConverter<Path,URI> unique()  {return INSTANCE;}
+        @Override public ObjectConverter<URI,Path> inverse() {return 
URIPath.INSTANCE;}
+        @Override public URI doConvert(final Path source) {
+            return source.toUri();
+        }
+    }
+
+    /**
+     * Converter from {@link Path} to {@link URL}.
+     */
+    public static final class PathURL extends PathConverter<Path,URL> {
+        private static final long serialVersionUID = -289518201451769080L;
+        static final PathURL INSTANCE = new PathURL();
+        public PathURL() {super(Path.class, URL.class);}        // 
Instantiated by ServiceLoader.
+
+        @Override public ObjectConverter<Path,URL> unique()  {return INSTANCE;}
+        @Override public ObjectConverter<URL,Path> inverse() {return 
URLPath.INSTANCE;}
+        @Override public URL doConvert(final Path source) throws 
MalformedURLException {
+            return source.toUri().toURL();
+        }
+    }
+
+    /**
+     * Converter from {@link Path} to {@link File}.
+     */
+    public static final class PathFile extends PathConverter<Path,File> {
+        private static final long serialVersionUID = 452241851474627778L;
+        static final PathFile INSTANCE = new PathFile();
+        public PathFile() {super(Path.class, File.class);}      // 
Instantiated by ServiceLoader.
+
+        @Override public ObjectConverter<Path,File> unique()  {return 
INSTANCE;}
+        @Override public ObjectConverter<File,Path> inverse() {return 
FilePath.INSTANCE;}
+        @Override public File doConvert(final Path source) throws 
UnsupportedOperationException {
+            return source.toFile();
+        }
+    }
+
+    /**
+     * Converter from {@link File} to {@link Path}.
+     */
+    public static final class FilePath extends PathConverter<File,Path> {
+        private static final long serialVersionUID = 6420947028493989549L;
+        static final FilePath INSTANCE = new FilePath();
+        public FilePath() {super(File.class, Path.class);}      // 
Instantiated by ServiceLoader.
+
+        @Override public ObjectConverter<File,Path> unique()  {return 
INSTANCE;}
+        @Override public ObjectConverter<Path,File> inverse() {return 
PathFile.INSTANCE;}
+        @Override public Path doConvert(final File source) {
+            return source.toPath();
+        }
+    }
+
+    /**
      * Converter from {@link File} to {@link URI}.
      * This converter changes relative paths to absolute paths.
      */
     public static final class FileURI extends PathConverter<File,URI> {
         private static final long serialVersionUID = 1122784850124333991L;
         static final FileURI INSTANCE = new FileURI();
-        public FileURI() {super(File.class, URI.class);} // Instantiated by 
ServiceLoader.
+        public FileURI() {super(File.class, URI.class);}        // 
Instantiated by ServiceLoader.
 
         @Override public ObjectConverter<File,URI> unique()  {return INSTANCE;}
         @Override public ObjectConverter<URI,File> inverse() {return 
URIFile.INSTANCE;}
@@ -113,7 +177,7 @@ abstract class PathConverter<S,T> extend
     public static final class FileURL extends PathConverter<File,URL> {
         private static final long serialVersionUID = 2191394598748096966L;
         static final FileURL INSTANCE = new FileURL();
-        public FileURL() {super(File.class, URL.class);} // Instantiated by 
ServiceLoader.
+        public FileURL() {super(File.class, URL.class);}        // 
Instantiated by ServiceLoader.
 
         @Override public ObjectConverter<File,URL> unique()  {return INSTANCE;}
         @Override public ObjectConverter<URL,File> inverse() {return 
URLFile.INSTANCE;}
@@ -123,12 +187,42 @@ abstract class PathConverter<S,T> extend
     }
 
     /**
+     * Converter from {@link URL} to {@link Path}.
+     */
+    public static final class URLPath extends PathConverter<URL,Path> {
+        private static final long serialVersionUID = 4030502499990629230L;
+        static final URLPath INSTANCE = new URLPath();
+        public URLPath() {super(URL.class, Path.class);}        // 
Instantiated by ServiceLoader.
+
+        @Override public ObjectConverter<URL,Path> unique()  {return INSTANCE;}
+        @Override public ObjectConverter<Path,URL> inverse() {return 
PathURL.INSTANCE;}
+        @Override public Path doConvert(final URL source) throws 
URISyntaxException {
+            return Paths.get(source.toURI());
+        }
+    }
+
+    /**
+     * Converter from {@link URI} to {@link Path}.
+     */
+    public static final class URIPath extends PathConverter<URI,Path> {
+        private static final long serialVersionUID = 5935532794533554151L;
+        static final URIPath INSTANCE = new URIPath();
+        public URIPath() {super(URI.class, Path.class);}        // 
Instantiated by ServiceLoader.
+
+        @Override public ObjectConverter<URI,Path> unique()  {return INSTANCE;}
+        @Override public ObjectConverter<Path,URI> inverse() {return 
PathURI.INSTANCE;}
+        @Override public Path doConvert(final URI source) throws 
IllegalArgumentException {
+            return Paths.get(source);
+        }
+    }
+
+    /**
      * Converter from {@link URL} to {@link File}.
      */
     public static final class URLFile extends PathConverter<URL,File> {
         private static final long serialVersionUID = 3669726699184691997L;
         static final URLFile INSTANCE = new URLFile();
-        public URLFile() {super(URL.class, File.class);} // Instantiated by 
ServiceLoader.
+        public URLFile() {super(URL.class, File.class);}        // 
Instantiated by ServiceLoader.
 
         @Override public ObjectConverter<URL,File> unique()  {return INSTANCE;}
         @Override public ObjectConverter<File,URL> inverse() {return 
FileURL.INSTANCE;}
@@ -138,12 +232,12 @@ abstract class PathConverter<S,T> extend
     }
 
     /**
-     * Converter from {@link URL} to {@link File}.
+     * Converter from {@link URI} to {@link File}.
      */
     public static final class URIFile extends PathConverter<URI,File> {
         private static final long serialVersionUID = 5070991554943811760L;
         static final URIFile INSTANCE = new URIFile();
-        public URIFile() {super(URI.class, File.class);} // Instantiated by 
ServiceLoader.
+        public URIFile() {super(URI.class, File.class);}        // 
Instantiated by ServiceLoader.
 
         @Override public ObjectConverter<URI,File> unique()  {return INSTANCE;}
         @Override public ObjectConverter<File,URI> inverse() {return 
FileURI.INSTANCE;}
@@ -158,7 +252,7 @@ abstract class PathConverter<S,T> extend
     public static final class URL_URI extends PathConverter<URL,URI> {
         private static final long serialVersionUID = 6327568235014244008L;
         static final URL_URI INSTANCE = new URL_URI();
-        public URL_URI() {super(URL.class, URI.class);} // Instantiated by 
ServiceLoader.
+        public URL_URI() {super(URL.class, URI.class);}         // 
Instantiated by ServiceLoader.
 
         @Override public ObjectConverter<URL,URI> unique()  {return INSTANCE;}
         @Override public ObjectConverter<URI,URL> inverse() {return 
URI_URL.INSTANCE;}
@@ -173,7 +267,7 @@ abstract class PathConverter<S,T> extend
     public static final class URI_URL extends PathConverter<URI,URL> {
         private static final long serialVersionUID = 5478354821309176895L;
         static final URI_URL INSTANCE = new URI_URL();
-        public URI_URL() {super(URI.class, URL.class);} // Instantiated by 
ServiceLoader.
+        public URI_URL() {super(URI.class, URL.class);}         // 
Instantiated by ServiceLoader.
 
         @Override public ObjectConverter<URI,URL> unique()  {return INSTANCE;}
         @Override public ObjectConverter<URL,URI> inverse() {return 
URL_URI.INSTANCE;}

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -43,7 +43,7 @@
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 package org.apache.sis.internal.converter;

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -26,8 +26,17 @@ import java.util.Locale;
 import java.util.TimeZone;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReference;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import javax.xml.bind.DatatypeConverter;
 
+// Branch-dependent imports
+import java.util.Objects;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
 
 /**
  * Place holder for some functionalities defined only in JDK8.
@@ -35,7 +44,7 @@ import javax.xml.bind.DatatypeConverter;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final class JDK8 {
@@ -53,6 +62,74 @@ public final class JDK8 {
     }
 
     /**
+     * Compares two numbers as unsigned.
+     *
+     * @param  x First unsigned value.
+     * @param  y Second unsigned value.
+     * @return Comparison result.
+     *
+     * @since 0.7
+     */
+    public static int compareUnsigned(final int x, final int y) {
+        return Integer.compare(x + Integer.MIN_VALUE, y + Integer.MIN_VALUE);
+    }
+
+    /**
+     * Returns the given byte as an unsigned integer.
+     *
+     * @param x The byte to return as an unsigned integer.
+     * @return The unsigned value of the given byte.
+     *
+     * @since 0.7
+     */
+    public static int toUnsignedInt(final byte x) {
+        return x & 0xFF;
+    }
+
+    /**
+     * Returns the given short as an unsigned integer.
+     *
+     * @param x The short to return as an unsigned integer.
+     * @return The unsigned value of the given short.
+     *
+     * @since 0.7
+     */
+    public static int toUnsignedInt(final short x) {
+        return x & 0xFFFF;
+    }
+
+    /**
+     * Safe cast of the given long to integer.
+     *
+     * @param value The value to cast.
+     * @return The casted value.
+     * @throws ArithmeticException if the value overflows.
+     *
+     * @since 0.7
+     */
+    public static int toIntExact(final long value) {
+        final int vi = (int) value;
+        if (vi != value) {
+            throw new ArithmeticException();
+        }
+        return vi;
+    }
+
+    /**
+     * Safe product of the arguments.
+     *
+     * @param x The first value.
+     * @param y The second value.
+     * @return The product.
+     * @throws ArithmeticException if the value overflows.
+     *
+     * @since 0.7
+     */
+    public static int multiplyExact(final int x, final int y) {
+        return toIntExact(x * (long) y);
+    }
+
+    /**
      * Returns the floating-point value adjacent to {@code value} in the 
direction of negative infinity.
      *
      * @param  value The value for which to get the adjacent value.
@@ -102,6 +179,27 @@ public final class JDK8 {
     }
 
     /**
+     * Removes the entry for the given key, provided that it is currently 
mapped to the given value.
+     *
+     * @param  <K>   The type of keys.
+     * @param  <V>   The type of values.
+     * @param  map   The map from where to remove the value.
+     * @param  key   The key for the value to remove.
+     * @param  value The value that must exist for allowing removal.
+     * @return {@code true} if the entry has been removed.
+     *
+     * @since 0.7
+     */
+    public static <K,V> boolean remove(final Map<K,V> map, final Object key, 
final Object value) {
+        final Object current = map.get(key);
+        final boolean c = Objects.equals(current, value) && (current != null 
|| map.containsKey(key));
+        if (c) {
+            map.remove(key);
+        }
+        return c;
+    }
+
+    /**
      * Removes all elements for which the given filter returns {@code true}.
      *
      * @param  <E>        The type of elements in the given collection.
@@ -193,7 +291,33 @@ public final class JDK8 {
         }
         calendar.setTime(date);
         final String text = DatatypeConverter.printDateTime(calendar);
-        CALENDAR.set(calendar); // Recycle for future usage.
+        CALENDAR.set(calendar);                                                
 // Recycle for future usage.
         return text;
     }
+
+    /**
+     * Creates a buffered reader using UTF-8 encoding.
+     *
+     * @param path The file to open.
+     * @return The reader.
+     * @throws IOException if an error occurred while opening the reader.
+     *
+     * @since 0.7
+     */
+    public static BufferedReader newBufferedReader(final Path path) throws 
IOException {
+        return Files.newBufferedReader(path, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * Creates a buffered writer using UTF-8 encoding.
+     *
+     * @param path The file to open.
+     * @return The writer.
+     * @throws IOException if an error occurred while opening the writer.
+     *
+     * @since 0.7
+     */
+    public static BufferedWriter newBufferedWriter(final Path path) throws 
IOException {
+        return Files.newBufferedWriter(path, StandardCharsets.UTF_8);
+    }
 }

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -24,97 +24,49 @@ import org.apache.sis.util.logging.Loggi
 
 /**
  * A thread executing short tasks after some (potentially zero nanosecond) 
delay.
- * This thread is reserved to internal SIS usage - no user code shall be 
executed here.
- * All submitted tasks shall be very quick, since there is only one thread 
shared by everyone.
+ * This class should be reserved to internal SIS usage without user's code.
+ * In practice some user code may be indirectly executed through SIS tasks 
invoking overrideable methods.
+ * But all submitted tasks shall be very quick, since there is only one thread 
shared by everyone.
  *
- * <div class="note"><b>Note:</b>
- * In practice some user code may be indirectly executed, since some SIS tasks 
invoke overrideable methods.
- * We may need to revisit the {@code DelayedExecutor} design in a future 
version if the above happens to be
- * a problem. For example we may allow the user to specify an application-wide 
scheduled executor and delegate
- * the tasks to that executor.</div>
- *
- * The methods for use in this class are:
+ * <p>The methods for use in this class are:</p>
  * <ul>
- *   <li>{@link #executeDaemonTask(DelayedRunnable)}</li>
- *   <li>{@link #schedule(DelayedRunnable)}</li>
+ *   <li>{@link #schedule(Runnable, long)}</li>
  * </ul>
  *
  * <div class="section">Comparison with {@code java.util.concurrent}</div>
- * We tried to use {@link java.util.concurrent.ScheduledThreadPoolExecutor} in 
a previous version,
- * but it seems more suitable to heavier tasks in applications controlling 
their own executor. For
- * example {@code ScheduledThreadPoolExecutor} acts as a fixed-sized pool, 
thus forcing us to use
- * only one thread if we don't want to waste resources (profiling shows that 
even a single thread
- * has very low activity). The {@code ThreadPoolExecutor} super-class is more 
flexible but still
- * have a quite aggressive policy on threads creation, and doesn't handle 
delayed tasks by itself.
- * We could combine both worlds with a {@code ThreadPoolExecutor} using a 
{@code DelayedQueue},
- * but it forces us to declare a core pool size of 0 otherwise {@code 
ThreadPoolExecutor} tries
- * to execute the tasks immediately without queuing them. Combined with the 
{@code DelayedQueue}
- * characteristics (being an unbounded queue), this result in {@code 
ThreadPoolExecutor} never
- * creating more than one thread (because it waits for the queue to reject a 
task before to create
- * more threads than the pool size).
+ * We tried to use {@link java.util.concurrent.ScheduledThreadPoolExecutor} in 
a previous SIS version,
+ * but its "fixed-sized pool" design forces us to use only one thread if we do 
not want to waste resources
+ * (profiling shows that even a single thread has very low activity), which 
reduces the interest of that class.
+ * Combination of {@code ThreadPoolExecutor} super-class with {@code 
DelayedQueue} were not successful neither.
  *
- * <p>Given that it seems difficult to configure {@code 
(Scheduled)ThreadPoolExecutor} in such
- * a way that two or more threads are created only when really needed, given 
that using those
- * thread pools seems an overkill when the pool size is fixed to one thread, 
given that our
- * profiling has show very low activity for that single thread anyway, and 
given that we do
- * not need cancellation and shutdown services for house keeping tasks (this 
is a daemon thread),
+ * <p>Given that it:</p>
+ * <ul>
+ *   <li>it seems difficult to configure {@code (Scheduled)ThreadPoolExecutor} 
in such a way
+ *       that two or more threads are created only when really needed,</li>
+ *   <li>using those executor services seems an overkill when the pool size is 
fixed to one thread,</li>
+ *   <li>our profiling has show very low activity for that single thread 
anyway,</li>
+ *   <li>we do not need cancellation and shutdown services for house keeping 
tasks (this is a daemon thread),</li>
+ * </ul>
  * a more lightweight solution seems acceptable here. Pseudo-benchmarking 
using the
- * {@code CacheTest.stress()} tests suggests that the lightweight solution is 
faster.</p>
- *
- * <div class="section">Future evolution</div>
- * We may remove (again) this class in a future SIS evolution if we happen to 
need an executor anyway.
- * However it may be better to wait and see what are the executor needs. 
Setting up an executor implies
- * choosing many arbitrary parameter values like the number of core threads, 
maximum threads, idle time,
- * queue capacity, etc. Furthermore some platforms (e.g. MacOS) provide 
OS-specific implementations
- * integrating well in their environment. We may want to let the user provides 
the executor of his
- * choice, or we way want to have more profiling data for choosing an 
appropriate executor. But we
- * may need to find some way to give priority to SIS tasks, since most of them 
are for releasing
- * resources - in which case quick execution probably help the system to run 
faster.
- * However before to switch from the lightweight solution to a more heavy 
solution,
- * micro-benchmarking is desirable. The {@code CacheTest.stress()} tests can 
be used
- * in first approximation.
+ * {@code CacheTest.stress()} tests suggests that the lightweight solution is 
faster.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  *
  * @see <a href="https://issues.apache.org/jira/browse/SIS-76";>SIS-76</a>
  */
 public final class DelayedExecutor extends DaemonThread {
     /**
-     * Executes the given short task in a daemon thread. This method shall be 
invoked for
-     * Apache SIS tasks only, <strong>not</strong> for arbitrary user task. 
The task must
-     * completes quickly, because we will typically use only one thread for 
all submitted
-     * tasks. Completion of the task shall not be critical, since the JVM is 
allowed to
-     * shutdown before task completion.
-     *
-     * <div class="section">Future evolution</div>
-     * If {@code DelayedExecutor} is removed in a future SIS version in favor 
of JDK6 executors,
-     * then the method signature will probably be {@code 
Executors.execute(Runnable)}.
-     *
-     * @param task The task to execute.
-     */
-    public static void executeDaemonTask(final DelayedRunnable task) {
-        QUEUE.add(task);
-    }
-
-    /**
      * Schedules the given short task for later execution in a daemon thread.
-     * The task will be executed after the delay specified by {@link 
DelayedRunnable#getDelay}
-     * The task must completes quickly, because we will typically use only one 
thread for all
-     * submitted tasks. Completion of the task shall not be critical, since 
the JVM is allowed
-     * to shutdown before task completion.
-     *
-     * <div class="section">Future evolution</div>
-     * If {@code DelayedExecutor} is removed in a future SIS version in favor 
of JDK6 executors,
-     * then the method signature will probably be {@code 
Executors.schedule(Runnable, long, TimeUnit)}.
+     * The task will be executed after the delay specified by {@link 
DelayedRunnable#getDelay(TimeUnit)}
+     * The task must completes quickly, because we will typically use only one 
thread for all submitted tasks.
+     * Completion of the task shall not be critical, since the JVM is allowed 
to shutdown before task completion.
      *
      * @param task The task to schedule for later execution.
      */
     public static void schedule(final DelayedRunnable task) {
-        // For now the implementation is identical to 'execute'. However it 
may become
-        // different if we choose to use a library-wide executor in a future 
SIS version.
         QUEUE.add(task);
     }
 

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -39,6 +39,12 @@ public abstract class DelayedRunnable im
      * Time of execution of this task, in nanoseconds provided by {@link 
System#nanoTime()}.
      * In the particular case of the {@link Immediate} subclass, the meaning 
of this field is
      * modified: it is rather an ordinal value used for preserving task order.
+     *
+     * <div class="note"><b>Note:</b>
+     * we use {@link System#nanoTime()} instead than {@link 
System#currentTimeMillis()} because
+     * the later is not guaranteed to be monotonic: {@code currentTimeMillis} 
may change abruptly
+     * for example if the user adjusts the clock of his operating system.
+     * </div>
      */
     final long timestamp;
 
@@ -74,7 +80,7 @@ public abstract class DelayedRunnable im
     @Override
     public int compareTo(final Delayed other) {
         if (other instanceof Immediate) {
-            return +1; // "Immediate" tasks always have precedence over 
delayed ones.
+            return +1;                      // "Immediate" tasks always have 
precedence over delayed ones.
         }
         return Long.signum(timestamp - ((DelayedRunnable) other).timestamp);
     }

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Loggers.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Loggers.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Loggers.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Loggers.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -16,6 +16,18 @@
  */
 package org.apache.sis.internal.system;
 
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.Handler;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import org.apache.sis.util.Static;
+import org.apache.sis.util.logging.Logging;
+
 
 /**
  * Names of loggers used in SIS other than the "module-wide" loggers. We often 
use approximatively one logger
@@ -24,10 +36,15 @@ package org.apache.sis.internal.system;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
-public final class Loggers {
+public final class Loggers extends Static {
+    /**
+     * The root logger.
+     */
+    public static final String ROOT = "org.apache.sis";
+
     /**
      * The logger for Apache SIS internal operations. The name of this logger 
does not match the package name
      * of the classes using it, because this logger name does not have the 
{@code "internal"} part in it.
@@ -35,6 +52,11 @@ public final class Loggers {
     public static final String SYSTEM = "org.apache.sis.system";
 
     /**
+     * The logger for operations related to JDBC operations.
+     */
+    public static final String SQL = "org.apache.sis.sql";
+
+    /**
      * The logger for operations related to XML marshalling or unmarshalling.
      */
     public static final String XML = "org.apache.sis.xml";
@@ -74,8 +96,105 @@ public final class Loggers {
     public static final String LOCALIZATION = "org.apache.sis.util.resources";
 
     /**
+     * The logger name for operation related to application (console, GUI or 
web).
+     */
+    public static final String APPLICATION = "org.apache.sis.application";
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Loggers() {
     }
+
+    /**
+     * Returns a map of effective logging levels for SIS loggers. The 
effective logging level take in account the level
+     * of parent loggers and the level of handlers. For example if a logger 
level is set to {@link Level#FINE} but no
+     * handler have a level finer than {@link Level#INFO}, then the effective 
logging level will be {@link Level#INFO}.
+     *
+     * <p>This method does not report the loggers that have an effective level 
identical to its parent logger.</p>
+     *
+     * @return The effective logging levels of SIS loggers.
+     */
+    public static SortedMap<String,Level> getEffectiveLevels() {
+        final SortedMap<String,Level> levels = new TreeMap<>();
+        for (final Field field : Loggers.class.getDeclaredFields()) {
+            if (Modifier.isStatic(field.getModifiers()) && field.getType() == 
String.class) try {
+                levels.put((String) field.get(null), null);
+            } catch (IllegalAccessException e) {
+                /*
+                 * Should never happen, unless we added some fields and forgot 
to update this method.
+                 * In such case forget the problematic fields and search the 
next one. This is okay
+                 * since this method is only for information purpose.
+                 */
+                Logging.unexpectedException(Logging.getLogger(SYSTEM), 
Loggers.class, "getEffectiveLevels", e);
+            }
+        }
+        /*
+         * Process the loggers in alphabetical order. The intend is to process 
parent loggers before child.
+         * The first logger in the map should be the SIS root logger, 
"org.apache.sis".
+         */
+        final Iterator<Map.Entry<String,Level>> it = 
levels.entrySet().iterator();
+        while (it.hasNext()) {
+            final Map.Entry<String,Level> entry = it.next();
+            final String name = entry.getKey();
+            final Logger logger = Logging.getLogger(name);
+            Level level = getEffectiveLevel(logger);
+            final Level h = getHandlerLevel(logger);
+            if (h.intValue() > level.intValue()) {
+                level = h;                              // Take in account the 
logging level of handlers.
+            }
+            entry.setValue(level);
+            /*
+             * Now verify if the level is identical to the effective level of 
parent logger.
+             * If they are identical, then we remove the entry in order to 
report only the changes.
+             */
+            Logger parent = logger;
+            while ((parent = parent.getParent()) != null) {
+                final Level p = levels.get(parent.getName());
+                if (p != null) {
+                    if (p.equals(level)) {
+                        it.remove();
+                    }
+                    break;
+                }
+            }
+        }
+        return levels;
+    }
+
+    /**
+     * Returns the effective level of the given logger, searching in the 
parent loggers if needed.
+     * This method does not verify if handlers have higher level.
+     */
+    private static Level getEffectiveLevel(Logger logger) {
+        while (logger != null) {
+            final Level level = logger.getLevel();
+            if (level != null) {
+                return level;
+            }
+            logger = logger.getParent();
+        }
+        return Level.INFO;      // Default value specified by the 
java.util.logging framework.
+    }
+
+    /**
+     * Returns the finest level of registered handlers for the given logger.
+     * This method verifies also in the parent handlers if the logger use them.
+     */
+    private static Level getHandlerLevel(Logger logger) {
+        Level level = Level.OFF;
+        while (logger != null) {
+            for (final Handler handler : logger.getHandlers()) {
+                final Level c = handler.getLevel();
+                if (c != null && c.intValue() < level.intValue()) {
+                    level = c;
+                }
+            }
+            if (!logger.getUseParentHandlers()) {
+                break;
+            }
+            logger = logger.getParent();
+        }
+        return level;
+    }
 }

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/OSGiActivator.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/OSGiActivator.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/OSGiActivator.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/OSGiActivator.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.internal.system;
 
-import javax.management.JMException;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleEvent;
@@ -30,7 +29,7 @@ import org.osgi.framework.BundleListener
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  *
  * @see ServletListener
@@ -50,6 +49,7 @@ public final class OSGiActivator impleme
     @Override
     public void start(final BundleContext context) {
         context.addBundleListener(this);
+        Shutdown.setContainer("OSGi");
     }
 
     /**
@@ -57,10 +57,10 @@ public final class OSGiActivator impleme
      * This method shutdowns the {@code sis-utility} threads.
      *
      * @param  context The execution context of the bundle being stopped.
-     * @throws JMException If an error occurred during unregistration of the 
supervisor MBean.
+     * @throws Exception If an error occurred during unregistration of the 
supervisor MBean or resource disposal.
      */
     @Override
-    public void stop(final BundleContext context) throws JMException {
+    public void stop(final BundleContext context) throws Exception {
         context.removeBundleListener(this);
         Shutdown.stop(getClass());
     }

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Semaphores.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Semaphores.java?rev=1723780&r1=1723779&r2=1723780&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Semaphores.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/system/Semaphores.java
 [UTF-8] Fri Jan  8 18:29:04 2016
@@ -36,7 +36,7 @@ public final class Semaphores {
      * {@code AbstractDerivedCRS} objects contain a {@code conversionFromBase} 
field, which contains a
      * {@code DefaultConversion.targetCRS} field referencing back the {@code 
AbstractDerivedCRS} object.
      */
-    public static final byte COMPARING = 1;
+    public static final byte CONVERSION_AND_CRS = 1;
 
     /**
      * A flag to indicate that {@link 
org.apache.sis.referencing.operation.AbstractCoordinateOperation}
@@ -71,7 +71,7 @@ public final class Semaphores {
     /**
      * Returns {@code true} if the given flag is set.
      *
-     * @param flag One of {@link #COMPARING}, {@link #ENCLOSED_IN_OPERATION} 
or other constants.
+     * @param flag One of {@link #CONVERSION_AND_CRS}, {@link 
#ENCLOSED_IN_OPERATION} or other constants.
      * @return {@code true} if the given flag is set.
      */
     public static boolean query(final byte flag) {
@@ -82,7 +82,7 @@ public final class Semaphores {
     /**
      * Sets the given flag.
      *
-     * @param flag One of {@link #COMPARING}, {@link #ENCLOSED_IN_OPERATION} 
or other constants.
+     * @param flag One of {@link #CONVERSION_AND_CRS}, {@link 
#ENCLOSED_IN_OPERATION} or other constants.
      * @return {@code true} if the given flag was already set.
      */
     public static boolean queryAndSet(final byte flag) {
@@ -99,7 +99,7 @@ public final class Semaphores {
     /**
      * Clears the given flag.
      *
-     * @param flag One of {@link #COMPARING}, {@link #ENCLOSED_IN_OPERATION} 
or other constants.
+     * @param flag One of {@link #CONVERSION_AND_CRS}, {@link 
#ENCLOSED_IN_OPERATION} or other constants.
      */
     public static void clear(final byte flag) {
         final Semaphores s = FLAGS.get();



Reply via email to