/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.referencing.factory;

import java.util.ServiceLoader;
import java.util.Collections;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;
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;
import java.util.concurrent.ConcurrentMap;
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;
import org.opengis.referencing.*;
import org.opengis.referencing.cs.*;
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 org.opengis.util.InternationalString;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.AbstractIterator;
import org.apache.sis.internal.util.DefinitionURI;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.util.SetOfUnknownSize;
import org.apache.sis.internal.metadata.NameMeaning;
import org.apache.sis.internal.referencing.LazySet;
import org.apache.sis.internal.referencing.Resources;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.IdentifiedObjects;
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.collection.BackingStoreException;


/**
 * A factory that delegates the object creation to another factory determined from the <var>authority</var> part
 * 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 a namespace,
 * for example {@code "EPSG:4326"} or {@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>
 *
 * <h2>URI syntax</h2>
 * This factory can also parse URNs or URLs of the following forms:
 *
 * <ul>
 *   <li>{@code "urn:ogc:def:}<var>type</var>{@code :}<var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var>{@code "}</li>
 *   <li>{@code "http://www.opengis.net/def/}<var>type</var>{@code /}<var>authority</var>{@code /}<var>version</var>{@code /}<var>code</var>{@code "}</li>
 *   <li>{@code "http://www.opengis.net/gml/srs/}<var>authority</var>{@code .xml#}<var>code</var>{@code "}</li>
 * </ul>
 *
 * 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 invoked method.
 *
 * <div class="note"><b>Example:</b>
 * 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 better performances and avoid ambiguities.</div>
 *
 * This class accepts also combined URIs of the following forms
 * (only two components shown, but arbitrary number of components is allowed):
 *
 * <ul>
 *   <li>{@code "urn:ogc:def:}<var>type</var>{@code ,}
 *       <var>type₁</var>{@code :}<var>authority₁</var>{@code :}<var>version₁</var>{@code :}<var>code₁</var>{@code ,}
 *       <var>type₂</var>{@code :}<var>authority₂</var>{@code :}<var>version₂</var>{@code :}<var>code₂</var>{@code "}</li>
 *   <li>{@code  "http://www.opengis.net/def/crs-compound?}<br>
 *       {@code 1=http://www.opengis.net/def/crs/}<var>authority₁</var>{@code /}<var>version₁</var>{@code /}<var>code₁</var>{@code &}<br>
 *       {@code 2=http://www.opengis.net/def/crs/}<var>authority₂</var>{@code /}<var>version₂</var>{@code /}<var>code₂</var>{@code "}</li>
 * </ul>
 *
 * Given such URIs, {@code MultiAuthoritiesFactory} invokes {@link #createObject(String)} for each component
 * and combines the result as described by the {@link CRS#compound(CoordinateReferenceSystem...)} method.
 * URNs (but not URLs) can also combine a
 * {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum geodetic datum} with an
 * {@linkplain org.apache.sis.referencing.cs.DefaultEllipsoidalCS ellipsoidal coordinate system} for creating a new
 * {@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS geographic CRS}, or a base geographic CRS with a
 * {@linkplain org.apache.sis.referencing.operation.DefaultConversion conversion} and a
 * {@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian coordinate system} for creating a new
 * {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS projected coordinate reference system}, or
 * {@linkplain org.apache.sis.referencing.operation.AbstractCoordinateOperation coordinate operations}
 * for creating a concatenated operation.
 *
 * <h2>Multiple versions for the same authority</h2>
 * {@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 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 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 of if the given version is zero,
 * then the first EPSG factory in iteration order is used regardless of its version number.
 * </div>
 *
 * <h2>Multi-threading</h2>
 * 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 {@link Iterable} instances,
 * do not need to be thread-safe. See constructor Javadoc for more information.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 0.8
 *
 * @see org.apache.sis.referencing.CRS#getAuthorityFactory(String)
 *
 * @since 0.7
 * @module
 */
