in endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [1331:1592]
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",
"SELECT COORD_REF_SYS_CODE," + // [ 1]
" COORD_REF_SYS_NAME," + // [ 2]
" AREA_OF_USE_CODE," + // [ 3]
" CRS_SCOPE," + // [ 4]
" REMARKS," + // [ 5]
" DEPRECATED," + // [ 6]
" COORD_REF_SYS_KIND," + // [ 7]
" COORD_SYS_CODE," + // [ 8] Null for CompoundCRS
" DATUM_CODE," + // [ 9] Null for ProjectedCRS
" SOURCE_GEOGCRS_CODE," + // [10] For ProjectedCRS
" PROJECTION_CONV_CODE," + // [11] For ProjectedCRS
" CMPD_HORIZCRS_CODE," + // [12] For CompoundCRS only
" CMPD_VERTCRS_CODE" + // [13] For CompoundCRS only
" 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 information,
* 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 another
* `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);
result.close(); // Must be closed before call to createGeographicCRS(String)
ensureNoCycle(GeographicCRS.class, epsg);
try {
datum = owner.createGeographicCRS(geoCode).getDatum();
} finally {
endOfRecursion(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 cannot 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);
result.close(); // Must be closed before call to createFoo(String)
ensureNoCycle(ProjectedCRS.class, epsg);
try {
final CartesianCS cs = owner.createCartesianCS(csCode);
final Conversion op;
try {
op = (Conversion) owner.createCoordinateOperation(opCode);
} catch (ClassCastException e) {
// Should never happen in a well-formed EPSG database.
// If happen anyway, the ClassCastException cause will give more hints than just the message.
throw (NoSuchAuthorityCodeException) noSuchAuthorityCode(Conversion.class, opCode).initCause(e);
}
final CoordinateReferenceSystem baseCRS;
final boolean suspendParamChecks;
if (!deprecated) {
baseCRS = owner.createCoordinateReferenceSystem(geoCode);
suspendParamChecks = true;
} 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 cannot 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;
baseCRS = createCoordinateReferenceSystem(geoCode); // Do not cache that CRS.
} 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.
*/
suspendParamChecks = 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 geodetic. 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.
*
* TODO: there is an ambiguity when the source CRS is geographic but the operation
* is nevertheless considered as not a map projection. It is the case of EPSG:5819.
* The problem is that the "COORD_REF_SYS_KIND" column still contains "Projected".
* We need to check if EPSG database 10+ has more specific information.
* See https://issues.apache.org/jira/browse/SIS-518
*/
@SuppressWarnings("LocalVariableHidesMemberVariable")
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 {
Semaphores.clear(Semaphores.SUSPEND_PARAMETER_CHECK, suspendParamChecks);
}
} finally {
endOfRecursion(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 cannot 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 {
endOfRecursion(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));
@SuppressWarnings("LocalVariableHidesMemberVariable")
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 = ServicesForMetadata.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;
}