You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2022/11/15 09:23:26 UTC
[sis] 03/04: If the unmarshalled operation in is a defining conversion, complete the conversion.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sis.git
commit a7d1c7e0a3ce4b1b1f746df133571a2d9d02ddc4
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon Oct 31 12:35:59 2022 +0100
If the unmarshalled operation in <gml:PassThroughOperation> is a defining conversion, complete the conversion.
---
.../referencing/CC_GeneralOperationParameter.java | 10 +-
.../jaxb/referencing/CC_GeneralParameterValue.java | 2 +-
.../jaxb/referencing/CC_OperationMethod.java | 2 +-
.../sis/referencing/crs/AbstractDerivedCRS.java | 13 +--
.../operation/AbstractCoordinateOperation.java | 20 +---
.../operation/AbstractSingleOperation.java | 3 +-
.../referencing/operation/DefaultConversion.java | 18 ++--
.../operation/DefaultPassThroughOperation.java | 116 +++++++++++++++------
.../apache/sis/referencing/operation/SubTypes.java | 2 +-
9 files changed, 112 insertions(+), 74 deletions(-)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
index bc58625c90..f99929afff 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
@@ -171,12 +171,14 @@ public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralO
* to occur in some arbitrary place.
*
* @param descriptor the descriptor to validate.
+ * @param parent the name of the element to report as the parent of {@code property}.
* @param property the name of the property to report as missing if an exception is thrown.
* @throws GeodeticException if the parameters are missing or invalid.
*/
- static void validate(final GeneralParameterDescriptor descriptor, String property) {
+ static void validate(final GeneralParameterDescriptor descriptor, final String parent, final String property) {
if (descriptor == null || descriptor.getName() == null) {
- short key = Errors.Keys.MissingValueForProperty_1;
+ short key = Errors.Keys.MissingComponentInElement_2;
+ String[] args = {parent, property};
/*
* The exception thrown by this method must be unchecked,
* otherwise JAXB just reports is without propagating it.
@@ -185,10 +187,10 @@ public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralO
final String link = ((IdentifiedObject) descriptor).getIdentifierMap().get(IdentifierSpace.XLINK);
if (link != null) {
key = Errors.Keys.NotABackwardReference_1;
- property = link;
+ args = new String[] {link};
}
}
- throw new GeodeticException(Errors.format(key, property));
+ throw new GeodeticException(Errors.format(key, args));
}
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralParameterValue.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralParameterValue.java
index ba45ef344c..b52c4952ff 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralParameterValue.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralParameterValue.java
@@ -110,6 +110,6 @@ public final class CC_GeneralParameterValue extends PropertyType<CC_GeneralParam
*/
public void setElement(final GeneralParameterValue parameter) {
metadata = parameter;
- CC_GeneralOperationParameter.validate(parameter.getDescriptor(), "<gml:operationParameter>");
+ CC_GeneralOperationParameter.validate(parameter.getDescriptor(), "ParameterValue", "operationParameter");
}
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java
index 6eb815ffad..ed050b78ba 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java
@@ -108,7 +108,7 @@ public final class CC_OperationMethod extends PropertyType<CC_OperationMethod, O
*/
public void setElement(final DefaultOperationMethod method) {
metadata = method;
- CC_GeneralOperationParameter.validate(method.getParameters(), "<gml:parameter>");
+ CC_GeneralOperationParameter.validate(method.getParameters(), "OperationMethod", "parameter");
}
/**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
index e4547697b6..e3b6407963 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
@@ -22,7 +22,6 @@ import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.ValidationException;
import org.opengis.util.FactoryException;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.crs.SingleCRS;
@@ -34,12 +33,12 @@ import org.opengis.referencing.operation.Conversion;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.geometry.MismatchedDimensionException;
+import org.apache.sis.referencing.GeodeticException;
import org.apache.sis.referencing.operation.DefaultConversion;
import org.apache.sis.internal.jaxb.referencing.CC_Conversion;
import org.apache.sis.internal.referencing.ReferencingFactoryContainer;
import org.apache.sis.internal.metadata.ImplementationHelper;
import org.apache.sis.internal.metadata.Identifiers;
-import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.system.Semaphores;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.ArgumentChecks;
@@ -54,7 +53,7 @@ import static org.apache.sis.util.Utilities.deepEquals;
* (not by a {@linkplain org.apache.sis.referencing.datum.AbstractDatum datum}).
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.2
+ * @version 1.3
*
* @param <C> the conversion type, either {@code Conversion} or {@code Projection}.
*
@@ -82,6 +81,7 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
*
* @see #getConversionFromBase()
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable.
private C conversionFromBase;
/**
@@ -162,9 +162,6 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
if (properties != null) {
factory = (MathTransformFactory) properties.get(ReferencingFactoryContainer.MT_FACTORY);
}
- if (factory == null) {
- factory = DefaultFactories.forBuildin(MathTransformFactory.class);
- }
try {
return DefaultConversion.castOrCopy(conversion).specialize(getConversionType(), baseCRS, this, factory);
} catch (FactoryException e) {
@@ -332,7 +329,7 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
* coordinate system (CS). The CS information is required by {@code createConversionFromBase(…)}
* in order to create a {@link MathTransform} with correct axis swapping and unit conversions.
*/
- private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws ValidationException {
+ private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
String property = "conversion";
if (conversionFromBase != null) {
final SingleCRS baseCRS = CC_Conversion.setBaseCRS(conversionFromBase, null); // Clear the temporary value now.
@@ -350,6 +347,6 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
* and call to `getConversionFromBase()` will throw a ClassCastException if this instance is actually
* a ProjectedCRS (because of the method overriding with return type covariance).
*/
- throw new ValidationException(Identifiers.missingValueForProperty(getName(), property));
+ throw new GeodeticException(Identifiers.missingValueForProperty(getName(), property));
}
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index 589e5f7781..f7db0369b3 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
@@ -670,23 +670,8 @@ check: for (int isTarget=0; ; isTarget++) { // 0 == source check; 1
}
/**
- * Returns the object for transforming coordinates in the {@linkplain #getSourceCRS() source CRS}
- * to coordinates in the {@linkplain #getTargetCRS() target CRS}.
- *
- * <h4>Use with interpolation CRS</h4>
- * If the {@linkplain #getInterpolationCRS() interpolation CRS} is non-null, then the math transform
- * input coordinates shall by (<var>interpolation</var>, <var>source</var>) tuples: for each value
- * to transform, the interpolation point coordinates shall be first, followed by the source coordinates.
- *
- * <div class="note"><b>Example:</b>
- * in a transformation between two {@linkplain org.apache.sis.referencing.crs.DefaultVerticalCRS vertical CRS},
- * if the {@linkplain #getSourceCRS() source} coordinates are (<var>z</var>) values but the coordinate operation
- * additionally requires (<var>x</var>,<var>y</var>) values for {@linkplain #getInterpolationCRS() interpolation}
- * purpose, then the math transform input coordinates shall be (<var>x</var>,<var>y</var>,<var>z</var>) tuples in
- * that order.</div>
- *
- * The interpolation coordinates will {@linkplain DefaultPassThroughOperation pass through the operation}
- * and appear in the math transform outputs, in the same order than inputs.
+ * Returns the object for transforming coordinates in the source CRS to coordinates in the target CRS.
+ * The transform may be {@code null} if this coordinate operation is a defining conversion.
*
* @return the transform from source to target CRS, or {@code null} if not applicable.
*/
@@ -1208,6 +1193,7 @@ check: for (int isTarget=0; ; isTarget++) { // 0 == source check; 1
/**
* Invoked by JAXB after unmarshalling.
+ * May be overridden by subclasses.
*/
void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
computeTransientFields();
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
index 8d89447e1c..6fa4250a43 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
@@ -49,6 +49,7 @@ import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.internal.metadata.ImplementationHelper;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.metadata.Identifiers;
+import org.apache.sis.referencing.GeodeticException;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ComparisonMode;
@@ -408,7 +409,7 @@ class AbstractSingleOperation extends AbstractCoordinateOperation implements Sin
private void setParameters(final GeneralParameterValue[] values) {
if (parameters == null) {
if (!(method instanceof DefaultOperationMethod)) { // May be a non-null proxy if defined only by xlink:href.
- throw new IllegalStateException(Identifiers.missingValueForProperty(getName(), "method"));
+ throw new GeodeticException(Identifiers.missingValueForProperty(getName(), "method"));
}
/*
* The descriptors in the <gml:method> element do not know the class of parameter value
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
index 3fff4153d9..1732f7c091 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
@@ -36,6 +36,7 @@ import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactor
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.internal.referencing.Resources;
+import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.Utilities;
@@ -217,8 +218,8 @@ public class DefaultConversion extends AbstractSingleOperation implements Conver
/**
* Constructs a new conversion with the same values than the specified one, together with the
- * specified source and target CRS. While the source conversion can be an arbitrary one, it is
- * typically a defining conversion.
+ * specified source and target CRS. While the source conversion can be an arbitrary one,
+ * it is typically a defining conversion.
*
* @param definition the defining conversion.
* @param source the new source CRS.
@@ -376,13 +377,14 @@ public class DefaultConversion extends AbstractSingleOperation implements Conver
*
* This {@code specialize(…)} method returns a conversion which implement at least the given {@code baseType}
* interface, but may also implement a more specific GeoAPI interface if {@code specialize(…)} has been able
- * to infer the type from this operation {@linkplain #getMethod() method}.
+ * to infer the type from the {@linkplain #getMethod() operation method}.
*
* @param <T> compile-time type of the {@code baseType} argument.
* @param baseType the base GeoAPI interface to be implemented by the conversion to return.
* @param sourceCRS the source CRS.
* @param targetCRS the target CRS.
- * @param factory the factory to use for creating a transform from the parameters or for performing axis changes.
+ * @param factory the factory to use for creating a transform from the parameters or for performing axis changes,
+ * or {@code null} for the default factory.
* @return the conversion of the given type between the given CRS.
* @throws ClassCastException if a contradiction is found between the given {@code baseType},
* the defining {@linkplain DefaultConversion#getInterface() conversion type} and
@@ -397,12 +399,11 @@ public class DefaultConversion extends AbstractSingleOperation implements Conver
*/
public <T extends Conversion> T specialize(final Class<T> baseType,
final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS,
- final MathTransformFactory factory) throws FactoryException
+ MathTransformFactory factory) throws FactoryException
{
ArgumentChecks.ensureNonNull("baseType", baseType);
ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
- ArgumentChecks.ensureNonNull("factory", factory);
/*
* Conceptual consistency check: verify that the new CRS use the same datum than the previous ones,
* since the purpose of this method is not to apply datum changes. Datum changes are the purpose of
@@ -425,6 +426,9 @@ public class DefaultConversion extends AbstractSingleOperation implements Conver
ensureCompatibleDatum("targetCRS", sourceCRS, super.getTargetCRS());
}
}
+ if (factory == null) {
+ factory = DefaultFactories.forBuildin(MathTransformFactory.class);
+ }
return SubTypes.create(baseType, this, sourceCRS, targetCRS, factory);
}
@@ -505,7 +509,7 @@ public class DefaultConversion extends AbstractSingleOperation implements Conver
/**
* Constructs a new object in which every attributes are set to a null value.
* <strong>This is not a valid object.</strong> This constructor is strictly
- * reserved to JAXB, which will assign values to the fields using reflexion.
+ * reserved to JAXB, which will assign values to the fields using reflection.
*/
private DefaultConversion() {
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
index 411ea47aab..60749dbaa6 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
@@ -19,36 +19,43 @@ package org.apache.sis.referencing.operation;
import java.util.Map;
import java.util.Arrays;
import java.util.Objects;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opengis.util.FactoryException;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.PassThroughOperation;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.CompoundCRS;
+import org.apache.sis.referencing.GeodeticException;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.operation.transform.PassThroughTransform;
import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.internal.metadata.ImplementationHelper;
import org.apache.sis.util.UnsupportedImplementationException;
-import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
+import org.apache.sis.referencing.CRS;
import static org.apache.sis.util.Utilities.deepEquals;
+import org.opengis.referencing.operation.Conversion;
+// Branch-dependent imports
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.SingleOperation;
+
/**
* Specifies that a subset of a coordinate tuple is subject to a specific coordinate operation.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 1.3
* @since 0.6
* @module
*/
@@ -114,9 +121,8 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
final int firstAffectedCoordinate,
final int numTrailingCoordinates)
{
- super(properties, sourceCRS, targetCRS, null, MathTransforms.passThrough(
- firstAffectedCoordinate, operation.getMathTransform(), numTrailingCoordinates));
- ArgumentChecks.ensureNonNull("operation", operation);
+ super(properties, sourceCRS, targetCRS, null,
+ MathTransforms.passThrough(firstAffectedCoordinate, operation.getMathTransform(), numTrailingCoordinates));
this.operation = operation;
}
@@ -223,11 +229,11 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
final MathTransform transform = super.getMathTransform();
if (transform instanceof PassThroughTransform) {
return ((PassThroughTransform) transform).getModifiedCoordinates();
- } else {
+ } else if (operation != null) {
/*
- * Should not happen with objects created by public methods since the constructor created the transform
- * itself. However may happen with operations parsed from GML. As a fallback, search in the components
- * of CompoundCRS. This is not a universal fallback, but work for the most straightforward cases.
+ * Should not happen with objects created by public methods since the constructor created the transform itself.
+ * However may happen with operations parsed from GML. As a fallback, search in the components of CompoundCRS.
+ * This is not a universal fallback, but works for the most straightforward cases.
*/
final CoordinateReferenceSystem sourceCRS = super.getSourceCRS();
if (sourceCRS instanceof CompoundCRS) {
@@ -245,8 +251,8 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
firstAffectedCoordinate += dim;
}
}
- throw new UnsupportedImplementationException(transform.getClass());
}
+ throw new UnsupportedImplementationException(transform.getClass());
}
/**
@@ -326,13 +332,13 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
/**
* Constructs a new object in which every attributes are set to a null value.
* <strong>This is not a valid object.</strong> This constructor is strictly
- * reserved to JAXB, which will assign values to the fields using reflexion.
+ * reserved to JAXB, which will assign values to the fields using reflection.
*/
private DefaultPassThroughOperation() {
/*
* A sub-operation is mandatory for SIS working. We do not verify its presence here because the verification
- * would have to be done in an 'afterMarshal(…)' method and throwing an exception in that method causes the
- * whole unmarshalling to fail. But the CC_CoordinateOperation adapter does some verifications.
+ * would have to be done in an `afterMarshal(…)` method and throwing an exception in that method causes the
+ * whole unmarshalling to fail. But the `CC_CoordinateOperation` adapter does some verifications.
*/
}
@@ -358,37 +364,79 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
*/
@XmlElement(name = "modifiedCoordinate", required = true)
private int[] getIndices() {
- final int[] indices = getModifiedCoordinates();
- for (int i=0; i<indices.length; i++) {
- indices[i]++;
+ final int[] dimensions = getModifiedCoordinates();
+ for (int i=0; i<dimensions.length; i++) {
+ dimensions[i]++;
}
- return indices;
+ return dimensions;
}
/**
* Invoked by JAXB at unmarshalling time for setting the modified coordinates.
+ * This method needs to be invoked last, even if the {@code <gml:modifiedCoordinate>}
+ * elements are not last in the GML document. It is the case when using JAXB because
+ * multiple occurrences of {@code <gml:modifiedCoordinate>} are aggregated in an array.
*/
- private void setIndices(final int[] coordinates) {
- String missing = "sourceCRS";
- final CoordinateReferenceSystem sourceCRS = super.getSourceCRS();
- if (sourceCRS != null) {
- missing = "modifiedCoordinate";
- if (coordinates != null && coordinates.length != 0) {
- missing = "coordOperation";
- if (operation != null) {
- for (int i=1; i<coordinates.length; i++) {
- final int previous = coordinates[i-1];
- if (previous < 1 || coordinates[i] != previous + 1) {
- throw new IllegalArgumentException(Errors.format(
- Errors.Keys.CanNotAssign_2, missing, Arrays.toString(coordinates)));
+ private void setIndices(final int[] dimensions) {
+ /*
+ * Argument and state validation.
+ */
+ String missing = "modifiedCoordinate";
+ FactoryException cause = null;
+ final int n = dimensions.length;
+ if (n != 0) {
+ if (!ArraysExt.isRange(dimensions[0], dimensions)) {
+ throw new GeodeticException(Errors.format(Errors.Keys.CanNotAssign_2, missing, Arrays.toString(dimensions)));
+ }
+ missing = "sourceCRS";
+ final CoordinateReferenceSystem sourceCRS = super.getSourceCRS();
+ if (sourceCRS != null) {
+ missing = "targetCRS";
+ final CoordinateReferenceSystem targetCRS = super.getTargetCRS();
+ if (targetCRS != null) {
+ missing = "coordOperation";
+ if (operation != null) {
+ /*
+ * If the operation is a defining operation, we need to replace it by a full operation.
+ * After that, we can store the modified coordinate indices in the transform field.
+ */
+ MathTransform subTransform = operation.getMathTransform();
+ if (operation instanceof Conversion) {
+ CoordinateReferenceSystem sourceSub = operation.getSourceCRS();
+ CoordinateReferenceSystem targetSub = operation.getTargetCRS();
+ if (subTransform == null || sourceSub == null || targetSub == null) try {
+ final int[] zeroBased = dimensions.clone();
+ for (int i=0; i<n; i++) zeroBased[i]--;
+ if (sourceSub == null) sourceSub = CRS.selectDimensions(sourceCRS, zeroBased);
+ if (targetSub == null) targetSub = CRS.selectDimensions(targetCRS, zeroBased);
+ operation = DefaultConversion.castOrCopy((Conversion) operation)
+ .specialize(Conversion.class, sourceSub, targetSub, null);
+ subTransform = operation.getMathTransform();
+ } catch (FactoryException e) {
+ cause = e;
+ }
+ }
+ if (subTransform != null) {
+ transform = MathTransforms.passThrough(dimensions[0] - 1, subTransform,
+ ReferencingUtilities.getDimension(sourceCRS) - dimensions[n-1]);
+ return;
}
}
- transform = MathTransforms.passThrough(coordinates[0] - 1, operation.getMathTransform(),
- ReferencingUtilities.getDimension(sourceCRS) - coordinates[coordinates.length - 1]);
- return;
}
}
}
- throw new IllegalStateException(Errors.format(Errors.Keys.MissingComponentInElement_2, missing, "PassThroughOperation"));
+ throw new GeodeticException(Errors.format(Errors.Keys.MissingComponentInElement_2, "PassThroughOperation", missing), cause);
+ }
+
+ /**
+ * Invoked by JAXB after unmarshalling. If needed, this method tries to infer source/target CRS
+ * of the nested operation from the source/target CRS if the enclosing pass-through operation.
+ */
+ @Override
+ void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+ super.afterUnmarshal(unmarshaller, parent);
+ if (transform == null) {
+ setIndices(ArraysExt.EMPTY_INT); // Cause an exception to be thrown.
+ }
}
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
index f525f8d809..90670bad4b 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
@@ -179,7 +179,7 @@ final class SubTypes {
conversion = new DefaultConversion(definition, sourceCRS, targetCRS, factory, actual);
}
/*
- * The DefaultConversion constructor may have used by MathTransformFactory for creating the actual
+ * The DefaultConversion constructor may have used MathTransformFactory for creating the actual
* MathTransform object. In such case, we can use the knownledge that the factory has about the
* coordinate operation for refining again the type of the object to be returned.
*/