public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements CRSAuthorityFactory,
        CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory
{
    /**
     * The factory providers given at construction time. Elements in the array are for {@link CRSAuthorityFactory},
     * {@link CSAuthorityFactory}, {@link DatumAuthorityFactory} and {@link CoordinateOperationAuthorityFactory}
     * in that order. That order is defined by the constant values in {@link AuthorityFactoryIdentifier}.
     *
     * <p>Note that this array is shorter than the amount of {@link AuthorityFactoryIdentifier} values.
     * The last {@link AuthorityFactoryIdentifier} values are handled in a special way.</p>
     *
     * <p>The array may contain {@code null} elements when there is no provider for a given type.
     * Content of this array shall be immutable after construction time in order to avoid the need
     * for synchronization when reading the array. However usage of an {@code Iterable} element
     * shall be synchronized on that {@code Iterable}.</p>
     */
    private final Iterable<? extends AuthorityFactory>[] providers;

    /**
     * The factories obtained from {@link #getAuthorityFactory(Class, String, String)} and similar methods.
     */
    private final ConcurrentMap<AuthorityFactoryIdentifier, AuthorityFactory> factories;

    /**
     * A bit masks identifying which providers have given us all their factories.
     * The value {@code (1 << type)} is set when {@code MultiAuthoritiesFactory}
     * has iterated until the end of {@code providers[type].iterator()}.
     */
    private final AtomicInteger isIterationCompleted;

    /**
     * The code spaces of all factories given to the constructor, created when first requested.
     *
     * @see #getCodeSpaces()
     */
    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.
     *
     * <h4>Requirements</h4>
     * {@code MultiAuthoritiesFactory} may iterate over the same {@code Iterable} more than once.
     * Each iteration <strong>shall</strong> return the same instances than previous iterations,
     * unless {@link #reload()} has been invoked.
     *
     * <p>The {@code Iterable}s do not need to be thread-safe.
     * {@code MultiAuthoritiesFactory} will use them only in blocks synchronized on the {@code Iterable} instance.
     * For example all usages of {@code crsFactory} will be done inside a {@code synchronized(crsFactory)} block.</p>
     *
     * <h4>Name collision</h4>
     * If an {@code Iterable} contains more than one factory for the same namespace and version,
     * then only the first occurrence will be used. All additional factories for the same namespace
     * and version will be ignored, after a warning has been logged.
     *
     * <h4>Caching</h4>
     * {@code MultiAuthoritiesFactory} caches the factories found from the given {@code Iterable}s,
     * but does not cache the objects created by those factories.
     * This constructor assumes that the given factories already do their own caching.
     *
     * @param crsFactories    the factories for creating {@link CoordinateReferenceSystem} objects, or null if none.
     * @param csFactories     the factories for creating {@link CoordinateSystem} objects, or null if none.
     * @param datumFactories  the factories for creating {@link Datum} objects, or null if none.
     * @param copFactories    the factories for creating {@link CoordinateOperation} objects, or null if none.
     */
    @SuppressWarnings({"unchecked", "rawtypes", "empty-statement"})    // Generic array creation.
    public MultiAuthoritiesFactory(final Iterable<? extends CRSAuthorityFactory> crsFactories,
                                   final Iterable<? extends CSAuthorityFactory> csFactories,
                                   final Iterable<? extends DatumAuthorityFactory> datumFactories,
                                   final Iterable<? extends CoordinateOperationAuthorityFactory> copFactories)
    {
        final Iterable<? extends AuthorityFactory>[] p = new Iterable[4];
        p[AuthorityFactoryIdentifier.CRS]       = crsFactories;
        p[AuthorityFactoryIdentifier.CS]        = csFactories;
        p[AuthorityFactoryIdentifier.DATUM]     = datumFactories;
        p[AuthorityFactoryIdentifier.OPERATION] = copFactories;
        /*
         * Mark null Iterables as if we already iterated over all their elements.
         * Opportunistically reduce the array size by trimming trailing null elements.
         * The memory gain is negligible, but this will reduce the number of iterations in loops.
         */
        int length = 0, nullMask = 0;
        for (int i=0; i < p.length; i++) {
            if (p[i] != null) length = i+1;
            else nullMask |= (1 << i);
        }
        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.
     */
    @Override
    public Citation getAuthority() {
        return null;
    }

    /**
     * Returns the set of authority codes for objects of the given type.
     * This method returns the union of codes returned by all factories specified at construction time.
     *
     * <p>The {@link Set#contains(Object)} method of the returned set is lenient:
     * it accepts various ways to format a code even if the iterator returns only one form.
     * For example the {@code contains(Object)} method may return {@code true} for {@code "EPSG:4326"},
     * {@code "EPSG::4326"}, {@code "urn:ogc:def:crs:EPSG::4326"}, <i>etc.</i> even if
     * the iterator returns only {@code "EPSG:4326"}.</p>
     *
     * <p><b>Warnings:</b></p>
     * <ul>
     *   <li>Callers should not retain a reference to the returned collection for a long time,
     *       since it may be backed by database connections (depending on the factory implementations).</li>
     *   <li>The returned set is not thread-safe. Each thread should ask its own instance and let
     *       the garbage collector disposes it as soon as the collection is not needed anymore.</li>
     *   <li>Call to the {@link Set#size()} method on the returned collection should be avoided
     *       since it may be costly.</li>
     * </ul>
     *
     * @param  type  the spatial reference objects type.
     * @return the set of authority codes for spatial reference objects of the given type.
     * @throws FactoryException if access to an underlying factory failed.
     */
    @Override
    public Set<String> getAuthorityCodes(final Class<? extends IdentifiedObject> type) throws FactoryException {
        return new SetOfUnknownSize<String>() {
            /**
             * Returns an iterator over all authority codes.
             * Codes are fetched on-the-fly.
             */
            @Override
            public Iterator<String> iterator() {
                return new AbstractIterator<String>() {
                    /** An iterator over the factories for which to return codes. */
                    private final Iterator<AuthorityFactory> factories = getAllFactories();

                    /** An iterator over the codes of the current factory. */
                    private Iterator<String> codes = Collections.emptyIterator();

                    /** The prefix to prepend before codes, or {@code null} if none. */
                    private String prefix;

                    /** For filtering duplicated codes when there is many versions of the same authority. */
                    private final Set<String> done = new HashSet<>();

                    /** Tests if there is more codes to return. */
                    @Override public boolean hasNext() {
                        while (next == null) {
                            while (!codes.hasNext()) {
                                do {
                                    if (!factories.hasNext()) {
                                        return false;
                                    }
                                    final AuthorityFactory factory = factories.next();
                                    codes = getAuthorityCodes(factory).iterator();
                                    prefix = getCodeSpace(factory);
                                } while (!done.add(prefix));
                            }
                            next = codes.next();
                        }
                        return true;
                    }

                    /** Returns the next element, with namespace inserted before the code if needed. */
                    @Override public String next() {
                        String code = super.next();
                        if (prefix != null && code.indexOf(Constants.DEFAULT_SEPARATOR) < 0) {
                            code = prefix + Constants.DEFAULT_SEPARATOR + code;
                        }
                        return code;
                    }
                };
            }

            /**
             * The cache of values returned by {@link #getAuthorityCodes(AuthorityFactory)}.
             */
            private final Map<AuthorityFactory, Set<String>> cache = new IdentityHashMap<>();

            /**
             * Returns the authority codes for the given factory.
             * This method invokes {@link AuthorityFactory#getAuthorityCodes(Class)}
             * only once per factory and caches the returned {@code Set<String>}.
             */
            final Set<String> getAuthorityCodes(final AuthorityFactory factory) {
                Set<String> codes = cache.get(factory);
                if (codes == null) {
                    try {
                        codes = factory.getAuthorityCodes(type);
                    } catch (FactoryException e) {
                        throw new BackingStoreException(e);
                    }
                    if (cache.put(factory, codes) != null) {
                        throw new ConcurrentModificationException();
                    }
                }
                return codes;
            }

            /**
             * The collection size, or a negative value if we have not yet computed the size.
             * A negative value different than -1 means that we have not counted all elements,
             * but we have determined that the set is not empty.
             */
            private int size = -1;

            /**
             * Returns {@code true} if the {@link #size()} method is cheap.
             */
            @Override
            protected boolean isSizeKnown() {
                return size >= 0;
            }

            /**
             * Returns the number of elements in this set (costly operation).
             */
            @Override
            public int size() {
                if (size < 0) {
                    int n = 0;
                    final Set<String> done = new HashSet<>();
                    for (final Iterator<AuthorityFactory> it = getAllFactories(); it.hasNext();) {
                        final AuthorityFactory factory = it.next();
                        if (done.add(getCodeSpace(factory))) {
                            n += getAuthorityCodes(factory).size();
                        }
                    }
                    size = n;
                }
                return size;
            }

            /**
             * Returns {@code true} if the set does not contain any element.
             * This method is much more efficient than testing {@code size() != 0}
             * since it will stop iteration as soon as an element is found.
             */
            @Override
            public boolean isEmpty() {
                if (size == -1) {
                    for (final Iterator<AuthorityFactory> it = getAllFactories(); it.hasNext();) {
                        if (!getAuthorityCodes(it.next()).isEmpty()) {
                            size = -2;      // Size still unknown, but we know that the set is not empty.
                            return false;
                        }
                    }
                    size = 0;
                }
                return size == 0;
            }

            /**
             * The proxy for the {@code GeodeticAuthorityFactory.getAuthorityCodes(type).contains(String)}.
             * Used by {@link #contains(Object)} for delegating its work to the most appropriate factory.
             */
            private final AuthorityFactoryProxy<Boolean> contains =
                new AuthorityFactoryProxy<Boolean>(Boolean.class, AuthorityFactoryIdentifier.ANY) {
                    @Override Boolean createFromAPI(AuthorityFactory factory, String code) throws FactoryException {
                        return getAuthorityCodes(factory).contains(code);
                    }
                    @Override AuthorityFactoryProxy<Boolean> specialize(String typeName) {
                        return this;
                    }
                };

            /**
             * Returns {@code true} if the factory contains the given code.
             */
            @Override
            public boolean contains(final Object code) {
                if (code instanceof String) try {
                    return create(contains, (String) code);
                } catch (NoSuchAuthorityCodeException e) {
                    // Ignore - will return false.
                } catch (FactoryException e) {
                    throw new BackingStoreException(e);
                }
                return false;
            }

            /** Declared soon as unsupported operation for preventing a call to {@link #size()}. */
            @Override public boolean removeAll(Collection<?> c) {throw new UnsupportedOperationException();}
            @Override public boolean retainAll(Collection<?> c) {throw new UnsupportedOperationException();}
            @Override public boolean remove   (Object o)        {throw new UnsupportedOperationException();}
        };
    }

    /**
     * Returns the code spaces of all factories given to the constructor.
     *
     * <div class="note"><b>Implementation note:</b>
     * the current implementation may be relatively costly since it implies instantiation of all factories.
     * </div>
     *
     * @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 Iterator<AuthorityFactory> it = getAllFactories(); it.hasNext();) {
                union.addAll(getCodeSpaces(it.next()));
            }
            codeSpaces = union = CollectionsExt.unmodifiableOrCopy(union);
        }
        return union;
    }

    /**
     * Returns the code spaces for the given factory.
     * This method delegates to {@link GeodeticAuthorityFactory#getCodeSpaces()} if possible,
     * or reproduces its default implementation otherwise.
     */
    private static Set<String> getCodeSpaces(final AuthorityFactory factory) {
        if (factory instanceof GeodeticAuthorityFactory) {
            return ((GeodeticAuthorityFactory) factory).getCodeSpaces();
        } else {
            final String authority = Citations.toCodeSpace(factory.getAuthority());
            return (authority != null) ? Collections.singleton(authority) : Collections.emptySet();
        }
    }

    /**
     * Returns the "main" namespace of the given factory, or {@code null} if none.
     * Current implementation returns the first namespace, but this may be changed in any future SIS version.
     *
     * <p>The purpose of this method is to get a unique identifier of a factory, ignoring version number.</p>
     */
    static String getCodeSpace(final AuthorityFactory factory) {
        return CollectionsExt.first(getCodeSpaces(factory));
    }

    /**
     * Caches the given factory, but without replacing existing instance if any.
     * This method returns the factory that we should use, either the given instance of the cached one.
     *
     * @param  identifier  the type, authority and version of the factory to cache.
     * @param  factory     the factory to cache.
     * @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);
        return (existing != null) ? existing : factory;
    }

    /**
     * Returns an iterator over all factories in this {@link MultiAuthoritiesFactory}.
     * Note that the same factory instance may be returned more than once if it implements more than one
     * of the {@link CRSAuthorityFactory}, {@link CSAuthorityFactory}, {@link DatumAuthorityFactory} or
     * {@link CoordinateOperationAuthorityFactory} interfaces.
     *
     * <p>This iterator takes care of synchronization on the {@code Iterable<AuthorityFactory>} instances.
     * Note that despite the above-cited synchronization, the returned iterator is <strong>not</strong>
     * thread-safe: each thread needs to use its own iterator instance. However provided that the above
     * condition is met, threads can safely use their iterators concurrently.</p>
     */
    final Iterator<AuthorityFactory> getAllFactories() {
        return new LazySynchronizedIterator<>(providers);
    }

    /**
     * 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 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 for the given type, authority and version.
     * @throws NoSuchAuthorityFactoryException if no suitable factory has been found.
     */
    private AuthorityFactory getAuthorityFactory(final AuthorityFactoryIdentifier request)
            throws NoSuchAuthorityFactoryException
    {
        AuthorityFactory factory = factories.get(request);
        if (factory != null) {
            return factory;
        }
        /*
         * If there is no factory in the cache for the given type, authority and version, then check if the
         * default factory (when no version is specified) is actually the factory for the requested version.
         * The reason why we have to do this check is because we do not ask the version of a factory before
         * we really need to do so, since fetching this information is relatively costly for some factories
         * (e.g. EPSGFactory needs to look in the "Version History" table of the dataset) and rarely needed.
         */
        if (request.hasVersion()) {
            factory = factories.get(request.versionOf(null));
            if (factory != null) {
                if (request.versionOf(factory.getAuthority()) == request) {
                    // Default factory is for the version that user requested. Cache that finding.
                    return cache(request, factory);
                }
                factory = null;
            }
        }
        /*
         * At this point we know that there is no factory in the cache for the requested type, authority and version.
         * Create new factories with the Iterables given at construction time. If we already started an iteration in
         * a previous call to this getAuthorityFactory(…) method, we will continue the search after skipping already
         * cached instances.
         */
        int doneMask = isIterationCompleted.get();
        final int type = request.type;
        if ((doneMask & (1 << type)) == 0) {
            if (type >= 0 && type < providers.length) {
                final Iterable<? extends AuthorityFactory> provider = providers[type];
                final Iterator<? extends AuthorityFactory> it;
                synchronized (provider) {               // Should never be null because of the 'doneMask' check.
                    it = provider.iterator();
                    while (it.hasNext()) {
                        factory = it.next();
                        if (factory != null) break;     // Paranoiac check against null factories.
                    }
                }
                /*
                 * Search for a factory for the given authority. Caches all factories that we find
                 * during the iteration process. Some factories may already be cached as a result
                 * of a partial iteration in a previous call to getAuthorityFactory(…).
                 */
                while (factory != null) {
                    for (final String namespace : getCodeSpaces(factory)) {
                        final AuthorityFactoryIdentifier unversioned = request.unversioned(namespace);
                        AuthorityFactory cached = cache(unversioned, factory);
                        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 (factory != cached || (request.hasVersion() && request.isSameAuthority(unversioned))) {
                            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 there is a conflict, log a warning provided that we did not already reported
                             * that conflict.
                             */
                            if (factory != cached && canLog(versioned)) {
                                versioned.logConflict(cached);
                            }
                            if (request.equals(versioned)) {
                                return cached;
                            }
                        }
                        if (found != null) {
                            return found;
                        }
                    }
                    factory = null;
                    synchronized (provider) {
                        while (it.hasNext()) {
                            factory = it.next();
                            if (factory != null) break;         // Paranoiac check against null factories.
                        }
                    }
                }
            } else if (type >= AuthorityFactoryIdentifier.GEODETIC) {
                /*
                 * Special cases: if the requested factory is ANY, take the first factory that we can find
                 * regardless of its type. We will try CRS, CS, DATUM and OPERATION factories in that order.
                 * The GEODETIC type is like ANY except for the additional restriction that the factory shall
                 * be an instance of the SIS-specific GeodeticAuthorityFactory class.
                 */
                assert providers.length <= Math.min(type, Byte.MAX_VALUE) : type;
                for (byte i=0; i < providers.length; i++) {
                    factory = getAuthorityFactory(request.newType(i));
                    switch (type) {
                        case AuthorityFactoryIdentifier.ANY: {
                            return factory;
                        }
                        case AuthorityFactoryIdentifier.GEODETIC: {
                            if (factory instanceof GeodeticAuthorityFactory) {
                                return factory;
                            }
                        }
                    }
                }
            }
            /*
             * Remember that we have iterated over all elements of this provider, so we will not try again.
             * Note that the mask values may also be modified in other threads for other providers, so we
             * need to atomically verify that the current value has not been modified before to set it.
             */
            while (!isIterationCompleted.compareAndSet(doneMask, doneMask | (1 << type))) {
                doneMask = isIterationCompleted.get();
            }
        }
        /*
         * 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(Resources.format(Resources.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 warnings.putIfAbsent(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.
     * @param  proxy  the proxy to use for creating the object.
     * @param  code   the code of the object to create.
     * @return the object from one of the authority factory specified at construction time.
     * @throws FactoryException if an error occurred while creating the object.
     */
    private <T> T create(AuthorityFactoryProxy<? extends T> proxy, String code) throws FactoryException {
        ArgumentChecks.ensureNonNull("code", code);
        final String authority, version;
        final String[] parameters;
        final DefinitionURI uri = DefinitionURI.parse(code);
        if (uri != null) {
            Class<? extends T> type = proxy.type;
            proxy = proxy.specialize(uri.type);
            /*
             * If the URN or URL contains combined references for compound coordinate reference systems,
             * create the components. First we verify that all component references have been parsed
             * before to start creating any object.
             */
            if (uri.code == null) {
                final DefinitionURI[] components = uri.components;
                if (components != null) {
                    for (int i=0; i < components.length; i++) {
                        if (components[i] == null) {
                            throw new NoSuchAuthorityCodeException(Resources.format(
                                    Resources.Keys.CanNotParseCombinedReference_2, i+1, uri.isHTTP ? 1 : 0),
                                    uri.authority, null, uri.toString());
                        }
                    }
                    if (proxy != null) type = proxy.type;       // Use the more specific type declared in the URN.
                    return combine(type, components, uri.isHTTP);
                }
            }
            /*
             * At this point we determined that the URN or URL references a single instance (not combined references).
             * Example: "urn:ogc:def:crs:EPSG:9.1:4326". Verifies that the object type is recognized and that a code
             * is present. The remainder steps are the same as if the user gave a simple code (e.g. "EPSG:4326").
             */
            if (uri.authority == null) {
                // We want this check before the 'code' value is modified below.
                throw new NoSuchAuthorityCodeException(
                        Resources.format(Resources.Keys.MissingAuthority_1, code), null, uri.code, code);
            }
            authority  = uri.authority;
            version    = uri.version;
            code       = uri.code;
            parameters = uri.parameters;
            if (code == null || proxy == null) {
                final String s = uri.toString();
                final String message;
                if (code == null) {
                    message = Errors.format(Errors.Keys.MissingComponentInElement_2, s, "code");
                } else {
                    message = Resources.format(Resources.Keys.CanNotCreateObjectAsInstanceOf_2, type,
                            DefinitionURI.PREFIX + DefinitionURI.SEPARATOR + uri.type);
                }
                throw new NoSuchAuthorityCodeException(message, authority, code, s);
            }
        } else {
            /*
             * Separate the authority from the rest of the code. The authority is mandatory; if missing,
             * an exception will be thrown. Note that the CharSequences.skipLeading/TrailingWhitespaces(…)
             * methods are robust to negative index, so the code will work even if code.indexOf(…) returned -1.
             */
            int afterAuthority = code.indexOf(Constants.DEFAULT_SEPARATOR);
            int end = CharSequences.skipTrailingWhitespaces(code, 0, afterAuthority);
            int start = CharSequences.skipLeadingWhitespaces(code, 0, end);
            if (start >= end) {
                throw new NoSuchAuthorityCodeException(Resources.format(Resources.Keys.MissingAuthority_1, code), null, code);
            }
            authority = code.substring(start, end);
            /*
             * Separate the version from the rest of the code. The version is optional. The code may have no room
             * for version (e.g. "EPSG:4326"), or specify an empty version (e.g. "EPSG::4326"). If the version is
             * equals to an empty string or to the "0" string, it will be considered as no version. Usage of 0 as
             * a pseudo-version is a practice commonly found in other software products.
             */
            int afterVersion = code.indexOf(Constants.DEFAULT_SEPARATOR, ++afterAuthority);
            start = CharSequences.skipLeadingWhitespaces(code, afterAuthority, afterVersion);
            end = CharSequences.skipTrailingWhitespaces(code, start, afterVersion);
            version = (start < end && !code.regionMatches(start, DefinitionURI.NO_VERSION, 0,
                    DefinitionURI.NO_VERSION.length())) ? code.substring(start, end) : null;
            if (version != null && !Character.isUnicodeIdentifierPart(version.codePointAt(0))) {
                throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.InvalidVersionIdentifier_1, version), authority, code);
            }
            /*
             * Separate the code from the authority and the version.
             */
            code = CharSequences.trimWhitespaces(code, Math.max(afterAuthority, afterVersion + 1), code.length()).toString();
            parameters = null;
        }
        /*
         * At this point we have the code without the authority and version parts.
         * Push back the authority part if the factory may need it. For now we do that only if the code has
         * parameters, since interpretation of the unit parameter in "AUTO(2):42001,unit,longitude,latitude"
         * depends on whether the authority is "AUTO" or "AUTO2". This works for now, but we may need a more
         * rigorous approach in a future SIS version.
         */
        if (parameters != null || code.indexOf(CommonAuthorityFactory.SEPARATOR) >= 0) {
            final StringBuilder buffer = new StringBuilder(authority.length() + code.length() + 1)
                    .append(authority).append(Constants.DEFAULT_SEPARATOR).append(code);
            if (parameters != null) {
                for (final String p : parameters) {
                    buffer.append(CommonAuthorityFactory.SEPARATOR).append(p);
                }
            }
            code = buffer.toString();
        }
        return proxy.createFromAPI(getAuthorityFactory(AuthorityFactoryIdentifier.create(proxy.factoryType, authority, version)), code);
    }

    /**
     * Returns a description of the object corresponding to 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:}<var>type</var>{@code :}<var>authority</var>{@code :}<var>version</var>{@code :}<var>code</var></li>
     *   <li>{@code http://www.opengis.net/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>
     *
     * @return a description of the object, or {@code null} if the object
     *         corresponding to the specified {@code code} has no description.
     * @throws FactoryException if an error occurred while fetching the description.
     */
    @Override
    public InternationalString getDescriptionText(final String code) throws FactoryException {
        return create(AuthorityFactoryProxy.DESCRIPTION, code);
    }

    /**
     * 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/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)} method
     * 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/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/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/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/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/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/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/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/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/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/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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>
     *   <li><code>http://www.opengis.net/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);
    }

    /**
     * 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 = Resources.forLocale(null).getLogRecord(Level.WARNING,
                Resources.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);
        }
    }

    /**
     * Invoked when a {@code createFoo(…)} method is given a combined URI.
     * A combined URI is a URN or URL referencing other components. For example if the given URI
     * is {@code "urn:ogc:def:crs, crs:EPSG::27700, crs:EPSG::5701"}, then the components are:
     * <ol>
     *   <li>{@code "urn:ogc:def:crs:EPSG:9.1:27700"}</li>
     *   <li>{@code "urn:ogc:def:crs:EPSG:9.1:5701"}</li>
     * </ol>
     *
     * We do not require the components to be instance of CRS, since the "Definition identifier URNs in
     * OGC namespace" best practice paper allows other kinds of combination (e.g. of coordinate operations).
     *
     * @param  <T>         compile-time value of {@code type} argument.
     * @param  type        type of object to create.
     * @param  references  parsed URI of the components.
     * @param  isHTTP      whether the user URI is an URL (i.e. {@code "http://something"}) instead than a URN.
     * @return the combined object.
     * @throws FactoryException if an error occurred while creating the combined object.
     */
    private <T> T combine(final Class<T> type, final DefinitionURI[] references, final boolean isHTTP) throws FactoryException {
        /*
         * Identify the type requested by the user and create all components with the assumption that they will
         * be of that type. This is the most common case. If during iteration we find an object of another kind,
         * then the array type will be downgraded to IdentifiedObject[]. The 'componentType' variable will keep
         * its non-null value only if the array stay of the expected sub-type.
         */
        final byte requestedType;
        IdentifiedObject[] components;
        Class<? extends IdentifiedObject> componentType;
        if (CoordinateReferenceSystem.class.isAssignableFrom(type)) {
            requestedType = AuthorityFactoryIdentifier.CRS;
            componentType = CoordinateReferenceSystem.class;
            components    = new CoordinateReferenceSystem[references.length];       // Intentional covariance.
        } else if (CoordinateOperation.class.isAssignableFrom(type)) {
            requestedType = AuthorityFactoryIdentifier.OPERATION;
            componentType = CoordinateOperation.class;
            components    = new CoordinateOperation[references.length];             // Intentional covariance.
        } else {
            throw new FactoryException(Resources.format(Resources.Keys.CanNotCombineUriAsType_1, type));
        }
        final String expected = NameMeaning.toObjectType(componentType);    // Note: "compound-crs" ⟶ "crs".
        for (int i=0; i<references.length; i++) {
            final DefinitionURI ref = references[i];
            final IdentifiedObject component = createObject(ref.toString());
            if (componentType != null && (!componentType.isInstance(component) || !expected.equalsIgnoreCase(ref.type))) {
                componentType = null;
                components = Arrays.copyOf(components, components.length, IdentifiedObject[].class);
            }
            components[i] = component;
        }
        /*
         * At this point we have successfully created all components. The way to interpret those components
         * depends mostly on the type of object requested by the user. For a given requested type, different
         * rules apply depending on the type of components. Those rules are described in OGC 07-092r1 (2007):
         * "Definition identifier URNs in OGC namespace".
         */
        IdentifiedObject combined = null;
        switch (requestedType) {
            case AuthorityFactoryIdentifier.OPERATION: {
                if (componentType != null) {
                    /*
                     * URN combined references for concatenated operations. We build an operation name from
                     * the operation identifiers (rather than CRS identifiers) because this is what the user
                     * gave to us, and because source/target CRS are not guaranteed to be defined. We do not
                     * yet support swapping roles of source and target CRS if an implied-reverse coordinate
                     * operation is included.
                     */
                    final CoordinateOperation[] ops = (CoordinateOperation[]) components;
                    String name = IdentifiedObjects.getIdentifierOrName(ops[0]) + " ⟶ "
                                + IdentifiedObjects.getIdentifierOrName(ops[ops.length - 1]);
                    combined = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
                            .createConcatenatedOperation(Collections.singletonMap(CoordinateOperation.NAME_KEY, name), ops);
                }
                break;
            }
            case AuthorityFactoryIdentifier.CRS: {
                if (componentType != null) {
                    /*
                     * URN combined references for compound coordinate reference systems.
                     * The URNs of the individual well-known CRSs are listed in the same order in which the
                     * individual coordinate tuples are combined to form the CompoundCRS coordinate tuple.
                     */
                    combined = CRS.compound((CoordinateReferenceSystem[]) components);
                } else if (!isHTTP) {
                    final CoordinateSystem cs = remove(references, components, CoordinateSystem.class);
                    if (cs != null) {
                        final Datum datum = remove(references, components, Datum.class);
                        if (datum != null) {
                            /*
                             * URN combined references for datum and coordinate system. In this case, the URN shall
                             * concatenate the URNs of one well-known datum and one well-known coordinate system.
                             */
                            if (ArraysExt.allEquals(references, null)) {
                                combined = combine((GeodeticDatum) datum, cs);
                            }
                        } else {
                            /*
                             * URN combined references for projected or derived CRSs. In this case, the URN shall
                             * concatenate the URNs of the one well-known CRS, one well-known Conversion, and one
                             * well-known CartesianCS. Similar action can be taken for derived CRS.
                             */
                            CoordinateReferenceSystem baseCRS = remove(references, components, CoordinateReferenceSystem.class);
                            CoordinateOperation op = remove(references, components, CoordinateOperation.class);
                            if (ArraysExt.allEquals(references, null) && op instanceof Conversion) {
                                combined = combine(baseCRS, (Conversion) op, cs);
                            }
                        }
                    }
                }
                break;
            }
        }
        /*
         * At this point the combined object has been created if we know how to create it.
         * Maybe the result matches the definition of an existing object in the database,
         * in which case we will use the existing definition for better metadata.
         */
        if (combined == null) {
            throw new FactoryException(Resources.format(Resources.Keys.UnexpectedComponentInURI));
        }
        final IdentifiedObject existing = newIdentifiedObjectFinder().findSingleton(combined);
        return type.cast(existing != null ? existing : combined);
    }

    /**
     * If the given {@code type} is found in the given {@code references}, sets that reference element to {@code null}
     * and returns the corresponding {@code components} element. Otherwise returns {@code null}. This is equivalent to
     * {@link Map#remove(Object, Object)} where {@code references} are the keys and {@code components} are the values.
     * We do not bother building that map because the arrays are very short (2 or 3 elements).
     */
    private static <T> T remove(final DefinitionURI[] references, final IdentifiedObject[] components, final Class<T> type) {
        final String expected = NameMeaning.toObjectType(type);
        for (int i=0; i<references.length; i++) {
            final DefinitionURI ref = references[i];
            if (ref != null && expected.equalsIgnoreCase(ref.type)) {
                references[i] = null;
                return type.cast(components[i]);
            }
        }
        return null;
    }

    /**
     * Invoked when a {@code createFoo(…)} method is given a combined URI containing a datum and a coordinate system.
     * If the given information are not sufficient or not applicable, then this method returns {@code null}.
     *
     * @param  datum  the datum, or {@code null} if missing.
     * @param  cs     the coordinate system (never null).
     * @return the combined CRS, or {@code null} if the given information are not sufficient.
     * @throws FactoryException if an error occurred while creating the combined CRS.
     */
    private static GeodeticCRS combine(final GeodeticDatum datum, final CoordinateSystem cs) throws FactoryException {
        final Map<String,?> properties = IdentifiedObjects.getProperties(datum, Datum.IDENTIFIERS_KEY);
        final CRSFactory factory = DefaultFactories.forBuildin(CRSFactory.class);
        if (datum instanceof GeodeticDatum) {
            if (cs instanceof EllipsoidalCS) {
                return factory.createGeographicCRS(properties, datum, (EllipsoidalCS) cs);
            } else if (cs instanceof SphericalCS) {
                return factory.createGeocentricCRS(properties, datum, (SphericalCS) cs);
            }
        }
        return null;
    }

    /**
     * Invoked when a {@code createFoo(…)} method is given a combined URI containing a conversion and a coordinate
     * system. If the given information are not sufficient or not applicable, then this method returns {@code null}.
     *
     * @param  baseCRS   the CRS on which the derived CRS will be based on, or {@code null} if missing.
     * @param  fromBase  the conversion from {@code baseCRS} to the CRS to be created by this method.
     * @param  cs        the coordinate system (never null).
     * @return the combined CRS, or {@code null} if the given information are not sufficient.
     * @throws FactoryException if an error occurred while creating the combined CRS.
     */
    private static GeneralDerivedCRS combine(final CoordinateReferenceSystem baseCRS, final Conversion fromBase,
            final CoordinateSystem cs) throws FactoryException
    {
        if (baseCRS != null && fromBase.getSourceCRS() == null && fromBase.getTargetCRS() == null) {
            final Map<String,?> properties = IdentifiedObjects.getProperties(fromBase, Datum.IDENTIFIERS_KEY);
            final CRSFactory factory = DefaultFactories.forBuildin(CRSFactory.class);
            if (baseCRS instanceof GeographicCRS && cs instanceof CartesianCS) {
                return factory.createProjectedCRS(properties, (GeographicCRS) baseCRS, fromBase, (CartesianCS) cs);
            } else {
                return factory.createDerivedCRS(properties, baseCRS, fromBase, cs);
            }
        }
        return null;
    }

    /**
     * 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.
     * @throws FactoryException if the finder can not be created.
     */
    @Override
    public IdentifiedObjectFinder newIdentifiedObjectFinder() throws FactoryException {
        return new Finder(this);
    }

    /**
     * A {@link IdentifiedObjectFinder} which tests every factories declared in the
     * {@linkplain MultiAuthoritiesFactory#getAllFactories() collection of factories}.
     */
    private static class Finder extends IdentifiedObjectFinder {
        /**
         * The finders of all factories, or {@code null} if not yet fetched.
         * We will create this array only when first needed in order to avoid instantiating the factories
         * before needed (for example we may be able to find an object using only its code). However if we
         * need to create this array, then we will create it fully (for all factories at once).
         */
        private IdentifiedObjectFinder[] finders;

        /**
         * Creates a new finder.
         */
        protected Finder(final MultiAuthoritiesFactory factory) throws FactoryException {
            super(factory);
        }

        /**
         * Sets the domain of the search (for example whether to include deprecated objects in the search).
         */
        @Override
        public void setSearchDomain(final Domain domain) {
            super.setSearchDomain(domain);
            if (finders != null) {
                for (final IdentifiedObjectFinder finder : finders) {
                    finder.setSearchDomain(domain);
                }
            }
        }

        /**
         * Sets whether the search should ignore coordinate system axes.
         */
        @Override
        public void setIgnoringAxes(final boolean ignore) {
            super.setIgnoringAxes(ignore);
            if (finders != null) {
                for (final IdentifiedObjectFinder finder : finders) {
                    finder.setIgnoringAxes(ignore);
                }
            }
        }

        /**
         * Delegates to every factories registered in the enclosing {@link MultiAuthoritiesFactory},
         * in iteration order. This method is invoked only if the parent class failed to find the
         * object by its identifiers and by its name. At this point, as a last resource, we will
         * scan over the objects in the database.
         *
         * <p>This method shall <strong>not</strong> delegate the job to the parent class, as the default
         * implementation in the parent class is very inefficient. We need to delegate to the finders of
         * all factories, so we can leverage their potentially more efficient algorithms.</p>
         */
        @Override
        final Set<IdentifiedObject> createFromCodes(final IdentifiedObject object) throws FactoryException {
            if (finders == null) try {
                final ArrayList<IdentifiedObjectFinder> list = new ArrayList<>();
                final Map<AuthorityFactory,Boolean> unique = new IdentityHashMap<>();
                final Iterator<AuthorityFactory> it = ((MultiAuthoritiesFactory) factory).getAllFactories();
                while (it.hasNext()) {
                    final AuthorityFactory candidate = it.next();
                    if (candidate instanceof GeodeticAuthorityFactory && unique.put(candidate, Boolean.TRUE) == null) {
                        IdentifiedObjectFinder finder = ((GeodeticAuthorityFactory) candidate).newIdentifiedObjectFinder();
                        if (finder != null) {   // Should never be null according method contract, but we are paranoiac.
                            finder.ignoreIdentifiers = true;
                            finder.setWrapper(this);
                            list.add(finder);
                        }
                    }
                }
                finders = list.toArray(new IdentifiedObjectFinder[list.size()]);
            } catch (BackingStoreException e) {
                throw e.unwrapOrRethrow(FactoryException.class);
            }
            final Set<IdentifiedObject> found = new LinkedHashSet<>();
            for (final IdentifiedObjectFinder finder : finders) {
                found.addAll(finder.find(object));
            }
            return found;
        }
    }

    /**
     * Clears the cache and notifies this {@code MultiAuthoritiesFactory} that all factories will need to
     * be fetched again from the providers given at construction time. In addition, all providers that are
     * instances of {@link ServiceLoader} will have their {@link ServiceLoader#reload() reload()} method invoked.
     *
     * <p>This method is intended for use in situations in which new factories can be installed into a running
     * Java virtual machine.</p>
     */
    public void reload() {
        for (int type=0; type < providers.length; type++) {
            final Iterable<?> provider = providers[type];
            if (provider != null) {
                synchronized (provider) {
                    if (provider instanceof LazySet<?>) {
                        ((LazySet<?>) provider).reload();
                    }
                    if (provider instanceof ServiceLoader<?>) {
                        ((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.
                     */
                    final Iterator<AuthorityFactoryIdentifier> it = factories.keySet().iterator();
                    while (it.hasNext()) {
                        if (it.next().type == type) {
                            it.remove();
                        }
                    }
                }
            }
        }
        applyAndMask(providers.length - 1);     // Clears all bits other than the bits for providers.
    }

    /**
     * Sets {@link #isIterationCompleted} to {@code iterationCompleted & mask}.
     * This is used by {@link #reload()} for clearing bits.
     */
    private void applyAndMask(final int mask) {
        int value;
        do value = isIterationCompleted.get();
        while (!isIterationCompleted.compareAndSet(value, value & mask));
    }
}
