/*
 * 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;

import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Filter;
import java.util.logging.LogRecord;
import org.opengis.util.FactoryException;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.cs.CartesianCS;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.GeodeticCRS;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.GeneralDerivedCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.TemporalCRS;
import org.opengis.referencing.crs.VerticalCRS;
import org.opengis.referencing.crs.EngineeringCRS;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.operation.Conversion;
import org.opengis.referencing.operation.OperationNotFoundException;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.measure.Units;
import org.apache.sis.geometry.Envelopes;
import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.internal.referencing.AxisDirections;
import org.apache.sis.internal.referencing.EllipsoidalHeightCombiner;
import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
import org.apache.sis.internal.referencing.CoordinateOperations;
import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.internal.referencing.DefinitionVerifier;
import org.apache.sis.internal.referencing.Resources;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.referencing.cs.AxisFilter;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.cs.DefaultVerticalCS;
import org.apache.sis.referencing.crs.DefaultGeographicCRS;
import org.apache.sis.referencing.crs.DefaultProjectedCRS;
import org.apache.sis.referencing.crs.DefaultVerticalCRS;
import org.apache.sis.referencing.crs.DefaultCompoundCRS;
import org.apache.sis.referencing.crs.DefaultEngineeringCRS;
import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
import org.apache.sis.referencing.operation.CoordinateOperationContext;
import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
import org.apache.sis.referencing.operation.DefaultConversion;
import org.apache.sis.referencing.factory.GeodeticObjectFactory;
import org.apache.sis.referencing.factory.UnavailableFactoryException;
import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.apache.sis.metadata.iso.extent.Extents;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.Static;


/**
 * Static methods working on {@linkplain CoordinateReferenceSystem Coordinate Reference Systems}.
 * The methods defined in this class can be grouped in three categories:
 *
 * <ul>
 *   <li>Factory methods, the most notable one being {@link #forCode(String)}.</li>
 *   <li>Methods providing information, like {@link #isHorizontalCRS(CoordinateReferenceSystem)}.</li>
 *   <li>Finding coordinate operations between a source and a target CRS.</li>
 * </ul>
 *
 * <div class="section">Usage example</div>
 * The most frequently used methods in this class are {@link #forCode forCode(…)}, {@link #fromWKT fromWKT(…)}
 * and {@link #findOperation findOperation(…)}. An usage example is like below
 * (see the <a href="http://sis.apache.org/tables/CoordinateReferenceSystems.html">Apache SIS™ Coordinate
 * Reference System (CRS) codes</a> page for the complete list of EPSG codes):
 *
 * {@preformat java
 *   CoordinateReferenceSystem source = CRS.forCode("EPSG:4326");                   // WGS 84
 *   CoordinateReferenceSystem target = CRS.forCode("EPSG:3395");                   // WGS 84 / World Mercator
 *   CoordinateOperation operation = CRS.findOperation(source, target, null);
 *   if (CRS.getLinearAccuracy(operation) > 100) {
 *       // If the accuracy is coarser than 100 metres (or any other threshold at application choice)
 *       // maybe the operation is not suitable. Decide here what to do (throw an exception, etc).
 *   }
 *   MathTransform mt = operation.getMathTransform();
 *   DirectPosition position = new DirectPosition2D(20, 30);            // 20°N 30°E   (watch out axis order!)
 *   position = mt.transform(position, position);
 *   System.out.println(position);
 * }
 *
 * <div class="section">Note on kinds of CRS</div>
 * The {@link #getSingleComponents(CoordinateReferenceSystem)} method decomposes an arbitrary CRS into a flat
 * list of single components. In such flat list, vertical and temporal components can easily be identified by
 * {@code instanceof} checks. But identifying the horizontal component is not as easy. The list below suggests
 * ways to classify the components:
 *
 * <ul>
 *   <li><code>if (crs instanceof TemporalCRS)</code> determines if the CRS is for the temporal component.</li>
 *   <li><code>if (crs instanceof VerticalCRS)</code> determines if the CRS is for the vertical component.</li>
 *   <li><code>if (CRS.{@linkplain #isHorizontalCRS(CoordinateReferenceSystem) isHorizontalCRS}(crs))</code>
 *       determines if the CRS is for the horizontal component.</li>
 * </ul>
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @author  Alexis Manin (Geomatys)
 * @version 1.1
 * @since   0.3
 * @module
 */
public final class CRS extends Static {
    /**
     * Do not allow instantiation of this class.
     */
    private CRS() {
    }

    /**
     * Returns the Coordinate Reference System for the given authority code.
     * The set of available codes depends on the {@link CRSAuthorityFactory} instances available on the classpath.
     * There is many thousands of <a href="http://sis.apache.org/tables/CoordinateReferenceSystems.html">CRS
     * defined by EPSG authority or by other authorities</a>.
     * The following table lists a very small subset of codes which are guaranteed to be available
     * on any installation of Apache SIS:
     *
     * <blockquote><table class="sis">
     *   <caption>Minimal set of supported authority codes</caption>
     *   <tr><th>Code</th>      <th>Enum</th>                            <th>CRS Type</th>        <th>Description</th></tr>
     *   <tr><td>CRS:27</td>    <td>{@link CommonCRS#NAD27  NAD27}</td>  <td>Geographic</td>      <td>Like EPSG:4267 except for (<var>longitude</var>, <var>latitude</var>) axis order</td></tr>
     *   <tr><td>CRS:83</td>    <td>{@link CommonCRS#NAD83  NAD83}</td>  <td>Geographic</td>      <td>Like EPSG:4269 except for (<var>longitude</var>, <var>latitude</var>) axis order</td></tr>
     *   <tr><td>CRS:84</td>    <td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Geographic</td>      <td>Like EPSG:4326 except for (<var>longitude</var>, <var>latitude</var>) axis order</td></tr>
     *   <tr><td>EPSG:4047</td> <td>{@link CommonCRS#SPHERE SPHERE}</td> <td>Geographic</td>      <td>GRS 1980 Authalic Sphere</td></tr>
     *   <tr><td>EPSG:4230</td> <td>{@link CommonCRS#ED50   ED50}</td>   <td>Geographic</td>      <td>European Datum 1950</td></tr>
     *   <tr><td>EPSG:4258</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> <td>Geographic</td>      <td>European Terrestrial Reference Frame 1989</td></tr>
     *   <tr><td>EPSG:4267</td> <td>{@link CommonCRS#NAD27  NAD27}</td>  <td>Geographic</td>      <td>North American Datum 1927</td></tr>
     *   <tr><td>EPSG:4269</td> <td>{@link CommonCRS#NAD83  NAD83}</td>  <td>Geographic</td>      <td>North American Datum 1983</td></tr>
     *   <tr><td>EPSG:4322</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  <td>Geographic</td>      <td>World Geodetic System 1972</td></tr>
     *   <tr><td>EPSG:4326</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Geographic</td>      <td>World Geodetic System 1984</td></tr>
     *   <tr><td>EPSG:4936</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> <td>Geocentric</td>      <td>European Terrestrial Reference Frame 1989</td></tr>
     *   <tr><td>EPSG:4937</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> <td>Geographic 3D</td>   <td>European Terrestrial Reference Frame 1989</td></tr>
     *   <tr><td>EPSG:4978</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Geocentric</td>      <td>World Geodetic System 1984</td></tr>
     *   <tr><td>EPSG:4979</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Geographic 3D</td>   <td>World Geodetic System 1984</td></tr>
     *   <tr><td>EPSG:4984</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  <td>Geocentric</td>      <td>World Geodetic System 1972</td></tr>
     *   <tr><td>EPSG:4985</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  <td>Geographic 3D</td>   <td>World Geodetic System 1972</td></tr>
     *   <tr><td>EPSG:5041</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Projected</td>       <td>WGS 84 / UPS North (E,N)</td></tr>
     *   <tr><td>EPSG:5042</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Projected</td>       <td>WGS 84 / UPS South (E,N)</td></tr>
     *   <tr><td>EPSG:322##</td><td>{@link CommonCRS#WGS72  WGS72}</td>  <td>Projected</td>       <td>WGS 72 / UTM zone ##N</td></tr>
     *   <tr><td>EPSG:323##</td><td>{@link CommonCRS#WGS72  WGS72}</td>  <td>Projected</td>       <td>WGS 72 / UTM zone ##S</td></tr>
     *   <tr><td>EPSG:326##</td><td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Projected</td>       <td>WGS 84 / UTM zone ##N</td></tr>
     *   <tr><td>EPSG:327##</td><td>{@link CommonCRS#WGS84  WGS84}</td>  <td>Projected</td>       <td>WGS 84 / UTM zone ##S</td></tr>
     *   <tr><td>EPSG:5715</td> <td>{@link CommonCRS.Vertical#DEPTH DEPTH}</td> <td>Vertical</td> <td>Mean Sea Level depth</td></tr>
     *   <tr><td>EPSG:5714</td> <td>{@link CommonCRS.Vertical#MEAN_SEA_LEVEL MEAN_SEA_LEVEL}</td> <td>Vertical</td> <td>Mean Sea Level height</td></tr>
     * </table></blockquote>
     *
     * This method accepts also the URN and URL syntaxes.
     * For example the following codes are considered equivalent to {@code "EPSG:4326"}:
     * <ul>
     *   <li>{@code "EPSG::4326"}</li>
     *   <li>{@code "urn:ogc:def:crs:EPSG::4326"}</li>
     *   <li>{@code "http://www.opengis.net/def/crs/epsg/0/4326"}</li>
     *   <li>{@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}</li>
     * </ul>
     *
     * URIs can be combined for creating larger objects. For example the following URIs combine a
     * two-dimensional WGS84 reference system (EPSG:4326) with a Mean Sea Level height (EPSG:5714).
     * The result is a three-dimensional {@linkplain org.apache.sis.referencing.crs.DefaultCompoundCRS
     * compound coordinate reference system}:
     *
     * <ul>
     *   <li>{@code "urn:ogc:def:crs,crs:EPSG::4326,crs:EPSG::5714"}</li>
     *   <li><code>"http://www.opengis.net/def/crs-compound?<br>
     *            1=http://www.opengis.net/def/crs/epsg/0/4326&amp;<br>
     *            2=http://www.opengis.net/def/crs/epsg/0/5714"</code></li>
     * </ul>
     *
     * <p>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}.</p>
     *
     * Note that the {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)}
     * method can be seen as a converse of this method.
     * More codes may also be supported depending on which extension modules are available.
     * See for example the {@linkplain org.apache.sis.storage.gdal bindings to Proj.4 library}.
     *
     * @param  code  the authority code.
     * @return the Coordinate Reference System for the given authority code.
     * @throws NoSuchAuthorityCodeException if there is no known CRS associated to the given code.
     * @throws FactoryException if the CRS creation failed for an other reason.
     *
     * @see #getAuthorityFactory(String)
     * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory
     * @see <a href="http://epsg-registry.org/">EPSG Geodetic Registry</a>
     *
     * @category factory
     */
    public static CoordinateReferenceSystem forCode(final String code)
            throws NoSuchAuthorityCodeException, FactoryException
    {
        ArgumentChecks.ensureNonNull("code", code);
        try {
            return AuthorityFactories.ALL.createCoordinateReferenceSystem(code);
        } catch (UnavailableFactoryException e) {
            return AuthorityFactories.fallback(e).createCoordinateReferenceSystem(code);
        }
    }

