sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1725815 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/referencing/factory/ sis-utility/src/main/java/org/apache/sis/util/resources/
Date Wed, 20 Jan 2016 21:11:53 GMT
Author: desruisseaux
Date: Wed Jan 20 21:11:53 2016
New Revision: 1725815

URL: http://svn.apache.org/viewvc?rev=1725815&view=rev
Log:
Initial implementation of createFoo(String) methods in MultiAuthoritiesFactory.
Opportunist javadoc fixes in ConcurrentAuthorityFactory and GeodeticAuthorityFactory.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java [UTF-8] Wed Jan 20 21:11:53 2016
@@ -17,6 +17,8 @@
 package org.apache.sis.referencing.factory;
 
 import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.AuthorityFactory;
@@ -27,6 +29,10 @@ import org.opengis.referencing.operation
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.iso.DefaultNameSpace;
+import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.util.resources.Messages;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.internal.system.Loggers;
 
 // Branch-dependent imports
 import java.util.Objects;
@@ -118,6 +124,20 @@ 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 in a {@code synchronized} block using the same lock (at least for the
+     * same instance of {@code AuthorityFactoryIdentifier}; lock may vary for other instances).</p>
+     *
+     * @see #conflict(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).
@@ -132,6 +152,21 @@ final class AuthorityFactoryIdentifier {
      * Creates a new identifier for a factory of the given type, authority and version.
      * Only the version can be null.
      */
+    static AuthorityFactoryIdentifier create(final Class<? extends AuthorityFactory> type,
+            final String authority, final String version)
+    {
+        for (byte i=0; i<TYPES.length; i++) {
+            if (TYPES[i].isAssignableFrom(type)) {
+                return create(i, authority, version);
+            }
+        }
+        throw new IllegalArgumentException();   // Should never happen since above loop should have found ANY.
+    }
+
+    /**
+     * Creates a new identifier for a factory of the given type, authority and version.
+     * Only the version can be null.
+     */
     static AuthorityFactoryIdentifier create(final byte type, final String authority, final String version) {
         return new AuthorityFactoryIdentifier(type, authority.toUpperCase(Locale.US),
                            (version == null) ? null : version.toLowerCase(Locale.US));
@@ -176,7 +211,7 @@ final class AuthorityFactoryIdentifier {
      * Creates a new identifier for the same authority and version than this identifier, but a different factory.
      */
     AuthorityFactoryIdentifier newType(final byte newType) {
-        return (newType != type) ? new AuthorityFactoryIdentifier(newType, authority, version) : this;
+        return new AuthorityFactoryIdentifier(newType, authority, version);
     }
 
     /**
@@ -228,6 +263,28 @@ 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.
+     *
+     * @param used The factory which will be used.
+     */
+    void logConflictWarning(final AuthorityFactory used) {
+        if (!hasLoggedWarning) {
+            hasLoggedWarning = true;
+            CharSequence name = authority;
+            if (version != null) {
+                name = Vocabulary.formatInternational(Vocabulary.Keys.Version_2, name, version);
+            }
+            final LogRecord record = Messages.getResources(null).getLogRecord(Level.WARNING,
+                    Messages.Keys.IgnoredServiceProvider_3, TYPES[type], name, Classes.getClass(used));
+            record.setLoggerName(Loggers.CRS_FACTORY);
+            // MultiAuthoritiesFactory.getAuthorityFactory(…) is the nearest public API.
+            Logging.log(MultiAuthoritiesFactory.class, "getAuthorityFactory", record);
+        }
+    }
+
+    /**
      * Returns a string representation of this identifier for debugging purpose.
      */
     @Debug

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java [UTF-8] Wed Jan 20 21:11:53 2016
@@ -826,7 +826,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a geographic coordinate reference system from a code.
+     * Returns a 2- or 3-dimensional coordinate reference system based on an ellipsoidal approximation of the geoid.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -849,7 +849,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a geocentric coordinate reference system from a code.
+     * Returns a 3-dimensional coordinate reference system with the origin at the approximate centre of mass of the earth.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -872,7 +872,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a projected coordinate reference system from a code.
+     * Returns a 2-dimensional coordinate reference system used to approximate the shape of the earth on a planar surface.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -895,7 +895,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a vertical coordinate reference system from a code.
+     * Returns a 1-dimensional coordinate reference system used for recording heights or depths.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -918,7 +918,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a temporal coordinate reference system from a code.
+     * Returns a 1-dimensional coordinate reference system used for the recording of time.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -941,7 +941,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a 3D or 4D coordinate reference system from a code.
+     * Returns a CRS describing the position of points through two or more independent coordinate reference systems.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -964,7 +964,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a derived coordinate reference system from a code.
+     * Returns a CRS that is defined by its coordinate conversion from another CRS (not by a datum).
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -987,7 +987,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an engineering coordinate reference system from a code.
+     * Returns a 1-, 2- or 3-dimensional contextually local coordinate reference system.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1010,7 +1010,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an image coordinate reference system from a code.
+     * Returns a 2-dimensional engineering coordinate reference system applied to locations in images.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1033,7 +1033,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an arbitrary datum from a code.
+     * Returns an arbitrary datum from a code. The returned object will typically be an
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1056,7 +1056,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a geodetic datum from a code.
+     * Returns a datum defining the location and orientation of an ellipsoid that approximates the shape of the earth.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1079,7 +1079,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a vertical datum from a code.
+     * Returns a datum identifying a particular reference level surface used as a zero-height surface.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1102,7 +1102,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a temporal datum from a code.
+     * Returns a datum defining the origin of a temporal coordinate reference system.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1125,7 +1125,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an engineering datum from a code.
+     * Returns a datum defining the origin of an engineering coordinate reference system.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1148,7 +1148,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an image datum from a code.
+     * Returns a datum defining the origin of an image coordinate reference system.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1171,7 +1171,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an ellipsoid from a code.
+     * Returns a geometric figure that can be used to describe the approximate shape of the earth.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1194,7 +1194,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a prime meridian from a code.
+     * Returns a prime meridian defining the origin from which longitude values are determined.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1217,7 +1217,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an extent (usually a domain of validity) from a code.
+     * Returns information about spatial, vertical, and temporal extent (usually a domain of validity) from a code.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1262,7 +1262,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an ellipsoidal coordinate system from a code.
+     * Returns a 2- or 3-dimensional coordinate system for geodetic latitude and longitude, sometime with ellipsoidal height.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1285,7 +1285,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a vertical coordinate system from a code.
+     * Returns a 1-dimensional coordinate system for heights or depths of points.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1308,7 +1308,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a temporal coordinate system from a code.
+     * Returns a 1-dimensional coordinate system for heights or depths of points.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1331,7 +1331,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a Cartesian coordinate system from a code.
+     * Returns a 2- or 3-dimensional Cartesian coordinate system made of straight orthogonal axes.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1354,7 +1354,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a spherical coordinate system from a code.
+     * Returns a 3-dimensional coordinate system with one distance measured from the origin and two angular coordinates.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1377,7 +1377,8 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a cylindrical coordinate system from a code.
+     * Returns a 3-dimensional coordinate system made of a polar coordinate system
+     * extended by a straight perpendicular axis.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1400,7 +1401,8 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a polar coordinate system from a code.
+     * Returns a 2-dimensional coordinate system for coordinates represented by a distance from the origin
+     * and an angle from a fixed direction.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1423,7 +1425,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a coordinate system axis from a code.
+     * Returns a coordinate system axis with name, direction, unit and range of values.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1468,7 +1470,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns a parameter descriptor from a code.
+     * Returns a definition of a single parameter used by an operation method.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1491,7 +1493,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an operation method from a code.
+     * Returns a description of the algorithm and parameters used to perform a coordinate operation.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>
@@ -1514,7 +1516,7 @@ public abstract class ConcurrentAuthorit
     }
 
     /**
-     * Returns an operation from a code.
+     * Returns an operation for transforming coordinates in the source CRS to coordinates in the target CRS.
      * The default implementation performs the following steps:
      * <ul>
      *   <li>Return the cached instance for the given code if such instance already exists.</li>

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] Wed Jan 20 21:11:53 2016
@@ -788,7 +788,7 @@ public abstract class GeodeticAuthorityF
     }
 
     /**
-     * Creates 2- or 3-dimensional coordinate system for geodetic latitude and longitude,
+     * Creates a 2- or 3-dimensional coordinate system for geodetic latitude and longitude,
      * sometime with ellipsoidal height.
      *
      * <div class="note"><b>Example:</b>
@@ -1069,7 +1069,7 @@ public abstract class GeodeticAuthorityF
     }
 
     /**
-     * Creates description of the algorithm and parameters used to perform a coordinate operation.
+     * Creates a description of the algorithm and parameters used to perform a coordinate operation.
      * An {@code OperationMethod} is a kind of metadata: it does not perform any coordinate operation
      * (e.g. map projection) by itself, but tells us what is needed in order to perform such operation.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Wed Jan 20 21:11:53 2016
@@ -20,6 +20,7 @@ import java.util.ServiceLoader;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.LinkedHashSet;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -29,9 +30,13 @@ import org.opengis.referencing.crs.*;
 import org.opengis.referencing.datum.*;
 import org.opengis.referencing.operation.*;
 import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.extent.Extent;
+import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.util.FactoryException;
+import javax.measure.unit.Unit;
 import org.apache.sis.internal.util.Citations;
 import org.apache.sis.internal.util.DefinitionURI;
+import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
@@ -41,59 +46,60 @@ import org.apache.sis.util.iso.DefaultNa
 
 /**
  * A factory that delegates the object creation to another factory determined from the <var>authority</var> part
- * in {@code "}<var>authority</var>{@code :}<var>code</var>{code "} arguments.
+ * in “<var>authority</var>:<var>code</var>” arguments.
  * The list of factories to use as delegates can be specified at construction time.
  *
- * <p>This factory requires that every codes given to a {@code createFoo(String)} method are prefixed by
- * the authority name, for example {@code "EPSG:4326"}. When a {@code createFoo(String)} method is invoked,
- * this class extracts the authority name from the {@code "authority:code"} argument and searches
- * for a factory for that authority in the list of factories given at construction time.
- * If a factory is found, then the work is delegated to that factory.
- * Otherwise a {@link NoSuchAuthorityCodeException} is thrown.</p>
+ * <p>This factory requires that every codes given to a {@code createFoo(String)} method are prefixed by a namespace,
+ * for example {@code "EPSG::4326"}.
+ * When a {@code createFoo(String)} method is invoked, this class uses the <var>authority</var> part in the
+ * “<var>authority</var>:<var>code</var>” argument for locating a factory capable to create a geodetic object
+ * for the <var>code</var> part.  If a factory is found in the list of factories given at construction time,
+ * then the work is delegated to that factory. Otherwise a {@link NoSuchAuthorityFactoryException} is thrown.</p>
  *
- * <p>This factory can also parse URNs of the form
- * {@code "urn:ogc:def:}<var>type</var>{@code :}<var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var>{@code "}.
- * In such case, the <var>type</var> specified in the URN may be used for invoking a more specific method.
+ * <div class="section">URI syntax</div>
+ * This factory can also parse URNs of the
+ * {@code "urn:ogc:def:}<var>type</var>{@code :}<var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var>{@code "}
+ * form and URLs of the {@code "http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var>{@code "} form.
+ * In such cases, the <var>type</var> specified in the URN may be used for invoking a more specific method.
  * However {@code MultiAuthoritiesFactory} uses the type information in the URN only for
  * delegating to a more specific method, never for delegating to a less specific method.
- * An exception will be thrown if the type in the URN is incompatible with the method invoked.</p>
+ * An exception will be thrown if the type in the URN is incompatible with the invoked method.
  *
  * <div class="note"><b>Example:</b>
- * if the {@link #createObject(String)} method is invoked with the <code>"urn:ogc:def:<b>crs</b>:EPSG::4326"</code>
- * URN, then {@code MultiAuthoritiesFactory} will delegate (indirectly, ignoring caching for this example) the object
+ * if <code>{@linkplain #createObject(String) createObject}("urn:ogc:def:<b>crs</b>:EPSG::4326")</code> is invoked,
+ * then {@code MultiAuthoritiesFactory} will delegate (indirectly, ignoring caching for this example) the object
  * creation to {@link org.apache.sis.referencing.factory.sql.EPSGDataAccess#createCoordinateReferenceSystem(String)}
  * instead of {@link org.apache.sis.referencing.factory.sql.EPSGDataAccess#createObject(String)} because of the
- * {@code "crs"} part in the URN. The more specific method gives more performances and avoid ambiguities.</div>
+ * {@code "crs"} part in the URN. The more specific method gives better performances and avoid ambiguities.</div>
  *
  * <div class="section">Multiple versions for the same authority</div>
  * {@code MultiAuthoritiesFactory} accepts an arbitrary amount of factories for the same authority, provided that
  * those factories have different version numbers. If a {@code createFoo(String)} method is invoked with a URN
- * containing a version number, then {@code MultiAuthoritiesFactory} will search for a factory with that exact
- * version, or throw a {@link NoSuchAuthorityCodeException} if no suitable factory is found.
+ * containing a version number different than zero, then {@code MultiAuthoritiesFactory} will search for a factory
+ * with that exact version, or throw a {@link NoSuchAuthorityFactoryException} if no suitable factory is found.
  * If a {@code createFoo(String)} method is invoked with the version number omitted, then {@code MultiAuthoritiesFactory}
  * will use the first factory in iteration order for the requested authority regardless of its version number.
  *
  * <div class="note"><b>Example:</b>
  * a {@code MultiAuthoritiesFactory} instance could contain two {@code EPSGFactory} instances:
- * one for version 8.2 of the EPSG dataset and another one for version 7.9 of the EPSG dataset.
+ * one for version 8.2 and another one for version 7.9 of the EPSG dataset.
  * A specific version can be requested in the URN given to {@code createFoo(String)} methods,
  * for example <code>"urn:ogc:def:crs:EPSG:<b>8.2</b>:4326"</code>.
- * If no version is given as in {@code "urn:ogc:def:crs:EPSG::4326"},
+ * If no version is given (for example {@code "urn:ogc:def:crs:EPSG::4326"}),
  * then the first EPSG factory in iteration order is used regardless of its version number.
  * </div>
  *
  * <div class="section">Multi-threading</div>
  * This class is thread-safe if all delegate factories are themselves thread-safe.
- * However the factory <em>providers</em>, which are given to the constructor as
- * {@code Iterable<? extends AuthorityFactory>} instances, do not need to be thread-safe.
- * See constructor Javadoc for more information.
+ * However the factory <em>providers</em>, which are given to the constructor as {@link Iterable} instances,
+ * do not need to be thread-safe. See constructor Javadoc for more information.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.7
  * @version 0.7
  * @module
  */
-public abstract class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements CRSAuthorityFactory,
+public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements CRSAuthorityFactory,
         CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory
 {
     /**
@@ -122,9 +128,16 @@ public abstract class MultiAuthoritiesFa
     private final AtomicInteger iterationCompleted;
 
     /**
-     * Creates a new multi-factory using the given lists of factories.
+     * The code spaces of all factories given to the constructor, created when first requested.
+     *
+     * @see #getCodeSpaces()
+     */
+    private volatile Set<String> codeSpaces;
+
+    /**
+     * 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 expected {@linkplain GeodeticAuthorityFactory#getAuthority() authority name} will be used.
+     * The first factory having the requested {@linkplain GeodeticAuthorityFactory#getCodeSpaces() namespace} will be used.
      *
      * <div class="section">Requirements</div>
      * {@code MultiAuthoritiesFactory} may iterate over the same {@code Iterable} more than once.
@@ -186,6 +199,35 @@ public abstract class MultiAuthoritiesFa
         return null;
     }
 
+    @Override
+    public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type) throws FactoryException {
+        throw new UnsupportedOperationException("Not supported yet.");      // TODO
+    }
+
+    /**
+     * Returns the code spaces of all factories given to the constructor.
+     * This method may be relatively costly since it implies instantiation of all factories.
+     *
+     * @return The code spaces of all factories.
+     */
+    @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    public Set<String> getCodeSpaces() {
+        Set<String> union = codeSpaces;
+        if (union == null) {
+            union = new LinkedHashSet<>();
+            for (final Iterable<? extends AuthorityFactory> provider : providers) {
+                if (provider != null) synchronized (provider) {
+                    for (final AuthorityFactory factory : provider) {
+                        union.addAll(getCodeSpaces(factory));
+                    }
+                }
+            }
+            codeSpaces = union = CollectionsExt.unmodifiableOrCopy(union);
+        }
+        return union;
+    }
+
     /**
      * Returns the code spaces for the given factory.
      * This method delegates to {@link GeodeticAuthorityFactory#getCodeSpaces()} if possible,
@@ -214,11 +256,36 @@ public abstract class MultiAuthoritiesFa
     }
 
     /**
+     * Returns the factory identified by the given type, authority and version.
+     *
+     * @param  <T>        The compile-time value of {@code type}.
+     * @param  type       The type of the desired factory as one of the {@link CRSAuthorityFactory}, {@link CSAuthorityFactory},
+     *                    {@link DatumAuthorityFactory} or {@link CoordinateOperationFactory} interfaces.
+     * @param  authority  The namespace or authority identifier of the desired factory.
+     *                    Examples: {@code "EPSG"}, {@code "CRS"} or {@code "AUTO2"}.
+     * @param  version    The version of the desired factory, or {@code null} for the default version.
+     * @return The factory for the given type, authority and version.
+     * @throws NoSuchAuthorityFactoryException if no suitable factory has been found.
+     */
+    /*
+     * This method is declared final for avoiding the false impression than overriding this method would change
+     * the behavior of MultiAuthoritiesFactory. It would not because the 'create(…)' method invokes the private
+     * 'getAuthorityFactory(…)' instead of the public one.
+     */
+    public final <T extends AuthorityFactory> T getAuthorityFactory(final Class<T> type,
+            final String authority, final String version) throws NoSuchAuthorityFactoryException
+    {
+        ArgumentChecks.ensureNonNull("type", type);
+        ArgumentChecks.ensureNonNull("authority", authority);
+        return type.cast(getAuthorityFactory(AuthorityFactoryIdentifier.create(type, authority, version)));
+    }
+
+    /**
      * Returns the factory identified by the given type, authority and version. If no such factory is found in
-     * the cache, then this method iterates on the factories created by the providers given at construction time.
+     * the cache, then this method iterates over the factories created by the providers given at construction time.
      *
      * @param  request The type, authority and version of the desired factory.
-     * @return The factory.
+     * @return The factory for the given type, authority and version.
      * @throws NoSuchAuthorityFactoryException if no suitable factory has been found.
      */
     private AuthorityFactory getAuthorityFactory(final AuthorityFactoryIdentifier request)
@@ -255,55 +322,55 @@ public abstract class MultiAuthoritiesFa
                 final Iterable<? extends AuthorityFactory> provider = providers[type];
                 synchronized (provider) {   // Should never be null because of the 'doneMask' check.
                     /*
-                     * Check again in case another thread has found the factory after the check at
-                     * the beginning of this method but before we entered in the synchronized block.
-                     */
-                    factory = factories.get(request);
-                    if (factory != null) {
-                        return factory;
-                    }
-                    /*
                      * Search for a factory for the given authority. Caches all factories that we find
-                     * during the iteration process. Some factories may be already cached as a result
+                     * during the iteration process. Some factories may already be cached as a result
                      * of a partial iteration in a previous call to getAuthorityFactory(…).
                      */
                     for (final Iterator<? extends AuthorityFactory> it = provider.iterator(); it.hasNext();) {
                         factory = it.next();
-                        AuthorityFactory found = null;
-                        AuthorityFactory conflict = null;
                         for (final String namespace : getCodeSpaces(factory)) {
                             final AuthorityFactoryIdentifier unversioned = request.unversioned(namespace);
                             AuthorityFactory cached = cache(unversioned, factory);
-                            if (request.equals(unversioned)) {
-                                found = cached;
-                            }
+                            final AuthorityFactory found = request.equals(unversioned) ? cached : null;
                             /*
                              * Only if we have no choice, ask to the factory what is its version number.
                              * We have no choice when ignoring the version number causes a conflict, or
                              * when the user asked for a specific version.
                              */
-                            if (cached != factory || request.hasVersion()) {
-                                // Make sure that we took in account the version number of the default factory.
-                                cache(unversioned.versionOf(cached.getAuthority()), cached);
-
-                                // Now check the version number of the new factory that we just fetched.
+                            if (factory != cached || (request.hasVersion() && request.getAuthority().equals(unversioned.getAuthority()))) {
                                 final AuthorityFactoryIdentifier versioned = unversioned.versionOf(factory.getAuthority());
                                 if (versioned != unversioned) {
+                                    /*
+                                     * Before to cache the factory with a key containing the factory version, make sure
+                                     * that we took in account the version of the default factory. This will prevent the
+                                     * call to 'cache(versioned, factory)' to overwrite the default factory.
+                                     */
+                                    if (factory != cached) {
+                                        cache(unversioned.versionOf(cached.getAuthority()), cached);
+                                    }
                                     cached = cache(versioned, factory);
-                                    if (request.equals(versioned)) {
-                                        found = cached;
+                                }
+                                /*
+                                 * 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.
+                                 */
+                                if (factory != cached) {
+                                    for (final AuthorityFactoryIdentifier identifier : factories.keySet()) {
+                                        if (identifier.equals(versioned)) {
+                                            identifier.logConflictWarning(cached);
+                                            break;
+                                        }
                                     }
                                 }
-                                if (cached != factory) {
-                                    conflict = cached;
+                                if (request.equals(versioned)) {
+                                    return cached;
                                 }
                             }
-                        }
-                        if (conflict != null) {
-                            // TODO: log a warning
-                        }
-                        if (found != null) {
-                            return found;
+                            if (found != null) {
+                                return found;
+                            }
                         }
                     }
                 }
@@ -343,7 +410,7 @@ public abstract class MultiAuthoritiesFa
     }
 
     /**
-     * Returns an object from a code using the given proxy.
+     * Creates an object from a code using the given proxy.
      *
      * @param  <T>   The type of the object to be returned.
      * @param  proxy The proxy to use for creating the object.
@@ -386,6 +453,582 @@ public abstract class MultiAuthoritiesFa
     }
 
     /**
+     * Creates an arbitrary object from a code.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var> — note that this form is ambiguous</li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var> — note that this form is ambiguous</li>
+     *   <li>{@code urn:ogc:def:}<var>type</var>{@code :}<var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * The two first formats are ambiguous when used with this {@code createObject(String)} because different kinds
+     * of objects can have the same code.
+     *
+     * @return The object for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public IdentifiedObject createObject(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.OBJECT, code);
+    }
+
+    /**
+     * Creates an arbitrary coordinate reference system from a code.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.CRS, code);
+    }
+
+    /**
+     * Creates a 2- or 3-dimensional coordinate reference system based on an ellipsoidal approximation of the geoid.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public GeographicCRS createGeographicCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.GEOGRAPHIC_CRS, code);
+    }
+
+    /**
+     * Creates a 3-dimensional coordinate reference system with the origin at the approximate centre of mass of the earth.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public GeocentricCRS createGeocentricCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.GEOCENTRIC_CRS, code);
+    }
+
+    /**
+     * Creates a 2-dimensional coordinate reference system used to approximate the shape of the earth on a planar surface.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public ProjectedCRS createProjectedCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.PROJECTED_CRS, code);
+    }
+
+    /**
+     * Creates a 1-dimensional coordinate reference system used for recording heights or depths.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public VerticalCRS createVerticalCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.VERTICAL_CRS, code);
+    }
+
+    /**
+     * Creates a 1-dimensional coordinate reference system used for the recording of time.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public TemporalCRS createTemporalCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.TEMPORAL_CRS, code);
+    }
+
+    /**
+     * Creates a CRS describing the position of points through two or more independent coordinate reference systems.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CompoundCRS createCompoundCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.COMPOUND_CRS, code);
+    }
+
+    /**
+     * Creates a CRS that is defined by its coordinate conversion from another CRS (not by a datum).
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public DerivedCRS createDerivedCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.DERIVED_CRS, code);
+    }
+
+    /**
+     * Creates a 1-, 2- or 3-dimensional contextually local coordinate reference system.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public EngineeringCRS createEngineeringCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.ENGINEERING_CRS, code);
+    }
+
+    /**
+     * Creates a 2-dimensional engineering coordinate reference system applied to locations in images.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>crs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li>{@code http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate reference system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public ImageCRS createImageCRS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.IMAGE_CRS, code);
+    }
+
+    /**
+     * Creates an arbitrary datum from a code. The returned object will typically be an
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>datum</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The datum for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public Datum createDatum(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.DATUM, code);
+    }
+
+    /**
+     * Creates a datum defining the location and orientation of an ellipsoid that approximates the shape of the earth.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>datum</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The datum for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public GeodeticDatum createGeodeticDatum(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.GEODETIC_DATUM, code);
+    }
+
+    /**
+     * Creates a datum identifying a particular reference level surface used as a zero-height surface.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>datum</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The datum for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public VerticalDatum createVerticalDatum(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.VERTICAL_DATUM, code);
+    }
+
+    /**
+     * Creates a datum defining the origin of a temporal coordinate reference system.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>datum</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The datum for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public TemporalDatum createTemporalDatum(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.TEMPORAL_DATUM, code);
+    }
+
+    /**
+     * Creates a datum defining the origin of an engineering coordinate reference system.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>datum</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The datum for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public EngineeringDatum createEngineeringDatum(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.ENGINEERING_DATUM, code);
+    }
+
+    /**
+     * Creates a datum defining the origin of an image coordinate reference system.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>datum</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The datum for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public ImageDatum createImageDatum(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.IMAGE_DATUM, code);
+    }
+
+    /**
+     * Creates a geometric figure that can be used to describe the approximate shape of the earth.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>ellipsoid</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The ellipsoid for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public Ellipsoid createEllipsoid(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.ELLIPSOID, code);
+    }
+
+    /**
+     * Creates a prime meridian defining the origin from which longitude values are determined.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>meridian</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The prime meridian for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public PrimeMeridian createPrimeMeridian(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.PRIME_MERIDIAN, code);
+    }
+
+    /**
+     * Creates information about spatial, vertical, and temporal extent (usually a domain of validity) from a code.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The extent for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public Extent createExtent(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.EXTENT, code);
+    }
+
+    /**
+     * Creates an arbitrary coordinate system from a code.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CoordinateSystem createCoordinateSystem(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.COORDINATE_SYSTEM, code);
+    }
+
+    /**
+     * Creates a 2- or 3-dimensional coordinate system for geodetic latitude and longitude, sometime with ellipsoidal height.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public EllipsoidalCS createEllipsoidalCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.ELLIPSOIDAL_CS, code);
+    }
+
+    /**
+     * Creates a 1-dimensional coordinate system for heights or depths of points.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public VerticalCS createVerticalCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.VERTICAL_CS, code);
+    }
+
+    /**
+     * Creates a 1-dimensional coordinate system for heights or depths of points.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public TimeCS createTimeCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.TIME_CS, code);
+    }
+
+    /**
+     * Creates a 2- or 3-dimensional Cartesian coordinate system made of straight orthogonal axes.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CartesianCS createCartesianCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.CARTESIAN_CS, code);
+    }
+
+    /**
+     * Creates a 3-dimensional coordinate system with one distance measured from the origin and two angular coordinates.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public SphericalCS createSphericalCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.SPHERICAL_CS, code);
+    }
+
+    /**
+     * Creates a 3-dimensional coordinate system made of a polar coordinate system
+     * extended by a straight perpendicular axis.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CylindricalCS createCylindricalCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.CYLINDRICAL_CS, code);
+    }
+
+    /**
+     * Creates a 2-dimensional coordinate system for coordinates represented by a distance from the origin
+     * and an angle from a fixed direction.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>cs</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The coordinate system for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public PolarCS createPolarCS(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.POLAR_CS, code);
+    }
+
+    /**
+     * Creates a coordinate system axis with name, direction, unit and range of values.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>axis</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The axis for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CoordinateSystemAxis createCoordinateSystemAxis(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.AXIS, code);
+    }
+
+    /**
+     * Creates an unit of measurement from a code.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>uom</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The unit of measurement for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public Unit<?> createUnit(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.UNIT, code);
+    }
+
+    /**
+     * Creates a definition of a single parameter used by an operation method.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>parameter</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The parameter descriptor for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public ParameterDescriptor<?> createParameterDescriptor(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.PARAMETER, code);
+    }
+
+    /**
+     * Creates a description of the algorithm and parameters used to perform a coordinate operation.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>method</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The operation method for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public OperationMethod createOperationMethod(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.METHOD, code);
+    }
+
+    /**
+     * Creates an operation for transforming coordinates in the source CRS to coordinates in the target CRS.
+     * The given code can use any of the following patterns, where <var>version</var> is optional:
+     * <ul>
+     *   <li><var>authority</var>{@code :}<var>code</var></li>
+     *   <li><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     *   <li><code>urn:ogc:def:<b>coordinateOperation</b>:</code><var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
+     * </ul>
+     *
+     * @return The operation for the given code.
+     * @throws FactoryException if the object creation failed.
+     */
+    @Override
+    public CoordinateOperation createCoordinateOperation(final String code) throws FactoryException {
+        return create(AuthorityFactoryProxy.OPERATION, code);
+    }
+
+    /**
      * Clears the cache and notifies all factories need to be fetched again from the providers given at
      * construction time. All providers that are instances of {@link ServiceLoader} will have their
      * {@link ServiceLoader#reload() reload()} method invoked.
@@ -403,6 +1046,12 @@ public abstract class MultiAuthoritiesFa
                         ((ServiceLoader<?>) provider).reload();
                     }
                     /*
+                     * Clear the 'iterationCompleted' bit before to clear the cache so that if another thread
+                     * invokes 'getAuthorityFactory(…)', it will block on the synchronized(provider) statement
+                     * until we finished the cleanup.
+                     */
+                    applyAndMask(~(1 << type));
+                    /*
                      * Clear the cache on a provider-by-provider basis, not by a call to factories.clear().
                      * This is needed because this MultiAuthoritiesFactory instance may be used concurrently
                      * by other threads, and we have no global lock for the whole factory.
@@ -413,11 +1062,19 @@ public abstract class MultiAuthoritiesFa
                             it.remove();
                         }
                     }
-                    int doneMask;
-                    do doneMask = iterationCompleted.get();
-                    while (iterationCompleted.compareAndSet(doneMask, doneMask & ~(1 << type)));
                 }
             }
         }
+        applyAndMask(providers.length - 1);     // Clears all bits other than the bits for providers.
+    }
+
+    /**
+     * Sets {@link #iterationCompleted} to {@code iterationCompleted & mask}.
+     * This is used by {@link #reload()} for clearing bits.
+     */
+    private void applyAndMask(final int mask) {
+        int value;
+        do value = iterationCompleted.get();
+        while (!iterationCompleted.compareAndSet(value, value & mask));
     }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] Wed Jan 20 21:11:53 2016
@@ -176,6 +176,12 @@ public final class Messages extends Inde
         public static final short IgnoredPropertyAssociatedTo_1 = 7;
 
         /**
+         * More than one service provider of type ‘{0}’ are declared for “{1}”. Only the first provider
+         * (an instance of ‘{2}’) will be used.
+         */
+        public static final short IgnoredServiceProvider_3 = 36;
+
+        /**
          * Parsing of “{0}” done, but some elements were ignored.
          */
         public static final short IncompleteParsing_1 = 14;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] Wed Jan 20 21:11:53 2016
@@ -38,6 +38,7 @@ DeprecatedCode_3                 = Code
 DiscardedExclusiveProperty_2     = Property \u201c{0}\u201d has been discarded in favor of \u201c{1}\u201d, because those two properties are mutually exclusive.
 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.
 IncompleteParsing_1              = Parsing of \u201c{0}\u201d done, but some elements were ignored.
 JNDINotSpecified_1               = No object associated to the \u201c{0}\u201d JNDI name.
 LoadingDatumShiftFile_1          = Loading datum shift file \u201c{0}\u201d.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties?rev=1725815&r1=1725814&r2=1725815&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties [ISO-8859-1] Wed Jan 20 21:11:53 2016
@@ -45,6 +45,7 @@ DeprecatedCode_3                 = Le co
 DiscardedExclusiveProperty_2     = La propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 \u00e9cart\u00e9e en faveur de \u00ab\u202f{1}\u202f\u00bb, parce que ces deux propri\u00e9t\u00e9s sont mutuellement exclusives.
 IgnoredPropertiesAfterFirst_1    = Des propri\u00e9t\u00e9s ont \u00e9t\u00e9 ignor\u00e9es apr\u00e8s la premi\u00e8re occurrence de \u2018{0}\u2019.
 IgnoredPropertyAssociatedTo_1    = Une propri\u00e9t\u00e9 associ\u00e9e \u00e0 \u2018{0}\u2019 a \u00e9t\u00e9 ignor\u00e9e.
+IgnoredServiceProvider_3         = Plusieurs fournisseurs de service de type \u2018{0}\u2019 sont d\u00e9clar\u00e9s pour \u00ab\u202f{1}\u202f\u00bb. Seul le premier fournisseur (une instance de \u2018{2}\u2019) sera utilis\u00e9.
 IncompleteParsing_1              = La lecture de \u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 faite, mais en ignorant certains \u00e9l\u00e9ments.
 JNDINotSpecified_1               = Aucun objet n\u2019est associ\u00e9 au nom JNDI \u00ab\u202f{0}\u202f\u00bb.
 LoadingDatumShiftFile_1          = Chargement du fichier de changement de r\u00e9f\u00e9rentiel \u00ab\u202f{0}\u202f\u00bb.



Mime
View raw message