Author: desruisseaux
Date: Thu Apr 21 20:07:44 2016
New Revision: 1740399
URL: http://svn.apache.org/viewvc?rev=1740399&view=rev
Log:
Merge bug fixes from JDK6 branch.
Modified:
sis/trunk/ (props changed)
sis/trunk/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
Propchange: sis/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Apr 21 20:07:44 2016
@@ -1,4 +1,4 @@
/sis/branches/Android:1430670-1480699
-/sis/branches/JDK6:1394364-1740152
-/sis/branches/JDK7:1394913-1740146
-/sis/branches/JDK8:1584960-1740143
+/sis/branches/JDK6:1394364-1740397
+/sis/branches/JDK7:1394913-1740391
+/sis/branches/JDK8:1584960-1740312
Modified:
sis/trunk/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java
[UTF-8] (original)
+++
sis/trunk/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -67,7 +67,7 @@ final class NamedFeatureType implements
}
/**
- * This feature type is considered to all other features except itself.
+ * This feature type is considered independent of all other feature types
except itself.
*/
@Override
public boolean isAssignableFrom(final DefaultFeatureType type) {
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -391,9 +391,10 @@ public class AbstractCS extends Abstract
* @return {@code true} if both objects are equal.
*/
@Override
+ @SuppressWarnings("fallthrough")
public boolean equals(final Object object, final ComparisonMode mode) {
if (object == this) {
- return true; // Slight optimization.
+ return true; // Slight
optimization.
}
if (!super.equals(object, mode)) {
return false;
@@ -403,6 +404,14 @@ public class AbstractCS extends Abstract
// No need to check the class - this check has been done by
super.equals(…).
return Arrays.equals(axes, ((AbstractCS) object).axes);
}
+ case DEBUG: {
+ final int d1 = axes.length;
+ final int d2 = ((CoordinateSystem) object).getDimension();
+ if (d1 != d2) {
+ throw new
AssertionError(Errors.format(Errors.Keys.MismatchedDimension_2, d1, d2));
+ }
+ // Fall through
+ }
default: {
final CoordinateSystem that = (CoordinateSystem) object;
final int dimension = getDimension();
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -16,6 +16,8 @@
*/
package org.apache.sis.referencing.operation;
+import org.opengis.referencing.cs.EllipsoidalCS;
+import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.IdentifiedObject;
import org.apache.sis.referencing.AbstractIdentifiedObject;
@@ -57,7 +59,7 @@ final class CRSPair {
*/
@Override
public int hashCode() {
- return sourceCRS.hashCode() * 31 + targetCRS.hashCode();
+ return Objects.hashCode(sourceCRS) * 31 + Objects.hashCode(targetCRS);
}
/**
@@ -79,8 +81,9 @@ final class CRSPair {
}
/**
- * Returns the name of the GeoAPI interface implemented by the specified
object,
- * followed by the name between brackets.
+ * Returns the name of the GeoAPI interface implemented by the specified
object. In the GeographicCRS
+ * or EllipsoidalCS cases, the trailing CRS or CS suffix is replaced by
the number of dimensions
+ * (e.g. "Geographic3D").
*/
static String label(final IdentifiedObject object) {
if (object == null) {
@@ -92,7 +95,18 @@ final class CRSPair {
} else {
type = Classes.getLeafInterfaces(object.getClass(),
IdentifiedObject.class)[0];
}
- String label = Classes.getShortName(type);
+ String suffix, label = Classes.getShortName(type);
+ if (label.endsWith((suffix = "CRS")) || label.endsWith(suffix = "CS"))
{
+ Object cs = object;
+ if (object instanceof CoordinateReferenceSystem) {
+ cs = ((CoordinateReferenceSystem)
object).getCoordinateSystem();
+ }
+ if (cs instanceof EllipsoidalCS) {
+ final StringBuilder sb = new StringBuilder(label);
+ sb.setLength(label.length() - suffix.length());
+ label = sb.append(((CoordinateSystem)
cs).getDimension()).append('D').toString();
+ }
+ }
String name = IdentifiedObjects.getName(object, null);
if (name != null) {
int i = 30; // Arbitrary
length threshold.
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -146,6 +146,11 @@ public class CoordinateOperationFinder e
private final Map<CRSPair,Boolean> previousSearches;
/**
+ * Whether this finder instance is allowed to use {@link
DefaultCoordinateOperationFactory#cache}.
+ */
+ private final boolean useCache;
+
+ /**
* Creates a new instance for the given factory and context.
*
* @param registry the factory to use for creating operations as defined
by authority, or {@code null} if none.
@@ -160,6 +165,7 @@ public class CoordinateOperationFinder e
super(registry, factory, context);
identifierOfStepCRS = new HashMap<Identifier,Object>(8);
previousSearches = new HashMap<CRSPair,Boolean>(8);
+ useCache = (context == null) && (factory == factorySIS);
}
/**
@@ -190,13 +196,33 @@ public class CoordinateOperationFinder e
{
ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
- if (!previousSearches.isEmpty()) {
- // TODO: verify here if the path is defined in EPSG database.
+ if (equalsIgnoreMetadata(sourceCRS, targetCRS)) try {
+ return createFromAffineTransform(AXIS_CHANGES, sourceCRS,
targetCRS,
+
CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(),
targetCRS.getCoordinateSystem()));
+ } catch (IllegalArgumentException e) {
+ throw new
FactoryException(Errors.format(Errors.Keys.CanNotInstantiate_1, new
CRSPair(sourceCRS, targetCRS)), e);
+ } catch (ConversionException e) {
+ throw new
FactoryException(Errors.format(Errors.Keys.CanNotInstantiate_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 && !previousSearches.isEmpty()) {
+ final CoordinateOperation op = factorySIS.cache.peek(key);
+ if (op != null) return op;
+ }
if (previousSearches.put(key, Boolean.TRUE) != null) {
throw new
FactoryException(Errors.format(Errors.Keys.RecursiveCreateCallForCode_2,
CoordinateOperation.class, key));
}
+ /*
+ * If the user did not specified an area of interest, use the domain
of validity of the CRS.
+ * Then verify in the EPSG dataset if the operation is explicitely
defined by an authority.
+ */
GeographicBoundingBox bbox =
Extents.getGeographicBoundingBox(areaOfInterest);
if (bbox == null) {
bbox =
Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS),
@@ -901,8 +927,14 @@ public class CoordinateOperationFinder e
* trivial operations.
*/
CoordinateOperation main = null;
- if (step1.getName() == AXIS_CHANGES && mt1.getSourceDimensions() ==
mt1.getTargetDimensions()) main = step2;
- if (step2.getName() == AXIS_CHANGES && mt2.getSourceDimensions() ==
mt2.getTargetDimensions()) main = step1;
+ final boolean isAxisChange1 = (step1.getName() == AXIS_CHANGES);
+ final boolean isAxisChange2 = (step2.getName() == AXIS_CHANGES);
+ if (isAxisChange1 && isAxisChange2 && isAffine(step1) &&
isAffine(step2)) {
+ main = step2; //
Arbitrarily take the last step.
+ } else {
+ if (isAxisChange1 && mt1.getSourceDimensions() ==
mt1.getTargetDimensions()) main = step2;
+ if (isAxisChange2 && mt2.getSourceDimensions() ==
mt2.getTargetDimensions()) main = step1;
+ }
if (main instanceof SingleOperation) {
final SingleOperation op = (SingleOperation) main;
final MathTransform mt =
factorySIS.getMathTransformFactory().createConcatenatedTransform(mt1, mt2);
@@ -915,7 +947,7 @@ public class CoordinateOperationFinder e
}
/*
* Sometime we get a concatenated operation made of an operation
followed by its inverse.
- * We can identity those case when the associated MathTransform is the
identity transform.
+ * We can identify thoses case when the associated MathTransform is
the identity transform.
* In such case, simplify by replacing the ConcatenatedTransform by a
SingleTransform.
*/
if (main instanceof ConcatenatedOperation &&
main.getMathTransform().isIdentity()) {
@@ -958,6 +990,18 @@ public class CoordinateOperationFinder e
}
/**
+ * Returns {@code true} if the given operation is non-null and use the
affine operation method.
+ */
+ private static boolean isAffine(final CoordinateOperation operation) {
+ if (operation instanceof SingleOperation) {
+ if (IdentifiedObjects.isHeuristicMatchForName(((SingleOperation)
operation).getMethod(), Constants.AFFINE)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Returns {@code true} if the specified operation is an identity
conversion.
* This method always returns {@code false} for transformations even if
their
* associated math transform is an identity one, because such
transformations
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -38,6 +38,7 @@ import org.opengis.referencing.Identifie
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeodeticCRS;
+import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.operation.*;
@@ -295,7 +296,8 @@ class CoordinateOperationRegistry {
* need to modify the coordinate operation in order to
match the new number of dimensions.
*/
if (combine != 0) {
- operation = propagateVertical(operation, source !=
sourceCRS, target != targetCRS);
+ operation = propagateVertical(sourceCRS, source !=
sourceCRS,
+ targetCRS, target !=
targetCRS, operation);
if (operation == null) {
continue;
}
@@ -304,8 +306,12 @@ class CoordinateOperationRegistry {
return operation;
}
} catch (IllegalArgumentException e) {
- throw new FactoryException(Errors.format(
- Errors.Keys.CanNotInstantiate_1, new
CRSPair(sourceCRS, targetCRS)), e);
+ String message =
Errors.format(Errors.Keys.CanNotInstantiate_1, new CRSPair(sourceCRS,
targetCRS));
+ String details = e.getLocalizedMessage();
+ if (details != null) {
+ message = message + ' ' + details;
+ }
+ throw new FactoryException(message, e);
} catch (ConversionException e) {
throw new FactoryException(Errors.format(
Errors.Keys.CanNotInstantiate_1, new
CRSPair(sourceCRS, targetCRS)), e);
@@ -545,7 +551,8 @@ class CoordinateOperationRegistry {
final MathTransformFactory
mtFactory)
throws IllegalArgumentException, ConversionException,
FactoryException
{
- assert Utilities.deepEquals(sourceCRS, targetCRS,
ComparisonMode.ALLOW_VARIANT);
+ assert ReferencingUtilities.getDimension(sourceCRS) !=
ReferencingUtilities.getDimension(targetCRS)
+ || Utilities.deepEquals(sourceCRS, targetCRS,
ComparisonMode.ALLOW_VARIANT);
final Matrix m =
CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(),
targetCRS.getCoordinateSystem());
return (m.isIdentity()) ? null : mtFactory.createAffineTransform(m);
}
@@ -702,16 +709,20 @@ class CoordinateOperationRegistry {
* <cite>best effort</cite> basis. In any cases, the {@link #complete}
method should be invoked
* after this one in order to ensure that the source and target CRS are
the expected ones.</p>
*
- * @param operation the original (typically two-dimensional) coordinate
operation.
+ * @param sourceCRS the potentially three-dimensional source CRS
* @param source3D {@code true} for adding ellipsoidal height in source
coordinates.
+ * @param targetCRS the potentially three-dimensional target CRS
* @param target3D {@code true} for adding ellipsoidal height in target
coordinates.
+ * @param operation the original (typically two-dimensional) coordinate
operation.
* @return a coordinate operation with the source and/or target
coordinates made 3D,
* or {@code null} if this method does not know how to create the
operation.
* @throws IllegalArgumentException if the operation method can not have
the desired number of dimensions.
* @throws FactoryException if an error occurred while creating the
coordinate operation.
*/
- private CoordinateOperation propagateVertical(final CoordinateOperation
operation,
- final boolean source3D, final boolean target3D) throws
IllegalArgumentException, FactoryException
+ private CoordinateOperation propagateVertical(final
CoordinateReferenceSystem sourceCRS, final boolean source3D,
+ final
CoordinateReferenceSystem targetCRS, final boolean target3D,
+ final CoordinateOperation
operation)
+ throws IllegalArgumentException, FactoryException
{
final List<CoordinateOperation> operations = new
ArrayList<CoordinateOperation>();
if (operation instanceof ConcatenatedOperation) {
@@ -719,8 +730,8 @@ class CoordinateOperationRegistry {
} else {
operations.add(operation);
}
- if ((source3D && !propagateVertical(operations.listIterator(), true))
||
- (target3D &&
!propagateVertical(operations.listIterator(operations.size()), false)))
+ if ((source3D && !propagateVertical(sourceCRS, targetCRS,
operations.listIterator(), true)) ||
+ (target3D && !propagateVertical(sourceCRS, targetCRS,
operations.listIterator(operations.size()), false)))
{
return null;
}
@@ -737,13 +748,18 @@ class CoordinateOperationRegistry {
* Appends a vertical axis in the source CRS of the first step {@code
forward = true} or in
* the target CRS of the last step {@code forward = false} of the given
operations chain.
*
+ * @param source3D the potentially three-dimensional source CRS
+ * @param target3D the potentially three-dimensional target CRS
* @param operations the chain of operations in which to add a vertical
axis.
* @param forward {@code true} for adding the vertical axis at the
beginning, or
* {@code false} for adding the vertical axis at the
end.
* @return {@code true} on success.
* @throws IllegalArgumentException if the operation method can not have
the desired number of dimensions.
*/
- private boolean propagateVertical(final ListIterator<CoordinateOperation>
operations, final boolean forward)
+ private boolean propagateVertical(final CoordinateReferenceSystem source3D,
+ final CoordinateReferenceSystem target3D,
+ final ListIterator<CoordinateOperation>
operations,
+ final boolean forward)
throws IllegalArgumentException, FactoryException
{
while (forward ? operations.hasNext() : operations.hasPrevious()) {
@@ -781,18 +797,18 @@ class CoordinateOperationRegistry {
if (op instanceof SingleOperation) {
final MathTransformFactory mtFactory =
factorySIS.getMathTransformFactory();
if (mtFactory instanceof DefaultMathTransformFactory) {
- final CoordinateReferenceSystem source3D =
toGeodetic3D(sourceCRS);
- final CoordinateReferenceSystem target3D =
toGeodetic3D(targetCRS);
+ if (forward) sourceCRS = toGeodetic3D(sourceCRS,
source3D);
+ else targetCRS = toGeodetic3D(targetCRS,
target3D);
final MathTransform mt;
try {
mt = ((DefaultMathTransformFactory)
mtFactory).createParameterizedTransform(
((SingleOperation)
op).getParameterValues(),
-
ReferencingUtilities.createTransformContext(source3D, target3D, null));
+
ReferencingUtilities.createTransformContext(sourceCRS, targetCRS, null));
} catch (InvalidGeodeticParameterException e) {
log(e);
break;
}
- operations.set(recreate(op, source3D, target3D, mt,
mtFactory.getLastMethodUsed()));
+ operations.set(recreate(op, sourceCRS, targetCRS, mt,
mtFactory.getLastMethodUsed()));
return true;
}
}
@@ -823,7 +839,7 @@ class CoordinateOperationRegistry {
* conform to the definition provided by the authority.
*/
final MathTransform mt =
factorySIS.getMathTransformFactory().createAffineTransform(matrix);
- operations.set(recreate(op, toGeodetic3D(sourceCRS),
toGeodetic3D(targetCRS), mt, null));
+ operations.set(recreate(op, toGeodetic3D(sourceCRS, source3D),
toGeodetic3D(targetCRS, target3D), mt, null));
}
/*
* If we processed the operation that change the number of
dimensions, we are done.
@@ -839,13 +855,27 @@ class CoordinateOperationRegistry {
* If the given CRS is two-dimensional, append an ellipsoidal height to it.
* It is caller's responsibility to ensure that the given CRS is
geographic.
*/
- private CoordinateReferenceSystem toGeodetic3D(CoordinateReferenceSystem
crs) throws FactoryException {
+ private CoordinateReferenceSystem toGeodetic3D(CoordinateReferenceSystem
crs,
+ final CoordinateReferenceSystem candidate) throws FactoryException
+ {
assert (crs instanceof GeodeticCRS) && (crs.getCoordinateSystem()
instanceof EllipsoidalCS) : crs;
- if (crs.getCoordinateSystem().getDimension() == 2) {
- crs =
ReferencingServices.getInstance().createCompoundCRS(factorySIS.getCRSFactory(),
factorySIS.getCSFactory(),
- derivedFrom(crs), crs,
CommonCRS.Vertical.ELLIPSOIDAL.crs());
+ if (crs.getCoordinateSystem().getDimension() != 2) {
+ return crs;
+ }
+ /*
+ * The check for same class is a cheap way to ensure that the two CRS
implement the same GeoAPI interface.
+ * This test is stricter than necessary, but the result should still
not wrong if we miss an opportunity
+ * to return the existing instance.
+ */
+ if (crs.getClass() == candidate.getClass() &&
candidate.getCoordinateSystem().getDimension() == 3) {
+ if (Utilities.equalsIgnoreMetadata(((SingleCRS) crs).getDatum(),
((SingleCRS) candidate).getDatum())) {
+ return candidate; // Keep the existing instance
since it may contain useful metadata.
+ }
}
- return crs;
+ return ReferencingServices.getInstance().createCompoundCRS(
+ factorySIS.getCRSFactory(),
+ factorySIS.getCSFactory(),
+ derivedFrom(crs), crs, CommonCRS.Vertical.ELLIPSOIDAL.crs());
}
/**
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -44,6 +44,7 @@ import org.apache.sis.referencing.factor
import
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
import org.apache.sis.util.collection.WeakHashSet;
import org.apache.sis.util.collection.Containers;
+import org.apache.sis.util.collection.Cache;
import org.apache.sis.util.iso.AbstractFactory;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.ArgumentChecks;
@@ -121,10 +122,21 @@ public class DefaultCoordinateOperationF
/**
* Weak references to existing objects.
* This set is used in order to return a pre-existing object instead of
creating a new one.
+ * This apply to object created explicitly, not to coordinate operations
inferred by a call
+ * to {@link #createOperation(CoordinateReferenceSystem,
CoordinateReferenceSystem)}.
*/
private final WeakHashSet<IdentifiedObject> pool;
/**
+ * The cache of coordinate operations found for a given pair of source and
target CRS.
+ * If current implementation, we cache only operations found without
context (otherwise
+ * we would need to take in account the area of interest and desired
accuracy in the key).
+ *
+ * @see #createOperation(CoordinateReferenceSystem,
CoordinateReferenceSystem, CoordinateOperationContext)
+ */
+ final Cache<CRSPair,CoordinateOperation> cache;
+
+ /**
* Constructs a factory with no default properties.
*/
public DefaultCoordinateOperationFactory() {
@@ -167,6 +179,7 @@ public class DefaultCoordinateOperationF
mtFactory = factory;
}
pool = new WeakHashSet<IdentifiedObject>(IdentifiedObject.class);
+ cache = new Cache<CRSPair,CoordinateOperation>(12, 50, true);
}
/**
@@ -697,9 +710,32 @@ next: for (int i=components.size(); --
final
CoordinateOperationContext context)
throws OperationNotFoundException, FactoryException
{
- final AuthorityFactory registry = USE_EPSG_FACTORY ?
CRS.getAuthorityFactory(Constants.EPSG) : null;
- return new CoordinateOperationFinder((registry instanceof
CoordinateOperationAuthorityFactory) ?
- (CoordinateOperationAuthorityFactory) registry : null, this,
context).createOperation(sourceCRS, targetCRS);
+ 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 = new CoordinateOperationFinder((registry instanceof
CoordinateOperationAuthorityFactory) ?
+ (CoordinateOperationAuthorityFactory) registry : null,
this, context).createOperation(sourceCRS, targetCRS);
+ }
+ } finally {
+ if (handler != null) {
+ handler.putAndUnlock(op);
+ }
+ }
+ return op;
}
/**
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -20,6 +20,7 @@ import java.util.Map;
import java.util.HashMap;
import javax.xml.bind.annotation.XmlTransient;
import javax.measure.unit.Unit;
+import org.opengis.metadata.Identifier;
import org.opengis.util.InternationalString;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;
@@ -34,9 +35,6 @@ import org.apache.sis.internal.referenci
import org.apache.sis.metadata.iso.ImmutableIdentifier;
import org.apache.sis.util.Deprecable;
-// Branch-dependent imports
-import org.opengis.metadata.Identifier;
-
/**
* Description of the inverse of another method. This class should be used
only when no operation is defined
Modified:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -115,9 +115,9 @@ final class SubOperationInfo {
final Class<?> targetType = type(target);
for (final Class<?>[] sourceTypes : COMPATIBLE_TYPES) {
if (sourceTypes[0].isAssignableFrom(targetType)) {
- int startAtDimension;
- int endAtDimension = 0;
for (final Class<?> sourceType : sourceTypes) {
+ int startAtDimension;
+ int endAtDimension = 0;
for (int i=0; i<sourceIsUsed.length; i++) {
final SingleCRS source = sources.get(i);
startAtDimension = endAtDimension;
@@ -130,7 +130,7 @@ final class SubOperationInfo {
if (failure == null) {
failure = exception;
} else {
- // failure.addSuppressed(exception);
+ // failure.addSuppressed(exception) on the
JDK7 branch.
}
continue;
}
Modified:
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -513,6 +513,44 @@ public final strictfp class CoordinateOp
//////////////////////////////////////////////////////////////////////////////////
/**
+ * Tests the conversion from a four-dimensional geographic CRS to a
two-dimensional geographic CRS.
+ * The vertical and temporal dimensions are simply dropped.
+ *
+ * @throws FactoryException if the operation can not be created.
+ * @throws TransformException if an error occurred while converting the
test points.
+ */
+ @Test
+ @DependsOnMethod("testGeographic3D_to_2D")
+ public void testGeographic4D_to_2D() throws FactoryException,
TransformException {
+ // NOTE: make sure that the 'sourceCRS' below is not equal to any
other 'sourceCRS' created in this class.
+ final CompoundCRS sourceCRS = compound("Test4D",
CommonCRS.WGS84.geographic3D(), CommonCRS.Temporal.UNIX.crs());
+ final GeographicCRS targetCRS = CommonCRS.WGS84.geographic();
+ final CoordinateOperation operation =
inference.createOperation(sourceCRS, targetCRS);
+ assertSame ("sourceCRS", sourceCRS,
operation.getSourceCRS());
+ assertSame ("targetCRS", targetCRS,
operation.getTargetCRS());
+
+ transform = operation.getMathTransform();
+ assertInstanceOf("transform", LinearTransform.class, transform);
+ assertEquals("sourceDimensions", 4, transform.getSourceDimensions());
+ assertEquals("targetDimensions", 2, transform.getTargetDimensions());
+ Assert.assertMatrixEquals("transform.matrix", Matrices.create(3, 5,
new double[] {
+ 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1
+ }), ((LinearTransform) transform).getMatrix(), STRICT);
+
+ isInverseTransformSupported = false;
+ verifyTransform(new double[] {
+ 30, 10, 20, 1000,
+ 20, 30, -10, 3000
+ }, new double[] {
+ 30, 10,
+ 20, 30
+ });
+ validate();
+ }
+
+ /**
* Tests the conversion from a three-dimensional geographic CRS to a
two-dimensional geographic CRS.
* The vertical dimension is simply dropped.
*
@@ -640,6 +678,46 @@ public final strictfp class CoordinateOp
}
/**
+ * Tests extracting the vertical part of a spatio-temporal CRS.
+ *
+ * @throws FactoryException if the operation can not be created.
+ * @throws TransformException if an error occurred while converting the
test points.
+ */
+ @Test
+ @DependsOnMethod("testGeographic3D_to_EllipsoidalHeight")
+ public void testGeographic4D_to_EllipsoidalHeight() throws
FactoryException, TransformException {
+ // NOTE: make sure that the 'sourceCRS' below is not equal to any
other 'sourceCRS' created in this class.
+ final CompoundCRS sourceCRS = compound("Test4D",
CommonCRS.WGS84.geographic3D(), CommonCRS.Temporal.JULIAN.crs());
+ final VerticalCRS targetCRS = CommonCRS.Vertical.ELLIPSOIDAL.crs();
+ final CoordinateOperation operation =
inference.createOperation(sourceCRS, targetCRS);
+ assertSame ("sourceCRS", sourceCRS,
operation.getSourceCRS());
+ assertSame ("targetCRS", targetCRS,
operation.getTargetCRS());
+ assertEquals ("name", "Axis changes",
operation.getName().getCode());
+ assertInstanceOf("operation", Conversion.class, operation);
+
+ transform = operation.getMathTransform();
+ assertInstanceOf("transform", LinearTransform.class, transform);
+ assertEquals("sourceDimensions", 4, transform.getSourceDimensions());
+ assertEquals("targetDimensions", 1, transform.getTargetDimensions());
+ Assert.assertMatrixEquals("transform.matrix", Matrices.create(2, 5,
new double[] {
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1
+ }), ((LinearTransform) transform).getMatrix(), STRICT);
+
+ isInverseTransformSupported = false;
+ verifyTransform(new double[] {
+ 0, 0, 0, 0,
+ 5, 8, 20, 10,
+ -5, -8, 24, 30
+ }, new double[] {
+ 0,
+ 20,
+ 24,
+ });
+ validate();
+ }
+
+ /**
* Convenience method for creating a compound CRS.
*/
private static CompoundCRS compound(final String name, final
CoordinateReferenceSystem... components) {
@@ -713,6 +791,7 @@ public final strictfp class CoordinateOp
@Test
@DependsOnMethod("testTemporalConversion")
public void testGeographic3D_to_4D() throws FactoryException,
TransformException {
+ // NOTE: make sure that the 'sourceCRS' below is not equal to any
other 'sourceCRS' created in this class.
final CompoundCRS sourceCRS = compound("Test3D",
CommonCRS.WGS84.geographic(), CommonCRS.Temporal.UNIX.crs());
final CompoundCRS targetCRS = compound("Test4D",
CommonCRS.WGS84.geographic3D(), CommonCRS.Temporal.MODIFIED_JULIAN.crs());
final CoordinateOperation operation =
inference.createOperation(sourceCRS, targetCRS);
Modified:
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
URL:
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java?rev=1740399&r1=1740398&r2=1740399&view=diff
==============================================================================
---
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
[UTF-8] (original)
+++
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
[UTF-8] Thu Apr 21 20:07:44 2016
@@ -328,7 +328,7 @@ public final strictfp class CoordinateOp
} else {
assertEpsgNameWithoutIdentifierEqual("NTF (Paris) to WGS 84 (1)",
operation);
assertEpsgNameWithoutIdentifierEqual("NTF (Paris)",
operation.getSourceCRS());
- assertEpsgNameWithoutIdentifierEqual("WGS 84",
operation.getTargetCRS());
+ assertEquals("name", "WGS 84",
operation.getTargetCRS().getName().getCode());
assertEpsgNameWithoutIdentifierEqual("NTF (Paris) to NTF (1)",
step1);
assertEpsgNameWithoutIdentifierEqual("NTF to WGS 84 (1)",
step2);
}