    /**
     * Creates a Coordinate Reference System object from a <cite>Well Known Text</cite> (WKT).
     * The default {@linkplain org.apache.sis.io.wkt Apache SIS parser} understands both
     * version 1 (a.k.a. OGC 01-009) and version 2 (a.k.a. ISO 19162) of the WKT format.
     *
     * <div class="note"><b>Example:</b> below is a slightly simplified WKT 2 string for a Mercator projection.
     * For making this example smaller, some optional {@code UNIT[…]} and {@code ORDER[…]} elements have been omitted.
     *
     * {@preformat wkt
     *   ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
     *     BaseGeodCRS["SIRGAS 2000",
     *       Datum["Sistema de Referencia Geocentrico para las Americas 2000",
     *         Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
     *     Conversion["Petrobras Mercator",
     *       Method["Mercator (variant B)", Id["EPSG",9805]],
     *       Parameter["Latitude of 1st standard parallel", -2],
     *       Parameter["Longitude of natural origin", -43],
     *       Parameter["False easting", 5000000],
     *       Parameter["False northing", 10000000]],
     *     CS[cartesian,2],
     *       Axis["easting (E)", east],
     *       Axis["northing (N)", north],
     *       LengthUnit["metre", 1],
     *     Id["EPSG",5641]]
     * }
     * </div>
     *
     * If the parsing produced warnings, they will be reported in a logger named {@code "org.apache.sis.io.wkt"}.
     * In particular, this method verifies if the description provided by the WKT matches the description provided
     * by the authority ({@code "EPSG:5641"} in above example) and reports discrepancies.
     * Note that this comparison between parsed CRS and authoritative CRS is specific to this convenience method;
     * other APIs documented in <cite>see also</cite> section do not perform this comparison automatically.
     * Should the WKT description and the authoritative description be in conflict, the WKT description prevails
     * as mandated by ISO 19162 standard (see {@link #fromAuthority fromAuthority(…)} if a different behavior is needed).
     *
     * <div class="section">Usage and performance considerations</div>
     * This convenience method delegates to
     * {@link org.apache.sis.referencing.factory.GeodeticObjectFactory#createFromWKT(String)}
     * using a default factory instance. This is okay for occasional use, but has the following limitations:
     *
     * <ul>
     *   <li>Performance may be sub-optimal in a multi-thread environment.</li>
     *   <li>No control on the WKT {@linkplain org.apache.sis.io.wkt.Convention conventions} in use.</li>
     *   <li>No control on the handling of {@linkplain org.apache.sis.io.wkt.Warnings warnings}.</li>
     * </ul>
     *
     * Applications which need to parse a large amount of WKT strings should consider to use
     * the {@link org.apache.sis.io.wkt.WKTFormat} class instead than this method.
     *
     * @param  text  coordinate system encoded in Well-Known Text format (version 1 or 2).
     * @return the parsed Coordinate Reference System.
     * @throws FactoryException if the given WKT can not be parsed.
     *
     * @see org.apache.sis.io.wkt.WKTFormat
     * @see org.apache.sis.referencing.factory.GeodeticObjectFactory#createFromWKT(String)
     * @see org.apache.sis.geometry.Envelopes#fromWKT(CharSequence)
     * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a>
     *
     * @since 0.6
     */
    public static CoordinateReferenceSystem fromWKT(final String text) throws FactoryException {
        ArgumentChecks.ensureNonNull("text", text);
        final CoordinateReferenceSystem crs = DefaultFactories.forBuildin(CRSFactory.class).createFromWKT(text);
        DefinitionVerifier.withAuthority(crs, Loggers.WKT, CRS.class, "fromWKT");
        return crs;
    }

    /**
     * Creates a coordinate reference system object from a XML string.
     * Note that the given argument is the XML document itself, <strong>not</strong> a URL to a XML document.
     * For reading XML documents from readers or input streams,
     * see static methods in the {@link org.apache.sis.xml.XML} class.
     *
     * <p>If the unmarshalling produced warnings, they will be reported in a logger named {@code "org.apache.sis.xml"}.
     * In particular, this method verifies if the description provided by the XML matches the description provided by
     * the authority code given in {@code <gml:identifier>} element, and reports discrepancies.
     * Note that this comparison between unmarshalled CRS and authoritative CRS is specific to this convenience method;
     * other APIs documented in <cite>see also</cite> section do not perform this comparison automatically.
     * Should the XML description and the authoritative description be in conflict, the XML description prevails
     * (see {@link #fromAuthority fromAuthority(…)} if a different behavior is needed).</p>
     *
     * @param  xml  coordinate reference system encoded in XML format.
     * @return the unmarshalled Coordinate Reference System.
     * @throws FactoryException if the object creation failed.
     *
     * @see org.apache.sis.referencing.factory.GeodeticObjectFactory#createFromXML(String)
     * @see org.apache.sis.xml.XML#unmarshal(String)
     *
     * @since 0.7
     */
    public static CoordinateReferenceSystem fromXML(final String xml) throws FactoryException {
        ArgumentChecks.ensureNonNull("text", xml);
        final CoordinateReferenceSystem crs = DefaultFactories.forBuildin(CRSFactory.class).createFromXML(xml);
        DefinitionVerifier.withAuthority(crs, Loggers.XML, CRS.class, "fromXML");
        return crs;
    }

