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 2a51813d48e47f0a24888bb8b3fa615a55e25c4a
Merge: 9cee4111e1 24e0c1b0b0
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Jan 22 15:45:02 2024 +0100

    Merge branch 'geoapi-3.1':
    Post-merge reorganization of import statements.

 .../main/org/apache/sis/feature/FeatureType.java                    | 1 -
 .../main/org/apache/sis/feature/Property.java                       | 1 -
 .../main/org/apache/sis/filter/Expression.java                      | 1 -
 .../org.apache.sis.feature/main/org/apache/sis/filter/Filter.java   | 1 -
 .../main/org/apache/sis/filter/FilterLiteral.java                   | 1 -
 .../apache/sis/pending/geoapi/filter/BetweenComparisonOperator.java | 1 -
 .../apache/sis/pending/geoapi/filter/BinaryComparisonOperator.java  | 1 -
 .../org/apache/sis/pending/geoapi/filter/FilterExpressions.java     | 1 -
 .../main/org/apache/sis/pending/geoapi/filter/Literal.java          | 1 -
 .../main/org/apache/sis/pending/geoapi/filter/LogicalOperator.java  | 1 -
 .../main/org/apache/sis/pending/geoapi/filter/Name.java             | 1 -
 .../main/org/apache/sis/pending/geoapi/filter/SortBy.java           | 1 -
 .../main/org/apache/sis/pending/geoapi/filter/SortProperty.java     | 1 -
 .../main/org/apache/sis/pending/geoapi/filter/ValueReference.java   | 1 -
 .../main/org/apache/sis/metadata/iso/OnlineResourceAdapter.java     | 1 -
 .../main/org/apache/sis/metadata/iso/URIStringAdapter.java          | 1 -
 .../apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java   | 1 -
 .../org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java | 1 -
 .../org/apache/sis/metadata/iso/maintenance/LegacyFeatureType.java  | 1 -
 .../main/org/apache/sis/pending/geoapi/evolution/Interim.java       | 1 -
 .../main/org/apache/sis/pending/geoapi/evolution/InterimType.java   | 1 -
 .../apache/sis/pending/geoapi/evolution/UnsupportedCodeList.java    | 1 -
 .../sis/pending/geoapi/evolution/UnsupportedCodeListAdapter.java    | 1 -
 .../sis/referencing/gazetteer/ModifiableLocationTypeAdapter.java    | 1 -
 .../main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java     | 6 +++---
 .../main/org/apache/sis/referencing/crs/ParametricCRS.java          | 1 -
 .../sis/referencing/operation/transform/ConcatenatedTransform.java  | 2 +-
 .../main/org/apache/sis/referencing/util/ReferencingUtilities.java  | 4 +++-
 .../operation/projection/ParameterizedTransformTestMock.java        | 3 ++-
 .../sis/referencing/operation/transform/TransformTestCase.java      | 3 ++-
 .../test/org/apache/sis/storage/netcdf/base/TestData.java           | 3 ++-
 .../main/org/apache/sis/pending/geoapi/temporal/Instant.java        | 1 -
 .../main/org/apache/sis/pending/geoapi/temporal/Period.java         | 1 -
 .../main/org/apache/sis/pending/geoapi/temporal/PeriodDuration.java | 1 -
 .../main/org/apache/sis/pending/geoapi/temporal/Position.java       | 1 -
 .../org/apache/sis/pending/geoapi/temporal/TemporalFactory.java     | 1 -
 .../test/org/apache/sis/test/ContentVerifier.java                   | 3 ++-
 .../org.apache.sis.util/test/org/apache/sis/test/GeoapiAssert.java  | 3 ++-
 38 files changed, 17 insertions(+), 40 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureType.java
index f30ca5e6ea,d4b582c1b0..d559a692ef
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureType.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureType.java
@@@ -14,11 -14,6 +14,10 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.feature;
 +
- // Specific to the main branch:
 +import java.util.Collection;
 +import org.opengis.util.GenericName;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Property.java
index d642c83a52,5406add651..931c1ca132
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Property.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Property.java
@@@ -14,18 -14,15 +14,17 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.feature;
 +
