use of org.apache.sis.util.collection.Cache in project sis by apache.
the class ConcurrentAuthorityFactory method createFromCoordinateReferenceSystemCodes.
/**
* Returns operations from source and target coordinate reference system codes.
* The default implementation performs the following steps:
* <ul>
* <li>Returns the cached collection for the given pair of codes if such collection already exists.</li>
* <li>Otherwise:
* <ol>
* <li>get an instance of the Data Access Object,</li>
* <li>delegate to its {@link GeodeticAuthorityFactory#createFromCoordinateReferenceSystemCodes(String, String)} method,</li>
* <li>release the Data Access Object — <em>this step assumes that the collection obtained at step 2
* is still valid after the Data Access Object has been released</em>,</li>
* <li>cache the result — <em>this step assumes that the collection obtained at step 2 is immutable</em>.</li>
* </ol>
* </li>
* </ul>
*
* @return the operations from {@code sourceCRS} to {@code targetCRS}.
* @throws FactoryException if the object creation failed.
*/
@Override
@SuppressWarnings("unchecked")
public Set<CoordinateOperation> createFromCoordinateReferenceSystemCodes(final String sourceCRS, final String targetCRS) throws FactoryException {
ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
final Key key = new Key(normalizeCode(sourceCRS), normalizeCode(targetCRS));
Object value = cache.peek(key);
if (!(value instanceof Set<?>)) {
final Cache.Handler<Object> handler = cache.lock(key);
try {
value = handler.peek();
if (!(value instanceof Set<?>)) {
final DAO factory = getDataAccess();
try {
value = factory.createFromCoordinateReferenceSystemCodes(sourceCRS, targetCRS);
} finally {
release("createFromCoordinateReferenceSystemCodes", CoordinateOperation.class, null);
}
}
} finally {
handler.putAndUnlock(value);
}
}
return (Set<CoordinateOperation>) value;
}
use of org.apache.sis.util.collection.Cache in project sis by apache.
the class ConcurrentAuthorityFactory method create.
/**
* Returns an object from a code using the given proxy. This method first checks in the cache.
* If no object exists in the cache for the given code, then a lock is created and the object
* creation is delegated to the {@linkplain #getDataAccess() Data Access Object}.
* The result is then stored in the cache and returned.
*
* @param <T> the type of the object to be returned.
* @param proxy the proxy to use for creating the object.
* @param code the code of the object to create.
* @return the object extracted from the cache or created.
* @throws FactoryException if an error occurred while creating the object.
*/
private <T> T create(final AuthorityFactoryProxy<T> proxy, final String code) throws FactoryException {
ArgumentChecks.ensureNonNull("code", code);
final Class<T> type = proxy.type;
final Key key = new Key(type, normalizeCode(code));
Object value = cache.peek(key);
if (!type.isInstance(value)) {
final Cache.Handler<Object> handler = cache.lock(key);
try {
value = handler.peek();
if (!type.isInstance(value)) {
final T result;
final DAO factory = getDataAccess();
try {
result = proxy.create(factory, key.code);
} finally {
release(null, type, code);
}
if (isCacheable(code, result)) {
// For the finally block below.
value = result;
}
return result;
}
} finally {
handler.putAndUnlock(value);
}
}
return type.cast(value);
}
use of org.apache.sis.util.collection.Cache in project sis by apache.
the class DefaultCoordinateOperationFactory method createOperation.
/**
* Finds or creates an operation for conversion or transformation between two coordinate reference systems.
* If an operation exists, it is returned. If more than one operation exists, then the operation having the
* widest intersection between its {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of
* validity} and the {@linkplain CoordinateOperationContext#getAreaOfInterest() area of interest} is returned.
*
* <p>The default implementation performs the following steps:</p>
* <ul>
* <li>If a coordinate operation has been previously cached for the given CRS and context, return it.</li>
* <li>Otherwise:
* <ol>
* <li>Invoke {@link #createOperationFinder(CoordinateOperationAuthorityFactory, CoordinateOperationContext)}.</li>
* <li>Invoke {@link CoordinateOperationFinder#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)}
* on the object returned by the previous step.</li>
* <li>Cache the result, then return it.</li>
* </ol>
* </li>
* </ul>
*
* Subclasses can override {@link #createOperationFinder createOperationFinder(…)} if they need more control on
* the way coordinate operations are inferred.
*
* @param sourceCRS input coordinate reference system.
* @param targetCRS output coordinate reference system.
* @param context area of interest and desired accuracy, or {@code null}.
* @return a coordinate operation 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.
*
* @see CoordinateOperationFinder
*
* @since 0.7
*/
public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS, final CoordinateOperationContext context) throws OperationNotFoundException, FactoryException {
final Cache.Handler<CoordinateOperation> handler;
CoordinateOperation op;
if (context == null) {
final CRSPair key = new CRSPair(sourceCRS, targetCRS);
op = cache.peek(key);
if (op != null) {
return op;
}
handler = cache.lock(key);
} else {
// We currently do not cache the operation when the result may depend on the context (see 'this.cache' javadoc).
handler = null;
op = null;
}
try {
if (handler == null || (op = handler.peek()) == null) {
final AuthorityFactory registry = USE_EPSG_FACTORY ? CRS.getAuthorityFactory(Constants.EPSG) : null;
op = createOperationFinder((registry instanceof CoordinateOperationAuthorityFactory) ? (CoordinateOperationAuthorityFactory) registry : null, context).createOperation(sourceCRS, targetCRS);
}
} finally {
if (handler != null) {
handler.putAndUnlock(op);
}
}
return op;
}
Aggregations