sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1674709 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/internal/referencing/j2d/ main/java/org/apache/sis/referencing/operation/transform/ test/java/org/apache/sis/referencing/operation/transform/
Date Mon, 20 Apr 2015 00:22:47 GMT
Author: desruisseaux
Date: Mon Apr 20 00:22:47 2015
New Revision: 1674709

URL: http://svn.apache.org/r1674709
Log:
Referencing: bug fixes
1) be less aggressive about unmodifiable ContextualParameters (we should be able to get a
parameter default value if the parameter is not present).
2) ParameterizedAffine should return the "Equidistant Cylindrical (Spherical)" parameters
when queried from a ProjectedCRS element no matter axis swapping.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ContextualParametersTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java?rev=1674709&r1=1674708&r2=1674709&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
[UTF-8] Mon Apr 20 00:22:47 2015
@@ -21,6 +21,7 @@ import java.awt.geom.AffineTransform;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.MathTransform;
+import org.apache.sis.internal.system.Semaphores;
 
 
 /**
@@ -109,12 +110,35 @@ public final class ParameterizedAffine e
     /**
      * Returns the parameter values for this map projection.
      *
+     * <p><b>Hack:</b> this method normally returns the matrix parameters
in case of doubt. However if
+     * {@link Semaphores#PROJCS} is set, then this method returns the map projection parameters
even
+     * if they are not a complete description of this math transform. This internal hack
shall be used
+     * only by {@link org.apache.sis.referencing.operation.DefaultSingleOperation}.</p>
+     *
+     * <p><b>Use case of above hack:</b> consider an "Equidistant Cylindrical
(Spherical)" map projection
+     * from a {@code GeographiCRS} base using (latitude, longitude) axis order. We need to
concatenate an
+     * affine transform performing the axis swapping before the actual map projection. The
concatenated
+     * transform is part of {@code SingleOperation}, which is itself part of {@code ProjecteCRS}.
+     * Consequently we have two conflicting needs:</p>
+     *
+     * <ul>
+     *   <li>If this method is queried from a {@code SingleOperation} instance (usually
indirectly as part of a
+     *     {@code ProjectedCRS}), then we want to return the "Equidistant Cylindrical (Spherical)"
map projection
+     *     parameters without bothering about axis swapping, because the later is described
by the {@code Axis["…"]}
+     *     elements in the enclosing {@code ProjectedCRS} instance.</li>
+     *   <li>But if this {@code MathTransform} is formatted directly (not as a component
of {@code ProjectedCRS}),
+     *     then we want to format it as a matrix, otherwise the users would have no way to
see that an axis swapping
+     *     has been applied.</li>
+     * </ul>
+     *
+     * The {@code Semaphores.PROJCS} flag is SIS internal mechanism for distinguish the two
above-cited cases.
+     *
      * @return The map projection parameters if they are an accurate description of this
transform,
      *         or the generic affine parameters in case of doubt.
      */
     @Override
     public ParameterValueGroup getParameterValues() {
-        return isDefinitive ? parameters : super.getParameterValues();
+        return isDefinitive || Semaphores.query(Semaphores.PROJCS) ? parameters : super.getParameterValues();
     }
 
     /**
@@ -131,7 +155,8 @@ public final class ParameterizedAffine e
         if (super.equals(object)) {
             if (object instanceof ParameterizedAffine) {
                 final ParameterizedAffine that = (ParameterizedAffine) object;
-                return Objects.equals(this.parameters, that.parameters);
+                return (this.isDefinitive == that.isDefinitive) &&
+                       Objects.equals(this.parameters, that.parameters);
             }
             return true;
         }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1674709&r1=1674708&r2=1674709&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
[UTF-8] Mon Apr 20 00:22:47 2015
@@ -18,6 +18,9 @@ package org.apache.sis.referencing.opera
 
 import java.util.List;
 import java.util.Arrays;
+import java.util.Map;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
 import java.util.Objects;
 import java.io.Serializable;
 import org.opengis.util.FactoryException;
@@ -368,13 +371,44 @@ public class ContextualParameters extend
     {
         if (!isFrozen) {
             isFrozen = true;
-            for (int i=0; i < values.length; i++) {
-                final ParameterValue<?> p = values[i];
+            /*
+             * Sort the parameter values in the same order than the parameter descriptor.
This is not essential,
+             * but makes easier to read 'toString()' output by ensuring a consistent order
for most projections.
+             * Some WKT parsers other than SIS may also require the parameter values to be
listed in that specific
+             * order. We proceed by first copying all parameters in a temporary HashMap:
+             */
+            final Map<ParameterDescriptor<?>, ParameterValue<?>> parameters
= new IdentityHashMap<>(values.length);
+            for (ParameterValue<?> p : values) {
                 if (p == null) {
-                    values = Arrays.copyOf(values, i);  // Trim extra values.
-                    break;
+                    break;  // The first null value in the array indicates the end of sequence.
+                }
+                p = DefaultParameterValue.unmodifiable(p);
+                final ParameterDescriptor<?> desc = p.getDescriptor();
+                if (parameters.put(desc, p) != null) {
+                    // Should never happen unless ParameterValue.descriptor changed (contract
violation).
+                    throw new IllegalStateException(Errors.format(Errors.Keys.ElementAlreadyPresent_1,
desc.getName()));
+                }
+            }
+            /*
+             * Then, copy all HashMap values back to the 'values' array in the order they
are declared in the
+             * descriptor. Implementation note: the iteration termination condition uses
the values array, not
+             * the descriptors list, because the former is often shorter than the later.
We should never reach
+             * the end of descriptors list before the end of values array because 'descriptors'
contains all
+             * 'parameters' keys. This is verified by the 'assert' below.
+             */
+            values = new ParameterValue<?>[parameters.size()];
+            assert descriptor.descriptors().containsAll(parameters.keySet());
+            final Iterator<GeneralParameterDescriptor> it = descriptor.descriptors().iterator();
+            for (int i=0; i < values.length;) {
+                /*
+                 * No need to check for it.hasNext(), since a NoSuchElementException below
would be a bug in
+                 * our algorithm (or a concurrent change in the 'descriptor.descriptors()'
list, which would
+                 * be a contract violation). See above 'assert'.
+                 */
+                final ParameterValue<?> p = parameters.get(it.next());
+                if (p != null) {
+                    values[i++] = p;
                 }
-                values[i] = DefaultParameterValue.unmodifiable(p);
             }
         }
         /*
@@ -418,11 +452,6 @@ public class ContextualParameters extend
         for (int i=0; i < values.length; i++) {
             ParameterValue<?> p = values[i];
             if (p == null) {
-                /*
-                 * No existing parameter instance. Create a new one if this ContextualParameter
-                 * is still modifiable.
-                 */
-                ensureModifiable();
                 p = ((ParameterDescriptor<?>) desc).createValue();
                 values[i] = p;
             } else if (p.getDescriptor() != desc) {  // Identity comparison should be okay
here.
@@ -430,7 +459,17 @@ public class ContextualParameters extend
             }
             return p;   // Found or created a parameter.
         }
