sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1724141 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ sis-referencing/src/main/java/org/apache/sis/referencing/ ...
Date Mon, 11 Jan 2016 23:00:55 GMT
Author: desruisseaux
Date: Mon Jan 11 23:00:55 2016
New Revision: 1724141

URL: http://svn.apache.org/viewvc?rev=1724141&view=rev
Log:
Begin support of authority codes in the "AUTO2" namespace.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
      - copied, changed from r1724140, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java
Removed:
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java

Copied: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java (from r1724140, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java&p1=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java&r1=1724140&r2=1724141&rev=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/GeodeticObjectBuilder.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -14,58 +14,67 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.referencing;
+package org.apache.sis.internal.referencing;
 
 import javax.measure.unit.Unit;
-import javax.measure.quantity.Length;
+import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.parameter.InvalidParameterValueException;
+import org.opengis.referencing.crs.CRSFactory;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.cs.CartesianCS;
-import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.Conversion;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.util.NoSuchIdentifierException;
-import org.opengis.util.FactoryException;
-import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.referencing.crs.DefaultProjectedCRS;
-import org.apache.sis.referencing.operation.DefaultConversion;
-import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
-import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.referencing.provider.TransverseMercator;
+import org.apache.sis.referencing.Builder;
 
 
 /**
  * Helper methods for building Coordinate Reference Systems and related objects.
  *
- * <p>For now, this class is defined in the test directory because this API needs more experimentation.
- * However this class may move in the main source directory later if we feel confident that its API is
- * mature enough.</p>
+ * <p>For now, this class is defined in the internal package because this API needs more experimentation.
+ * However this class may move in a public package later if we feel confident that its API is mature enough.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
  * @version 0.7
  * @module
  */
-public strictfp class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder> {
+public class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder> {
     /**
-     * The name of the conversion used by {@code ProjectedCRS} or {@code DerivedCRS},
-     * or {@code null} if unspecified.
+     * The name of the conversion to use for creating a {@code ProjectedCRS} or {@code DerivedCRS}.
+     * This name is for information purpose; its value does not impact the numerical results of coordinate operations.
+     *
+     * @see #setConversionName(String)
      */
     private String conversionName;
 
     /**
+     * The conversion method used by {@code ProjectedCRS} or {@code DerivedCRS}, or {@code null} if unspecified.
+     *
+     * @see #setConversionMethod(String)
+     */
+    private OperationMethod method;
+
+    /**
      * The projection parameters, or {@code null} if not applicable.
      */
     private ParameterValueGroup parameters;
 
     /**
-     * The math transform factory, fetched when first needed.
+     * The factor for Coordinate Reference System objects, fetched when first needed.
      */
-    private MathTransformFactory mtFactory;
+    private CRSFactory crsFactory;
+
+    /**
+     * The factor for Coordinate Operation objects, fetched when first needed.
+     */
+    private CoordinateOperationFactory copFactory;
 
     /**
      * Creates a new builder.
@@ -74,13 +83,23 @@ public strictfp class GeodeticObjectBuil
     }
 
     /**
-     * Returns the math transform factory. This method fetch the factory when first needed.
+     * Returns the factory for Coordinate Reference System objects. This method fetches the factory when first needed.
+     */
+    private CRSFactory getCRSFactory() {
+        if (crsFactory == null) {
+            crsFactory = DefaultFactories.forBuildin(CRSFactory.class);
+        }
+        return crsFactory;
+    }
+
+    /**
+     * Returns the factory for Coordinate Operation objects. This method fetches the factory when first needed.
      */
-    private MathTransformFactory getMathTransformFactory() {
-        if (mtFactory == null) {
-            mtFactory = DefaultFactories.forBuildin(MathTransformFactory.class);
+    private CoordinateOperationFactory getCoordinateOperationFactory() {
+        if (copFactory == null) {
+            copFactory = DefaultFactories.forBuildin(CoordinateOperationFactory.class);
         }
-        return mtFactory;
+        return copFactory;
     }
 
     /**
@@ -98,15 +117,16 @@ public strictfp class GeodeticObjectBuil
      *
      * This method can be invoked only once.
      *
-     * @param  method Name of the conversion method.
+     * @param  name Name of the conversion method.
      * @return {@code this}, for method call chaining.
-     * @throws NoSuchIdentifierException if the given name is unknown to the math transform factory.
+     * @throws FactoryException if the operation method of the given name can not be obtained.
      */
-    public GeodeticObjectBuilder setConversionMethod(final String method) throws NoSuchIdentifierException {
-        if (parameters != null) {
+    public GeodeticObjectBuilder setConversionMethod(final String name) throws FactoryException {
+        if (method != null) {
             throw new IllegalStateException(Errors.format(Errors.Keys.ElementAlreadyPresent_1, "OperationMethod"));
         }
-        parameters = getMathTransformFactory().getDefaultParameters(method);
+        method = getCoordinateOperationFactory().getOperationMethod(name);
+        parameters = method.getParameters().createValue();
         return this;
     }
 
@@ -152,6 +172,41 @@ public strictfp class GeodeticObjectBuil
     }
 
     /**
+     * Sets the operation method, parameters and conversion name for a Transverse Mercator projection.
+     * This convenience method delegates to the following methods:
+     *
+     * <ul>
+     *   <li>{@link #setConversionName(String)} with a name like <cite>"Transverse Mercator"</cite>
+     *       or <cite>"UTM zone 10N"</cite>, depending on the arguments given to this method.</li>
+     *   <li>{@link #setConversionMethod(String)} with the name of the Transverse Mercator projection method.</li>
+     *   <li>{@link #setParameter(String, double, Unit)} for each of the parameters enumerated below:</li>
+     * </ul>
+     *
+     * <blockquote><table class="sis">
+     *   <caption>Transverse Mercator parameters</caption>
+     *   <tr><th>Parameter name</th>                 <th>Value</th></tr>
+     *   <tr><td>Latitude of natural origin</td>     <td>0°</td></tr>
+     *   <tr><td>Longitude of natural origin</td>    <td>Central meridian, optionally snapped to a UTM zone</td></tr>
+     *   <tr><td>Scale factor at natural origin</td> <td>0.9996</td></tr>
+     *   <tr><td>False easting</td>                  <td>500000 metres</td></tr>
+     *   <tr><td>False northing</td>                 <td>0 (North hemisphere) or 10000000 (South hemisphere) metres</td></tr>
+     * </table></blockquote>
+     *
+     * @param  centralMeridian  The longitude in the center of the desired projection.
+     * @param  isUTM            If {@code true}, the given central meridian will be snapped to the central meridian of a UTM zone.
+     * @param  isSouth          {@code false} for a projection in the North hemisphere, or {@code true} for the South hemisphere.
+     * @return {@code this}, for method call chaining.
+     * @throws FactoryException if the operation method for the Transverse Mercator projection can not be obtained.
+     */
+    public GeodeticObjectBuilder setTransverseMercator(double centralMeridian, boolean isUTM, final boolean isSouth)
+            throws FactoryException
+    {
+        setConversionMethod("Transverse_Mercator");
+        setConversionName(TransverseMercator.setParameters(parameters, centralMeridian, isUTM, isSouth));
+        return this;
+    }
+
+    /**
      * Creates a projected CRS using a conversion built from the values given by the {@code setParameter(…)} calls.
      *
      * <div class="note"><b>Example:</b>
@@ -181,21 +236,6 @@ public strictfp class GeodeticObjectBuil
      */
     public ProjectedCRS createProjectedCRS(final GeographicCRS baseCRS, final CartesianCS derivedCS) throws FactoryException {
         ensureConversionMethodSet();
-        final Ellipsoid ellipsoid = baseCRS.getDatum().getEllipsoid();
-        final MathTransformFactory mtFactory = getMathTransformFactory();
-        final MathTransform mt;
-        if (mtFactory instanceof DefaultMathTransformFactory) {
-            // The Apache SIS implementation avoid to override any value explicitely set by the user.
-            final DefaultMathTransformFactory.Context context = new DefaultMathTransformFactory.Context();
-            context.setSource(ellipsoid);
-            mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform(parameters, context);
-        } else {
-            // Fallback for non-SIS implementations.
-            final Unit<Length> unit = ellipsoid.getAxisUnit();
-            parameters.parameter(Constants.SEMI_MAJOR).setValue(ellipsoid.getSemiMajorAxis(), unit);
-            parameters.parameter(Constants.SEMI_MINOR).setValue(ellipsoid.getSemiMinorAxis(), unit);
-            mt = mtFactory.createParameterizedTransform(parameters);
-        }
         onCreate(false);
         try {
             /*
@@ -206,7 +246,7 @@ public strictfp class GeodeticObjectBuil
             final Object name = (conversionName != null) ? properties.put(Conversion.NAME_KEY, conversionName) : null;
             final Object alias = properties.put(Conversion.ALIAS_KEY, null);
             final Object identifier = properties.put(Conversion.IDENTIFIERS_KEY, null);
-            final Conversion conversion = new DefaultConversion(properties, mtFactory.getLastMethodUsed(), mt, parameters);
+            final Conversion conversion = getCoordinateOperationFactory().createDefiningConversion(properties, method, parameters);
             /*
              * Restore the original properties and create the final ProjectedCRS.
              */
@@ -215,7 +255,7 @@ public strictfp class GeodeticObjectBuil
             if (name != null) {
                 properties.put(Conversion.NAME_KEY, name);
             }
-            return new DefaultProjectedCRS(properties, baseCRS, conversion, derivedCS);
+            return getCRSFactory().createProjectedCRS(properties, baseCRS, conversion, derivedCS);
         } finally {
             onCreate(true);
         }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -16,13 +16,19 @@
  */
 package org.apache.sis.internal.referencing.provider;
 
+import javax.measure.unit.Unit;
+import javax.measure.unit.SI;
+import javax.measure.unit.NonSI;
 import javax.xml.bind.annotation.XmlTransient;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterValueGroup;
+import org.apache.sis.measure.Longitude;
+import org.apache.sis.parameter.Parameters;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.operation.projection.NormalizedProjection;
+import org.apache.sis.internal.util.Constants;
 
 
 /**
@@ -31,7 +37,7 @@ import org.apache.sis.referencing.operat
  * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
  * @author  Rueben Schulz (UBC)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see <a href="http://www.remotesensing.org/geotiff/proj_list/transverse_mercator.html">Transverse Mercator on RemoteSensing.org</a>
@@ -44,6 +50,14 @@ public final class TransverseMercator ex
     private static final long serialVersionUID = -3386587506686432398L;
 
     /**
+     * Width of a Universal Transverse Mercator (UTM) zone, in degrees.
+     *
+     * @see #zone(double)
+     * @see #centralMeridian(int)
+     */
+    private static final double ZONE_WIDTH = 6;
+
+    /**
      * 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°.
      */
@@ -119,4 +133,79 @@ public final class TransverseMercator ex
     protected NormalizedProjection createProjection(final Parameters parameters) {
         return new org.apache.sis.referencing.operation.projection.TransverseMercator(this, parameters);
     }
+
+    /**
+     * Sets the parameter values for a Transverse Mercator projection and returns a suggested conversion name.
+     *
+     * <blockquote><table class="sis">
+     *   <caption>Transverse Mercator parameters</caption>
+     *   <tr><th>Parameter name</th>                 <th>Value</th></tr>
+     *   <tr><td>Latitude of natural origin</td>     <td>0°</td></tr>
+     *   <tr><td>Longitude of natural origin</td>    <td>Central meridian, optionally snapped to a UTM zone</td></tr>
+     *   <tr><td>Scale factor at natural origin</td> <td>0.9996</td></tr>
+     *   <tr><td>False easting</td>                  <td>500000 metres</td></tr>
+     *   <tr><td>False northing</td>                 <td>0 (North hemisphere) or 10000000 (South hemisphere) metres</td></tr>
+     * </table></blockquote>
+     *
+     * @param  group            The parameters for which to set the values.
+     * @param  centralMeridian  The longitude in the center of the desired projection.
+     * @param  isUTM            If {@code true}, the given central meridian will be snapped to the central meridian of a UTM zone.
+     * @param  isSouth          {@code false} for a projection in the North hemisphere, or {@code true} for the South hemisphere.
+     * @return A name like <cite>"Transverse Mercator"</cite> or <cite>"UTM zone 10N"</cite>,
+     *         depending on the arguments given to this method.
+     *
+     * @since 0.7
+     */
+    public static String setParameters(final ParameterValueGroup group,
+            double centralMeridian, final boolean isUTM, final boolean isSouth)
+    {
+        int zone = zone(centralMeridian);
+        if (isUTM) {
+            centralMeridian = centralMeridian(zone);
+        } else if (centralMeridian != centralMeridian(zone)) {
+            zone = 0;
+        }
+        String name = "Transverse Mercator";
+        if (zone != 0) {
+            name = "UTM zone " + zone + (isSouth ? 'S' : 'N');
+        }
+        group.parameter("latitude_of_origin")       .setValue(0, NonSI.DEGREE_ANGLE);
+        group.parameter(Constants.CENTRAL_MERIDIAN) .setValue(centralMeridian, NonSI.DEGREE_ANGLE);
+        group.parameter(Constants.SCALE_FACTOR)     .setValue(0.9996, Unit.ONE);
+        group.parameter(Constants.FALSE_EASTING)    .setValue(500000, SI.METRE);
+        group.parameter(Constants.FALSE_NORTHING)   .setValue(isSouth ? 10000000 : 0, SI.METRE);
+        return name;
+    }
+
+    /**
+     * Computes the UTM zone from a meridian in the zone.
+     *
+     * @param  centralMeridian A meridian inside the desired zone, in degrees relative to Greenwich.
+     *         Positive longitudes are toward east, and negative longitudes toward west.
+     * @return The UTM zone number numbered from 1 to 60 inclusive, or 0 if the given central meridian was NaN.
+     *
+     * @since 0.7
+     */
+    public static int zone(double centralMeridian) {
+        /*
+         * Casts to int are equivalent to Math.floor(double) for positive values, which is guaranteed
+         * to be the case here since we normalize the central meridian to the [MIN_VALUE … MAX_VALUE] range.
+         */
+        double z = (centralMeridian - Longitude.MIN_VALUE) / ZONE_WIDTH;                    // Zone number with fractional part.
+        z -= Math.floor(z / ((Longitude.MAX_VALUE - Longitude.MIN_VALUE) / ZONE_WIDTH))     // Roll in the [0 … 60) range.
+                          * ((Longitude.MAX_VALUE - Longitude.MIN_VALUE) / ZONE_WIDTH);
+        return (int) (z + 1);   // Cast only after addition in order to handle NaN as documented.
+    }
+
+    /**
+     * Computes the central meridian of a given UTM zone.
+     *
+     * @param zone The UTM zone as a number in the [1 … 60] range.
+     * @return The central meridian of the given UTM zone.
+     *
+     * @since 0.7
+     */
+    public static double centralMeridian(final int zone) {
+        return (zone - 0.5) * ZONE_WIDTH + Longitude.MIN_VALUE;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -18,6 +18,7 @@ package org.apache.sis.referencing;
 
 import java.util.Map;
 import java.util.Date;
+import java.util.HashMap;
 import javax.measure.unit.SI;
 import javax.measure.unit.NonSI;
 import javax.measure.unit.Unit;
@@ -32,7 +33,9 @@ import org.opengis.referencing.crs.Verti
 import org.opengis.referencing.crs.TemporalCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.GeocentricCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.CRSAuthorityFactory;
 import org.opengis.referencing.cs.TimeCS;
 import org.opengis.referencing.cs.VerticalCS;
 import org.opengis.referencing.cs.CartesianCS;
@@ -45,7 +48,6 @@ import org.opengis.referencing.datum.Ver
 import org.opengis.referencing.datum.VerticalDatumType;
 import org.opengis.referencing.datum.TemporalDatum;
 import org.opengis.referencing.datum.DatumAuthorityFactory;
-import org.opengis.referencing.crs.CRSAuthorityFactory;
 import org.apache.sis.referencing.datum.DefaultVerticalDatum;
 import org.apache.sis.referencing.datum.DefaultTemporalDatum;
 import org.apache.sis.referencing.cs.AxesConvention;
@@ -56,6 +58,7 @@ import org.apache.sis.referencing.crs.De
 import org.apache.sis.referencing.crs.DefaultVerticalCRS;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.crs.DefaultGeocentricCRS;
+import org.apache.sis.internal.referencing.provider.TransverseMercator;
 import org.apache.sis.internal.system.SystemListener;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.system.Loggers;
@@ -115,7 +118,7 @@ import static org.apache.sis.internal.ut
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.referencing.factory.CommonAuthorityFactory
@@ -138,7 +141,8 @@ public enum CommonCRS {
      *   <tr><th>Ellipsoid axes unit:</th>     <td>{@link SI#METRE}</td></tr>
      * </table></blockquote>
      */
-    WGS84((short) 4326, (short) 4979, (short) 4978, (short) 6326, (short) 7030),
+    WGS84((short) 4326, (short) 4979, (short) 4978, (short) 6326, (short) 7030,     // Geodetic info
+          (short) 32600, (short) 32700, (byte) 1, (byte) 60),                       // UTM info
 
     /**
      * World Geodetic System 1972.
@@ -154,7 +158,8 @@ public enum CommonCRS {
      *   <tr><th>Ellipsoid axes unit:</th>     <td>{@link SI#METRE}</td></tr>
      * </table></blockquote>
      */
-    WGS72((short) 4322, (short) 4985, (short) 4984, (short) 6322, (short) 7043),
+    WGS72((short) 4322, (short) 4985, (short) 4984, (short) 6322, (short) 7043,     // Geodetic info
+          (short) 32200, (short) 32300, (byte) 1, (byte) 60),                       // UTM info
 
     /**
      * North American Datum 1983.
@@ -178,7 +183,8 @@ public enum CommonCRS {
      * The <cite>Web Map Server</cite> {@code "CRS:83"} authority code uses the NAD83 datum,
      * while the {@code "IGNF:MILLER"} authority code uses the GRS80 datum.</div>
      */
-    NAD83((short) 4269, (short) 0, (short) 0, (short) 6269, (short) 7019),
+    NAD83((short) 4269, (short) 0, (short) 0, (short) 6269, (short) 7019,           // Geodetic info
+          (short) 26900, (short) 0, (byte) 1, (byte) 23),                           // UTM info
 
     /**
      * North American Datum 1927.
@@ -194,7 +200,8 @@ public enum CommonCRS {
      *   <tr><th>Ellipsoid axes unit:</th>     <td>{@link SI#METRE}</td></tr>
      * </table></blockquote>
      */
-    NAD27((short) 4267, (short) 0, (short) 0, (short) 6267, (short) 7008),
+    NAD27((short) 4267, (short) 0, (short) 0, (short) 6267, (short) 7008,           // Geodetic info
+          (short) 26700, (short) 0, (byte) 1, (byte) 22),                           // UTM info
 
     /**
      * European Terrestrial Reference System 1989.
@@ -217,7 +224,8 @@ public enum CommonCRS {
      * The <cite>Web Map Server</cite> {@code "CRS:83"} authority code uses the NAD83 datum,
      * while the {@code "IGNF:MILLER"} authority code uses the GRS80 datum.</div>
      */
-    ETRS89((short) 4258, (short) 4937, (short) 4936, (short) 6258, (short) 7019),
+    ETRS89((short) 4258, (short) 4937, (short) 4936, (short) 6258, (short) 7019,    // Geodetic info
+           (short) 25800, (short) 0, (byte) 28, (byte) 38),                         // UTM info
 
     /**
      * European Datum 1950.
@@ -233,7 +241,8 @@ public enum CommonCRS {
      *   <tr><th>Ellipsoid axes unit:</th>     <td>{@link SI#METRE}</td></tr>
      * </table></blockquote>
      */
-    ED50((short) 4230, (short) 0, (short) 0, (short) 6230, (short) 7022),
+    ED50((short) 4230, (short) 0, (short) 0, (short) 6230, (short) 7022,            // Geodetic info
+           (short) 23000, (short) 0, (byte) 28, (byte) 38),                         // UTM info
 
     /**
      * Unspecified datum based upon the GRS 1980 Authalic Sphere. Spheres use a simpler algorithm for
@@ -251,7 +260,8 @@ public enum CommonCRS {
      *
      * @see org.apache.sis.referencing.datum.DefaultEllipsoid#getAuthalicRadius()
      */
-    SPHERE((short) 4047, (short) 0, (short) 0, (short) 6047, (short) 7048);
+    SPHERE((short) 4047, (short) 0, (short) 0, (short) 6047, (short) 7048,          // Geodetic info
+           (short) 0, (short) 0, (byte) 0, (byte) 0);                               // UTM info
 
     /**
      * The enum for the default CRS.
@@ -288,6 +298,16 @@ public enum CommonCRS {
     final short ellipsoid;
 
     /**
+     * EPSG codes of pseudo "UTM zone zero" (North case and South case), or 0 if none.
+     */
+    final short northUTM, southUTM;
+
+    /**
+     * Zone number of the first UTM and last UTM zone defined in the EPSG database, inclusive.
+     */
+    final byte firstZone, lastZone;
+
+    /**
      * The cached object. This is initially {@code null}, then set to various kind of objects depending
      * on which method has been invoked. The kind of object stored in this field may change during the
      * application execution.
@@ -316,6 +336,14 @@ public enum CommonCRS {
     private transient volatile GeocentricCRS cachedGeocentric;
 
     /**
+     * The Universal Transverse Mercator projections, created when first needed.
+     * All accesses to this map shall be synchronized on {@code cachedUTM}.
+     *
+     * @see #UTM(double, boolean)
+     */
+    private final Map<Integer,ProjectedCRS> cachedUTM;
+
+    /**
      * Creates a new constant for the given EPSG or SIS codes.
      *
      * @param geographic The EPSG code for the two-dimensional geographic CRS.
@@ -324,14 +352,19 @@ public enum CommonCRS {
      * @param datum      The EPSG code for the datum.
      * @param ellipsoid  The EPSG code for the ellipsoid.
      */
-    private CommonCRS(final short geographic, final short geo3D, final short geocentric,
-            final short datum, final short ellipsoid)
+    private CommonCRS(final short geographic, final short geo3D, final short geocentric, final short datum, final short ellipsoid,
+            final short northUTM, final short southUTM, final byte firstZone, final byte lastZone)
     {
         this.geographic = geographic;
         this.geocentric = geocentric;
         this.geo3D      = geo3D;
         this.datum      = datum;
         this.ellipsoid  = ellipsoid;
+        this.northUTM   = northUTM;
+        this.southUTM   = southUTM;
+        this.firstZone  = firstZone;
+        this.lastZone   = lastZone;
+        cachedUTM = new HashMap<>();
     }
 
     /**
@@ -351,11 +384,15 @@ public enum CommonCRS {
     /**
      * Invoked by when the cache needs to be cleared after a classpath change.
      */
+    @SuppressWarnings("NestedSynchronizedStatement")    // Safe because cachedUTM never call any method of 'this'.
     synchronized void clear() {
         cached           = null;
         cachedGeo3D      = null;
         cachedNormalized = null;
         cachedGeocentric = null;
+        synchronized (cachedUTM) {
+            cachedUTM.clear();
+        }
     }
 
     /**
@@ -667,7 +704,7 @@ public enum CommonCRS {
                 object = ellipsoid(cached);
                 if (object == null) {
                     if (this == NAD83) {
-                        object = ETRS89.ellipsoid(); // Share the same instance for NAD83 and ETRS89.
+                        object = ETRS89.ellipsoid();            // Share the same instance for NAD83 and ETRS89.
                     } else {
                         final DatumAuthorityFactory factory = datumFactory();
                         if (factory != null) try {
@@ -707,7 +744,7 @@ public enum CommonCRS {
                 object = primeMeridian(cached);
                 if (object == null) {
                     if (this != DEFAULT) {
-                        object = DEFAULT.primeMeridian(); // Share the same instance for all constants.
+                        object = DEFAULT.primeMeridian();           // Share the same instance for all constants.
                     } else {
                         final DatumAuthorityFactory factory = datumFactory();
                         if (factory != null) try {
@@ -767,6 +804,61 @@ public enum CommonCRS {
         return (datum != null) ? datum.getPrimeMeridian() : null;
     }
 
+    /**
+     * Returns a Universal Transverse Mercator projection for the zone containing the given meridian.
+     * If the given central meridian is not between -180° and 180°, then it will be rolled into that range.
+     * If the given central meridian is not in the center of a UTM zone, then it will be snapped to the center.
+     *
+     * @param  centralMeridian  The longitude in the center of the desired projection.
+     * @param  isSouth          {@code false} for a projection in the North hemisphere, or {@code true} for the South hemisphere.
+     * @return A Universal Transverse Mercator projection for the zone containing the given meridian.
+     *
+     * @since 0.7
+     */
+    public ProjectedCRS UTM(final double centralMeridian, final boolean isSouth) {
+        final int zone = TransverseMercator.zone(centralMeridian);
+        final Integer key = isSouth ? -zone : zone;
+        ProjectedCRS crs;
+        synchronized (cachedUTM) {
+            crs = cachedUTM.get(key);
+        }
+        if (crs == null) {
+            int code = 0;
+            if (zone >= firstZone && zone <= lastZone) {
+                code = Short.toUnsignedInt(isSouth ? southUTM : northUTM);
+                if (code != 0) {
+                    code += zone;
+                    final CRSAuthorityFactory factory = crsFactory();
+                    if (factory != null) try {
+                        return factory.createProjectedCRS(String.valueOf(code));
+                    } catch (FactoryException e) {
+                        failure(this, "UTM", e);
+                    }
+                }
+            }
+            /*
+             * All constants defined in this enumeration use the same coordinate system, EPSG::4400.
+             * We will arbitrarily create this CS only for a frequently created CRS, and share that
+             * CS instance for all other constants.
+             */
+            final CartesianCS cs;
+            if (this == DEFAULT && zone == 31 && !isSouth) {    // MUST be the zone of 3°
+                cs = (CartesianCS) StandardDefinitions.createCoordinateSystem((short) 4400);
+            } else {
+                cs = DEFAULT.UTM(3, false).getCoordinateSystem();
+            }
+            crs = StandardDefinitions.createUTM(code, geographic(), centralMeridian, isSouth, cs);
+            final ProjectedCRS other;
+            synchronized (cachedUTM) {
+                other = cachedUTM.putIfAbsent(key, crs);
+            }
+            if (other != null) {
+                return other;
+            }
+        }
+        return crs;
+    }
+
 
 
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -32,9 +32,17 @@ import org.opengis.referencing.cs.AxisDi
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.cs.EllipsoidalCS;
+import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.util.NoSuchIdentifierException;
+import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.metadata.AxisNames;
+import org.apache.sis.internal.referencing.provider.TransverseMercator;
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.referencing.datum.DefaultEllipsoid;
@@ -47,6 +55,9 @@ import org.apache.sis.referencing.cs.Def
 import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.crs.DefaultVerticalCRS;
+import org.apache.sis.referencing.crs.DefaultProjectedCRS;
+import org.apache.sis.referencing.operation.DefaultConversion;
+import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.measure.Longitude;
 import org.apache.sis.measure.Latitude;
 
@@ -81,15 +92,17 @@ final class StandardDefinitions {
     /**
      * Returns a map of properties for the given EPSG code, name and alias.
      *
-     * @param  code  The EPSG code.
+     * @param  code  The EPSG code, or 0 if none.
      * @param  name  The object name.
      * @param  alias The alias, or {@code null} if none.
      * @param  world {@code true} if the properties shall have an entry for the domain of validity.
      * @return The map of properties to give to constructors or factory methods.
      */
-    private static Map<String,Object> properties(final short code, final String name, final String alias, final boolean world) {
+    private static Map<String,Object> properties(final int code, final String name, final String alias, final boolean world) {
         final Map<String,Object> map = new HashMap<>(8);
-        map.put(IDENTIFIERS_KEY, new NamedIdentifier(Citations.EPSG, String.valueOf(code)));
+        if (code != 0) {
+            map.put(IDENTIFIERS_KEY, new NamedIdentifier(Citations.EPSG, String.valueOf(code)));
+        }
         map.put(NAME_KEY, new NamedIdentifier(Citations.EPSG, name));
         map.put(ALIAS_KEY, alias); // May be null, which is okay.
         if (world) {
@@ -110,6 +123,34 @@ final class StandardDefinitions {
     }
 
     /**
+     * Returns the operation method for Transverse Mercator projection using the SIS factory implementation.
+     * This method restricts the factory to SIS implementation instead than arbitrary factory in order to meet
+     * the contract saying that {@link CommonCRS} methods should never fail.
+     *
+     * @param code             The EPSG code, or 0 if none.
+     * @param baseCRS          The geographic CRS on which the projected CRS is based.
+     * @param centralMeridian  The longitude in the center of the desired projection.
+     * @param isSouth          {@code false} for a projection in the North hemisphere, or {@code true} for the South hemisphere.
+     * @param derivedCS        The projected coordinate system.
+     */
+    static ProjectedCRS createUTM(final int code, final GeographicCRS baseCRS,
+            final double centralMeridian, final boolean isSouth, final CartesianCS derivedCS)
+    {
+        final OperationMethod method;
+        try {
+            method = DefaultFactories.forBuildin(MathTransformFactory.class, DefaultMathTransformFactory.class).getOperationMethod("Transverse Mercator");
+        } catch (NoSuchIdentifierException e) {
+            throw new IllegalStateException(e);     // Should not happen with SIS implementation.
+        }
+        final ParameterValueGroup parameters = method.getParameters().createValue();
+        String name = TransverseMercator.setParameters(parameters, centralMeridian, true, isSouth);
+        final DefaultConversion conversion = new DefaultConversion(properties(0, name, null, false), method, null, parameters);
+
+        name = baseCRS.getName().getCode() + " / " + name;
+        return new DefaultProjectedCRS(properties(code, name, null, false), baseCRS, conversion, derivedCS);
+    }
+
+    /**
      * Creates a geodetic CRS from hard-coded values for the given code.
      *
      * @param  code  The EPSG code.
@@ -271,6 +312,7 @@ final class StandardDefinitions {
             case 6422: name = "Ellipsoidal 2D"; dim = 2; axisCode = 108; break;
             case 6423: name = "Ellipsoidal 3D"; dim = 3; axisCode = 111; break;
             case 6500: name = "Earth centred";  dim = 3; axisCode = 118; isCartesian = true; break;
+            case 4400: name = "Cartesian 2D";   dim = 2; axisCode =   3; isCartesian = true; break;
             default:   throw new AssertionError(code);
         }
         final Map<String,?> properties = properties(code, name, null, false);
@@ -283,12 +325,17 @@ final class StandardDefinitions {
             case 0:  break;
         }
         if (isCartesian) {
-            return new DefaultCartesianCS(properties, xAxis, yAxis, zAxis);
-        }
-        if (zAxis != null) {
-            return new DefaultEllipsoidalCS(properties, xAxis, yAxis, zAxis);
+            if (zAxis != null) {
+                return new DefaultCartesianCS(properties, xAxis, yAxis, zAxis);
+            } else {
+                return new DefaultCartesianCS(properties, xAxis, yAxis);
+            }
         } else {
-            return new DefaultEllipsoidalCS(properties, xAxis, yAxis);
+            if (zAxis != null) {
+                return new DefaultEllipsoidalCS(properties, xAxis, yAxis, zAxis);
+            } else {
+                return new DefaultEllipsoidalCS(properties, xAxis, yAxis);
+            }
         }
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -22,10 +22,10 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Collections;
 import java.util.Arrays;
-import java.util.Locale;
 import javax.measure.unit.NonSI;
 import org.opengis.util.NameFactory;
 import org.opengis.util.FactoryException;
+import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
@@ -34,6 +34,7 @@ import org.opengis.referencing.crs.CRSFa
 import org.opengis.referencing.crs.CRSAuthorityFactory;
 import org.opengis.referencing.crs.EngineeringCRS;
 import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.cs.CSFactory;
@@ -41,24 +42,34 @@ import org.opengis.referencing.cs.Cartes
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.datum.DatumFactory;
 import org.opengis.referencing.datum.EngineeringDatum;
+import org.opengis.util.GenericName;
+import org.opengis.util.ScopedName;
+import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
+import org.apache.sis.internal.referencing.provider.TransverseMercator;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.internal.simple.SimpleIdentifier;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.math.MathFunctions;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.iso.DefaultNameSpace;
+import org.apache.sis.util.iso.SimpleInternationalString;
 
 
 /**
- * Creates coordinate reference systems in the "{@code OGC}" or "{@code CRS}" namespace.
+ * Creates coordinate reference systems in the "{@code OGC}", "{@code CRS}" or {@code "AUTO(2)"} namespaces.
  * All namespaces recognized by this factory are defined by the Open Geospatial Consortium (OGC).
  * Most codes map to one of the constants in the {@link CommonCRS} enumeration.
  *
  * <table class="sis">
  *   <caption>Recognized Coordinate Reference System codes</caption>
  *   <tr>
+ *     <th>Namespace</th>
  *     <th>Code</th>
  *     <th>Name</th>
  *     <th>Datum type</th>
@@ -66,6 +77,7 @@ import org.apache.sis.util.CharSequences
  *     <th>Axis direction</th>
  *     <th>Units</th>
  *   </tr><tr>
+ *     <td>CRS</td>
  *     <td>1</td>
  *     <td>Computer display</td>
  *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultEngineeringCRS Engineering}</td>
@@ -73,6 +85,7 @@ import org.apache.sis.util.CharSequences
  *     <td>(east, south)</td>
  *     <td>pixels</td>
  *   </tr><tr>
+ *     <td>CRS</td>
  *     <td>27</td>
  *     <td>NAD27</td>
  *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS Geographic}</td>
@@ -80,6 +93,7 @@ import org.apache.sis.util.CharSequences
  *     <td>(east, north)</td>
  *     <td>degrees</td>
  *   </tr><tr>
+ *     <td>CRS</td>
  *     <td>83</td>
  *     <td>NAD83</td>
  *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS Geographic}</td>
@@ -87,6 +101,7 @@ import org.apache.sis.util.CharSequences
  *     <td>(east, north)</td>
  *     <td>degrees</td>
  *   </tr><tr>
+ *     <td>CRS</td>
  *     <td>84</td>
  *     <td>WGS84</td>
  *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS Geographic}</td>
@@ -94,23 +109,76 @@ import org.apache.sis.util.CharSequences
  *     <td>(east, north)</td>
  *     <td>degrees</td>
  *   </tr><tr>
+ *     <td>CRS</td>
  *     <td>88</td>
  *     <td>NAVD88</td>
  *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultVerticalCRS Vertical}</td>
  *     <td>{@linkplain org.apache.sis.referencing.cs.DefaultVerticalCS Vertical}</td>
  *     <td>up</td>
  *     <td>metres</td>
+ *   </tr><tr>
+ *     <td>AUTO2</td>
+ *     <td>42001</td>
+ *     <td>WGS 84 / Auto UTM</td>
+ *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS Projected}</td>
+ *     <td>{@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian}</td>
+ *     <td>up</td>
+ *     <td>user-specified</td>
+ *   </tr><tr>
+ *     <td>AUTO2</td>
+ *     <td>42002</td>
+ *     <td>WGS 84 / Auto Tr Mercator</td>
+ *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS Projected}</td>
+ *     <td>{@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian}</td>
+ *     <td>up</td>
+ *     <td>user-specified</td>
+ *   </tr><tr>
+ *     <td>AUTO2</td>
+ *     <td>42003</td>
+ *     <td>WGS 84 / Auto Orthographic</td>
+ *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS Projected}</td>
+ *     <td>{@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian}</td>
+ *     <td>up</td>
+ *     <td>user-specified</td>
+ *   </tr><tr>
+ *     <td>AUTO2</td>
+ *     <td>42004</td>
+ *     <td>WGS 84 / Auto Equirectangular</td>
+ *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS Projected}</td>
+ *     <td>{@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian}</td>
+ *     <td>up</td>
+ *     <td>user-specified</td>
+ *   </tr><tr>
+ *     <td>AUTO2</td>
+ *     <td>42005</td>
+ *     <td>WGS 84 / Auto Mollweide</td>
+ *     <td>{@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS Projected}</td>
+ *     <td>{@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian}</td>
+ *     <td>up</td>
+ *     <td>user-specified</td>
  *   </tr>
  * </table>
  *
  * <div class="section">Note on codes in CRS namespace</div>
- * The format is usually <code>"CRS:</code><var>n</var><code>"</code> where <var>n</var> is a number like 27, 83 or 84.
+ * The format is usually "{@code CRS:}<var>n</var>" where <var>n</var> is a number like 27, 83 or 84.
  * However this factory is lenient and allows the {@code CRS} part to be repeated as in {@code "CRS:CRS84"}.
  * It also accepts {@code "OGC"} as a synonymous of the {@code "CRS"} namespace.
  *
  * <div class="note"><b>Examples:</b>
  * {@code "CRS:27"}, {@code "CRS:83"}, {@code "CRS:84"}, {@code "CRS:CRS84"}, {@code "OGC:CRS84"}.</div>
  *
+ * <div class="section">Note on codes in AUTO(2) namespace</div>
+ * The format is usually "{@code AUTO2:}<var>n</var>,<var>factor</var>,<var>λ₀</var>,<var>φ₀</var>"
+ * where <var>n</var> is a number between 42001 and 42005 inclusive, <var>factor</var> is a conversion
+ * factor from the CRS units to metres (e.g. 0.3048 for a CRS in feet) and (<var>λ₀</var>,<var>φ₀</var>)
+ * is the longitude and latitude of a point in the projection centre.
+ *
+ * <div class="note"><b>Examples:</b>
+ * {@code "AUTO2:42003,1,-100,45"}.</div>
+ *
+ * Codes in the {@code "AUTO"} namespace are the same than codes in the {@code "AUTO2"} namespace,
+ * but with the unit factor omitted.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.7
  * @version 0.7
@@ -121,15 +189,46 @@ import org.apache.sis.util.CharSequences
  */
 public class CommonAuthorityFactory extends GeodeticAuthorityFactory implements CRSAuthorityFactory {
     /**
+     * The {@value} prefix for a code identified by parameters.
+     * This is defined in annexes B.7 to B.11 of WMS 1.3 specification.
+     * The {@code "AUTO(2)"} namespaces are not considered by SIS as real authorities.
+     */
+    private static final String AUTO2 = "AUTO2";
+
+    /**
+     * First code in the AUTO(2) namespace.
+     */
+    private static final int FIRST_PROJECTION_CODE = 42001;
+
+    /**
+     * Names of objects in the AUTO(2) namespace for codes from 42001 to 42005 inclusive.
+     * Those names are defined in annexes B.7 to B.11 of WMS 1.3 specification.
+     *
+     * @see #getDescriptionText(String)
+     */
+    private static final String[] PROJECTION_NAMES = {
+        "WGS 84 / Auto UTM",
+        "WGS 84 / Auto Tr. Mercator",
+        "WGS 84 / Auto Orthographic",
+        "WGS 84 / Auto Equirectangular",
+        "WGS 84 / Auto Mollweide"
+    };
+
+    /**
+     * The parameter separator for codes in the {@code "AUTO(2)"} namespace.
+     */
+    private static final char SEPARATOR = ',';
+
+    /**
      * The codes known to this factory, associated with their CRS type. This is set to an empty map
-     * at {@code CommonAuthorityFactory} construction time, but filled only when first needed.
+     * at {@code CommonAuthorityFactory} construction time and filled only when first needed.
      */
     private final Map<String,Class<?>> codes;
 
     /**
-     * The authority for this factory.
+     * The authority for this factory, created when first needed.
      */
-    private final Citation authority;
+    private Citation authority;
 
     /**
      * The "Computer display" reference system (CRS:1). Created when first needed.
@@ -141,17 +240,10 @@ public class CommonAuthorityFactory exte
     /**
      * Constructs a default factory for the {@code CRS} authority.
      *
-     * @param nameFactory The factory to use for parsing authority code as {@link org.opengis.util.GenericName} instances.
+     * @param nameFactory The factory to use for {@linkplain NameFactory#parseGenericName parsing} authority codes.
      */
     public CommonAuthorityFactory(final NameFactory nameFactory) {
         super(nameFactory);
-        final DefaultCitation c = new DefaultCitation(Citations.OGC);
-        c.setIdentifiers(Arrays.asList(
-                new SimpleIdentifier(null, Constants.OGC, false),
-                new SimpleIdentifier(null, Constants.CRS, false)
-        ));
-        c.freeze();
-        authority = c;
         codes = new LinkedHashMap<>();
     }
 
@@ -162,14 +254,73 @@ public class CommonAuthorityFactory exte
      * @return The OGC authority.
      */
     @Override
-    public Citation getAuthority() {
+    public synchronized Citation getAuthority() {
+        if (authority == null) {
+            final DefaultCitation c = new DefaultCitation(Citations.OGC);
+            c.setIdentifiers(Arrays.asList(
+                    new SimpleIdentifier(null, Constants.OGC, false),
+                    new SimpleIdentifier(null, Constants.CRS, false)
+            ));
+            c.freeze();
+            authority = c;
+        }
         return authority;
     }
 
     /**
-     * Provides a complete set of the known codes provided by this authority.
-     * The returned set contains only numeric identifiers like {@code "84"}, {@code "27"}, <i>etc</i>.
-     * The authority name ({@code "CRS"}) is not included in the character strings.
+     * Returns {@code true} if the given string if one of the namespaces recognized by this factory.
+     */
+    private static boolean isAuthority(final String namespace) {
+        if (!namespace.equalsIgnoreCase(Constants.CRS) && !namespace.equalsIgnoreCase(Constants.OGC)) {
+            final int s = AUTO2.length() - 1;
+            if (!namespace.regionMatches(true, 0, AUTO2, 0, s)) {
+                return false;
+            }
+            switch (namespace.length() - s) {
+                case 0:  break;                                 // Namespace is exactly "AUTO" (ignoring case).
+                case 1:  final char c = namespace.charAt(s);    // Namespace has one more character than "AUTO".
+                         return (c >= '1' && c <= '2');         // Namespace has more than one more character.
+                default: return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * If the given code begins with {@code "OGC"}, {@code "CRS"}, {@code "AUTO"}, {@code "AUTO1"} or {@code "AUTO2"}
+     * authority (ignoring spaces), returns the code without the authority part. Otherwise if the code starts with any
+     * other authority, throw an exception. Otherwise if the code has no authority, returns the code as-is.
+     */
+    private String trimAuthority(String code) throws NoSuchAuthorityCodeException {
+        final GenericName name = nameFactory.parseGenericName(null, code);
+        if (name instanceof ScopedName) {
+            final GenericName scope = ((ScopedName) name).path();
+            if (!isAuthority(CharSequences.trimWhitespaces(scope.toString()))) {
+                throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.UnknownAuthority_1, scope), Constants.OGC, code);
+            }
+            code = name.tip().toString();
+        }
+        /*
+         * Above code removed the "CRS" part when it is used as a namespace, as in "CRS:84".
+         * The code below removes the "CRS" prefix when it is concatenated within the code,
+         * as in "CRS84". Together, those two checks handle redundant codes like "CRS:CRS84"
+         * (malformed code, but seen in practice).
+         */
+        int start = CharSequences.skipLeadingWhitespaces(code, 0, code.length());
+        if (code.regionMatches(true, start, Constants.CRS, 0, Constants.CRS.length())) {
+            start = CharSequences.skipLeadingWhitespaces(code, start + Constants.CRS.length(), code.length());
+        }
+        code = code.substring(start, CharSequences.skipTrailingWhitespaces(code, start, code.length()));
+        if (code.isEmpty()) {
+            throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.EmptyArgument_1, "code"), Constants.OGC, code);
+        }
+        return code;
+    }
+
+    /**
+     * Provides a complete set of the known codes provided by this factory.
+     * The returned set contains a namespace followed by numeric identifiers
+     * like {@code "CRS:84"}, {@code "CRS:27"}, {@code "AUTO2:42001"}, <i>etc</i>.
      *
      * @param  type The spatial reference objects type.
      * @return The set of authority codes for spatial reference objects of the given type.
@@ -184,11 +335,14 @@ public class CommonAuthorityFactory exte
         }
         synchronized (codes) {
             if (codes.isEmpty()) {
-                add(Constants.CRS84, GeographicCRS.class);   // Put first the codes that are most likely to be requested.
-                add(Constants.CRS83, GeographicCRS.class);
+                add(Constants.CRS1,  EngineeringCRS.class);
                 add(Constants.CRS27, GeographicCRS.class);
+                add(Constants.CRS83, GeographicCRS.class);
+                add(Constants.CRS84, GeographicCRS.class);
                 add(Constants.CRS88, VerticalCRS.class);
-                add(Constants.CRS1,  EngineeringCRS.class);
+                for (int code = FIRST_PROJECTION_CODE; code < FIRST_PROJECTION_CODE + PROJECTION_NAMES.length; code++) {
+                    add(code, ProjectedCRS.class);
+                }
             }
         }
         return all ? Collections.unmodifiableSet(codes.keySet()) : new FilteredCodes(codes, type).keySet();
@@ -197,13 +351,58 @@ public class CommonAuthorityFactory exte
     /**
      * Adds an element in the {@link #codes} map, witch check against duplicated values.
      */
-    private void add(final byte code, final Class<? extends SingleCRS> type) throws FactoryException {
-        if (codes.put(String.valueOf(code).intern(), type) != null) {
+    private void add(final int code, final Class<? extends SingleCRS> type) throws FactoryException {
+        final String namespace = (code >= FIRST_PROJECTION_CODE) ? AUTO2 : Constants.CRS;
+        if (codes.put(namespace + DefaultNameSpace.DEFAULT_SEPARATOR + code, type) != null) {
             throw new FactoryException();    // Should never happen, but we are paranoiac.
         }
     }
 
     /**
+     * Returns a description of the object corresponding to a code.
+     * The description can be used for example in a combo box in a graphical user interface.
+     *
+     * <p>Codes in the {@code "AUTO(2)"} namespace do not need parameters for this method.
+     * But if parameters are nevertheless specified, then they will be taken in account.</p>
+     *
+     * <table class="sis">
+     *   <caption>Examples</caption>
+     *   <tr><th>Argument value</th>                <th>Return value</th></tr>
+     *   <tr><td>{@code CRS:84}</td>                <td>WGS 84</td></tr>
+     *   <tr><td>{@code AUTO2:42001}</td>           <td>WGS 84 / Auto UTM</td></tr>
+     *   <tr><td>{@code AUTO2:42001,1,-100,45}</td> <td>WGS 84 / UTM zone 47N</td></tr>
+     * </table>
+     *
+     * @param  code Value in the CRS or AUTO(2) code space.
+     * @return A description of the object.
+     * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
+     * @throws FactoryException if an error occurred while fetching the description.
+     */
+    @Override
+    public InternationalString getDescriptionText(final String code) throws FactoryException {
+        final String localCode = trimAuthority(code);
+        if (localCode.indexOf(SEPARATOR) < 0) {
+            /*
+             * For codes in the "AUTO(2)" namespace without parameters, we can not rely on the default implementation
+             * since it would fail to create the ProjectedCRS instance. Instead we return a generic description.
+             * Note that we do not execute this block if parametes were specified. If there is parameters,
+             * then we instead rely on the default implementation for a more accurate description text.
+             */
+            final int codeValue;
+            try {
+                codeValue = Integer.parseInt(localCode);
+            } catch (NumberFormatException exception) {
+                throw noSuchAuthorityCode(false, localCode, code, exception);
+            }
+            final int i = codeValue - FIRST_PROJECTION_CODE;
+            if (i >= 0 && i < PROJECTION_NAMES.length) {
+                return new SimpleInternationalString(PROJECTION_NAMES[i]);
+            }
+        }
+        return new SimpleInternationalString(createCoordinateReferenceSystem(localCode).getName().getCode());
+    }
+
+    /**
      * Creates an object from the specified code.
      * The default implementation delegates to {@link #createCoordinateReferenceSystem(String)}.
      *
@@ -216,41 +415,120 @@ public class CommonAuthorityFactory exte
 
     /**
      * Creates a coordinate reference system from the specified code.
+     * This method performs the following steps:
+     *
+     * <ol>
+     *   <li>Skip the {@code "OGC"}, {@code "CRS"}, {@code "AUTO"}, {@code "AUTO1"} or {@code "AUTO2"} namespace
+     *       if present (ignoring case). All other namespaces will cause an exception to be thrown.</li>
+     *   <li>Skip the {@code "CRS"} prefix if present. This additional check is for accepting codes like
+     *       {@code "OGC:CRS84"} (not a valid CRS code, but seen in practice).</li>
+     *   <li>In the remaining text, interpret the integer value as documented in this class javadoc.
+     *       Note that some codes require coma-separated parameters after the integer value.</li>
+     * </ol>
      *
+     * @param  code Value allocated by OGC.
+     * @return The coordinate reference system for the given code.
      * @throws FactoryException if the object creation failed.
      */
     @Override
     public CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) throws FactoryException {
-        String c = trimAuthority(code, authority).toUpperCase(Locale.US);
-        if (c.startsWith(Constants.CRS)) {
-            /*
-             * "trimAuthority" removed "CRS" when it was separated from the code, as in "CRS:84".
-             * This block removes "CRS" when it is concatenated with the code, as in "CRS84".
-             */
-            c = CharSequences.trimWhitespaces(c.substring(Constants.CRS.length()));
+        ArgumentChecks.ensureNonNull("code", code);
+        String localCode  = trimAuthority(code);
+        String complement = null;
+        final int startOfParameters = localCode.indexOf(SEPARATOR);
+        if (startOfParameters >= 0) {
+            localCode = code.substring(0, CharSequences.skipTrailingWhitespaces(code, 0, startOfParameters));
+            complement = code.substring(startOfParameters + 1);
         }
-        final int n;
+        int codeValue = 0;
+        double[] parameters = ArraysExt.EMPTY_DOUBLE;
         try {
-            n = Integer.parseInt(c);
+            codeValue = Integer.parseInt(localCode);
+            if (complement != null) {
+                parameters = CharSequences.parseDoubles(complement, SEPARATOR);
+            }
         } catch (NumberFormatException exception) {
-            // If a number can not be parsed, then this is an invalid authority code.
-            NoSuchAuthorityCodeException e = noSuchAuthorityCode(CoordinateReferenceSystem.class, code);
-            e.initCause(exception);
-            throw e;
+            throw noSuchAuthorityCode(codeValue >= FIRST_PROJECTION_CODE, localCode, code, exception);
+        }
+        /*
+         * At this point we have isolated the code value from the parameters (if any). Verify the number of arguments.
+         * Then codes in the AUTO(2) namespace are delegated to a separated method while codes in the CRS namespaces
+         * are handled below.
+         */
+        final int count = parameters.length;
+        if (codeValue >= FIRST_PROJECTION_CODE) {
+            int expected;
+            short errorKey = 0;
+            if (count < (expected = 2)) {
+                errorKey = Errors.Keys.TooFewArguments_2;
+            } else if (count > (expected = 3)) {
+                errorKey = Errors.Keys.TooManyArguments_2;
+            }
+            if (errorKey == 0) {
+                return createAuto(code, codeValue, (count > 2) ? parameters[0] : 1,
+                                                                 parameters[count - 2],
+                                                                 parameters[count - 1]);
+            }
+            throw new NoSuchAuthorityCodeException(Errors.format(errorKey, expected, count),
+                    AUTO2, localCode, code);
+        }
+        if (count != 0) {
+            throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.UnexpectedCharactersAfter_2,
+                    localCode, complement), Constants.CRS, localCode, code);
         }
         final CommonCRS crs;
-        switch (n) {
+        switch (codeValue) {
             case Constants.CRS1:  return displayCRS();
             case Constants.CRS84: crs = CommonCRS.WGS84; break;
             case Constants.CRS83: crs = CommonCRS.NAD83; break;
             case Constants.CRS27: crs = CommonCRS.NAD27; break;
             case Constants.CRS88: return CommonCRS.Vertical.NAVD88.crs();
-            default: throw noSuchAuthorityCode(CoordinateReferenceSystem.class, code);
+            default: throw noSuchAuthorityCode(false, localCode, code, null);
         }
         return crs.normalizedGeographic();
     }
 
     /**
+     * Creates a projected CRS from parameters in the {@code AUTO(2)} namespace.
+     *
+     * @param  code        The user-specified code, used only for error reporting.
+     * @param  projection  The projection code (e.g. 42001).
+     * @return The projected CRS for the given projection and parameters.
+     */
+    @SuppressWarnings("fallthrough")
+    private static ProjectedCRS createAuto(final String code, final int projection,
+            final double factor, final double longitude, final double latitude) throws FactoryException
+    {
+        if (!Double.isInfinite(longitude) && !Double.isNaN(longitude) && !Double.isNaN(latitude) && factor > 0) {
+            /*
+             * 42001: Universal Transverse Mercator   —   central meridian must be in the center of a UTM zone.
+             * 42002: Transverse Mercator             —   like 42001 except that central meridian can be anywhere.
+             */
+            boolean isUTM = (projection == 42001);
+            if (isUTM || projection == 42002) {
+                final boolean isSouth = MathFunctions.isNegative(latitude);
+                final CartesianCS cs;
+                if (factor == 1) {
+                    if (!isUTM) {
+                        isUTM = TransverseMercator.centralMeridian(TransverseMercator.zone(longitude)) == longitude;
+                    }
+                    if (isUTM) {
+                        return CommonCRS.WGS84.UTM(longitude, isSouth);
+                    }
+                    cs = CommonCRS.WGS84.UTM(3, false).getCoordinateSystem();       // In metres.
+                } else {
+                    cs = null;  // TODO
+                }
+                return new GeodeticObjectBuilder().setTransverseMercator(factor, isUTM, isSouth)
+                        .createProjectedCRS(CommonCRS.WGS84.geographic(), cs);
+            }
+        }
+        final String localCode = String.valueOf(projection);
+        throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.NoSuchAuthorityCode_3,
+            AUTO2, ProjectedCRS.class, localCode), AUTO2, localCode, code);
+    }
+
+    /**
      * Returns the "Computer display" reference system (CRS:1). This is rarely used.
      */
     private synchronized CoordinateReferenceSystem displayCRS() throws FactoryException {
@@ -269,4 +547,22 @@ public class CommonAuthorityFactory exte
         }
         return displayCRS;
     }
+
+    /**
+     * Creates an exception for an unknown authority code.
+     *
+     * @param  code       The unknown authority code, without namespace.
+     * @param  identifier The unknown authority code as specified by the user (may include namespace).
+     * @param  cause      The failure cause, or {@code null} if none.
+     * @return An exception initialized with an error message built from the specified informations.
+     */
+    private static NoSuchAuthorityCodeException noSuchAuthorityCode(final boolean isAuto,
+            final String code, final String identifier, final Exception cause)
+    {
+        NoSuchAuthorityCodeException e = new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.NoSuchAuthorityCode_3,
+                Constants.OGC, isAuto ? ProjectedCRS.class : CoordinateReferenceSystem.class, code),
+                Constants.OGC, code, identifier);
+        e.initCause(cause);
+        return e;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -246,7 +246,7 @@ public abstract class ConcurrentAuthorit
      * on experience gained.
      *
      * @param dataAccessClass The class of Data Access Object (DAO) created by {@link #newDataAccess()}.
-     * @param nameFactory The factory to use for parsing authority codes as {@link org.opengis.util.GenericName} instances.
+     * @param nameFactory The factory to use for {@linkplain NameFactory#parseGenericName parsing} authority codes.
      */
     protected ConcurrentAuthorityFactory(Class<DAO> dataAccessClass, NameFactory nameFactory) {
         this(dataAccessClass, nameFactory, 100, 8);
@@ -262,7 +262,7 @@ public abstract class ConcurrentAuthorit
      * for the eldest ones will be replaced by weak references.
      *
      * @param dataAccessClass The class of Data Access Object (DAO) created by {@link #newDataAccess()}.
-     * @param nameFactory The factory to use for parsing authority code as {@link org.opengis.util.GenericName} instances.
+     * @param nameFactory The factory to use for {@linkplain NameFactory#parseGenericName parsing} authority codes.
      * @param maxStrongReferences The maximum number of objects to keep by strong reference.
      * @param maxConcurrentQueries The maximal amount of Data Access Objects to use concurrently.
      *        If more than this amount of threads are querying this {@code ConcurrentAuthorityFactory} concurrently,

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -69,14 +69,33 @@ import org.apache.sis.util.Debug;
  */
 public abstract class GeodeticAuthorityFactory extends AbstractFactory implements AuthorityFactory {
     /**
-     * The factory to use for parsing authority code as {@link GenericName} instances.
+     * The factory to use for parsing authority codes as {@link GenericName} instances.
+     *
+     * <div class="note"><b>Example:</b>
+     * This factory can be used as below:
+     *
+     * {@preformat java
+     *     public Foo createFoo(String code) {
+     *         GenericName name = nameFactory.parseGenericName(null, code);
+     *         if (name instanceof ScopedName) {
+     *             GenericName scope = ((ScopedName) name).path();
+     *             if (!MY_AUTHORITY.equals(scope.toString())) {
+     *                 throw new NoSuchAuthorityCodeException("Not a code managed by MyAuthority.", "MyAuthority", code);
+     *             }
+     *         }
+     *         code = name.tip().toString();
+     *         // From this point, the code is local to this factory namespace.
+     *     }
+     * }</div>
+     *
+     * Subclasses may also use this factory for creating {@linkplain AbstractIdentifiedObject#getAlias() aliases}.
      */
     protected final NameFactory nameFactory;
 
     /**
      * Creates a new authority factory for geodetic objects.
      *
-     * @param nameFactory The factory to use for parsing authority codes as {@link GenericName} instances.
+     * @param nameFactory The factory to use for {@linkplain NameFactory#parseGenericName parsing} authority codes.
      */
     protected GeodeticAuthorityFactory(final NameFactory nameFactory) {
         ArgumentChecks.ensureNonNull("nameFactory", nameFactory);
@@ -134,6 +153,10 @@ public abstract class GeodeticAuthorityF
      * This may be costly since it involves a full object creation.
      * Subclasses are encouraged to provide a more efficient implementation if they can.
      *
+     * @param  code Value allocated by authority.
+     * @return A description of the object, or {@code null} if the object
+     *         corresponding to the specified {@code code} has no description.
+     * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
      * @throws FactoryException if an error occurred while fetching the description.
      */
     @Override
@@ -1152,25 +1175,24 @@ public abstract class GeodeticAuthorityF
      * @return The code without the authority scope.
      */
     final String trimAuthority(String code, Citation authority) {
-        code = code.trim();
         final GenericName name = nameFactory.parseGenericName(null, code);
         if (name instanceof ScopedName) {
             final GenericName scope = ((ScopedName) name).path();
             if (authority == null) {
                 authority = getAuthority();     // Costly operation for EPSGDataAccess.
             }
-            if (Citations.identifierMatches(authority, null, scope.toString().trim())) {
-                return CharSequences.trimWhitespaces(name.tip().toString().trim());
+            if (Citations.identifierMatches(authority, null, scope.toString())) {    // Comparison ignores spaces.
+                code = name.tip().toString();
             }
         }
-        return code;
+        return CharSequences.trimWhitespaces(code);
     }
 
     /**
      * Creates an exception for an unknown authority code.
      * This convenience method is provided for implementation of {@code createFoo(String)} methods in subclasses.
      *
-     * @param  type  The GeoAPI interface that was to be created (e.g. {@code CoordinateReferenceSystem.class}).
+     * @param  type  The GeoAPI interface of the requested object (e.g. {@code CoordinateReferenceSystem.class}).
      * @param  code  The unknown authority code.
      * @return An exception initialized with an error message built from the specified informations.
      */

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -29,7 +29,7 @@ import org.opengis.parameter.ParameterVa
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.cs.HardCodedCS;
-import org.apache.sis.referencing.GeodeticObjectBuilder;
+import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.io.wkt.Convention;

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -23,6 +23,7 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.EngineeringCRS;
 import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.datum.Datum;
@@ -71,13 +72,16 @@ public final strictfp class CommonAuthor
     public void testGetAuthorityCodes() throws FactoryException {
         assertTrue("getAuthorityCodes(Datum.class)",
                 factory.getAuthorityCodes(Datum.class).isEmpty());
-        assertSetEquals(Arrays.asList("1", "27", "83", "84", "88"),
+        assertSetEquals(Arrays.asList("CRS:1", "CRS:27", "CRS:83", "CRS:84", "CRS:88",
+                                      "AUTO2:42001", "AUTO2:42002", "AUTO2:42003", "AUTO2:42004", "AUTO2:42005"),
                 factory.getAuthorityCodes(CoordinateReferenceSystem.class));
-        assertSetEquals(Arrays.asList("27", "83", "84"),
+        assertSetEquals(Arrays.asList("AUTO2:42001", "AUTO2:42002", "AUTO2:42003", "AUTO2:42004", "AUTO2:42005"),
+                factory.getAuthorityCodes(ProjectedCRS.class));
+        assertSetEquals(Arrays.asList("CRS:27", "CRS:83", "CRS:84"),
                 factory.getAuthorityCodes(GeographicCRS.class));
-        assertSetEquals(Arrays.asList("88"),
+        assertSetEquals(Arrays.asList("CRS:88"),
                 factory.getAuthorityCodes(VerticalCRS.class));
-        assertSetEquals(Arrays.asList("1"),
+        assertSetEquals(Arrays.asList("CRS:1"),
                 factory.getAuthorityCodes(EngineeringCRS.class));
     }
 

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1724141&r1=1724140&r2=1724141&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] Mon Jan 11 23:00:55 2016
@@ -576,7 +576,7 @@ search:     for (; fromIndex <= toIndex;
      *
      * <p>Special cases:</p>
      * <ul>
-     *   <li>If {@code toIndex} is lower than {@code toIndex},
+     *   <li>If {@code fromIndex} is lower than {@code toIndex},
      *       then this method unconditionally returns {@code toIndex}.</li>
      *   <li>If the given range contains only space characters and the character at {@code fromIndex}
      *       is the low surrogate of a valid supplementary code point, then this method returns



Mime
View raw message