sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1675677 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-referencing/src/main/java/org/apache/sis/referencing/datum/ sis-referencing/src/main/java/org/apache/sis/referencing/operation/ si...
Date Thu, 23 Apr 2015 16:47:10 GMT
Author: desruisseaux
Date: Thu Apr 23 16:47:09 2015
New Revision: 1675677

URL: http://svn.apache.org/r1675677
Log:
Referencing: Moved internal methods closer to methods doing similar work, and added DefaultConversion.specialize(...)
method.

Removed:
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/OperationMethodsTest.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.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/test/java/org/apache/sis/internal/util/CitationsTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -21,16 +21,10 @@ import org.opengis.util.Record;
 import javax.measure.unit.SI;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
-import org.opengis.metadata.Identifier;
-import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.quality.Result;
 import org.opengis.metadata.quality.PositionalAccuracy;
 import org.opengis.metadata.quality.QuantitativeResult;
 import org.opengis.referencing.operation.*;
-import org.apache.sis.referencing.AbstractIdentifiedObject;
-import org.apache.sis.internal.util.Citations;
-import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.Characters;
 import org.apache.sis.util.Static;
 import org.apache.sis.measure.Units;
 
@@ -63,120 +57,18 @@ public final class OperationMethods exte
     }
 
     /**
-     * Returns the most specific {@link CoordinateOperation} interface implemented by the
specified operation.
-     * Special cases:
-     *
-     * <ul>
-     *   <li>If the operation implements the {@link Transformation} interface,
-     *       then this method returns {@code Transformation.class}. Transformation
-     *       has precedence over any other interface implemented by the operation.</li>
-     *   <li>Otherwise if the operation implements the {@link Conversion} interface,
-     *       then this method returns the most specific {@code Conversion} sub-interface.</li>
-     *   <li>Otherwise if the operation implements the {@link SingleOperation} interface,
-     *       then this method returns {@code SingleOperation.class}.</li>
-     *   <li>Otherwise if the operation implements the {@link ConcatenatedOperation}
interface,
-     *       then this method returns {@code ConcatenatedOperation.class}.</li>
-     *   <li>Otherwise this method returns {@code CoordinateOperation.class}.</li>
-     * </ul>
-     *
-     * @param  operation A coordinate operation.
-     * @return The most specific GeoAPI interface implemented by the given operation.
-     */
-    public static Class<? extends CoordinateOperation> getType(final CoordinateOperation
operation) {
-        if (operation instanceof        Transformation) return        Transformation.class;
-        if (operation instanceof       ConicProjection) return       ConicProjection.class;
-        if (operation instanceof CylindricalProjection) return CylindricalProjection.class;
-        if (operation instanceof      PlanarProjection) return      PlanarProjection.class;
-        if (operation instanceof            Projection) return            Projection.class;
-        if (operation instanceof            Conversion) return            Conversion.class;
-        if (operation instanceof       SingleOperation) return       SingleOperation.class;
-        if (operation instanceof ConcatenatedOperation) return ConcatenatedOperation.class;
-        return CoordinateOperation.class;
-    }
-
-    /**
-     * Determines whether a match or mismatch is found between the two given collections
of identifiers.
-     * If any of the given collections is {@code null} or empty, this method returns {@code
null}.
-     *
-     * <p>According ISO 19162 (<cite>Well known text representation of coordinate
reference systems</cite>),
-     * {@linkplain AbstractIdentifiedObject#getIdentifier() identifiers} should have precedence
over
-     * {@linkplain AbstractIdentifiedObject#getName() name} for identifying {@code IdentifiedObject}s,
-     * at least in the case of {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod
-     * operation methods} and {@linkplain org.apache.sis.parameter.AbstractParameterDescriptor
parameters}.</p>
-     *
-     * @param  id1 The first collection of identifiers, or {@code null}.
-     * @param  id2 The second collection of identifiers, or {@code null}.
-     * @return {@code TRUE} or {@code FALSE} on match or mismatch respectively, or {@code
null} if this method
-     *         can not determine if there is a match or mismatch.
-     */
-    public static Boolean hasCommonIdentifier(final Iterable<? extends Identifier>
id1,
-                                              final Iterable<? extends Identifier>
id2)
-    {
-        if (id1 != null && id2 != null) {
-            boolean hasFound = false;
-            for (final Identifier identifier : id1) {
-                final Citation authority = identifier.getAuthority();
-                final String   codeSpace = identifier.getCodeSpace();
-                for (final Identifier other : id2) {
-                    if (authorityMatches(identifier, authority, codeSpace)) {
-                        if (CharSequences.equalsFiltered(identifier.getCode(), other.getCode(),
Characters.Filter.UNICODE_IDENTIFIER, true)) {
-                            return Boolean.TRUE;
-                        }
-                        hasFound = true;
-                    }
-                }
-            }
-            if (hasFound) {
-                return Boolean.FALSE;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns {@code true} if the given identifier authority matches the given {@code authority}.
-     * If one of the authority is null, then the comparison fallback on the given {@code
codeSpace}.
-     * If the code spaces are also null, then this method conservatively returns {@code false}.
-     *
-     * @param  identifier The identifier to compare.
-     * @param  authority  The desired authority, or {@code null}.
-     * @param  codeSpace  The desired code space or {@code null}, used as a fallback if an
authority is null.
-     * @return {@code true} if the authority or code space (as a fallback only) matches.
-     */
-    private static boolean authorityMatches(final Identifier identifier, final Citation authority,
final String codeSpace) {
-        if (authority != null) {
-            final Citation other = identifier.getAuthority();
-            if (other != null) {
-                return Citations.identifierMatches(authority, other);
-            }
-        }
-        if (codeSpace != null) {
-            final String other = identifier.getCodeSpace();
-            if (other != null) {
-                return CharSequences.equalsFiltered(codeSpace, other, Characters.Filter.UNICODE_IDENTIFIER,
true);
-            }
-        }
-        return false;
-    }
-
-    /**
      * Convenience method returning the accuracy in meters for the specified operation.
      * This method tries each of the following procedures and returns the first successful
one:
      *
      * <ul>
      *   <li>If a {@link QuantitativeResult} is found with a linear unit, then this
accuracy estimate
      *       is converted to {@linkplain SI#METRE metres} and returned.</li>
-     *
      *   <li>Otherwise, if the operation is a {@link Conversion}, then returns 0 since
a conversion
      *       is by definition accurate up to rounding errors.</li>
-     *
      *   <li>Otherwise, if the operation is a {@link Transformation}, then checks if
the datum shift
      *       were applied with the help of Bursa-Wolf parameters. This procedure looks for
SIS-specific
      *       {@link PositionalAccuracyConstant#DATUM_SHIFT_APPLIED} and
-     *       {@link PositionalAccuracyConstant#DATUM_SHIFT_OMITTED DATUM_SHIFT_OMITTED} constants.
-     *       If a datum shift has been applied, returns 25 meters.
-     *       If a datum shift should have been applied but has been omitted, returns 3000
meters.</li>
-     *
+     *       {@link PositionalAccuracyConstant#DATUM_SHIFT_OMITTED DATUM_SHIFT_OMITTED} constants.</li>
      *   <li>Otherwise, if the operation is a {@link ConcatenatedOperation}, returns
the sum of the accuracy
      *       of all components. This is a conservative scenario where we assume that errors
cumulate linearly.
      *       Note that this is not necessarily the "worst case" scenario since the accuracy
could be worst
@@ -224,16 +116,16 @@ public final class OperationMethods exte
         }
         /*
          * If the coordinate operation is actually a transformation, checks if Bursa-Wolf
parameters
-         * were available for the datum shift. This is SIS-specific. See method javadoc for
a rational
+         * were available for the datum shift. This is SIS-specific. See field javadoc for
a rational
          * about the return values chosen.
          */
         if (operation instanceof Transformation) {
             if (!accuracies.contains(PositionalAccuracyConstant.DATUM_SHIFT_OMITTED)) {
                 if (accuracies.contains(PositionalAccuracyConstant.DATUM_SHIFT_APPLIED))
{
-                    return 25;
+                    return PositionalAccuracyConstant.DATUM_SHIFT_ACCURACY;
                 }
             }
-            return 3000;
+            return PositionalAccuracyConstant.UNKNOWN_ACCURACY;
         }
         /*
          * If the coordinate operation is a compound of other coordinate operations, returns
the sum of their accuracy,

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -34,7 +34,7 @@ import org.apache.sis.util.resources.Mes
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.6
  * @module
  *
  * @see org.opengis.referencing.operation.Transformation#getCoordinateOperationAccuracy()
@@ -47,6 +47,28 @@ public final class PositionalAccuracyCon
     private static final long serialVersionUID = -2554090935254116470L;
 
     /**
+     * Presumed worst case error when no datum shift information was found.
+     * The highest value found in the EPSG database 6.7 is 999 metres (worst datum shift),
so this error
+     * should be yet higher. I have seen 3 kilometres mentioned in some documentation somewhere.
+     *
+     * <p>If this value is modified, please update {@code getLinearAccuracy()} public
javadoc accordingly.</p>
+     *
+     * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
+     */
+    public static final double UNKNOWN_ACCURACY = 3000;
+
+    /**
+     * Default accuracy of datum shift, if not explicitly provided in the EPSG database.
+     * The 25 meters value is the next highest value (after 999 metres) found in the EPSG
+     * database version 6.7 for a significant number of transformations.
+     *
+     * <p>If this value is modified, please update {@code getLinearAccuracy()} public
javadoc accordingly.</p>
+     *
+     * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
+     */
+    public static final double DATUM_SHIFT_ACCURACY = 25;
+
+    /**
      * Indicates that a {@linkplain org.opengis.referencing.operation.Transformation transformation}
      * requires a datum shift and some method has been applied. Datum shift methods often
use
      * {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa Wolf parameters},

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -31,8 +31,8 @@ import org.apache.sis.referencing.Abstra
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.internal.util.Citations;
 import org.apache.sis.internal.metadata.MetadataUtilities;
-import org.apache.sis.internal.referencing.OperationMethods;
 
 import static org.apache.sis.util.Utilities.deepEquals;
 import static org.apache.sis.util.collection.Containers.property;
@@ -414,7 +414,7 @@ public class AbstractDatum extends Abstr
                  * and parameters. We extend this rule to datum as well.
                  */
                 final Datum that = (Datum) object;
-                final Boolean match = OperationMethods.hasCommonIdentifier(getIdentifiers(),
that.getIdentifiers());
+                final Boolean match = Citations.hasCommonIdentifier(getIdentifiers(), that.getIdentifiers());
                 if (match != null) {
                     return match;
                 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -75,8 +75,6 @@ class AbstractSingleOperation extends Ab
                                    final MathTransform             transform)
     {
         super(properties, sourceCRS, targetCRS, interpolationCRS, transform);
-        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
-        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
         ArgumentChecks.ensureNonNull("method",    method);
         ArgumentChecks.ensureNonNull("transform", transform);
         checkDimensions(method, transform, properties);
@@ -91,21 +89,6 @@ class AbstractSingleOperation extends Ab
     }
 
     /**
-     * Creates a defining conversion. This is for {@link DefaultConversion} constructor only.
-     */
-    AbstractSingleOperation(final Map<String,?>   properties,
-                            final OperationMethod method,
-                            final MathTransform   transform)
-    {
-        super(properties, null, null, null, transform);
-        ArgumentChecks.ensureNonNull("method",    method);
-        ArgumentChecks.ensureNonNull("transform", transform);
-        checkDimensions(method, transform, properties);
-        this.method = method;
-        parameters = Containers.property(properties, OperationMethods.PARAMETERS_KEY, ParameterValueGroup.class);
-    }
-
-    /**
      * Constructs a new operation with the same values than the specified one, together with
the
      * specified source and target CRS. While the source operation can be an arbitrary one,
it is
      * typically a defining conversion.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -21,6 +21,7 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.util.ArgumentChecks;
 
 
 /**
@@ -39,7 +40,7 @@ import org.opengis.referencing.crs.Coord
  * and {@linkplain #getTargetCRS() target CRS}. But {@code Conversion} instances without
those information may exist
  * temporarily while creating a {@linkplain org.apache.sis.referencing.crs.DefaultDerivedCRS
derived} or
  * {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS projected CRS}.
- * Those <cite>defining conversions</cite> have no source and target CRS since
those elements are created by the
+ * Those <cite>defining conversions</cite> have no source and target CRS since
those elements are provided by the
  * derived or projected CRS themselves. This class provides a {@linkplain #DefaultConversion(Map,
OperationMethod,
  * MathTransform) constructor} for such defining conversions.
  *
@@ -109,17 +110,19 @@ public class DefaultConversion extends A
                              final MathTransform             transform)
     {
         super(properties, sourceCRS, targetCRS, interpolationCRS, method, transform);
+        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
     }
 
     /**
      * Creates a defining conversion from the given transform.
-     * This conversion has no source and target CRS since those elements will be created
by the
+     * This conversion has no source and target CRS since those elements will be provided
by the
      * {@linkplain org.apache.sis.referencing.crs.DefaultDerivedCRS derived} or
      * {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS projected CRS}.
      *
      * <p>The properties given in argument follow the same rules than for the
-     * {@linkplain AbstractCoordinateOperation#AbstractCoordinateOperation(Map, CoordinateReferenceSystem,
-     * CoordinateReferenceSystem, CoordinateReferenceSystem, MathTransform) super-class constructor}.</p>
+     * {@linkplain #DefaultConversion(Map, CoordinateReferenceSystem, CoordinateReferenceSystem,
+     * CoordinateReferenceSystem, OperationMethod, MathTransform) above constructor}.</p>
      *
      * @param properties The properties to be given to the identified object.
      * @param method     The operation method.
@@ -129,7 +132,7 @@ public class DefaultConversion extends A
                              final OperationMethod method,
                              final MathTransform   transform)
     {
-        super(properties, method, transform);
+        super(properties, null, null, null, method, transform);
     }
 
     /**
@@ -205,4 +208,41 @@ public class DefaultConversion extends A
     public Class<? extends Conversion> getInterface() {
         return Conversion.class;
     }
+
+    /**
+     * Returns a specialization of this conversion with a more specific type, source and
target CRS.
+     * This {@code specialize(…)} method is typically invoked on {@linkplain #DefaultConversion(Map,
+     * OperationMethod, MathTransform) defining conversion} instances, when more information
become
+     * available about the conversion to create.
+     *
+     * <p>The given {@code baseType} argument can be one of the following values:</p>
+     * <ul>
+     *   <li><code>{@linkplain org.opengis.referencing.operation.Conversion}.class</code></li>
+     *   <li><code>{@linkplain org.opengis.referencing.operation.Projection}.class</code></li>
+     *   <li><code>{@linkplain org.opengis.referencing.operation.CylindricalProjection}.class</code></li>
+     *   <li><code>{@linkplain org.opengis.referencing.operation.ConicProjection}.class</code></li>
+     *   <li><code>{@linkplain org.opengis.referencing.operation.PlanarProjection}.class</code></li>
+     * </ul>
+     *
+     * This {@code specialize(…)} method returns a conversion which implement at least
the given {@code baseType}
+     * interface, but may also implement a more specific GeoAPI interface if {@code specialize(…)}
has been able
+     * to infer the type from this operation {@linkplain #getMethod() method}.
+     *
+     * @param  <T>        Compile-time type of the {@code baseType} argument.
+     * @param  baseType   The base GeoAPI interface to be implemented by the conversion to
return.
+     * @param  sourceCRS  The source CRS.
+     * @param  targetCRS  The target CRS.
+     * @return The conversion of the given type between the given CRS.
+     * @throws ClassCastException if a contradiction is found between the given {@code baseType},
+     *         the defining {@linkplain DefaultConversion#getInterface() conversion type}
and
+     *         the {@linkplain DefaultOperationMethod#getOperationType() method operation
type}.
+     */
+    public <T extends Conversion> T specialize(final Class<T> baseType,
+            final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS)
+    {
+        ArgumentChecks.ensureNonNull("baseType",  baseType);
+        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
+        return SubTypes.create(baseType, this, sourceCRS, targetCRS);
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -32,11 +32,11 @@ import org.apache.sis.util.Workaround;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.internal.util.Citations;
 import org.apache.sis.parameter.Parameterized;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.AbstractIdentifiedObject;
-import org.apache.sis.internal.referencing.OperationMethods;
 import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.ArgumentChecks.*;
@@ -600,7 +600,7 @@ public class DefaultOperationMethod exte
                      * and parameters.
                      */
                     final OperationMethod that = (OperationMethod) object;
-                    final Boolean match = OperationMethods.hasCommonIdentifier(getIdentifiers(),
that.getIdentifiers());
+                    final Boolean match = Citations.hasCommonIdentifier(getIdentifiers(),
that.getIdentifiers());
                     if (match != null) {
                         if (!match) {
                             return false;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultTransformation.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -21,6 +21,7 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.util.ArgumentChecks;
 
 
 /**
@@ -108,6 +109,8 @@ public class DefaultTransformation exten
                                  final MathTransform             transform)
     {
         super(properties, sourceCRS, targetCRS, interpolationCRS, method, transform);
+        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -17,6 +17,8 @@
 package org.apache.sis.referencing.operation;
 
 import org.opengis.referencing.operation.*;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.AbstractIdentifiedObject;
 
 
 /**
@@ -27,6 +29,8 @@ import org.opengis.referencing.operation
  * <p>This class currently provides implementation for the following methods:</p>
  * <ul>
  *   <li>{@link AbstractCoordinateOperation#castOrCopy(CoordinateOperation)}</li>
+ *   <li>{@link DefaultConversion#castOrCopy(Conversion)}</li>
+ *   <li>{@link DefaultConversion#specialize(Class, CoordinateReferenceSystem, CoordinateReferenceSystem)}</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
@@ -96,4 +100,53 @@ final class SubTypes {
         }
         return new DefaultConversion(object);
     }
+
+    /**
+     * Returns a conversion from the specified defining conversion.
+     * The new conversion will be a more specific type like a {@linkplain PlanarProjection
planar},
+     * {@linkplain CylindricalProjection cylindrical} or {@linkplain ConicProjection conic
projection}.
+     * The returned conversion will implement at least the {@code baseType} interface, but
may implement
+     * a more specific GeoAPI interface if this method has been able to infer the type from
the
+     * {@code conversion} argument.
+     *
+     * @param  baseType   The base GeoAPI interface to be implemented by the conversion to
return.
+     * @param  definition The defining conversion.
+     * @param  sourceCRS  The source CRS.
+     * @param  targetCRS  The target CRS.
+     * @return The conversion of the given type between the given CRS.
+     * @throws ClassCastException if a contradiction is found between the given {@code baseType},
+     *         the defining {@linkplain DefaultConversion#getInterface() conversion type}
and
+     *         the {@linkplain DefaultOperationMethod#getOperationType() method operation
type}.
+     */
+    static <T extends Conversion> T create(final Class<T> baseType, final Conversion
definition,
+            final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS)
+    {
+        Class<? extends T> type = baseType;
+        if (definition instanceof AbstractIdentifiedObject) {
+            final Class<?> c = ((AbstractIdentifiedObject) definition).getInterface();
+            if (!c.isAssignableFrom(baseType)) {  // Do nothing if c is a parent type.
+                type = c.asSubclass(type);
+            }
+        }
+        final OperationMethod method = definition.getMethod();
+        if (method instanceof DefaultOperationMethod) {
+            final Class<? extends SingleOperation> c = ((DefaultOperationMethod) method).getOperationType();
+            if (!c.isAssignableFrom(baseType)) {  // Do nothing if c is a parent type.
+                type = c.asSubclass(type);
+            }
+        }
+        final Conversion conversion;
+        if (CylindricalProjection.class.isAssignableFrom(type)) {
+            conversion = new DefaultCylindricalProjection(definition, sourceCRS, targetCRS);
+        } else if (ConicProjection.class.isAssignableFrom(type)) {
+            conversion = new DefaultConicProjection(definition, sourceCRS, targetCRS);
+        } else if (PlanarProjection.class.isAssignableFrom(type)) {
+            conversion = new DefaultPlanarProjection(definition, sourceCRS, targetCRS);
+        } else if (Projection.class.isAssignableFrom(type)) {
+            conversion = new DefaultProjection(definition, sourceCRS, targetCRS);
+        } else {
+            conversion = new DefaultConversion(definition, sourceCRS, targetCRS);
+        }
+        return type.cast(conversion);
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -92,7 +92,6 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.operation.DefaultOperationMethodTest.class,
     org.apache.sis.referencing.operation.AbstractSingleOperationTest.class,
     org.apache.sis.referencing.operation.transform.OperationMethodSetTest.class,
-    org.apache.sis.internal.referencing.OperationMethodsTest.class,
     org.apache.sis.internal.referencing.provider.AffineTest.class,
     org.apache.sis.internal.referencing.provider.LongitudeRotationTest.class,
     org.apache.sis.internal.referencing.provider.MapProjectionTest.class,

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -23,6 +23,8 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.util.InternationalString;
 import org.apache.sis.xml.IdentifierSpace;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Characters;
 import org.apache.sis.util.Static;
 
 import static org.apache.sis.util.CharSequences.equalsFiltered;
@@ -230,6 +232,71 @@ public final class Citations extends Sta
     }
 
     /**
+     * Returns {@code true} if the given identifier authority matches the given {@code authority}.
+     * If one of the authority is null, then the comparison fallback on the given {@code
codeSpace}.
+     * If the code spaces are also null, then this method conservatively returns {@code false}.
+     *
+     * @param  identifier The identifier to compare.
+     * @param  authority  The desired authority, or {@code null}.
+     * @param  codeSpace  The desired code space or {@code null}, used as a fallback if an
authority is null.
+     * @return {@code true} if the authority or code space (as a fallback only) matches.
+     */
+    private static boolean authorityMatches(final Identifier identifier, final Citation authority,
final String codeSpace) {
+        if (authority != null) {
+            final Citation other = identifier.getAuthority();
+            if (other != null) {
+                return identifierMatches(authority, other);
+            }
+        }
+        if (codeSpace != null) {
+            final String other = identifier.getCodeSpace();
+            if (other != null) {
+                return CharSequences.equalsFiltered(codeSpace, other, Characters.Filter.UNICODE_IDENTIFIER,
true);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Determines whether a match or mismatch is found between the two given collections
of identifiers.
+     * If any of the given collections is {@code null} or empty, then this method returns
{@code null}.
+     *
+     * <p>According ISO 19162 (<cite>Well known text representation of coordinate
reference systems</cite>),
+     * {@linkplain org.apache.sis.referencing.AbstractIdentifiedObject#getIdentifiers() identifiers}
should have precedence over
+     * {@linkplain org.apache.sis.referencing.AbstractIdentifiedObject#getName() name} for
identifying {@code IdentifiedObject}s,
+     * at least in the case of {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod
operation methods} and
+     * {@linkplain org.apache.sis.parameter.AbstractParameterDescriptor parameters}.</p>
+     *
+     * @param  id1 The first collection of identifiers, or {@code null}.
+     * @param  id2 The second collection of identifiers, or {@code null}.
+     * @return {@code TRUE} or {@code FALSE} on match or mismatch respectively, or {@code
null} if this method
+     *         can not determine if there is a match or mismatch.
+     */
+    public static Boolean hasCommonIdentifier(final Iterable<? extends Identifier>
id1,
+                                              final Iterable<? extends Identifier>
id2)
+    {
+        if (id1 != null && id2 != null) {
+            boolean hasFound = false;
+            for (final Identifier identifier : id1) {
+                final Citation authority = identifier.getAuthority();
+                final String   codeSpace = identifier.getCodeSpace();
+                for (final Identifier other : id2) {
+                    if (authorityMatches(identifier, authority, codeSpace)) {
+                        if (CharSequences.equalsFiltered(identifier.getCode(), other.getCode(),
Characters.Filter.UNICODE_IDENTIFIER, true)) {
+                            return Boolean.TRUE;
+                        }
+                        hasFound = true;
+                    }
+                }
+            }
+            if (hasFound) {
+                return Boolean.FALSE;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Infers an identifier from the given citation, or returns {@code null} if no identifier
has been found.
      * This method removes leading and trailing {@linkplain Character#isWhitespace(int) whitespaces}.
      * See {@link org.apache.sis.metadata.iso.citation.Citations#getIdentifier(Citation)}

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationsTest.java?rev=1675677&r1=1675676&r2=1675677&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationsTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationsTest.java
[UTF-8] Thu Apr 23 16:47:09 2015
@@ -16,8 +16,12 @@
  */
 package org.apache.sis.internal.util;
 
+import java.util.List;
+import java.util.ArrayList;
+import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.internal.simple.SimpleCitation;
+import org.apache.sis.internal.simple.SimpleIdentifier;
 import org.apache.sis.xml.IdentifierSpace;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
@@ -36,6 +40,48 @@ import static org.junit.Assert.*;
  */
 public final strictfp class CitationsTest extends TestCase {
     /**
+     * Creates an identifier with a code space.
+     */
+     @SuppressWarnings("serial")
+     private static Identifier identifier(final String codeSpace, final String code) {
+        return new SimpleIdentifier(null, code) {
+            @Override public String getCodeSpace() {
+                return codeSpace;
+            }
+        };
+    }
+
+    /**
+     * Tests {@link Citations#hasCommonIdentifier(Iterable, Iterable)}.
+     */
+    @Test
+    public void testHasCommonIdentifier() {
+        final List<Identifier> id1 = new ArrayList<>(3);
+        final List<Identifier> id2 = new ArrayList<>(2);
+        assertNull(Citations.hasCommonIdentifier(id1, id2));
+        /*
+         * Add codes for two Operation Methods which are implemented in Apache SIS by the
same class:
+         *
+         *  - EPSG:9804  —  "Mercator (variant A)" (formerly known as "Mercator (1SP)").
+         *  - EPSG:1026  —  "Mercator (Spherical)"
+         *  - GeoTIFF:7  —  "CT_Mercator"
+         */
+        id1.add(identifier("EPSG", "9804"));
+        id1.add(identifier("EPSG", "1026"));
+        id1.add(identifier("GeoTIFF", "7"));
+        assertNull(Citations.hasCommonIdentifier(id1, id2));
+        /*
+         * EPSG:9841 is a legacy (now deprecated) code for "Mercator (1SP)".
+         * We could have declared it as a deprecated code in the above list,
+         * but for the sake of this test we do not.
+         */
+        id2.add(identifier("EPSG", "9841"));
+        assertEquals(Boolean.FALSE, Citations.hasCommonIdentifier(id1, id2));
+        id2.add(identifier("EPSG", "9804"));
+        assertEquals(Boolean.TRUE, Citations.hasCommonIdentifier(id1, id2));
+    }
+
+    /**
      * Tests {@link Citations#getIdentifier(Citation, boolean)}.
      */
     @Test



Mime
View raw message