    /**
     * Replaces the given coordinate reference system by an authoritative description, if one can be found.
     * This method can be invoked after constructing a CRS in a context where the EPSG (or other authority)
     * code is suspected more reliable than the rest of the description. A common case is a <cite>Well Known
     * Text</cite> (WKT) string declaring wrong projection method or parameter values for the EPSG code that
     * it pretends to describe. For example:
     *
     * <blockquote>
     *   {@code PROJCS["WGS 84 / Pseudo-Mercator",}<br>
     *   {@code   }(…base CRS omitted for brevity…)<br>
     *   {@code   PROJECTION["Mercator (variant A)"],} — <em><b>wrong:</b> shall be "Popular Visualisation Pseudo Mercator"</em><br>
     *   {@code   }(…parameters and axes omitted for brevity…)<br>
     *   {@code   AUTHORITY["EPSG", "3857"]]}
     * </blockquote>
     *
     * In such cases, Apache SIS behavior in {@link #fromWKT(String)}, {@link #fromXML(String)} and other methods is
     * conform to the <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">ISO 19162 specification</a>:
     *
     * <blockquote><cite>"Should any attributes or values given in the cited identifier be in conflict with attributes
     * or values given explicitly in the WKT description, the WKT values shall prevail."</cite></blockquote>
     *
     * In situations where the opposite behavior is desired (i.e. to make the authority identifier prevails),
     * this method can be invoked. This method performs the following actions:
     *
     * <ul>
     *   <li>If the given CRS has an {@linkplain AbstractIdentifiedObject#getIdentifiers() identifier} and if the authority factory can
     *     {@linkplain org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCoordinateReferenceSystem(String) create a CRS}
     *     for that identifier, then:
     *     <ul>
     *       <li>If the CRS defined by the authority is {@linkplain Utilities#equalsIgnoreMetadata equal, ignoring metadata},
     *         to the given CRS, then this method returns silently the <em>authoritative</em> CRS.</li>
     *       <li>Otherwise if the CRS defined by the authority is equal, ignoring axis order and units, to the given CRS,
     *         then this method returns a <em>new</em> CRS derived from the authoritative one but with same
     *         {@linkplain org.apache.sis.referencing.cs.AxesConvention axes convention} than the given CRS.
     *         A warning is emitted.</li>
     *       <li>Otherwise this method discards the given CRS and returns the <em>authoritative</em> CRS.
     *         A warning is emitted with a message indicating where a difference has been found.</li>
     *     </ul>
     *   </li>
     *   <li>Otherwise if the given CRS does not have identifier, then this method
     *       {@linkplain org.apache.sis.referencing.factory.IdentifiedObjectFinder searches for an equivalent CRS}
     *       defined by the authority factory. If such CRS is found, then:
     *     <ul>
     *       <li>If the CRS defined by the authority is {@linkplain Utilities#equalsIgnoreMetadata equal, ignoring metadata},
     *         to the given CRS, then this method returns silently the <em>authoritative</em> CRS.</li>
     *       <li>Otherwise if the CRS defined by the authority is equal, ignoring axis order and units, to the given CRS,
     *         then this method returns silently a <em>new</em> CRS derived from the authoritative one but with same
     *         {@linkplain org.apache.sis.referencing.cs.AxesConvention axes convention} than the given CRS.</li>
     *     </ul>
     *   </li>
     *   <li>Otherwise this method silently returns the given CRS as-is.</li>
     * </ul>
     *
     * <div class="section">Avoiding warning redundancies</div>
     * The warnings logged by this method are redundant with warnings logged by other methods in this class,
     * in particular {@link #fromWKT(String)} and {@link #fromXML(String)} methods. For avoiding this annoyance,
     * a {@code null} value for the {@code warningFilter} argument means to shut off those redundant loggings.
     * A non-null {@code warningFilter} argument is more useful for CRS parsed by methods outside this class,
     * for example {@link org.apache.sis.io.wkt.WKTFormat} or {@link org.apache.sis.xml.XML#unmarshal(String)}.
     *
     * @param  crs            the CRS to replace by an authoritative CRS, or {@code null}.
     * @param  factory        the factory where to search for authoritative definitions, or {@code null} for the default.
     * @param  warningFilter  whether to log warnings, or {@code null} for the default behavior (which is to filter out
     *                        the warnings that are redundant with warnings emitted by other methods in this class).
     * @return the suggested CRS to use (may be the {@code crs} argument itself), or {@code null} if the given CRS was null.
     * @throws FactoryException if an error occurred while querying the authority factory.
     *
     * @since 1.0
     */
    public static CoordinateReferenceSystem fromAuthority(CoordinateReferenceSystem crs,
            final CRSAuthorityFactory factory, final Filter warningFilter) throws FactoryException
    {
        if (crs != null) {
            final DefinitionVerifier verification = DefinitionVerifier.withAuthority(crs, factory, true);
            if (verification != null) {
                crs = verification.authoritative;
                if (warningFilter != null) {
                    final LogRecord record = verification.warning(false);
                    if (record != null) {
                        record.setLoggerName(Modules.REFERENCING);
                        record.setSourceClassName(CRS.class.getName());
                        record.setSourceMethodName("fromAuthority");
                        if (warningFilter.isLoggable(record)) {
                            Logging.getLogger(Modules.REFERENCING).log(record);
                        }
                    }
                }
            }
        }
        return crs;
    }

