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;
}
Aggregations