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); + } + } + } + } +}
