This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sis.git

commit ecf0bfa5b2353f924e39091d28604db656e5d13d
Merge: 4a18444a15 90b66dd6ad
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Sat Oct 4 13:30:35 2025 +0200

    Merge branch 'geoapi-3.1': removal of deprecated methods.

 .../main/org/apache/sis/console/SIS.java           |   3 +-
 .../org/apache/sis/console/TransformCommand.java   |   4 +-
 .../apache/sis/coverage/grid/GridDerivation.java   |  34 --
 .../org/apache/sis/coverage/grid/GridExtent.java   |  34 --
 .../org/apache/sis/coverage/grid/GridGeometry.java |  17 -
 .../apache/sis/coverage/grid/PixelTranslation.java |   3 +-
 .../org/apache/sis/feature/FeatureOperations.java  |   3 +-
 .../main/org/apache/sis/feature/Features.java      |   3 +-
 .../main/org/apache/sis/image/ImageProcessor.java  |  75 +---
 .../main/org/apache/sis/image/package-info.java    |   2 +-
 .../apache/sis/metadata/ModifiableMetadata.java    |  66 +---
 .../metadata/internal/shared/RecordSchemaSIS.java  | 108 ------
 .../apache/sis/metadata/iso/DefaultMetadata.java   |  19 +-
 .../sis/metadata/iso/citation/Citations.java       |   3 +-
 .../metadata/iso/citation/DefaultCitationDate.java |  15 -
 .../iso/extent/DefaultGeographicDescription.java   |  41 +-
 .../metadata/iso/extent/DefaultTemporalExtent.java |  46 +--
 .../apache/sis/metadata/iso/extent/Extents.java    |  22 +-
 .../sis/metadata/iso/extent/package-info.java      |   6 +-
 .../maintenance/DefaultMaintenanceInformation.java |   4 +-
 .../org/apache/sis/metadata/iso/package-info.java  |   2 +-
 .../sis/pending/geoapi/evolution/Interim.java      |   5 +-
 .../sis/pending/geoapi/evolution/InterimType.java  |   2 -
 .../geoapi/evolution/UnsupportedCodeList.java      |   2 -
 .../evolution/UnsupportedCodeListAdapter.java      |   4 +-
 .../sis/pending/geoapi/evolution/package-info.java |   2 -
 .../org/apache/sis/temporal/LenientDateFormat.java |   8 +-
 .../org/apache/sis/util/iso/DefaultNameSpace.java  |   6 +-
 .../org/apache/sis/util/iso/DefaultRecord.java     |  26 +-
 .../apache/sis/util/iso/DefaultRecordSchema.java   | 128 +++---
 .../org/apache/sis/util/iso/DefaultRecordType.java |  86 +++--
 .../main/org/apache/sis/util/iso/Names.java        |   3 +-
 .../main/org/apache/sis/util/iso/Types.java        |  51 +--
 .../main/org/apache/sis/util/iso/package-info.java |   9 +-
 .../main/org/apache/sis/xml/Namespaces.java        |   3 +-
 .../main/org/apache/sis/xml/XML.java               |   3 +-
 .../sis/metadata/iso/DefaultMetadataTest.java      | 100 +++--
 .../iso/quality/DefaultQuantitativeResultTest.java |  23 +-
 .../sis/util/iso/DefaultRecordSchemaTest.java      |  21 +-
 .../org/apache/sis/util/iso/DefaultRecordTest.java |  13 +-
 .../apache/sis/util/iso/DefaultRecordTypeTest.java |  10 +-
 .../sis/util/iso/SerializableRecordSchema.java     |  81 ----
 .../test/org/apache/sis/util/iso/TypesTest.java    |  18 +-
 .../apache/sis/profile/france/FrenchProfile.java   |   3 +-
 .../apache/sis/profile/japan/JapaneseProfile.java  |   4 +-
 .../main/module-info.java                          |   1 +
 .../main/org/apache/sis/geometry/Envelopes.java    |  25 +-
 .../apache/sis/geometry/GeneralDirectPosition.java |  12 +-
 .../main/org/apache/sis/geometry/Shapes2D.java     |   3 +-
 .../main/org/apache/sis/geometry/package-info.java |   2 +-
 .../main/org/apache/sis/io/wkt/Formatter.java      |  36 +-
 .../main/org/apache/sis/io/wkt/package-info.java   |   2 +-
 .../org/apache/sis/parameter/TensorParameters.java |  89 -----
 .../main/org/apache/sis/referencing/CRS.java       |   3 +-
 .../main/org/apache/sis/referencing/CommonCRS.java |  12 +-
 .../apache/sis/referencing/IdentifiedObjects.java  |   3 +-
 .../apache/sis/referencing/crs/AbstractCRS.java    |   4 +-
 .../sis/referencing/crs/AbstractSingleCRS.java     |   3 +-
 .../sis/referencing/crs/DefaultEngineeringCRS.java |  14 +-
 .../sis/referencing/crs/DefaultGeocentricCRS.java  |  24 +-
 .../sis/referencing/crs/DefaultGeographicCRS.java  |  13 +-
 .../sis/referencing/crs/DefaultParametricCRS.java  |  13 +-
 .../sis/referencing/crs/DefaultTemporalCRS.java    |  13 +-
 .../sis/referencing/crs/DefaultVerticalCRS.java    |  13 +-
 .../org/apache/sis/referencing/crs/SubTypes.java   |   1 +
 .../apache/sis/referencing/crs/package-info.java   |   3 +-
 .../org/apache/sis/referencing/cs/AbstractCS.java  |   1 +
 .../sis/referencing/cs/CoordinateSystems.java      |   3 +-
 .../org/apache/sis/referencing/cs/SubTypes.java    |   1 +
 .../sis/referencing/datum/AbstractDatum.java       |   7 +-
 .../sis/referencing/datum/DatumOrEnsemble.java     |   3 +-
 .../sis/referencing/datum/DefaultEllipsoid.java    |  15 +-
 .../referencing/datum/DefaultGeodeticDatum.java    |   2 +-
 .../sis/referencing/datum/TimeDependentBWP.java    |  13 +-
 .../apache/sis/referencing/datum/package-info.java |   8 +-
 .../factory/GeodeticAuthorityFactory.java          |   2 +-
 .../referencing/factory/GeodeticObjectFactory.java |   7 +-
 .../factory/MultiAuthoritiesFactory.java           |  10 +-
 .../referencing/factory/sql/EPSGDataAccess.java    |  10 +-
 .../factory/sql/InstallationScriptProvider.java    |  22 --
 .../internal/ParameterizedTransformBuilder.java    |  17 +
 .../internal/PositionalAccuracyConstant.java       |   4 +-
 .../{crs => legacy}/DefaultImageCRS.java           | 153 +++++---
 .../{datum => legacy}/DefaultImageDatum.java       |  20 +-
 .../{cs => legacy}/DefaultUserDefinedCS.java       |  46 +--
 .../sis/referencing/legacy/package-info.java       |  64 +++
 .../operation/CoordinateOperationFinder.java       |   4 +-
 .../operation/CoordinateOperationRegistry.java     |   5 +-
 .../referencing/operation/DefaultConversion.java   |   6 +-
 .../DefaultCoordinateOperationFactory.java         |  29 +-
 .../operation/InverseOperationMethod.java          |   4 +-
 .../operation/matrix/AffineTransforms2D.java       |   3 +-
 .../sis/referencing/operation/matrix/Matrices.java |   3 +-
 .../operation/projection/package-info.java         |  15 +-
 .../GeocentricAffineBetweenGeographic.java         |  15 +-
 .../operation/provider/MapProjection.java          |   8 +-
 .../operation/transform/AbstractMathTransform.java |  51 +--
 .../transform/DefaultMathTransformFactory.java     | 429 +--------------------
 .../transform/EllipsoidToCentricTransform.java     |  45 +--
 .../operation/transform/MathTransformProvider.java |  26 +-
 .../operation/transform/MathTransforms.java        |   3 +-
 .../operation/transform/package-info.java          |   2 +-
 .../org/apache/sis/referencing/package-info.java   |   2 +-
 .../xml/bind/referencing/CC_OperationMethod.java   |   4 +-
 .../sis/xml/bind/referencing/CD_ImageDatum.java    |   2 +-
 .../sis/xml/bind/referencing/CS_UserDefinedCS.java |   2 +-
 .../apache/sis/referencing/crs/HardCodedCRS.java   |   3 +-
 .../sis/referencing/datum/HardCodedDatum.java      |   3 +-
 .../{crs => legacy}/DefaultImageCRSTest.java       |   6 +-
 .../operation/CoordinateOperationFinderTest.java   |   5 +-
 .../DefaultCoordinateOperationFactoryTest.java     |  13 -
 .../transform/MathTransformFactoryMock.java        |   2 -
 .../sis/storage/geotiff/base/GeoCodesTest.java     |   4 +-
 .../main/org/apache/sis/storage/gpx/Metadata.java  |   5 +-
 .../main/org/apache/sis/storage/DataStores.java    |   3 +-
 .../main/org/apache/sis/storage/FeatureQuery.java  |  19 +-
 .../main/org/apache/sis/storage/package-info.java  |   2 +-
 .../main/org/apache/sis/io/IO.java                 |   3 +-
 .../main/org/apache/sis/math/DecimalFunctions.java |   3 +-
 .../main/org/apache/sis/math/MathFunctions.java    |   3 +-
 .../main/org/apache/sis/measure/Quantities.java    |   3 +-
 .../main/org/apache/sis/measure/Units.java         |   3 +-
 .../main/org/apache/sis/system/Environment.java    |   3 +-
 .../main/org/apache/sis/system/Loggers.java        |   3 +-
 .../main/org/apache/sis/system/Threads.java        |   3 +-
 .../main/org/apache/sis/util/ArgumentChecks.java   |  51 +--
 .../main/org/apache/sis/util/ArraysExt.java        |   2 +-
 .../main/org/apache/sis/util/CharSequences.java    |   2 +-
 .../main/org/apache/sis/util/Characters.java       |   2 +-
 .../main/org/apache/sis/util/Classes.java          |   2 +-
 .../main/org/apache/sis/util/Exceptions.java       |   2 +-
 .../main/org/apache/sis/util/Locales.java          |   2 +-
 .../main/org/apache/sis/util/Numbers.java          |   2 +-
 .../main/org/apache/sis/util/ObjectConverters.java |   2 +-
 .../main/org/apache/sis/util/Static.java           | 119 ------
 .../main/org/apache/sis/util/StringBuilders.java   |  31 +-
 .../main/org/apache/sis/util/Utilities.java        |   2 +-
 .../org/apache/sis/util/collection/Containers.java |   3 +-
 .../org/apache/sis/util/collection/TreeTables.java |   3 +-
 .../main/org/apache/sis/util/logging/Logging.java  |   3 +-
 .../main/org/apache/sis/util/package-info.java     |   2 +-
 .../test/org/apache/sis/test/GeoapiAssert.java     |   3 +-
 .../test/org/apache/sis/test/TestCase.java         |   1 +
 143 files changed, 673 insertions(+), 2126 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java
