Search in sources :

Example 1 with DefaultParametricDatum

use of org.apache.sis.referencing.datum.DefaultParametricDatum in project sis by apache.

the class EPSGDataAccess method createCoordinateReferenceSystem.

/**
 * Creates an arbitrary coordinate reference system from a code.
 * The returned object will typically be an instance of {@link GeographicCRS}, {@link ProjectedCRS},
 * {@link VerticalCRS} or {@link CompoundCRS}.
 *
 * <div class="note"><b>Example:</b>
 * some EPSG codes for coordinate reference systems are:
 *
 * <table class="sis" summary="EPSG codes examples">
 *   <tr><th>Code</th> <th>Type</th>          <th>Description</th></tr>
 *   <tr><td>4326</td> <td>Geographic</td>    <td>World Geodetic System 1984</td></tr>
 *   <tr><td>4979</td> <td>Geographic 3D</td> <td>World Geodetic System 1984</td></tr>
 *   <tr><td>4978</td> <td>Geocentric</td>    <td>World Geodetic System 1984</td></tr>
 *   <tr><td>3395</td> <td>Projected</td>     <td>WGS 84 / World Mercator</td></tr>
 *   <tr><td>5714</td> <td>Vertical</td>      <td>Mean Sea Level height</td></tr>
 *   <tr><td>6349</td> <td>Compound</td>      <td>NAD83(2011) + NAVD88 height</td></tr>
 *   <tr><td>5800</td> <td>Engineering</td>   <td>Astra Minas Grid</td></tr>
 * </table></div>
 *
 * @param  code  value allocated by EPSG.
 * @return the coordinate reference system for the given code.
 * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
 * @throws FactoryException if the object creation failed for some other reason.
 */
