sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1660664 [1/2] - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ core/sis-referencing/src/main/java/org/apache/sis/in...
Date Wed, 18 Feb 2015 16:26:53 GMT
Author: desruisseaux
Date: Wed Feb 18 16:26:52 2015
New Revision: 1660664

URL: http://svn.apache.org/r1660664
Log:
Allow the "Affine general parametric transformation" coordinate operation method to understand
the parameter names used by EPSG:9624 in addition to the OGC syntax.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MatrixParameters.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AffineTest.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MatrixParametersTest.java
      - copied, changed from r1660202, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/HardCoded.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/TensorParameters.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorValuesTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CopyTransformTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ProjectiveTransformTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/ReferencingAssert.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/iso/TypeNames.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/HardCoded.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/HardCoded.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/HardCoded.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/HardCoded.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -42,6 +42,16 @@ public final class HardCoded extends Sta
     /**
      * The {@value} code space.
      */
+    public static final String SIS = "SIS";
+
+    /**
+     * The {@value} code space.
+     */
+    public static final String OGC = Citations.OGC;
+
+    /**
+     * The {@value} code space.
+     */
     public static final String CRS = "CRS";
 
     /**
@@ -60,6 +70,18 @@ public final class HardCoded extends Sta
     public static final byte CRS84 = 84;
 
     /**
+     * EPSG code of the {@code A0} coefficient used in affine (general parametric) and polynomial transformations.
+     * Codes for parameters {@code A1} to {@code A8} inclusive follow, but the affine coefficients stop at {@code A2}.
+     */
+    public static final short A0 = 8623;
+
+    /**
+     * EPSG code of the {@code B0} coefficient used in affine (general parametric) and polynomial transformations.
+     * Codes for parameters {@code B1} to {@code B3} inclusive follow, but the affine coefficients stop at {@code B2}.
+     */
+    public static final short B0 = 8639;
+
+    /**
      * Do not allow instantiation of this class.
      */
     private HardCoded() {

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -27,7 +27,6 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.parameter.Parameterized;
-import org.apache.sis.parameter.TensorParameters;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
@@ -192,7 +191,7 @@ public class AffineTransform2D extends I
      */
     @Override
     public ParameterDescriptorGroup getParameterDescriptors() {
-        return Affine.PARAMETERS;
+        return Affine.descriptor(2, 2);
     }
 
     /**
@@ -202,7 +201,7 @@ public class AffineTransform2D extends I
      */
     @Override
     public ParameterValueGroup getParameterValues() {
-        return TensorParameters.WKT1.createValueGroup(Affine.IDENTIFICATION, getMatrix());
+        return Affine.parameters(getMatrix());
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -22,12 +22,14 @@ import org.opengis.parameter.ParameterDe
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.Conversion;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.parameter.TensorParameters;
+import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 
@@ -38,18 +40,18 @@ import org.apache.sis.referencing.operat
  *
  * <table class="sis">
  *   <caption>{@code Affine} parameters</caption>
- *   <tr><th>Parameter name</th><th>Default value</th></tr>
- *   <tr><td>{@code num_row}</td><td>3</td></tr>
- *   <tr><td>{@code num_col}</td><td>3</td></tr>
- *   <tr><td>{@code elt_0_0}</td><td>1</td></tr>
- *   <tr><td>{@code elt_0_1}</td><td>0</td></tr>
- *   <tr><td>{@code elt_0_2}</td><td>0</td></tr>
- *   <tr><td>{@code elt_1_0}</td><td>0</td></tr>
- *   <tr><td>{@code elt_1_1}</td><td>1</td></tr>
- *   <tr><td>{@code elt_1_2}</td><td>0</td></tr>
- *   <tr><td>{@code elt_2_0}</td><td>0</td></tr>
- *   <tr><td>{@code elt_2_1}</td><td>0</td></tr>
- *   <tr><td>{@code elt_2_2}</td><td>1</td></tr>
+ *   <tr><th>EPSG code</th><th>EPSG name</th><th>OGC name</th><th>Default value</th></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code num_row}</td> <td>3</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code num_col}</td> <td>3</td></tr>
+ *   <tr><td>8623</td> <td>{@code A0}</td> <td>{@code elt_0_0}</td> <td>1</td></tr>
+ *   <tr><td>8624</td> <td>{@code A1}</td> <td>{@code elt_0_1}</td> <td>0</td></tr>
+ *   <tr><td>8625</td> <td>{@code A2}</td> <td>{@code elt_0_2}</td> <td>0</td></tr>
+ *   <tr><td>8639</td> <td>{@code B0}</td> <td>{@code elt_1_0}</td> <td>0</td></tr>
+ *   <tr><td>8640</td> <td>{@code B1}</td> <td>{@code elt_1_1}</td> <td>1</td></tr>
+ *   <tr><td>8641</td> <td>{@code B2}</td> <td>{@code elt_1_2}</td> <td>0</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code elt_2_0}</td> <td>0</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code elt_2_1}</td> <td>0</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code elt_2_2}</td> <td>1</td></tr>
  * </table>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
@@ -64,36 +66,65 @@ public final class Affine extends Abstra
     private static final long serialVersionUID = 649555815622129472L;
 
     /**
-     * The default matrix size.
+     * The number of dimensions used by the EPSG:9624 definition. This will be used as the
+     * default number of dimensions. Operation methods of other dimensions, where we have
+     * no EPSG definition, shall use the Well Known Text (WKT) parameter names.
      */
-    private static final int DEFAULT_MATRIX_SIZE = 3;
+    public static final int EPSG_DIMENSION = 2;
 
     /**
-     * The set of predefined providers.
+     * The maximal number of dimension to be cached in the {@link #cached} array.
      */
-    private static final Affine[] methods = new Affine[8];
+    private static final int MAX_CACHED_DIMENSION = 6;
+
+    /**
+     * Cached providers for methods of dimension 1×1 to {@link #MAX_CACHED_DIMENSION}.
+     * The index of each element is computed by {@link #cacheIndex(int, int)}.
+     * All usages of this array shall be synchronized on {@code cached}.
+     */
+    private static final Affine[] cached = new Affine[MAX_CACHED_DIMENSION * MAX_CACHED_DIMENSION];
+
+    /**
+     * Returns the index where to store a method of the given dimensions in the {@link #cached} array,
+     * or -1 if it should not be cached.
+     */
+    static int cacheIndex(int sourceDimensions, int targetDimensions) {
+        if (--sourceDimensions >= 0 && sourceDimensions < MAX_CACHED_DIMENSION &&
+            --targetDimensions >= 0 && targetDimensions < MAX_CACHED_DIMENSION)
+        {
+            return sourceDimensions * MAX_CACHED_DIMENSION + targetDimensions;
+        }
+        return -1;
+    }
+
+    /**
+     * Index equivalent to {@link cacheIndex(EPSG_DIMENSION, EPSG_DIMENSION)}.
+     * We expand the computation inline for allowing the compiler to replace the whole
+     * expression by a single constant.
+     */
+    static final int EPSG_INDEX = (EPSG_DIMENSION - 1) * MAX_CACHED_DIMENSION + (EPSG_DIMENSION - 1);
 
     /**
      * The name, aliases and identifiers of the "Affine" method.
      */
-    public static final Map<String,?> IDENTIFICATION =
+    private static final Map<String,?> IDENTIFICATION =
             Collections.singletonMap(NAME_KEY, new NamedIdentifier(Citations.OGC, "Affine"));
 
     /**
      * The group of all parameters expected by this coordinate operation.
      */