-        ensureModifiable();
+        /*
+         * We may reach this point if map projection construction is completed (i.e. 'completeTransform(…)'
has
+         * been invoked) and the user asks for a parameter which is not one of the parameters
that we retained.
+         * Returns a parameter initialized to the default value, which is the actual value
(otherwise we would
+         * have stored that parameter).  Note: we do not bother making the parameter immutable
for performance
+         * reason. If the user invokes a setter method on the returned parameter, he may
get a false impression
+         * that this ContextualParameters is still modifiable. We presume that such scenario
would be rare.
+         */
+        if (isFrozen) {
+            return ((ParameterDescriptor<?>) desc).createValue();
+        }
         /*
          * Should never reach this point. If it happen anyway, this means that the descriptor
now accepts
          * more parameters than what it declared at ContextualParameteres construction time,
or that some

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1674709&r1=1674708&r2=1674709&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] Mon Apr 20 00:22:47 2015
@@ -665,7 +665,7 @@ public class DefaultMathTransformFactory
          * "elt_0_0", "elt_0_1", etc.  The following code just forwards those parameters
to the newly
          * created transform; it does not change the operation.
          */
-        if (parameterized instanceof ParameterizedAffine) {
+        if (parameterized instanceof ParameterizedAffine && !(mt instanceof ParameterizedAffine))
{
             mt = ((ParameterizedAffine) parameterized).newTransform(mt);
         }
         return mt;

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ContextualParametersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ContextualParametersTest.java?rev=1674709&r1=1674708&r2=1674709&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ContextualParametersTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/ContextualParametersTest.java
[UTF-8] Mon Apr 20 00:22:47 2015
@@ -112,15 +112,16 @@ public final strictfp class ContextualPa
     @Test
     public void testSameTransform() throws FactoryException {
         final ContextualParameters p = create(1, 1);
+        p.parameter("Mandatory 1").setValue(4);
         final MathTransform kernel = MathTransforms.linear(3, 4);
         assertEquals(kernel, p.completeTransform(DefaultMathTransformFactoryTest.factory(),
kernel));
         try {
-            p.parameter("Mandatory 1");
+            p.parameter("Mandatory 1").setValue(10);
             fail("Shall not be allowed to modify an immutable instance.");
-        } catch (IllegalStateException e) {
+        } catch (UnsupportedOperationException e) {
             // This is the expected exception.
             final String message = e.getMessage();
-            assertTrue(message, message.contains("ContextualParameters"));
+            assertTrue(message, message.contains("ParameterValue"));
         }
     }
 



Mime
View raw message