@Override
public synchronized CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) throws NoSuchAuthorityCodeException, FactoryException {
    ArgumentChecks.ensureNonNull("code", code);
    CoordinateReferenceSystem returnValue = null;
    try (ResultSet result = executeQuery("Coordinate Reference System", "COORD_REF_SYS_CODE", "COORD_REF_SYS_NAME", // [ 1]
    "SELECT COORD_REF_SYS_CODE," + // [ 2]
    " COORD_REF_SYS_NAME," + // [ 3]
    " AREA_OF_USE_CODE," + // [ 4]
    " CRS_SCOPE," + // [ 5]
    " REMARKS," + // [ 6]
    " DEPRECATED," + // [ 7]
    " COORD_REF_SYS_KIND," + // [ 8] Null for CompoundCRS
    " COORD_SYS_CODE," + // [ 9] Null for ProjectedCRS
    " DATUM_CODE," + // [10] For ProjectedCRS
    " SOURCE_GEOGCRS_CODE," + // [11] For ProjectedCRS
    " PROJECTION_CONV_CODE," + // [12] For CompoundCRS only
    " CMPD_HORIZCRS_CODE," + // [13] For CompoundCRS only
    " CMPD_VERTCRS_CODE" + " FROM [Coordinate Reference System]" + " WHERE COORD_REF_SYS_CODE = ?", code)) {
        while (result.next()) {
            final Integer epsg = getInteger(code, result, 1);
            final String name = getString(code, result, 2);
            final String area = getOptionalString(result, 3);
            final String scope = getOptionalString(result, 4);
            final String remarks = getOptionalString(result, 5);
            final boolean deprecated = getOptionalBoolean(result, 6);
            final String type = getString(code, result, 7);
            /*
                 * Note: Do not invoke 'createProperties' now, even if we have all required informations,
                 *       because the 'properties' map is going to overwritten by calls to 'createDatum', etc.
                 *
                 * The following switch statement should have a case for all "epsg_crs_kind" values enumerated
                 * in the "EPSG_Prepare.sql" file, except that the values in this Java code are in lower cases.
                 */
            final CRSFactory crsFactory = owner.crsFactory;
            final CoordinateReferenceSystem crs;
            switch(type.toLowerCase(Locale.US)) {
                /* ----------------------------------------------------------------------
                     *   GEOGRAPHIC CRS
                     *
                     *   NOTE: 'createProperties' MUST be invoked after any call to an other
                     *         'createFoo' method. Consequently, do not factor out.
                     * ---------------------------------------------------------------------- */
                case "geographic 2d":
                case "geographic 3d":
                    {
                        Integer csCode = getInteger(code, result, 8);
                        if (replaceDeprecatedCS) {
                            csCode = DEPRECATED_CS.getOrDefault(csCode, csCode);
                        }
                        final EllipsoidalCS cs = owner.createEllipsoidalCS(csCode.toString());
                        final String datumCode = getOptionalString(result, 9);
                        final GeodeticDatum datum;
                        if (datumCode != null) {
                            datum = owner.createGeodeticDatum(datumCode);
                        } else {
                            final String geoCode = getString(code, result, 10, 9);
                            // Must be closed before call to createGeographicCRS(String)
                            result.close();
                            ensureNoCycle(GeographicCRS.class, epsg);
                            try {
                                datum = owner.createGeographicCRS(geoCode).getDatum();
                            } finally {
                                endOfRecursivity(GeographicCRS.class, epsg);
                            }
                        }
                        crs = crsFactory.createGeographicCRS(createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated), datum, cs);
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   PROJECTED CRS
                     *
                     *   NOTE: This method invokes itself indirectly, through createGeographicCRS.
                     *         Consequently we can not use 'result' anymore after this block.
                     * ---------------------------------------------------------------------- */
                case "projected":
                    {
                        final String csCode = getString(code, result, 8);
                        final String geoCode = getString(code, result, 10);
                        final String opCode = getString(code, result, 11);
                        // Must be closed before call to createFoo(String)
                        result.close();
                        ensureNoCycle(ProjectedCRS.class, epsg);
                        try {
                            final CartesianCS cs = owner.createCartesianCS(csCode);
                            final Conversion op;
                            try {
                                op = (Conversion) owner.createCoordinateOperation(opCode);
                            } catch (ClassCastException e) {
                                // If happen anyway, the ClassCastException cause will give more hints than just the message.
                                throw (NoSuchAuthorityCodeException) noSuchAuthorityCode(Projection.class, opCode).initCause(e);
                            }
                            final CoordinateReferenceSystem baseCRS;
                            final boolean resumeParamChecks;
                            if (!deprecated) {
                                baseCRS = owner.createCoordinateReferenceSystem(geoCode);
                                resumeParamChecks = false;
                            } else {
                                /*
                                 * If the ProjectedCRS is deprecated, one reason among others may be that it uses one of
                                 * the deprecated coordinate systems. Those deprecated CS used non-linear units like DMS.
                                 * Apache SIS can not instantiate a ProjectedCRS when the baseCRS uses such units, so we
                                 * set a flag asking to replace the deprecated CS by a supported one. Since that baseCRS
                                 * would not be exactly as defined by EPSG, we must not cache it because we do not want
                                 * 'owner.createGeographicCRS(geoCode)' to return that modified CRS. Since the same CRS
                                 * may be recreated every time a deprecated ProjectedCRS is created, we temporarily
                                 * shutdown the loggings in order to avoid the same warning to be logged many time.
                                 */
                                final boolean old = quiet;
                                try {
                                    quiet = true;
                                    replaceDeprecatedCS = true;
                                    // Do not cache that CRS.
                                    baseCRS = createCoordinateReferenceSystem(geoCode);
                                } finally {
                                    replaceDeprecatedCS = false;
                                    quiet = old;
                                }
                                /*
                                 * The crsFactory method calls will indirectly create a parameterized MathTransform.
                                 * Their constructor will try to verify the parameter validity. But some deprecated
                                 * CRS had invalid parameter values (they were deprecated precisely for that reason).
                                 * If and only if we are creating a deprecated CRS, temporarily suspend the parameter
                                 * checks.
                                 */
                                resumeParamChecks = !Semaphores.queryAndSet(Semaphores.SUSPEND_PARAMETER_CHECK);
                            // Try block must be immediately after above line (do not insert any code between).
                            }
                            try {
                                /*
                                 * For a ProjectedCRS, the baseCRS is always geographic. So in theory we would not
                                 * need the 'instanceof' check. However the EPSG dataset version 8.9 also uses the
                                 * "projected" type for CRS that are actually derived CRS. See EPSG:5820 and 5821.
                                 */
                                final Map<String, Object> properties = createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated);
                                if (baseCRS instanceof GeographicCRS) {
                                    crs = crsFactory.createProjectedCRS(properties, (GeographicCRS) baseCRS, op, cs);
                                } else {
                                    crs = crsFactory.createDerivedCRS(properties, baseCRS, op, cs);
                                }
                            } finally {
                                if (resumeParamChecks) {
                                    Semaphores.clear(Semaphores.SUSPEND_PARAMETER_CHECK);
                                }
                            }
                        } finally {
                            endOfRecursivity(ProjectedCRS.class, epsg);
                        }
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   VERTICAL CRS
                     * ---------------------------------------------------------------------- */
                case "vertical":
                    {
                        final VerticalCS cs = owner.createVerticalCS(getString(code, result, 8));
                        final VerticalDatum datum = owner.createVerticalDatum(getString(code, result, 9));
                        crs = crsFactory.createVerticalCRS(createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated), datum, cs);
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   TEMPORAL CRS
                     *
                     *   NOTE : The original EPSG database does not define any temporal CRS.
                     *          This block is a SIS-specific extension.
                     * ---------------------------------------------------------------------- */
                case "time":
                case "temporal":
                    {
                        final TimeCS cs = owner.createTimeCS(getString(code, result, 8));
                        final TemporalDatum datum = owner.createTemporalDatum(getString(code, result, 9));
                        crs = crsFactory.createTemporalCRS(createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated), datum, cs);
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   COMPOUND CRS
                     *
                     *   NOTE: This method invokes itself recursively.
                     *         Consequently, we can not use 'result' anymore.
                     * ---------------------------------------------------------------------- */
                case "compound":
                    {
                        final String code1 = getString(code, result, 12);
                        final String code2 = getString(code, result, 13);
                        result.close();
                        final CoordinateReferenceSystem crs1, crs2;
                        ensureNoCycle(CompoundCRS.class, epsg);
                        try {
                            crs1 = owner.createCoordinateReferenceSystem(code1);
                            crs2 = owner.createCoordinateReferenceSystem(code2);
                        } finally {
                            endOfRecursivity(CompoundCRS.class, epsg);
                        }
                        // Note: Do not invoke 'createProperties' sooner.
                        crs = crsFactory.createCompoundCRS(createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated), crs1, crs2);
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   GEOCENTRIC CRS
                     * ---------------------------------------------------------------------- */
                case "geocentric":
                    {
                        final CoordinateSystem cs = owner.createCoordinateSystem(getString(code, result, 8));
                        final GeodeticDatum datum = owner.createGeodeticDatum(getString(code, result, 9));
                        final Map<String, Object> properties = createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated);
                        if (cs instanceof CartesianCS) {
                            crs = crsFactory.createGeocentricCRS(properties, datum, (CartesianCS) cs);
                        } else if (cs instanceof SphericalCS) {
                            crs = crsFactory.createGeocentricCRS(properties, datum, (SphericalCS) cs);
                        } else {
                            throw new FactoryDataException(error().getString(Errors.Keys.IllegalCoordinateSystem_1, cs.getName()));
                        }
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   ENGINEERING CRS
                     * ---------------------------------------------------------------------- */
                case "engineering":
                    {
                        final CoordinateSystem cs = owner.createCoordinateSystem(getString(code, result, 8));
                        final EngineeringDatum datum = owner.createEngineeringDatum(getString(code, result, 9));
                        crs = crsFactory.createEngineeringCRS(createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated), datum, cs);
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   PARAMETRIC CRS
                     * ---------------------------------------------------------------------- */
                case "parametric":
                    {
                        final DefaultParametricCS cs = owner.createParametricCS(getString(code, result, 8));
                        final DefaultParametricDatum datum = owner.createParametricDatum(getString(code, result, 9));
                        crs = ReferencingServices.getInstance().createParametricCRS(createProperties("Coordinate Reference System", name, epsg, area, scope, remarks, deprecated), datum, cs, crsFactory);
                        break;
                    }
                /* ----------------------------------------------------------------------
                     *   UNKNOWN CRS
                     * ---------------------------------------------------------------------- */
                default:
                    {
                        throw new FactoryDataException(error().getString(Errors.Keys.UnknownType_1, type));
                    }
            }
            returnValue = ensureSingleton(crs, returnValue, code);
            if (result.isClosed()) {
                return returnValue;
            }
        }
    } catch (SQLException exception) {
        throw databaseFailure(CoordinateReferenceSystem.class, code, exception);
    }
    if (returnValue == null) {
        throw noSuchAuthorityCode(CoordinateReferenceSystem.class, code);
    }
    return returnValue;
}
Also used : SQLException(java.sql.SQLException) InternationalString(org.opengis.util.InternationalString) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) ResultSet(java.sql.ResultSet) DefaultParametricDatum(org.apache.sis.referencing.datum.DefaultParametricDatum) NoSuchAuthorityCodeException(org.opengis.referencing.NoSuchAuthorityCodeException) DefaultParametricCS(org.apache.sis.referencing.cs.DefaultParametricCS) DefaultGeodeticDatum(org.apache.sis.referencing.datum.DefaultGeodeticDatum) FactoryDataException(org.apache.sis.referencing.factory.FactoryDataException) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap)

Aggregations

ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 DefaultParametricCS (org.apache.sis.referencing.cs.DefaultParametricCS)1 DefaultGeodeticDatum (org.apache.sis.referencing.datum.DefaultGeodeticDatum)1 DefaultParametricDatum (org.apache.sis.referencing.datum.DefaultParametricDatum)1 FactoryDataException (org.apache.sis.referencing.factory.FactoryDataException)1 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)1 NoSuchAuthorityCodeException (org.opengis.referencing.NoSuchAuthorityCodeException)1 InternationalString (org.opengis.util.InternationalString)1