This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 973019be6b42517022f10b037d3b8f51a1fe3925 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sat Jul 6 15:58:19 2024 +0200 Reduce usage of deprecated methods, and consolidation. --- .../org/apache/sis/io/wkt/MathTransformParser.java | 11 +- .../sis/referencing/MultiRegisterOperations.java | 2 +- .../referencing/factory/IdentifiedObjectSet.java | 5 +- .../internal/ParameterizedTransformBuilder.java | 45 +++------ .../sis/referencing/operation/package-info.java | 14 --- .../operation/projection/NormalizedProjection.java | 3 +- .../CoordinateSystemTransformBuilder.java | 29 +----- .../transform/DefaultMathTransformFactory.java | 95 ++++-------------- .../operation/transform/MathTransformBuilder.java | 111 +++++++++++++++++++++ .../projection/MapProjectionTestCase.java | 3 +- .../transform/MathTransformFactoryMock.java | 51 +++++++--- .../apache/sis/util/privy/MetadataServices.java | 2 +- geoapi/snapshot | 2 +- 13 files changed, 198 insertions(+), 175 deletions(-) diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java index 282575dc0a..0226437ebc 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java @@ -415,10 +415,9 @@ class MathTransformParser extends AbstractParser { return null; } classification = element.pullString("classification"); - final MathTransformFactory mtFactory = factories.getMathTransformFactory(); - final ParameterValueGroup parameters; + final MathTransform.Builder builder; try { - parameters = mtFactory.getDefaultParameters(classification); + builder = factories.getMathTransformFactory().builder(classification); } catch (NoSuchIdentifierException exception) { throw element.parseFailed(exception); } @@ -426,18 +425,18 @@ class MathTransformParser extends AbstractParser { * Scan over all PARAMETER["name", value] elements and * set the corresponding parameter in the parameter group. */ - parseParameters(element, parameters, null, null); + parseParameters(element, builder.parameters(), null, null); element.close(ignoredElements); /* * We now have all information for constructing the math transform. */ final MathTransform transform; try { - transform = mtFactory.createParameterizedTransform(parameters); + transform = builder.create(); } catch (FactoryException exception) { throw element.parseFailed(exception); } - lastMethod = mtFactory.getLastMethodUsed(); + lastMethod = builder.getMethod().orElse(null); return transform; } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/MultiRegisterOperations.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/MultiRegisterOperations.java index 6bf7628dbd..db0cdca8e4 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/MultiRegisterOperations.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/MultiRegisterOperations.java @@ -416,7 +416,7 @@ public class MultiRegisterOperations extends AbstractFactory implements Register * @throws IllegalArgumentException if the specified type is not one of the above-cited values. */ @Override - public <T extends Factory> Optional<T> getFactory(final Class<T> type) { + public <T extends Factory> Optional<T> getFactory(final Class<? extends T> type) { final Factory factory; final Boolean b = FACTORY_TYPES.get(type); if (b != null) { diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java index 5f5ac29be8..3abc6e9f4b 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java @@ -533,9 +533,8 @@ public class IdentifiedObjectSet<T extends IdentifiedObject> extends AbstractSet * <li>If {@link NoSuchAuthorityCodeException}, returns {@code false} since failure to find a code declared * in the collection would be an inconsistency. Note that this exception is a subtype of * {@code NoSuchIdentifierException}, so it must be tested before the last case below.</li> - * <li>If {@link NoSuchIdentifierException}, returns {@code true} since this exception is caused by an attempt to - * {@linkplain org.opengis.referencing.operation.MathTransformFactory#createParameterizedTransform - * create a parameterized transform} for an unimplemented operation.</li> + * <li>If {@link NoSuchIdentifierException}, returns {@code true} because this exception is caused + * by an attempt to create a parameterized transform for an unimplemented operation.</li> * <li>If {@link MissingFactoryResourceException}, returns {@code true}.</li> * <li>Otherwise returns {@code false}.</li> * </ul> diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java index bab03dcdb0..d439168dd4 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java @@ -19,7 +19,6 @@ package org.apache.sis.referencing.internal; import java.util.Map; import java.util.LinkedHashMap; import java.util.Collections; -import java.util.Optional; import java.util.OptionalInt; import java.util.logging.Level; import java.util.logging.LogRecord; @@ -55,6 +54,7 @@ import org.apache.sis.referencing.operation.matrix.Matrices; import org.apache.sis.referencing.operation.provider.AbstractProvider; import org.apache.sis.referencing.operation.provider.VerticalOffset; import org.apache.sis.referencing.operation.transform.MathTransforms; +import org.apache.sis.referencing.operation.transform.MathTransformBuilder; import org.apache.sis.referencing.operation.transform.ContextualParameters; import org.apache.sis.referencing.operation.transform.MathTransformProvider; import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory; @@ -87,7 +87,7 @@ import org.opengis.util.UnimplementedServiceException; * * @author Martin Desruisseaux (Geomatys) */ -public class ParameterizedTransformBuilder implements MathTransform.Builder, MathTransformProvider.Context { +public class ParameterizedTransformBuilder extends MathTransformBuilder implements MathTransformProvider.Context { /** * Minimal precision of ellipsoid semi-major and semi-minor axis lengths, in metres. * If the length difference between the axis of two ellipsoids is greater than this threshold, @@ -96,11 +96,6 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat */ private static final double ELLIPSOID_PRECISION = Formulas.LINEAR_TOLERANCE; - /** - * The factory to use for building the transform. - */ - private final MathTransformFactory factory; - /** * Coordinate system of the source or target points. */ @@ -111,15 +106,6 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat */ private Ellipsoid sourceEllipsoid, targetEllipsoid; - /** - * The provider that created the parameterized {@link MathTransform} instance, or {@code null} - * if this information does not apply. This is initially set to the operation method specified - * in the call to {@link #builder(String)}, but may be modified by {@link #create()}. - * - * @see #getMethod() - */ - protected OperationMethod provider; - /** * The parameters of the transform to create. This is initialized to default values. * The instance is returned directly by {@link #parameters()} for allowing users to @@ -163,7 +149,7 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat * @param method a method known to the given factory, or {@code null} if none. */ public ParameterizedTransformBuilder(final MathTransformFactory factory, final OperationMethod method) { - this.factory = factory; + super(factory); if (method != null) { provider = method; parameters = method.getParameters().createValue(); @@ -365,19 +351,6 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat } } - /** - * Returns the operation method used for creating the math transform from the parameter values. - * This is initially the operation method specified in the call to {@link #builder(String)}, - * but may change after the call to {@link #create()} if the method has been adjusted because - * of the parameter values. - * - * @return the operation method used for creating the math transform from the parameter values. - */ - @Override - public final Optional<OperationMethod> getMethod() { - return Optional.ofNullable(provider); - } - /** * Returns the parameter values to modify for defining the transform to create. * Those parameters are initialized to default values, which are {@linkplain #getMethod() method} depend. @@ -453,7 +426,7 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat * Returns the value of the given parameter in the given unit, or {@code NaN} if the parameter is not set. * * <p><b>NOTE:</b> Do not merge this function with {@code ensureSet(…)}. We keep those two methods - * separated in order to give to {@code createParameterizedTransform(…)} a "all or nothing" behavior.</p> + * separated in order to give to {@code completeParameters()} an "all or nothing" behavior.</p> */ private static double getValue(final ParameterValue<?> parameter, final Unit<?> unit) { return (parameter.getValue() != null) ? parameter.doubleValue(unit) : Double.NaN; @@ -665,6 +638,10 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat : DefaultMathTransformFactory.provider()).getOperationMethod(method); } } + /* + * Will catch only exceptions that may be the result of improper parameter usage (e.g. a value out + * of range). Do not catch exceptions caused by programming errors (e.g. null pointer exception). + */ final MathTransform transform; if (provider instanceof MathTransformProvider) try { transform = ((MathTransformProvider) provider).createMathTransform(this); @@ -677,7 +654,7 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat if (provider instanceof AbstractProvider) { provider = ((AbstractProvider) provider).variantFor(transform); } - return swapAndScaleAxes(transform); + return swapAndScaleAxes(unique(transform)); } catch (FactoryException exception) { if (warning != null) { exception.addSuppressed(warning); @@ -807,7 +784,9 @@ public class ParameterizedTransformBuilder implements MathTransform.Builder, Mat * created transform; it does not change the operation. */ if (normalized instanceof ParameterizedAffine && !(mt instanceof ParameterizedAffine)) { - mt = ((ParameterizedAffine) normalized).newTransform(mt); + if (mt != (mt = ((ParameterizedAffine) normalized).newTransform(mt))) { + mt = unique(mt); + } } return mt; } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/package-info.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/package-info.java index 3895167703..00874455c0 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/package-info.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/package-info.java @@ -34,20 +34,6 @@ * — changes a <i>defining conversion</i> into a complete conversion.</li> * </ul> * - * <h2>Apache SIS specific behavior</h2> - * The following operations have a behavior in Apache SIS which may be different - * than the behavior found in other software products. Those particularities apply only when the math transform is - * {@linkplain org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory#createParameterizedTransform - * created directly}. Users do not need to care about them when the coordinate operation is - * {@linkplain org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#createOperation - * inferred by Apache SIS for a given pair of CRS}. - * - * <ul> - * <li><b>Longitude rotation</b> (EPSG:9601) — the longitude offset may be specified in any units, - * but SIS unconditionally converts the value to degrees. Consequently, the user is responsible - * for converting the longitude axis of source and target CRS to degrees before this operation is applied.</li> - * </ul> - * * <h2><i>Early binding</i> versus <i>late binding</i> implementations</h2> * There is sometimes multiple ways of transforming coordinates for a given pair of source and target CRS. * For example, the {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters} diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java index 1226a486e1..f3f8c3368d 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java @@ -99,8 +99,7 @@ import org.opengis.metadata.Identifier; * The first matrix on the left side is for {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes * swapping axes} from (<var>latitude</var>, <var>longitude</var>) to (<var>longitude</var>, <var>latitude</var>) order. * This matrix is shown here for completeness, but is not managed by this projection package. Axes swapping is managed - * at a {@linkplain org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory#createParameterizedTransform - * higher level}.</div> + * at a {@linkplain org.apache.sis.referencing.internal.ParameterizedTransformBuilder higher level}.</div> * * {@code NormalizedProjection} does not store the above cited parameters (central meridian, scale factor, <i>etc.</i>) * on intent (except indirectly), in order to make clear that those parameters are not used by subclasses. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java index 930a981f92..3229427266 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/CoordinateSystemTransformBuilder.java @@ -18,7 +18,6 @@ package org.apache.sis.referencing.operation.transform; import java.util.List; import java.util.ArrayList; -import java.util.Optional; import javax.measure.IncommensurableException; import org.opengis.util.FactoryException; import org.opengis.parameter.ParameterValueGroup; @@ -32,7 +31,6 @@ import org.opengis.referencing.cs.PolarCS; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransformFactory; import org.opengis.referencing.operation.OperationNotFoundException; -import org.opengis.referencing.operation.OperationMethod; import org.apache.sis.referencing.cs.AxesConvention; import org.apache.sis.referencing.cs.CoordinateSystems; import org.apache.sis.referencing.cs.DefaultCompoundCS; @@ -48,12 +46,7 @@ import org.apache.sis.util.resources.Errors; * * @author Martin Desruisseaux (Geomatys) */ -class CoordinateSystemTransformBuilder implements MathTransform.Builder { - /** - * The factory to use for building the transform. - */ - protected final MathTransformFactory factory; - +final class CoordinateSystemTransformBuilder extends MathTransformBuilder { /** * The source and target coordinate systems. */ @@ -66,18 +59,13 @@ class CoordinateSystemTransformBuilder implements MathTransform.Builder { */ private Ellipsoid ellipsoid; - /** - * The operation method used for the transform. - */ - private OperationMethod method; - /** * Creates a new builder. * * @param factory the factory to use for building the transform. */ CoordinateSystemTransformBuilder(final MathTransformFactory factory) { - this.factory = factory; + super(factory); } /** @@ -110,15 +98,6 @@ class CoordinateSystemTransformBuilder implements MathTransform.Builder { } } - /** - * Returns the operation method used for creating the math transform from the parameter values. - * This information is known only after {@link #create()} has been invoked. - */ - @Override - public Optional<OperationMethod> getMethod() { - return Optional.ofNullable(method); - } - /** * Unsupported operation because this builder has no parameters. */ @@ -213,7 +192,7 @@ class CoordinateSystemTransformBuilder implements MathTransform.Builder { if (result == null) { result = single(source, target); } - return result; + return unique(result); } /** @@ -263,7 +242,7 @@ class CoordinateSystemTransformBuilder implements MathTransform.Builder { CoordinateSystems.replaceAxes(stepTarget, AxesConvention.NORMALIZED), stepTarget)); final MathTransform result = factory.createConcatenatedTransform(before, factory.createConcatenatedTransform(tr, after)); - method = (passthrough == 0 ? kernel.method : kernel.method3D); + provider = (passthrough == 0 ? kernel.method : kernel.method3D); return result; } } catch (IllegalArgumentException | IncommensurableException e) { diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java index c44cc8c2b6..a408b92ac3 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java @@ -44,23 +44,17 @@ import org.opengis.util.FactoryException; import org.opengis.util.NoSuchIdentifierException; import org.apache.sis.io.wkt.Parser; import org.apache.sis.util.ArgumentChecks; -import org.apache.sis.util.Classes; import org.apache.sis.util.privy.Constants; import org.apache.sis.util.iso.AbstractFactory; -import org.apache.sis.util.resources.Errors; import org.apache.sis.util.collection.WeakHashSet; import org.apache.sis.referencing.privy.CoordinateOperations; import org.apache.sis.referencing.operation.DefaultOperationMethod; -import org.apache.sis.referencing.operation.provider.AbstractProvider; import org.apache.sis.referencing.operation.matrix.Matrices; import org.apache.sis.referencing.internal.ParameterizedTransformBuilder; import org.apache.sis.referencing.factory.InvalidGeodeticParameterException; import org.apache.sis.parameter.DefaultParameterValueGroup; import org.apache.sis.system.Reflect; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.util.UnimplementedServiceException; - /** * Low level factory for creating {@linkplain AbstractMathTransform math transforms}. @@ -191,12 +185,14 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math /** * The last coordinate operation method used by a {@code create(…)} constructor. */ - private final ThreadLocal<OperationMethod> lastMethod; + final ThreadLocal<OperationMethod> lastMethod; /** * The math transforms created so far. This pool is used in order to return instances of existing * math transforms when possible. If {@code null}, then no pool should be used. A null value is * preferable when the transforms are known to be short-lived, for avoiding the cost of caching them. + * + * @see #unique(MathTransform) */ private final WeakHashSet<MathTransform> pool; @@ -482,38 +478,9 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math @Override public MathTransform.Builder builder(final String method) throws NoSuchIdentifierException { if (method.replace('_', ' ').equalsIgnoreCase(Constants.COORDINATE_SYSTEM_CONVERSION)) { - return new CoordinateSystemTransformBuilder(this) { - @Override public MathTransform create() throws FactoryException { - try { - return super.create(); - } finally { - ((DefaultMathTransformFactory) factory).lastMethod.set(getMethod().orElse(null)); - } - } - }; - } - return new ContextBuilder(this, getOperationMethod(method)); - } - - /** - * Builder of a parameterized math transform, which is also the context for transform providers. - * Instances are created by {@link #builder(String)}. The same instance is also used for context - * given to {@link MathTransformProvider}. - */ - private static final class ContextBuilder extends ParameterizedTransformBuilder { - /** Creates a new builder for the given operation method. */ - ContextBuilder(final DefaultMathTransformFactory factory, final OperationMethod method) { - super(factory, method); - } - - /** Creates the parameterized transform. */ - @Override public MathTransform create() throws FactoryException { - try { - return super.create(); - } finally { - ((DefaultMathTransformFactory) getFactory()).lastMethod.set(provider); - } + return new CoordinateSystemTransformBuilder(this); } + return new ParameterizedTransformBuilder(this, getOperationMethod(method)); } /** @@ -533,8 +500,12 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math * @see #getAvailableMethods(Class) * @see #createParameterizedTransform(ParameterValueGroup) * @see AbstractMathTransform#getParameterValues() + * + * @deprecated This {@linkplain #createParameterizedTransform way to create parameterized transform} is ambiguous. + * Use {@link #builder(String)} instead. */ @Override + @Deprecated(since="1.5") public ParameterValueGroup getDefaultParameters(final String method) throws NoSuchIdentifierException { return getOperationMethod(method).getParameters().createValue(); } @@ -571,7 +542,7 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math /** * The builder, created when first needed. */ - private ContextBuilder builder; + private ParameterizedTransformBuilder builder; /** * The parameters actually used. @@ -703,12 +674,12 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math /** * Returns the builder on which to delegate the {@code MathTransform} creation. */ - final ContextBuilder builder() throws FactoryException { + final ParameterizedTransformBuilder builder() throws FactoryException { if (builder == null) { if (factory == null) { factory = provider(); } - builder = new ContextBuilder(factory, null); + builder = new ParameterizedTransformBuilder(factory, null); if (parameters != null) { builder.setParameters(parameters, false); } @@ -880,41 +851,19 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math * @see #getAvailableMethods(Class) * @see #getLastMethodUsed() * @see org.apache.sis.parameter.ParameterBuilder#createGroupForMapProjection(ParameterDescriptor...) + * + * @deprecated This constructor is ambiguous when axis directions are parts of the map projection definition + * as in <q>Transverse Mercator (South Orientated)</q>. + * Use {@link #builder(String)} instead for allowing the implementation to resolve such ambiguities. */ @Override + @Deprecated(since="1.5") public MathTransform createParameterizedTransform(final ParameterValueGroup parameters) throws NoSuchIdentifierException, FactoryException { - OperationMethod method = null; - RuntimeException failure = null; - MathTransform transform; - try { - method = CoordinateOperations.findMethod(this, parameters.getDescriptor()); - /* - * Will catch only exceptions that may be the result of improper parameter usage (e.g. a value out - * of range). Do not catch exceptions caused by programming errors (e.g. null pointer exception). - */ - if (method instanceof MathTransformProvider) try { - transform = ((MathTransformProvider) method).createMathTransform(this, parameters); - } catch (IllegalArgumentException | IllegalStateException exception) { - throw new InvalidGeodeticParameterException(exception.getLocalizedMessage(), exception); - } else { - throw new UnimplementedServiceException(Errors.format( - Errors.Keys.UnsupportedImplementation_1, Classes.getClass(method))); - } - transform = unique(transform); - if (method instanceof AbstractProvider) { - method = ((AbstractProvider) method).variantFor(transform); - } - } catch (FactoryException e) { - if (failure != null) { - e.addSuppressed(failure); - } - throw e; - } finally { - lastMethod.set(method); // May be null in case of failure, which is intended. - } - return transform; + final var builder = new ParameterizedTransformBuilder(this, null); + builder.setParameters(parameters, false); + return builder.create(); } /** @@ -1008,7 +957,7 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math ArgumentChecks.ensureNonNull("baseCRS", baseCRS); ArgumentChecks.ensureNonNull("parameters", parameters); ArgumentChecks.ensureNonNull("derivedCS", derivedCS); - final var builder = new ContextBuilder(this, null); + final var builder = new ParameterizedTransformBuilder(this, null); builder.setParameters(parameters, true); builder.setSourceAxes(baseCRS); builder.setTargetAxes(derivedCS, null); @@ -1234,7 +1183,7 @@ public class DefaultMathTransformFactory extends AbstractFactory implements Math /** * Replaces the given transform by a unique instance, if one already exists. */ - private MathTransform unique(final MathTransform tr) { + final MathTransform unique(final MathTransform tr) { return (pool != null) ? pool.unique(tr) : tr; } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformBuilder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformBuilder.java new file mode 100644 index 0000000000..9ca49145f5 --- /dev/null +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformBuilder.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.referencing.operation.transform; + +import java.util.Objects; +import java.util.Optional; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.MathTransformFactory; +import org.opengis.referencing.operation.OperationMethod; +import org.apache.sis.metadata.iso.citation.Citations; +import org.apache.sis.referencing.IdentifiedObjects; +import org.apache.sis.util.privy.Strings; + + +/** + * Builder of a parameterized math transform using a method identified by a name or code. + * A builder instance is created by a call to {@link DefaultMathTransformFactory#builder(String)}. + * The {@linkplain #parameters() parameters} are set to default values and should be modified + * in-place by the caller. If the transform requires semi-major and semi-minor axis lengths, + * those parameters can be set directly or {@linkplain #setSourceAxes indirectly}. + * Then, the transform is created by a call to {@link #create()}. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.5 + * @since 1.5 + */ +public abstract class MathTransformBuilder implements MathTransform.Builder { + /** + * The factory to use for building the transform. + */ + protected final MathTransformFactory factory; + + /** + * The provider that created the parameterized {@link MathTransform} instance, or {@code null} + * if this information does not apply. This is initially set to the operation method specified + * in the call to {@link #builder(String)}, but may be modified by {@link #create()}. + * + * <p>This operation method is usually an instance of {@link MathTransformProvider}, + * but not necessarily.</p> + * + * @see #getMethod() + */ + protected OperationMethod provider; + + /** + * Creates a new builder. + * + * @param factory factory to use for building the transform. + */ + protected MathTransformBuilder(final MathTransformFactory factory) { + this.factory = Objects.requireNonNull(factory); + } + + /** + * Returns the operation method used for creating the math transform from the parameter values. + * This is initially the operation method specified in the call to {@link #builder(String)}, + * but may change after the call to {@link #create()} if the method has been adjusted because + * of the parameter values. + * + * @return the operation method used for creating the math transform from the parameter values. + */ + @Override + public final Optional<OperationMethod> getMethod() { + return Optional.ofNullable(provider); + } + + /** + * Eventually replaces the given transform by a unique instance. The replacement is done + * only if the {@linkplain #factory} is an instance of {@link DefaultMathTransformFactory} + * and {@linkplain DefaultMathTransformFactory#caching(boolean) caching} is enabled. + * + * <p>This is a helper method for {@link #create()} implementations.</p> + * + * @param result the newly created transform. + * @return a transform equals to the given transform (may be the given transform itself). + */ + protected MathTransform unique(MathTransform result) { + if (factory instanceof DefaultMathTransformFactory) { + final var df = (DefaultMathTransformFactory) factory; + df.lastMethod.set(getMethod().orElse(null)); + result = df.unique(result); + } + return result; + } + + /** + * Returns a string representation of this builder for debugging purposes. + * + * @return a string representation of this builder. + */ + @Override + public String toString() { + return Strings.toString(getClass(), + "factory", Citations.getIdentifier(factory.getVendor()), + "method", IdentifiedObjects.getDisplayName(provider, null)); + } +} diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java index 83aebfe4e1..b0b03ff68d 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java @@ -29,6 +29,7 @@ import org.apache.sis.parameter.Parameters; import org.apache.sis.util.privy.Constants; import org.apache.sis.referencing.operation.DefaultOperationMethod; import org.apache.sis.referencing.operation.provider.MapProjection; +import org.apache.sis.referencing.operation.provider.AbstractProvider; import org.apache.sis.referencing.operation.transform.CoordinateDomain; import org.apache.sis.referencing.operation.transform.MathTransformFactoryMock; import org.apache.sis.referencing.operation.transform.MathTransformProvider; @@ -150,7 +151,7 @@ abstract class MapProjectionTestCase extends MathTransformTestCase { * Initializes a complete projection (including conversion from degrees to radians) for the given provider. * Base CRS axis order is (longitude, latitude). */ - final void createCompleteProjection(final DefaultOperationMethod provider, + final void createCompleteProjection(final AbstractProvider provider, final double semiMajor, final double semiMinor, final double centralMeridian, diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java index f368841e2d..0a9459255d 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformFactoryMock.java @@ -17,6 +17,7 @@ package org.apache.sis.referencing.operation.transform; import java.util.Set; +import java.util.Optional; import org.opengis.util.FactoryException; import org.opengis.util.NoSuchIdentifierException; import org.opengis.metadata.citation.Citation; @@ -28,7 +29,6 @@ import org.opengis.referencing.operation.MathTransformFactory; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.OperationMethod; import org.opengis.referencing.operation.SingleOperation; -import org.apache.sis.referencing.operation.DefaultOperationMethod; import org.apache.sis.referencing.operation.provider.AbstractProvider; // Test dependencies @@ -48,7 +48,7 @@ public final class MathTransformFactoryMock implements MathTransformFactory { /** * The operation method. */ - private final DefaultOperationMethod method; + private final AbstractProvider method; /** * Parameters used during the last creation of a math transform. @@ -70,7 +70,7 @@ public final class MathTransformFactoryMock implements MathTransformFactory { * * @param method the operation method to put in this factory. */ - public MathTransformFactoryMock(final DefaultOperationMethod method) { + public MathTransformFactoryMock(final AbstractProvider method) { this.method = method; } @@ -107,6 +107,36 @@ public final class MathTransformFactoryMock implements MathTransformFactory { return method; } + /** + * Returns the builder for the operation method. + * + * @param name shall be the operation method name. + * @return the builder. + * @throws NoSuchIdentifierException if the given name is not the name + * of the operation method known to this factory. + */ + @Override + public MathTransform.Builder builder(final String name) throws NoSuchIdentifierException { + if (method.isHeuristicMatchForName(name)) { + final ParameterValueGroup parameters = method.getParameters().createValue(); + return new MathTransform.Builder() { + @Override public Optional<OperationMethod> getMethod() { + return Optional.of(method); + } + + @Override public ParameterValueGroup parameters() { + return parameters; + } + + @Override public MathTransform create() throws FactoryException { + lastParameters = parameters; + return method.createMathTransform(MathTransformFactoryMock.this, parameters); + } + }; + } + throw new NoSuchIdentifierException(null, name); + } + /** * Returns the parameters for the operation method. * @@ -116,6 +146,7 @@ public final class MathTransformFactoryMock implements MathTransformFactory { * of the operation method known to this factory. */ @Override + @Deprecated public ParameterValueGroup getDefaultParameters(final String name) throws NoSuchIdentifierException { if (method.isHeuristicMatchForName(name)) { return method.getParameters().createValue(); @@ -131,9 +162,10 @@ public final class MathTransformFactoryMock implements MathTransformFactory { * @throws FactoryException if the provider cannot create the transform. */ @Override + @Deprecated public MathTransform createParameterizedTransform(ParameterValueGroup parameters) throws FactoryException { lastParameters = parameters; - return ((MathTransformProvider) method).createMathTransform(this, parameters); + return method.createMathTransform(this, parameters); } /** @@ -200,17 +232,6 @@ public final class MathTransformFactoryMock implements MathTransformFactory { throw new UnsupportedOperationException(); } - /** - * Unimplemented method. - * - * @param code ignored. - * @return never returned. - */ - @Override - public MathTransform.Builder builder(String code) { - throw new UnsupportedOperationException(); - } - /** * Unimplemented method. * diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/MetadataServices.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/MetadataServices.java index c20f80d7c5..b3cc0b19c8 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/MetadataServices.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/MetadataServices.java @@ -129,7 +129,7 @@ public class MetadataServices extends OptionalDependency { */ final UML uml = code.getClass().getAnnotation(UML.class); if (uml != null) try { - return ResourceBundles.codeLists(locale).getString(uml.identifier() + '.' + code.identifier()); + return ResourceBundles.codeLists(locale).getString(uml.identifier() + '.' + code.identifier().orElse(code.name())); } catch (MissingResourceException e) { /* * Ignore. The reason for not finding the resource may because of above code not covering enough cases. diff --git a/geoapi/snapshot b/geoapi/snapshot index e57e817bb1..48d58002a5 160000 --- a/geoapi/snapshot +++ b/geoapi/snapshot @@ -1 +1 @@ -Subproject commit e57e817bb1965d241d4f16f498499d6bb304fddd +Subproject commit 48d58002a5f500446c1237bf8718f018d0f90982