    /**
     * Suggests a coordinate reference system which could be a common target for coordinate operations having the
     * given sources. This method compares the {@linkplain #getGeographicBoundingBox(CoordinateReferenceSystem)
     * domain of validity} of all given CRSs. If a CRS has a domain of validity that contains the domain of all other
     * CRS, then that CRS is returned. Otherwise this method verifies if a {@linkplain GeneralDerivedCRS#getBaseCRS()
     * base CRS} (usually a {@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS geographic CRS} instance)
     * would be suitable. If no suitable CRS is found, then this method returns {@code null}.
     *
     * <div class="note"><b>Use case:</b>
     * before to test if two arbitrary envelopes {@linkplain GeneralEnvelope#intersects(Envelope) intersect} each other,
     * they need to be {@linkplain Envelopes#transform(Envelope, CoordinateReferenceSystem) transformed} in the same CRS.
     * However if one CRS is a Transverse Mercator projection while the other CRS is a world-wide geographic CRS, then
     * attempts to use the Transverse Mercator projection as the common CRS is likely to fail since the geographic envelope
     * may span an area far outside the projection domain of validity. This {@code suggestCommonTarget(…)} method can used
     * for choosing a common CRS which is less likely to fail.</div>
     *
     * @param  regionOfInterest  the geographic area for which the coordinate operations will be applied,
     *                           or {@code null} if unknown. Will be intersected with CRS domains of validity.
     * @param  sourceCRS         the coordinate reference systems for which a common target CRS is desired.
     *                           May contain {@code null} elements, which are ignored.
     * @return a CRS that may be used as a common target for all the given source CRS in the given region of interest,
     *         or {@code null} if this method did not find a common target CRS. The returned CRS may be different than
     *         all given CRS.
     *
     * @since 0.8
     */
    public static CoordinateReferenceSystem suggestCommonTarget(GeographicBoundingBox regionOfInterest,
                                                                CoordinateReferenceSystem... sourceCRS)
    {
        CoordinateReferenceSystem bestCRS = null;
        /*
         * Compute the union of the domain of validity of all CRS. If a CRS does not specify a domain of validity,
         * then assume that the CRS is valid for the whole world if the CRS is geodetic (otherwise ignore that CRS).
         * Opportunistically remember the domain of validity of each CRS in this loop since we will need them later.
         */
        boolean worldwide = false;
        DefaultGeographicBoundingBox domain = null;
        final GeographicBoundingBox[] domains = new GeographicBoundingBox[sourceCRS.length];
        for (int i=0; i < sourceCRS.length; i++) {
            final CoordinateReferenceSystem crs = sourceCRS[i];
            final GeographicBoundingBox bbox = getGeographicBoundingBox(crs);
            if (bbox != null) {
                domains[i] = bbox;
                if (!worldwide) {
                    if (domain == null) {
                        domain = new DefaultGeographicBoundingBox(bbox);
                    } else {
                        domain.add(bbox);
                    }
                }
            } else if (crs instanceof GeodeticCRS) {
                /*
                 * Geodetic CRS (geographic or geocentric) can generally be presumed valid in a worldwide area.
                 * The 'worldwide' flag is a little optimization for remembering that we do not need to compute
                 * the union anymore, but we still need to continue the loop for fetching all bounding boxes.
                 */
                bestCRS = crs;                      // Fallback to be used if we don't find anything better.
                worldwide = true;
            }
        }
        /*
         * At this point we got the union of the domain of validity of all CRS. We are interested only in the
         * part that intersect the region of interest. If the union is whole world, we do not need to compute
         * the intersection; we can just leave the region of interest unchanged.
         */
        if (domain != null && !worldwide) {
            if (regionOfInterest != null) {
                domain.intersect(regionOfInterest);
            }
            regionOfInterest = domain;
            domain = null;
        }
        /*
         * Iterate again over the domain of validity of all CRS.  For each domain of validity, compute the area
         * which is inside the domain or interest and the area which is outside. The "best CRS" will be the one
         * which comply with the following rules, in preference order:
         *
         *   1) The CRS which is valid over the largest area of the region of interest.
         *   2) If two CRS are equally good according rule 1, then the CRS with the smallest "outside area".
         *
         * Example: given two source CRS, a geographic one and a projected one:
         *
         *   - If the projected CRS contains fully the region of interest, then it will be returned.
         *     The preference is given to the projected CRS because geometric operations are likely
         *     to be more accurate in that space. Furthermore forward conversions from geographic to
         *     projected CRS are usually faster than inverse conversions.
         *
         *   - Otherwise (i.e. if the region of interest is likely to be wider than the projected CRS
         *     domain of validity), then the geographic CRS will be returned.
         */
        final double roiArea  = Extents.area(regionOfInterest);   // NaN if 'regionOfInterest' is null.
        double maxInsideArea  = 0;
        double minOutsideArea = Double.POSITIVE_INFINITY;
        boolean tryDerivedCRS = false;
        do {
            for (int i=0; i < domains.length; i++) {
                final GeographicBoundingBox bbox = domains[i];
                if (bbox != null) {
                    double insideArea  = Extents.area(bbox);
                    double outsideArea = 0;
                    if (regionOfInterest != null) {
                        if (domain == null) {
                            domain = new DefaultGeographicBoundingBox(bbox);
                        } else {
                            domain.setBounds(bbox);
                        }
                        domain.intersect(regionOfInterest);
                        final double area = insideArea;
                        insideArea = Extents.area(domain);
                        outsideArea = area - insideArea;
                    }
                    if (insideArea > maxInsideArea || (insideArea == maxInsideArea && outsideArea < minOutsideArea)) {
                        maxInsideArea  = insideArea;
                        minOutsideArea = outsideArea;
                        bestCRS        = sourceCRS[i];
                    }
                }
            }
            /*
             * If the best CRS does not cover fully the region of interest, then we will redo the check again
             * but using base CRS instead. For example if the list of source CRS had some projected CRS, we
             * will try with the geographic CRS on which those projected CRS are based.
             */
            if (Double.isNaN(roiArea) || maxInsideArea < roiArea) {
                if (tryDerivedCRS) break;                                               // Do not try twice.
                final CoordinateReferenceSystem[] derivedCRS = new CoordinateReferenceSystem[sourceCRS.length];
                for (int i=0; i < derivedCRS.length; i++) {
                    GeographicBoundingBox bbox = null;
                    final CoordinateReferenceSystem crs = sourceCRS[i];
                    if (crs instanceof GeneralDerivedCRS) {
                        final CoordinateReferenceSystem baseCRS = ((GeneralDerivedCRS) crs).getBaseCRS();
                        bbox = getGeographicBoundingBox(baseCRS);
                        if (bbox == null && bestCRS == null && baseCRS instanceof GeodeticCRS) {
                            bestCRS = baseCRS;      // Fallback to be used if we don't find anything better.
                        }
                        tryDerivedCRS = true;
                        derivedCRS[i] = baseCRS;
                    }
                    domains[i] = bbox;
                }
                sourceCRS = derivedCRS;
            } else {
                break;
            }
        } while (tryDerivedCRS);
        return bestCRS;
    }

    /**
     * Finds a mathematical operation that transforms or converts coordinates from the given source to the
     * given target coordinate reference system. If an estimation of the geographic area containing the points
     * to transform is known, it can be specified for helping this method to find a better suited operation.
     * If no area of interest is specified, then the current default is the widest
     * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}.
     * A future Apache SIS version may also take the country of current locale in account.
     *
     * <div class="note"><b>Note:</b>
     * the area of interest is just one aspect that may affect the coordinate operation.
     * Other aspects are the time of interest (because some coordinate operations take in account the
     * plate tectonics movement) or the desired accuracy. For more control on the coordinate operation
     * to create, see {@link CoordinateOperationContext}.</div>
     *
     * After the caller received a {@code CoordinateOperation} instance, the following methods can be invoked
     * for checking if the operation suits the caller's needs:
     *
     * <ul>
     *   <li>{@link #getGeographicBoundingBox(CoordinateOperation)}
     *       for checking if the operation is valid in the caller's area of interest.</li>
     *   <li>{@link #getLinearAccuracy(CoordinateOperation)}
     *       for checking if the operation has sufficient accuracy for caller's purpose.</li>
     * </ul>
     *
     * If the source and target CRS are equivalent, then this method returns an operation backed by an
     * {@linkplain org.apache.sis.referencing.operation.transform.AbstractMathTransform#isIdentity() identity}
     * transform. If there is no known operation between the given pair of CRS, then this method throws an
     * {@link OperationNotFoundException}.
     *
     * @param  sourceCRS       the CRS of source coordinates.
     * @param  targetCRS       the CRS of target coordinates.
     * @param  areaOfInterest  the area of interest, or {@code null} if none.
     * @return the mathematical operation from {@code sourceCRS} to {@code targetCRS}.
     * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
     * @throws FactoryException if the operation can not be created for another reason.
     *
     * @see Envelopes#findOperation(Envelope, Envelope)
     * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
     *
     * @since 0.7
     */
    public static CoordinateOperation findOperation(final CoordinateReferenceSystem sourceCRS,
                                                    final CoordinateReferenceSystem targetCRS,
                                                    final GeographicBoundingBox areaOfInterest)
            throws FactoryException
    {
        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
        final CoordinateOperationContext context = CoordinateOperationContext.fromBoundingBox(areaOfInterest);
        /*
         * In principle following code should just delegate to factory.createOperation(…). However that operation
         * may fail if a connection to the EPSG database has been found, but the EPSG tables do not yet exist in
         * that database and we do not have the SQL scripts for creating them.
         */
        final DefaultCoordinateOperationFactory factory = CoordinateOperations.factory();
        try {
            return factory.createOperation(sourceCRS, targetCRS, context);
        } catch (UnavailableFactoryException e) {
            if (AuthorityFactories.failure(e)) {
                throw e;
            } else try {
                // Above method call replaced the EPSG factory by a fallback. Try again.
                return factory.createOperation(sourceCRS, targetCRS, context);
            } catch (FactoryException ex) {
                ex.addSuppressed(e);
                throw ex;
            }
        }
    }

    /**
     * Finds mathematical operations that transform or convert coordinates from the given source to the
     * given target coordinate reference system. If at least one operation exists, they are returned in
     * preference order: the operation having the widest intersection between its
     * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
     * and the given area of interest are returned first.
     *
     * @param  sourceCRS       the CRS of source coordinates.
     * @param  targetCRS       the CRS of target coordinates.
     * @param  areaOfInterest  the area of interest, or {@code null} if none.
     * @return mathematical operations from {@code sourceCRS} to {@code targetCRS}.
     * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
     * @throws FactoryException if the operation can not be created for another reason.
     *
     * @see DefaultCoordinateOperationFactory#createOperations(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
     *
     * @since 1.0
     */
    public static List<CoordinateOperation> findOperations(final CoordinateReferenceSystem sourceCRS,
                                                           final CoordinateReferenceSystem targetCRS,
                                                           final GeographicBoundingBox areaOfInterest)
            throws FactoryException
    {
        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
        final CoordinateOperationContext context = CoordinateOperationContext.fromBoundingBox(areaOfInterest);
        final DefaultCoordinateOperationFactory factory = CoordinateOperations.factory();
        try {
            return factory.createOperations(sourceCRS, targetCRS, context);
        } catch (UnavailableFactoryException e) {
            if (AuthorityFactories.failure(e)) {
                throw e;
            } else try {
                return Collections.singletonList(factory.createOperation(sourceCRS, targetCRS, context));
            } catch (FactoryException ex) {
                ex.addSuppressed(e);
                throw ex;
            }
        }
    }

