sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1726918 [1/2] - in /sis/branches/JDK7: ./ core/sis-metadata/src/main/java/org/apache/sis/io/wkt/ core/sis-referencing/src/main/java/org/apache/sis/referencing/ core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ core/sis...
Date Tue, 26 Jan 2016 22:54:17 GMT
Author: desruisseaux
Date: Tue Jan 26 22:54:16 2016
New Revision: 1726918

URL: http://svn.apache.org/viewvc?rev=1726918&view=rev
Log:
Merge MultiAuthoritiesFactory completion from the JDK8 branch.

Added:
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
      - copied unchanged from r1726916, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
Modified:
    sis/branches/JDK7/   (props changed)
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Transliterator.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties

Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jan 26 22:54:16 2016
@@ -1,4 +1,4 @@
 /sis/branches/Android:1430670-1480699
 /sis/branches/JDK6:1394913-1508480
-/sis/branches/JDK8:1584960-1726714
+/sis/branches/JDK8:1584960-1726916
 /sis/trunk:1394364-1508466,1519089-1519674

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Transliterator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Transliterator.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Transliterator.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Transliterator.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -328,41 +328,46 @@ public abstract class Transliterator imp
      * @see org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis#formatTo(Formatter)
      */
     public String toLatinAbbreviation(final CoordinateSystem cs, final AxisDirection direction, String abbreviation) {
-        if (abbreviation != null && !abbreviation.isEmpty() && abbreviation.length() <= 2) {
-            switch (abbreviation.charAt(0)) {
-                /*
-                 * ISO 19162:2015 §7.5.3 recommendations:
-                 *
-                 *   a) For PolarCS using Greek letter θ for direction, the letter ‘U’ should be used in WKT.
-                 *   b) For SphericalCS using φ and θ, the letter ‘U’ and ‘V’ respectively should be used in WKT.
-                 */
-                case 'θ': {
-                    if  (cs instanceof SphericalCS) abbreviation ="V";
-                    else if (cs instanceof PolarCS) abbreviation ="U";
-                    break;
-                }
-                /*
-                 * ISO 19162:2015 §7.5.3 requirement (ii) and recommendation (b):
-                 *
-                 *  ii) Greek letters φ and λ for geodetic latitude and longitude must be replaced by Latin char.
-                 *   b) For SphericalCS using φ and θ, the letter ‘U’ and ‘V’ respectively should be used in WKT.
-                 *
-                 * Note that some SphericalCS may use φ′ or φc for distinguishing from geodetic latitude φ.
-                 */
-                case 'φ': {
-                    if (cs instanceof SphericalCS) {
-                        abbreviation = "U";
-                    } else if (cs instanceof EllipsoidalCS) {
-                        abbreviation = "B";    // From German "Breite", used in academic texts worldwide.
+        if (abbreviation != null && !abbreviation.isEmpty()) {
+            if (abbreviation.length() <= 2) {
+                switch (abbreviation.charAt(0)) {
+                    /*
+                     * ISO 19162:2015 §7.5.3 recommendations:
+                     *
+                     *   a) For PolarCS using Greek letter θ for direction, the letter ‘U’ should be used in WKT.
+                     *   b) For SphericalCS using φ and θ, the letter ‘U’ and ‘V’ respectively should be used in WKT.
+                     */
+                    case 'θ': {
+                        if  (cs instanceof SphericalCS) abbreviation ="V";
+                        else if (cs instanceof PolarCS) abbreviation ="U";
+                        break;
                     }
-                    break;
-                }
-                case 'λ': {
-                    if (cs instanceof EllipsoidalCS) {
-                        abbreviation = "L";    // From German "Länge", used in academic texts worldwide.
+                    /*
+                     * ISO 19162:2015 §7.5.3 requirement (ii) and recommendation (b):
+                     *
+                     *  ii) Greek letters φ and λ for geodetic latitude and longitude must be replaced by Latin char.
+                     *   b) For SphericalCS using φ and θ, the letter ‘U’ and ‘V’ respectively should be used in WKT.
+                     *
+                     * Note that some SphericalCS may use φ′ or φc for distinguishing from geodetic latitude φ.
+                     */
+                    case 'φ': {
+                        if (cs instanceof SphericalCS) {
+                            abbreviation = "U";
+                        } else if (cs instanceof EllipsoidalCS) {
+                            abbreviation = "B";    // From German "Breite", used in academic texts worldwide.
+                        }
+                        break;
+                    }
+                    case 'λ': {
+                        if (cs instanceof EllipsoidalCS) {
+                            abbreviation = "L";    // From German "Länge", used in academic texts worldwide.
+                        }
+                        break;
                     }
-                    break;
                 }
+            } else {
+                if      (abbreviation.equalsIgnoreCase("Lat" )) abbreviation = "B";
+                else if (abbreviation.equalsIgnoreCase("Long")) abbreviation = "L";
             }
         }
         return abbreviation;

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -62,11 +62,13 @@ final class AuthorityFactories<T extends
             new AuthorityFactories<>(DatumAuthorityFactory.class),
             new AuthorityFactories<>(CoordinateOperationAuthorityFactory.class))
     {
+        /** Anonymous constructor */ {
+            setLenient(true);
+        }
+
         @Override
         public void reload() {
-            synchronized (EPSG) {
-                EPSG[0] = null;
-            }
+            EPSG(null);
             super.reload();
         }
     };
@@ -89,6 +91,15 @@ final class AuthorityFactories<T extends
     }
 
     /**
+     * Sets the EPSG factory to the given value.
+     */
+    static void EPSG(final AuthorityFactory factory) {
+        synchronized (EPSG) {
+            EPSG[0] = factory;
+        }
+    }
+
+    /**
      * Returns the EPSG factory.
      */
     static AuthorityFactory EPSG() {

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -23,6 +23,7 @@ import java.util.Collections;
 import javax.measure.unit.NonSI;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystem;
@@ -38,6 +39,7 @@ import org.opengis.referencing.crs.Proje
 import org.opengis.referencing.crs.TemporalCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.EngineeringCRS;
+import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.apache.sis.internal.metadata.AxisDirections;
@@ -123,15 +125,21 @@ public final class CRS extends Static {
      * This method accepts also the URN and URL syntax.
      * For example the following codes are considered equivalent to {@code "EPSG:4326"}:
      * <ul>
+     *   <li>{@code "EPSG::4326"}</li>
      *   <li>{@code "urn:ogc:def:crs:EPSG::4326"}</li>
+     *   <li>{@code "http://www.opengis.net/def/crs/epsg/0/4326"}</li>
      *   <li>{@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}</li>
      * </ul>
      *
+     * The {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)} method can be seen
+     * as a converse of this method.
+     *
      * @param  code The authority code.
      * @return The Coordinate Reference System for the given authority code.
      * @throws NoSuchAuthorityCodeException If there is no known CRS associated to the given code.
      * @throws FactoryException if the CRS creation failed for an other reason.
      *
+     * @see #getAuthorityFactory()
      * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory
      *
      * @category factory
@@ -541,4 +549,34 @@ check:  while (lower != 0 || upper != di
         ArgumentChecks.ensureNonNull("crs", crs);
         return ReferencingUtilities.getGreenwichLongitude(crs.getDatum().getPrimeMeridian(), NonSI.DEGREE_ANGLE);
     }
+
+    /**
+     * Returns the system-wide authority factory used by {@link #forCode(String)} and other SIS methods.
+     * By default, this method returns an instance of {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
+     * capable to process at least some EPSG and WMS codes. The set of EPSG codes that are guaranteed to be supported
+     * is listed in the {@link #forCode(String)} method javadoc.
+     * Other authorities may also be supported if their factories are declared in the following file:
+     *
+     * {@preformat text
+     *     META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
+     * }
+     *
+     * <div class="section">Factories of other kinds</div>
+     * By default the returned factory can also be used as
+     * {@link org.opengis.referencing.cs.CSAuthorityFactory},
+     * {@link org.opengis.referencing.datum.DatumAuthorityFactory} or
+     * {@link org.opengis.referencing.operation.CoordinateOperationAuthorityFactory}.
+     * However callers are encouraged to verify the type before to cast
+     * since a future SIS version may allow users to set a custom factory.
+     *
+     * @return The system-wide authority factory used by SIS.
+     *
+     * @see #forCode(String)
+     * @see org.apache.sis.referencing.factory.MultiAuthoritiesFactory
+     *
+     * @since 0.7
+     */
+    public static CRSAuthorityFactory getAuthorityFactory() {
+        return AuthorityFactories.ALL;
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -52,7 +52,13 @@ final class EPSGFactoryFallback extends
      * This field should always be {@code false}, except for debugging purposes.
      */
     @Debug
-    static final boolean FORCE_HARDCODED = true;
+    static final boolean FORCE_HARDCODED = false;
+
+    /**
+     * A temporary flag for tests that need to be revisited after the upgrade to the next EPSG database version.
+     */
+    @Debug
+    static final boolean PENDING_NEXT_EPSG = false;
 
     /**
      * The singleton instance.

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -24,6 +24,7 @@ import java.util.Collection;
 
 import org.opengis.util.NameSpace;
 import org.opengis.util.GenericName;
+import org.opengis.util.FactoryException;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;
@@ -31,11 +32,15 @@ import org.opengis.referencing.operation
 
 import org.apache.sis.util.Static;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.iso.DefaultNameSpace;
-import org.apache.sis.metadata.iso.citation.Citations; // For javadoc.
+import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.metadata.NameMeaning;
 import org.apache.sis.internal.metadata.NameToIdentifier;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
 
-import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
 import static org.apache.sis.internal.util.Citations.iterator;
 import static org.apache.sis.internal.util.Citations.identifierMatches;
 
@@ -46,7 +51,7 @@ import static org.apache.sis.internal.ut
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Guilhem Legal (Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see CRS
@@ -99,8 +104,8 @@ public final class IdentifiedObjects ext
      * @return An view of the identified object as an immutable map.
      */
     public static Map<String,?> getProperties(final IdentifiedObject object, final String... excludes) {
-        ensureNonNull("object", object);
-        ensureNonNull("excludes", excludes);
+        ArgumentChecks.ensureNonNull("object", object);
+        ArgumentChecks.ensureNonNull("excludes", excludes);
         return new Properties(object, excludes);
     }
 
@@ -366,6 +371,142 @@ public final class IdentifiedObjects ext
     }
 
     /**
+     * Looks up a URN, such as {@code "urn:ogc:def:crs:EPSG:8.2:4326"}, of the specified object.
+     * This method searches in all {@linkplain org.apache.sis.referencing.factory.GeodeticAuthorityFactory geodetic
+     * authority factories} known to SIS for an object {@linkplain org.apache.sis.util.ComparisonMode#APPROXIMATIVE
+     * approximatively equals} to the specified object. If such an object is found, then the URN for the given
+     * authority is returned. Otherwise or if there is ambiguity, this method returns {@code null}.
+     *
+     * <p><strong>Note that this method checks the identifier validity.</strong>
+     * If the given object declares explicitly an identifier, then this method will instantiate an object from the
+     * authority factory using that identifier and compare it with the given object. If the comparison fails, then
+     * this method returns {@code null}. Consequently this method may return {@code null} even if the given object
+     * declares explicitly its identifier. If the declared identifier is wanted unconditionally, use the following
+     * pattern instead:
+     *
+     * {@preformat java
+     *     String urn = toURN(object.getClass(), getIdentifier(object, authority));
+     * }
+     *
+     * This method can be seen as a converse of {@link CRS#forCode(String)}.
+     *
+     * @param  object The object (usually a {@linkplain org.apache.sis.referencing.crs.AbstractCRS
+     *         coordinate reference system}) whose identifier is to be found, or {@code null}.
+     * @param  authority The authority for the identifier to return, or {@code null} for
+     *         the first identifier regardless its authority.
+     * @return The identifier, or {@code null} if none was found without ambiguity or if the given object was null.
+     * @throws FactoryException if an error occurred during the search.
+     *
+     * @see #newFinder()
+     * @see #toURN(Class, Identifier)
+     *
+     * @since 0.7
+     */
+    public static String lookupURN(final IdentifiedObject object, final Citation authority) throws FactoryException {
+        String urn = null;
+        if (object != null) {
+            for (final IdentifiedObject candidate : newFinder().find(object)) {
+                final String c = toURN(candidate.getClass(), getIdentifier(candidate, authority));
+                if (c != null) {
+                    if (urn != null && !urn.equals(c)) {
+                        return null;
+                    }
+                    urn = c;
+                }
+            }
+        }
+        return urn;
+    }
+
+    /**
+     * Looks up an EPSG code, such as {@code 4326}, of the specified object. This method searches in EPSG factories
+     * known to SIS for an object {@linkplain org.apache.sis.util.ComparisonMode#APPROXIMATIVE approximatively equals}
+     * to the specified object. If such an object is found, then its EPSG identifier is returned.
+     * Otherwise or if there is ambiguity, this method returns {@code null}.
+     *
+     * <p><strong>Note that this method checks the identifier validity.</strong>
+     * If the given object declares explicitly an identifier, then this method will instantiate an object from the
+     * EPSG factory using that identifier and compare it with the given object. If the comparison fails, then this
+     * method returns {@code null}. Consequently this method may return {@code null} even if the given object
+     * declares explicitly its identifier. If the declared identifier is wanted unconditionally, use the following
+     * pattern instead:
+     *
+     * {@preformat java
+     *     String code = toString(getIdentifier(object, Citations.EPSG));
+     * }
+     *
+     * This method can be seen as a converse of {@link CRS#forCode(String)}.
+     *
+     * @param  object The object (usually a {@linkplain org.apache.sis.referencing.crs.AbstractCRS
+     *         coordinate reference system}) whose EPSG code is to be found, or {@code null}.
+     * @return The EPSG code, or {@code null} if none was found without ambiguity or if the given object was null.
+     * @throws FactoryException if an error occurred during the search.
+     *
+     * @see #newFinder()
+     *
+     * @since 0.7
+     */
+    public static Integer lookupEPSG(final IdentifiedObject object) throws FactoryException {
+        Integer code = null;
+        if (object != null) {
+            for (final IdentifiedObject candidate : newFinder().find(object)) {
+                final Identifier id = getIdentifier(candidate, Citations.EPSG);
+                if (id != null) try {
+                    Integer previous = code;
+                    code = Integer.valueOf(id.getCode());
+                    if (previous != null && !previous.equals(code)) {
+                        return null;
+                    }
+                } catch (NumberFormatException e) {
+                    Logging.recoverableException(Logging.getLogger(Loggers.CRS_FACTORY), IdentifiedObjects.class, "lookupEPSG", e);
+                }
+            }
+        }
+        return code;
+    }
+
+    /**
+     * Creates a finder which can be used for looking up unidentified objects.
+     * This method is an alternative to {@code lookup(…)} methods when more control are desired.
+     *
+     * <div class="note"><b>Example 1: be lenient regarding axis order</b><br>
+     * By default, {@code lookup(…)} methods require that objects in the dataset have their axes in the
+     * same order than the given object. For relaxing this condition, one can use the following Java code:
+     *
+     * {@preformat java
+     *     IdentifiedObjectFinder finder = IdentifiedObjects.newFinder();
+     *     finder.setIgnoringAxes(true);
+     *     IdentifiedObject found = finder.findSingleton(object);
+     * }
+     *
+     * This example assumes that at most one object from the dataset will match the given object.
+     * If more than one object may match, then the call to {@code findSingleton(…)} should be replaced
+     * by {@code find(…)}.</div>
+     *
+     * <div class="note"><b>Example 2: extend the search to deprecated definitions</b><br>
+     * By default, {@code lookup(…)} methods exclude deprecated objects from the search.
+     * To search also among deprecated objects, one can use the following Java code:
+     *
+     * {@preformat java
+     *     IdentifiedObjectFinder finder = IdentifiedObjects.newFinder();
+     *     finder.setSearchDomain(IdentifiedObjectFinder.Domain.ALL_DATASET);
+     *     Set<IdentifiedObject> found = finder.find(object);
+     * }
+     *
+     * This example does not use the {@code findSingleton(…)} convenience method on the assumption
+     * that the search may find both deprecated and non-deprecated objects.</div>
+     *
+     * @return A finder to use for looking up unidentified objects.
+     * @throws FactoryException if the finder can not be created.
+     *
+     * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#newIdentifiedObjectFinder()
+     * @see IdentifiedObjectFinder#find(IdentifiedObject)
+     */
+    public static IdentifiedObjectFinder newFinder() throws FactoryException {
+        return AuthorityFactories.ALL.newIdentifiedObjectFinder();
+    }
+
+    /**
      * Returns {@code true} if either the {@linkplain AbstractIdentifiedObject#getName() primary name} or at least
      * one {@linkplain AbstractIdentifiedObject#getAlias() alias} matches the given string according heuristic rules.
      * If the given object is an instance of {@link AbstractIdentifiedObject}, then this method delegates to its
@@ -404,12 +545,68 @@ public final class IdentifiedObjects ext
             // We really need to delegate to the overridden method.
             return ((AbstractIdentifiedObject) object).isHeuristicMatchForName(name);
         } else {
-            ensureNonNull("object", object);
+            ArgumentChecks.ensureNonNull("object", object);
             return NameToIdentifier.isHeuristicMatchForName(object.getName(), object.getAlias(), name);
         }
     }
 
     /**
+     * Returns the URN of the given identifier, or {@code null} if no valid URN can be formed.
+     * The given type should be assignable to one of the given types:
+     *
+     * <table class="sis">
+     *   <caption>Recognized object types in URN</caption>
+     *   <tr><th>Interface</th>                                                     <th>Type in URN</th>         <th>Meaning</th></tr>
+     *   <tr><td>{@link org.opengis.referencing.cs.CoordinateSystemAxis}</td>       <td>axis</td>                <td>Coordinate system axe definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.operation.CoordinateOperation}</td> <td>coordinateOperation</td> <td>Coordinate operation definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.crs.CoordinateReferenceSystem}</td> <td>crs</td>                 <td>Coordinate reference system definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.cs.CoordinateSystem}</td>           <td>cs</td>                  <td>Coordinate system definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.datum.Datum}</td>                   <td>datum</td>               <td>Datum definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.datum.Ellipsoid}</td>               <td>ellipsoid</td>           <td>Ellipsoid definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.datum.PrimeMeridian}</td>           <td>meridian</td>            <td>Prime meridian definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.operation.OperationMethod}</td>     <td>method</td>              <td>Operation method definition</td></tr>
+     *   <tr><td>{@link org.opengis.parameter.ParameterDescriptor}</td>             <td>parameter</td>           <td>Operation parameter definition</td></tr>
+     *   <tr><td>{@link org.opengis.referencing.ReferenceSystem}</td>               <td>referenceSystem</td>     <td>Value reference system definition</td></tr>
+     *   <tr><td>{@link javax.measure.unit.Unit}</td>                               <td>uom</td>                 <td>Unit of measure definition</td></tr>
+     * </table>
+     *
+     * In addition, the identifier codespace shall be one of the following authorities:
+     *
+     * <table class="sis">
+     *   <caption>Recognized authorities in URN</caption>
+     *   <tr><th>Namespace</th> <th>Authority</th>         <th>Description</th></tr>
+     *   <tr><td>OGC</td>       <td>{@code "EPSG"}</td>    <td>EPSG dataset</td></tr>
+     *   <tr><td>OGC</td>       <td>{@code "OGC"}</td>     <td>Open Geospatial Consortium</td></tr>
+     *   <tr><td>OGC</td>       <td>{@code "OGC-WFS"}</td> <td>OGC Web Feature Service</td></tr>
+     *   <tr><td>OGC</td>       <td>{@code "SI"}</td>      <td>Système International d'Unités</td></tr>
+     *   <tr><td>OGC</td>       <td>{@code "UCUM"}</td>    <td>Unified Code for Units of Measure</td></tr>
+     *   <tr><td>OGC</td>       <td>{@code "UNSD"}</td>    <td>United Nations Statistics Division</td></tr>
+     *   <tr><td>OGC</td>       <td>{@code "USNO"}</td>    <td>United States Naval Observatory</td></tr>
+     * </table>
+     *
+     * The reason why the authorities are restricted to the above white list is because this method formats a URN
+     * in the OGC namespace. Consequently the URN should use only components recognized by the OGC Naming Authority.
+     *
+     * <p>The above tables may be expanded in any future SIS version.</p>
+     *
+     * @param  type A type assignable to one of the types listed in above table.
+     * @param  identifier The identifier for which to format a URN, or {@code null}.
+     * @return The URN for the given identifier, or {@code null} if the given identifier was null
+     *         or can not be formatted by this method.
+     *
+     * @see #lookupURN(IdentifiedObject, Citation)
+     *
+     * @since 0.7
+     */
+    public static String toURN(final Class<?> type, final Identifier identifier) {
+        ArgumentChecks.ensureNonNull("type", type);
+        if (identifier == null) {
+            return null;
+        }
+        return NameMeaning.toURN(type, identifier.getCodeSpace(), identifier.getVersion(), identifier.getCode());
+    }
+
+    /**
      * Returns a string representation of the given identifier.
      * This method applies the following rules:
      *

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -64,6 +64,7 @@ import org.apache.sis.measure.Latitude;
 import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
 import static org.opengis.referencing.IdentifiedObject.ALIAS_KEY;
 import static org.opengis.referencing.IdentifiedObject.IDENTIFIERS_KEY;
+import static org.opengis.referencing.crs.GeographicCRS.SCOPE_KEY;
 import static org.opengis.referencing.datum.Datum.DOMAIN_OF_VALIDITY_KEY;
 import static org.apache.sis.internal.metadata.ReferencingServices.AUTHALIC_RADIUS;
 
@@ -163,9 +164,10 @@ final class StandardDefinitions {
     static GeographicCRS createGeographicCRS(final short code, final GeodeticDatum datum, final EllipsoidalCS cs) {
         final String name;
         String alias = null;
+        String scope = null;
         boolean world = false;
         switch (code) {
-            case 4326: name = "WGS 84"; world = true; break;
+            case 4326: name = "WGS 84"; world = true; scope = "Horizontal component of 3D system."; break;
             case 4322: name = "WGS 72"; world = true; break;
             case 4258: name = "ETRS89"; alias = "ETRS89-GRS80"; break;
             case 4269: name = "NAD83";  break;
@@ -174,7 +176,9 @@ final class StandardDefinitions {
             case 4047: name = "Unspecified datum based upon the GRS 1980 Authalic Sphere"; world = true; break;
             default:   throw new AssertionError(code);
         }
-        return new DefaultGeographicCRS(properties(code, name, alias, world), datum, cs);
+        final Map<String, Object> properties = properties(code, name, alias, world);
+        properties.put(SCOPE_KEY, scope);
+        return new DefaultGeographicCRS(properties, datum, cs);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -124,20 +124,6 @@ final class AuthorityFactoryIdentifier {
     private String version;
 
     /**
-     * {@code true} if {@code MultiAuthoritiesFactory} found more than one factory for this identifier.
-     * This is rarely needed, unless there is a configuration problem. This information is ignored by
-     * all methods in this class except {@link #conflict(AuthorityFactory)}, which use this field only
-     * for avoiding to log the same message twice.
-     *
-     * <p>This field does not need to be declared {@code volatile} because {@code MultiAuthoritiesFactory}
-     * will read and write this field (indirectly, though a call to {@code logConflictWarning(…)} only in
-     * a {@code synchronized} block.</p>
-     *
-     * @see #logConflictWarning(AuthorityFactory)
-     */
-    private boolean hasLoggedWarning;
-
-    /**
      * Creates a new identifier for a factory of the given type, authority and version.
      * The given authority shall be already in upper cases and the version in lower cases
      * (this is not verified by this constructor).
@@ -187,7 +173,7 @@ final class AuthorityFactoryIdentifier {
      * Creates a new identifier for the same type and authority than this identifier, but a different version
      * extracted from the given authority.
      *
-     * @param  factory The factory's authority.
+     * @param  factory The factory's authority, or {@code null} for creating an identifier without version.
      * @return An identifier for the version of the given authority, or {@code this} if the version is the same.
      */
     AuthorityFactoryIdentifier versionOf(final Citation factory) {
@@ -252,7 +238,7 @@ final class AuthorityFactoryIdentifier {
     /**
      * Returns the authority with the version, if any.
      */
-    CharSequence getAuthority() {
+    CharSequence getAuthorityAndVersion() {
         CharSequence name = authority;
         if (hasVersion()) {
             name = Vocabulary.formatInternational(Vocabulary.Keys.Version_2, name, version);
@@ -270,19 +256,31 @@ final class AuthorityFactoryIdentifier {
     /**
      * Logs a message reporting a conflict between the factory identified by this {@code AuthorityFactoryIdentifier}
      * and another factory, if this instance has not already logged a warning. This method assumes that it is invoked
-     * by the {@code MultiAuthoritiesFactory.getAuthorityFactory(…)} method in a synchronized block.
+     * by the {@code MultiAuthoritiesFactory.getAuthorityFactory(…)} method.
      *
      * @param used The factory which will be used.
      */
-    void logConflictWarning(final AuthorityFactory used) {
-        if (!hasLoggedWarning) {
-            hasLoggedWarning = true;
-            final LogRecord record = Messages.getResources(null).getLogRecord(Level.WARNING,
-                    Messages.Keys.IgnoredServiceProvider_3, TYPES[type], getAuthority(), Classes.getClass(used));
-            record.setLoggerName(Loggers.CRS_FACTORY);
-            // MultiAuthoritiesFactory.getAuthorityFactory(…) is the nearest public API.
-            Logging.log(MultiAuthoritiesFactory.class, "getAuthorityFactory", record);
-        }
+    void logConflict(final AuthorityFactory used) {
+        log(Messages.getResources(null).getLogRecord(Level.WARNING, Messages.Keys.IgnoredServiceProvider_3,
+                TYPES[type], getAuthorityAndVersion(), Classes.getClass(used)));
+    }
+
+    /**
+     * Logs a warning about a factory not found for the requested version, in which case
+     * {@code AuthorityFactoryIdentifier} fallback on a default version.
+     */
+    void logFallback() {
+        log(Messages.getResources(null).getLogRecord(Level.WARNING, Messages.Keys.FallbackDefaultFactoryVersion_2,
+                authority, version));
+    }
+
+    /**
+     * Do the logging of the warning prepared by the above methods.
+     */
+    private void log(final LogRecord record) {
+        record.setLoggerName(Loggers.CRS_FACTORY);
+        // MultiAuthoritiesFactory.getAuthorityFactory(…) is the nearest public API.
+        Logging.log(MultiAuthoritiesFactory.class, "getAuthorityFactory", record);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -1149,7 +1149,7 @@ public abstract class GeodeticAuthorityF
     }
 
     /**
-     * Returns a finder which can be used for looking up unidentified objects.
+     * Creates a finder which can be used for looking up unidentified objects.
      * The finder tries to fetch a fully {@linkplain AbstractIdentifiedObject identified object}
      * from an incomplete one, for example from an object without "{@code ID[…]}" or
      * "{@code AUTHORITY[…]}" element in <cite>Well Known Text</cite>.

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Set;
 import java.util.Map;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.IdentityHashMap;
@@ -30,6 +31,8 @@ import java.util.concurrent.ConcurrentMa
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.ConcurrentModificationException;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
 import javax.measure.unit.Unit;
 import org.opengis.referencing.*;
 import org.opengis.referencing.cs.*;
@@ -41,6 +44,7 @@ import org.opengis.metadata.extent.Exten
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.AbstractIterator;
 import org.apache.sis.internal.util.Citations;
 import org.apache.sis.internal.util.DefinitionURI;
@@ -51,10 +55,15 @@ import org.apache.sis.internal.util.SetO
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Messages;
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.collection.BackingStoreException;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * A factory that delegates the object creation to another factory determined from the <var>authority</var> part
@@ -154,6 +163,20 @@ public class MultiAuthoritiesFactory ext
     private volatile Set<String> codeSpaces;
 
     /**
+     * Whether this factory should relax some rules when processing a given authority code.
+     * See {@link #isLenient()} javadoc for a description of relaxed rules.
+     *
+     * @see #isLenient()
+     */
+    private volatile boolean isLenient;
+
+    /**
+     * The factories for which we have logged a warning. This is used in order to avoid logging the same
+     * warnings many time. We do not bother using a concurrent map here since this map should be rarely used.
+     */
+    private final Map<AuthorityFactoryIdentifier, Boolean> warnings;
+
+    /**
      * Creates a new multi-factories instance using the given lists of factories.
      * Calls to {@code createFoo(String)} methods will scan the supplied factories in their iteration order when first needed.
      * The first factory having the requested {@linkplain GeodeticAuthorityFactory#getCodeSpaces() namespace} will be used.
@@ -205,10 +228,39 @@ public class MultiAuthoritiesFactory ext
         }
         providers = ArraysExt.resize(p, length);
         factories = new ConcurrentHashMap<>();
+        warnings  = new HashMap<>();
         isIterationCompleted = new AtomicInteger(nullMask);
     }
 
     /**
+     * Returns whether this factory should relax some rules when processing a given authority code.
+     * If this value is {@code true}, then the behavior of this {@code MultiAuthoritiesFactory}
+     * is changed as below:
+     *
+     * <ul>
+     *   <li>If a version is specified in a URN but there is no factory for that specific version,
+     *       then fallback on a factory for the same authority but the default version.</li>
+     * </ul>
+     *
+     * The default value is {@code false}, which means that an exception will be thrown
+     * if there is no factory specifically for the requested version.
+     *
+     * @return Whether this factory should relax some rules when processing a given authority code.
+     */
+    public boolean isLenient() {
+        return isLenient;
+    }
+
+    /**
+     * Sets whether this factory should relax some rules when processing a given code.
+     *
+     * @param lenient Whether this factory should relax some rules when processing a given authority code.
+     */
+    public void setLenient(final boolean lenient) {
+        isLenient = lenient;
+    }
+
+    /**
      * Returns the database or specification that defines the codes recognized by this factory.
      * The default implementation returns {@code null} since {@code MultiAuthoritiesFactory} is not
      * about a particular authority.
@@ -463,7 +515,7 @@ public class MultiAuthoritiesFactory ext
      * @return The given {@code factory} if no previous instance was cached, or the existing instance otherwise.
      */
     private AuthorityFactory cache(final AuthorityFactoryIdentifier identifier, final AuthorityFactory factory) {
-        final AuthorityFactory existing = factories.putIfAbsent(identifier.intern(), factory);
+        final AuthorityFactory existing = JDK8.putIfAbsent(factories, identifier.intern(), factory);
         return (existing != null) ? existing : factory;
     }
 
@@ -588,19 +640,10 @@ public class MultiAuthoritiesFactory ext
                             }
                             /*
                              * If there is a conflict, log a warning provided that we did not already reported
-                             * that conflict. The flag telling us if we already logged a warning is in the key,
-                             * so we have to find that key in the loop below. This is inefficient, but conflict
-                             * should not happen in a sane environment.
+                             * that conflict.
                              */
-                            if (factory != cached) {
-                                for (final AuthorityFactoryIdentifier identifier : factories.keySet()) {
-                                    if (identifier.equals(versioned)) {
-                                        synchronized (provider) {
-                                            identifier.logConflictWarning(cached);
-                                        }
-                                        break;
-                                    }
-                                }
+                            if (factory != cached && canLog(versioned)) {
+                                versioned.logConflict(cached);
                             }
                             if (request.equals(versioned)) {
                                 return cached;
@@ -649,11 +692,34 @@ public class MultiAuthoritiesFactory ext
                 doneMask = isIterationCompleted.get();
             }
         }
-        final String authority = request.getAuthority().toString();
+        /*
+         * No factory found. Before to fail, search for a factory for the default version if we are allowed to.
+         */
+        if (request.hasVersion() && isLenient) {
+            factory = getAuthorityFactory(request.versionOf(null));
+            if (canLog(request)) {
+                request.logFallback();
+            }
+            return factory;
+        }
+        final String authority = request.getAuthorityAndVersion().toString();
         throw new NoSuchAuthorityFactoryException(Errors.format(Errors.Keys.UnknownAuthority_1, authority), authority);
     }
 
     /**
+     * Returns {@code true} if this {@code MultiAuthoritiesFactory} can log a warning for the given factory.
+     */
+    private boolean canLog(AuthorityFactoryIdentifier identifier) {
+        synchronized (warnings) {
+            if (warnings.containsKey(identifier)) {
+                return false;
+            }
+            // Invoke identifier.intern() only if needed.
+            return JDK8.putIfAbsent(warnings, identifier.intern(), Boolean.TRUE) == null;
+        }
+    }
+
+    /**
      * Creates an object from a code using the given proxy.
      *
      * @param  <T>   The type of the object to be returned.
@@ -1363,7 +1429,58 @@ public class MultiAuthoritiesFactory ext
     }
 
     /**
-     * Returns a finder which can be used for looking up unidentified objects.
+     * Creates operations from source and target coordinate reference system codes.
+     * If the authority for the two given CRS is handled by the same factory, then
+     * this method delegates to that factory. Otherwise this method returns an empty set.
+     *
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public Set<CoordinateOperation> createFromCoordinateReferenceSystemCodes(
+            final String sourceCRS, final String targetCRS) throws FactoryException
+    {
+        final Deferred deferred = new Deferred();
+        final CoordinateOperationAuthorityFactory factory = create(deferred, sourceCRS);
+        final String source = deferred.code;
+        if (create(deferred, targetCRS) == factory) {
+            return factory.createFromCoordinateReferenceSystemCodes(source, deferred.code);
+        }
+        /*
+         * No coordinate operation because of mismatched factories. This is not illegal (the result is an empty set)
+         * but it is worth to notify the user because this case has some chances to be an user error.
+         */
+        final LogRecord record = Messages.getResources(null).getLogRecord(Level.WARNING,
+                Messages.Keys.MismatchedOperationFactories_2, sourceCRS, targetCRS);
+        record.setLoggerName(Loggers.CRS_FACTORY);
+        Logging.log(MultiAuthoritiesFactory.class, "createFromCoordinateReferenceSystemCodes", record);
+        return super.createFromCoordinateReferenceSystemCodes(sourceCRS, targetCRS);
+    }
+
+    /**
+     * A proxy that does not execute immediately the {@code create} method on a factory,
+     * but instead stores information for later execution.
+     */
+    private static final class Deferred extends AuthorityFactoryProxy<CoordinateOperationAuthorityFactory> {
+        Deferred() {super(CoordinateOperationAuthorityFactory.class, AuthorityFactoryIdentifier.OPERATION);}
+
+        /** The authority code saved by the {@code createFromAPI(…)} method. */
+        String code;
+
+        /**
+         * Saves the given code in the {@link #code} field and returns the given factory unchanged.
+         * @throws FactoryException if the given factory is not an instance of {@link CoordinateOperationAuthorityFactory}.
+         */
+        @Override
+        CoordinateOperationAuthorityFactory createFromAPI(final AuthorityFactory factory, final String code)
+                throws FactoryException
+        {
+            this.code = code;
+            return opFactory(factory);
+        }
+    }
+
+    /**
+     * Creates a finder which can be used for looking up unidentified objects.
      * The default implementation delegates the lookups to the underlying factories.
      *
      * @return A finder to use for looking up unidentified objects.

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -73,7 +73,8 @@ import org.opengis.util.Factory;
     org.apache.sis.referencing.crs.DefaultCompoundCRSTest.class,
     org.apache.sis.referencing.crs.DefaultEngineeringCRSTest.class,
     org.apache.sis.referencing.crs.DefaultImageCRSTest.class,
-    org.apache.sis.referencing.cs.DirectionAlongMeridianTest.class
+    org.apache.sis.referencing.cs.DirectionAlongMeridianTest.class,
+    org.apache.sis.referencing.factory.GeodeticObjectFactoryTest.class
 })
 public final strictfp class GeodeticObjectParserTest extends TestCase {
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -43,14 +43,19 @@ import static org.apache.sis.test.Assert
  * @module
  */
 @DependsOn({
-    CommonCRSTest.class
+    CommonCRSTest.class,
+    AuthorityFactoriesTest.class
 })
 public final strictfp class CRSTest extends TestCase {
     /**
      * Asserts that the result of {@link CRS#forCode(String)} is the given CRS.
      */
     private static void verifyForCode(final SingleCRS expected, final String code) throws FactoryException {
-        assertTrue(code, Utilities.deepEquals(expected, CRS.forCode(code), ComparisonMode.IGNORE_METADATA));
+        final CoordinateReferenceSystem actual = CRS.forCode(code);
+        assertTrue(code, Utilities.deepEquals(expected, actual, ComparisonMode.DEBUG));
+        if (!EPSGFactoryFallback.FORCE_HARDCODED) {
+            assertSame(code, expected, actual);
+        }
     }
 
     /**
@@ -64,6 +69,7 @@ public final strictfp class CRSTest exte
     public void testForEpsgCode() throws FactoryException {
         verifyForCode(CommonCRS.WGS84 .geographic(),   "EPSG:4326");
         verifyForCode(CommonCRS.WGS84 .geographic(),   "urn:ogc:def:crs:EPSG::4326");
+        verifyForCode(CommonCRS.WGS84 .geographic(),   "urn:x-ogc:def:crs:EPSG::4326");
         verifyForCode(CommonCRS.WGS84 .geographic(),   "http://www.opengis.net/gml/srs/epsg.xml#4326");
         verifyForCode(CommonCRS.WGS72 .geographic(),   "EPSG:4322");
         verifyForCode(CommonCRS.SPHERE.geographic(),   "EPSG:4047");
@@ -82,7 +88,7 @@ public final strictfp class CRSTest exte
          * Following test is skipped when using the EPSG factory because EPSG uses
          * the "Gravity-related depth" axis name while ISO 19111 mandates "Depth".
          */
-        if (AuthorityFactories.EPSG() instanceof EPSGFactoryFallback) {
+        if (EPSGFactoryFallback.PENDING_NEXT_EPSG) {
             verifyForCode(CommonCRS.Vertical.DEPTH.crs(), "EPSG:5715");
         }
     }
@@ -100,6 +106,8 @@ public final strictfp class CRSTest exte
         verifyForCode(CommonCRS.WGS84.normalizedGeographic(), "CRS:84");
         verifyForCode(CommonCRS.NAD83.normalizedGeographic(), "CRS:83");
         verifyForCode(CommonCRS.NAD27.normalizedGeographic(), "CRS:27");
+        verifyForCode(CommonCRS.WGS84.normalizedGeographic(), "http://www.opengis.net/gml/srs/crs.xml#84");
+        verifyForCode(CommonCRS.NAD83.normalizedGeographic(), "http://www.opengis.net/gml/srs/crs.xml#83");
     }
 
     /**
@@ -244,4 +252,16 @@ public final strictfp class CRSTest exte
         assertEquals(0,          CRS.getGreenwichLongitude(HardCodedCRS.WGS84), STRICT);
         assertEquals(2.33722917, CRS.getGreenwichLongitude(HardCodedCRS.NTF),   1E-12);
     }
+
+    /**
+     * Tests {@link IdentifiedObjects#lookupEPSG(IdentifiedObject)} and
+     * {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)}.
+     *
+     * @throws FactoryException if an error occurred during the lookup.
+     */
+    @Test
+    public void testIdentifiedObjectLookup() throws FactoryException {
+        IdentifiedObjectsTest.testLookupEPSG();
+        IdentifiedObjectsTest.testLookupWMS();
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -163,10 +163,13 @@ public final strictfp class CommonCRSTes
                  */
                 Validators.validate(crs);
             }
-            assertSame  (name, datum,          e.datum()); // Datum before CRS creation.
-            assertSame  (name, crs.getDatum(), e.datum()); // Datum after CRS creation.
+            assertSame  (name, datum,          e.datum());                      // Datum before CRS creation.
+            assertSame  (name, crs.getDatum(), e.datum());                      // Datum after CRS creation.
             assertEquals(name, datumName, datum.getName().getCode());
             assertEquals(name, datumType, datum.getVerticalDatumType());
+            if (!EPSGFactoryFallback.PENDING_NEXT_EPSG && e == CommonCRS.Vertical.DEPTH) {
+                continue;   // Pending the renaming of "Gravity-related depth" as "Depth" in EPSG database.
+            }
             assertEquals(name, axisName,  crs.getCoordinateSystem().getAxis(0).getName().getCode());
         }
     }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -16,15 +16,27 @@
  */
 package org.apache.sis.referencing;
 
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.GeocentricCRS;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Utilities;
 
 // Test dependencies
+import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
+import org.apache.sis.test.TestUtilities;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.apache.sis.test.Assert.*;
 
 
 /**
@@ -41,36 +53,87 @@ import static org.junit.Assert.*;
 })
 public final strictfp class EPSGFactoryFallbackTest extends TestCase {
     /**
+     * Tests {@link EPSGFactoryFallback#getAuthorityCodes(Class)}.
+     *
+     * @throws FactoryException if the set of authority codes can not be fetched.
+     */
+    @Test
+    public void testGetAuthorityCodes() throws FactoryException {
+        assertSetEquals(Arrays.asList("4978", "4984", "4936"),
+                EPSGFactoryFallback.INSTANCE.getAuthorityCodes(GeocentricCRS.class));
+        assertSetEquals(Arrays.asList("4326", "4322", "4047", "4269", "4267", "4258", "4230", "4979", "4985", "4937"),
+                EPSGFactoryFallback.INSTANCE.getAuthorityCodes(GeographicCRS.class));
+        assertSetEquals(Arrays.asList("5714", "5715", "5703"),
+                EPSGFactoryFallback.INSTANCE.getAuthorityCodes(VerticalCRS.class));
+    }
+
+    /**
      * Tests {@link EPSGFactoryFallback#createCoordinateReferenceSystem(String)}.
      *
-     * @throws FactoryException If a CRS can not be constructed.
+     * @throws FactoryException if a CRS can not be constructed.
      *
      * @see CRSTest#testForEpsgCode()
      * @see CRSTest#testForCrsCode()
      */
     @Test
-    public void testForCode() throws FactoryException {
-        verifyForCode(CommonCRS.WGS84 .geographic(),            "4326");
-        verifyForCode(CommonCRS.WGS72 .geographic(),            "4322");
-        verifyForCode(CommonCRS.SPHERE.geographic(),            "4047");
-        verifyForCode(CommonCRS.NAD83 .geographic(),            "4269");
-        verifyForCode(CommonCRS.NAD27 .geographic(),            "4267");
-        verifyForCode(CommonCRS.ETRS89.geographic(),            "4258");
-        verifyForCode(CommonCRS.ED50  .geographic(),            "4230");
-        verifyForCode(CommonCRS.WGS84 .geocentric(),            "4978");
-        verifyForCode(CommonCRS.WGS72 .geocentric(),            "4984");
-        verifyForCode(CommonCRS.ETRS89.geocentric(),            "4936");
-        verifyForCode(CommonCRS.WGS84 .geographic3D(),          "4979");
-        verifyForCode(CommonCRS.WGS72 .geographic3D(),          "4985");
-        verifyForCode(CommonCRS.ETRS89.geographic3D(),          "4937");
-        verifyForCode(CommonCRS.Vertical.MEAN_SEA_LEVEL.crs(),  "5714");
-        verifyForCode(CommonCRS.Vertical.DEPTH.crs(),           "5715");
+    public void testCreateCRS() throws FactoryException {
+        verifyCreate(CommonCRS.WGS84 .geographic(),            "4326");
+        verifyCreate(CommonCRS.WGS72 .geographic(),            "4322");
+        verifyCreate(CommonCRS.SPHERE.geographic(),            "4047");
+        verifyCreate(CommonCRS.NAD83 .geographic(),            "4269");
+        verifyCreate(CommonCRS.NAD27 .geographic(),            "4267");
+        verifyCreate(CommonCRS.ETRS89.geographic(),            "4258");
+        verifyCreate(CommonCRS.ED50  .geographic(),            "4230");
+        verifyCreate(CommonCRS.WGS84 .geocentric(),            "4978");
+        verifyCreate(CommonCRS.WGS72 .geocentric(),            "4984");
+        verifyCreate(CommonCRS.ETRS89.geocentric(),            "4936");
+        verifyCreate(CommonCRS.WGS84 .geographic3D(),          "4979");
+        verifyCreate(CommonCRS.WGS72 .geographic3D(),          "4985");
+        verifyCreate(CommonCRS.ETRS89.geographic3D(),          "4937");
+        verifyCreate(CommonCRS.Vertical.MEAN_SEA_LEVEL.crs(),  "5714");
+        verifyCreate(CommonCRS.Vertical.DEPTH.crs(),           "5715");
     }
 
     /**
      * Asserts that the result of {@link CommonCRS#forCode(String, String, FactoryException)} is the given CRS.
      */
-    private static void verifyForCode(final SingleCRS expected, final String code) throws FactoryException {
+    private static void verifyCreate(final SingleCRS expected, final String code) throws FactoryException {
         assertSame(code, expected, EPSGFactoryFallback.INSTANCE.createCoordinateReferenceSystem(code));
     }
+
+    /**
+     * Sets the EPSG factory to the given instance and clears the cache of all {@link CommonCRS} enumeration values.
+     */
+    private static void setEPSGFactory(final CRSAuthorityFactory factory) {
+        AuthorityFactories.EPSG(factory);
+        for (final CommonCRS          crs : CommonCRS         .values()) crs.clear();
+        for (final CommonCRS.Vertical crs : CommonCRS.Vertical.values()) crs.clear();
+        for (final CommonCRS.Temporal crs : CommonCRS.Temporal.values()) crs.clear();
+    }
+
+    /**
+     * Compares all CRS created by {@link EPSGFactoryFallback} with CRS created by the real EPSG database.
+     *
+     * @throws FactoryException if a CRS can not be constructed.
+     */
+    @Test
+    @DependsOnMethod({"testGetAuthorityCodes", "testCreateCRS"})
+    public void compareAllCodes() throws FactoryException {
+        final CRSAuthorityFactory EPSG = (CRSAuthorityFactory) AuthorityFactories.EPSG();
+        try {
+            setEPSGFactory(EPSGFactoryFallback.INSTANCE);
+            final ArrayList<String> codes = new ArrayList<>(EPSGFactoryFallback.INSTANCE.getAuthorityCodes(CoordinateReferenceSystem.class));
+            Collections.shuffle(codes, TestUtilities.createRandomNumberGenerator());
+            for (final String code : codes) {
+                if (!EPSGFactoryFallback.PENDING_NEXT_EPSG && code.equals("5715")) {
+                    continue;
+                }
+                final CoordinateReferenceSystem crs = EPSGFactoryFallback.INSTANCE.createCoordinateReferenceSystem(code);
+                final CoordinateReferenceSystem expected = EPSG.createCoordinateReferenceSystem(code);
+                assertTrue(code, Utilities.deepEquals(expected, crs, ComparisonMode.DEBUG));
+            }
+        } finally {
+            setEPSGFactory(EPSG);
+        }
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -18,8 +18,11 @@ package org.apache.sis.referencing;
 
 import org.opengis.util.GenericName;
 import org.opengis.util.NameFactory;
+import org.opengis.util.FactoryException;
+import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;
 import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.test.mock.IdentifiedObjectMock;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
@@ -30,10 +33,13 @@ import static org.apache.sis.referencing
 
 /**
  * Tests the {@link IdentifiedObjects} static methods.
+ * This test class intentionally declares {@code testLookup()} method without {@link Test} annotation
+ * because those tests should not be executed only after the EPSG tests. Those tests will be executed
+ * by {@link CRSTest} instead.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 public final strictfp class IdentifiedObjectsTest extends TestCase {
@@ -73,4 +79,40 @@ public final strictfp class IdentifiedOb
         assertTrue (isHeuristicMatchForName(object, "Réunion"));
         assertTrue (isHeuristicMatchForName(object, "Reunion"));
     }
+
+    /**
+     * Tests {@link IdentifiedObjects#lookupEPSG(IdentifiedObject)} and
+     * {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)}
+     * with a CRS which is expected to be found in the EPSG dataset.
+     *
+     * <p>This method is intentionally not annotated with {@link Test}.
+     * See class javadoc for explanation.</p>
+     *
+     * @throws FactoryException if an error occurred during the lookup.
+     *
+     * @see CRSTest#testIdentifiedObjectLookup()
+     */
+    public static void testLookupEPSG() throws FactoryException {
+        assertEquals("EPSG:4326", Integer.valueOf(4326), IdentifiedObjects.lookupEPSG(HardCodedCRS.WGS84_φλ));
+        String urn = IdentifiedObjects.lookupURN(HardCodedCRS.WGS84_φλ, null);
+        assertTrue(urn, urn.matches("urn\\:ogc\\:def\\:crs\\:EPSG\\:.*\\:4326"));
+    }
+
+    /**
+     * Tests {@link IdentifiedObjects#lookupEPSG(IdentifiedObject)} and
+     * {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)}.
+     * with a CRS which is expected to be found in the WMS definitions.
+     *
+     * <p>This method is intentionally not annotated with {@link Test}.
+     * See class javadoc for explanation.</p>
+     *
+     * @throws FactoryException if an error occurred during the lookup.
+     *
+     * @see CRSTest#testIdentifiedObjectLookup()
+     */
+    public static void testLookupWMS() throws FactoryException {
+        assertNull("CRS:84", IdentifiedObjects.lookupEPSG(HardCodedCRS.WGS84));
+        String urn = IdentifiedObjects.lookupURN(HardCodedCRS.WGS84, null);
+        assertTrue(urn, urn.matches("urn\\:ogc\\:def\\:crs\\:OGC\\:.*\\:CRS84"));
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -18,6 +18,7 @@ package org.apache.sis.referencing.facto
 
 import java.util.Set;
 import java.util.LinkedHashSet;
+import javax.measure.unit.Unit;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;
@@ -31,8 +32,8 @@ import org.opengis.referencing.datum.Dat
 import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.datum.VerticalDatum;
+import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
 import org.opengis.util.InternationalString;
-import javax.measure.unit.Unit;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.internal.simple.SimpleCitation;
 import org.apache.sis.measure.Units;
@@ -52,7 +53,7 @@ import static org.junit.Assert.*;
  * @module
  */
 public final strictfp class AuthorityFactoryMock extends GeodeticAuthorityFactory
-        implements CRSAuthorityFactory, CSAuthorityFactory, DatumAuthorityFactory
+        implements CRSAuthorityFactory, CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory
 {
     /**
      * The authority.

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -342,7 +342,7 @@ public final strictfp class CommonAuthor
                 "  AXIS[“Latitude”, NORTH],\n" +
                 "  AUTHORITY[“CRS”, “84”]]", crs);
 
-        assertWktEquals(Convention.WKT2,
+        assertWktEqualsRegex(Convention.WKT2, "(?m)\\Q" +
                 "GEODCRS[“WGS 84”,\n" +
                 "  DATUM[“World Geodetic System 1984”,\n" +
                 "    ELLIPSOID[“WGS 84”, 6378137.0, 298.257223563, LENGTHUNIT[“metre”, 1]]],\n" +
@@ -351,9 +351,10 @@ public final strictfp class CommonAuthor
                 "    AXIS[“Longitude (L)”, east, ORDER[1]],\n" +
                 "    AXIS[“Latitude (B)”, north, ORDER[2]],\n" +
                 "    ANGLEUNIT[“degree”, 0.017453292519943295],\n" +
-                "  AREA[“World”],\n" +
+                "  SCOPE[“Horizontal component of 3D system.\\E.*\\Q”],\n" +
+                "  AREA[“World\\E.*\\Q”],\n" +
                 "  BBOX[-90.00, -180.00, 90.00, 180.00],\n" +
-                "  ID[“CRS”, 84, CITATION[“OGC:WMS”], URI[“urn:ogc:def:crs:OGC:1.3:CRS84”]]]", crs);
+                "  ID[“CRS”, 84, CITATION[“OGC:WMS”], URI[“urn:ogc:def:crs:OGC:1.3:CRS84”]]]\\E", crs);
         /*
          * Note: the WKT specification defines the ID element as:
          *

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -79,8 +79,6 @@ public final strictfp class MultiAuthori
 
         /** Verifies the log message. */
         @Override protected void verifyMessage(final String message) {
-            assertTrue(message, message.contains("CRSAuthorityFactory"));
-            assertTrue(message, message.contains("AuthorityFactoryMock"));
             for (final String keyword : expectedKeywords) {
                 assertTrue(message, message.contains(keyword));
             }
@@ -186,12 +184,12 @@ public final strictfp class MultiAuthori
         assertSame("MOCK1", mock1, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock1", "2.3"));
 
         listener.maximumLogCount = 1;
-        ((Listener) listener).expectedKeywords = new String[] {"MOCK1", "2.3"};
+        ((Listener) listener).expectedKeywords = new String[] {"CRSAuthorityFactory", "AuthorityFactoryMock", "MOCK1", "2.3"};
         assertSame("MOCK3", mock3, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock3", null));
         assertEquals("Expected a warning about the extraneous MOCK1 factory.", 0, listener.maximumLogCount);
 
         listener.maximumLogCount = 1;
-        ((Listener) listener).expectedKeywords = new String[] {"MOCK3"};
+        ((Listener) listener).expectedKeywords = new String[] {"CRSAuthorityFactory", "AuthorityFactoryMock", "MOCK3"};
         assertSame("MOCK5", mock5, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock5", null));
         assertEquals("Expected a warning about the extraneous MOCK3 factory.", 0, listener.maximumLogCount);
 
@@ -309,6 +307,31 @@ public final strictfp class MultiAuthori
     }
 
     /**
+     * Tests {@link MultiAuthoritiesFactory#createFromCoordinateReferenceSystemCodes(String, String)}.
+     *
+     * @throws FactoryException if an error occurred while creating the operation.
+     */
+    @Test
+    public void testCreateFromCoordinateReferenceSystemCodes() throws FactoryException {
+        final List<AuthorityFactoryMock> mock = Arrays.asList(
+                new AuthorityFactoryMock("MOCK", null),
+                new AuthorityFactoryMock("MOCK", "2.3"));
+        final MultiAuthoritiesFactory factory = new MultiAuthoritiesFactory(mock, null, null, mock);
+        /*
+         * Our mock factory does not implement createFromCoordinateReferenceSystemCodes(String, String),
+         * so we just test that we didn't got an exception and no message were logged.
+         */
+        assertTrue(factory.createFromCoordinateReferenceSystemCodes("MOCK:4326", "MOCK:84").isEmpty());
+        /*
+         * Following should log a warning telling that the authority factories do not match.
+         */
+        listener.maximumLogCount = 1;
+        ((Listener) listener).expectedKeywords = new String[] {"MOCK:4326", "MOCK:2.3:84"};
+        assertTrue(factory.createFromCoordinateReferenceSystemCodes("MOCK:4326", "MOCK:2.3:84").isEmpty());
+        assertEquals("Expected a warning about mismatched factories.", 0, listener.maximumLogCount);
+    }
+
+    /**
      * Tests {@link MultiAuthoritiesFactory#newIdentifiedObjectFinder()}.
      *
      * @throws FactoryException if an error occurred while creating the finder.

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -53,6 +53,7 @@ import org.apache.sis.referencing.crs.De
 import org.apache.sis.referencing.datum.BursaWolfParameters;
 import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
 import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
+import org.apache.sis.referencing.factory.GeodeticObjectFactory;
 import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
 import org.apache.sis.referencing.factory.UnavailableFactoryException;
 
@@ -100,8 +101,9 @@ public final strictfp class EPSGFactoryT
      */
     @BeforeClass
     public static void createFactory() throws FactoryException {
+        final GeodeticObjectFactory f = new GeodeticObjectFactory();
         try {
-            factory = new EPSGFactory();
+            factory = new EPSGFactory(null, null, f, f, f, null, null, null);
         } catch (UnavailableFactoryException e) {
             Logging.getLogger(Loggers.CRS_FACTORY).warning(e.toString());
             // Leave INSTANCE to null. This will have the effect of skipping tests.
@@ -298,7 +300,7 @@ public final strictfp class EPSGFactoryT
     /**
      * Tests the "WGS 72 / UTM zone 10N" projection and ensures
      * that it is not confused with "WGS 72BE / UTM zone 10N".
-     * In the EPSG database, those two projected CRS uses the same conversion.
+     * In the EPSG database, those two projected CRS use the same conversion.
      * However in Apache SIS the conversions must differ because the datum are not the same.
      *
      * @throws FactoryException if an error occurred while querying the factory.
@@ -323,6 +325,10 @@ public final strictfp class EPSGFactoryT
         assertEpsgNameAndIdentifierEqual("Transverse Mercator", 9807, variant.getConversionFromBase().getMethod());
         assertEpsgNameAndIdentifierEqual("UTM zone 10N", 16010, variant.getConversionFromBase());
         verifyTransverseMercatorParmeters(crs.getConversionFromBase().getParameterValues(), -123);
+        assertEquals("Operation method", crs.getConversionFromBase().getMethod(),
+                                     variant.getConversionFromBase().getMethod());
+        assertEquals("Coordinate system", crs.getCoordinateSystem(),
+                                      variant.getCoordinateSystem());
         assertSame("Operation method", crs.getConversionFromBase().getMethod(),
                                    variant.getConversionFromBase().getMethod());
         assertSame("Coordinate system", crs.getCoordinateSystem(),

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -30,8 +30,6 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.SingleOperation;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
-import org.apache.sis.referencing.operation.transform.MathTransformProvider;
-import org.apache.sis.referencing.operation.transform.MathTransforms;
 
 
 /**

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -168,19 +168,21 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.crs.DefaultCompoundCRSTest.class,
     org.apache.sis.referencing.crs.HardCodedCRSTest.class,
 
+    // Direct (not from authority codes) geodetic object creations.
     org.apache.sis.referencing.StandardDefinitionsTest.class,
-    org.apache.sis.referencing.CommonCRSTest.class,
-    org.apache.sis.referencing.EPSGFactoryFallbackTest.class,
-    org.apache.sis.referencing.CRSTest.class,
+    org.apache.sis.referencing.factory.GeodeticObjectFactoryTest.class,
     org.apache.sis.referencing.factory.GIGS3002.class,
     org.apache.sis.referencing.factory.GIGS3003.class,
     org.apache.sis.referencing.factory.GIGS3004.class,
     org.apache.sis.referencing.factory.GIGS3005.class,
-    org.apache.sis.referencing.factory.GeodeticObjectFactoryTest.class,
-    org.apache.sis.referencing.factory.CommonAuthorityFactoryTest.class,
-    org.apache.sis.referencing.factory.AuthorityFactoryProxyTest.class,
-    org.apache.sis.referencing.factory.IdentifiedObjectFinderTest.class,
-    org.apache.sis.referencing.factory.MultiAuthoritiesFactoryTest.class,
+
+    // Well Known Text parsing require above factory.
+    org.apache.sis.io.wkt.MathTransformParserTest.class,
+    org.apache.sis.io.wkt.GeodeticObjectParserTest.class,
+    org.apache.sis.io.wkt.WKTFormatTest.class,
+    org.apache.sis.io.wkt.WKTParserTest.class,
+
+    // Geodetic object creations from authority codes.
     org.apache.sis.referencing.factory.GIGS2001.class,
     org.apache.sis.referencing.factory.GIGS2002.class,
     org.apache.sis.referencing.factory.GIGS2003.class,
@@ -190,12 +192,17 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.factory.GIGS2007.class,
     org.apache.sis.referencing.factory.GIGS2008.class,
     org.apache.sis.referencing.factory.GIGS2009.class,
-    org.apache.sis.referencing.factory.sql.EPSGFactoryTest.class,
 
-    org.apache.sis.io.wkt.MathTransformParserTest.class,
-    org.apache.sis.io.wkt.GeodeticObjectParserTest.class,
-    org.apache.sis.io.wkt.WKTFormatTest.class,
-    org.apache.sis.io.wkt.WKTParserTest.class,
+    // Following tests use indirectly EPSG factory.
+    org.apache.sis.referencing.CommonCRSTest.class,
+    org.apache.sis.referencing.factory.CommonAuthorityFactoryTest.class,
+    org.apache.sis.referencing.factory.AuthorityFactoryProxyTest.class,
+    org.apache.sis.referencing.factory.IdentifiedObjectFinderTest.class,
+    org.apache.sis.referencing.factory.MultiAuthoritiesFactoryTest.class,
+    org.apache.sis.referencing.factory.sql.EPSGFactoryTest.class,
+    org.apache.sis.referencing.EPSGFactoryFallbackTest.class,
+    org.apache.sis.referencing.AuthorityFactoriesTest.class,
+    org.apache.sis.referencing.CRSTest.class,
 
     org.apache.sis.geometry.AbstractDirectPositionTest.class,
     org.apache.sis.geometry.GeneralDirectPositionTest.class,

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -240,6 +240,9 @@ public final class DefinitionURI {
             upper = uri.indexOf(separator, lower);
             if (upper < 0) {
                 upper = uri.length();
+                if (lower > upper) {
+                    return result;        // Happen if a component is missing.
+                }
             }
             switch (p) {
                 /*

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] Tue Jan 26 22:54:16 2016
@@ -166,6 +166,12 @@ public final class Messages extends Inde
         public static final short DiscardedExclusiveProperty_2 = 2;
 
         /**
+         * There is no factory for version {1} of “{0}” authority. Fallback on default version for
+         * objects creation.
+         */
+        public static final short FallbackDefaultFactoryVersion_2 = 38;
+
+        /**
          * Ignored properties after the first occurrence of ‘{0}’.
          */
         public static final short IgnoredPropertiesAfterFirst_1 = 6;
@@ -208,6 +214,11 @@ public final class Messages extends Inde
         public static final short MismatchedEllipsoidAxisLength_3 = 9;
 
         /**
+         * No coordinate operation from “{0}” to “{1}” because of mismatched factories.
+         */
+        public static final short MismatchedOperationFactories_2 = 37;
+
+        /**
          * Despite its name, this parameter is effectively “{0}”.
          */
         public static final short MisnamedParameter_1 = 18;

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties?rev=1726918&r1=1726917&r2=1726918&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] Tue Jan 26 22:54:16 2016
@@ -36,6 +36,7 @@ DataDirectoryNotSpecified_1      = The \
 DataDirectoryNotWritable_2       = Apache SIS can not write in the \u201c{1}\u201d directory given by the {0} environment variable.
 DeprecatedCode_3                 = Code \u201c{0}\u201d is deprecated and replaced by code {1}. Reason is: {2}
 DiscardedExclusiveProperty_2     = Property \u201c{0}\u201d has been discarded in favor of \u201c{1}\u201d, because those two properties are mutually exclusive.
+FallbackDefaultFactoryVersion_2  = There is no factory for version {1} of \u201c{0}\u201d authority. Fallback on default version for objects creation.
 IgnoredPropertiesAfterFirst_1    = Ignored properties after the first occurrence of \u2018{0}\u2019.
 IgnoredPropertyAssociatedTo_1    = Ignored property associated to \u2018{0}\u2019.
 IgnoredServiceProvider_3         = More than one service provider of type \u2018{0}\u2019 are declared for \u201c{1}\u201d. Only the first provider (an instance of \u2018{2}\u2019) will be used.
@@ -45,6 +46,7 @@ LoadingDatumShiftFile_1          = Loadi
 LocalesDiscarded                 = Text were discarded for some locales.
 OptionalModuleNotFound_1         = Optional module \u201c{0}\u201d requested but not found.
 PropertyHiddenBy_2               = Property \u201c{0}\u201d is hidden by \u201c{1}\u201d.
+MismatchedOperationFactories_2   = No coordinate operation from \u201c{0}\u201d to \u201c{1}\u201d because of mismatched factories.
 MismatchedEllipsoidAxisLength_3  = The \u201c{1}\u201d parameter could have been omitted. But it has been given a value of {2} which does not match the definition of the \u201c{0}\u201d ellipsoid.
 MisnamedParameter_1              = Despite its name, this parameter is effectively \u201c{0}\u201d.
 NonConformFormatting_1           = Formatting of \u201c{0}\u201d is not conform to the format standard.




Mime
View raw message