- // Specific to the main branch:
 +import org.opengis.util.GenericName;
 +
  
  /**
 - * Utility methods for testing XML files or JAXB annotations.
 - * {@link org.apache.sis.xml.test.AnnotationConsistencyCheck} and
 - * {@link org.apache.sis.xml.test.SchemaCompliance} verifies JAXB annotations.
 - * {@link org.apache.sis.xml.test.DocumentComparator} compares an actual XML 
document with the expected one.
 + * Place-holder for an interface not available in GeoAPI 3.0.
 + * This place-holder will be removed after we upgrade to a later GeoAPI 
version.
   *
 - * <p>Objects defined in this package are only for SIS testing purpose any 
many change
 - * in any future version without notice.</p>
 + * <p><strong>Do not put this type in public API</strong>. We need to prevent 
users from using
 + * this type in order to reduce compatibility breaks when we will upgrade the 
GeoAPI version.</p>
   *
   * @author  Martin Desruisseaux (Geomatys)
   */
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/Expression.java
index 7d10de7f66,0000000000..82f2c09c2f
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/Expression.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/Expression.java
@@@ -1,82 -1,0 +1,81 @@@
 +/*
 + * 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.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.function.Function;
 +import org.opengis.util.ScopedName;
 +
 +
 +/**
 + * A literal or a named procedure that performs a distinct computation.
 + *
 + * <div class="warning"><b>Upcoming API change</b><br>
 + * This is a placeholder for a GeoAPI 3.1 interface not yet released.
 + * In a future version, all usages of this interface may be replaced
 + * by an interface of the same name but in the {@code org.opengis.filter} 
package
 + * instead of {@code org.apache.sis.filter}.
 + * </div>
 + *
 + * @param  <R>  the type of resources (e.g. {@code Feature}) used as inputs.
 + * @param  <V>  the type of values computed by the expression.
 + */
 +public interface Expression<R,V> extends Function<R,V> {
 +    /**
 +     * Returns the name of the function to be called.
 +     *
 +     * @return name of the function to be called.
 +     */
 +    ScopedName getFunctionName();
 +
 +    /**
 +     * Returns the class of resources expected by this expression.
 +     *
 +     * @return type of resources accepted by this expression.
 +     */
 +    Class<? super R> getResourceClass();
 +
 +    /**
 +     * Returns the list sub-expressions that will be evaluated to provide the 
parameters to the function.
 +     *
 +     * @return the sub-expressions to be evaluated, or an empty list if none.
 +     */
 +    List<Expression<R,?>> getParameters();
 +
 +    /**
 +     * Evaluates the expression value based on the content of the given 
object.
 +     *
 +     * @param  input  the object to be evaluated by the expression.
 +     *         Can be {@code null} if this expression allows null values.
 +     * @return value computed by the expression.
 +     * @throws NullPointerException if {@code input} is null and this 
expression requires non-null values.
 +     * @throws IllegalArgumentException if the expression can not be applied 
on the given object.
 +     */
 +    @Override
 +    V apply(R input);
 +
 +    /**
 +     * Returns an expression doing the same evaluation than this method, but 
returning results
 +     * as values of the specified type.
 +     *
 +     * @param  <N>   compile-time value of {@code type}.
 +     * @param  type  desired type of expression results.
 +     * @return expression doing the same operation this this expression but 
with results of the specified type.
 +     * @throws ClassCastException if the specified type is not a target type 
supported by implementation.
 +     */
 +    <N> Expression<R,N> toValueType(Class<N> type);
 +}
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/Filter.java
index 0e11130b4f,0000000000..abada8666e
mode 100644,000000..100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/Filter.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/Filter.java
@@@ -1,95 -1,0 +1,94 @@@
 +/*
 + * 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.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.function.Predicate;
 +
 +
 +/**
 + * Identification of a subset of resources from a collection of resources
 + * whose property values satisfy a set of logically connected predicates.
 + *
 + * <div class="warning"><b>Upcoming API change</b><br>
 + * This is a placeholder for a GeoAPI 3.1 interface not yet released.
 + * In a future version, all usages of this interface may be replaced
 + * by an interface of the same name but in the {@code org.opengis.filter} 
package
 + * instead of {@code org.apache.sis.filter}.
 + * </div>
 + *
 + * @param  <R>  the type of resources (e.g. {@link 
org.apache.sis.feature.AbstractFeature}) to filter.
 + *
 + * @since 1.1
 + */
 +public interface Filter<R> extends Predicate<R> {
 +    /**
 +     * A filter that always evaluates to {@code true}.
 +     *
 +     * @param  <R>  the type of resources to filter.
 +     * @return the "no filtering" filter.
 +     */
 +    @SuppressWarnings("unchecked")
 +    static <R> Filter<R> include() {
 +        return FilterLiteral.INCLUDE;
 +    }
 +
 +    /**
 +     * A filter that always evaluates to {@code false}.
 +     *
 +     * @param  <R>  the type of resources to filter.
 +     * @return the "exclude all" filter.
 +     */
 +    @SuppressWarnings("unchecked")
 +    static <R> Filter<R> exclude() {
 +        return FilterLiteral.EXCLUDE;
 +    }
 +
 +    /**
 +     * Returns the nature of the operator.
 +     *
 +     * @return the nature of this operator.
 +     */
 +    Enum<?> getOperatorType();
 +
 +    /**
 +     * Returns the class of resources expected by this filter.
 +     *
 +     * @return type of resources accepted by this filter.
 +     *
 +     * @since 1.4
 +     */
 +    Class<? super R> getResourceClass();
 +
 +    /**
 +     * Returns the expressions used as arguments for this filter.
 +     *
 +     * @return the expressions used as inputs, or an empty list if none.
 +     */
 +    List<Expression<R,?>> getExpressions();
 +
 +    /**
 +     * Given an object, determines if the test(s) represented by this filter 
are passed.
 +     *
 +     * @param  object  the object (often a {@code Feature} instance) to 
evaluate.
 +     * @return {@code true} if the test(s) are passed for the provided object.
 +     * @throws NullPointerException if {@code object} is null.
 +     * @throws IllegalArgumentException if the filter can not be applied on 
the given object.
 +     */
 +    @Override
 +    boolean test(R object);
 +}
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/FilterLiteral.java
index 5cfc050274,0000000000..d39cef550c
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/FilterLiteral.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/FilterLiteral.java
@@@ -1,71 -1,0 +1,70 @@@
 +/*
 + * 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.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.Collections;
 +import java.io.Serializable;
 +import java.io.ObjectStreamException;
 +
 +
 +/**
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
 + */
 +final class FilterLiteral implements Filter<Object>, Serializable {
 +    @SuppressWarnings("rawtypes")
 +    public static final Filter INCLUDE = new FilterLiteral(true);
 +
 +    @SuppressWarnings("rawtypes")
 +    public static final Filter EXCLUDE = new FilterLiteral(false);
 +
 +    private final boolean value;
 +
 +    private FilterLiteral(final boolean value) {
 +        this.value = value;
 +    }
 +
 +    @Override
 +    public Enum<?> getOperatorType() {
 +        return value ? FilterName.INCLUDE : FilterName.EXCLUDE;
 +    }
 +
 +    @Override
 +    public Class<Object> getResourceClass() {
 +        return Object.class;
 +    }
 +
 +    @Override
 +    public List<Expression<? super Object, ?>> getExpressions() {
 +        return Collections.emptyList();
 +    }
 +
 +    @Override
 +    public boolean test(Object object) {
 +        return value;
 +    }
 +
 +    @Override
 +    public String toString() {
 +        return "Filter." + (value ? "INCLUDE" : "EXCLUDE");
 +    }
 +
 +    private Object readResolve() throws ObjectStreamException {
 +        return value ? INCLUDE : EXCLUDE;
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/BetweenComparisonOperator.java
index 150bc15949,8254cbf98d..e59a40790f
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/BetweenComparisonOperator.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/BetweenComparisonOperator.java
@@@ -14,20 -14,15 +14,19 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import org.apache.sis.filter.Expression;
 +import org.apache.sis.filter.Filter;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +@SuppressWarnings("doclint:missing")
 +public interface BetweenComparisonOperator<R> extends Filter<R> {
 +    Expression<R,?> getExpression();
 +    Expression<R,?> getLowerBoundary();
 +    Expression<R,?> getUpperBoundary();
  }
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/BinaryComparisonOperator.java
index 9297b589ab,8254cbf98d..85df30990a
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/BinaryComparisonOperator.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/BinaryComparisonOperator.java
@@@ -14,21 -14,15 +14,20 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import org.apache.sis.filter.Expression;
 +import org.apache.sis.filter.Filter;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +@SuppressWarnings("doclint:missing")
 +public interface BinaryComparisonOperator<R> extends Filter<R> {
 +    Expression<R,?> getOperand1();
 +    Expression<R,?> getOperand2();
 +    boolean isMatchingCase();
 +    MatchAction getMatchAction();
  }
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/FilterExpressions.java
index 0be04f0bde,0000000000..4cbbb41cd0
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/FilterExpressions.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/FilterExpressions.java
@@@ -1,112 -1,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.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.Objects;
 +import java.util.AbstractList;
 +import java.util.Locale;
 +import org.opengis.util.ScopedName;
 +import org.apache.sis.filter.Filter;
 +import org.apache.sis.filter.Expression;
 +import org.apache.sis.util.iso.Names;
 +
 +
 +/**
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
 + */
 +@SuppressWarnings("doclint:missing")
 +final class FilterExpressions<R> extends AbstractList<Expression<R,?>> {
 +    private final List<Filter<R>> filters;
 +
 +    FilterExpressions(final List<Filter<R>> filters) {
 +        this.filters = Objects.requireNonNull(filters);
 +    }
 +
 +    @Override
 +    public boolean isEmpty() {
 +        return filters.isEmpty();
 +    }
 +
 +    @Override
 +    public int size() {
 +        return filters.size();
 +    }
 +
 +    @Override
 +    public Expression<R,?> get(final int index) {
 +        return new Element<>(filters.get(index));
 +    }
 +
 +    private static final class Element<R> implements Expression<R,Boolean> {
 +        private final Filter<R> filter;
 +
 +        Element(final Filter<R> filter) {
 +            this.filter = Objects.requireNonNull(filter);
 +        }
 +
 +        @Override
 +        public ScopedName getFunctionName() {
 +            final Enum<?> type = filter.getOperatorType();
 +            final String identifier = type.name().toLowerCase(Locale.US);
 +            if (identifier != null) {
 +                return Names.createScopedName(Name.STANDARD, null, 
identifier);
 +            } else {
 +                return Names.createScopedName(Name.EXTENSION, null, 
type.name());
 +            }
 +        }
 +
 +        @Override
 +        public Class<? super R> getResourceClass() {
 +            return filter.getResourceClass();
 +        }
 +
 +        @Override
 +        public List<Expression<R,?>> getParameters() {
 +            return filter.getExpressions();
 +        }
 +
 +        @Override
 +        public Boolean apply(final R input) {
 +            return filter.test(input);
 +        }
 +
 +        @Override
 +        @SuppressWarnings("unchecked")
 +        public <N> Expression<R,N> toValueType(final Class<N> type) {
 +            if (type.isAssignableFrom(Boolean.class)) return 
(Expression<R,N>) this;
 +            else throw new ClassCastException();
 +        }
 +
 +        @Override
 +        public int hashCode() {
 +            return ~filter.hashCode();
 +        }
 +
 +        @Override
 +        public boolean equals(final Object obj) {
 +            return (obj instanceof Element) && filter.equals(((Element) 
obj).filter);
 +        }
 +
 +        @Override
 +        public String toString() {
 +            return "Expression[" + filter.toString() + ']';
 +        }
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/Literal.java
index 4577d62d48,8254cbf98d..de447db3dd
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/Literal.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/Literal.java
@@@ -14,30 -14,15 +14,29 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.Collections;
 +import org.opengis.util.ScopedName;
 +import org.apache.sis.filter.Expression;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 +@SuppressWarnings("doclint:missing")
 +public interface Literal<R,V> extends Expression<R,V> {
 +    @Override
 +    default ScopedName getFunctionName() {
 +        return Name.LITERAL;
 +    }
 +
 +    @Override
 +    default List<Expression<R,?>> getParameters() {
 +        return Collections.emptyList();
 +    }
  
 -    exports org.apache.sis.map;
 +    V getValue();
  }
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/LogicalOperator.java
index 07d0a7489f,8254cbf98d..9ecd8f7a37
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/LogicalOperator.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/LogicalOperator.java
@@@ -14,27 -14,15 +14,26 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import org.apache.sis.filter.Filter;
 +import org.apache.sis.filter.Expression;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 +@SuppressWarnings("doclint:missing")
 +public interface LogicalOperator<R> extends Filter<R> {
 +    @Override
 +    LogicalOperatorName getOperatorType();
 +
 +    @Override
 +    default List<Expression<R,?>> getExpressions() {
 +        return new FilterExpressions<>(getOperands());
 +    }
  
 -    exports org.apache.sis.map;
 +    List<Filter<R>> getOperands();
  }
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/Name.java
index 530f611a41,0000000000..2c0201bc90
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/Name.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/Name.java
@@@ -1,42 -1,0 +1,41 @@@
 +/*
 + * 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.filter;
 +
- // Specific to the main branch:
 +import org.opengis.util.LocalName;
 +import org.opengis.util.ScopedName;
 +import org.apache.sis.filter.internal.FunctionNames;
 +import org.apache.sis.util.iso.Names;
 +
 +
 +/**
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
 + */
 +@SuppressWarnings("doclint:missing")
 +public final class Name {
 +    static final LocalName STANDARD = Names.createLocalName(null, null, 
"fes");
 +
 +    static final LocalName EXTENSION = Names.createLocalName(null, null, 
"extension");
 +
 +    public static final ScopedName LITERAL = Names.createScopedName(STANDARD, 
null, FunctionNames.Literal);
 +
 +    public static final ScopedName VALUE_REFERENCE = 
Names.createScopedName(STANDARD, null, FunctionNames.ValueReference);
 +
 +    private Name() {
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/SortBy.java
index 031e127fd4,8254cbf98d..acda9ca854
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/SortBy.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/SortBy.java
@@@ -14,18 -14,15 +14,17 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.Comparator;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +@SuppressWarnings("doclint:missing")
 +public interface SortBy<R> extends Comparator<R> {
 +    List<SortProperty<R>> getSortProperties();
  }
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/SortProperty.java
index 61f95bccd9,8254cbf98d..692742122a
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/SortProperty.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/SortProperty.java
@@@ -14,19 -14,15 +14,18 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import java.util.Comparator;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 +@SuppressWarnings("doclint:missing")
 +public interface SortProperty<R> extends Comparator<R> {
 +    ValueReference<R,?> getValueReference();
  
 -    exports org.apache.sis.map;
 +    SortOrder getSortOrder();
  }
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/ValueReference.java
index ba315f3854,8254cbf98d..868ac52fc3
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/ValueReference.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/ValueReference.java
@@@ -14,17 -14,15 +14,16 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.filter;
 +
- // Specific to the main branch:
 +import org.apache.sis.filter.Expression;
 +
  
  /**
 - * Raster imagery and geometry features.
 - *
 - * @author  Johann Sorel (Geomatys)
 + * Placeholder for GeoAPI 3.1 interfaces (not yet released).
 + * Shall not be visible in public API, as it will be deleted after next 
GeoAPI release.
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +@SuppressWarnings("doclint:missing")
 +public interface ValueReference<R,V> extends Expression<R,V> {
 +    String getXPath();
  }
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/Interim.java
index 1aba3a5484,0000000000..54a86ce83f
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,69 -1,0 +1,68 @@@
 +/*
 + * 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;
 +
- // Specific to the main branch:
 +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 {
 +    /**
 +     * 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 2eaaaf8f40,2dd08f7e4d..8c48b7a5f9
--- 
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
@@@ -14,14 -14,12 +14,13 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 -package org.apache.sis.style.se1;
 +package org.apache.sis.pending.geoapi.evolution;
  
- // Specific to the main branch:
 -import jakarta.xml.bind.annotation.adapters.XmlAdapter;
 -
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.filter.Expression;
 +import java.lang.annotation.ElementType;
 +import java.lang.annotation.Retention;
 +import java.lang.annotation.RetentionPolicy;
 +import java.lang.annotation.Target;
 +import java.lang.reflect.Method;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/geoapi/evolution/UnsupportedCodeList.java
index 32179593dd,0000000000..e949e74e4a
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,99 -1,0 +1,98 @@@
 +/*
 + * 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;
 +
- // Specific to the main branch:
 +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 c59aca6cd1,0000000000..d0cf585e44
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,165 -1,0 +1,164 @@@
 +/*
 + * 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;
 +
- // Specific to the main branch:
 +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);
 +    }
 +
 +    /**
 +     * 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.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationTypeAdapter.java
index 806278f66f,0000000000..e3a7f657fb
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationTypeAdapter.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationTypeAdapter.java
@@@ -1,102 -1,0 +1,101 @@@
 +/*
 + * 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.gazetteer;
 +
- // Specific to the main branch:
 +import java.util.List;
 +import java.util.Map;
 +import java.util.IdentityHashMap;
 +import org.opengis.util.InternationalString;
 +import org.apache.sis.util.internal.UnmodifiableArrayList;
 +
 +
 +/**
 + * Workaround for the lack of {@code LocationType} interface in GeoAPI 3.0.
 + * This workaround will be removed if a future GeoAPI version publish that 
interface,
 + * or if {@link AbstractLocationType} is made public.
 + */
 +final class ModifiableLocationTypeAdapter extends ModifiableLocationType {
 +    /**
 +     * The reference system of the original type.
 +     * This is the only information not stored in {@link 
ModifiableLocationType}.
 +     */
 +    private final ReferencingByIdentifiers referenceSystem;
 +
 +    /**
 +     * Copies all information from the given type.
 +     */
 +    private ModifiableLocationTypeAdapter(final AbstractLocationType type,
 +            final Map<AbstractLocationType,ModifiableLocationTypeAdapter> 
previous)
 +    {
 +        super(type.getName());
 +        setTheme(type.getTheme());
 +        setDefinition(type.getDefinition());
 +        setTerritoryOfUse(type.getTerritoryOfUse());
 +        setOwner(type.getOwner());
 +        for (final InternationalString s : type.getIdentifications()) {
 +            addIdentification(s);
 +        }
 +        referenceSystem = type.getReferenceSystem();
 +        for (final AbstractLocationType c : type.getChildren()) {
 +            ModifiableLocationTypeAdapter p = previous.get(c);
 +            if (p == null) {
 +                p = new ModifiableLocationTypeAdapter(c, previous);
 +                previous.put(c, p);
 +            }
 +            p.addParent(this);
 +        }
 +    }
 +
 +    /**
 +     * Returns type type as-is if it is already an instance of {@code 
ModifiableLocationType},
 +     * or returns a copy otherwise.
 +     */
 +    static ModifiableLocationType copy(final AbstractLocationType type) {
 +        if (type instanceof ModifiableLocationType) {
 +            return (ModifiableLocationType) type;
 +        } else {
 +            return new ModifiableLocationTypeAdapter(type,
 +                    new 
IdentityHashMap<AbstractLocationType,ModifiableLocationTypeAdapter>());
 +        }
 +    }
 +
 +    /**
 +     * Copies a list of location types.
 +     */
 +    static List<ModifiableLocationType> copy(final List<? extends 
AbstractLocationType> types) {
 +        final Map<AbstractLocationType,ModifiableLocationTypeAdapter> 
previous = new IdentityHashMap<>();
 +        final ModifiableLocationType[] nt = new 
ModifiableLocationType[types.size()];
 +        for (int i=0; i<nt.length; i++) {
 +            final AbstractLocationType c = types.get(i);
 +            ModifiableLocationTypeAdapter p = previous.get(c);
 +            if (p == null) {
 +                p = new ModifiableLocationTypeAdapter(c, previous);
 +                previous.put(c, p);
 +            }
 +            nt[i] = p;
 +        }
 +        return UnmodifiableArrayList.wrap(nt);
 +    }
 +
 +    /**
 +     * Returns the reference system of the type given to the constructor.
 +     */
 +    @Override
 +    public ReferencingByIdentifiers getReferenceSystem() {
 +        return referenceSystem;
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
index 823972fa20,d4a72411e1..9610db43fa
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
@@@ -46,9 -46,6 +46,9 @@@ import org.apache.sis.io.wkt.Formatter
  import org.apache.sis.measure.Units;
  import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
  
- // Specific to the geoapi-3.1 and geoapi-4.0 branches:
- import org.opengis.metadata.Identifier;
++// Specific to the main branch:
++import org.opengis.referencing.ReferenceIdentifier;
 +
  
  /**
   * A 2- or 3-dimensional coordinate reference system based on a geodetic 
datum.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/ParametricCRS.java
index 0ce4963bec,8254cbf98d..a1d7d8a03c
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/ParametricCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/ParametricCRS.java
@@@ -14,16 -14,15 +14,15 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.referencing.crs;
 +
- // Specific to the main branch:
 +import org.opengis.referencing.crs.SingleCRS;
 +
  
  /**
 - * Raster imagery and geometry features.
 + * Place-holder for an interface not yet present in GeoAPI 3.0.
   *
 - * @author  Johann Sorel (Geomatys)
 + * @author  Martin Desruisseaux (Geomatys)
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +interface ParametricCRS extends SingleCRS {
  }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java
index 54e79ea9f5,d0bb28fc88..17704043b5
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java
@@@ -60,6 -59,6 +59,9 @@@ import org.apache.sis.referencing.opera
  import org.apache.sis.metadata.internal.Identifiers;
  import org.apache.sis.xml.NilObject;
  
++// Specific to the main branch:
++import org.opengis.referencing.ReferenceIdentifier;
++
  
  /**
   * A set of static methods working on GeoAPI referencing objects.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ParameterizedTransformTestMock.java
index 240bd72a22,0000000000..41dda797cc
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ParameterizedTransformTestMock.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ParameterizedTransformTestMock.java
@@@ -1,77 -1,0 +1,78 @@@
 +/*
 + * 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.projection;
 +
- // Specific to the main branch:
 +import org.opengis.referencing.operation.MathTransformFactory;
++
++// Test dependencies
 +import static org.junit.Assume.*;
 +import static org.apache.sis.test.GeoapiAssert.PENDING_NEXT_GEOAPI_RELEASE;
 +
 +
 +/**
 + * Placeholder for a GeoAPI 3.1 method which was not available in GeoAPI 3.0.
 + * This placeholder does nothing. See Apache SIS JDK6 branch for a real test.
 + *
 + * @author  Martin Desruisseaux (Geomatys)
 + */
 +final class ParameterizedTransformTestMock {
 +    ParameterizedTransformTestMock(MathTransformFactory factory) {
 +        // See GeoAPI 3.1 for real construction.
 +    }
 +
 +    public void testMercator1SP() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    public void testMercator2SP() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    public void testPseudoMercator() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    public void testMiller() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    public void testLambertConicConformal1SP() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    public void testLambertConicConformal2SP() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    public void testLambertConicConformalBelgium() {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/TransformTestCase.java
index 2665a07c8c,0000000000..256db6cb7e
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/TransformTestCase.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/TransformTestCase.java
@@@ -1,65 -1,0 +1,66 @@@
 +/*
 + * 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;
 +
- // Specific to the main branch:
 +import java.util.Random;
++
++// Test dependencies
 +import static org.junit.Assume.*;
 +import static org.apache.sis.test.GeoapiAssert.PENDING_NEXT_GEOAPI_RELEASE;
 +
 +
 +/**
 + * Placeholder for a GeoAPI 3.1 method which was not available in GeoAPI 3.0.
 + * This placeholder does nothing. See Apache SIS JDK6 branch for a real test.
 + *
 + * @author  Martin Desruisseaux (Geomatys)
 + */
 +public class TransformTestCase extends 
org.opengis.test.referencing.TransformTestCase {
 +    /**
 +     * The deltas to use for approximating math transform derivatives by the 
finite differences method.
 +     */
 +    protected double[] derivativeDeltas;
 +
 +    /**
 +     * Placeholder for a GeoAPI 3.1 method which was not available in GeoAPI 
3.0.
 +     * This placeholder does nothing. See Apache SIS JDK6 branch for a real 
test.
 +     *
 +     * @param coordinate Ignored.
 +     */
 +    protected final void verifyDerivative(final double... coordinate) {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +
 +    /**
 +     * Placeholder for a GeoAPI 3.1 method which was not available in GeoAPI 
3.0.
 +     * This placeholder does nothing. See Apache SIS JDK6 branch for a real 
test.
 +     *
 +     * @param minOrdinates    Ignored.
 +     * @param maxOrdinates    Ignored.
 +     * @param numOrdinates    Ignored.
 +     * @param randomGenerator Ignored.
 +     */
 +    protected final void verifyInDomain(final double[] minOrdinates, final 
double[] maxOrdinates,
 +            final int[] numOrdinates, final Random randomGenerator)
 +    {
 +        // See GeoAPI 3.1 for the real test.
 +        // The test is run on Apache SIS branches.
 +       assumeTrue(PENDING_NEXT_GEOAPI_RELEASE); // For reporting the test as 
skippped.
 +    }
 +}
diff --cc 
endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestData.java
index e030c23b7b,a29dc1760d..7695095d21
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestData.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestData.java
@@@ -14,12 -14,12 +14,13 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 -package org.apache.sis.cql;
 +package org.apache.sis.storage.netcdf.base;
  
- // Specific to the main branch:
 -import org.locationtech.jts.geom.GeometryFactory;
 -import org.opengis.filter.FilterFactory;
 -import org.opengis.feature.Feature;
 -import org.apache.sis.filter.DefaultFilterFactory;
 +import java.net.URL;
 +import java.io.InputStream;
++
++// Test dependencies
 +import static org.junit.Assume.*;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Instant.java
index df32a3631a,8254cbf98d..42e96dbf6c
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Instant.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Instant.java
@@@ -14,25 -14,15 +14,24 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.temporal;
 +
- // Specific to the main branch:
 +import java.util.Date;
 +import org.opengis.temporal.TemporalPrimitive;
 +
  
  /**
 - * Raster imagery and geometry features.
 + * Placeholder for a GeoAPI interfaces not present in GeoAPI 3.0.
   *
 - * @author  Johann Sorel (Geomatys)
 + * @author  Martin Desruisseaux (Geomatys)
 + * @since   0.3
 + * @version 0.5
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +public interface Instant extends TemporalPrimitive {
 +    /**
 +     * Gets the date of this instant.
 +     *
 +     * @return The date.
 +     */
 +    Date getDate();
  }
diff --cc 
endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Period.java
index 49803fd695,5406add651..05c94dcccf
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Period.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Period.java
@@@ -14,31 -14,16 +14,30 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.temporal;
 +
- // Specific to the main branch:
 +import org.opengis.temporal.TemporalPrimitive;
 +
  
  /**
 - * Utility methods for testing XML files or JAXB annotations.
 - * {@link org.apache.sis.xml.test.AnnotationConsistencyCheck} and
 - * {@link org.apache.sis.xml.test.SchemaCompliance} verifies JAXB annotations.
 - * {@link org.apache.sis.xml.test.DocumentComparator} compares an actual XML 
document with the expected one.
 - *
 - * <p>Objects defined in this package are only for SIS testing purpose any 
many change
 - * in any future version without notice.</p>
 + * Placeholder for a GeoAPI interfaces not present in GeoAPI 3.0.
   *
   * @author  Martin Desruisseaux (Geomatys)
 + * @since   0.3
 + * @version 0.3
   */
 -package org.apache.sis.xml.test;
 +public interface Period extends TemporalPrimitive {
 +    /**
 +     * Links this period to the instant at which it ends.
 +     *
 +     * @return The beginning instant.
 +     */
 +    Instant getBeginning();
 +
 +    /**
 +     * Links this period to the instant at which it ends.
 +     *
 +     * @return The end instant.
 +     */
 +    Instant getEnding();
 +}
diff --cc 
endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/PeriodDuration.java
index 2f62d27e24,0000000000..15f686c990
mode 100644,000000..100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/PeriodDuration.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/PeriodDuration.java
@@@ -1,70 -1,0 +1,69 @@@
 +/*
 + * 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.temporal;
 +
- // Specific to the main branch:
 +import org.opengis.util.InternationalString;
 +
 +
 +/**
 + * Placeholder for a GeoAPI interfaces which is still incomplete in GeoAPI 
3.0.
 + * We reproduce here the GeoAPI 3.1-pending API. Note that at the time of 
writing,
 + * this is a bad API (values shall not be instances of {@link 
InternationalString}).
 + * This will be fixed in a future GeoAPI version.
 + *
 + * @author  Martin Desruisseaux (Geomatys)
 + * @since   0.3
 + * @version 0.3
 + */
 +@SuppressWarnings("doclint:missing")
 +public interface PeriodDuration extends org.opengis.temporal.PeriodDuration {
 +    /**
 +     * A positive integer, followed by the character "Y",
 +     * which indicated the number of years in the period.
 +     */
 +    InternationalString getYears();
 +
 +    /**
 +     * A positive integer, followed by the character "M",
 +     * which indicated the number of months in the period.
 +     */
 +    InternationalString getMonths();
 +
 +    /**
 +     * A positive integer, followed by the character "D",
 +     * which indicated the number of days in the period.
 +     */
 +    InternationalString getDays();
 +
 +    /**
 +     * A positive integer, followed by the character "H",
 +     * which indicated the number of hours in the period.
 +     */
 +    InternationalString getHours();
 +
 +    /**
 +     * A positive integer, followed by the character "M",
 +     * which indicated the number of minutes in the period.
 +     */
 +    InternationalString getMinutes();
 +
 +    /**
 +     * A positive integer, followed by the character "S",
 +     * which indicated the number of seconds in the period.
 +     */
 +    InternationalString getSeconds();
 +}
diff --cc 
endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Position.java
index bd633ff989,8254cbf98d..ba3604b9cd
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Position.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Position.java
@@@ -14,24 -14,15 +14,23 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.temporal;
 +
- // Specific to the main branch:
 +import java.util.Date;
 +
  
  /**
 - * Raster imagery and geometry features.
 + * Placeholder for a GeoAPI interfaces not present in GeoAPI 3.0.
   *
 - * @author  Johann Sorel (Geomatys)
 + * @author  Martin Desruisseaux (Geomatys)
 + * @since   0.3
 + * @version 0.3
   */
 -module org.apache.sis.portrayal.map {
 -    requires transitive org.apache.sis.portrayal;
 -    requires static org.locationtech.jts;
 -
 -    exports org.apache.sis.map;
 +public interface Position {
 +    /**
 +     * Returns the time value as a {@code Date} object.
 +     *
 +     * @return The temporal value.
 +     */
 +    Date getDate();
  }
diff --cc 
endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/TemporalFactory.java
index 21a6ffe3d6,d4b582c1b0..f63edc99e4
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/TemporalFactory.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/TemporalFactory.java
@@@ -14,11 -14,6 +14,10 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 +package org.apache.sis.pending.geoapi.temporal;
 +
- // Specific to the main branch:
 +import java.util.Date;
 +import org.opengis.util.InternationalString;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.util/test/org/apache/sis/test/ContentVerifier.java
index 59a017e091,2dd08f7e4d..9647c64f65
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/ContentVerifier.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/ContentVerifier.java
@@@ -14,11 -14,12 +14,12 @@@
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
 -package org.apache.sis.style.se1;
 +package org.apache.sis.test;
  
- // Specific to the main branch:
 -import jakarta.xml.bind.annotation.adapters.XmlAdapter;
 +import org.opengis.metadata.Metadata;
+ 
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.filter.Expression;
++// Test dependencies
 +import static org.junit.Assume.assumeTrue;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.util/test/org/apache/sis/test/GeoapiAssert.java
index 65fd059698,0000000000..f2ae5b0e43
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,194 -1,0 +1,195 @@@
 +/*
 + * 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;
 +
- // Specific to the main branch:
 +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.Assert.assertEquals;
 +import static org.junit.Assert.fail;
 +
 +
 +/**
 + * 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 trunk, 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 {
 +    /**
 +     * 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() {
 +    }
 +
 +    /**
 +     * 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 String message, final Object 
expected, final Object actual) {
 +        final boolean isNull = (actual == null);
 +        if (isNull != (expected == null)) {
 +            fail(concat(message, isNull ? "Value is null." : "Expected 
null."));
 +        }
 +        return isNull;
 +    }
 +
 +    /**
 +     * 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 message  Header of the exception message in case of failure, or 
{@code null} if none.
 +     * @param expected The expected title or alternate title.
 +     * @param actual   The citation to test.
 +     */
 +    public static void assertAnyTitleEquals(final String message, final 
String expected, final Citation actual) {
 +        if (isNull(message, expected, actual)) {
 +            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 equals 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 message    Header of the exception message in case of failure, 
or {@code null} if none.
 +     * @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.
 +     */
 +    public static void assertIdentifierEquals(final String message, final 
String authority, final String codeSpace,
 +            final String version, final String code, final 
ReferenceIdentifier actual)
 +    {
 +        if (actual == null) {
 +            fail(concat(message, "Identifier is null"));
 +        } else {
 +            if (!UNRESTRICTED.equals(authority)) 
assertAnyTitleEquals(message,                      authority, 
actual.getAuthority());
 +            if (!UNRESTRICTED.equals(codeSpace)) assertEquals 
(concat(message, "Wrong code space"), codeSpace, actual.getCodeSpace());
 +            if (!UNRESTRICTED.equals(version))   assertEquals 
(concat(message, "Wrong version"),    version,   actual.getVersion());
 +            if (!UNRESTRICTED.equals(code))      assertEquals 
(concat(message, "Wrong code"),       code,      actual.getCode());
 +        }
 +    }
 +
 +    /**
 +     * Asserts that all axes in the given coordinate system are pointing 
toward the given directions, in the same order.
 +     *
 +     * @param message  Header of the exception message in case of failure, or 
{@code null} if none.
 +     * @param cs       The coordinate system to test.
 +     * @param expected The expected axis directions.
 +     */
 +    public static void assertAxisDirectionsEqual(String message,
 +            final CoordinateSystem cs, final AxisDirection... expected)
 +    {
 +        assertEquals(concat(message, "Wrong coordinate system dimension."), 
expected.length, cs.getDimension());
 +        message = concat(message, "Wrong axis direction.");
 +        for (int i=0; i<expected.length; i++) {
 +            assertEquals(message, expected[i], cs.getAxis(i).getDirection());
 +        }
 +    }
 +
 +    /**
 +     * Asserts that the given matrix is equals to the expected one, up to the 
given tolerance value.
 +     *
 +     * @param message   Header of the exception message in case of failure, 
or {@code null} if none.
 +     * @param expected  The expected matrix, which may be {@code null}.
 +     * @param actual    The matrix to compare, or {@code null}.
 +     * @param tolerance The tolerance threshold.
 +     */
 +    public static void assertMatrixEquals(final String message, final Matrix 
expected, final Matrix actual, final double tolerance) {
 +        if (isNull(message, expected, actual)) {
 +            return;
 +        }
 +        final int numRow = actual.getNumRow();
 +        final int numCol = actual.getNumCol();
 +        assertEquals("numRow", expected.getNumRow(), numRow);
 +        assertEquals("numCol", expected.getNumCol(), 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("Matrix.getElement(" + j + ", " + i + "): expected " 
+ e + " but got " + a);
 +                }
 +            }
 +        }
 +    }
 +}

Reply via email to