    /**
     * Returns a positional accuracy estimation in metres for the given operation, or {@code NaN} if unknown.
     * This method applies the following heuristics:
     *
     * <ul>
     *   <li>If the given operation is an instance of {@link AbstractCoordinateOperation}, then delegate to the
     *       operation {@link AbstractCoordinateOperation#getLinearAccuracy() getLinearAccuracy()} method.</li>
     *
     *   <li>Otherwise if at least one {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult
     *       quantitative result} is found with a linear unit, then return the largest value converted to metres.</li>
     *
     *   <li>Otherwise if the operation is a {@linkplain org.apache.sis.referencing.operation.DefaultConversion
     *       conversion}, then returns 0 since a conversion is by definition accurate up to rounding errors.</li>
     *
     *   <li>Otherwise if the operation is a {@linkplain org.apache.sis.referencing.operation.DefaultTransformation
     *       transformation}, then the returned value depends on whether the datum shift were applied with the help
     *       of Bursa-Wolf parameters of not.</li>
     * </ul>
     *
     * See {@link AbstractCoordinateOperation#getLinearAccuracy()} for more details on the above heuristic rules.
     *
     * @param  operation  the coordinate operation for which to get the accuracy estimation, or {@code null}.
     * @return the accuracy estimation (always in meters), or NaN if unknown.
     *
     * @see #findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
     *
     * @since 0.7
     */
    public static double getLinearAccuracy(final CoordinateOperation operation) {
        if (operation == null) {
            return Double.NaN;
        } else if (operation instanceof AbstractCoordinateOperation) {
            return ((AbstractCoordinateOperation) operation).getLinearAccuracy();
        } else {
            return PositionalAccuracyConstant.getLinearAccuracy(operation);
        }
    }

    /**
     * Returns the valid geographic area for the given coordinate operation, or {@code null} if unknown.
     * This method explores the {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
     * associated with the given operation. If more than one geographic bounding box is found, then this method
     * computes their {@linkplain DefaultGeographicBoundingBox#add(GeographicBoundingBox) union}.
     *
     * <p><b>Fallback:</b> if the given operation does not declare explicitly a domain of validity, then this
     * method computes the intersection of the domain of validity declared by source and target CRS. If no CRS
     * declare a domain of validity, then this method returns {@code null}.</p>
     *
     * @param  operation  the coordinate operation for which to get the domain of validity, or {@code null}.
     * @return the geographic area where the operation is valid, or {@code null} if unspecified.
     *
     * @see #findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
     * @see Extents#getGeographicBoundingBox(Extent)
     *
     * @category information
     *
     * @since 0.7
     */
    public static GeographicBoundingBox getGeographicBoundingBox(final CoordinateOperation operation) {
        if (operation == null) {
            return null;
        }
        GeographicBoundingBox bbox = Extents.getGeographicBoundingBox(operation.getDomainOfValidity());
        if (bbox == null) {
            bbox = Extents.intersection(getGeographicBoundingBox(operation.getSourceCRS()),
                                        getGeographicBoundingBox(operation.getTargetCRS()));
        }
        return bbox;
    }

    /**
     * Returns the valid geographic area for the given coordinate reference system, or {@code null} if unknown.
     * This method explores the {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of
     * validity} associated with the given CRS. If more than one geographic bounding box is found, then this method
     * computes their {@linkplain DefaultGeographicBoundingBox#add(GeographicBoundingBox) union}.
     * together.
     *
     * @param  crs  the coordinate reference system for which to get the domain of validity, or {@code null}.
     * @return the geographic area where the coordinate reference system is valid, or {@code null} if unspecified.
     *
     * @see #getDomainOfValidity(CoordinateReferenceSystem)
     * @see Extents#getGeographicBoundingBox(Extent)
     *
     * @category information
     */
    public static GeographicBoundingBox getGeographicBoundingBox(final CoordinateReferenceSystem crs) {
        return (crs != null) ? Extents.getGeographicBoundingBox(crs.getDomainOfValidity()) : null;
    }

    /**
     * Returns the domain of validity of the specified coordinate reference system, or {@code null} if unknown.
     * If non-null, then the returned envelope will use the same coordinate reference system them the given CRS
     * argument.
     *
     * @param  crs  the coordinate reference system, or {@code null}.
     * @return the envelope with coordinates in the given CRS, or {@code null} if none.
     *
     * @see #getGeographicBoundingBox(CoordinateReferenceSystem)
     *
     * @category information
     * @since 0.8
     */
    public static Envelope getDomainOfValidity(final CoordinateReferenceSystem crs) {
        Envelope envelope = null;
        GeneralEnvelope merged = null;
        /* if (envelope == null) */ {   // Condition needed on other branches but not on trunk.
            final GeographicBoundingBox bounds = getGeographicBoundingBox(crs);
            if (bounds != null && !Boolean.FALSE.equals(bounds.getInclusion())) {
                /*
                 * We do not assign WGS84 unconditionally to the geographic bounding box, because
                 * it is not defined to be on a particular datum; it is only approximated bounds.
                 * We try to get the GeographicCRS from the user-supplied CRS in order to reduce
                 * the amount of transformation needed.
                 */
                final SingleCRS targetCRS = getHorizontalComponent(crs);
                final GeographicCRS sourceCRS = ReferencingUtilities.toNormalizedGeographicCRS(targetCRS, false, false);
                if (sourceCRS != null) {
                    envelope = merged = new GeneralEnvelope(bounds);
                    merged.translate(-getGreenwichLongitude(sourceCRS), 0);
                    merged.setCoordinateReferenceSystem(sourceCRS);
                    try {
                        envelope = Envelopes.transform(envelope, targetCRS);
                    } catch (TransformException exception) {
                        /*
                         * The envelope is probably outside the range of validity for this CRS.
                         * It should not occurs, since the envelope is supposed to describe the
                         * CRS area of validity. Logs a warning and returns null, since it is a
                         * legal return value according this method contract.
                         */
                        unexpectedException("getEnvelope", exception);
                        envelope = null;
                    }
                }
            }
        }
        return envelope;
    }