index 9f839fe81e,4d5cdfde24..4c67ce7c67
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java
@@@ -305,8 -291,7 +306,7 @@@ public class DefaultMaintenanceInformat
              }
          }
          if (newValue != null) {
-             @SuppressWarnings("removal")
-             final var date = new DefaultCitationDate(newValue, NEXT_UPDATE);
 -            final var date = new 
DefaultCitationDate(TemporalDate.toTemporal(newValue), DateType.NEXT_UPDATE);
++            final var date = new 
DefaultCitationDate(TemporalDate.toTemporal(newValue), NEXT_UPDATE);
              if (dates != null) {
                  dates.add(date);
              } else {
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/Interim.java
index 54a86ce83f,0000000000..0be4e94ff1
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/Interim.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/Interim.java
@@@ -1,68 -1,0 +1,65 @@@
 +/*
 + * 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.pending.geoapi.evolution;
 +
 +import java.lang.reflect.Method;
 +import static java.util.logging.Logger.getLogger;
 +import org.opengis.geometry.Envelope;
 +import org.opengis.geometry.Geometry;
- import org.apache.sis.util.Static;
 +import org.apache.sis.util.logging.Logging;
 +import org.apache.sis.system.Modules;
 +
 +
 +/**
 + * Temporary methods used until a new major GeoAPI release provides the 
missing functionalities.
 + *
 + * @author  Martin Desruisseaux (Geomatys)
-  * @version 1.1
-  * @since   0.8
 + */
- public final class Interim extends Static {
++public final class Interim {
 +    /**
 +     * Do not allow instantiation of this class.
 +     */
 +    private Interim() {
 +    }
 +
 +    /**
 +     * Returns the return type of the given method, or the interim type if 
the method is annotated
 +     * with {@link InterimType}.
 +     *
 +     * @param  method  the method from which to get the return type.
 +     * @return the return type or the interim type.
 +     */
 +    public static Class<?> getReturnType(final Method method) {
 +        final InterimType an = method.getAnnotation(InterimType.class);
 +        return (an != null) ? an.value() : method.getReturnType();
 +    }
 +
 +    /**
 +     * Invokes {@code Geometry.getEnvelope()} if that method exists.
 +     *
 +     * @param  geometry  the geometry from which to get the envelope.
 +     * @return the geometry envelope, or {@code null} if none.
 +     */
 +    public static Envelope getEnvelope(final Geometry geometry) {
 +        try {
 +            return (Envelope) 
geometry.getClass().getMethod("getEnvelope").invoke(geometry);
 +        } catch (ReflectiveOperationException | ClassCastException e) {
 +            Logging.recoverableException(getLogger(Modules.METADATA), 
Interim.class, "getEnvelope", e);
 +            return null;
 +        }
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/InterimType.java
index 8c48b7a5f9,a6eeffe0b8..6f58a9d186
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/InterimType.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/InterimType.java
@@@ -24,21 -21,25 +24,19 @@@ import java.lang.reflect.Method
  
  
  /**
 - * JAXB adapter for (un)marshalling of GeoAPI code list.
 + * Identifies an interim class to use until an official GeoAPI class or 
interface is released.
   *
   * @author  Martin Desruisseaux (Geomatys)
-  * @version 0.8
-  * @since   0.8
 + *
 + * @see Interim#getReturnType(Method)
   */
 -@SuppressWarnings("deprecation")
 -public final class CD_VerticalDatumType extends 
CodeListAdapter<VerticalDatumType> {
 -    /**
 -     * Empty constructor for JAXB only.
 -     */
 -    public CD_VerticalDatumType() {
 -    }
 -
 +@Target(ElementType.METHOD)
 +@Retention(RetentionPolicy.RUNTIME)
 +public @interface InterimType {
      /**
 -     * {@inheritDoc}
 +     * The interim Apache SIS class to use until the GeoAPI class or 
interface is released.
       *
 -     * @return {@code VerticalDatumType.class}
 +     * @return Apache SIS class to use in the interim.
       */
 -    @Override
 -    protected Class<VerticalDatumType> getCodeListClass() {
 -        return VerticalDatumType.class;
 -    }
 +    Class<?> value();
  }
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeList.java
index e949e74e4a,0000000000..1890fe5671
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeList.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeList.java
@@@ -1,98 -1,0 +1,96 @@@
 +/*
 + * Copyright 2014 desruisseaux.
 + *
 + * Licensed 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.pending.geoapi.evolution;
 +
 +import java.util.List;
 +import java.util.ArrayList;
 +import org.opengis.annotation.UML;
 +import org.opengis.util.CodeList;
 +import static org.opengis.annotation.Obligation.CONDITIONAL;
 +import static org.opengis.annotation.Specification.ISO_19115;
 +
 +
 +/**
 + * Placeholder for code list not yet available in GeoAPI.
 + * Currently defines constants mostly for {@code 
org.opengis.metadata.citation.TelephoneType},
 + * but constants for other code list can be constructed like below:
 + *
 + * {@snippet lang="java" :
 + *   
operation.getDistributedComputingPlatforms().add(UnsupportedCodeList.valueOf("SOAP"));
 + *   }
 + *
 + * @author  Martin Desruisseaux (Geomatys)
-  * @version 1.0
-  * @since   0.5
 + */
 +public final class UnsupportedCodeList extends CodeList<UnsupportedCodeList> {
 +    /**
 +     * For cross-version compatibility.
 +     */
 +    private static final long serialVersionUID = 7205015191869240829L;
 +
 +    /**
 +     * The list of constants defined in this code list.
 +     */
 +    private static final List<UnsupportedCodeList> VALUES = new 
ArrayList<UnsupportedCodeList>(3);
 +
 +    /**
 +     * A frequently used code list element.
 +     */
 +    @UML(identifier="voice", obligation=CONDITIONAL, specification=ISO_19115)
 +    public static final CodeList<?> VOICE = new UnsupportedCodeList("VOICE");
 +
 +    /**
 +     * A frequently used code list element.
 +     */
 +    @UML(identifier="facsimile", obligation=CONDITIONAL, 
specification=ISO_19115)
 +    public static final CodeList<?> FACSIMILE = new 
UnsupportedCodeList("FACSIMILE");
 +
 +    /**
 +     * A frequently used code list element.
 +     */
 +    @UML(identifier="WebServices", obligation=CONDITIONAL, 
specification=ISO_19115)
 +    public static final CodeList<?> WEB_SERVICES = new 
UnsupportedCodeList("WEB_SERVICES");
 +
 +    /**
 +     * Constructor for new code list element.
 +     *
 +     * @param name The code list name.
 +     */
 +    private UnsupportedCodeList(String name) {
 +        super(name, VALUES);
 +    }
 +
 +    /**
 +     * Returns the list of codes of the same kind than this code list element.
 +     *
 +     * @return All code values for this code list.
 +     */
 +    @Override
 +    public UnsupportedCodeList[] family() {
 +        synchronized (VALUES) {
 +            return VALUES.toArray(new UnsupportedCodeList[VALUES.size()]);
 +        }
 +    }
 +
 +    /**
 +     * Returns the telephone type that matches the given string, or returns a 
new one if none match it.
 +     *
 +     * @param code The name of the code to fetch or to create.
 +     * @return A code matching the given name.
 +     */
 +    public static UnsupportedCodeList valueOf(String code) {
 +        return valueOf(UnsupportedCodeList.class, code);
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeListAdapter.java
index d0cf585e44,0000000000..b4f891bf73
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeListAdapter.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeListAdapter.java
@@@ -1,164 -1,0 +1,162 @@@
 +/*
 + * 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.pending.geoapi.evolution;
 +
 +import jakarta.xml.bind.annotation.adapters.XmlAdapter;
 +import org.opengis.util.CodeList;
 +import org.apache.sis.util.iso.Types;
 +import org.apache.sis.xml.bind.Context;
 +import org.apache.sis.xml.bind.cat.CodeListUID;
 +
 +
 +/**
 + * An adapter for {@link UnsupportedCodeList}, in order to implement the ISO 
19115-3 standard.
 + * See {@link org.apache.sis.xml.bind.cat.CodeListAdapter} for more 
information.
 + *
 + * @param <ValueType> The subclass implementing this adapter.
 + *
 + * @author  Cédric Briançon (Geomatys)
 + * @author  Martin Desruisseaux (Geomatys)
-  * @version 0.5
-  * @since   0.5
 + */
 +public abstract class UnsupportedCodeListAdapter<ValueType extends 
UnsupportedCodeListAdapter<ValueType>>
 +        extends XmlAdapter<ValueType,CodeList<?>>
 +{
 +    /**
 +     * The value of the {@link CodeList}.
 +     */
 +    protected CodeListUID identifier;
 +
 +    /**
 +     * Empty constructor for subclasses only.
 +     */
 +    protected UnsupportedCodeListAdapter() {
 +    }
 +
 +    /**
 +     * Creates a wrapper for a {@link CodeList}, in order to handle the 
format specified in ISO-19139.
 +     *
 +     * @param  value  the value of the {@link CodeList} to be marshalled.
 +     */
 +    protected UnsupportedCodeListAdapter(final CodeListUID value) {
 +        identifier = value;
 +    }
 +
 +    /**
 +     * Wraps the code into an adapter.
 +     * Most implementations will be like below:
 +     *
 +     * {@snippet lang="java" :
 +     *     return new ValueType(value);
 +     *     }
 +     *
 +     * @param  value  the value of {@link CodeList} to be marshalled.
 +     * @return the wrapper for the code list value.
 +     */
 +    protected abstract ValueType wrap(CodeListUID value);
 +
 +    /**
 +     * Returns the name of the code list class.
 +     *
 +     * @return the code list class name.
 +     */
 +    protected abstract String getCodeListName();
 +
 +    /**
 +     * Substitutes the adapter value read from an XML stream by the object 
which will
 +     * contains the value. JAXB calls automatically this method at 
unmarshalling time.
 +     *
 +     * @param  adapter  the adapter for this metadata value.
 +     * @return a code list which represents the metadata value.
 +     */
 +    @Override
 +    public final CodeList<?> unmarshal(final ValueType adapter) {
 +        if (adapter == null) {
 +            return null;
 +        }
-         return Types.forCodeName(UnsupportedCodeList.class, 
adapter.identifier.toString(), true);
++        return Types.forCodeName(UnsupportedCodeList.class, 
adapter.identifier.toString(), UnsupportedCodeList::valueOf);
 +    }
 +
 +    /**
 +     * Substitutes the code list by the adapter to be marshalled into an XML 
file or stream.
 +     * JAXB calls automatically this method at marshalling time.
 +     *
 +     * @param  value  the code list value.
 +     * @return the adapter for the given code list.
 +     */
 +    @Override
 +    public final ValueType marshal(final CodeList<?> value) {
 +        if (value == null) {
 +            return null;
 +        }
 +        final String name = value.name();
 +        final int length = name.length();
 +        final StringBuilder buffer = new StringBuilder(length);
 +        final String codeListValue = toIdentifier(name, buffer, false);
 +        buffer.setLength(0);
 +        return wrap(new CodeListUID(Context.current(), getCodeListName(), 
codeListValue,
 +                null, toIdentifier(name, buffer, true)));
 +    }
 +
 +    /**
 +     * Converts the given Java constant name to something hopefully close to 
the UML identifier,
 +     * or close to the textual value to put in the XML. This method convert 
the Java constant name
 +     * to camel case if {@code isValue} is {@code true}, or to lower cases 
with word separated by
 +     * spaces if {@code isValue} is {@code true}.
 +     *
 +     * @param  name    The Java constant name (e.g. {@code WEB_SERVICES}).
 +     * @param  buffer  An initially empty buffer to use for creating the 
identifier.
 +     * @param  isValue {@code false} for the {@code codeListValue} attribute, 
or {@code true} for the XML value.
 +     * @return The identifier (e.g. {@code "webServices"} or {@code "Web 
services"}).
 +     */
 +    protected String toIdentifier(final String name, final StringBuilder 
buffer, final boolean isValue) {
 +        final int length = name.length();
 +        boolean toUpper = isValue;
 +        for (int i=0; i<length;) {
 +            int c = name.codePointAt(i);
 +            i += Character.charCount(c);
 +            if (c == '_') {
 +                if (isValue) {
 +                    c = ' ';
 +                } else {
 +                    toUpper = true;
 +                    continue;
 +                }
 +            }
 +            if (toUpper) {
 +                c = Character.toUpperCase(c);
 +                toUpper = false;
 +            } else {
 +                c = Character.toLowerCase(c);
 +            }
 +            buffer.appendCodePoint(c);
 +        }
 +        return buffer.toString();
 +    }
 +
 +    /**
 +     * Invoked by JAXB on marshalling. Subclasses must override this
 +     * method with the appropriate {@code @XmlElement} annotation.
 +     *
 +     * @return The {@code CodeList} value to be marshalled.
 +     */
 +    public abstract CodeListUID getElement();
 +
 +    /*
 +     * We do not define setter method (even abstract) since it seems to 
confuse JAXB.
 +     * It is subclasses responsibility to define the setter method.
 +     */
 +}
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/package-info.java
index eca7531330,d4b582c1b0..2d431bc16f
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/package-info.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/package-info.java
@@@ -28,8 -25,11 +28,6 @@@
   * This package is for internal use by SIS only. Classes in this package
   * may change in incompatible ways in any future version without notice.
   *
 - * <h2>Implementation notes</h2>
 - * Feature type analysis is done through {@link 
org.apache.sis.storage.sql.feature.Analyzer} class.
 - *
 - * @author  Johann Sorel (Geomatys)
   * @author  Martin Desruisseaux (Geomatys)
-  * @version 1.1
-  * @since   0.5
 - * @author  Alexis Manin (Geomatys)
   */
 -package org.apache.sis.storage.sql.feature;
 +package org.apache.sis.pending.geoapi.evolution;
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordSchema.java
index 535065ee72,35bd16dcb3..fc294a308c
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordSchema.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordSchema.java
@@@ -37,24 -39,21 +39,18 @@@ import org.apache.sis.util.resources.Er
  import org.apache.sis.util.collection.WeakValueHashMap;
  import org.apache.sis.metadata.simple.SimpleAttributeType;
  import org.apache.sis.converter.SurjectiveConverter;
+ import org.apache.sis.util.internal.shared.Constants;
  import org.apache.sis.util.internal.shared.Strings;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.feature.AttributeType;
 -
  
  /**
-  * A collection of record types in a given namespace.
-  * This class works also as a factory for creating {@code RecordType} and 
{@code Record} instances.
-  * The factory methods are:
+  * A factory for creating {@code RecordType} instances.
   *
-  * <ul>
-  *   <li>{@link #createRecordType(CharSequence, Map)}</li>
-  * </ul>
-  *
-  * Subclasses can modify the characteristics of the records to be created
-  * by overriding the following methods:
-  *
-  * <ul>
-  *   <li>{@link DefaultNameFactory#toTypeName(Class)} if the factory given to 
the constructor.</li>
-  * </ul>
+  * <div class="warning"><b>Possible future change:</b>
+  * This class is derived from ISO 19103:2005. The record attributes and 
methods have been modified
+  * in ISO 19103:2015, then all classes related to records have been fully 
removed in ISO 19103:2024.
+  * The implication for Apache <abbr>SIS</abbr> has not yet been determined.
+  * In the meantime, this class should be considered as merely a factory of 
{@link DefaultRecordType} instances.</div>
   *
   * <h2>Thread safety</h2>
   * The same {@code DefaultRecordSchema} instance can be safely used by many 
threads without synchronization
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java
index f791fc49b0,0c94341564..09640338af
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java
@@@ -41,9 -42,13 +42,10 @@@ import org.apache.sis.pending.jdk.JDK19
  import org.apache.sis.util.CharSequences;
  import org.apache.sis.util.ObjectConverters;
  import org.apache.sis.util.resources.Errors;
+ import org.apache.sis.util.resources.Vocabulary;
  import org.apache.sis.converter.SurjectiveConverter;
- import org.apache.sis.metadata.internal.shared.RecordSchemaSIS;
+ import org.apache.sis.metadata.internal.Resources;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.util.NameFactory;
 -
  
  /**
   * An immutable definition of the type of a {@linkplain DefaultRecord record}.
@@@ -191,9 -234,9 +231,9 @@@ public class DefaultRecordType extends 
       *
       * @deprecated To be removed after {@link DefaultRecordSchema} has been 
removed.
       */
-     @Deprecated(since = "1.5", forRemoval = true)
+     @Deprecated(since = "1.5")
      DefaultRecordType(final TypeName typeName, final RecordSchema container,
 -            final Map<? extends CharSequence, ? extends Type> fields, final 
NameFactory nameFactory)
 +            final Map<? extends CharSequence, ? extends Type> fields, final 
DefaultNameFactory nameFactory)
      {
          this.typeName  = typeName;
          this.container = container;
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
index e7f65776f6,f20ba91f21..9e585f675f
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
@@@ -59,17 -58,17 +57,17 @@@ import java.io.InputStream
   *
   * <ul>
   *   <li>Methods for fetching the ISO name or description of a code list:<ul>
 - *     <li>{@link #getStandardName(Class)}            for ISO name</li>
 - *     <li>{@link #getListName(ControlledVocabulary)} for ISO name</li>
 - *     <li>{@link #getDescription(Class)}             for a description</li>
 + *     <li>{@link #getStandardName(Class)}   for ISO name</li>
 + *     <li>{@link #getListName(CodeList)}    for ISO name</li>
 + *     <li>{@link #getDescription(Class)}    for a description</li>
   *   </ul></li>
   *   <li>Methods for fetching the ISO name or description of a code value:<ul>
 - *     <li>{@link #getCodeName(ControlledVocabulary)}    for ISO name,</li>
 - *     <li>{@link #getCodeTitle(ControlledVocabulary)}   for a label or 
title</li>
 - *     <li>{@link #getDescription(ControlledVocabulary)} for a more verbose 
description</li>
 + *     <li>{@link #getCodeName(CodeList)}    for ISO name,</li>
 + *     <li>{@link #getCodeTitle(CodeList)}   for a label or title</li>
 + *     <li>{@link #getDescription(CodeList)} for a more verbose 
description</li>
   *   </ul></li>
   *   <li>Methods for fetching an instance from a name (converse of above 
{@code get} methods):<ul>
-  *     <li>{@link #forCodeName(Class, String, boolean)}</li>
+  *     <li>{@link #forCodeName(Class, String, Function)}</li>
   *     <li>{@link #forEnumName(Class, String)}</li>
   *   </ul></li>
   * </ul>
@@@ -212,12 -211,12 +210,12 @@@ public final class Types 
       * @param  code  the code for which to get the name, or {@code null}.
       * @return the UML identifiers or programmatic name for the given code, 
or {@code null} if the given code is null.
       *
 -     * @see #getCodeLabel(ControlledVocabulary)
 -     * @see #getCodeTitle(ControlledVocabulary)
 -     * @see #getDescription(ControlledVocabulary)
 +     * @see #getCodeLabel(CodeList)
 +     * @see #getCodeTitle(CodeList)
 +     * @see #getDescription(CodeList)
-      * @see #forCodeName(Class, String, boolean)
+      * @see #forCodeName(Class, String, Function)
       */
 -    public static String getCodeName(final ControlledVocabulary code) {
 +    public static String getCodeName(final CodeList<?> code) {
          if (code == null) {
              return null;
          }
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/DefaultMetadataTest.java
index d983e58109,6e5ea43db1..01c06cc607
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/DefaultMetadataTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/DefaultMetadataTest.java
@@@ -227,9 -259,9 +256,9 @@@ public final class DefaultMetadataTest 
          /*
           * Verifies that the deprecated method get its value from the 
CitationDate objects.
           */
-         Date creation = date("2014-10-07 00:00:00");
+         Instant creation = Instant.parse("2014-10-07T00:00:00Z");
          final var dates = new DefaultCitationDate[] {
-                 new DefaultCitationDate(date("2014-10-09 00:00:00"), 
DateType.valueOf("LAST_UPDATE")),
 -                new 
DefaultCitationDate(Instant.parse("2014-10-09T00:00:00Z"), 
DateType.LAST_UPDATE),
++                new 
DefaultCitationDate(Instant.parse("2014-10-09T00:00:00Z"), 
DateType.valueOf("LAST_UPDATE")),
                  new DefaultCitationDate(creation, DateType.CREATION)
          };
          metadata.setDateInfo(Arrays.asList(dates));
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/util/iso/DefaultRecordSchemaTest.java
index 966e38cdb6,11dbc1a1d8..88709de1d1
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/util/iso/DefaultRecordSchemaTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/util/iso/DefaultRecordSchemaTest.java
@@@ -57,10 -71,9 +71,9 @@@ public final class DefaultRecordSchemaT
          /*
           * Inspect properties.
           */
-         assertSame(schema, recordType.getContainer());
          assertEquals(Names.createTypeName("MySchema", ":", "MyRecordType"), 
recordType.getTypeName());
          int count = 0;
 -        for (final Map.Entry<MemberName,Type> entry : 
recordType.getFieldTypes().entrySet()) {
 +        for (final Map.Entry<MemberName,Type> entry : 
recordType.getMemberTypes().entrySet()) {
              final String   expectedName;
              final String   expectedType;
              final Class<?> expectedClass;
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/util/iso/TypesTest.java
index fea409d520,dbd827f4ee..d765addb60
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/util/iso/TypesTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/util/iso/TypesTest.java
@@@ -38,9 -37,9 +37,8 @@@ import org.junit.jupiter.api.Test
  import static org.junit.jupiter.api.Assertions.*;
  import org.apache.sis.test.TestCase;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.metadata.constraint.Restriction;
 -import org.opengis.parameter.ParameterDirection;
 +// Specific to the main branch:
 +import org.opengis.referencing.datum.PixelInCell;
- import static org.apache.sis.test.GeoapiAssert.PENDING_NEXT_GEOAPI_RELEASE;
  
  
  /**
@@@ -129,8 -128,21 +127,8 @@@ public final class TypesTest extends Te
          assertNull(Types.forEnumName(ElementType.class, "variable"));
      }
  
 -    /**
 -     * Tests the {@link Types#forEnumName(Class, String)} method with an 
enumeration from GeoAPI.
 -     * Such enumerations implement the {@link 
org.opengis.util.ControlledVocabulary} interface.
 -     */
 -    @Test
 -    public void testForGeoapiEnumName() {
 -        assertSame(ParameterDirection.IN_OUT, 
Types.forEnumName(ParameterDirection.class, "IN_OUT"));
 -        assertSame(ParameterDirection.IN_OUT, 
Types.forEnumName(ParameterDirection.class, "INOUT"));
 -        assertSame(ParameterDirection.IN_OUT, 
Types.forEnumName(ParameterDirection.class, "in out"));
 -        assertSame(ParameterDirection.IN_OUT, 
Types.forEnumName(ParameterDirection.class, "in/out"));
 -        assertNull(Types.forEnumName(ParameterDirection.class, "out/in"));
 -    }
 -
      /**
-      * Tests the {@link Types#forCodeName(Class, String, boolean)} method.
+      * Tests the {@link Types#forCodeName(Class, String, Function)} method.
       */
      @Test
      public void testForCodeName() {
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
index 5cdff6f346,3e761910d9..8e149bf7a0
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
@@@ -1636,12 -1616,16 +1620,16 @@@ public class Formatter implements Local
              } else {
                  append(number.doubleValue());
              }
-         }
-         else if (value instanceof CodeList<?>) append((CodeList<?>) value);
-         else if (value instanceof Date)        append((Date)        value);
-         else if (value instanceof Temporal)    append((Temporal)    value);
-         else if (value instanceof Boolean)     append((Boolean)     value);
-         else if (value instanceof CharSequence) {
 -        } else if (value instanceof ControlledVocabulary) {
 -            append((ControlledVocabulary) value);
++        } else if (value instanceof CodeList<?>) {
++            append((CodeList<?>) value);
+         } else if (value instanceof Temporal) {
+             append((Temporal) value);
+         } else if (value instanceof Date) {
+             appendSeparator();
+             dateFormat.format((Date) value, buffer, dummy);
+         } else if (value instanceof Boolean) {
+             append((Boolean) value);
+         } else if (value instanceof CharSequence) {
              append((value instanceof InternationalString) ?
                      ((InternationalString) value).toString(locale) : 
value.toString(), null);
          } else if (value.getClass().isArray()) {
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
index 2b5cd1208c,91115e1be5..e386038daa
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
@@@ -77,9 -77,9 +77,9 @@@ import org.apache.sis.referencing.datum
   * in the javadoc, this condition holds if all components were created using 
only SIS factories and static constants.
   *
   * @author  Martin Desruisseaux (IRD, Geomatys)
-  * @version 1.5
+  * @version 1.6
   *
 - * @see 
org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createGeodeticCRS(String)
 + * @see 
org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createGeocentricCRS(String)
   *
   * @since 0.4
   */
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
index a28e4a6fdf,2ec5a4c69d..8a652dcea0
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
@@@ -66,8 -66,7 +65,8 @@@ import org.apache.sis.util.logging.Logg
   * @version 1.5
   * @since   1.5
   */
 +@SuppressWarnings("unchecked")  // See `getDatumEnsemble(…)`
- public final class DatumOrEnsemble extends Static {
+ public final class DatumOrEnsemble {
      /**
       * The {@value} keyword which sometime appear at the end of a datum 
ensemble name.
       */
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index 89248ff848,64593b9891..65d5c8aad1
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
@@@ -64,8 -64,10 +64,11 @@@ import org.apache.sis.util.logging.Logg
  import org.apache.sis.io.wkt.Parser;
  import org.apache.sis.xml.XML;
  
 -// Specific the the main and geoapi-3.1 branches:
 +// Specific to the main branch:
+ import org.apache.sis.referencing.legacy.DefaultImageCRS;
+ import org.apache.sis.referencing.legacy.DefaultImageDatum;
+ import org.apache.sis.referencing.legacy.DefaultUserDefinedCS;
 +import org.apache.sis.referencing.datum.DefaultDatumEnsemble;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 4d8769969b,3aeb68781e..d3849493ca
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
@@@ -1545,7 -1540,7 +1545,6 @@@ search: try (ResultSet result = execute
       * @see #createCoordinateSystem(String)
       */
      @Override
--    @SuppressWarnings("removal")
      public synchronized IdentifiedObject createObject(final String code)
              throws NoSuchAuthorityCodeException, FactoryException
      {
@@@ -3568,7 -3540,8 +3567,14 @@@
                                      + " FROM \"Coordinate_Operation Path\""
                                      + " WHERE (CONCAT_OPERATION_CODE = ?)"
                                      + " ORDER BY OP_PATH_STEP", 
epsg).toArray(CoordinateOperation[]::new);
-                     constructor = (factory, metadata) -> 
factory.createConcatenatedOperation(metadata, operations);
 -                    constructor = (factory, metadata) ->
 -                            factory.createConcatenatedOperation(metadata, 
sourceCRS, targetCRS, operations);
++                    constructor = (factory, metadata) -> {
++                        if (factory instanceof 
DefaultCoordinateOperationFactory) {
++                            return ((DefaultCoordinateOperationFactory) 
factory)
++                                    .createConcatenatedOperation(metadata, 
sourceCRS, targetCRS, operations);
++                        } else {
++                            return 
factory.createConcatenatedOperation(metadata, operations);
++                        }
++                    };
                  } else {
                      /*
                       * At this stage, the parameters are ready for use. 
Create the math transform and wrap it in the
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index 5c08f4d503,bd26960b06..03b1ece95c
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@@ -1157,7 -1162,9 +1157,9 @@@ public class CoordinateOperationFinder 
                      op.getParameterValues(),
                      typeOf(op));
          } else {
-             main = factory.createConcatenatedOperation(defaultName(sourceCRS, 
targetCRS), step1, step2);
 -            main = factory.createConcatenatedOperation(
++            main = factorySIS.createConcatenatedOperation(
+                     defaultName(sourceCRS, targetCRS),
+                     sourceCRS, targetCRS, step1, step2);
          }
          /*
           * Sometimes we get a concatenated operation made of an operation 
followed by its inverse.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
index 07932c263b,ae2f3379c1..f9e3fe6c3d
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
@@@ -565,26 -539,6 +538,26 @@@ next:   for (SingleCRS component : CRS.
          return pool.unique(op);
      }
  
 +    /**
 +     * Creates an ordered sequence of two or more single coordinate 
operations.
 +     *
 +     * @deprecated Replaced by {@linkplain #createConcatenatedOperation(Map, 
CoordinateReferenceSystem,
 +     * CoordinateReferenceSystem, CoordinateOperation...) a method with 
explicit CRS arguments} because
 +     * of potential <abbr>CRS</abbr> swapping.
 +     *
 +     * @param  properties  the properties to be given to the identified 
object.
 +     * @param  operations  the sequence of operations. Shall contain at least 
two operations.
 +     * @return the concatenated operation created from the given arguments.
 +     * @throws FactoryException if the object creation failed.
 +     */
 +    @Override
-     @Deprecated(since="1.5", forRemoval=true)
++    @Deprecated(since="1.5")
 +    public CoordinateOperation createConcatenatedOperation(final 
Map<String,?> properties,
 +            final CoordinateOperation... operations) throws FactoryException
 +    {
 +        return createConcatenatedOperation(properties, null, null, 
operations);
 +    }
 +
      /**
       * Creates an ordered sequence of two or more single coordinate 
operations.
       * The sequence of operations is constrained by the requirement that the 
source coordinate reference system
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
index 9a497db2ff,3a764936a9..2b513927f0
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
@@@ -40,11 -40,10 +40,10 @@@ import org.apache.sis.referencing.opera
  import org.apache.sis.util.OptionalCandidate;
  import org.apache.sis.util.ArgumentChecks;
  import org.apache.sis.util.ArraysExt;
- import org.apache.sis.util.Static;
  import org.apache.sis.util.internal.shared.DoubleDouble;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.coordinate.MismatchedDimensionException;
 +// Specific to the main branch:
 +import org.opengis.geometry.MismatchedDimensionException;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/legacy/DefaultImageCRSTest.java
index 48499d73dd,d426f736bf..f1ce38023e
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/legacy/DefaultImageCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/legacy/DefaultImageCRSTest.java
@@@ -38,9 -37,11 +37,11 @@@ import static org.apache.sis.referencin
  
  // Specific to the main and geoapi-3.1 branches:
  import org.opengis.referencing.datum.PixelInCell;
+ import org.apache.sis.referencing.legacy.DefaultImageCRS;
+ import org.apache.sis.referencing.legacy.DefaultImageDatum;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import static org.opengis.test.Assertions.assertAxisDirectionsEqual;
 +// Specific to the main branch:
 +import static org.apache.sis.test.GeoapiAssert.assertAxisDirectionsEqual;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
index e981c0a289,2c9e54f5b6..9c95e5f3a8
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
@@@ -551,12 -550,9 +551,9 @@@ public class FeatureQuery extends Quer
          /**
           * The literal, value reference or more complex expression to be 
retrieved by a {@code Query}.
           * Never {@code null}.
-          *
-          * @deprecated Replaced by {@link #expression()} in preparation for 
making {@code NamedExpression} a record.
           */
-         @Deprecated(since = "1.5")
          @SuppressWarnings("serial")
-         public final Expression<? super AbstractFeature, ?> expression;
 -        private final Expression<? super Feature, ?> expression;
++        private final Expression<? super AbstractFeature, ?> expression;
  
          /**
           * The name to assign to the expression result, or {@code null} if 
unspecified.
@@@ -569,16 -562,11 +563,11 @@@
  
          /**
           * Whether the expression result should be stored or evaluated every 
times that it is requested.
 -         * A stored value will exist as a feature {@link Attribute}, while a 
virtual value will exist as
 -         * a feature {@link Operation}. The latter are commonly called 
"computed fields" and are equivalent
 +         * A stored value will exist as a feature {@link AbstractAttribute}, 
while a virtual value will exist as
 +         * a feature {@link AbstractOperation}. The latter are commonly 
called "computed fields" and are equivalent
           * to SQL {@code GENERATED ALWAYS} keyword for columns.
-          *
-          * @deprecated Replaced by {@link #type()} in preparation for making 
{@code NamedExpression} a record.
-          *
-          * @since 1.4
           */
-         @Deprecated(since = "1.5")
-         public final ProjectionType type;
+         private final ProjectionType type;
  
          /**
           * Creates a new stored column with the given expression and no name.
diff --cc 
endorsed/src/org.apache.sis.util/test/org/apache/sis/test/GeoapiAssert.java
index e39b5f3b8d,0000000000..f4658453ce
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/GeoapiAssert.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/GeoapiAssert.java
@@@ -1,248 -1,0 +1,247 @@@
 +/*
 + * 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.test;
 +
 +import java.util.Collection;
 +import org.opengis.metadata.citation.Citation;
 +import org.opengis.referencing.ReferenceIdentifier;
 +import org.opengis.referencing.cs.AxisDirection;
 +import org.opengis.referencing.cs.CoordinateSystem;
 +import org.opengis.referencing.operation.Matrix;
 +import org.opengis.util.InternationalString;
- import org.apache.sis.util.Static;
 +
 +// Test dependencies
 +import static org.junit.jupiter.api.Assertions.*;
 +import org.opengis.test.Assert;
 +
 +
 +/**
 + * Temporary class for test methods that are expected to be provided in next 
GeoAPI release.
 + * Those methods are defined in a separated class in order to make easier for 
us to identify
 + * which methods may be removed from SIS (actually moved to GeoAPI) in a 
future GeoAPI release.
 + *
 + * <p>This class is needed for Apache SIS main branch, since the later is 
linked to GeoAPI official release.
 + * But this class can be removed on Apache SIS branches which are linked to a 
GeoAPI development branch.</p>
 + *
 + * @author  Martin Desruisseaux (Geomatys)
 + */
- public final class GeoapiAssert extends Static {
++public final class GeoapiAssert {
 +    /**
 +     * A flag for code that are pending next GeoAPI release before to be 
enabled.
 +     * This flag is always set to {@code false}, except occasionally just 
before
 +     * a GeoAPI release for testing purpose. It shall be used as below:
 +     *
 +     * {@snippet lang="java" :
 +     *     if (PENDING_NEXT_GEOAPI_RELEASE) {
 +     *         // Do some stuff here.
 +     *     }
 +     *     }
 +     *
 +     * The intend is to make easier to identify test cases that fail with the 
current version
 +     * of the {@code geoapi-conformance} module, but should pass with the 
development snapshot.
 +     */
 +    public static final boolean PENDING_NEXT_GEOAPI_RELEASE = false;
 +
 +    /**
 +     * The keyword for unrestricted value in {@link String} arguments.
 +     */
 +    private static final String UNRESTRICTED = "##unrestricted";
 +
 +    /**
 +     * Do not allow instantiation of this class.
 +     */
 +    private GeoapiAssert() {
 +    }
 +
 +    private static String nonNull(final String message) {
 +        return (message != null) ? message.trim().concat(" ") : "";
 +    }
 +
 +    /**
 +     * Returns the concatenation of the given message with the given 
extension.
 +     * This method returns the given extension if the message is null or 
empty.
 +     *
 +     * <p>Invoking this method is equivalent to invoking {@code 
nonNull(message) + ext},
 +     * but avoid the creation of temporary objects in the common case where 
the message
 +     * is null.</p>
 +     *
 +     * @param  message  the message, or {@code null}.
 +     * @param  ext      the extension to append after the message.
 +     * @return the concatenated string.
 +     */
 +    private static String concat(String message, final String ext) {
 +        if (message == null || (message = message.trim()).isEmpty()) {
 +            return ext;
 +        }
 +        return message + ' ' + ext;
 +    }
 +
 +    /**
 +     * Verifies if we expected a null value, then returns {@code true} if the 
value is null as expected.
 +     */
 +    private static boolean isNull(final Object expected, final Object actual, 
final String message) {
 +        final boolean isNull = (actual == null);
 +        if (isNull != (expected == null)) {
 +            fail(concat(message, isNull ? "Value is null." : "Expected 
null."));
 +        }
 +        return isNull;
 +    }
 +
 +    public static void assertPositive(final int value, final String message) {
 +        Assert.assertPositive(message, value);
 +    }
 +
 +    public static void assertStrictlyPositive(final int value, final String 
message) {
 +        Assert.assertStrictlyPositive(message, value);
 +    }
 +
 +    public static <T> void assertValidRange(final Comparable<T> minimum, 
final Comparable<T> maximum, final String message) {
 +        Assert.assertValidRange(message, minimum, maximum);
 +    }
 +
 +    public static void assertValidRange(final int minimum, final int maximum, 
final String message) {
 +        Assert.assertValidRange(message, minimum, maximum);
 +    }
 +
 +    public static void assertValidRange(final double minimum, final double 
maximum, final String message) {
 +        Assert.assertValidRange(message, minimum, maximum);
 +    }
 +
 +    public static <T> void assertBetween(final Comparable<T> minimum, final 
Comparable<T> maximum, T value, final String message) {
 +        Assert.assertBetween(message, minimum, maximum, value);
 +    }
 +
 +    public static void assertBetween(final int minimum, final int maximum, 
final int value, final String message) {
 +        Assert.assertBetween(message, minimum, maximum, value);
 +    }
 +
 +    public static void assertBetween(final double minimum, final double 
maximum, final double value, final String message) {
 +        Assert.assertBetween(message, minimum, maximum, value);
 +    }
 +
 +    public static void assertContains(final Collection<?> collection, final 
Object value, final String message) {
 +        Assert.assertContains(message, collection, value);
 +    }
 +
 +    /**
 +     * Asserts that the title or an alternate title of the given citation is 
equal to the given string.
 +     * This method is typically used for testing if a citation stands for the 
OGC, OGP or EPSG authority
 +     * for instance. Such abbreviations are often declared as {@linkplain 
Citation#getAlternateTitles()
 +     * alternate titles} rather than the main {@linkplain Citation#getTitle() 
title}, but this method
 +     * tests both for safety.
 +     *
 +     * @param expected  the expected title or alternate title.
 +     * @param actual    the citation to test.
 +     * @param message   header of the exception message in case of failure, 
or {@code null} if none.
 +     */
 +    public static void assertAnyTitleEquals(final String expected, final 
Citation actual, final String message) {
 +        if (isNull(expected, actual, message)) {
 +            return;
 +        }
 +        InternationalString title = actual.getTitle();
 +        if (title != null && expected.equals(title.toString())) {
 +            return;
 +        }
 +        for (final InternationalString t : actual.getAlternateTitles()) {
 +            if (expected.equals(t.toString())) {
 +                return;
 +            }
 +        }
 +        fail(concat(message, '"' + expected + "\" not found in title or 
alternate titles."));
 +    }
 +
 +    /**
 +     * Asserts that the given identifier is equal to the given authority, 
code space, version and code.
 +     * If any of the above-cited properties is {@code ""##unrestricted"}, 
then it will not be verified.
 +     * This flexibility is useful in the common case where a test accepts any 
{@code version} value.
 +     *
 +     * @param authority  the expected authority title or alternate title (may 
be {@code null}), or {@code "##unrestricted"}.
 +     * @param codeSpace  the expected code space (may be {@code null}), or 
{@code "##unrestricted"}.
 +     * @param version    the expected version    (may be {@code null}), or 
{@code "##unrestricted"}.
 +     * @param code       the expected code value (may be {@code null}), or 
{@code "##unrestricted"}.
 +     * @param actual     the identifier to test.
 +     * @param message    header of the exception message in case of failure, 
or {@code null} if none.
 +     */
 +    public static void assertIdentifierEquals(final String authority, final 
String codeSpace, final String version,
 +            final String code, final ReferenceIdentifier actual, final String 
message)
 +    {
 +        if (actual == null) {
 +            fail(concat(message, "Identifier is null"));
 +        } else {
 +            if (!UNRESTRICTED.equals(authority)) 
assertAnyTitleEquals(authority, actual.getAuthority(), message);
 +            if (!UNRESTRICTED.equals(codeSpace)) assertEquals(codeSpace, 
actual.getCodeSpace(), () -> concat(message, "Wrong code space"));
 +            if (!UNRESTRICTED.equals(version))   assertEquals(version,   
actual.getVersion(),   () -> concat(message, "Wrong version"));
 +            if (!UNRESTRICTED.equals(code)) assertEquals(code, 
actual.getCode(), () -> concat(message, "Wrong code"));
 +        }
 +    }
 +
 +    /**
 +     * Asserts that all axes in the given coordinate system are pointing 
toward the given directions, in the same order.
 +     *
 +     * @param cs        the coordinate system to test.
 +     * @param expected  the expected axis directions.
 +     */
 +    public static void assertAxisDirectionsEqual(final CoordinateSystem cs, 
final AxisDirection... expected) {
 +        assertAxisDirectionsEqual(cs, expected, null);
 +    }
 +
 +    /**
 +     * Asserts that all axes in the given coordinate system are pointing 
toward the given directions,
 +     * in the same order.
 +     *
 +     * @param cs        the coordinate system to test.
 +     * @param expected  the expected axis directions.
 +     * @param message   header of the exception message in case of failure, 
or {@code null} if none.
 +     */
 +    public static void assertAxisDirectionsEqual(final CoordinateSystem cs, 
final AxisDirection[] expected, final String message) {
 +        assertEquals(expected.length, cs.getDimension(), () -> 
concat(message, "Wrong coordinate system dimension."));
 +        for (int i=0; i<expected.length; i++) {
 +            final int ci = i;   // Because lambda expressions require final 
values.
 +            assertEquals(expected[i], cs.getAxis(i).getDirection(),
 +                    () -> concat(message, "Wrong axis direction at index" + 
ci + '.'));
 +        }
 +    }
 +
 +    /**
 +     * Asserts that the given matrix is equal to the expected one, up to the 
given tolerance value.
 +     *
 +     * @param expected   the expected matrix, which may be {@code null}.
 +     * @param actual     the matrix to compare, or {@code null}.
 +     * @param tolerance  the tolerance threshold.
 +     * @param message    header of the exception message in case of failure, 
or {@code null} if none.
 +     *
 +     * @see 
org.opengis.test.referencing.TransformTestCase#assertMatrixEquals(String, 
Matrix, Matrix, Matrix)
 +     */
 +    public static void assertMatrixEquals(final Matrix expected, final Matrix 
actual, final double tolerance, final String message) {
 +        if (isNull(expected, actual, message)) {
 +            return;
 +        }
 +        final int numRow = actual.getNumRow();
 +        final int numCol = actual.getNumCol();
 +        assertEquals(expected.getNumRow(), numRow, "numRow");
 +        assertEquals(expected.getNumCol(), numCol, "numCol");
 +        for (int j=0; j<numRow; j++) {
 +            for (int i=0; i<numCol; i++) {
 +                final double e = expected.getElement(j,i);
 +                final double a = actual.getElement(j,i);
 +                if (!(StrictMath.abs(e - a) <= tolerance) && 
Double.doubleToLongBits(a) != Double.doubleToLongBits(e)) {
 +                    fail(nonNull(message) + "Matrix.getElement(" + j + ", " + 
i + "): expected " + e + " but got " + a);
 +                }
 +            }
 +        }
 +    }
 +}

Reply via email to