use of org.opengis.util.FactoryException in project sis by apache.
the class ReferencingFunctions method getIdentifiedObject.
/**
* Gets the CRS or other kind of object from the given code.
* If the code is a URN, then it can be any kind of object.
* Otherwise a Coordinate Reference System is assumed.
* This method caches the result.
*
* @param codeOrPath the code allocated by an authority, or the path to a file.
* @param type how to interpret {@code codeOrPath}, or {@code null} for guessing.
* @return the identified object for the given code.
* @throws FactoryException if an error occurred while creating the object.
* @throws DataStoreException if an error occurred while reading a data file.
*/
private IdentifiedObject getIdentifiedObject(final String codeOrPath, CodeType type) throws FactoryException, DataStoreException {
final CacheKey<IdentifiedObject> key = new CacheKey<>(IdentifiedObject.class, codeOrPath, null, null);
IdentifiedObject object = key.peek();
if (object == null) {
final Cache.Handler<IdentifiedObject> handler = key.lock();
try {
object = handler.peek();
if (object == null) {
if (type == null) {
type = CodeType.guess(codeOrPath);
}
if (type.equals(CodeType.URN)) {
object = CRS.getAuthorityFactory(null).createObject(codeOrPath);
} else if (type.isCRS) {
object = CRS.forCode(codeOrPath);
} else {
/*
* Apparently not an AUTHORITY:CODE string.
* Try to read a dataset from a file or URL, then get its CRS.
*/
final Metadata metadata;
try (DataStore store = DataStores.open(codeOrPath)) {
metadata = store.getMetadata();
}
if (metadata != null) {
for (final ReferenceSystem rs : metadata.getReferenceSystemInfo()) {
if (rs instanceof CoordinateReferenceSystem) {
return rs;
} else if (object == null) {
// Will be used as a fallback if we find no CRS.
object = rs;
}
}
}
if (object == null) {
throw new FactoryException(Errors.getResources(getJavaLocale()).getString(Errors.Keys.UnspecifiedCRS));
}
}
}
} finally {
handler.putAndUnlock(object);
}
}
return object;
}
use of org.opengis.util.FactoryException in project sis by apache.
the class CoordinateOperationFinder method createOperations.
/**
* Infers operations for conversions or transformations between two coordinate reference systems.
* If a non-null authority factory – the <cite>registry</cite> – has been specified at construction time,
* then this method will first query that factory (<cite>late-binding</cite> approach – see class javadoc).
* If no operation has been found in the registry or if no registry has been specified to the constructor,
* this method inspects the given CRS and delegates the work to one or many {@code createOperationStep(…)}
* methods (<cite>early-binding</cite> approach).
*
* <p>At first, this method is invoked with the {@code sourceCRS} and {@code targetCRS} arguments given to the
* {@link DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem,
* CoordinateOperationContext) CoordinateOperationFactory.createOperation(…)} method. But then, this method may
* be invoked recursively by some {@code createOperationStep(…)} methods with different source or target CRS,
* for example in order to process the {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS#getBaseCRS()
* base geographic CRS} of a projected CRS.</p>
*
* <p>Coordinate operations are returned in preference order: best operations for the area of interest should be first.
* The returned list is modifiable: callers can add, remove or set elements without impact on this
* {@code CoordinateOperationFinder} instance.</p>
*
* @param sourceCRS input coordinate reference system.
* @param targetCRS output coordinate reference system.
* @return coordinate operations from {@code sourceCRS} to {@code targetCRS}.
* @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
* @throws FactoryException if the operation creation failed for some other reason.
*
* @since 1.0
*/
@Override
public List<CoordinateOperation> createOperations(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS) throws FactoryException {
ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
if (equalsIgnoreMetadata(sourceCRS, targetCRS))
try {
return asList(createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(), targetCRS.getCoordinateSystem())));
} catch (IllegalArgumentException | IncommensurableException e) {
throw new FactoryException(Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, new CRSPair(sourceCRS, targetCRS)), e);
}
/*
* If this method is invoked recursively, verify if the requested operation is already in the cache.
* We do not perform this verification on the first invocation because it was already verified by
* DefaultCoordinateOperationFactory.createOperation(…). We do not block if the operation is in
* process of being computed in another thread because of the risk of deadlock. If the operation
* is not in the cache, store the key in our internal map for preventing infinite recursivity.
*/
final CRSPair key = new CRSPair(sourceCRS, targetCRS);
if (useCache && stopAtFirst && !previousSearches.isEmpty()) {
final CoordinateOperation op = factorySIS.cache.peek(key);
// Must be a modifiable list as per this method contract.
if (op != null)
return asList(op);
}
if (previousSearches.put(key, Boolean.TRUE) != null) {
throw new FactoryException(Resources.format(Resources.Keys.RecursiveCreateCallForCode_2, CoordinateOperation.class, key));
}
/*
* If the user did not specified an area of interest, use the domain of validity of the CRS.
*/
GeographicBoundingBox bbox = Extents.getGeographicBoundingBox(areaOfInterest);
if (bbox == null) {
bbox = Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS), CRS.getGeographicBoundingBox(targetCRS));
areaOfInterest = CoordinateOperationContext.setGeographicBoundingBox(areaOfInterest, bbox);
}
/*
* Verify if some extension module handles this pair of CRS in a special way. For example it may
* be the "sis-gdal" module checking if the given CRS are wrappers around Proj.4 data structure.
*/
{
// For keeping 'operations' list locale.
final List<CoordinateOperation> operations = new ArrayList<>();
for (final SpecializedOperationFactory sp : factorySIS.getSpecializedFactories()) {
for (final CoordinateOperation op : sp.findOperations(sourceCRS, targetCRS)) {
if (filter(op)) {
operations.add(op);
}
}
}
if (!operations.isEmpty()) {
CoordinateOperationSorter.sort(operations, bbox);
return operations;
}
}
/*
* Verify in the EPSG dataset if the operation is explicitely defined by an authority.
*/
if (registry != null) {
final List<CoordinateOperation> authoritatives = super.createOperations(sourceCRS, targetCRS);
if (!authoritatives.isEmpty())
return authoritatives;
}
// //////////////////////////////////////////////////////////////////////////////
if (sourceCRS instanceof GeneralDerivedCRS) {
final GeneralDerivedCRS source = (GeneralDerivedCRS) sourceCRS;
if (targetCRS instanceof GeneralDerivedCRS) {
return createOperationStep(source, (GeneralDerivedCRS) targetCRS);
}
if (targetCRS instanceof SingleCRS) {
return createOperationStep(source, (SingleCRS) targetCRS);
}
}
// //////////////////////////////////////////////////////////////////////////////
if (targetCRS instanceof GeneralDerivedCRS) {
final GeneralDerivedCRS target = (GeneralDerivedCRS) targetCRS;
if (sourceCRS instanceof SingleCRS) {
return createOperationStep((SingleCRS) sourceCRS, target);
}
}
// //////////////////////////////////////////////////////////////////////////////
if (sourceCRS instanceof GeodeticCRS) {
final GeodeticCRS source = (GeodeticCRS) sourceCRS;
if (targetCRS instanceof GeodeticCRS) {
return createOperationStep(source, (GeodeticCRS) targetCRS);
}
if (targetCRS instanceof VerticalCRS) {
return createOperationStep(source, (VerticalCRS) targetCRS);
}
}
// //////////////////////////////////////////////////////////////////////////////
if (sourceCRS instanceof VerticalCRS) {
final VerticalCRS source = (VerticalCRS) sourceCRS;
if (targetCRS instanceof VerticalCRS) {
return createOperationStep(source, (VerticalCRS) targetCRS);
}
}
// //////////////////////////////////////////////////////////////////////////////
if (sourceCRS instanceof TemporalCRS) {
final TemporalCRS source = (TemporalCRS) sourceCRS;
if (targetCRS instanceof TemporalCRS) {
return createOperationStep(source, (TemporalCRS) targetCRS);
}
}
// //////////////////////////////////////////////////////////////////////////////
if (sourceCRS instanceof CompoundCRS || targetCRS instanceof CompoundCRS) {
return createOperationStep(sourceCRS, CRS.getSingleComponents(sourceCRS), targetCRS, CRS.getSingleComponents(targetCRS));
}
throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS));
}
use of org.opengis.util.FactoryException in project sis by apache.
the class CoordinateOperationRegistry method createOperations.
/**
* Finds or infers operations for conversions or transformations between two coordinate reference systems.
* {@code CoordinateOperationRegistry} implements the <cite>late-binding</cite> approach (see definition
* of terms in class javadoc) by extracting the authority codes from the supplied {@code sourceCRS} and
* {@code targetCRS}, then by submitting those codes to the
* <code>{@linkplain CoordinateOperationAuthorityFactory#createFromCoordinateReferenceSystemCodes
* createFromCoordinateReferenceSystemCodes}(sourceCode, targetCode)</code> method.
*
* <p>Operations in the returned list are ordered in preference order (preferred operation first).
* If no operation is found for those codes, then this method returns an empty list.
* Note that it does not mean that no path exist;
* it only means that it was not defined explicitely in the registry.</p>
*
* @param sourceCRS input coordinate reference system.
* @param targetCRS output coordinate reference system.
* @return coordinate operations from {@code sourceCRS} to {@code targetCRS},
* or an empty list if no such operation is explicitly defined in the underlying database.
* @throws FactoryException if the operation creation failed.
*/
public List<CoordinateOperation> createOperations(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS) throws FactoryException {
CoordinateReferenceSystem source = sourceCRS;
CoordinateReferenceSystem target = targetCRS;
for (int combine = 0; ; combine++) {
/*
* First, try directly the provided (sourceCRS, targetCRS) pair. If that pair does not work,
* try to use different combinations of user-provided CRS and two-dimensional components of
* those CRS. The code below assumes that the user-provided CRS are three-dimensional, but
* actually it works for other kind of CRS too without testing twice the same combinations.
*/
switch(combine) {
// 3D → 3D
case 0:
break;
case // 3D → 2D
1:
// 3D → 2D
target = CRS.getHorizontalComponent(targetCRS);
if (target == targetCRS)
continue;
break;
case // 2D → 2D
2:
// 2D → 2D
source = CRS.getHorizontalComponent(sourceCRS);
if (source == sourceCRS)
continue;
break;
case 3:
if (source == sourceCRS || target == targetCRS)
continue;
// 2D → 3D
target = targetCRS;
break;
default:
return Collections.emptyList();
}
if (source != null && target != null)
try {
final List<CoordinateOperation> operations = search(source, target);
if (operations != null) {
/*
* Found an operation. If we had to extract the horizontal part of some 3D CRS, then we
* need to modify the coordinate operation in order to match the new number of dimensions.
*/
if (combine != 0) {
for (int i = operations.size(); --i >= 0; ) {
CoordinateOperation operation = operations.get(i);
operation = propagateVertical(sourceCRS, source != sourceCRS, targetCRS, target != targetCRS, operation);
if (operation != null) {
operation = complete(operation, sourceCRS, targetCRS);
operations.set(i, operation);
} else {
operations.remove(i);
}
}
}
if (!operations.isEmpty()) {
return operations;
}
}
} catch (IllegalArgumentException | IncommensurableException e) {
String message = Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, new CRSPair(sourceCRS, targetCRS));
String details = e.getLocalizedMessage();
if (details != null) {
message = message + ' ' + details;
}
throw new FactoryException(message, e);
}
}
}
use of org.opengis.util.FactoryException in project sis by apache.
the class EPSGFactory method newDataAccess.
/**
* Creates the factory which will perform the actual geodetic object creation work.
* This method is invoked automatically when a new worker is required, either because the previous
* one has been disposed after its timeout or because a new one is required for concurrency.
*
* <p>The default implementation performs the following steps:</p>
* <ol>
* <li>Gets a new connection from the {@link #dataSource}.</li>
* <li>If this method is invoked for the first time, verifies if the EPSG tables exists.
* If the tables are not found, invokes {@link #install(Connection)}.</li>
* <li>Delegates to {@link #newDataAccess(Connection, SQLTranslator)}, which provides an easier
* overriding point for subclasses wanting to return a custom {@link EPSGDataAccess} instance.</li>
* </ol>
*
* @return Data Access Object (DAO) to use in {@code createFoo(String)} methods.
* @throws FactoryException if the constructor failed to connect to the EPSG database.
* This exception usually has a {@link SQLException} as its cause.
*/
@Override
protected EPSGDataAccess newDataAccess() throws FactoryException {
UnavailableFactoryException exception;
Connection connection = null;
try {
connection = dataSource.getConnection();
Logging.log(EPSGFactory.class, "newDataAccess", Initializer.connected(connection.getMetaData()));
SQLTranslator tr = translator;
if (tr == null) {
synchronized (this) {
tr = translator;
if (tr == null) {
tr = new SQLTranslator(connection.getMetaData(), catalog, schema);
try {
if (!tr.isTableFound()) {
install(connection);
// Set only on success.
tr.setup(connection.getMetaData());
}
} finally {
// Set only after installation in order to block other threads.
translator = tr;
}
}
}
}
if (tr.isTableFound()) {
return newDataAccess(connection, tr);
} else {
connection.close();
exception = new UnavailableFactoryException(canNotUse(SQLTranslator.tableNotFound(locale)));
}
} catch (Exception e) {
// Really want to catch all exceptions here.
if (connection != null)
try {
connection.close();
} catch (SQLException e2) {
e.addSuppressed(e2);
}
if (e instanceof FactoryException) {
throw (FactoryException) e;
}
/*
* Derby sometime wraps SQLException into another SQLException. For making the stack strace a
* little bit simpler, keep only the root cause provided that the exception type is compatible.
*/
exception = new UnavailableFactoryException(canNotUse(e), Exceptions.unwrap(e));
}
exception.setUnavailableFactory(this);
throw exception;
}
use of org.opengis.util.FactoryException in project sis by apache.
the class ConcurrentAuthorityFactory method getAuthority.
/**
* Returns the database or specification that defines the codes recognized by this factory.
* The default implementation performs the following steps:
* <ul>
* <li>Returns the cached value if it exists.</li>
* <li>Otherwise:
* <ol>
* <li>get an instance of the Data Access Object,</li>
* <li>delegate to its {@link GeodeticAuthorityFactory#getAuthority()} method,</li>
* <li>release the Data Access Object,</li>
* <li>cache the result.</li>
* </ol>
* </li>
* </ul>
*
* If this method can not get a Data Access Object (for example because no database connection is available),
* then this method returns {@code null}.
*
* @return the organization responsible for definition of the database, or {@code null} if unavailable.
*/
@Override
public Citation getAuthority() {
Citation c = authority;
if (c == null || c == UNAVAILABLE)
try {
final DAO factory = getDataAccess();
try {
/*
* Cache only in case of success. If we failed, we
* will try again next time this method is invoked.
*/
authority = c = factory.getAuthority();
} finally {
release("getAuthority", Citation.class, null);
}
} catch (FactoryException e) {
authority = UNAVAILABLE;
/*
* Use the warning level only on the first failure, then the fine level on all subsequent failures.
* Do not log the stack trace if we failed because of UnavailableFactoryException since it may be
* normal (the EPSG geodetic dataset is optional, even if strongly recommended).
*/
final LogRecord record = new LogRecord(c == null ? Level.WARNING : Level.FINE, e.getLocalizedMessage());
if (!(e instanceof UnavailableFactoryException)) {
record.setThrown(e);
}
record.setLoggerName(Loggers.CRS_FACTORY);
Logging.log(ConcurrentAuthorityFactory.class, "getAuthority", record);
c = null;
}
return c;
}
Aggregations