    /**
     * Creates a compound coordinate reference system from an ordered list of CRS components.
     * A CRS is inferred from the given components and the domain of validity is set to the
     * {@linkplain org.apache.sis.metadata.iso.extent.DefaultExtent#intersect intersection}
     * of the domain of validity of all components.
     *
     * <div class="section">Ellipsoidal height</div>
     * If a two-dimensional geographic or projected CRS if followed or preceded by a vertical CRS with ellipsoidal
     * {@linkplain org.apache.sis.referencing.datum.DefaultVerticalDatum#getVerticalDatumType() datum type}, then
     * this method combines them in a single three-dimensional geographic or projected CRS.  Note that standalone
     * ellipsoidal heights are not allowed according ISO 19111. But if such situation is nevertheless found, then
     * the action described here fixes the issue. This is the reverse of <code>{@linkplain #getVerticalComponent
     * getVerticalComponent}(crs, true)</code>.
     *
     * <div class="section">Components order</div>
     * Apache SIS is permissive on the order of components that can be used in a compound CRS.
     * However for better inter-operability, users are encouraged to follow the order mandated by ISO 19162:
     *
     * <ol>
     *   <li>A mandatory horizontal CRS (only one of two-dimensional {@code GeographicCRS} or {@code ProjectedCRS} or {@code EngineeringCRS}).</li>
     *   <li>Optionally followed by a {@code VerticalCRS} or a {@code ParametricCRS} (but not both).</li>
     *   <li>Optionally followed by a {@code TemporalCRS}.</li>
     * </ol>
     *
     * @param  components  the sequence of coordinate reference systems making the compound CRS.
     * @return the compound CRS, or {@code components[0]} if the given array contains only one component.
     * @throws IllegalArgumentException if the given array is empty or if the array contains incompatible components.
     * @throws FactoryException if the geodetic factory failed to create the compound CRS.
     *
     * @since 0.8
     *
     * @see org.apache.sis.referencing.crs.DefaultCompoundCRS
     * @see GeodeticObjectFactory#createCompoundCRS(Map, CoordinateReferenceSystem...)
     * @see org.apache.sis.geometry.Envelopes#compound(Envelope...)
     * @see org.apache.sis.referencing.operation.transform.MathTransforms#compound(MathTransform...)
     */
    public static CoordinateReferenceSystem compound(final CoordinateReferenceSystem... components) throws FactoryException {
        ArgumentChecks.ensureNonNull("components", components);
        switch (components.length) {
            case 0: {
                throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "components"));
            }
            case 1: {
                final CoordinateReferenceSystem crs = components[0];
                if (crs != null) return crs;
                break;
            }
        }
        return new EllipsoidalHeightCombiner().createCompoundCRS(components);
    }

    /**
     * Gets or creates a coordinate reference system with a subset of the dimensions of the given CRS.
     * This method can be used for dimensionality reduction, but not for changing axis order.
     * The specified dimensions are used as if they were in strictly increasing order without duplicated values.
     *
     * <div class="section">Ellipsoidal height</div>
     * This method can transform a three-dimensional geographic CRS into a two-dimensional geographic CRS.
     * In this aspect, this method is the converse of {@link #compound(CoordinateReferenceSystem...)}.
     * This method can also extract the {@linkplain CommonCRS.Vertical#ELLIPSOIDAL ellipsoidal height}
     * from a three-dimensional geographic CRS, but this is generally not recommended since ellipsoidal
     * heights make little sense without their (<var>latitude</var>, <var>longitude</var>) locations.
     *
     * @param  crs         the CRS to reduce the dimensionality, or {@code null} if none.
     * @param  dimensions  the dimensions to retain. The dimensions will be taken in increasing order, ignoring duplicated values.
     * @return a coordinate reference system for the given dimensions. May be the given {@code crs}, which may be {@code null}.
     * @throws IllegalArgumentException if the given array is empty or if the array contains invalid indices.
     * @throws FactoryException if the geodetic factory failed to create a compound CRS.
     *
     * @see #getComponentAt(CoordinateReferenceSystem, int, int)
     * @see #compound(CoordinateReferenceSystem...)
     *
     * @since 1.0
     */
    public static CoordinateReferenceSystem reduce(final CoordinateReferenceSystem crs, final int... dimensions) throws FactoryException {
        ArgumentChecks.ensureNonNull("dimensions", dimensions);
        if (crs == null) {
            return null;
        }
        final int dimension = ReferencingUtilities.getDimension(crs);
        long selected = 0;
        for (final int d : dimensions) {
            if (d < 0 || d >= dimension) {
                throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, d));
            }
            if (d >= Long.SIZE) {
                throw new IllegalArgumentException(Errors.format(Errors.Keys.ExcessiveNumberOfDimensions_1, d));
            }
            selected |= (1L << d);
        }
        if (selected == 0) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "dimensions"));
        }
        final List<CoordinateReferenceSystem> components = new ArrayList<>(Long.bitCount(selected));
        reduce(0, crs, dimension, selected, components);
        return compound(components.toArray(new CoordinateReferenceSystem[components.size()]));
    }

    /**
     * Adds the components of reduced CRS into the given list.
     * This method may invoke itself recursively for walking through compound CRS.
     *
     * @param  previous    number of dimensions of previous CRS.
     * @param  crs         the CRS for which to select components.
     * @param  dimension   number of dimensions of {@code crs}.
     * @param  selected    bitmask of dimensions to select.
     * @param  addTo       where to add CRS components.
     * @return new bitmask after removal of dimensions of the components added to {@code addTo}.
     */
    private static long reduce(int previous, final CoordinateReferenceSystem crs, int dimension, long selected,
            final List<CoordinateReferenceSystem> addTo) throws FactoryException
    {
        final long current = (Numerics.bitmask(dimension) - 1) << previous;
        final long intersect = selected & current;
        if (intersect != 0) {
            if (intersect == current) {
                addTo.add(crs);
                selected &= ~current;
            } else if (crs instanceof CompoundCRS) {
                for (final CoordinateReferenceSystem component : ((CompoundCRS) crs).getComponents()) {
                    dimension = ReferencingUtilities.getDimension(component);
                    selected = reduce(previous, component, dimension, selected, addTo);
                    if ((selected & current) == 0) break;           // Stop if it would be useless to continue.
                    previous += dimension;
                }
            } else if (dimension == 3 && crs instanceof SingleCRS) {
                final Datum datum = ((SingleCRS) crs).getDatum();
                if (datum instanceof GeodeticDatum) {
                    final boolean isVertical = Long.bitCount(intersect) == 1;               // Presumed for now, verified later.
                    final int verticalDimension = Long.numberOfTrailingZeros((isVertical ? intersect : ~intersect) >>> previous);
                    final CoordinateSystemAxis verticalAxis = crs.getCoordinateSystem().getAxis(verticalDimension);
                    if (AxisDirections.isVertical(verticalAxis.getDirection())) try {
                        addTo.add(new EllipsoidalHeightSeparator((GeodeticDatum) datum).separate((SingleCRS) crs, isVertical));
                        selected &= ~current;
                    } catch (IllegalArgumentException | ClassCastException e) {
                        throw new FactoryException(Resources.format(Resources.Keys.CanNotSeparateCRS_1, crs.getName()));
                    }
                }
            }
        }
        if ((selected & current) != 0) {
            throw new FactoryException(Resources.format(Resources.Keys.CanNotSeparateCRS_1, crs.getName()));
        }
        return selected;
    }

    /**
     * Returns {@code true} if the given CRS is horizontal. The current implementation considers a
     * CRS as horizontal if it is two-dimensional and comply with one of the following conditions:
     *
     * <ul>
     *   <li>is an instance of {@link GeographicCRS} (or an equivalent {@link GeodeticCRS}), or</li>
     *   <li>is an instance of {@link ProjectedCRS}, or</li>
     *   <li>is an instance of {@link EngineeringCRS} (following
     *     <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#111">ISO 19162 §16.1</a>
     *     definition of {@literal <horizontal crs>}).</li>
     * </ul>
     *
     * In case of doubt, this method conservatively returns {@code false}.
     *
     * @todo Future SIS implementation may extend the above conditions list. For example a radar station could
     *       use a polar coordinate system in a <code>DerivedCRS</code> instance based on a projected CRS.
     *       Conversely, a future SIS versions may impose more conditions on <code>EngineeringCRS</code>.
     *       See <a href="http://issues.apache.org/jira/browse/SIS-161">SIS-161</a>.
     *
     * @param  crs  the coordinate reference system, or {@code null}.
     * @return {@code true} if the given CRS is non-null and likely horizontal, or {@code false} otherwise.
     *
     * @see #getHorizontalComponent(CoordinateReferenceSystem)
     *
     * @category information
     */
    public static boolean isHorizontalCRS(final CoordinateReferenceSystem crs) {
        return horizontalCode(crs) == 2;
    }

    /**
     * If the given CRS would qualify as horizontal except for its number of dimensions, returns that number.
     * Otherwise returns 0. The number of dimensions can only be 2 or 3.
     */
    private static int horizontalCode(final CoordinateReferenceSystem crs) {
        /*
         * In order to determine if the CRS is geographic, checking the CoordinateSystem type is more reliable
         * then checking if the CRS implements the GeographicCRS interface.  This is because the GeographicCRS
         * type did not existed in ISO 19111:2007, so a CRS could be standard-compliant without implementing
         * the GeographicCRS interface.
         */
        boolean isEngineering = false;
        final boolean isGeodetic = (crs instanceof GeodeticCRS);
        if (isGeodetic || crs instanceof ProjectedCRS || (isEngineering = (crs instanceof EngineeringCRS))) {
            final CoordinateSystem cs = crs.getCoordinateSystem();
            final int dim = cs.getDimension();
            if ((dim & ~1) == 2 && (!isGeodetic || (cs instanceof EllipsoidalCS))) {
                if (isEngineering) {
                    int n = 0;
                    for (int i=0; i<dim; i++) {
                        if (AxisDirections.isCompass(cs.getAxis(i).getDirection())) n++;
                    }
                    // If we don't have exactly 2 east, north, etc. directions, consider as non-horizontal.
                    if (n != 2) return 0;
                }
                return dim;
            }
        }
        return 0;
    }

    /**
     * Returns the first horizontal coordinate reference system found in the given CRS, or {@code null} if there is
     * none. If the given CRS is already horizontal according {@link #isHorizontalCRS(CoordinateReferenceSystem)},
     * then this method returns it as-is. Otherwise if the given CRS is compound, then this method searches for the
     * first horizontal component in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem)
     * single components list}.
     *
     * <p>In the special case where a three-dimensional geographic or projected CRS is found, this method
     * will create a two-dimensional geographic or projected CRS without the vertical axis.</p>
     *
     * @param  crs  the coordinate reference system, or {@code null}.
     * @return the first horizontal CRS, or {@code null} if none.
     *
     * @category information
     */
    public static SingleCRS getHorizontalComponent(final CoordinateReferenceSystem crs) {
        switch (horizontalCode(crs)) {
            /*
             * If the CRS is already two-dimensional and horizontal, return as-is.
             * We don't need to check if crs is an instance of SingleCRS since all
             * CRS accepted by horizontalCode(…) are SingleCRS.
             */
            case 2: {
                return (SingleCRS) crs;
            }
            case 3: {
                /*
                 * The CRS would be horizontal if we can remove the vertical axis. CoordinateSystems.replaceAxes(…)
                 * will do this task for us. We can verify if the operation has been successful by checking that
                 * the number of dimensions has been reduced by 1 (from 3 to 2).
                 */
                final CoordinateSystem cs = CoordinateSystems.replaceAxes(crs.getCoordinateSystem(), new AxisFilter() {
                    @Override public boolean accept(final CoordinateSystemAxis axis) {
                        return !AxisDirections.isVertical(axis.getDirection());
                    }
                });
                if (cs.getDimension() != 2) break;
                /*
                 * Most of the time, the CRS to rebuild will be geodetic. In such case we known that the
                 * coordinate system is ellipsoidal because (i.e. the CRS is geographic) because it was
                 * a condition verified by horizontalCode(…). A ClassCastException would be a bug.
                 */
                final Map<String, ?> properties = ReferencingUtilities.getPropertiesForModifiedCRS(crs);
                if (crs instanceof GeodeticCRS) {
                    return new DefaultGeographicCRS(properties, ((GeodeticCRS) crs).getDatum(), (EllipsoidalCS) cs);
                }
                /*
                 * In Apache SIS implementation, the Conversion contains the source and target CRS together with
                 * a MathTransform.   We need to recreate the same conversion, but without CRS and MathTransform
                 * for letting SIS create or associate new ones, which will be two-dimensional now.
                 */
                if (crs instanceof ProjectedCRS) {
                    final ProjectedCRS  proj = (ProjectedCRS) crs;
                    final GeographicCRS base = (GeographicCRS) getHorizontalComponent(proj.getBaseCRS());
                    Conversion fromBase = proj.getConversionFromBase();
                    fromBase = new DefaultConversion(IdentifiedObjects.getProperties(fromBase),
                            fromBase.getMethod(), null, fromBase.getParameterValues());
                    return new DefaultProjectedCRS(properties, base, fromBase, (CartesianCS) cs);
                }
                /*
                 * If the CRS is neither geographic or projected, then it is engineering.
                 */
                return new DefaultEngineeringCRS(properties, ((EngineeringCRS) crs).getDatum(), cs);
            }
        }
        if (crs instanceof CompoundCRS) {
            final CompoundCRS cp = (CompoundCRS) crs;
            for (final CoordinateReferenceSystem c : cp.getComponents()) {
                final SingleCRS candidate = getHorizontalComponent(c);
                if (candidate != null) {
                    return candidate;
                }
            }
        }
        return null;
    }

    /**
     * Returns the first vertical coordinate reference system found in the given CRS, or {@code null} if there is none.
     * If the given CRS is already an instance of {@code VerticalCRS}, then this method returns it as-is.
     * Otherwise if the given CRS is compound, then this method searches for the first vertical component
     * in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem) single components list}.
     *
     * <div class="section">Height in a three-dimensional geographic CRS</div>
     * In ISO 19111 model, ellipsoidal heights are indissociable from geographic CRS because such heights
     * without their (<var>latitude</var>, <var>longitude</var>) locations make little sense. Consequently
     * a standard-conformant library should return {@code null} when asked for the {@code VerticalCRS}
     * component of a geographic CRS. This is what {@code getVerticalComponent(…)} does when the
     * {@code allowCreateEllipsoidal} argument is {@code false}.
     *
     * <p>However in some exceptional cases, handling ellipsoidal heights like any other kind of heights
     * may simplify the task. For example when computing <em>difference</em> between heights above the
     * same datum, the impact of ignoring locations may be smaller (but not necessarily canceled).
     * Orphan {@code VerticalCRS} may also be useful for information purpose like labeling a plot axis.
     * If the caller feels confident that ellipsoidal heights are safe for his task, he can set the
     * {@code allowCreateEllipsoidal} argument to {@code true}. In such case, this {@code getVerticalComponent(…)}
     * method will create a temporary {@code VerticalCRS} from the first three-dimensional {@code GeographicCRS}
     * <em>in last resort</em>, only if it can not find an existing {@code VerticalCRS} instance.
     * <strong>Note that this is not a valid CRS according ISO 19111</strong> — use with care.</p>
     *
     * @param  crs  the coordinate reference system, or {@code null}.
     * @param  allowCreateEllipsoidal {@code true} for allowing the creation of orphan CRS for ellipsoidal heights.
     *         The recommended value is {@code false}.
     * @return the first vertical CRS, or {@code null} if none.
     *
     * @see #compound(CoordinateReferenceSystem...)
     *
     * @category information
     */
    public static VerticalCRS getVerticalComponent(final CoordinateReferenceSystem crs, final boolean allowCreateEllipsoidal) {
        if (crs instanceof VerticalCRS) {
            return (VerticalCRS) crs;
        }
        if (crs instanceof CompoundCRS) {
            final CompoundCRS cp = (CompoundCRS) crs;
            boolean a = false;
            do { // Executed at most twice.
                for (final CoordinateReferenceSystem c : cp.getComponents()) {
                    final VerticalCRS candidate = getVerticalComponent(c, a);
                    if (candidate != null) {
                        return candidate;
                    }
                }
            } while ((a = !a) == allowCreateEllipsoidal);
        }
        if (allowCreateEllipsoidal && horizontalCode(crs) == 3) {
            final CoordinateSystem cs = crs.getCoordinateSystem();
            final int i = AxisDirections.indexOfColinear(cs, AxisDirection.UP);
            if (i >= 0) {
                final CoordinateSystemAxis axis = cs.getAxis(i);
                VerticalCRS c = CommonCRS.Vertical.ELLIPSOIDAL.crs();
                if (!c.getCoordinateSystem().getAxis(0).equals(axis)) {
                    final Map<String,?> properties = IdentifiedObjects.getProperties(c);
                    c = new DefaultVerticalCRS(properties, c.getDatum(), new DefaultVerticalCS(properties, axis));
                }
                return c;
            }
        }
        return null;
    }

    /**
     * Returns the first temporal coordinate reference system found in the given CRS, or {@code null} if there is none.
     * If the given CRS is already an instance of {@code TemporalCRS}, then this method returns it as-is.
     * Otherwise if the given CRS is compound, then this method searches for the first temporal component
     * in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem) single components list}.
     *
     * @param  crs  the coordinate reference system, or {@code null}.
     * @return the first temporal CRS, or {@code null} if none.
     *
     * @category information
     */
    public static TemporalCRS getTemporalComponent(final CoordinateReferenceSystem crs) {
        if (crs instanceof TemporalCRS) {
            return (TemporalCRS) crs;
        }
        if (crs instanceof CompoundCRS) {
            final CompoundCRS cp = (CompoundCRS) crs;
            for (final CoordinateReferenceSystem c : cp.getComponents()) {
                final TemporalCRS candidate = getTemporalComponent(c);
                if (candidate != null) {
                    return candidate;
                }
            }
        }
        return null;
    }

    /**
     * Returns the ordered list of single coordinate reference systems for the specified CRS.
     * This method performs the following choices:
     *
     * <ul>
     *   <li>If the given CRS is null, returns an empty list.</li>
     *   <li>If the given CRS is an instance of {@link SingleCRS}, returns that instance in a singleton list.</li>
     *   <li>If the given CRS is an instance of {@link CompoundCRS}, returns a flattened list of its
     *       {@linkplain DefaultCompoundCRS#getComponents() components}. Some components may themselves be
     *       other {@code CompoundCRS} instances, in which case those compound CRS are also flattened in their
     *       list of {@code SingleCRS} components.</li>
     *   <li>Otherwise throws a {@code ClassCastException}.</li>
     * </ul>
     *
     * <div class="note"><b>Example:</b>
     * Apache SIS allows 4-dimensional (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>)
     * coordinate reference system to be built in two different ways as shown below:
     *
     * <div class="horizontal-flow">
     * <div><p><b>Hierarchical structure</b></p>
     * <blockquote>
     *   <code>CompoundCRS</code> — (<var>x</var>, <var>y</var>, <var>z</var>, <var>t</var>)<br>
     *   <code>  ├─CompoundCRS</code> — (<var>x</var>, <var>y</var>, <var>z</var>)<br>
     *   <code>  │   ├─ProjectedCRS</code> — (<var>x</var>, <var>y</var>)<br>
     *   <code>  │   └─VerticalCRS</code> — (<var>z</var>)<br>
     *   <code>  └─TemporalCRS</code> — (<var>t</var>)
     * </blockquote></div>
     * <div><p><b>Flat list</b></p>
     * <blockquote>
     *   <code>CompoundCRS</code> — (<var>x</var>, <var>y</var>, <var>z</var>, <var>t</var>)<br>
     *   <code>  ├─ProjectedCRS</code> — (<var>x</var>, <var>y</var>)<br>
     *   <code>  ├─VerticalCRS</code> — (<var>z</var>)<br>
     *   <code>  └─TemporalCRS</code> — (<var>t</var>)
     * </blockquote>
     * </div></div>
     *
     * This method guaranteed that the returned list is a flat one as shown on the right side.
     * Note that such flat lists are the only one allowed by ISO/OGC standards for compound CRS.
     * The hierarchical structure is an Apache SIS flexibility.</div>
     *
     * @param  crs  the coordinate reference system, or {@code null}.
     * @return the single coordinate reference systems, or an empty list if the given CRS is {@code null}.
     * @throws ClassCastException if a CRS is neither a {@link SingleCRS} or a {@link CompoundCRS}.
     *
     * @see DefaultCompoundCRS#getSingleComponents()
     */
    public static List<SingleCRS> getSingleComponents(final CoordinateReferenceSystem crs) {
        final List<SingleCRS> singles;
        if (crs == null) {
            singles = Collections.emptyList();
        } else if (crs instanceof CompoundCRS) {
            if (crs instanceof DefaultCompoundCRS) {
                singles = ((DefaultCompoundCRS) crs).getSingleComponents();
            } else {
                final List<CoordinateReferenceSystem> elements = ((CompoundCRS) crs).getComponents();
                singles = new ArrayList<>(elements.size());
                ReferencingUtilities.getSingleComponents(elements, singles);
            }
        } else {
            // Intentional CassCastException here if the crs is not a SingleCRS.
            singles = Collections.singletonList((SingleCRS) crs);
        }
        return singles;
    }

    /**
     * Returns the coordinate reference system in the given range of dimension indices.
     * This method processes as below:
     *
     * <ul>
     *   <li>If the given {@code crs} is {@code null}, then this method returns {@code null}.</li>
     *   <li>Otherwise if {@code lower} is 0 and {@code upper} is the number of CRS dimensions,
     *       then this method returns the given CRS unchanged.</li>
     *   <li>Otherwise if the given CRS is an instance of {@link CompoundCRS}, then this method
     *       searches for a {@linkplain CompoundCRS#getComponents() component} where:
     *       <ul>
     *         <li>The {@linkplain org.apache.sis.referencing.cs.AbstractCS#getDimension() number of dimensions}
     *             is equals to {@code upper - lower};</li>
     *         <li>The sum of the number of dimensions of all previous CRS is equals to {@code lower}.</li>
     *       </ul>
     *       If such component is found, then it is returned.</li>
     *   <li>Otherwise (i.e. no component match), this method returns {@code null}.</li>
     * </ul>
     *
     * This method does <strong>not</strong> build new CRS from the components. For example this method does not
     * create a {@link CompoundCRS} or a three-dimensional CRS if the given range spans more than one component.
     *
     * @param  crs    the coordinate reference system to decompose, or {@code null}.
     * @param  lower  the first dimension to keep, inclusive.
     * @param  upper  the last  dimension to keep, exclusive.
     * @return the sub-coordinate system, or {@code null} if the given {@code crs} was {@code null}
     *         or can not be decomposed for dimensions in the [{@code lower} … {@code upper}] range.
     * @throws IndexOutOfBoundsException if the given index are out of bounds.
     *
     * @see #reduce(CoordinateReferenceSystem, int...)
     * @see org.apache.sis.geometry.GeneralEnvelope#subEnvelope(int, int)
     *
     * @since 0.5
     */
    public static CoordinateReferenceSystem getComponentAt(CoordinateReferenceSystem crs, int lower, int upper) {
        int dimension = ReferencingUtilities.getDimension(crs);
        ArgumentChecks.ensureValidIndexRange(dimension, lower, upper);
check:  while (lower != 0 || upper != dimension) {
            if (crs instanceof CompoundCRS) {
                // We need nested CompoundCRS (if any) below, not a flattened list of SingleCRS.
                final List<CoordinateReferenceSystem> components = ((CompoundCRS) crs).getComponents();
                final int size = components.size();
                for (int i=0; i<size; i++) {
                    crs = components.get(i);
                    dimension = crs.getCoordinateSystem().getDimension();
                    if (lower < dimension) {
                        /*
                         * The requested dimensions may intersect the dimension of this CRS.
                         * The outer loop will perform the verification, and eventually go
                         * down again in the tree of sub-components.
                         */
                        continue check;
                    }
                    lower -= dimension;
                    upper -= dimension;
                }
            }
            return null;
        }
        return crs;
    }

    /**
     * Returns the Greenwich longitude of the prime meridian of the given CRS in degrees.
     * If the prime meridian uses an other unit than degrees, then the value will be converted.
     *
     * @param  crs  the coordinate reference system from which to get the prime meridian.
     * @return the Greenwich longitude (in degrees) of the prime meridian of the given CRS.
     *
     * @see org.apache.sis.referencing.datum.DefaultPrimeMeridian#getGreenwichLongitude(Unit)
     *
     * @since 0.5
     */
    public static double getGreenwichLongitude(final GeodeticCRS crs) {
        ArgumentChecks.ensureNonNull("crs", crs);
        return ReferencingUtilities.getGreenwichLongitude(crs.getDatum().getPrimeMeridian(), Units.DEGREE);
    }

    /**
     * Returns the system-wide authority factory used by {@link #forCode(String)} and other SIS methods.
     * If the given authority is non-null, then this method returns a factory specifically for that authority.
     * Otherwise, this method returns the {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
     * instance that manages all other factories.
     *
     * <p>The {@code authority} argument can be {@code "EPSG"}, {@code "OGC"} or any other authority found
     * on the classpath. In the {@code "EPSG"} case, whether the full set of EPSG codes is supported or not
     * depends on whether a {@linkplain org.apache.sis.referencing.factory.sql connection to the database}
     * can be established. If no connection can be established, then this method returns a small embedded
     * EPSG factory containing at least the CRS defined in the {@link #forCode(String)} method javadoc.</p>
     *
     * <p>User-defined authorities can be added to the SIS environment by creating a {@code CRSAuthorityFactory}
     * implementation with a public no-argument constructor, and declaring the fully-qualified name of that class
     * in a file at the following location:</p>
     *
     * {@preformat text
     *     META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
     * }
     *
     * @param  authority  the authority of the desired factory (typically {@code "EPSG"} or {@code "OGC"}),
     *         or {@code null} for the {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
     *         instance that manage all factories.
     * @return the system-wide authority factory used by SIS for the given authority.
     * @throws FactoryException if no factory can be returned for the given authority.
     *
     * @see #forCode(String)
     * @see org.apache.sis.referencing.factory.MultiAuthoritiesFactory
     *
     * @since 0.7
     */
    public static CRSAuthorityFactory getAuthorityFactory(final String authority) throws FactoryException {
        if (authority == null) {
            return AuthorityFactories.ALL;
        }
        return AuthorityFactories.ALL.getAuthorityFactory(CRSAuthorityFactory.class, authority, null);
    }

    /**
     * Invoked when an unexpected exception occurred. Those exceptions must be non-fatal, i.e. the caller
     * <strong>must</strong> have a reasonable fallback (otherwise it should propagate the exception).
     */
    private static void unexpectedException(final String methodName, final Exception exception) {
        Logging.unexpectedException(Logging.getLogger(Modules.REFERENCING), CRS.class, methodName, exception);
    }
}