-    public static final ParameterDescriptorGroup PARAMETERS;
+    private static final ParameterDescriptorGroup PARAMETERS;
     static {
         final int[] indices = new int[2]; // The length of this array is the number of tensor dimensions.
         @SuppressWarnings("rawtypes")
         final ParameterDescriptor<?>[] parameters =
-                new ParameterDescriptor[indices.length + (DEFAULT_MATRIX_SIZE * DEFAULT_MATRIX_SIZE)];
+                new ParameterDescriptor[indices.length + (EPSG_DIMENSION +1) * (EPSG_DIMENSION + 1)];
         int k = 0;
         do {
             parameters[k] = TensorParameters.WKT1.getDimensionDescriptor(k);
         } while (++k < indices.length);
-        for (int j=0; j<DEFAULT_MATRIX_SIZE; j++) {
-            for (int i=0; i<DEFAULT_MATRIX_SIZE; i++) {
+        for (int j=0; j <= EPSG_DIMENSION; j++) {
+            for (int i=0; i <= EPSG_DIMENSION; i++) {
                 indices[0] = j;
                 indices[1] = i;
                 parameters[k++] = TensorParameters.WKT1.getElementDescriptor(indices);
@@ -106,15 +137,17 @@ public final class Affine extends Abstra
      * Creates a provider for affine transform with a default matrix size.
      */
     public Affine() {
-        this(DEFAULT_MATRIX_SIZE - 1, DEFAULT_MATRIX_SIZE - 1);
-        methods[DEFAULT_MATRIX_SIZE - 2] = this;
+        super(EPSG_DIMENSION, EPSG_DIMENSION, PARAMETERS);
+        synchronized (cached) {
+            cached[EPSG_INDEX] = this;
+        }
     }
 
     /**
      * Creates a provider for affine transform with the specified dimensions.
      */
-    private Affine(final int sourceDimension, final int targetDimension) {
-        super(sourceDimension, targetDimension, PARAMETERS);
+    private Affine(final int sourceDimensions, final int targetDimensions) {
+        super(sourceDimensions, targetDimensions, PARAMETERS);
     }
 
     /**
@@ -136,6 +169,10 @@ public final class Affine extends Abstra
      */
     @Override
     public MathTransform createMathTransform(final ParameterValueGroup values) throws ParameterNotFoundException {
+        /*
+         * The TensorParameters constant used below (WKT1 or EPSG) does not matter,
+         * since both of them understand the names of the other TensorParameters.
+         */
         return MathTransforms.linear(TensorParameters.WKT1.toMatrix(values));
     }
 
@@ -153,25 +190,59 @@ public final class Affine extends Abstra
 
     /**
      * Returns the operation method for the specified source and target dimensions.
-     * This method provides different sourceDimensions for different matrix sizes.
+     * This method provides different {@code Affine} instances for different dimensions.
      *
      * @param sourceDimensions The number of source dimensions.
      * @param targetDimensions The number of target dimensions.
      * @return The provider for transforms of the given source and target dimensions.
      */
-    public static Affine getProvider(final int sourceDimensions, final int targetDimensions) {
-        if (sourceDimensions == targetDimensions) {
-            final int i = sourceDimensions - 1;
-            if (i >= 0 && i < methods.length) {
-                synchronized (Affine.class) {
-                    Affine method = methods[i];
-                    if (method == null) {
-                        methods[i] = method = new Affine(sourceDimensions, targetDimensions);
-                    }
-                    return method;
+    private static Affine getProvider(final int sourceDimensions, final int targetDimensions) {
+        final int i = cacheIndex(sourceDimensions, targetDimensions);
+        if (i >= 0) {
+            final Affine method;
+            synchronized (Affine.class) {
+                method = cached[i];
+            }
+            if (method != null) {
+                return method;
+            }
+        }
+        /*
+         * At this point, no existing instance has been found in the cache.
+         * Create a new instance and cache it if its dimension is not too large.
+         */
+        final Affine method = new Affine(sourceDimensions, targetDimensions);
+        if (i >= 0) {
+            synchronized (Affine.class) {
+                final Affine other = cached[i];     // May have been created in another thread.
+                if (other != null) {
+                    return other;
                 }
+                cached[i] = method;
             }
         }
-        return new Affine(sourceDimensions, targetDimensions);
+        return method;
+    }
+
+    /**
+     * Returns the parameter descriptor for the given dimensions.
+     *
+     * @param sourceDimensions The number of source dimensions.
+     * @param targetDimensions The number of target dimensions.
+     * @return The parameters descriptor for the given dimensions.
+     */
+    public static ParameterDescriptorGroup descriptor(final int sourceDimensions, final int targetDimensions) {
+        return getProvider(sourceDimensions, targetDimensions).getParameters();
+    }
+
+    /**
+     * Returns the parameter values for the given matrix.
+     *
+     * @param  matrix The matrix for which to get parameter values.
+     * @return The parameters of the given matrix.
+     */
+    public static ParameterValueGroup parameters(final Matrix matrix) {
+        return TensorParameters.WKT1.createValueGroup(IdentifiedObjects.getProperties(
+                descriptor(matrix.getNumRow() - 1, matrix.getNumCol() - 1)), matrix);
     }
 }

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MatrixParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MatrixParameters.java?rev=1660664&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MatrixParameters.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MatrixParameters.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.parameter;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.io.ObjectStreamException;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.parameter.ParameterDescriptor;
+import org.apache.sis.referencing.NamedIdentifier;
+import org.apache.sis.internal.referencing.HardCoded;
+import org.apache.sis.metadata.iso.ImmutableIdentifier;
+import org.apache.sis.metadata.iso.citation.Citations;
+
+import static org.apache.sis.internal.util.CollectionsExt.first;
+
+
+/**
+ * A special case of {@link TensorParameters} restricted to the two-dimensional case.
+ * The main purpose for this class is to use the EPSG:9624 parameter names, either as
+ * alias or as primary name.
+ *
+ * <table class="sis">
+ *   <caption>{@code Affine} parameters</caption>
+ *   <tr><th>EPSG code</th><th>EPSG name</th><th>OGC name</th><th>Default value</th></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code num_row}</td> <td>3</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code num_col}</td> <td>3</td></tr>
+ *   <tr><td>8623</td> <td>{@code A0}</td> <td>{@code elt_0_0}</td> <td>1</td></tr>
+ *   <tr><td>8624</td> <td>{@code A1}</td> <td>{@code elt_0_1}</td> <td>0</td></tr>
+ *   <tr><td>8625</td> <td>{@code A2}</td> <td>{@code elt_0_2}</td> <td>0</td></tr>
+ *   <tr><td>8639</td> <td>{@code B0}</td> <td>{@code elt_1_0}</td> <td>0</td></tr>
+ *   <tr><td>8640</td> <td>{@code B1}</td> <td>{@code elt_1_1}</td> <td>1</td></tr>
+ *   <tr><td>8641</td> <td>{@code B2}</td> <td>{@code elt_1_2}</td> <td>0</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code elt_2_0}</td> <td>0</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code elt_2_1}</td> <td>0</td></tr>
+ *   <tr><td>    </td> <td>          </td> <td>{@code elt_2_2}</td> <td>1</td></tr>
+ * </table>
+ *
+ * Note that the EPSG database contains A3, A4, A5, A6, A7, A8 and B3 parameters,
+ * but they are for polynomial transformations, not affine transformations.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.6
+ * @version 0.6
+ * @module
+ */
+final class MatrixParameters extends TensorParameters<Double> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8452879524565700115L;
+
+    /**
+     * Constructs a descriptors provider.
+     *
+     * @param prefix    The prefix to insert in front of parameter name for each tensor elements.
+     * @param separator The separator between dimension (row, column, …) indices in parameter names.
+     * @param numRow    The parameter for the number of rows.
+     * @param numCol    The parameter for the number of columns.
+     */
+    MatrixParameters(final String prefix, final String separator,
+            final ParameterDescriptor<Integer> numRow, final ParameterDescriptor<Integer> numCol)
+    {
+        super(Double.class, prefix, separator, numRow, numCol);
+    }
+
+    /**
+     * {@code true} for using the EPSG names, or {@code false} for using the WKT1 names.
+     * Current implementation uses {@link #separator} emptiness as a criterion. This is
+     * an arbitrary choice that may change in any future SIS version. However we need a
+     * criterion which is preserved during serialization.
+     *
+     * @see #EPSG
+     */
+    final boolean isEPSG() {
+        return separator.isEmpty();
+    }
+
+    /**
+     * Returns {@code true} if an official EPSG parameter exists for the given indices. Those parameters
+     * are {@code "A0"}, {@code "A1"}, {@code "A2"}, {@code "B0"}, {@code "B1"} and {@code "B2"}.
+     */
+    private static boolean isEPSG(final int[] indices) {
+        return indices[0] < 2 && indices[1] < 3;
+    }
+
+    /**
+     * Returns an alias for the given indices, or {@code null} if none.
+     * The default implementation formats:
+     *
+     * <ul>
+     *   <li>the first index (the matrix row) as letter, starting from {@code 'A'},</li>
+     *   <li>the second index (the matrix column) as digit, starting from {@code '0'}.</li>
+     * </ul>
+     *
+     * Note that for <var>row</var> &lt; 2 and <var>column</var> &lt; 3, the returned aliases are the names
+     * used by the EPSG database. For other row and column indices, the same pattern is still used but the
+     * result is not an official EPSG parameter name.
+     *
+     * @param  indices The indices of the tensor element for which to create a parameter alias.
+     * @return The parameter descriptor alias for the tensor element at the given indices, or {@code null} if none.
+     */
+    static String indicesToAlias(final int[] indices) {
+        final int row = indices[0];
+        if (row >= 0 && row < 26) {
+            final int col = indices[1];
+            if (col >= 0 && col < 10) {
+                return String.valueOf(new char[] {(char) ('A' + row), (char) ('0' + col)});
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the indices for the given alias, or {@code null} if none.
+     * This method is the converse of {@link #indicesToAlias(int[])}.
+     */
+    static int[] aliasToIndices(final String alias) {
+        if (alias.length() == 2) {
+            final int row = alias.charAt(0) - 'A';
+            if (row >= 0 && row < 26) {
+                final int col = alias.charAt(1) - '0';
+                if (col >= 0 && col < 10) {
+                    return new int[] {row, col};
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the parameter descriptor name of a matrix element at the given indices.
+     * Overridden as a matter of principle, but not used directly by this implementation.
+     */
+    @Override
+    protected String indicesToName(final int[] indices) throws IllegalArgumentException {
+        return isEPSG() ? indicesToAlias(indices) : super.indicesToName(indices);
+    }
+
+    /**
+     * Returns the indices of matrix element for the given parameter name, or {@code null} if none.
+     * This implementation unconditionally checks for the EPSG name first since this is a very quick check.
+     * If the given name does not use the EPSG syntax, then this method fallback on the WKT1 syntax.
+     */
+    @Override
+    protected int[] nameToIndices(final String name) throws IllegalArgumentException {
+        int[] indices = aliasToIndices(name);
+        if (indices == null) {
+            if (isEPSG()) {
+                if (WKT1 == this) {
+                    // Should never happen, but still unconditionally tested
+                    // (no 'assert' keyword) for preventing stack overflow.
+                    throw new AssertionError();
+                }
+                indices = WKT1.nameToIndices(name);
+            } else {
+                indices = super.nameToIndices(name);
+            }
+        }
+        return indices;
+    }
+
+    /**
+     * Creates a new parameter descriptor for a matrix element at the given indices. This method creates both the
+     * OGC name (e.g. {@code "elt_1_2"}) and the EPSG name (e.g. {@code "B2"}), together with the EPSG identifier
+     * (e.g. {@code "EPSG:8641"}) it it exists. See {@link org.apache.sis.internal.referencing.provider.Affine}
+     * for a table summarizing the parameter names and identifiers.
+     */
+    @Override
+    protected ParameterDescriptor<Double> createElementDescriptor(final int[] indices) throws IllegalArgumentException {
+        final Object name, alias, identifier;
+        if (isEPSG()) {
+            /*
+             * For the EPSG convention, we recycle the names and identifiers created for the WKT1 convention but
+             * interchanging the name with the alias (since our WKT1 convention adds the EPSG names as aliases).
+             * We use WKT1 as the primary source because it is still very widely used, and works for arbitrary
+             * dimensions while the EPSG parameters are (officially) restricted to 3×3 matrices.
+             */
+            if (WKT1 == this) {
+                // Should never happen, but still unconditionally tested
+                // (no 'assert' keyword) for preventing stack overflow.
+                throw new AssertionError();
+            }
+            final ParameterDescriptor<Double> wkt = WKT1.getElementDescriptor(indices);
+            name       = first(wkt.getAlias());
+            alias      = wkt.getName();
+            identifier = first(wkt.getIdentifiers());
+        } else {
+            /*
+             * For the WKT1 convention, create an alias matching the EPSG pattern ("A0", "A1", etc.) for all
+             * indices but declare the EPSG authority and identifier only for A0, A1, A2, B0, B1 and B2.
+             */
+            name = new NamedIdentifier(Citations.OGC, HardCoded.OGC, super.indicesToName(indices), null, null);
+            final Citation authority;
+            final String codeSpace;
+            if (isEPSG(indices)) {
+                authority = Citations.OGP;
+                codeSpace = HardCoded.EPSG;
+                final int code = (indices[0] == 0 ? HardCoded.A0 : HardCoded.B0) + indices[1];
+                identifier = new ImmutableIdentifier(authority, codeSpace, String.valueOf(code));
+            } else {
+                authority  = Citations.SIS;
+                codeSpace  = HardCoded.SIS;
+                identifier = null;
+            }
+            final String c = indicesToAlias(indices);
+            alias = (c != null) ? new NamedIdentifier(authority, codeSpace, c, null, null) : null;
+        }
+        final Map<String,Object> properties = new HashMap<>(4);
+        properties.put(ParameterDescriptor.NAME_KEY,        name);
+        properties.put(ParameterDescriptor.ALIAS_KEY,       alias);
+        properties.put(ParameterDescriptor.IDENTIFIERS_KEY, identifier);
+        return new DefaultParameterDescriptor<>(properties, 0, 1, Double.class, null, null, getDefaultValue(indices));
+    }
+
+    /**
+     * On deserialization, replaces the deserialized instance by the unique instance if possible.
+     */
+    Object readResolve() throws ObjectStreamException {
+        final TensorParameters<?> candidate = isEPSG() ? EPSG : WKT1;
+        return equals(candidate) ? candidate : this;
+    }
+}

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

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

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/TensorParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/TensorParameters.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/TensorParameters.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/TensorParameters.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Arrays;
+import java.util.Collections;
 import java.io.IOException;
 import java.io.Serializable;
 import java.io.ObjectInputStream;
@@ -33,9 +34,12 @@ import org.opengis.parameter.GeneralPara
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.parameter.InvalidParameterNameException;
 import org.opengis.metadata.Identifier;
+import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.internal.referencing.provider.Affine;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.measure.NumberRange;
@@ -53,9 +57,13 @@ import java.util.Objects;
  *
  * <p>Each group of parameters contains the following elements:</p>
  * <ul>
- *   <li>A mandatory parameter for the number of rows ({@code "num_row"} in WKT 1).</li>
- *   <li>A mandatory parameter for the number of columns ({@code "num_col"} in WKT 1).</li>
- *   <li>(<i>etc.</i> for third-order or higher-order tensors).</li>
+ *   <li>Parameters (usually mandatory) for the tensor dimensions:
+ *     <ul>
+ *       <li>number of rows ({@code "num_row"} in WKT 1),</li>
+ *       <li>number of columns ({@code "num_col"} in WKT 1),</li>
+ *       <li><i>etc.</i> for third-order or higher-order tensors.</li>
+ *     </ul>
+ *   </li>
  *   <li>A maximum of {@code num_row} × {@code num_col} × … optional parameters for the matrix or tensor element values.
  *       Parameter names depend on the formatting convention.</li>
  * </ul>
@@ -70,8 +78,26 @@ import java.util.Objects;
  * For a more efficient matrix storage, see {@link org.apache.sis.referencing.operation.matrix.MatrixSIS}.</p>
  *
  * {@section Formatting}
- * The parameters format for a matrix is typically like below:
+ * In the particular case of a tensor of {@linkplain #rank() rank} 2 (i.e. a matrix),
+ * the parameters are typically formatted as below. Note that in the EPSG convention,
+ * the matrix is implicitly {@linkplain Matrices#isAffine affine} and of dimension 3×3.
  *
+ * <table class="sis">
+ *   <caption>Well Known Text format for a matrix</caption>
+ * <tr>
+ *   <th>Using EPSG names</th>
+ *   <th>Using OGC names</th>
+ * </tr>
+ * <tr><td>
+ * {@preformat wkt
+ *   Parameter["A0", <value>, ID["EPSG",8623]],
+ *   Parameter["A1", <value>, ID["EPSG",8624]],
+ *   Parameter["A2", <value>, ID["EPSG",8625]],
+ *   Parameter["B0", <value>, ID["EPSG",8639]],
+ *   Parameter["B1", <value>, ID["EPSG",8640]],
+ *   Parameter["B2", <value>, ID["EPSG",8641]]
+ * }
+ * </td><td>
  * {@preformat wkt
  *   Parameter["num_row", 3],
  *   Parameter["num_col", 3],
@@ -84,6 +110,11 @@ import java.util.Objects;
  *   ...
  *   Parameter["elt_<num_row-1>_<num_col-1>", <value>]
  * }
+ * </td></tr></table>
+ *
+ * <div class="note"><b>Note:</b>
+ * the EPSG database contains also A3, A4, A5, A6, A7, A8 and B3 parameters,
+ * but they are for polynomial transformations, not affine transformations.</div>
  *
  * Those groups are extensible, i.e. the number of <code>"elt_<var>row</var>_<var>col</var>"</code> parameters
  * depends on the {@code "num_row"} and {@code "num_col"} parameter values. For this reason, the descriptor of
@@ -91,7 +122,7 @@ import java.util.Objects;
  *
  * {@section Usage}
  * For creating a new group of parameters for a matrix using the {@link #WKT1} naming conventions,
- * on can use the following code:
+ * one can use the following code:
  *
  * {@preformat java
  *   Map<String,?> properties = Collections.singletonMap("name", "My operation");
@@ -102,10 +133,9 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
-@SuppressWarnings("unchecked")
 public class TensorParameters<E> implements Serializable {
     /**
      * Serial number for inter-operability with different versions.
@@ -113,17 +143,40 @@ public class TensorParameters<E> impleme
     private static final long serialVersionUID = -7386537348359343836L;
 
     /**
-     * Parses and creates parameters names for matrices matching the
+     * Parses and creates matrix parameters with names matching the <cite>"Affine parametric transformation"</cite>
+     * (EPSG:9624) operation method. The matrix size is 3×3 and the parameter names are {@code "A0"}, {@code "A1"},
+     * {@code "A2"}, {@code "B0"}, {@code "B1"} and {@code "B2"} where:
+     *
+     * <ul>
+     *   <li>the letter indicates the row (first row is {@code "A"}),
+     *   <li>the digit is the column index (first column is {@code "0"}).</li>
+     * </ul>
+     *
+     * This implementation accepts also parameters for matrix of different size (for example {@code "C4"} for row 3
+     * and column 4), but such extensions are not official EPSG parameter names.
+     *
+     * <p>If addition, each parameter accepts also the {@link WKT1} name (e.g. {@code "elt_1_2"})
+     * as an {@linkplain ParameterDescriptor#getAlias() alias}.</p>
+     *
+     * @since 0.6
+     */
+    public static final TensorParameters<Double> EPSG;
+
+    /**
+     * Parses and creates matrix parameters with names matching the
      * <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">Well Known Text</a>
      * version 1 (WKT 1) convention.
      *
      * <ul>
      *   <li>First parameter is {@code "num_row"}.</li>
      *   <li>Second parameter is {@code "num_col"}.</li>
-     *   <li>All other parameters are of the form <code>"elt_<var>row</var>_<var>col</var>"</code>.</li>
+     *   <li>All other parameters are of the form <code>"elt_</code><var>row</var><code>_</code><var>col</var><code>"</code>.
+     *       Those parameters have alias of the form {@code "A0"}, {@code "A1"}, <i>etc.</i> where the letter indicates
+     *       the row (first row is {@code "A"}) and the digit is the column index (first column is {@code "0"}).</li>
      * </ul>
      *
-     * <div class="note"><b>Example:</b> {@code "elt_2_1"} is the element name for the value at line 2 and row 1.</div>
+     * <div class="note"><b>Example:</b> {@code "elt_1_2"} is the element name for the value at row 1 and column 2.
+     * Its alias is {@code "B2"}, which is the EPSG name for the same parameter.</div>
      */
     public static final TensorParameters<Double> WKT1;
     static {
@@ -135,15 +188,29 @@ public class TensorParameters<E> impleme
          *       elements.
          */
         final NumberRange<Integer> valueDomain = NumberRange.create(1, true, 50, true);
-        final Integer defaultSize = 3;
-        final ParameterDescriptor<Integer> numRow, numCol;
+        final Integer defaultSize = Affine.EPSG_DIMENSION + 1;
+        /*
+         * For the WKT1 convention, the "num_row" and "num_col" parameters are mandatory.
+         */
         final Map<String,Object> properties = new HashMap<>(4);
         properties.put(Identifier.AUTHORITY_KEY, Citations.OGC);
         properties.put(Identifier.CODE_KEY, "num_row");
-        numRow = new DefaultParameterDescriptor<>(properties, 1, 1, Integer.class, valueDomain, null, defaultSize);
+        ParameterDescriptor<Integer> numRow = new DefaultParameterDescriptor<>(
+                properties, 1, 1, Integer.class, valueDomain, null, defaultSize);
         properties.put(Identifier.CODE_KEY, "num_col");
-        numCol = new DefaultParameterDescriptor<>(properties, 1, 1, Integer.class, valueDomain, null, defaultSize);
-        WKT1 = new TensorParameters<>(Double.class, "elt_", "_", numRow, numCol);
+        ParameterDescriptor<Integer> numCol = new DefaultParameterDescriptor<>(
+                properties, 1, 1, Integer.class, valueDomain, null, defaultSize);
+        WKT1 = new MatrixParameters("elt_", "_", numRow, numCol);
+        /*
+         * For the EPSG convention, there is no "num_row" or "num_col" parameters since the matrix
+         * size if fixed to 3×3. However since we still need them, we will declare them as optional
+         * and we will hide them from the descriptor unless the matrix size is different than 3×3.
+         */
+        numRow = new DefaultParameterDescriptor<>(IdentifiedObjects.getProperties(numRow),
+                0, 1, Integer.class, valueDomain, null, defaultSize);
+        numCol = new DefaultParameterDescriptor<>(IdentifiedObjects.getProperties(numCol),
+                0, 1, Integer.class, valueDomain, null, defaultSize);
+        EPSG = new MatrixParameters("", "", numRow, numCol);
     }
 
     /**
@@ -207,7 +274,7 @@ public class TensorParameters<E> impleme
      *                    Length may be different if the caller wants to generalize usage of this class to tensors.
      */
     @SafeVarargs
-    @SuppressWarnings("rawtypes")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public TensorParameters(final Class<E> elementType, final String prefix, final String separator,
             final ParameterDescriptor<Integer>... dimensions)
     {
@@ -235,7 +302,7 @@ public class TensorParameters<E> impleme
      *
      * <p>This method is invoked by constructor and on deserialization.</p>
      */
-    @SuppressWarnings("rawtypes")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     private <T> ParameterDescriptor<T>[] createCache() {
         if (Number.class.isAssignableFrom(elementType)) try {
             one  = (E) Numbers.wrap(1, (Class) elementType);
@@ -265,10 +332,10 @@ public class TensorParameters<E> impleme
      *
      * <table class="sis">
      *   <caption>Tensor types implied by rank</caption>
-     *   <tr><th>Rank</th> <th>Type</th></tr>
-     *   <tr><td>0</td>    <td>scalar</td></tr>
-     *   <tr><td>1</td>    <td>vector</td></tr>
-     *   <tr><td>2</td>    <td>matrix</td></tr>
+     *   <tr><th>Rank</th> <th>Type</th>   <th>Used with</th></tr>
+     *   <tr><td>0</td>    <td>scalar</td> <td></td></tr>
+     *   <tr><td>1</td>    <td>vector</td> <td></td></tr>
+     *   <tr><td>2</td>    <td>matrix</td> <td>Affine general parametric transformation</td></tr>
      *   <tr><td><var>k</var></td><td>rank <var>k</var> tensor</td></tr>
      * </table>
      *
@@ -352,47 +419,41 @@ public class TensorParameters<E> impleme
      * This method is invoked by {@link #getElementDescriptor(int[])} when a new descriptor needs
      * to be created.
      *
-     * {@section Default implementation}
+     * <p><b>Default implementation</b></p>
      * The default implementation converts the given indices to a parameter name by invoking the
      * {@link #indicesToName(int[])} method, then creates a descriptor for an optional parameter
-     * of that name.
+     * of that name. The default value is given by {@link #getDefaultValue(int[])}.
      *
-     * {@section Subclassing}
+     * <p><b>Subclassing</b></p>
      * Subclasses can override this method if they want more control on descriptor properties
-     * like identification information, value domain and default values.
+     * like identification information, aliases or value domain.
      *
      * @param  indices The indices of the tensor element for which to create a parameter.
      * @return The parameter descriptor for the given tensor element.
      * @throws IllegalArgumentException If the given array does not have the expected length or have illegal value.
      *
      * @see #indicesToName(int[])
-     * @see #nameToIndices(String)
+     * @see #getDefaultValue(int[])
      */
     protected ParameterDescriptor<E> createElementDescriptor(final int[] indices) throws IllegalArgumentException {
-        boolean isDiagonal = true;
-        for (int i=1; i<indices.length; i++) {
-            if (indices[i] != indices[i-1]) {
-                isDiagonal = false;
-                break;
-            }
-        }
-        final Map<String,Object> properties = new HashMap<>(4);
-        properties.put(Identifier.CODE_KEY, indicesToName(indices));
-        properties.put(Identifier.AUTHORITY_KEY, dimensions[0].getName().getAuthority());
-        return new DefaultParameterDescriptor<>(properties, 0, 1, elementType, null, null, isDiagonal ? one : zero);
+        final Citation authority = dimensions[0].getName().getAuthority();
+        final String name = indicesToName(indices);
+        return new DefaultParameterDescriptor<>(
+                Collections.singletonMap(ParameterDescriptor.NAME_KEY, new NamedIdentifier(authority, name)),
+                0, 1, elementType, null, null, getDefaultValue(indices));
     }
 
     /**
      * Returns the parameter descriptor name of a matrix or tensor element at the given indices.
      * The returned name shall be parsable by the {@link #nameToIndices(String)} method.
      *
-     * {@section Default implementation}
+     * <p><b>Default implementation</b></p>
      * The default implementation requires an {@code indices} array having a length equals to the {@linkplain #rank()
      * rank}. That length is usually 2, where {@code indices[0]} is the <var>row</var> index and {@code indices[1]} is
      * the <var>column</var> index. Then this method builds a name with the “{@link #prefix} + <var>row</var> +
      * {@link #separator} + <var>column</var> + …” pattern (e.g. {@code "elt_0_0"}).
      *
-     * {@section Subclassing}
+     * <p><b>Subclassing</b></p>
      * If a subclass overrides this method for creating different names, then that subclass shall
      * also override {@link #nameToIndices(String)} for parsing those names.
      *
@@ -418,7 +479,7 @@ public class TensorParameters<E> impleme
      * Returns the indices of matrix element for the given parameter name, or {@code null} if none.
      * This method is the converse of {@link #indicesToName(int[])}.
      *
-     * {@section Default implementation}
+     * <p><b>Default implementation</b></p>
      * The default implementation expects a name matching the “{@link #prefix} + <var>row</var> + {@link #separator} +
      * <var>column</var> + …” pattern and returns an array containing the <var>row</var>, <var>column</var> and other
      * indices, in that order.
@@ -448,6 +509,26 @@ public class TensorParameters<E> impleme
     }
 
     /**
+     * Returns the default value for the parameter descriptor at the given indices.
+     * The default implementation returns 1 if all indices are equals, or 0 otherwise.
+     *
+     * @param  indices The indices of the tensor element for which to get the default value.
+     * @return The default value for the tensor element at the given indices, or {@code null} if none.
+     *
+     * @see DefaultParameterDescriptor#getDefaultValue()
+     *
+     * @since 0.6
+     */
+    protected E getDefaultValue(final int[] indices) {
+        for (int i=1; i<indices.length; i++) {
+            if (indices[i] != indices[i-1]) {
+                return zero;
+            }
+        }
+        return one;
+    }
+
+    /**
      * Returns the descriptor in this group for the specified name.
      *
      * @param  name The case insensitive name of the parameter to search for.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -24,7 +24,6 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
-import org.apache.sis.parameter.TensorParameters;
 import org.apache.sis.internal.referencing.provider.Affine;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -310,7 +309,7 @@ final class CopyTransform extends Abstra
      */
     @Override
     public ParameterDescriptorGroup getParameterDescriptors() {
-        return Affine.PARAMETERS;
+        return Affine.descriptor(srcDim, getTargetDimensions());
     }
 
     /**
@@ -318,7 +317,7 @@ final class CopyTransform extends Abstra
      */
     @Override
     public ParameterValueGroup getParameterValues() {
-        return TensorParameters.WKT1.createValueGroup(Affine.IDENTIFICATION, getMatrix());
+        return Affine.parameters(getMatrix());
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -25,7 +25,6 @@ import org.opengis.referencing.operation
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.geometry.GeneralDirectPosition;
-import org.apache.sis.parameter.TensorParameters;
 import org.apache.sis.internal.referencing.provider.Affine;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
@@ -134,7 +133,7 @@ final class IdentityTransform extends Ab
      */
     @Override
     public ParameterDescriptorGroup getParameterDescriptors() {
-        return Affine.PARAMETERS;
+        return Affine.descriptor(dimension, dimension);
     }
 
     /**
@@ -144,7 +143,7 @@ final class IdentityTransform extends Ab
      */
     @Override
     public ParameterValueGroup getParameterValues() {
-        return TensorParameters.WKT1.createValueGroup(Affine.IDENTIFICATION, getMatrix());
+        return Affine.parameters(getMatrix());
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -28,7 +28,6 @@ import org.apache.sis.referencing.operat
 import org.apache.sis.referencing.operation.matrix.Matrix1;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.internal.referencing.provider.Affine;
-import org.apache.sis.parameter.TensorParameters;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.ComparisonMode;
 
@@ -116,7 +115,7 @@ class LinearTransform1D extends Abstract
      */
     @Override
     public ParameterDescriptorGroup getParameterDescriptors() {
-        return Affine.PARAMETERS;
+        return Affine.descriptor(1, 1);
     }
 
     /**
@@ -128,7 +127,7 @@ class LinearTransform1D extends Abstract
      */
     @Override
     public ParameterValueGroup getParameterValues() {
-        return TensorParameters.WKT1.createValueGroup(Affine.IDENTIFICATION, getMatrix());
+        return Affine.parameters(getMatrix());
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -25,7 +25,6 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.util.ComparisonMode;
-import org.apache.sis.parameter.TensorParameters;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
@@ -152,7 +151,7 @@ class ProjectiveTransform extends Abstra
      */
     @Override
     public ParameterDescriptorGroup getParameterDescriptors() {
-        return Affine.PARAMETERS;
+        return Affine.descriptor(getSourceDimensions(), getTargetDimensions());
     }
 
     /**
@@ -163,7 +162,7 @@ class ProjectiveTransform extends Abstra
      */
     @Override
     public ParameterValueGroup getParameterValues() {
-        return TensorParameters.WKT1.createValueGroup(Affine.IDENTIFICATION, getMatrix());
+        return Affine.parameters(getMatrix());
     }
 
     /**

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AffineTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AffineTest.java?rev=1660664&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AffineTest.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AffineTest.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.referencing.provider;
+
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the {@link Affine} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.6
+ * @version 0.6
+ * @module
+ */
+@DependsOn(org.apache.sis.parameter.MatrixParametersTest.class)
+public final strictfp class AffineTest extends TestCase {
+    /**
+     * Ensures that the {@link Affine#EPSG_INDEX} value is consistent with
+     * {@link Affine#cacheIndex(int, int)} computation.
+     */
+    @Test
+    public void testEpsgIndex() {
+        assertEquals("EPSG_INDEX", Affine.cacheIndex(Affine.EPSG_DIMENSION, Affine.EPSG_DIMENSION), Affine.EPSG_INDEX);
+    }
+}

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

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

Copied: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MatrixParametersTest.java (from r1660202, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MatrixParametersTest.java?p2=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MatrixParametersTest.java&p1=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java&r1=1660202&r2=1660664&rev=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MatrixParametersTest.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -16,184 +16,148 @@
  */
 package org.apache.sis.parameter;
 
-import java.util.Map;
-import java.util.List;
-import java.util.Random;
-import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.parameter.GeneralParameterDescriptor;
-import org.opengis.referencing.operation.Matrix;
-import org.apache.sis.referencing.operation.matrix.Matrices;
-import org.apache.sis.test.TestUtilities;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
-import static java.util.Collections.singletonMap;
-import static org.opengis.test.Validators.validate;
-import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
-import static org.apache.sis.parameter.TensorParameters.WKT1;
 import static org.apache.sis.test.Assert.*;
 
 
 /**
- * Tests the {@link TensorParameters} class.
+ * Tests the {@link MatrixParameters} class using the {@link TensorParameters#WKT1} and
+ * {@link TensorParameters#EPSG} constants.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.4
- * @version 0.4
+ * @since   0.6
+ * @version 0.6
  * @module
  */
-@DependsOn(ParametersTest.class)
-public final strictfp class TensorParametersTest extends TestCase {
+@DependsOn(TensorParametersTest.class)
+public final strictfp class MatrixParametersTest extends TestCase {
     /**
-     * Asserts that the given descriptor has the given name and default value.
+     * The expected parameter names according the EPSG convention for the matrix elements.
+     *
+     * @see TensorParametersTest#ELEMENT_NAMES
      */
-    static void assertDescriptorEquals(final String name, final Number defaultValue,
-            final GeneralParameterDescriptor actual)
-    {
-        assertEquals(name, actual.getName().getCode());
-        assertEquals(name, defaultValue, ((ParameterDescriptor<?>) actual).getDefaultValue());
+    private static final String[][] NAMES = {
+        {"A0", "A1", "A2", "A3"},
+        {"B0", "B1", "B2", "B3"},
+        {"C0", "C1", "C2", "C3"},
+        {"D0", "D1", "D2", "D3"}
+    };
+
+    /**
+     * The expected parameter identifiers for the matrix elements, or 0 if none.
+     * Note that the EPSG database contains A3 and B3 parameters, but they are
+     * for polynomial transformation, not affine transformation.
+     */
+    private static final short[][] IDENTIFIERS = {
+        {8623, 8624, 8625, 0},
+        {8639, 8640, 8641, 0},
+        {   0,    0,    0, 0},
+        {   0,    0,    0, 0}
+    };
+
+    /**
+     * Tests {@link MatrixParameters#isEPSG()}.
+     */
+    @Test
+    public void testIsEPSG() {
+        assertTrue (((MatrixParameters) TensorParameters.EPSG).isEPSG());
+        assertFalse(((MatrixParameters) TensorParameters.WKT1).isEPSG());
     }
 
     /**
-     * Tests {@link TensorParameters#getDimensionDescriptor(int)}.
+     * Tests {@link MatrixParameters#indicesToAlias(int[])}.
      */
     @Test
-    public void testGetDimensionDescriptor() {
-        final Integer THREE = 3;
-        assertDescriptorEquals("num_row", THREE, WKT1.getDimensionDescriptor(0));
-        assertDescriptorEquals("num_col", THREE, WKT1.getDimensionDescriptor(1));
+    public void testIndicesToAlias() {
+        assertEquals("A0", MatrixParameters.indicesToAlias(new int[] {0, 0}));
+        assertEquals("A1", MatrixParameters.indicesToAlias(new int[] {0, 1}));
+        assertEquals("A2", MatrixParameters.indicesToAlias(new int[] {0, 2}));
+        assertEquals("B0", MatrixParameters.indicesToAlias(new int[] {1, 0}));
+        assertEquals("B1", MatrixParameters.indicesToAlias(new int[] {1, 1}));
+        assertEquals("B2", MatrixParameters.indicesToAlias(new int[] {1, 2}));
+        assertNull(MatrixParameters.indicesToAlias(new int[] {27, 2}));
+        assertNull(MatrixParameters.indicesToAlias(new int[] {2, 10}));
     }
 
     /**
-     * Tests {@link TensorParameters#getElementDescriptor(int[])}.
+     * Tests {@link MatrixParameters#aliasToIndices(String)}.
      */
     @Test
-    @DependsOnMethod("testIndicesToName")
-    public void testGetElementDescriptor() {
-        final Double  ZERO  = 0.0;
-        final Double  ONE   = 1.0;
-        final ParameterDescriptor<Double> e00 = WKT1.getElementDescriptor(0, 0);
-        final ParameterDescriptor<Double> e01 = WKT1.getElementDescriptor(0, 1);
-        final ParameterDescriptor<Double> e10 = WKT1.getElementDescriptor(1, 0);
-        final ParameterDescriptor<Double> e11 = WKT1.getElementDescriptor(1, 1);
-        assertDescriptorEquals("elt_0_0", ONE,  e00);
-        assertDescriptorEquals("elt_0_1", ZERO, e01);
-        assertDescriptorEquals("elt_1_0", ZERO, e10);
-        assertDescriptorEquals("elt_1_1", ONE,  e11);
-        assertSame(e00, WKT1.getElementDescriptor(0, 0)); // Test caching.
-        assertSame(e01, WKT1.getElementDescriptor(0, 1));
-        assertSame(e10, WKT1.getElementDescriptor(1, 0));
-        assertSame(e11, WKT1.getElementDescriptor(1, 1));
-        /*
-         * Tests a value outside the cache capacity.
-         */
-        final int row = TensorParameters.CACHE_SIZE + 1;
-        final int col = TensorParameters.CACHE_SIZE + 2;
-        assertDescriptorEquals("elt_" + row + "_" + col, ZERO, WKT1.getElementDescriptor(row, col));
+    public void testAliasToIndices() {
+        assertArrayEquals(new int[] {0, 0}, MatrixParameters.aliasToIndices("A0"));
+        assertArrayEquals(new int[] {0, 1}, MatrixParameters.aliasToIndices("A1"));
+        assertArrayEquals(new int[] {0, 2}, MatrixParameters.aliasToIndices("A2"));
+        assertArrayEquals(new int[] {1, 0}, MatrixParameters.aliasToIndices("B0"));
+        assertArrayEquals(new int[] {1, 1}, MatrixParameters.aliasToIndices("B1"));
+        assertArrayEquals(new int[] {1, 2}, MatrixParameters.aliasToIndices("B2"));
+        assertNull(MatrixParameters.aliasToIndices("2B"));
+        assertNull(MatrixParameters.aliasToIndices("elt_1_2"));
     }
 
     /**
-     * Tests {@link TensorParameters#indicesToName(int[])}.
+     * Tests {@link MatrixParameters#indicesToName(int[])}.
      */
     @Test
+    @DependsOnMethod({"testIsEPSG", "testIndicesToAlias"})
     public void testIndicesToName() {
-        assertEquals("elt_4_8", WKT1.indicesToName(new int[] {4, 8}));
-        assertEquals("elt_7_2", WKT1.indicesToName(new int[] {7, 2}));
+        TensorParametersTest.testIndicesToName(TensorParameters.WKT1);
+        assertEquals("E8", TensorParameters.EPSG.indicesToName(new int[] {4, 8}));
+        assertEquals("H2", TensorParameters.EPSG.indicesToName(new int[] {7, 2}));
     }
 
     /**
-     * Tests {@link TensorParameters#nameToIndices(String)}.
+     * Tests {@link MatrixParameters#nameToIndices(String)}.
      */
     @Test
+    @DependsOnMethod({"testIsEPSG", "testAliasToIndices"})
     public void testNameToIndices() {
-        assertArrayEquals(new int[] {4, 8}, WKT1.nameToIndices("elt_4_8"));
-        assertArrayEquals(new int[] {7, 2}, WKT1.nameToIndices("elt_7_2"));
-        assertNull(WKT1.nameToIndices("other_7_2"));
-        assertNull(WKT1.nameToIndices("elt_7"));
-        try {
-            WKT1.nameToIndices("elt_7_2_3");
-            fail("Should not have parsed a name with too many indices.");
-        } catch (IllegalArgumentException e) {
-            // This is the expected exception.
-        }
+        TensorParametersTest.testNameToIndices(TensorParameters.WKT1);
+        assertArrayEquals(new int[] {4, 8}, TensorParameters.EPSG.nameToIndices("E8"));
+        assertArrayEquals(new int[] {7, 2}, TensorParameters.EPSG.nameToIndices("H2"));
+        assertNull(TensorParameters.EPSG.nameToIndices("other_7_2"));
+        assertNull(TensorParameters.EPSG.nameToIndices("elt_7"));
     }
 
     /**
-     * Tests {@link TensorParameters#descriptors(int[])} for a 1×1, 2×3 and 3×3 matrices.
+     * Tests {@link MatrixParameters#getDimensionDescriptor(int)}.
      */
     @Test
-    @DependsOnMethod("testGetElementDescriptor")
-    public void testDescriptors() {
-        final Double  ZERO  = 0.0;
-        final Double  ONE   = 1.0;
-        final Integer THREE = 3;
-        List<GeneralParameterDescriptor> descriptors = WKT1.descriptors(new int[] {1, 1});
-        assertDescriptorEquals("num_row", THREE, descriptors.get(0));
-        assertDescriptorEquals("num_col", THREE, descriptors.get(1));
-        assertDescriptorEquals("elt_0_0", ONE,   descriptors.get(2));
-        assertEquals("size", 3, descriptors.size());
-
-        descriptors = WKT1.descriptors(new int[] {2, 3});
-        assertDescriptorEquals("num_row", THREE, descriptors.get(0));
-        assertDescriptorEquals("num_col", THREE, descriptors.get(1));
-        assertDescriptorEquals("elt_0_0", ONE,   descriptors.get(2));
-        assertDescriptorEquals("elt_0_1", ZERO,  descriptors.get(3));
-        assertDescriptorEquals("elt_0_2", ZERO,  descriptors.get(4));
-        assertDescriptorEquals("elt_1_0", ZERO,  descriptors.get(5));
-        assertDescriptorEquals("elt_1_1", ONE,   descriptors.get(6));
-        assertDescriptorEquals("elt_1_2", ZERO,  descriptors.get(7));
-        assertEquals("size", 8, descriptors.size());
-
-        descriptors = WKT1.descriptors(new int[] {3, 3});
-        assertDescriptorEquals("num_row", THREE, descriptors.get( 0));
-        assertDescriptorEquals("num_col", THREE, descriptors.get( 1));
-        assertDescriptorEquals("elt_0_0", ONE,   descriptors.get( 2));
-        assertDescriptorEquals("elt_0_1", ZERO,  descriptors.get( 3));
-        assertDescriptorEquals("elt_0_2", ZERO,  descriptors.get( 4));
-        assertDescriptorEquals("elt_1_0", ZERO,  descriptors.get( 5));
-        assertDescriptorEquals("elt_1_1", ONE,   descriptors.get( 6));
-        assertDescriptorEquals("elt_1_2", ZERO,  descriptors.get( 7));
-        assertDescriptorEquals("elt_2_0", ZERO,  descriptors.get( 8));
-        assertDescriptorEquals("elt_2_1", ZERO,  descriptors.get( 9));
-        assertDescriptorEquals("elt_2_2", ONE,   descriptors.get(10));
-        assertEquals("size", 11, descriptors.size());
+    public void testGetDimensionDescriptor() {
+        TensorParametersTest.testGetDimensionDescriptor(TensorParameters.WKT1);
+        TensorParametersTest.testGetDimensionDescriptor(TensorParameters.EPSG);
+    }
+
+    /**
+     * Tests {@link TensorParameters#getElementDescriptor(int[])}.
+     */
+    @Test
+    @DependsOnMethod("testIndicesToName")
+    public void testGetElementDescriptor() {
+        TensorParametersTest.testGetElementDescriptor(TensorParameters.WKT1, TensorParametersTest.ELEMENT_NAMES, NAMES, IDENTIFIERS);
+        TensorParametersTest.testGetElementDescriptor(TensorParameters.EPSG, NAMES, TensorParametersTest.ELEMENT_NAMES, IDENTIFIERS);
     }
 
     /**
-     * Tests {@link TensorParameters#createValueGroup(Map, Matrix)} and its converse
-     * {@link TensorParameters#toMatrix(ParameterValueGroup)}.
-     */
-    @Test
-    @DependsOnMethod("testDescriptors")
-    public void testMatrixConversion() {
-        final int size = 8;
-        final Random random = TestUtilities.createRandomNumberGenerator();
-        for (int numRow = 2; numRow <= size; numRow++) {
-            for (int numCol = 2; numCol <= size; numCol++) {
-                final Matrix matrix = Matrices.createZero(numRow, numCol);
-                for (int j=0; j<numRow; j++) {
-                    for (int i=0; i<numCol; i++) {
-                        matrix.setElement(j, i, 200*random.nextDouble() - 100);
-                    }
-                }
-                final ParameterValueGroup group = WKT1.createValueGroup(singletonMap(NAME_KEY, "Test"), matrix);
-                validate(group);
-                assertEquals("num_row",  numRow, group.parameter("num_row").intValue());
-                assertEquals("num_col",  numCol, group.parameter("num_col").intValue());
-                assertEquals("elements", matrix, WKT1.toMatrix(group));
-                assertEquals("elements", matrix, WKT1.toMatrix(new ParameterValueGroupWrapper(group)));
-            }
-        }
+     * Tests {@link TensorParameters#descriptors(int[])} for a 1×1, 2×3 and 3×3 matrices.
+     */
+    @Test
+    @DependsOnMethod("testGetElementDescriptor")
+    public void testDescriptors() {
+        TensorParametersTest.testDescriptors(TensorParameters.WKT1, TensorParametersTest.ELEMENT_NAMES, NAMES, IDENTIFIERS);
+        TensorParametersTest.testDescriptors(TensorParameters.EPSG, NAMES, TensorParametersTest.ELEMENT_NAMES, IDENTIFIERS);
     }
 
     /**
      * Tests serialization.
      */
     @Test
+    @DependsOnMethod("testIsEPSG")
     public void testSerialization() {
-        assertSerializedEquals(TensorParameters.WKT1);
+        assertSame(TensorParameters.EPSG, assertSerializedEquals(TensorParameters.EPSG));
+        assertSame(TensorParameters.WKT1, assertSerializedEquals(TensorParameters.WKT1));
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java?rev=1660664&r1=1660663&r2=1660664&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/TensorParametersTest.java [UTF-8] Wed Feb 18 16:26:52 2015
@@ -28,13 +28,14 @@ import org.apache.sis.test.TestUtilities
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
 import org.junit.Test;
 
 import static java.util.Collections.singletonMap;
 import static org.opengis.test.Validators.validate;
 import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
-import static org.apache.sis.parameter.TensorParameters.WKT1;
-import static org.apache.sis.test.Assert.*;
+import static org.apache.sis.test.ReferencingAssert.*;
 
 
 /**
@@ -42,19 +43,75 @@ import static org.apache.sis.test.Assert
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 @DependsOn(ParametersTest.class)
 public final strictfp class TensorParametersTest extends TestCase {
     /**
-     * Asserts that the given descriptor has the given name and default value.
+     * The parameters to use for testing purpose. Mostly identical to {@link TensorParameters#WKT1},
+     * except that it is not an instance of the {@link MatrixParameters} subclass. Those parameters
+     * do not contain EPSG aliases and identifiers.
      */
-    static void assertDescriptorEquals(final String name, final Number defaultValue,
-            final GeneralParameterDescriptor actual)
+    private static TensorParameters<Double> WKT1;
+
+    /**
+     * The expected parameter names according the WKT 1 convention for the matrix size.
+     */
+    private static final String[][] SIZE_NAMES = {
+        {"num_row"},
+        {"num_col"}
+    };
+
+    /**
+     * The expected parameter names according the WKT 1 convention for the matrix elements.
+     *
+     * @see MatrixParametersTest#NAMES
+     */
+    static final String[][] ELEMENT_NAMES = {
+        {"elt_0_0", "elt_0_1", "elt_0_2", "elt_0_3"},
+        {"elt_1_0", "elt_1_1", "elt_1_2", "elt_1_3"},
+        {"elt_2_0", "elt_2_1", "elt_2_2", "elt_2_3"},
+        {"elt_3_0", "elt_3_1", "elt_3_2", "elt_3_3"}
+    };
+
+    /**
+     * Creates the parameters to be used by the tests in this class.
+     */
+    @BeforeClass
+    @SuppressWarnings("unchecked")
+    public static void createTensorParameters() {
+        WKT1 = new TensorParameters<>(Double.class, "elt_", "_",
+                TensorParameters.WKT1.getDimensionDescriptor(0),
+                TensorParameters.WKT1.getDimensionDescriptor(1));
+    }
+
+    /**
+     * Discards the parameters used by the tests in this class.
+     */
+    @AfterClass
+    public static void clearTensorParameters() {
+        WKT1 = null;
+    }
+
+    /**
+     * Asserts that the given descriptor has the given name, alias, identifier and default value.
+     *
+     * @param names        The expected parameter names for all matrix elements.
+     * @param aliases      The expected parameter aliases for all matrix elements, or {@code null} for no alias.
+     * @param identifiers  The expected parameter identifiers for all matrix elements, or {@code null} for no identifier.
+     * @param defaultValue The expected parameter default value.
+     * @param actual       The actual parameter to verify.
+     * @param row          Row index of the matrix element to test.
+     * @param column       Column index of the matrix element to test.
+     */
+    private static void verifyDescriptor(final String[][] names, final String[][] aliases, final short[][] identifiers,
+            final Number defaultValue, final GeneralParameterDescriptor actual, final int row, final int column)
     {
-        assertEquals(name, actual.getName().getCode());
-        assertEquals(name, defaultValue, ((ParameterDescriptor<?>) actual).getDefaultValue());
+        assertEquals("name", names[row][column], actual.getName().getCode());
+        assertAliasTipEquals((aliases != null) ? aliases[row][column] : null, actual);
+        assertIdentifierEqualsEPSG((identifiers != null) ? identifiers[row][column] : 0, actual);
+        assertEquals("defaultValue", defaultValue, ((ParameterDescriptor<?>) actual).getDefaultValue());
     }
 
     /**
@@ -62,9 +119,14 @@ public final strictfp class TensorParame
      */
     @Test
     public void testGetDimensionDescriptor() {
-        final Integer THREE = 3;
-        assertDescriptorEquals("num_row", THREE, WKT1.getDimensionDescriptor(0));
-        assertDescriptorEquals("num_col", THREE, WKT1.getDimensionDescriptor(1));
+        testGetDimensionDescriptor(WKT1);
+    }
+
+    /** Implementation of {@link #testGetDimensionDescriptor()} with user-supplied parameters. */
+    static void testGetDimensionDescriptor(final TensorParameters<Double> WKT1) {
+        final Integer N3 = 3;
+        verifyDescriptor(SIZE_NAMES, null, null, N3, WKT1.getDimensionDescriptor(0), 0, 0);
+        verifyDescriptor(SIZE_NAMES, null, null, N3, WKT1.getDimensionDescriptor(1), 1, 0);
     }
 
     /**
@@ -73,26 +135,38 @@ public final strictfp class TensorParame
     @Test
     @DependsOnMethod("testIndicesToName")
     public void testGetElementDescriptor() {
-        final Double  ZERO  = 0.0;
-        final Double  ONE   = 1.0;
+        testGetElementDescriptor(WKT1, ELEMENT_NAMES, null, null);
+    }
+
+    /** Implementation of {@link #testGetElementDescriptor()} with user-supplied parameters. */
+    static void testGetElementDescriptor(final TensorParameters<Double> WKT1,
+            final String[][] names, final String[][] aliases, final short[][] identifiers)
+    {
+        final Double N0 = 0.0;
+        final Double N1 = 1.0;
         final ParameterDescriptor<Double> e00 = WKT1.getElementDescriptor(0, 0);
         final ParameterDescriptor<Double> e01 = WKT1.getElementDescriptor(0, 1);
         final ParameterDescriptor<Double> e10 = WKT1.getElementDescriptor(1, 0);
         final ParameterDescriptor<Double> e11 = WKT1.getElementDescriptor(1, 1);
-        assertDescriptorEquals("elt_0_0", ONE,  e00);
-        assertDescriptorEquals("elt_0_1", ZERO, e01);
-        assertDescriptorEquals("elt_1_0", ZERO, e10);
-        assertDescriptorEquals("elt_1_1", ONE,  e11);
+        verifyDescriptor(names, aliases, identifiers, N1, e00, 0, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, e01, 0, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, e10, 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, e11, 1, 1);
         assertSame(e00, WKT1.getElementDescriptor(0, 0)); // Test caching.
         assertSame(e01, WKT1.getElementDescriptor(0, 1));
         assertSame(e10, WKT1.getElementDescriptor(1, 0));
         assertSame(e11, WKT1.getElementDescriptor(1, 1));
-        /*
-         * Tests a value outside the cache capacity.
-         */
+    }
+
+    /**
+     * Tests {@link TensorParameters#getElementDescriptor(int[])} with a value outside the cache capacity.
+     */
+    @DependsOnMethod("testGetElementDescriptor")
+    public void testGetElementDescriptorOutsideCache() {
         final int row = TensorParameters.CACHE_SIZE + 1;
         final int col = TensorParameters.CACHE_SIZE + 2;
-        assertDescriptorEquals("elt_" + row + "_" + col, ZERO, WKT1.getElementDescriptor(row, col));
+        verifyDescriptor(new String[][] {{"elt_" + row + "_" + col}}, null, null, 0.0,
+                WKT1.getElementDescriptor(row, col), 0, 0);
     }
 
     /**
@@ -100,6 +174,11 @@ public final strictfp class TensorParame
      */
     @Test
     public void testIndicesToName() {
+        testIndicesToName(WKT1);
+    }
+
+    /** Implementation of {@link #testIndicesToName()} with user-supplied parameters. */
+    static void testIndicesToName(final TensorParameters<Double> WKT1) {
         assertEquals("elt_4_8", WKT1.indicesToName(new int[] {4, 8}));
         assertEquals("elt_7_2", WKT1.indicesToName(new int[] {7, 2}));
     }
@@ -109,6 +188,11 @@ public final strictfp class TensorParame
      */
     @Test
     public void testNameToIndices() {
+        testNameToIndices(WKT1);
+    }
+
+    /** Implementation of {@link #testNameToIndices()} with user-supplied parameters. */
+    static void testNameToIndices(final TensorParameters<Double> WKT1) {
         assertArrayEquals(new int[] {4, 8}, WKT1.nameToIndices("elt_4_8"));
         assertArrayEquals(new int[] {7, 2}, WKT1.nameToIndices("elt_7_2"));
         assertNull(WKT1.nameToIndices("other_7_2"));
@@ -127,39 +211,67 @@ public final strictfp class TensorParame
     @Test
     @DependsOnMethod("testGetElementDescriptor")
     public void testDescriptors() {
-        final Double  ZERO  = 0.0;
-        final Double  ONE   = 1.0;
-        final Integer THREE = 3;
+        testDescriptors(WKT1, ELEMENT_NAMES, null, null);
+    }
+
+    /** Implementation of {@link #testDescriptors()} with user-supplied parameters. */
+    static void testDescriptors(final TensorParameters<Double> WKT1,
+            final String[][] names, final String[][] aliases, final short[][] identifiers)
+    {
+        final Double  N0 = 0.0;
+        final Double  N1 = 1.0;
+        final Integer N3 = 3;
         List<GeneralParameterDescriptor> descriptors = WKT1.descriptors(new int[] {1, 1});
-        assertDescriptorEquals("num_row", THREE, descriptors.get(0));
-        assertDescriptorEquals("num_col", THREE, descriptors.get(1));
-        assertDescriptorEquals("elt_0_0", ONE,   descriptors.get(2));
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(0), 0, 0);
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(1), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get(2), 0, 0);
         assertEquals("size", 3, descriptors.size());
 
         descriptors = WKT1.descriptors(new int[] {2, 3});
-        assertDescriptorEquals("num_row", THREE, descriptors.get(0));
-        assertDescriptorEquals("num_col", THREE, descriptors.get(1));
-        assertDescriptorEquals("elt_0_0", ONE,   descriptors.get(2));
-        assertDescriptorEquals("elt_0_1", ZERO,  descriptors.get(3));
-        assertDescriptorEquals("elt_0_2", ZERO,  descriptors.get(4));
-        assertDescriptorEquals("elt_1_0", ZERO,  descriptors.get(5));
-        assertDescriptorEquals("elt_1_1", ONE,   descriptors.get(6));
-        assertDescriptorEquals("elt_1_2", ZERO,  descriptors.get(7));
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(0), 0, 0);
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(1), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get(2), 0, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(3), 0, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(4), 0, 2);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(5), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get(6), 1, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(7), 1, 2);
         assertEquals("size", 8, descriptors.size());
 
         descriptors = WKT1.descriptors(new int[] {3, 3});
-        assertDescriptorEquals("num_row", THREE, descriptors.get( 0));
-        assertDescriptorEquals("num_col", THREE, descriptors.get( 1));
-        assertDescriptorEquals("elt_0_0", ONE,   descriptors.get( 2));
-        assertDescriptorEquals("elt_0_1", ZERO,  descriptors.get( 3));
-        assertDescriptorEquals("elt_0_2", ZERO,  descriptors.get( 4));
-        assertDescriptorEquals("elt_1_0", ZERO,  descriptors.get( 5));
-        assertDescriptorEquals("elt_1_1", ONE,   descriptors.get( 6));
-        assertDescriptorEquals("elt_1_2", ZERO,  descriptors.get( 7));
-        assertDescriptorEquals("elt_2_0", ZERO,  descriptors.get( 8));
-        assertDescriptorEquals("elt_2_1", ZERO,  descriptors.get( 9));
-        assertDescriptorEquals("elt_2_2", ONE,   descriptors.get(10));
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(0), 0, 0);
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(1), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get( 2), 0, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 3), 0, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 4), 0, 2);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 5), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get( 6), 1, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 7), 1, 2);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 8), 2, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 9), 2, 1);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get(10), 2, 2);
         assertEquals("size", 11, descriptors.size());
+
+        descriptors = WKT1.descriptors(new int[] {4, 4});
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(0), 0, 0);
+        verifyDescriptor(SIZE_NAMES, null, null,      N3, descriptors.get(1), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get( 2), 0, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 3), 0, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 4), 0, 2);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 5), 0, 3);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 6), 1, 0);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get( 7), 1, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 8), 1, 2);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get( 9), 1, 3);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(10), 2, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(11), 2, 1);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get(12), 2, 2);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(13), 2, 3);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(14), 3, 0);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(15), 3, 1);
+        verifyDescriptor(names, aliases, identifiers, N0, descriptors.get(16), 3, 2);
+        verifyDescriptor(names, aliases, identifiers, N1, descriptors.get(17), 3, 3);
+        assertEquals("size", 18, descriptors.size());
     }
 
     /**
@@ -194,6 +306,6 @@ public final strictfp class TensorParame
      */
     @Test
     public void testSerialization() {
-        assertSerializedEquals(TensorParameters.WKT1);
+        assertSerializedEquals(WKT1);
     }
 }



Mime
View raw message