sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1670967 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ core/sis-referencing/src/main/java/org/apache/sis/parameter/ core/sis-referencing/src/main/java/org/apache/sis/referencing/ c...
Date Thu, 02 Apr 2015 21:05:36 GMT
Author: desruisseaux
Date: Thu Apr  2 21:05:35 2015
New Revision: 1670967

URL: http://svn.apache.org/r1670967
Log:
Referencing: add parameter definitions for EquidistantCylindrical projection.
As a side effect, added 'replaceNames' method in ParameterBuilder in order to
make easier to use an existing ParameterDescriptor as a template.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterTableRow.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
    sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderMock.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java
    sis/branches/JDK8/ide-project/NetBeans/nbproject/genfiles.properties
    sis/branches/JDK8/ide-project/NetBeans/nbproject/project.xml

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java?rev=1670967&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.referencing.provider;
+
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.operation.CylindricalProjection;
+
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.util.resources.Messages;
+
+
+/**
+ * The provider for "<cite>Equidistant Cylindrical</cite>" projection (EPSG:1028, EPSG:1029,
+ * <span class="deprecated">EPSG:9842</span>, <span class="deprecated">EPSG:9823</span>).
+ *
+ * <div class="note"><b>Note:</b>
+ * EPSG defines two codes for this projection, 1029 being the spherical case and 1028 the ellipsoidal case.
+ * However the formulas are the same in both cases, with an additional adjustment of Earth radius in the
+ * ellipsoidal case. Consequently they are implemented in Apache SIS by the same class.</div>
+ *
+ * <div class="note"><b>Note:</b>
+ * EPSG:1028 and 1029 are the current codes, while EPSG:9842 and 9823 are deprecated codes.
+ * The new and deprecated definitions differ only by their names. In the Apache SIS implementation,
+ * both current and legacy definitions are known, but the legacy names are marked as deprecated.</div>
+ *
+ * @author  John Grange
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.6
+ * @version 0.6
+ * @module
+ *
+ * @see <a href="http://www.remotesensing.org/geotiff/proj_list/equirectangular.html">Equirectangular on RemoteSensing.org</a>
+ */
+public final class EquidistantCylindrical extends AbstractProvider {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -278288251842178001L;
+
+    /**
+     * The operation parameter descriptor for the <cite>Latitude of 1st standard parallel</cite> (φ₁) parameter value.
+     * Valid values range is (-90 … 90)° and default value is 0°.
+     */
+    public static final ParameterDescriptor<Double> STANDARD_PARALLEL;
+
+    /**
+     * The operation parameter descriptor for the <cite>Latitude of natural origin</cite> (φ₀) parameter value.
+     * Valid values range is (-90 … 90)° and default value is 0°.
+     *
+     * <p>In theory, this parameter should not be used and its value should be 0 in all cases.
+     * This parameter is included for completeness in CRS labelling only.</p>
+     */
+    public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
+
+    /**
+     * The operation parameter descriptor for the <cite>Longitude of natural origin</cite> (λ₀) parameter value.
+     * Valid values range is [-180 … 180]° and default value is 0°.
+     */
+    public static final ParameterDescriptor<Double> CENTRAL_MERIDIAN;
+
+    /**
+     * The operation parameter descriptor for the <cite>False easting</cite> (FE) parameter value.
+     * Valid values range is unrestricted and default value is 0 metre.
+     */
+    public static final ParameterDescriptor<Double> FALSE_EASTING;
+
+    /**
+     * The operation parameter descriptor for the <cite>False northing</cite> (FN) parameter value.
+     * Valid values range is unrestricted and default value is 0 metre.
+     */
+    public static final ParameterDescriptor<Double> FALSE_NORTHING;
+
+    /**
+     * The group of all parameters expected by this coordinate operation.
+     */
+    public static final ParameterDescriptorGroup PARAMETERS;
+    static {
+        final ParameterBuilder builder = builder();
+
+        STANDARD_PARALLEL = createLatitude(builder
+                .addIdentifier("8823")
+                .addName("Latitude of 1st standard parallel")
+                .addName(Citations.OGC,     "standard_parallel_1")
+                .addName(Citations.ESRI,    "Standard_Parallel_1")
+                .addName(Citations.NETCDF,  "standard_parallel")
+                .addName(Citations.GEOTIFF, "ProjStdParallel1")
+                .addName(Citations.PROJ4,   "lat_ts"), false);
+
+        CENTRAL_MERIDIAN = createLongitude(builder
+                .addIdentifier("8802")
+                .addName("Longitude of natural origin")
+                .addName(Citations.OGC,     "central_meridian")
+                .addName(Citations.ESRI,    "Central_Meridian")
+                .addName(Citations.NETCDF,  "longitude_of_projection_origin")
+                .addName(Citations.GEOTIFF, "ProjCenterLong")
+                .addName(Citations.PROJ4,   "lon_0")
+                .addDeprecatedIdentifier("8822", "8802")    // Was used by EPSG:9842 only.
+                .addDeprecatedName("Longitude of false origin", "Longitude of natural origin"));
+
+        FALSE_EASTING = createShift(builder
+                .addIdentifier("8806")
+                .addName("False easting")
+                .addName(Citations.OGC,     "false_easting")
+                .addName(Citations.ESRI,    "False_Easting")
+                .addName(Citations.NETCDF,  "false_easting")
+                .addName(Citations.GEOTIFF, "FalseEasting")
+                .addName(Citations.PROJ4,   "x_0"));
+
+        FALSE_NORTHING = createShift(builder
+                .addIdentifier("8807")
+                .addName("False northing")
+                .addName(Citations.OGC,     "false_northing")
+                .addName(Citations.ESRI,    "False_Northing")
+                .addName(Citations.NETCDF,  "false_northing")
+                .addName(Citations.GEOTIFF, "FalseNorthing")
+                .addName(Citations.PROJ4,   "y_0"));
+        /*
+         * "Latitude of natural origin" and "Scale factor" are not formally parameters
+         * of the "Equidistant Cylindrical" projection according EPSG.  But we declare
+         * them as optional parameters because they are sometime used.
+         */
+        LATITUDE_OF_ORIGIN = createConstant(builder     // Was used by EPSG:9842 and 9823.
+                .addIdentifier("8801")
+                .addName("Latitude of natural origin")
+                .addName(Citations.OGC,     "latitude_of_origin")
+                .addName(Citations.ESRI,    "Latitude_Of_Origin")
+                .addName(Citations.NETCDF,  "latitude_of_projection_origin")
+                .addName(Citations.GEOTIFF, "ProjCenterLat")
+                .addName(Citations.PROJ4,   "lat_0")
+                .setRemarks(Messages.formatInternational(Messages.Keys.ConstantProjParameterValue_1, 0))
+                .setRequired(false), 0.0);
+
+        PARAMETERS = builder
+            .addIdentifier(             "1028")                     // The ellipsoidal case
+            .addIdentifier(             "1029")                     // The spherical case
+            .addDeprecatedIdentifier(   "9842", "1028")             // Using deprecated parameter names
+            .addDeprecatedIdentifier(   "9823", "1029")             // Using deprecated parameter names
+            .addName(                   "Equidistant Cylindrical")
+            .addName(                   "Equidistant Cylindrical (Spherical)")
+            .addName(Citations.OGC,     "Equirectangular")
+            .addName(Citations.ESRI,    "Equidistant_Cylindrical")
+            .addName(Citations.GEOTIFF, "CT_Equirectangular")
+            .addName(Citations.PROJ4,   "eqc")
+            .addIdentifier(Citations.GEOTIFF, "17")
+            .createGroupForMapProjection(
+                    STANDARD_PARALLEL,
+                    LATITUDE_OF_ORIGIN,
+                    CENTRAL_MERIDIAN,
+                    FALSE_EASTING,
+                    FALSE_NORTHING);
+    }
+
+    /**
+     * Constructs a new provider.
+     */
+    public EquidistantCylindrical() {
+        super(2, 2, PARAMETERS);
+    }
+
+    /**
+     * Returns the operation type for this map projection.
+     *
+     * @return {@code CylindricalProjection.class}
+     */
+    @Override
+    public Class<CylindricalProjection> getOperationType() {
+        return CylindricalProjection.class;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return The map projection created from the given parameter values.
+     */
+    @Override
+    public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup parameters) {
+        return null;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/EquidistantCylindrical.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -191,27 +191,6 @@ public abstract class MapProjection exte
     }
 
     /**
-     * Copies the names and identifiers from the given parameter into the builder.
-     * The given {@code esri} and {@code netcdf} parameters will be inserted after the OGC name.
-     */
-    static ParameterBuilder withEsriAndNetcdf(final ParameterDescriptor<?> source, final ParameterBuilder builder,
-            final String esri, final String netcdf)
-    {
-        for (final Identifier identifier : source.getIdentifiers()) {
-            builder.addIdentifier(identifier);
-        }
-        builder.addName(source.getName());
-        for (final GenericName alias : source.getAlias()) {
-            builder.addName(alias);
-            if (((Identifier) alias).getAuthority() == Citations.OGC) {
-                builder.addName(Citations.ESRI,   esri)
-                       .addName(Citations.NETCDF, netcdf);
-            }
-        }
-        return builder;
-    }
-
-    /**
      * Creates a remarks for parameters that are not formally EPSG parameter.
      *
      * @param origin The name of the projection for where the parameter is formally used.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -24,7 +24,6 @@ import org.apache.sis.parameter.Paramete
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.referencing.operation.projection.Mercator;
 import org.apache.sis.referencing.operation.projection.NormalizedProjection;
-import org.apache.sis.util.resources.Messages;
 
 
 /**
@@ -32,6 +31,8 @@ import org.apache.sis.util.resources.Mes
  * (EPSG:9804, EPSG:1026, <span class="deprecated">EPSG:9841</span>).
  * EPSG defines two codes for this projection, 1026 being the spherical case and 9804 the ellipsoidal case.
  *
+ * <p>This provider reuses many of the parameters defined in {@link Mercator2SP}.</p>
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Rueben Schulz (UBC)
  * @since   0.6
@@ -91,41 +92,26 @@ public final class Mercator1SP extends M
     static {
         final ParameterBuilder builder = builder();
 
-        LATITUDE_OF_ORIGIN = createConstant(builder
-                .addIdentifier("8801")
-                .addName("Latitude of natural origin")
-                .addName(Citations.OGC,     "latitude_of_origin")
-                .addName(Citations.GEOTIFF, "NatOriginLat")
-                .addName(Citations.PROJ4,   "lat_0")
-                .setRemarks(Messages.format(Messages.Keys.ConstantProjParameterValue_1, 0)), 0.0);
-
-        CENTRAL_MERIDIAN = createLongitude(builder
-                .addIdentifier("8802")
-                .addName("Longitude of natural origin")
-                .addName(Citations.OGC,     "central_meridian")
-                .addName(Citations.GEOTIFF, "NatOriginLong")
-                .addName(Citations.PROJ4,   "lon_0"));
-
-        SCALE_FACTOR = createScale(builder
-                .addIdentifier("8805")
-                .addName("Scale factor at natural origin")
-                .addName(Citations.OGC,     "scale_factor")
-                .addName(Citations.GEOTIFF, "ScaleAtNatOrigin")
-                .addName(Citations.PROJ4,   "k"));
-
-        FALSE_EASTING = createShift(builder
-                .addIdentifier("8806")
-                .addName("False easting")
-                .addName(Citations.OGC,     "false_easting")
-                .addName(Citations.GEOTIFF, "FalseEasting")
-                .addName(Citations.PROJ4,   "x_0"));
-
-        FALSE_NORTHING = createShift(builder
-                .addIdentifier("8807")
-                .addName("False northing")
-                .addName(Citations.OGC,     "false_northing")
-                .addName(Citations.GEOTIFF, "FalseNorthing")
-                .addName(Citations.PROJ4,   "y_0"));
+        LATITUDE_OF_ORIGIN = createConstant(builder.addNamesAndIdentifiers(Mercator2SP.LATITUDE_OF_ORIGIN)
+                .replaceNames(Citations.ESRI,    (String[]) null)
+                .replaceNames(Citations.NETCDF,  (String[]) null)
+                .setRemarks(Mercator2SP.LATITUDE_OF_ORIGIN.getRemarks()), 0.0);
+
+        CENTRAL_MERIDIAN = createLongitude(builder.addNamesAndIdentifiers(Mercator2SP.CENTRAL_MERIDIAN)
+                .replaceNames(Citations.ESRI,    (String[]) null)
+                .replaceNames(Citations.NETCDF,  (String[]) null));
+
+        SCALE_FACTOR = createScale(builder.addNamesAndIdentifiers(Mercator2SP.SCALE_FACTOR)
+                .replaceNames(Citations.ESRI,    (String[]) null)
+                .replaceNames(Citations.NETCDF,  (String[]) null));
+
+        FALSE_EASTING = createShift(builder.addNamesAndIdentifiers(Mercator2SP.FALSE_EASTING)
+                .replaceNames(Citations.ESRI,    (String[]) null)
+                .replaceNames(Citations.NETCDF,  (String[]) null));
+
+        FALSE_NORTHING = createShift(builder.addNamesAndIdentifiers(Mercator2SP.FALSE_NORTHING)
+                .replaceNames(Citations.ESRI,    (String[]) null)
+                .replaceNames(Citations.NETCDF,  (String[]) null));
 
         PARAMETERS = builder
             .addIdentifier(             "9804")                                                   // The ellipsoidal case
@@ -136,8 +122,8 @@ public final class Mercator1SP extends M
             .addName(                   "Mercator (1SP)")                                         // Prior to EPSG version 7.6
             .addDeprecatedName(         "Mercator (1SP) (Spherical)", "Mercator (Spherical)")     // Prior to EPSG version 7.6
             .addName(Citations.OGC,     "Mercator_1SP")
-            .addName(Citations.GEOTIFF, "CT_Mercator")
-            .addName(Citations.PROJ4,   "merc")
+            .addName(sameNameAs(Citations.GEOTIFF, Mercator2SP.PARAMETERS))
+            .addName(sameNameAs(Citations.PROJ4,   Mercator2SP.PARAMETERS))
             .addIdentifier(Citations.GEOTIFF,   "7")
             .addIdentifier(Citations.MAP_INFO, "10")    // MapInfo names this projection "Mercator".
             .createGroupForMapProjection(

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -28,7 +28,6 @@ import org.apache.sis.referencing.operat
 
 /**
  * The provider for "<cite>Mercator (variant B)</cite>" projection (EPSG:9805).
- * This provider reuses many of the parameters defined in {@link Mercator1SP}.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Rueben Schulz (UBC)
@@ -81,13 +80,13 @@ public final class Mercator2SP extends M
      * The operation parameter descriptor for the <cite>False easting</cite> (FE) parameter value.
      * Valid values range is unrestricted and default value is 0 metre.
      */
-    public static final ParameterDescriptor<Double> FALSE_EASTING;
+    public static final ParameterDescriptor<Double> FALSE_EASTING = EquidistantCylindrical.FALSE_EASTING;
 
     /**
      * The operation parameter descriptor for the <cite>False northing</cite> (FN) parameter value.
      * Valid values range is unrestricted and default value is 0 metre.
      */
-    public static final ParameterDescriptor<Double> FALSE_NORTHING;
+    public static final ParameterDescriptor<Double> FALSE_NORTHING = EquidistantCylindrical.FALSE_NORTHING;
 
     /**
      * The group of all parameters expected by this coordinate operation.
@@ -96,34 +95,31 @@ public final class Mercator2SP extends M
     static {
         final ParameterBuilder builder = builder();
 
-        STANDARD_PARALLEL = createLatitude(builder
-                .addIdentifier("8823")
-                .addName("Latitude of 1st standard parallel")
-                .addName(Citations.OGC,     "standard_parallel_1")
-                .addName(Citations.ESRI,    "Standard_Parallel_1")
-                .addName(Citations.NETCDF,  "standard_parallel")
-                .addName(Citations.GEOTIFF, "StdParallel1")
-                .addName(Citations.PROJ4,   "lat_1"), false);
+        STANDARD_PARALLEL = createLatitude(builder.addNamesAndIdentifiers(EquidistantCylindrical.STANDARD_PARALLEL)
+                .replaceNames(Citations.GEOTIFF, "StdParallel1")
+                .replaceNames(Citations.PROJ4,   "lat_1"), false);
 
-        CENTRAL_MERIDIAN = createLongitude(withEsriAndNetcdf(Mercator1SP.CENTRAL_MERIDIAN,
-                builder, "Central_Meridian", "longitude_of_projection_origin"));
+        CENTRAL_MERIDIAN = createLongitude(builder.addNamesAndIdentifiers(EquidistantCylindrical.CENTRAL_MERIDIAN)
+                .replaceNames(Citations.GEOTIFF, "NatOriginLong"));
 
-        FALSE_EASTING = createShift(withEsriAndNetcdf(Mercator1SP.FALSE_EASTING,
-                builder, "False_Easting", "false_easting"));
-
-        FALSE_NORTHING = createShift(withEsriAndNetcdf(Mercator1SP.FALSE_NORTHING,
-                builder, "False_Northing", "false_northing"));
         /*
          * "Latitude of natural origin" and "Scale factor" are not formally parameters
          * of the "Mercator (variant B)" projection according EPSG. But we declare them
          * as optional parameters because they are sometime used.
          */
-        LATITUDE_OF_ORIGIN = createConstant(withEsriAndNetcdf(Mercator1SP.LATITUDE_OF_ORIGIN, builder,
-                "Latitude_Of_Origin", "latitude_of_projection_origin").setRequired(false)
-                .setRemarks(Mercator1SP.LATITUDE_OF_ORIGIN.getRemarks()), 0.0);
-
-        SCALE_FACTOR = createScale(withEsriAndNetcdf(Mercator1SP.SCALE_FACTOR, builder,
-                "Scale_Factor", "scale_factor_at_projection_origin")
+        builder.setRequired(false); // Will apply to all remaining parameters.
+        LATITUDE_OF_ORIGIN = createConstant(builder.addNamesAndIdentifiers(EquidistantCylindrical.LATITUDE_OF_ORIGIN)
+                .replaceNames(Citations.GEOTIFF, "NatOriginLat")
+                .setRemarks(EquidistantCylindrical.LATITUDE_OF_ORIGIN.getRemarks()), 0.0);
+
+        SCALE_FACTOR = createScale(builder
+                .addIdentifier("8805")
+                .addName("Scale factor at natural origin")
+                .addName(Citations.OGC,     "scale_factor")
+                .addName(Citations.ESRI,    "Scale_Factor")
+                .addName(Citations.NETCDF,  "scale_factor_at_projection_origin")
+                .addName(Citations.GEOTIFF, "ScaleAtNatOrigin")
+                .addName(Citations.PROJ4,   "k")
                 .setRemarks(notFormalParameter(Mercator1SP.NAME, "Mercator (variant B)")));
 
         PARAMETERS = builder
@@ -133,8 +129,8 @@ public final class Mercator2SP extends M
             .addName(Citations.OGC,     "Mercator_2SP")
             .addName(Citations.ESRI,    "Mercator")
             .addName(Citations.NETCDF,  "Mercator")
-            .addName(sameNameAs(Citations.GEOTIFF, Mercator1SP.PARAMETERS))
-            .addName(sameNameAs(Citations.PROJ4,   Mercator1SP.PARAMETERS))
+            .addName(Citations.GEOTIFF, "CT_Mercator")
+            .addName(Citations.PROJ4,   "merc")
             .addIdentifier(Citations.MAP_INFO, "26")    // MapInfo names this projection "Regional Mercator".
             .addIdentifier(Citations.S57,       "8")
             .createGroupForMapProjection(

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -92,9 +92,10 @@ public final class MillerCylindrical ext
          * The "latitude of origin" and the "scale factor" are not formally a parameter of the "Miller Cylindrical"
          * projection. But we declare them as an optional parameters because they are sometime used.
          */
+        builder.setRequired(false); // Will apply to all remaining parameters.
         final InternationalString remarks = notFormalParameter(Mercator1SP.NAME, "Miller Cylindrical");
-        final ParameterDescriptor<?> scaleFactor = createScale(exceptEPSG(Mercator1SP.SCALE_FACTOR, builder)
-                .setRemarks(remarks).setRequired(false));
+        final ParameterDescriptor<?> scaleFactor = createScale(
+                exceptEPSG(Mercator1SP.SCALE_FACTOR, builder).setRemarks(remarks));
 
         final ParameterDescriptor<?> latitudeOfOrigin = createLatitude(
                 exceptEPSG(Mercator1SP.LATITUDE_OF_ORIGIN, builder).setRemarks(remarks), false);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterTableRow.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterTableRow.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterTableRow.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterTableRow.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -38,6 +38,7 @@ import org.opengis.referencing.Identifie
 import org.apache.sis.io.wkt.Colors;
 import org.apache.sis.io.wkt.ElementKind;
 import org.apache.sis.util.Characters;
+import org.apache.sis.util.Deprecable;
 import org.apache.sis.measure.Range;
 import org.apache.sis.measure.RangeFormat;
 import org.apache.sis.internal.metadata.NameToIdentifier;
@@ -145,20 +146,22 @@ final class ParameterTableRow {
             final Collection<GenericName> aliases = object.getAlias();
             if (aliases != null) { // Paranoiac check.
                 for (GenericName alias : aliases) {
-                    String codespace = NameToIdentifier.getCodeSpace(alias, locale);
-                    if (codespace != null) {
-                        alias = alias.tip();
-                    } else {
-                        final NameSpace scope = alias.scope();
-                        if (scope != null && !scope.isGlobal()) {
-                            codespace = NameToIdentifier.toString(scope.name().tip(), locale);
+                    if (!isDeprecated(alias)) {
+                        String codespace = NameToIdentifier.getCodeSpace(alias, locale);
+                        if (codespace != null) {
+                            alias = alias.tip();
+                        } else {
+                            final NameSpace scope = alias.scope();
+                            if (scope != null && !scope.isGlobal()) {
+                                codespace = NameToIdentifier.toString(scope.name().tip(), locale);
+                            }
                         }
-                    }
-                    if (preferredCodespaces == null || preferredCodespaces.contains(codespace)) {
-                        addIdentifier(codespace, NameToIdentifier.toString(alias, locale));
-                        name = null;
-                        if (isBrief) {
-                            break;
+                        if (preferredCodespaces == null || preferredCodespaces.contains(codespace)) {
+                            addIdentifier(codespace, NameToIdentifier.toString(alias, locale));
+                            name = null;
+                            if (isBrief) {
+                                break;
+                            }
                         }
                     }
                 }
@@ -178,9 +181,11 @@ final class ParameterTableRow {
             final Collection<? extends Identifier> ids = object.getIdentifiers();
             if (ids != null) { // Paranoiac check.
                 for (final Identifier id : ids) {
-                    final String codespace = id.getCodeSpace();
-                    if (preferredCodespaces == null || preferredCodespaces.contains(codespace)) {
-                        addIdentifier(codespace, id); // No .getCode() here.
+                    if (!isDeprecated(id)) {
+                        final String codespace = id.getCodeSpace();
+                        if (preferredCodespaces == null || preferredCodespaces.contains(codespace)) {
+                            addIdentifier(codespace, id); // No .getCode() here.
+                        }
                     }
                 }
             }
@@ -197,6 +202,13 @@ final class ParameterTableRow {
     }
 
     /**
+     * Returns {@code true} if the given name or identifier is deprecated.
+     */
+    private static boolean isDeprecated(final Object object) {
+        return (object instanceof Deprecable) && ((Deprecable) object).isDeprecated();
+    }
+
+    /**
      * Helper method for the constructor only, adding an identifier for the given code space.
      * As a side effect, this method remembers the length of the widest code space.
      */

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -31,6 +31,7 @@ import org.opengis.referencing.Identifie
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Citations;
+import org.apache.sis.util.Deprecable;
 import org.apache.sis.util.resources.Errors;
 
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -261,6 +262,64 @@ public abstract class Builder<B extends
     }
 
     /**
+     * Returns the name factory to use for creating namespaces and local names.
+     * The factory will be fetched when first needed, and while not change anymore
+     * for the rest of this {@code Builder} lifetime.
+     */
+    private NameFactory factory() {
+        if (nameFactory == null) {
+            nameFactory = DefaultFactories.forBuildin(NameFactory.class);
+        }
+        return nameFactory;
+    }
+
+    /**
+     * Creates or returns an existing name for the given string in the current namespace.
+     * The namespace may be cleared at anytime by a call to {@link #setCodeSpace(Citation, String)}.
+     */
+    private GenericName createName(final CharSequence name) {
+        final NameFactory factory = factory();
+        if (namespace == null) {
+            final String codespace = getCodeSpace();
+            if (codespace != null) {
+                namespace = factory.createNameSpace(factory.createLocalName(null, codespace), null);
+            }
+        }
+        return factory.createLocalName(namespace, name);
+    }
+
+    /**
+     * Creates or returns an existing name for the given string in the given namespace.
+     */
+    private GenericName createName(final Citation authority, final CharSequence name) {
+        if (authority == getAuthority()) {
+            return createName(name);
+        } else {
+            return new NamedIdentifier(authority, name);
+        }
+    }
+
+    /**
+     * Creates an identifier from a string for the given authority.
+     */
+    private Identifier createIdentifier(final Citation authority, final String identifier) {
+        if (authority == getAuthority()) {
+            return new ImmutableIdentifier(authority, getCodeSpace(), identifier, getVersion(), null);
+        } else {
+            // Do not use the version information since it applies to the default authority rather than the given one.
+            return new ImmutableIdentifier(authority, Citations.getUnicodeIdentifier(authority), identifier);
+        }
+    }
+
+    /**
+     * Converts the given name into an identifier. Note that {@link NamedIdentifier}
+     * implements both {@link GenericName} and {@link Identifier} interfaces.
+     */
+    private static Identifier toIdentifier(final GenericName name) {
+        return (name instanceof Identifier) ? (Identifier) name : new NamedIdentifier(name);
+    }
+
+    /**
      * Sets the property value for the given key, if a change is still possible. The check for change permission
      * is needed for all keys defined in the {@link Identifier} interface. This check is not needed for other keys,
      * so callers do not need to invoke this method for other keys.
@@ -285,30 +344,6 @@ public abstract class Builder<B extends
     }
 
     /**
-     * Returns the name factory to use for creating namespaces and local names.
-     */
-    private NameFactory factory() {
-        if (nameFactory == null) {
-            nameFactory = DefaultFactories.forBuildin(NameFactory.class);
-        }
-        return nameFactory;
-    }
-
-    /**
-     * Returns the namespace, creating it when first needed.
-     */
-    private NameSpace namespace() {
-        if (namespace == null) {
-            final String codespace = getCodeSpace();
-            if (codespace != null) {
-                final NameFactory factory = factory();
-                namespace = factory.createNameSpace(factory.createLocalName(null, codespace), null);
-            }
-        }
-        return namespace;
-    }
-
-    /**
      * Returns the value of the first argument given by the last call to {@link #setCodeSpace(Citation, String)},
      * or {@code null} if none. The default value is {@code null}.
      *
@@ -423,7 +458,7 @@ public abstract class Builder<B extends
         ensureNonNull("name", name);
         if (properties.putIfAbsent(IdentifiedObject.NAME_KEY, name.toString()) != null) {
             // A primary name is already present. Add the given name as an alias instead.
-            aliases.add(name instanceof GenericName ? (GenericName) name : factory().createLocalName(namespace(), name));
+            aliases.add(createName(name));
         }
         return self();
     }
@@ -512,7 +547,7 @@ public abstract class Builder<B extends
     public B addName(final GenericName name) {
         ensureNonNull("name", name);
         if (properties.get(IdentifiedObject.NAME_KEY) == null) {
-            properties.put(IdentifiedObject.NAME_KEY, (name instanceof Identifier) ? name : new NamedIdentifier(name));
+            properties.put(IdentifiedObject.NAME_KEY, toIdentifier(name));
         } else {
             aliases.add(name);
         }
@@ -577,8 +612,7 @@ public abstract class Builder<B extends
      */
     public B addIdentifier(final Citation authority, final String identifier) {
         ensureNonNull("identifier", identifier);
-        // Do not use the version information since it applies to the default authority rather than the given one.
-        identifiers.add(new ImmutableIdentifier(authority, Citations.getUnicodeIdentifier(authority), identifier));
+        identifiers.add(createIdentifier(authority, identifier));
         return self();
     }
 
@@ -624,6 +658,183 @@ public abstract class Builder<B extends
         return self();
     }
 
+    /**
+     * Returns {@code true} if the given name or identifier is deprecated.
+     */
+    private static boolean isDeprecated(final Object object) {
+        return (object instanceof Deprecable) && ((Deprecable) object).isDeprecated();
+    }
+
+    /**
+     * Adds all non-deprecated names and identifiers from the given object.
+     * Other properties like description and remarks are ignored.
+     *
+     * <p>This is a convenience method for using an existing object as a template, before to modify
+     * some names and identifiers by calls to {@link #replaceNames(Citation, CharSequence...)} or
+     * {@link #replaceIdentifiers(Citation, String...)}.</p>
+     *
+     * @param  object The object from which to copy the references to names and identifiers.
+     * @return {@code this}, for method call chaining.
+     *
+     * @since 0.6
+     */
+    public B addNamesAndIdentifiers(final IdentifiedObject object) {
+        ensureNonNull("object", object);
+        for (final Identifier id : object.getIdentifiers()) {
+            if (!isDeprecated(id)) {
+                addIdentifier(id);
+            }
+        }
+        Identifier id = object.getName();
+        if (!isDeprecated(id)) {
+            addName(id);
+        }
+        for (final GenericName alias : object.getAlias()) {
+            if (!isDeprecated(alias)) {
+                addName(alias);
+            }
+        }
+        return self();
+    }
+
+    /**
+     * Replaces the names associated to the given authority by the given new names.
+     * More specifically:
+     *
+     * <ul>
+     *   <li>The first occurrence of a name associated to {@code authority} will be replaced by a new name
+     *       with the same authority and the local part defined by {@code replacements[0]}.</li>
+     *   <li>The second occurrence of a name associated to {@code authority} will be replaced by a new name
+     *       with the same authority and the local part defined by {@code replacements[1]}.</li>
+     *   <li><i>etc.</i> until one of the following conditions is meet:
+     *     <ul>
+     *       <li>There is no more name associated to the given authority in this {@code Builder}, in which case
+     *           new names are inserted for all remaining elements in the {@code replacements} array.</li>
+     *       <li>There is no more elements in the {@code replacements} array, in which case all remaining
+     *           names associated to the given authority in this {@code Builder} are removed.</li>
+     *     </ul>
+     *   </li>
+     * </ul>
+     *
+     * @param  authority The authority of the names to replaces.
+     * @param  replacements The new local parts for the names to replace,
+     *         or {@code null} for removing all identifiers associated to the given authority.
+     * @return {@code this}, for method call chaining.
+     *
+     * @since 0.6
+     */
+    public B replaceNames(final Citation authority, final CharSequence... replacements) {
+        ensureNonNull("authority", authority);
+        final int length = (replacements != null) ? replacements.length : 0;
+        /*
+         * IdentifiedObjects store the "primary name" separately from aliases. Consequently we will start
+         * the iteration at index -1 where i=-1 is used as a sentinel value meaning "primary name" before
+         * to iterate over the aliases. Note that the type is not the same:
+         *
+         *   - Primary:   Identifier or String
+         *   - Aliases:   Identifier or GenericName
+         */
+        int next = 0;
+        int insertAt = aliases.size();
+        for (int i = -1; i < aliases.size(); i++) {
+            final Object name = (i < 0) ? properties.get(IdentifiedObject.NAME_KEY) : aliases.get(i);
+            if (name != null) {  // Actually only the primary name can be null.
+                final boolean isIdentifier = (name instanceof Identifier);
+                if (authority.equals(isIdentifier ? ((Identifier) name).getAuthority() : getAuthority())) {
+                    /*
+                     * Found a name associated to the given authority. Process to the replacement if we still
+                     * have some elements to take in the 'replacements' array, otherwise remove the name.
+                     */
+                    if (next < length) {
+                        final CharSequence code = replacements[next++];
+                        if (!code.toString().equals(isIdentifier ? ((Identifier) name).getCode() : name.toString())) {
+                            if (i < 0) {
+                                properties.put(IdentifiedObject.NAME_KEY, (authority != getAuthority())
+                                        ? new NamedIdentifier(authority, code) : code.toString());
+                            } else {
+                                aliases.set(i, createName(authority, code));
+                            }
+                            insertAt = i + 1;
+                        }
+                    } else {
+                        if (i < 0) {
+                            properties.remove(IdentifiedObject.NAME_KEY);
+                        } else {
+                            aliases.remove(i--);
+                        }
+                    }
+                }
+            }
+        }
+        /*
+         * If there is any remaining elements in the 'replacements' array, insert them right after the last
+         * element of the given authority that we found (so we keep together the names of the same authority).
+         */
+        while (next < length) {
+            aliases.add(insertAt++, createName(authority, replacements[next++]));
+        }
+        /*
+         * If the primary name has been removed as a result of this method execution,
+         * take the first alias as the new primary name.
+         */
+        if (properties.get(IdentifiedObject.NAME_KEY) == null && !aliases.isEmpty()) {
+            properties.put(IdentifiedObject.NAME_KEY, toIdentifier(aliases.remove(0)));
+        }
+        return self();
+    }
+
+    /**
+     * Replaces the identifiers associated to the given authority by the given new identifiers.
+     * More specifically:
+     *
+     * <ul>
+     *   <li>The first occurrence of an identifier associated to {@code authority} will be replaced by a new
+     *       identifier with the same authority and the code defined by {@code replacements[0]}.</li>
+     *   <li>The second occurrence of an identifier associated to {@code authority} will be replaced by a new
+     *       identifier with the same authority and the code defined by {@code replacements[1]}.</li>
+     *   <li><i>etc.</i> until one of the following conditions is meet:
+     *     <ul>
+     *       <li>There is no more identifier associated to the given authority in this {@code Builder}, in which case
+     *           new identifiers are inserted for all remaining elements in the {@code replacements} array.</li>
+     *       <li>There is no more elements in the {@code replacements} array, in which case all remaining
+     *           identifiers associated to the given authority in this {@code Builder} are removed.</li>
+     *     </ul>
+     *   </li>
+     * </ul>
+     *
+     * @param  authority The authority of the names to replaces.
+     * @param  replacements The new codes for the identifiers to replace,
+     *         or {@code null} for removing all identifiers associated to the given authority.
+     * @return {@code this}, for method call chaining.
+     *
+     * @since 0.6
+     */
+    public B replaceIdentifiers(final Citation authority, final String... replacements) {
+        ensureNonNull("authority", authority);
+        final int length = (replacements != null) ? replacements.length : 0;
+        int next = 0;
+        int insertAt = identifiers.size();
+        for (int i=0; i<identifiers.size();) {
+            final Identifier identifier = identifiers.get(i);
+            if (authority.equals(identifier.getAuthority())) {
+                if (next >= length) {
+                    identifiers.remove(i);
+                    continue; // Do not increment i.
+                }
+                final String code = replacements[next++];
+                if (!code.equals(identifier.getCode())) {
+                    identifiers.set(i, createIdentifier(authority, code));
+                    insertAt = i + 1;
+                }
+            }
+            i++;
+        }
+        while (next < length) {
+            identifiers.add(insertAt++, createIdentifier(authority, replacements[next++]));
+        }
+        return self();
+    }
+
     /**
      * Sets the parameter description as a {@code String} or {@code InternationalString} instance.
      * Calls to this method overwrite any previous value.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Thu Apr  2 21:05:35 2015
@@ -2,7 +2,8 @@
 # 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.LongitudeRotation
-org.apache.sis.internal.referencing.provider.Mercator1SP
+org.apache.sis.internal.referencing.provider.EquidistantCylindrical
 org.apache.sis.internal.referencing.provider.Mercator2SP
+org.apache.sis.internal.referencing.provider.Mercator1SP
 org.apache.sis.internal.referencing.provider.PseudoMercator
 org.apache.sis.internal.referencing.provider.MillerCylindrical

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -19,7 +19,8 @@ package org.apache.sis.internal.referenc
 import java.util.Map;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
-import java.util.ServiceLoader;
+import org.opengis.util.GenericName;
+import org.opengis.metadata.Identifier;
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.OperationMethod;
@@ -45,31 +46,70 @@ import static org.junit.Assert.*;
 })
 public final strictfp class AllProvidersTest extends TestCase {
     /**
-     * Returns all registered operation methods.
+     * Returns all providers to test.
      */
-    private static Iterable<OperationMethod> methods() {
-        return ServiceLoader.load(OperationMethod.class, AbstractProvider.class.getClassLoader());
+    private static Class<?>[] methods() {
+        return new Class<?>[] {
+            Affine.class,
+            LongitudeRotation.class,
+            EquidistantCylindrical.class,
+            Mercator2SP.class,
+            Mercator1SP.class,
+            PseudoMercator.class,
+            MillerCylindrical.class
+        };
     }
 
     /**
      * Ensures that every parameter instance is unique. Actually this test is not strong requirement.
      * This is only for sharing existing resources by avoiding unnecessary objects duplication.
+     *
+     * @throws ReflectiveOperationException if the instantiation of a service provider failed.
      */
     @Test
-    public void ensureParameterUniqueness() {
+    public void ensureParameterUniqueness() throws ReflectiveOperationException {
         final Map<GeneralParameterDescriptor, String> groupNames = new IdentityHashMap<>();
-        final Map<GeneralParameterDescriptor, GeneralParameterDescriptor> existings = new HashMap<>();
-        for (final OperationMethod method : methods()) {
+        final Map<GeneralParameterDescriptor, GeneralParameterDescriptor> parameters = new HashMap<>();
+        final Map<Object, Object> namesAndIdentifiers = new HashMap<>();
+        for (final Class<?> c : methods()) {
+            final OperationMethod method = (OperationMethod) c.newInstance();
             final ParameterDescriptorGroup group = method.getParameters();
-            final String name = group.getName().getCode();
+            final String operationName = group.getName().getCode();
             for (final GeneralParameterDescriptor param : group.descriptors()) {
-                assertFalse("Parameter declared twice in the same group.", name.equals(groupNames.put(param, name)));
-                final GeneralParameterDescriptor existing = existings.put(param, param);
+                assertFalse("Parameter declared twice in the same group.",
+                        operationName.equals(groupNames.put(param, operationName)));
+                /*
+                 * Ensure uniqueness of the parameter descriptor as a whole.
+                 */
+                final Identifier name = param.getName();
+                Object existing = parameters.put(param, param);
                 if (existing != null && existing != param) {
-                    fail("Parameter “" + param.getName().getCode() + "” defined in “" + name + '”'
+                    fail("Parameter “" + name.getCode() + "” defined in “" + operationName + '”'
                             + " was already defined in “" + groupNames.get(existing) + "”."
                             + " The same instance could be shared.");
                 }
+                /*
+                 * Ensure uniqueness of each name and identifier.
+                 */
+                existing = namesAndIdentifiers.put(name, name);
+                if (existing != null && existing != name) {
+                    fail("The name of parameter “" + name.getCode() + "” defined in “" + operationName + '”'
+                            + " was already defined elsewhere. The same instance could be shared.");
+                }
+                for (final GenericName alias : param.getAlias()) {
+                    existing = namesAndIdentifiers.put(alias, alias);
+                    if (existing != null && existing != alias) {
+                        fail("Alias “" + alias + "” of parameter “" + name.getCode() + "” defined in “" + operationName + '”'
+                                + " was already defined elsewhere. The same instance could be shared.");
+                    }
+                }
+                for (final Identifier id : param.getIdentifiers()) {
+                    existing = namesAndIdentifiers.put(id, id);
+                    if (existing != null && existing != id) {
+                        fail("Identifier “" + id + "” of parameter “" + name.getCode() + "” defined in “" + operationName + '”'
+                                + " was already defined elsewhere. The same instance could be shared.");
+                    }
+                }
             }
         }
     }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderMock.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderMock.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderMock.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderMock.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -16,6 +16,10 @@
  */
 package org.apache.sis.referencing;
 
+import org.opengis.metadata.Identifier;
+import org.opengis.referencing.IdentifiedObject;
+import org.opengis.util.GenericName;
+
 
 /**
  * A {@link Builder} that doesn't build anything. Such builder is useless and is defined here
@@ -23,8 +27,45 @@ package org.apache.sis.referencing;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 final strictfp class BuilderMock extends Builder<BuilderMock> {
+    /**
+     * Convenience accessor for the property value assigned to {@link IdentifiedObject#NAME_KEY}.
+     */
+    Object getName() {
+        return properties.get(IdentifiedObject.NAME_KEY);
+    }
+
+    /**
+     * Convenience accessor for the property value assigned to {@link IdentifiedObject#ALIAS_KEY}.
+     */
+    GenericName[] getAliases() {
+        return (GenericName[]) properties.get(IdentifiedObject.ALIAS_KEY);
+    }
+
+    /**
+     * Convenience accessor for the property value assigned to {@link IdentifiedObject#IDENTIFIERS_KEY}.
+     */
+    Identifier[] getIdentifiers() {
+        return (Identifier[]) properties.get(IdentifiedObject.IDENTIFIERS_KEY);
+    }
+
+    /**
+     * Convenience accessor for aliases or identifiers as strings.
+     *
+     * @param kind 0 for identifiers, or 1 for names.
+     */
+    String[] getAsStrings(final int kind) {
+        final Object[] values = (kind == 0) ? getIdentifiers() : getAliases();
+        final String[] s = new String[values.length + kind];
+        if (kind != 0) {
+            s[0] = getName().toString();
+        }
+        for (int i=0; i<values.length; i++) {
+            s[i + kind] = values[i].toString();
+        }
+        return s;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java [UTF-8] Thu Apr  2 21:05:35 2015
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.referencing;
 
+import java.util.Map;
 import org.opengis.util.NameSpace;
 import org.opengis.util.LocalName;
 import org.opengis.util.GenericName;
@@ -25,11 +26,11 @@ import org.opengis.metadata.Identifier;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
-import static org.opengis.referencing.IdentifiedObject.*;
 import static org.apache.sis.metadata.iso.citation.HardCodedCitations.*;
 
 
@@ -38,9 +39,10 @@ import static org.apache.sis.metadata.is
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
+@DependsOn(AbstractIdentifiedObjectTest.class)
 public final strictfp class BuilderTest extends TestCase {
     /**
      * Tests {@link Builder#verifyParameterizedType(Class)}.
@@ -99,7 +101,7 @@ public final strictfp class BuilderTest
      * Tests {@link Builder#addName(CharSequence)} without codespace.
      */
     @Test
-    public void testUnscopedName() {
+    public void testAddName() {
         final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
 
         // Expected values to be used later in the test.
@@ -118,17 +120,41 @@ public final strictfp class BuilderTest
         assertSame(builder, builder.addName("Mercator_1SP"));           // OGC
         assertSame(builder, builder.addName("CT_Mercator"));            // GeoTIFF
         builder.onCreate(false);
-        assertEquals(name, builder.properties.get(NAME_KEY));
-        assertArrayEquals(new GenericName[] {alias1, alias2, alias3},
-                (GenericName[]) builder.properties.get(ALIAS_KEY));
+        assertEquals(name, builder.getName());
+        assertArrayEquals(new GenericName[] {alias1, alias2, alias3}, builder.getAliases());
+    }
+
+    /**
+     * Creates a {@link Builder} with <cite>"Mercator (variant A)"</cite> projection (EPSG:9804) names and identifiers.
+     * This method uses scopes for differentiating the EPSG names from the OGC and GeoTIFF ones.
+     *
+     * @param  withNames       {@code true} for adding the names in the builder.
+     * @param  withIdentifiers {@code true} for adding the identifiers in the builder.
+     * @return The builder with Mercator names and/or identifiers.
+     */
+    private static BuilderMock createMercator(final boolean withNames, final boolean withIdentifiers) {
+        final BuilderMock builder = new BuilderMock();
+        assertSame(builder, builder.setCodeSpace(OGP, "EPSG"));
+        if (withNames) {
+            assertSame(builder, builder.addName(         "Mercator (variant A)")); // EPSG version 7.6 and later.
+            assertSame(builder, builder.addName(         "Mercator (1SP)"));       // EPSG before version 7.6.
+            assertSame(builder, builder.addName(OGC,     "Mercator_1SP"));
+            assertSame(builder, builder.addName(GEOTIFF, "CT_Mercator"));
+        }
+        if (withIdentifiers) {
+            assertSame(builder, builder.addIdentifier(      "9804"));
+            assertSame(builder, builder.addIdentifier(GEOTIFF, "7"));
+        }
+        builder.onCreate(false);
+        return builder;
     }
 
     /**
      * Tests {@link Builder#addName(Citation, CharSequence)} and {@link Builder#addName(CharSequence)} with codespace.
      */
     @Test
-    @DependsOnMethod({"testUnscopedName", "testSetCodeSpace"})
-    public void testScopedName() {
+    @DependsOnMethod({"testAddName", "testSetCodeSpace"})
+    public void testAddNameWithScope() {
         final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
 
         // Expected values to be used later in the test.
@@ -142,16 +168,9 @@ public final strictfp class BuilderTest
         assertEquals("EPSG",                 alias1.scope().name().toString());
 
         // The test.
-        final BuilderMock builder = new BuilderMock();
-        assertSame(builder, builder.setCodeSpace(OGP, "EPSG"));
-        assertSame(builder, builder.addName(          "Mercator (variant A)"));
-        assertSame(builder, builder.addName(          "Mercator (1SP)"));
-        assertSame(builder, builder.addName(OGC,      "Mercator_1SP"));
-        assertSame(builder, builder.addName(GEOTIFF,  "CT_Mercator"));
-        builder.onCreate(false);
-        assertEquals(name, builder.properties.get(NAME_KEY));
-        assertArrayEquals(new GenericName[] {alias1, alias2, alias3},
-                (GenericName[]) builder.properties.get(ALIAS_KEY));
+        final BuilderMock builder = createMercator(true, false);
+        assertEquals(name, builder.getName());
+        assertArrayEquals(new GenericName[] {alias1, alias2, alias3}, builder.getAliases());
     }
 
     /**
@@ -166,7 +185,7 @@ public final strictfp class BuilderTest
      * with codespace.
      */
     @Test
-    public void testIdentifiers() {
+    public void testAddIdentifiers() {
         // Expected values to be used later in the test.
         final Identifier id1 = new ImmutableIdentifier(OGP,     "EPSG",    "9804");
         final Identifier id2 = new ImmutableIdentifier(GEOTIFF, "GeoTIFF", "7");
@@ -174,11 +193,126 @@ public final strictfp class BuilderTest
         assertEquals("GeoTIFF:7", IdentifiedObjects.toString(id2));
 
         // The test.
-        final BuilderMock builder = new BuilderMock();
-        assertSame(builder, builder.setCodeSpace (OGP,  "EPSG"));
-        assertSame(builder, builder.addIdentifier(      "9804"));
-        assertSame(builder, builder.addIdentifier(GEOTIFF, "7"));
+        final BuilderMock builder = createMercator(false, true);
+        assertArrayEquals(new Identifier[] {id1, id2}, builder.getIdentifiers());
+    }
+
+    /**
+     * Tests {@link Builder#addNamesAndIdentifiers(IdentifiedObject)}.
+     *
+     * @since 0.6
+     */
+    @Test
+    @DependsOnMethod({"testAddNameWithScope", "testAddIdentifiers"})
+    public void testAddNamesAndIdentifiers() {
+        final BuilderMock builder = createMercator(true, true);
+        final AbstractIdentifiedObject object = new AbstractIdentifiedObject(builder.properties);
+        builder.onCreate(true);
+        for (final Map.Entry<String,?> entry : builder.properties.entrySet()) {
+            final Object value = entry.getValue();
+            switch (entry.getKey()) {
+                case Identifier.AUTHORITY_KEY: {
+                    assertSame("Authority and codespace shall be unchanged.", OGP, value);
+                    break;
+                }
+                case Identifier.CODESPACE_KEY: {
+                    assertEquals("Authority and codespace shall be unchanged.", "EPSG", value);
+                    break;
+                }
+                default: {
+                    assertNull("Should not contain any non-null value except the authority.", value);
+                    break;
+                }
+            }
+        }
+        assertSame(builder, builder.addNamesAndIdentifiers(object));
+        builder.onCreate(false);
+        assertSame       ("name",        object.getName(),                  builder.getName());
+        assertArrayEquals("aliases",     object.getAlias().toArray(),       builder.getAliases());
+        assertArrayEquals("identifiers", object.getIdentifiers().toArray(), builder.getIdentifiers());
+    }
+
+    /**
+     * Tests {@link Builder#replaceNames(Citation, CharSequence...)}.
+     *
+     * <div class="note">This test depends on {@link #testReplaceIdentifiers()} because
+     * {@code replaceIdentifiers} implementation is simpler than {@code replaceNames}.</div>
+     *
+     * @since 0.6
+     */
+    @Test
+    @DependsOnMethod("testReplaceIdentifiers")  // See javadoc.
+    public void testReplaceNames() {
+        final BuilderMock builder = createMercator(true, false);
+
+        // Replace "OGC:Mercator_1SP" and insert a new OGC code before the GeoTIFF one.
+        assertSame(builder, builder.replaceNames(OGC, "Replacement 1", "Replacement 2"));
+        builder.onCreate(false);
+        assertArrayEquals(new String[] {
+            "Mercator (variant A)",
+            "Mercator (1SP)",
+            "OGC:Replacement 1",
+            "OGC:Replacement 2",
+            "GeoTIFF:CT_Mercator"
+        }, builder.getAsStrings(1));
+
+        // Replace "EPSG:Mercator (variant A)" and "(1SP)", and insert a new EPSG code as an alias.
+        assertSame(builder, builder.replaceNames(OGP, "Replacement 3", "Replacement 4", "Replacement 5"));
+        builder.onCreate(false);
+        assertArrayEquals(new String[] {
+            "Replacement 3",
+            "Replacement 4",
+            "Replacement 5",
+            "OGC:Replacement 1",
+            "OGC:Replacement 2",
+            "GeoTIFF:CT_Mercator"
+        }, builder.getAsStrings(1));
+
+        // Remove all EPSG codes.
+        assertSame(builder, builder.replaceNames(OGP, (String[]) null));
+        builder.onCreate(false);
+        assertArrayEquals(new String[] {
+            "OGC:Replacement 1",
+            "OGC:Replacement 2",
+            "GeoTIFF:CT_Mercator"
+        }, builder.getAsStrings(1));
+    }
+
+    /**
+     * Tests {@link Builder#replaceNames(Citation, CharSequence...)}.
+     *
+     * @since 0.6
+     */
+    @Test
+    @DependsOnMethod("testAddNamesAndIdentifiers")
+    public void testReplaceIdentifiers() {
+        final BuilderMock builder = createMercator(false, true);
+
+        // Replace "GeoTIFF:7" and append a new GeoTIFF code at the end of the list.
+        assertSame(builder, builder.replaceIdentifiers(GEOTIFF, "Replacement 1", "Replacement 2"));
+        builder.onCreate(false);
+        assertArrayEquals(new String[] {
+            "Id[\"EPSG\", 9804, Citation[\"OGP\"]]",
+            "Id[\"GeoTIFF\", \"Replacement 1\"]",
+            "Id[\"GeoTIFF\", \"Replacement 2\"]"
+        }, builder.getAsStrings(0));
+
+        // Replace "EPSG:9804" and insert a new EPSG code as an alias.
+        assertSame(builder, builder.replaceIdentifiers(OGP, "Replacement 3", "Replacement 4"));
+        builder.onCreate(false);
+        assertArrayEquals(new String[] {
+            "Id[\"EPSG\", \"Replacement 3\", Citation[\"OGP\"]]",
+            "Id[\"EPSG\", \"Replacement 4\", Citation[\"OGP\"]]",
+            "Id[\"GeoTIFF\", \"Replacement 1\"]",
+            "Id[\"GeoTIFF\", \"Replacement 2\"]"
+        }, builder.getAsStrings(0));
+
+        // Remove all EPSG codes.
+        assertSame(builder, builder.replaceIdentifiers(OGP, (String[]) null));
         builder.onCreate(false);
-        assertArrayEquals(new Identifier[] {id1, id2}, (Identifier[]) builder.properties.get(IDENTIFIERS_KEY));
+        assertArrayEquals(new String[] {
+            "Id[\"GeoTIFF\", \"Replacement 1\"]",
+            "Id[\"GeoTIFF\", \"Replacement 2\"]"
+        }, builder.getAsStrings(0));
     }
 }

Modified: sis/branches/JDK8/ide-project/NetBeans/nbproject/genfiles.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/ide-project/NetBeans/nbproject/genfiles.properties?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/ide-project/NetBeans/nbproject/genfiles.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/ide-project/NetBeans/nbproject/genfiles.properties [ISO-8859-1] Thu Apr  2 21:05:35 2015
@@ -3,6 +3,6 @@
 build.xml.data.CRC32=58e6b21c
 build.xml.script.CRC32=462eaba0
 build.xml.stylesheet.CRC32=28e38971@1.53.1.46
-nbproject/build-impl.xml.data.CRC32=efed6ae2
+nbproject/build-impl.xml.data.CRC32=21ae62d4
 nbproject/build-impl.xml.script.CRC32=fc0a5456
-nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48
+nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48

Modified: sis/branches/JDK8/ide-project/NetBeans/nbproject/project.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/ide-project/NetBeans/nbproject/project.xml?rev=1670967&r1=1670966&r2=1670967&view=diff
==============================================================================
--- sis/branches/JDK8/ide-project/NetBeans/nbproject/project.xml (original)
+++ sis/branches/JDK8/ide-project/NetBeans/nbproject/project.xml Thu Apr  2 21:05:35 2015
@@ -58,6 +58,7 @@
             </reference>
         </references>
         <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1">
+            <word>accessor</word>
             <word>bitmask</word>
             <word>classname</word>
             <word>classnames</word>



Mime
View raw message