sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1674327 [2/3] - in /sis/branches/JDK7: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/ ...
Date Fri, 17 Apr 2015 14:33:55 GMT
Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.referencing;
 
+import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.util.resources.Vocabulary;
 
@@ -36,6 +37,13 @@ final class DeprecatedName extends Named
     private static final long serialVersionUID = 1792369861343798471L;
 
     /**
+     * Information about the replacement for this name.
+     *
+     * @see #getRemarks()
+     */
+    private final InternationalString remarks;
+
+    /**
      * Creates a new deprecated EPSG name.
      *
      * @param supersededBy The name that replace this one.
@@ -43,8 +51,8 @@ final class DeprecatedName extends Named
     DeprecatedName(final Citation authority, final String codeSpace, final CharSequence code, final String version,
             final CharSequence supersededBy)
     {
-        super(authority, codeSpace, code, version,
-                Vocabulary.formatInternational(Vocabulary.Keys.SupersededBy_1, supersededBy));
+        super(authority, codeSpace, code, version, null);
+        remarks = Vocabulary.formatInternational(Vocabulary.Keys.SupersededBy_1, supersededBy);
     }
 
     /**
@@ -56,4 +64,16 @@ final class DeprecatedName extends Named
     public boolean isDeprecated() {
         return true;
     }
+
+    /**
+     * Information about the replacement for this name.
+     *
+     * <div class="note"><b>Example:</b> "superseded by code XYZ".</div>
+     *
+     * @return Information about the replacement for this name, or {@code null} if none.
+     */
+    @Override
+    public InternationalString getRemarks() {
+        return remarks;
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -33,13 +33,10 @@ import org.opengis.metadata.Identifier;
 import org.opengis.parameter.InvalidParameterValueException;
 import org.apache.sis.internal.metadata.NameToIdentifier;
 import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.metadata.iso.citation.Citations;  // For javadoc
+import org.apache.sis.internal.util.Citations;
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
-import org.apache.sis.util.collection.WeakValueHashMap;
 import org.apache.sis.util.ArgumentChecks;
 
-import static org.apache.sis.internal.util.Citations.getUnicodeIdentifier;
-
 // Branch-dependent imports
 import java.util.Objects;
 
@@ -66,8 +63,8 @@ import java.util.Objects;
  *
  * <ul>
  *   <li><b>{@linkplain #tip() Tip}:</b> derived from the identifier {@linkplain #getCode() code}.</li>
- *   <li><b>{@linkplain #head() Head}:</b> derived from the identifier {@linkplain #getCodeSpace() code space}.</li>
- *   <li><b>{@linkplain #scope() Scope}:</b> derived from the shortest {@linkplain #getAuthority() authority}'s
+ *   <li><b>{@linkplain #head() Head}:</b> derived from the identifier {@linkplain #getCodeSpace() code space} if non-null.
+ *     If there is no code space, then the scope is derived from the shortest {@linkplain #getAuthority() authority}'s
  *     {@linkplain Citation#getAlternateTitles() alternate titles}, or the {@linkplain Citation#getTitle() main title}
  *     if there is no alternate titles. This policy exploits the ISO 19115 comment saying that citation alternate titles
  *     often contain abbreviation (for example "DCW" as an alternative title for <cite>"Digital Chart of the World"</cite>).</li>
@@ -76,8 +73,7 @@ import java.util.Objects;
  * <div class="note"><b>Example:</b>
  * If the identifier attributes are {@code authority} = {@code new DefaultCitation("IOGP")},
  * {@code codeSpace} = {@code "EPSG"} and {@code code} = {@code "4326"}, then the name attributes will be
- * {@code scope} = {@code "IOGP"}, {@code head} = {@code "EPSG"}, {@code tip} = {@code "4326"} and
- * {@link #toString()} = {@code "EPSG:4326"}.
+ * {@code head} = {@code "EPSG"}, {@code tip} = {@code "4326"} and {@link #toString()} = {@code "EPSG:4326"}.
  * Note that the scope does not appear in the string representation of names.</div>
  *
  *
@@ -101,11 +97,6 @@ public class NamedIdentifier extends Imm
     private static final long serialVersionUID = -3982456534858346939L;
 
     /**
-     * A pool of {@link NameSpace} values for given {@link InternationalString}.
-     */
-    private static final Map<CharSequence,NameSpace> SCOPES = new WeakValueHashMap<>(CharSequence.class);
-
-    /**
      * The name of this identifier as a generic name.
      * If {@code null}, will be constructed only when first needed.
      */
@@ -118,9 +109,8 @@ public class NamedIdentifier extends Imm
     private transient boolean isNameSupplied;
 
     /**
-     * Creates a new identifier from the specified one. This is a copy constructor
-     * which will get the code, codespace, authority, version and the remarks (if
-     * available) from the given identifier.
+     * Creates a new identifier from the specified one. This is a copy constructor which get the code,
+     * codespace, authority, version and the description (if available) from the given identifier.
      *
      * <p>If the given identifier implements the {@link GenericName} interface, then calls to
      * {@link #tip()}, {@link #head()}, {@link #scope()} and similar methods will delegate
@@ -177,16 +167,16 @@ public class NamedIdentifier extends Imm
      *          the authority. The code can not be null.
      */
     public NamedIdentifier(final Citation authority, final CharSequence code) {
-        super(authority, getUnicodeIdentifier(authority), toString(code));
+        super(authority, Citations.getCodeSpace(authority), toString(code));
         if (code instanceof InternationalString) {
-            name = createName(authority, code);
+            name = createName(authority, super.getCodeSpace(), code);
             isNameSupplied = true; // Because 'code' is an international string.
         }
     }
 
     /**
      * Constructs an identifier from an authority and localizable code,
-     * with an optional version number and remarks.
+     * with an optional version number and description.
      *
      * <p>If the given code is an {@link InternationalString}, then the {@code code.toString(Locale.ROOT)}
      * return value will be used for the {@link #getCode() code} property, and the complete international
@@ -204,15 +194,15 @@ public class NamedIdentifier extends Imm
      * @param version
      *          The version of the associated code space or code as specified by the code authority,
      *          or {@code null} if none.
-     * @param remarks
-     *          Comments on or information about this identifier, or {@code null} if none.
+     * @param description
+     *          Natural language description of the meaning of the code value, or {@code null} if none.
      */
     public NamedIdentifier(final Citation authority, final String codeSpace, final CharSequence code,
-            final String version, final InternationalString remarks)
+            final String version, final InternationalString description)
     {
-        super(authority, codeSpace, toString(code), version, remarks);
+        super(authority, codeSpace, toString(code), version, description);
         if (code instanceof InternationalString) {
-            name = createName(authority, code);
+            name = createName(authority, codeSpace, code);
             isNameSupplied = true; // Because 'code' is an international string.
         }
     }
@@ -242,7 +232,7 @@ public class NamedIdentifier extends Imm
      */
     private synchronized GenericName getName() {
         if (name == null) {
-            name = createName(super.getAuthority(), super.getCode());
+            name = createName(super.getAuthority(), super.getCodeSpace(), super.getCode());
         }
         return name;
     }
@@ -251,28 +241,22 @@ public class NamedIdentifier extends Imm
      * Constructs a generic name from the specified authority and code.
      *
      * @param  authority The authority, or {@code null} if none.
-     * @param  code The code.
+     * @param  codeSpace The code space, or {@code null} if none.
+     * @param  code      The code.
      * @return A new generic name for the given authority and code.
      * @category Generic name
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-197">SIS-197</a>
      */
-    private GenericName createName(final Citation authority, final CharSequence code) {
-        final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
-        final String identifier = getUnicodeIdentifier(authority);      // Whitespaces trimed by Citations.
-        NameSpace scope = null;
-        if (identifier != null) {
-            synchronized (SCOPES) {
-                scope = SCOPES.get(identifier);
-                if (scope == null) {
-                    scope = factory.createNameSpace(factory.createLocalName(null, identifier), null);
-                    SCOPES.put(identifier, scope);
-                }
-            }
+    private static GenericName createName(final Citation authority, String codeSpace, final CharSequence code) {
+        if (codeSpace == null) {
+            codeSpace = Citations.getCodeSpace(authority);   // Whitespaces trimed by Citations.
         }
-        final String codeSpace = super.getCodeSpace();
+        final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
         if (codeSpace != null) {
-            return factory.createGenericName(scope, codeSpace, code);
+            return factory.createGenericName(null, codeSpace, code);
         } else {
-            return factory.createLocalName(scope, code);
+            return factory.createLocalName(null, code);
         }
     }
 

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -47,7 +47,8 @@ import org.apache.sis.util.resources.Err
  *     <ul>
  *       <li>{@link #isAffine()}</li>
  *       <li>{@link #normalizeColumns()}</li>
- *       <li>{@link #concatenate(int, Number, Number)}</li>
+ *       <li>{@link #convertBefore(int, Number, Number)}</li>
+ *       <li>{@link #convertAfter(int, Number, Number)}</li>
  *     </ul>
  *   </li>
  * </ul>
@@ -268,7 +269,7 @@ public abstract class MatrixSIS implemen
      * @return {@code true} if this matrix is an identity matrix.
      *
      * @see Matrices#isIdentity(Matrix, double)
-     * @see java.awt.geom.AffineTransform#isIdentity()
+     * @see AffineTransform#isIdentity()
      */
     @Override
     public abstract boolean isIdentity();
@@ -318,35 +319,26 @@ public abstract class MatrixSIS implemen
     }
 
     /**
-     * Assuming that this matrix represents an affine transform, applies a scale and a translation
-     * on the given dimension.
-     * If:
-     * <ul>
-     *   <li>{@code original} is this matrix before this method call</li>
-     *   <li>{@code modified} is this matrix after this method call</li>
-     * </ul>
-     *
-     * then transforming a coordinate by {@code modified} is equivalent to first replacing the ordinate
-     * value at dimension {@code srcDim} by ({@code scale} × <var>ordinate</var> + {@code offset}),
-     * then apply the {@code original} transform.
+     * Assuming that this matrix represents an affine transform, concatenates a scale and a translation on the
+     * given dimension. Converting a point with the resulting matrix is equivalent to first convert the point
+     * with {@code ordinates[srcDim] = ordinates[srcDim] * scale + offset}, then apply the original matrix.
      *
-     * <div class="section">Comparison with Java2D</div>
+     * <div class="section">Equivalence between this method and Java2D {@code AffineTransform} methods</div>
      * If this matrix was an instance of Java2D {@link AffineTransform}, then invoking this method would
      * be equivalent to invoke the following {@code AffineTransform} methods in the order shown below:
      *
-     * <table class="sis">
-     *   <caption>Equivalence between this method and {@code AffineTransform} ({@code at}) methods</caption>
+     * <table class="sis" summary="Equivalence between this method and AffineTransform methods">
      *   <tr>
-     *     <th>{@code concatenate(0, scale, offset)}</th>
-     *     <th class="sep">{@code concatenate(1, scale, offset)}</th>
-     *   </tr>
-     *   <tr>
-     *     <td><code>at.{@linkplain AffineTransform#translate(double, double) translate}(offset, 0)</code></td>
-     *     <td class="sep"><code>at.{@linkplain AffineTransform#translate(double, double) translate}(0, offset)</code></td>
-     *   </tr>
-     *   <tr>
-     *     <td><code>at.{@linkplain AffineTransform#scale(double, double) scale}(scale, 1)</code></td>
-     *     <td class="sep"><code>at.{@linkplain AffineTransform#scale(double, double) scale}(1, scale)</code></td>
+     *     <th>{@code MatrixSIS} method</th>
+     *     <th class="sep">{@code AffineTransform} methods</th>
+     *   </tr><tr>
+     *     <td>{@code concatenate(0, scale, offset)}</td>
+     *     <td class="sep"><code>at.{@linkplain AffineTransform#translate(double, double) translate}(offset, 0);
+     *     at.{@linkplain AffineTransform#scale(double, double) scale}(scale, 1);</code></td>
+     *   </tr><tr>
+     *     <td class="hsep">{@code concatenate(1, scale, offset)}</td>
+     *     <td class="hsep sep"><code>at.{@linkplain AffineTransform#translate(double, double) translate}(0, offset);
+     *     at.{@linkplain AffineTransform#scale(double, double) scale}(1, scale);</code></td>
      *   </tr>
      * </table>
      *
@@ -359,7 +351,7 @@ public abstract class MatrixSIS implemen
      *
      * @since 0.6
      */
-    public void concatenate(final int srcDim, final Number scale, final Number offset) {
+    public void convertBefore(final int srcDim, final Number scale, final Number offset) {
         final int lastCol = getNumCol() - 1;
         ArgumentChecks.ensureValidIndex(lastCol, srcDim);
         final DoubleDouble s = new DoubleDouble();
@@ -381,12 +373,45 @@ public abstract class MatrixSIS implemen
     }
 
     /**
+     * Assuming that this matrix represents an affine transform, pre-concatenates a scale and a translation on the
+     * given dimension. Converting a point with the resulting matrix is equivalent to first convert the point with
+     * the original matrix, then convert the result with {@code ordinates[tgtDim] = ordinates[tgtDim] * scale + offset}.
+     *
+     * @param tgtDim The dimension of the ordinate to rescale in the target coordinates.
+     * @param scale  The amount by which to multiply the target ordinate value after this transform, or {@code null} if none.
+     * @param offset The amount by which to translate the target ordinate value after this transform, or {@code null} if none.
+     * @throws UnsupportedOperationException if this matrix is unmodifiable.
+     *
+     * @see AffineTransform#preConcatenate(AffineTransform)
+     *
+     * @since 0.6
+     */
+    public void convertAfter(final int tgtDim, final Number scale, final Number offset) {
+        final int lastRow = getNumRow() - 1;
+        final int lastCol = getNumCol() - 1;
+        ArgumentChecks.ensureValidIndex(lastRow, tgtDim);
+        final DoubleDouble s = new DoubleDouble();
+        if (scale != null) {
+            for (int i=lastCol; i>=0; i--) {
+                get(tgtDim, i, s);
+                s.multiply(scale);
+                set(tgtDim, i, s);
+            }
+        }
+        if (offset != null) {
+            get(tgtDim, lastCol, s);
+            s.add(offset);
+            set(tgtDim, lastCol, s);
+        }
+    }
+
+    /**
      * Returns a new matrix which is the result of multiplying this matrix with the specified one.
      * In other words, returns {@code this} × {@code matrix}.
      *
      * <div class="section">Relationship with coordinate operations</div>
      * In the context of coordinate operations, {@code Matrix.multiply(other)} is equivalent to
-     * <code>{@linkplain java.awt.geom.AffineTransform#concatenate AffineTransform.concatenate}(other)</code>:
+     * <code>{@linkplain AffineTransform#concatenate AffineTransform.concatenate}(other)</code>:
      * first transforms by the supplied transform and then transform the result by the original transform.
      *
      * @param  matrix The matrix to multiply to this matrix.
@@ -423,7 +448,7 @@ public abstract class MatrixSIS implemen
      * @return The inverse of this matrix.
      * @throws NoninvertibleMatrixException if this matrix is not invertible.
      *
-     * @see java.awt.geom.AffineTransform#createInverse()
+     * @see AffineTransform#createInverse()
      */
     public MatrixSIS inverse() throws NoninvertibleMatrixException {
         return Solver.inverse(this, true);

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -16,19 +16,20 @@
  */
 package org.apache.sis.referencing.operation.projection;
 
+import java.util.Map;
+import java.util.EnumMap;
 import org.opengis.util.FactoryException;
+import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.TransformException;
-import org.apache.sis.internal.referencing.provider.AbstractMercator;
 import org.apache.sis.internal.referencing.provider.Mercator1SP;
 import org.apache.sis.internal.referencing.provider.Mercator2SP;
 import org.apache.sis.internal.referencing.provider.MercatorSpherical;
 import org.apache.sis.internal.referencing.provider.RegionalMercator;
-import org.apache.sis.internal.referencing.provider.MillerCylindrical;
 import org.apache.sis.internal.referencing.provider.PseudoMercator;
 import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
@@ -86,6 +87,8 @@ public class Mercator extends Normalized
      *
      * <p><b>CONVENTION:</b> Spherical cases must be odd, all other cases must be even. This allow us to perform
      * quick checks for all spherical cases using {@code if ((type & SPHERICAL) != 0)}.</p>
+     *
+     * @see #getType(ParameterDescriptorGroup)
      */
     static final byte SPHERICAL = 1, PSEUDO = 3,    // Must be odd and SPHERICAL must be 1.
                       REGIONAL  = 2, MILLER = 4;    // Must be even.
@@ -107,6 +110,56 @@ public class Mercator extends Normalized
     final byte type;
 
     /**
+     * Returns the (<var>role</var> → <var>parameter</var>) associations for a Mercator projection of the given type.
+     *
+     * @param  type One of {@link #REGIONAL}, {@link #SPHERICAL}, {@link #PSEUDO} or {@link #MILLER} constants.
+     * @return The roles map to give to super-class constructor.
+     */
+    @SuppressWarnings("fallthrough")
+    private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte type) {
+        final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class);
+        /*
+         * "Longitude of origin" is a parameter of all Mercator projections, but is intentionally omitted from
+         * this map because it will be handled in a special way by the Mercator constructor. The "scale factor"
+         * is not formally a "Mercator 2SP" argument, but we accept it anyway for all Mercator projections
+         * since it may be used in some Well Known Text (WKT).
+         */
+        roles.put(ParameterRole.SCALE_FACTOR, Mercator1SP.SCALE_FACTOR);
+        switch (type) {
+            case REGIONAL: {
+                roles.put(ParameterRole.FALSE_EASTING,  RegionalMercator.EASTING_AT_FALSE_ORIGIN);
+                roles.put(ParameterRole.FALSE_NORTHING, RegionalMercator.NORTHING_AT_FALSE_ORIGIN);
+                break;
+            }
+            case SPHERICAL: {
+                /*
+                 * According to EPSG guide, the latitude of conformal sphere radius should be the latitude of origin.
+                 * However that origin is fixed to 0° by EPSG guide, which makes radius calculation ineffective when
+                 * using the official parameters. We could fallback on the standard parallel (φ1) if φ0 is not set,
+                 * but for now we wait to see for real cases. Some arguments that may be worth consideration:
+                 *
+                 *   - The standard parallel is not an EPSG parameter for Spherical case.
+                 *   - Users who set the standard parallel anyway may expect that latitude to be used for radius
+                 *     calculation, since standard parallels are also known as "latitude of true scale".
+                 *   - Using the standard parallel instead than the latitude of origin would be consistent
+                 *     with what EPSG does for the Equirectangular projection.
+                 *
+                 * Anyway, this choice matters only when the user request explicitely spherical formulas applied
+                 * on an ellipsoidal figure of the Earth, which should be very rare.
+                 */
+                roles.put(ParameterRole.LATITUDE_OF_CONFORMAL_SPHERE_RADIUS, Mercator1SP.LATITUDE_OF_ORIGIN);
+                // Fall through
+            }
+            default: {
+                roles.put(ParameterRole.FALSE_EASTING,  Mercator1SP.FALSE_EASTING);
+                roles.put(ParameterRole.FALSE_NORTHING, Mercator1SP.FALSE_NORTHING);
+                break;
+            }
+        }
+        return roles;
+    }
+
+    /**
      * Creates a Mercator projection from the given parameters.
      * The {@code method} argument can be the description of one of the following:
      *
@@ -132,21 +185,7 @@ public class Mercator extends Normalized
      */
     @Workaround(library="JDK", version="1.7")
     private Mercator(final OperationMethod method, final Parameters parameters, final byte type) {
-        super(method, parameters,
-                (type == SPHERICAL) ? Mercator2SP     .STANDARD_PARALLEL        : null,     // See note below.
-                (type == REGIONAL ) ? RegionalMercator.EASTING_AT_FALSE_ORIGIN  : AbstractMercator.FALSE_EASTING,
-                (type == REGIONAL ) ? RegionalMercator.NORTHING_AT_FALSE_ORIGIN : AbstractMercator.FALSE_NORTHING);
-        /*
-         * Note on above Mercator2SP.STANDARD_PARALLEL argument (used for computing radius of conformal sphere):
-         * according the EPSG guide we should rather use Mercator2SP.LATITUDE_OF_ORIGIN. But the later is fixed
-         * to 0° by EPSG guide, which makes radius calculation ineffective when using the official parameters.
-         * Given that we already allow usage of Mercator2SP.STANDARD_PARALLEL (which is not an EPSG parameter)
-         * for compatibility reasons, user who set the standard parallel may expect this latitude to be used for
-         * radius calculation. Using the standard parallel instead than the latitude of origin is also consistent
-         * with what EPSG does for the Equirectangular projection. Anyway, this choice matters only when the user
-         * request explicitely spherical formulas applied on an ellipsoidal figure of the Earth, which should be
-         * very rare.
-         */
+        super(method, parameters, roles(type));
         this.type = type;
         /*
          * The "Longitude of natural origin" parameter is found in all Mercator projections and is mandatory.
@@ -175,13 +214,12 @@ public class Mercator extends Normalized
          * if they really want, since we sometime see such CRS definitions.
          */
         final double φ1 = toRadians(getAndStore(parameters, Mercator2SP.STANDARD_PARALLEL));
-        double k0 = getAndStore(parameters, Mercator1SP.SCALE_FACTOR);
-        k0 *= cos(φ1) / rν(sin(φ1));
+        final DoubleDouble k0 = new DoubleDouble(cos(φ1), 0);
+        k0.divide(rν(sin(φ1)), 0);
         /*
          * In principle we should rotate the central meridian (λ0) in the normalization transform, as below:
          *
-         *     context.normalizeGeographicInputs(λ0);
-         *     context.scaleAndTranslate2D(false, k0, 0, 0);
+         *     context.normalizeGeographicInputs(λ0);   // Actually done by the super-class constructor.
          *
          * However in the particular case of Mercator projection, we will apply the longitude rotation in the
          * denormalization matrix instead.   This is possible only for this particular projection because the
@@ -189,19 +227,20 @@ public class Mercator extends Normalized
          * simple as possible, we increase the chances of efficient concatenation of an inverse with a forward
          * projection.
          */
-        final MatrixSIS   normalize = context.normalizeGeographicInputs(0);
-        final MatrixSIS denormalize = context.scaleAndTranslate2D(false, k0, 0, 0);
+        final MatrixSIS denormalize = context.getMatrix(false);
+        denormalize.convertBefore(0, k0, null);
+        denormalize.convertBefore(1, k0, null);
         if (λ0 != 0) {
             final DoubleDouble offset = DoubleDouble.createDegreesToRadians();
             offset.multiply(-λ0);
-            denormalize.concatenate(0, null, offset);
+            denormalize.convertBefore(0, null, offset);
         }
         if (φ0 != 0) {
-            denormalize.concatenate(1, null, new DoubleDouble(-log(expOfNorthing(φ0, excentricity * sin(φ0)))));
+            denormalize.convertBefore(1, null, new DoubleDouble(-log(expOfNorthing(φ0, excentricity * sin(φ0)))));
         }
         if (type == MILLER) {
-            normalize  .concatenate(1, new DoubleDouble(0.8),  null);
-            denormalize.concatenate(1, new DoubleDouble(1.25), null);
+            context.getMatrix(true).convertBefore(1, new DoubleDouble(0.8), null);
+            denormalize.convertBefore(1, new DoubleDouble(1.25), null);
         }
     }
 
@@ -217,10 +256,10 @@ public class Mercator extends Normalized
      * Returns the type of the projection based on the name and identifier of the given parameter group.
      */
     private static byte getType(final ParameterDescriptorGroup parameters) {
-        if (identMatch(parameters, RegionalMercator .NAME, RegionalMercator .IDENTIFIER)) return REGIONAL;
-        if (identMatch(parameters, MercatorSpherical.NAME, MercatorSpherical.IDENTIFIER)) return SPHERICAL;
-        if (identMatch(parameters, PseudoMercator   .NAME, PseudoMercator   .IDENTIFIER)) return PSEUDO;
-        if (identMatch(parameters, MillerCylindrical.NAME, null))                         return MILLER;
+        if (identMatch(parameters, "(?i).*\\bvariant\\s*C\\b.*", RegionalMercator .IDENTIFIER)) return REGIONAL;
+        if (identMatch(parameters, "(?i).*\\bSpherical\\b.*",    MercatorSpherical.IDENTIFIER)) return SPHERICAL;
+        if (identMatch(parameters, "(?i).*\\bPseudo.*",          PseudoMercator   .IDENTIFIER)) return PSEUDO;
+        if (identMatch(parameters, "(?i).*\\bMiller.*",          null))                         return MILLER;
         return 0;
     }
 
@@ -246,9 +285,9 @@ public class Mercator extends Normalized
     }
 
     /**
-     * Converts the specified (<var>λ</var>,<var>φ</var>) coordinate (units in radians)
-     * and stores the result in {@code dstPts} (linear distance on a unit sphere). In addition,
-     * opportunistically computes the projection derivative if {@code derivate} is {@code true}.
+     * Converts the specified (λ,φ) coordinate (units in radians) and stores the result in {@code dstPts}
+     * (linear distance on a unit sphere). In addition, opportunistically computes the projection derivative
+     * if {@code derivate} is {@code true}.
      *
      * @return The matrix of the projection derivative at the given source position,
      *         or {@code null} if the {@code derivate} argument is {@code false}.
@@ -363,8 +402,10 @@ public class Mercator extends Normalized
      * </ul>
      * </div>
      *
-     * @author Martin Desruisseaux (MPO, IRD, Geomatys)
-     * @author Rueben Schulz (UBC)
+     * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
+     * @author  Rueben Schulz (UBC)
+     * @since   0.6
+     * @version 0.6
      * @module
      */
     static final class Spherical extends Mercator {
@@ -376,7 +417,7 @@ public class Mercator extends Normalized
         /**
          * Constructs a new map projection from the parameters of the given projection.
          *
-         * @param other  The other projection (usually ellipsoidal) from which to copy the parameters.
+         * @param other The other projection (usually ellipsoidal) from which to copy the parameters.
          */
         Spherical(final Mercator other) {
             super(other);

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -18,12 +18,16 @@ package org.apache.sis.referencing.opera
 
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Map;
+import java.util.EnumMap;
 import java.io.Serializable;
 import org.opengis.metadata.Identifier;
+import org.opengis.parameter.ParameterValue;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.GeneralParameterDescriptor;
+import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransform2D;
@@ -38,10 +42,12 @@ import org.apache.sis.parameter.Paramete
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.AbstractMathTransform2D;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
 import org.apache.sis.internal.referencing.provider.MapProjection;
 import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.Numerics;
 
@@ -68,8 +74,7 @@ import java.util.Objects;
  *   <li>On output, the {@link #transform(double[],int,double[],int,boolean) transform(…)} method returns
  *   (<var>x</var>, <var>y</var>) values on a sphere or ellipse having a semi-major axis length (<var>a</var>) of 1.
  *   The multiplication by the scale factor (<var>k</var>₀) and the translation by false easting (FE) and false
- *   northing (FN) are applied by the {@linkplain ContextualParameters#scaleAndTranslate2D denormalization}
- *   affine transform.</li>
+ *   northing (FN) are applied by the {@linkplain ContextualParameters#getMatrix denormalization} affine transform.</li>
  * </ul>
  *
  * The normalization and denormalization steps are represented below by the matrices immediately on the left and right
@@ -120,6 +125,7 @@ import java.util.Objects;
  * @version 0.6
  * @module
  *
+ * @see ContextualParameters
  * @see <a href="http://mathworld.wolfram.com/MapProjection.html">Map projections on MathWorld</a>
  */
 public abstract class NormalizedProjection extends AbstractMathTransform2D implements Serializable {
@@ -183,6 +189,168 @@ public abstract class NormalizedProjecti
     private final MathTransform2D inverse;
 
     /**
+     * Maps the parameters to be used for initializing {@link NormalizedProjection} and its
+     * {@linkplain ContextualParameters#getMatrix(boolean) normalization / denormalization} matrices.
+     * This is an enumeration of parameters found in almost every map projections, but under different names.
+     * This enumeration allows {@code NormalizedProjection} subclasses to specify which parameter names, ranges
+     * and default values should be used by the
+     * {@linkplain NormalizedProjection#NormalizedProjection(OperationMethod, Parameters, Map) projection constructor}.
+     *
+     * <p>{@code NormalizedProjection} subclasses will typically provide values only for the following keys:
+     * {@link #CENTRAL_MERIDIAN}, {@link #SCALE_FACTOR}, {@link #FALSE_EASTING} and {@link #FALSE_NORTHING}.</p>
+     *
+     * @author  Martin Desruisseaux (Geomatys)
+     * @since   0.6
+     * @version 0.6
+     * @module
+     *
+     * @see NormalizedProjection#NormalizedProjection(OperationMethod, Parameters, Map)
+     */
+    protected static enum ParameterRole {
+        /**
+         * Maps the <cite>semi-major axis length</cite> parameter (symbol: <var>a</var>).
+         * This value is used for computing {@link NormalizedProjection#excentricity},
+         * and is also a multiplication factor for the denormalization matrix.
+         *
+         * <p>Unless specified otherwise, this is always mapped to a parameter named {@code "semi_major"}.
+         * {@code NormalizedProjection} subclasses typically do not need to provide a value for this key.</p>
+         */
+        SEMI_MAJOR(Constants.SEMI_MAJOR),
+
+        /**
+         * Maps the <cite>semi-minor axis length</cite> parameter (symbol: <var>b</var>).
+         * This value is used for computing {@link NormalizedProjection#excentricity}.
+         *
+         * <p>Unless specified otherwise, this is always mapped to a parameter named {@code "semi_minor"}.
+         * {@code NormalizedProjection} subclasses typically do not need to provide a value for this key.</p>
+         */
+        SEMI_MINOR(Constants.SEMI_MINOR),
+
+        /**
+         * Maps the parameter for the latitude where to compute the <cite>radius of conformal sphere</cite>
+         * (symbol: <var>R</var><sub>c</sub>). If this parameter is provided, then the radius of the conformal
+         * sphere at latitude φ will be used instead than the semi-major axis length in the denormalisation matrix.
+         * In other words, if provided then <var>a</var> is replaced by <var>R</var><sub>c</sub> below:
+         *
+         * <center>{@include ../transform/formulas.html#DenormalizeCartesian}</center>
+         *
+         * <p>This enumeration shall be used <strong>only</strong> when the user requested explicitely spherical
+         * formulas, for example the <cite>"Mercator (Spherical)"</cite> projection (EPSG:1026), but the figure
+         * of the Earth may be an ellipsoid rather than a sphere. In the majority of cases, this enumeration should
+         * not be used.</p>
+         */
+        LATITUDE_OF_CONFORMAL_SPHERE_RADIUS(null),
+
+        /**
+         * Maps the <cite>central meridian</cite> parameter (symbol: λ₀).
+         * This value is subtracted from the longitude values before the map projections.
+         *
+         * <p>Some common names for this parameter are:</p>
+         * <ul>
+         *   <li>Longitude of origin</li>
+         *   <li>Longitude of false origin</li>
+         *   <li>Longitude of natural origin</li>
+         *   <li>Spherical longitude of origin</li>
+         *   <li>Longitude of projection centre</li>
+         * </ul>
+         */
+        CENTRAL_MERIDIAN(Constants.CENTRAL_MERIDIAN),
+
+        /**
+         * Maps the <cite>scale factor</cite> parameter (symbol: <var>k</var>₀).
+         * This is a multiplication factor for the (<var>x</var>,<var>y</var>) values obtained after map projections.
+         *
+         * <p>Some common names for this parameter are:</p>
+         * <ul>
+         *   <li>Scale factor at natural origin</li>
+         *   <li>Scale factor on initial line</li>
+         *   <li>Scale factor on pseudo standard parallel</li>
+         * </ul>
+         */
+        SCALE_FACTOR(Constants.SCALE_FACTOR),
+
+        /**
+         * Maps the <cite>false easting</cite> parameter (symbol: <var>FE</var>).
+         * This is a translation term for the <var>x</var> values obtained after map projections.
+         *
+         * <p>Some common names for this parameter are:</p>
+         * <ul>
+         *   <li>False easting</li>
+         *   <li>Easting at false origin</li>
+         *   <li>Easting at projection centre</li>
+         * </ul>
+         */
+        FALSE_EASTING(Constants.FALSE_EASTING),
+
+        /**
+         * Maps the <cite>false northing</cite> parameter (symbol: <var>FN</var>).
+         * This is a translation term for the <var>y</var> values obtained after map projections.
+         *
+         * <p>Some common names for this parameter are:</p>
+         * <ul>
+         *   <li>False northing</li>
+         *   <li>Northing at false origin</li>
+         *   <li>Northing at projection centre</li>
+         * </ul>
+         */
+        FALSE_NORTHING(Constants.FALSE_NORTHING);
+
+        /**
+         * The OGC name for this parameter. This is used only when inferring automatically the role map.
+         * We use the OGC name instead than the EPSG name because OGC names are identical for a wider
+         * range of projections (e.g. {@code "scale_factor"} for almost all projections).
+         */
+        private final String name;
+
+        /**
+         * Creates a new parameter role associated to the given OGC name.
+         */
+        private ParameterRole(final String name) {
+            this.name = name;
+        }
+
+        /**
+         * Provides default (<var>role</var> → <var>parameter</var>) associations for the given map projection.
+         * This is a convenience method for a typical set of parameters found in map projections.
+         * This method expects a {@code projection} argument containing descriptors for the given parameters
+         * (using OGC names):
+         *
+         * <ul>
+         *   <li>{@code "semi_major"}</li>
+         *   <li>{@code "semi_minor"}</li>
+         *   <li>{@code "central_meridian"}</li>
+         *   <li>{@code "scale_factor"}</li>
+         *   <li>{@code "false_easting"}</li>
+         *   <li>{@code "false_northing"}</li>
+         * </ul>
+         *
+         * <div class="note"><b>Note:</b>
+         * Apache SIS uses EPSG names as much as possible, but this method is an exception to this rule.
+         * In this particular case we use OGC names because they are identical for a wide range of projections.
+         * For example there is at least {@linkplain #SCALE_FACTOR three different EPSG names} for the
+         * <cite>"scale factor"</cite> parameter, which OGC defines only {@code "scale_factor"} for all of them.</div>
+         *
+         * @param  projection The map projection method for which to infer (<var>role</var> → <var>parameter</var>) associations.
+         * @return The parameters associated to most role in this enumeration.
+         * @throws ParameterNotFoundException if one of the above-cited parameters is not found in the given projection method.
+         * @throws ClassCastException if a parameter has been found but is not an instance of {@code ParameterDescriptor<Double>}.
+         */
+        public static Map<ParameterRole, ParameterDescriptor<Double>> defaultMap(final OperationMethod projection)
+                throws ParameterNotFoundException, ClassCastException
+        {
+            final ParameterDescriptorGroup parameters = projection.getParameters();
+            final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class);
+            for (final ParameterRole role : values()) {
+                if (role.name != null) {
+                    final GeneralParameterDescriptor p = parameters.descriptor(role.name);
+                    roles.put(role, Parameters.cast((ParameterDescriptor<?>) p, Double.class));
+                }
+            }
+            return roles;
+        }
+    }
+
+    /**
      * Constructs a new map projection from the supplied parameters.
      * This constructor applies the following operations on the {@link ContextualParameter}:
      *
@@ -196,123 +364,112 @@ public abstract class NormalizedProjecti
      *   </li>
      *   <li>On the <b>denormalization</b> matrix (to be applied after {@code this} transform):
      *     <ul>
-     *       <li>{@linkplain ContextualParameters#scaleAndTranslate2D(boolean, double, double, double) Scale}
-     *           by the <cite>semi-major</cite> axis length.</li>
+     *       <li>{@linkplain MatrixSIS#convertAfter(int, Number, Number) Scale} by the <cite>semi-major</cite> axis length.</li>
+     *       <li>If a scale factor is present (not all map projections have a scale factor), apply that scale.</li>
      *       <li>Translate by the <cite>false easting</cite> and <cite>false northing</cite> (after the scale).</li>
      *     </ul>
      *   </li>
      *   <li>On the <b>contextual parameters</b> (not the parameters of {@code this} transform):
      *     <ul>
      *       <li>Store the values for <cite>semi-major</cite> axis length, <cite>semi-minor</cite> axis length,
-     *           <cite>central meridian</cite>, <cite>false easting</cite> and <cite>false northing</cite> values.</li>
+     *         <cite>scale factor</cite> (if present), <cite>central meridian</cite>,
+     *         <cite>false easting</cite> and <cite>false northing</cite> values.</li>
      *     </ul>
      *   </li>
      * </ul>
      *
-     * <div class="section">Pre-requite</div>
-     * The parameters of the given {@code method} argument shall contains descriptor for the given parameters
-     * (using OGC names):
-     * <ul>
-     *   <li>{@code "semi_major"}       (mandatory)</li>
-     *   <li>{@code "semi_minor"}       (mandatory)</li>
-     *   <li>{@code "central_meridian"} (optional, default to 0°)</li>
-     *   <li>{@code "false_easting"}    (optional, default to 0 metre)</li>
-     *   <li>{@code "false_northing"}   (optional, default to 0 metre)</li>
-     * </ul>
-     *
-     * <div class="note"><b>Note:</b>
-     * Apache SIS uses EPSG names as much as possible, but this constructor is an exception to this rule.
-     * In this particular case we use OGC names because they are identical for a wide range of projections.
-     * For example there is at least two different EPSG names for the <cite>false northing</cite> parameter,
-     * depending on the projection:
+     * In matrix form, this constructor creates the following matrices (subclasses are free to modify):
+     * <table class="sis">
+     *   <caption>Initial matrix coefficients after construction</caption>
+     *   <tr>
+     *     <th>Normalization</th>
+     *     <th class="sep">Denormalization</th>
+     *   </tr>
+     *   <tr>
+     *     <td>{@include ../transform/formulas.html#NormalizeGeographic}</td>
+     *     <td class="sep">{@include ../transform/formulas.html#DenormalizeCartesian}</td>
+     *   </tr>
+     * </table>
+     *
+     * <div class="section">Which parameters are considered</div>
+     * The {@code roles} map specifies which parameters to look for <cite>central meridian</cite>,
+     * <cite>scale factor</cite>, <cite>false easting</cite>, <cite>false northing</cite> and other values.
+     * All entries in the {@code roles} map are optional.
+     * All descriptors in the map shall comply to the following constraints:
      *
      * <ul>
-     *   <li><cite>Northing at false origin</cite></li>
-     *   <li><cite>Northing at projection centre</cite></li>
+     *   <li>Descriptors associated to {@link ParameterRole#SEMI_MAJOR}, {@link ParameterRole#SEMI_MINOR SEMI_MINOR},
+     *     {@link ParameterRole#FALSE_EASTING FALSE_EASTING} and {@link ParameterRole#FALSE_NORTHING FALSE_NORTHING}
+     *     shall have the same linear unit of measurement (usually metre).</li>
+     *   <li>Descriptors associated to angular measures ({@link ParameterRole#CENTRAL_MERIDIAN} and
+     *     {@link ParameterRole#LATITUDE_OF_CONFORMAL_SPHERE_RADIUS LATITUDE_OF_CONFORMAL_SPHERE_RADIUS})
+     *     shall use degrees.</li>
      * </ul>
      *
-     * OGC defines only {@code "false_northing"} for all, which makes a convenient name to look for in this
-     * constructor.</div>
+     * Note that users can still use units of their choice in the {@link Parameters} object given in argument to
+     * this constructor. But those values will be converted to the units of measurement specified by the parameter
+     * descriptors in the {@code roles} map, which must be the above-cited units.
      *
      * @param method     Description of the map projection parameters.
      * @param parameters The parameters of the projection to be created.
+     * @param roles Parameters to look for <cite>central meridian</cite>, <cite>scale factor</cite>,
+     *        <cite>false easting</cite>, <cite>false northing</cite> and other values, or {@code null}
+     *        for the {@linkplain ParameterRole#defaultMap(OperationMethod) default associations}.
      */
-    protected NormalizedProjection(final OperationMethod method, final Parameters parameters) {
-        this(method, parameters, null,
-                descriptor(method, Constants.FALSE_EASTING),
-                descriptor(method, Constants.FALSE_NORTHING));
-        context.normalizeGeographicInputs(getAndStore(parameters, descriptor(method, Constants.CENTRAL_MERIDIAN)));
-    }
-
-    /**
-     * Returns the parameter descriptor for the given name.
-     * This is a helper method for above constructor only.
-     */
-    private static ParameterDescriptor<Double> descriptor(final OperationMethod method, final String name) {
-        ensureNonNull("method", method);
-        return Parameters.cast((ParameterDescriptor<?>) method.getParameters().descriptor(name), Double.class);
-    }
-
-    /**
-     * Constructs a new map projection by fetching the values using the given parameter descriptors.
-     * At the difference of the {@link #NormalizedProjection(OperationMethod, Parameters)} constructor,
-     * this constructor does <strong>not</strong> apply the following operations:
-     *
-     * <ul>
-     *   <li>Normalization: no operation done. Callers shall invoke
-     *     {@link ContextualParameters#normalizeGeographicInputs(double)} themselves.</li>
-     * </ul>
-     *
-     *
-     * <div class="section">Radius of conformal sphere (Rc)</div>
-     * If the {@code conformalSphereAtφ} argument is non-null, then the radius of the conformal sphere
-     * at latitude φ will be used instead than the semi-major axis length <var>a</var> (<b>Source:</b>
-     * <cite>Geomatics Guidance Note Number 7, part 2, version 49</cite> from EPSG: table 3 in section
-     * 1.2 and explanation in section 1.3.3.1).
-     *
-     * <p><b>Important usage notes:</b><p>
-     * <ul>
-     *   <li>The {@code conformalSphereAtφ} argument shall be non-null <strong>only</strong> when the user
-     *       requested explicitely spherical formulas, for example the <cite>"Mercator (Spherical)"</cite>
-     *       projection (EPSG:1026), but the figure of the Earth is an ellipsoid rather than a sphere.</li>
-     *   <li>This parameter value is <strong>not</strong> stored since we presume that the caller will fetch
-     *       the value for its own processing.</li>
-     * </ul>
-     *
-     * @param conformalSphere_φ If non-null, the the latitude where to compute the radius of conformal sphere.
-     * @param falseEasting      The descriptor for fetching the <cite>"False easting"</cite> parameter.
-     * @param falseNorthing     The descriptor for fetching the <cite>"False northing"</cite> parameter.
-     */
-    NormalizedProjection(final OperationMethod method, final Parameters parameters,
-            final ParameterDescriptor<Double> conformalSphere_φ,
-            final ParameterDescriptor<Double> falseEasting,
-            final ParameterDescriptor<Double> falseNorthing)
+    protected NormalizedProjection(final OperationMethod method, final Parameters parameters,
+            Map<ParameterRole, ? extends ParameterDescriptor<Double>> roles)
     {
+        ensureNonNull("method", method);
         ensureNonNull("parameters", parameters);
+        if (roles == null) {
+            roles = ParameterRole.defaultMap(method);
+        }
         context = new ContextualParameters(method);
-              double a  = getAndStore(parameters, MapProjection.SEMI_MAJOR);
-        final double b  = getAndStore(parameters, MapProjection.SEMI_MINOR);
-        final double fe = getAndStore(parameters, falseEasting);
-        final double fn = getAndStore(parameters, falseNorthing);
+        /*
+         * Note: we do not use Map.getOrDefault(K,V) below because the user could have explicitly associated
+         * a null value to keys (we are paranoiac...) and because it conflicts with the "? extends" part of
+         * in this constructor signature.
+         */
+        ParameterDescriptor<Double> semiMajor = roles.get(ParameterRole.SEMI_MAJOR);
+        ParameterDescriptor<Double> semiMinor = roles.get(ParameterRole.SEMI_MINOR);
+        if (semiMajor == null) semiMajor = MapProjection.SEMI_MAJOR;
+        if (semiMinor == null) semiMinor = MapProjection.SEMI_MINOR;
+
+              double a  = getAndStore(parameters, semiMajor);
+        final double b  = getAndStore(parameters, semiMinor);
+        final double λ0 = getAndStore(parameters, roles.get(ParameterRole.CENTRAL_MERIDIAN));
+        final double fe = getAndStore(parameters, roles.get(ParameterRole.FALSE_EASTING));
+        final double fn = getAndStore(parameters, roles.get(ParameterRole.FALSE_NORTHING));
         final double rs = b / a;
         excentricitySquared = 1 - (rs * rs);
         excentricity = sqrt(excentricitySquared);
-        if (conformalSphere_φ != null && excentricitySquared != 0) {
-            /*
-             * EPSG said: R is the radius of the sphere and will normally be one of the CRS parameters.
-             * If the figure of the earth used is an ellipsoid rather than a sphere then R should be calculated
-             * as the radius of the conformal sphere at the projection origin at latitude φ₀ using the formula
-             * for Rc given in section 1.2, table 3.
-             *
-             * Table 3 gives:
-             * Radius of conformal sphere Rc = a √(1 – ℯ²) / (1 – ℯ²⋅sin²φ)
-             *
-             * Using √(1 – ℯ²) = b/a we rewrite as: Rc = b / (1 – ℯ²⋅sin²φ)
-             */
-            final double sinφ = sin(toRadians(parameters.doubleValue(conformalSphere_φ)));
-            a = b / (1 - excentricitySquared * (sinφ*sinφ));
+        if (excentricitySquared != 0) {
+            final ParameterDescriptor<Double> radius = roles.get(ParameterRole.LATITUDE_OF_CONFORMAL_SPHERE_RADIUS);
+            if (radius != null) {
+                /*
+                 * EPSG said: R is the radius of the sphere and will normally be one of the CRS parameters.
+                 * If the figure of the earth used is an ellipsoid rather than a sphere then R should be calculated
+                 * as the radius of the conformal sphere at the projection origin at latitude φ₀ using the formula
+                 * for Rc given in section 1.2, table 3.
+                 *
+                 * Table 3 gives:
+                 * Radius of conformal sphere Rc = a √(1 – ℯ²) / (1 – ℯ²⋅sin²φ)
+                 *
+                 * Using √(1 – ℯ²) = b/a we rewrite as: Rc = b / (1 – ℯ²⋅sin²φ)
+                 */
+                final double sinφ = sin(toRadians(parameters.doubleValue(radius)));
+                a = b / (1 - excentricitySquared * (sinφ*sinφ));
+            }
+        }
+        context.normalizeGeographicInputs(λ0);
+        final DoubleDouble k = new DoubleDouble(a);
+        final ParameterDescriptor<Double> scaleFactor = roles.get(ParameterRole.SCALE_FACTOR);
+        if (scaleFactor != null) {
+            k.multiply(getAndStore(parameters, scaleFactor));
         }
-        context.scaleAndTranslate2D(false, a, fe, fn);
+        final MatrixSIS denormalize = context.getMatrix(false);
+        denormalize.convertAfter(0, k, new DoubleDouble(fe));
+        denormalize.convertAfter(1, k, new DoubleDouble(fn));
         inverse = new Inverse();
     }
 
@@ -330,23 +487,30 @@ public abstract class NormalizedProjecti
     }
 
     /**
-     * Returns {@code true} if the projection specified by the given parameters has the given name or identifier.
-     * If non-null, the given identifier is presumed in the EPSG namespace and has precedence over the name.
+     * Returns {@code true} if the projection specified by the given parameters has the given keyword or identifier.
+     * If non-null, the given identifier is presumed in the EPSG namespace and has precedence over the keyword.
+     *
+     * <div class="note"><b>Implementation note:</b>
+     * Since callers usually give a constant string for the {@code regex} argument, it would be more efficient to
+     * compile the {@link java.util.regex.Pattern} once for all. However the regular expression is used only as a
+     * fallback if the descriptor does not contain EPSG identifier, which should be rare. Usually, the regular
+     * expression will never be compiled.</div>
      *
      * @param  parameters The user-specified parameters.
-     * @param  name       The name to compare against the parameter group name.
+     * @param  regex      The regular expression to use when using the operation name as the criterion.
      * @param  identifier The identifier to compare against the parameter group name.
-     * @return {@code true} if the given parameter group has a name or EPSG identifier matching the given ones.
+     * @return {@code true} if the given parameter group name contains the given keyword
+     *         or has an EPSG identifier equals to the given identifier.
      */
-    static boolean identMatch(final ParameterDescriptorGroup parameters, final String name, final String identifier) {
+    static boolean identMatch(final ParameterDescriptorGroup parameters, final String regex, final String identifier) {
         if (identifier != null) {
             for (final Identifier id : parameters.getIdentifiers()) {
-                if (identifier.equals(id.getCode()) && Constants.EPSG.equals(id.getCodeSpace())) {
-                    return true;
+                if (Constants.EPSG.equals(id.getCodeSpace())) {
+                    return identifier.equals(id.getCode());
                 }
             }
         }
-        return IdentifiedObjects.isHeuristicMatchForName(parameters, name);
+        return parameters.getName().getCode().matches(regex);
     }
 
     /**
@@ -354,10 +518,43 @@ public abstract class NormalizedProjecti
      * A "contextual parameter" is a parameter that apply to the normalize → {@code this} → denormalize
      * chain as a whole. It does not really apply to this {@code NormalizedProjection} instance when taken alone.
      *
-     * <p>This method shall be invoked at construction time only.</p>
+     * <p>This method performs the following actions:</p>
+     * <ul>
+     *   <li>Convert the value to the units specified by the descriptor.</li>
+     *   <li>Ensure that the value is contained in the range specified by the descriptor.</li>
+     *   <li>Store the value only if different than the default value.</li>
+     * </ul>
+     *
+     * This method shall be invoked at construction time only.
      */
     final double getAndStore(final Parameters parameters, final ParameterDescriptor<Double> descriptor) {
-        return MapProjection.getAndStore(parameters, context, descriptor);
+        if (descriptor == null) {
+            return 0;   // Default value for all parameters except scale factor.
+        }
+        final double value = parameters.doubleValue(descriptor);    // Apply a unit conversion if needed.
+        final Double defaultValue = descriptor.getDefaultValue();
+        if (defaultValue == null || !defaultValue.equals(value)) {
+            MapProjection.validate(descriptor, value);
+            context.parameter(descriptor.getName().getCode()).setValue(value);
+        }
+        return value;
+    }
+
+    /**
+     * Same as {@link #getAndStore(Parameters, ParameterDescriptor)}, but returns the given default value
+     * if the parameter is not specified.  This method shall be used only for parameters having a default
+     * value more complex than what we can represent in {@link ParameterDescriptor#getDefaultValue()}.
+     */
+    final double getAndStore(final Parameters parameters, final ParameterDescriptor<Double> descriptor,
+            final double defaultValue)
+    {
+        final Double value = parameters.getValue(descriptor);   // Apply a unit conversion if needed.
+        if (value == null) {
+            return defaultValue;
+        }
+        MapProjection.validate(descriptor, value);
+        context.parameter(descriptor.getName().getCode()).setValue(value);
+        return value;
     }
 
     /**
@@ -427,30 +624,51 @@ public abstract class NormalizedProjecti
     @Debug
     @Override
     public ParameterValueGroup getParameterValues() {
-        final ParameterDescriptorGroup descriptor = filter(getParameterDescriptors());
-        final ParameterValueGroup values = descriptor.createValue();
-        values.parameter(Constants.SEMI_MAJOR).setValue(1.0);
-        values.parameter(Constants.SEMI_MINOR).setValue(sqrt(1 - excentricitySquared));
-        return values;
+        return getParameterValues(new String[] {
+            Constants.SEMI_MAJOR,
+            Constants.SEMI_MINOR
+        });
     }
 
     /**
-     * Filter the given parameter descriptor in order to retain only the semi-major and semi-minor axis lengths.
-     * This filtered version is used for displaying the parameter values of this non-linear kernel only, not for
-     * displaying the {@linkplain #getContextualParameters() contextual parameters}. Since displaying the kernel
-     * parameter values is for debugging purpose only, it is not worth to cache this descriptor.
+     * Filters the parameter descriptor in order to retain only the parameters of the given names, and
+     * sets the semi-major and semi-minor axis lengths. The specified parameters list should contains at
+     * least the {@code "semi_major"} and {@code "semi_minor"} strings.
+     *
+     * <p>This filtered descriptor is used for displaying the parameter values of this non-linear kernel only,
+     * not for displaying the {@linkplain #getContextualParameters() contextual parameters}. Since displaying
+     * the kernel parameter values is for debugging purpose only, it is not worth to cache this descriptor.</p>
      */
-    private static ParameterDescriptorGroup filter(final ParameterDescriptorGroup descriptor) {
-        final List<GeneralParameterDescriptor> filtered = new ArrayList<>(5);
+    @Debug
+    final ParameterValueGroup getParameterValues(final String[] nonLinearParameters) {
+        ParameterDescriptorGroup descriptor = getParameterDescriptors();
+        final List<GeneralParameterDescriptor> filtered = new ArrayList<>(nonLinearParameters.length);
         for (final GeneralParameterDescriptor p : descriptor.descriptors()) {
-            if (IdentifiedObjects.isHeuristicMatchForName(p, Constants.SEMI_MAJOR) ||
-                IdentifiedObjects.isHeuristicMatchForName(p, Constants.SEMI_MINOR))
-            {
-                filtered.add(p);
+            for (final String name : nonLinearParameters) {
+                if (IdentifiedObjects.isHeuristicMatchForName(p, name)) {
+                    filtered.add(p);
+                    break;
+                }
             }
         }
-        return new DefaultParameterDescriptorGroup(IdentifiedObjects.getProperties(descriptor),
+        descriptor = new DefaultParameterDescriptorGroup(IdentifiedObjects.getProperties(descriptor),
                 1, 1, filtered.toArray(new GeneralParameterDescriptor[filtered.size()]));
+        /*
+         * Parameter values for the ellipsoid semi-major and semi-minor axis lengths are 1 and <= 1
+         * respectively because the denormalization (e.g. multiplication by a scale factor) will be
+         * applied by an affine transform after this NormalizedProjection.
+         */
+        final ParameterValueGroup values = descriptor.createValue();
+        for (final GeneralParameterDescriptor desc : filtered) {
+            final String name = desc.getName().getCode();
+            final ParameterValue<?> p = values.parameter(name);
+            switch (name) {
+                case Constants.SEMI_MAJOR: p.setValue(1.0); break;
+                case Constants.SEMI_MINOR: p.setValue(sqrt(1 - excentricitySquared)); break;
+                default: p.setValue(context.parameter(name).getValue());
+            }
+        }
+        return values;
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -36,7 +36,7 @@
  * More on this convention is explained below.</p>
  *
  * <p>Users wanting to know more about the available projections and their parameters should look at the
- * <a href="http://sis.apache.org/CoordinateOperationMethods.html">list of coordinate operation methods</a>.
+ * <a href="http://sis.apache.org/content/CoordinateOperationMethods.html">list of coordinate operation methods</a>.
  * Only users interested in the <em>implementation</em> of those projections should look at this package.</p>
  *
  *
@@ -122,7 +122,7 @@
  * <ul>
  *   <li>A {@linkplain org.apache.sis.referencing.operation.transform.ContextualParameters#normalizeGeographicInputs normalization} affine transform</li>
  *   <li>A {@link      org.apache.sis.referencing.operation.projection.NormalizedProjection} subclass</li>
- *   <li>A {@linkplain org.apache.sis.referencing.operation.transform.ContextualParameters#scaleAndTranslate2D denormalization} affine transform</li>
+ *   <li>A {@linkplain org.apache.sis.referencing.operation.transform.ContextualParameters#getMatrix denormalization} affine transform</li>
  * </ul>
  *
  * The first step (<cite>"normalization"</cite>) converts longitude and latitude values from degrees to radians

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -98,8 +98,8 @@ import static org.apache.sis.util.Argume
  *     it actually used in a new {@code ContextualParameters} instance.</li>
  *
  *   <li>The map projection constructor may keep only the non-linear parameters for itself,
- *     and gives the linear parameters to the {@link #normalizeGeographicInputs normalizeGeographicInputs(…)}
- *     and {@link #scaleAndTranslate2D scaleAndTranslate2D(…)} methods, which will create the matrices show above.
+ *     and gives the linear parameters to the {@link #normalizeGeographicInputs normalizeGeographicInputs(…)} and
+ *     {@link MatrixSIS#convertAfter MatrixSIS.convertAfter(…)} methods, which will create the matrices show above.
  *     The projection constructor is free to apply additional operations on the two affine transforms
  *     ({@linkplain #getMatrix(boolean) normalize / denormalize}) before or after the above-cited
  *     methods have been invoked.</li>
@@ -240,21 +240,36 @@ public class ContextualParameters extend
 
     /**
      * Returns the affine transforms to be applied before or after the non-linear kernel operation.
-     *
-     * <p>Immediately after {@linkplain #ContextualParameters(OperationMethod) construction}, those matrices
+     * Immediately after {@linkplain #ContextualParameters(OperationMethod) construction}, those matrices
      * are modifiable identity matrices. Callers can modify the matrix element values, typically by calls to
-     * the {@link MatrixSIS#concatenate(int, Number, Number) MatrixSIS.concatenate(…)} method. Alternatively,
-     * the following methods can be invoked for applying some frequently used configurations:
+     * the {@link MatrixSIS#convertBefore(int, Number, Number) MatrixSIS.convertBefore(…)} method.
+     * Alternatively, the following methods can be invoked for applying some frequently used configurations:
      *
      * <ul>
      *   <li>{@link #normalizeGeographicInputs(double)}</li>
      *   <li>{@link #denormalizeGeographicOutputs(double)}</li>
-     *   <li>{@link #scaleAndTranslate2D(boolean, double, double, double)}</li>
      * </ul>
      *
      * After the {@link #completeTransform(MathTransformFactory, MathTransform) completeTransform(…)} method has been
      * invoked, the matrices returned by this method are {@linkplain Matrices#unmodifiable(Matrix) unmodifiable}.
      *
+     *
+     * <div class="section">Application to map projections</div>
+     * After {@link org.apache.sis.referencing.operation.projection.NormalizedProjection} construction, the matrices
+     * returned by {@code projection.getContextualParameters().getMatrix(…)} are initialized to the values shown below.
+     * Note that some {@code NormalizedProjection} subclasses apply further modifications to those matrices.
+     *
+     * <table class="sis">
+     *   <caption>Initial matrix coefficients after construction</caption>
+     *   <tr>
+     *     <th>{@code getMatrix(true)}</th>
+     *     <th class="sep">{@code getMatrix(false)}</th>
+     *   </tr><tr>
+     *     <td>{@include formulas.html#NormalizeGeographic}</td>
+     *     <td class="sep">{@include formulas.html#DenormalizeCartesian}</td>
+     *   </tr>
+     * </table>
+     *
      * @param  norm {@code true} for fetching the <cite>normalization</cite> transform to apply before the kernel,
      *         or {@code false} for the <cite>denormalization</cite> transform to apply after the kernel.
      * @return The matrix for the requested normalization ({@code true}) or denormalization ({@code false}) affine transform.
@@ -269,43 +284,6 @@ public class ContextualParameters extend
     }
 
     /**
-     * Concatenates a uniform two-dimensional scale and a translation to the (de)normalization matrix.
-     * The scale and translations are applied only on the two first dimensions.
-     *
-     * <div class="section">Application to map projections</div>
-     * In map projections, the scale is the <cite>semi-major</cite> axis length (<var>a</var>) – potentially multiplied
-     * by an other scale factor <var>k</var>₀ – and the translation terms are the <cite>false easting</cite> (FE) and
-     * <cite>false northing</cite> (FN). The following method invocation:
-     *
-     * {@preformat java
-     *   scaleAndTranslate2D(false, a*k0, FE, FN);
-     * }
-     *
-     * is then equivalent to {@linkplain java.awt.geom.AffineTransform#concatenate concatenating} the denormalization
-     * matrix with the following matrix. This will have the effect of applying the conversion described above after
-     * the non-linear kernel operation.
-     *
-     * <center>{@include formulas.html#DenormalizeCartesian}</center>
-     *
-     * @param  norm  {@code true} to apply the scale and translations on the <cite>normalize</cite> transform,
-     *               or {@code false} to apply them on the <cite>denormalize</cite> transform.
-     * @param  scale The scale to apply on the 2 first axes.
-     * @param  tx    The translation to apply on the <var>x</var> axis after the scale.
-     * @param  ty    The translation to apply on the <var>y</var> axis after the scale.
-     * @return The (de)normalization affine transform as a matrix.
-     *         Callers can change that matrix directly if they want to apply additional (de)normalization operations.
-     * @throws IllegalStateException if this {@code ContextualParameter} has been made unmodifiable.
-     */
-    public MatrixSIS scaleAndTranslate2D(final boolean norm, double scale, double tx, double ty) {
-        ensureModifiable();
-        final MatrixSIS m = (MatrixSIS) (norm ? normalize : denormalize);  // Must be the same instance, not a copy.
-        final DoubleDouble s = (scale != 1) ? new DoubleDouble(scale) : null;
-        m.concatenate(0, s, (tx != 0) ? tx : null);
-        m.concatenate(1, s, (ty != 0) ? ty : null);
-        return m;
-    }
-
-    /**
      * Prepends a normalization step converting input ordinates in the two first dimensions from degrees to radians.
      * The normalization can optionally subtract the given λ₀ value (in degrees) from the longitude.
      *
@@ -333,8 +311,8 @@ public class ContextualParameters extend
             offset.multiply(toRadians);
         }
         final MatrixSIS normalize = (MatrixSIS) this.normalize;  // Must be the same instance, not a copy.
-        normalize.concatenate(0, toRadians, offset);
-        normalize.concatenate(1, toRadians, null);
+        normalize.convertBefore(0, toRadians, offset);
+        normalize.convertBefore(1, toRadians, null);
         return normalize;
     }
 
@@ -358,8 +336,8 @@ public class ContextualParameters extend
         ensureModifiable();
         final DoubleDouble toDegrees = DoubleDouble.createRadiansToDegrees();
         final MatrixSIS denormalize = (MatrixSIS) this.denormalize;  // Must be the same instance, not a copy.
-        denormalize.concatenate(0, toDegrees, (λ0 != 0) ? λ0 : null);
-        denormalize.concatenate(1, toDegrees, null);
+        denormalize.convertAfter(0, toDegrees, (λ0 != 0) ? λ0 : null);
+        denormalize.convertAfter(1, toDegrees, null);
         return denormalize;
     }
 

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -83,7 +83,7 @@ import org.apache.sis.internal.jdk8.JDK8
  * <div class="section">Standard parameters</div>
  * {@code MathTransform} instances are created from {@linkplain org.apache.sis.parameter.DefaultParameterValueGroup
  * parameter values}. The parameters expected by each operation available in a default Apache SIS installation is
- * <a href="http://sis.apache.org/CoordinateOperationMethods.html">listed here</a>.
+ * <a href="http://sis.apache.org/content/CoordinateOperationMethods.html">listed here</a>.
  * The set of parameters varies for each operation or projection, but the following can be considered typical:
  *
  * <ul>

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html [UTF-8] Fri Apr 17 14:33:54 2015
@@ -150,7 +150,7 @@
           <mtr>
             <mtd><mi>π</mi><mo>/</mo><mn>180</mn></mtd>
             <mtd><mn>0</mn></mtd>
-            <mtd><mo>-</mo><mo>(</mo><mi>π</mi><mo>/</mo><mn>180</mn><mo>)</mo> <mo>⋅</mo> <msub><mi>λ</mi><mn>0</mn></msub></mtd>
+            <mtd><mo>-</mo><msub><mi>λ</mi><mn>0</mn></msub> <mo>⋅</mo> <mo>(</mo><mi>π</mi><mo>/</mo><mn>180</mn><mo>)</mo></mtd>
           </mtr>
           <mtr>
             <mtd><mn>0</mn></mtd>

Modified: sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Fri Apr 17 14:33:54 2015
@@ -9,3 +9,6 @@ org.apache.sis.internal.referencing.prov
 org.apache.sis.internal.referencing.provider.PseudoMercator
 org.apache.sis.internal.referencing.provider.RegionalMercator
 org.apache.sis.internal.referencing.provider.MillerCylindrical
+org.apache.sis.internal.referencing.provider.LambertConformal1SP
+org.apache.sis.internal.referencing.provider.LambertConformal2SP
+org.apache.sis.internal.referencing.provider.LambertConformalBelgium

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -59,7 +59,10 @@ public final strictfp class AllProviders
             MercatorSpherical.class,
             PseudoMercator.class,
             RegionalMercator.class,
-            MillerCylindrical.class
+            MillerCylindrical.class,
+            LambertConformal1SP.class,
+            LambertConformal2SP.class,
+            LambertConformalBelgium.class
         };
     }
 

Copied: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java (from r1674318, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java?p2=sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java&p1=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java&r1=1674318&r2=1674327&rev=1674327&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/CoordinateOperationMethodsHTML.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -49,6 +49,9 @@ import org.apache.sis.util.Numbers;
 import org.apache.sis.util.Workaround;
 import org.apache.sis.test.HTMLGenerator;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Generates a list of projection parameters in a HTML page. This class is used for updating the
@@ -76,12 +79,14 @@ public final class CoordinateOperationMe
     public static void main(final String[] args) throws IOException {
         final MathTransformFactory factory = DefaultFactories.forBuildin(MathTransformFactory.class);
         final List<OperationMethod> methods = new ArrayList<>(factory.getAvailableMethods(SingleOperation.class));
-        Collections.sort(methods, (final OperationMethod o1, final OperationMethod o2) -> {
-            int c = category(o1) - category(o2);
-            if (c == 0) {  // If the two methods are in the same category, sort by name.
-                c = o1.getName().getCode().compareTo(o2.getName().getCode());
+        Collections.sort(methods, new java.util.Comparator<OperationMethod>() {
+            @Override public int compare(OperationMethod o1, OperationMethod o2) {
+                int c = category(o1) - category(o2);
+                if (c == 0) {  // If the two methods are in the same category, sort by name.
+                    c = o1.getName().getCode().compareTo(o2.getName().getCode());
+                }
+                return c;
             }
-            return c;
         });
         try (final CoordinateOperationMethodsHTML writer = new CoordinateOperationMethodsHTML()) {
             writer.writeIndex(methods);
@@ -327,7 +332,7 @@ public final class CoordinateOperationMe
             writeName(param);
             String remarks = toLocalizedString(param.getRemarks());
             if (remarks != null) {
-                Integer index = footnotes.putIfAbsent(remarks, footnotes.size() + 1);
+                Integer index = JDK8.putIfAbsent(footnotes, remarks, footnotes.size() + 1);
                 if (index == null) {
                     index = footnotes.size();
                 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -22,12 +22,12 @@ import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.test.ReferencingAssert;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.apache.sis.test.ReferencingAssert.*;
 import static org.apache.sis.internal.util.Constants.*;
 
 
@@ -103,7 +103,7 @@ public final strictfp class MapProjectio
         assertParamEquals(null,                                SEMI_MAJOR,           true,  it.next());
         assertParamEquals(null,                                SEMI_MINOR,           true,  it.next());
         assertParamEquals("Latitude of 1st standard parallel", STANDARD_PARALLEL_1,  true,  it.next());
-        assertParamEquals(null,                               "latitude_of_origin",  false, it.next());
+        assertParamEquals("Latitude of natural origin",        "latitude_of_origin",  false, it.next());
         assertParamEquals("Longitude of natural origin",       CENTRAL_MERIDIAN,     true,  it.next());
         assertParamEquals(null,                                SCALE_FACTOR,         false, it.next());
         assertParamEquals("False easting",                     FALSE_EASTING,        true,  it.next());
@@ -121,15 +121,15 @@ public final strictfp class MapProjectio
             final GeneralParameterDescriptor actual)
     {
         if (epsgName != null) {
-            ReferencingAssert.assertEpsgIdentifierEquals(epsgName, actual.getName());
+            assertEpsgIdentifierEquals(epsgName, actual.getName());
         } else {
-            ReferencingAssert.assertOgcIdentifierEquals(ogcName, actual.getName());
+            assertOgcIdentifierEquals(ogcName, actual.getName());
         }
         assertEquals("minimumOccurs", isMandatory ? 1 : 0, actual.getMinimumOccurs());
         if (epsgName != null) {
             for (final GenericName alias : actual.getAlias()) {
                 if (alias instanceof Identifier && ((Identifier) alias).getAuthority() != Citations.EPSG) {
-                    ReferencingAssert.assertOgcIdentifierEquals(ogcName, (Identifier) alias);
+                    assertOgcIdentifierEquals(ogcName, (Identifier) alias);
                     return;
                 }
             }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java?rev=1674327&r1=1674326&r2=1674327&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/BuilderTest.java [UTF-8] Fri Apr 17 14:33:54 2015
@@ -109,6 +109,9 @@ public final strictfp class BuilderTest
         final LocalName alias1 = factory.createLocalName(null, "Mercator (1SP)");
         final LocalName alias2 = factory.createLocalName(null, "Mercator_1SP");
         final LocalName alias3 = factory.createLocalName(null, "CT_Mercator");
+        assertTrue("That name should not have a scope.", alias1.scope().isGlobal());
+        assertTrue("That name should not have a scope.", alias2.scope().isGlobal());
+        assertTrue("That name should not have a scope.", alias3.scope().isGlobal());
         assertEquals("Mercator (1SP)", alias1.toString());
         assertEquals("Mercator_1SP",   alias2.toString());
         assertEquals("CT_Mercator",    alias3.toString());
@@ -162,10 +165,13 @@ public final strictfp class BuilderTest
         final GenericName alias1 = factory.createLocalName(scope(factory, "EPSG"), "Mercator (1SP)");
         final GenericName alias2 = new NamedIdentifier(OGC,     "Mercator_1SP");
         final GenericName alias3 = new NamedIdentifier(GEOTIFF, "CT_Mercator");
+        assertTrue ("That name should not have a scope.", alias3.scope().isGlobal());
+        assertTrue ("That name should not have a scope.", alias2.scope().isGlobal());
+        assertFalse("That name should be in EPSG scope.", alias1.scope().isGlobal());
+        assertEquals("EPSG",                 alias1.scope().name().toString());
         assertEquals("Mercator (1SP)",       alias1.toString());
         assertEquals("OGC:Mercator_1SP",     alias2.toString());
         assertEquals("GeoTIFF:CT_Mercator",  alias3.toString());
-        assertEquals("EPSG",                 alias1.scope().name().toString());
 
         // The test.
         final BuilderMock builder = createMercator(true, false);



Mime
View raw message