This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 9873c5394a0af61c781226d0cec50295dfacb652 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Dec 12 14:44:12 2023 +0100 Do not emit warning for "No spatial or temporal dimension has been found". The CRS of a grid coverage may be an EngineeringCRS, which is fine. --- .../org/apache/sis/coverage/grid/GridGeometry.java | 14 +++- .../sis/metadata/internal/ReferencingServices.java | 35 +++++---- .../apache/sis/metadata/internal/Resources.java | 6 ++ .../sis/metadata/internal/Resources.properties | 1 + .../sis/metadata/internal/Resources_fr.properties | 1 + .../sis/metadata/iso/extent/DefaultExtent.java | 4 +- .../iso/extent/DefaultGeographicBoundingBox.java | 4 +- .../iso/extent/DefaultSpatialTemporalExtent.java | 4 +- .../metadata/iso/extent/DefaultTemporalExtent.java | 4 +- .../metadata/iso/extent/DefaultVerticalExtent.java | 4 +- .../iso/extent/NotSpatioTemporalException.java | 86 ++++++++++++++++++++++ .../sis/metadata/iso/extent/package-info.java | 2 +- .../org/apache/sis/geometry/EnvelopeReducer.java | 2 + .../apache/sis/geometry/WraparoundAdjustment.java | 4 +- .../main/org/apache/sis/referencing/CRS.java | 31 +++++++- .../apache/sis/referencing/internal/Resources.java | 28 +------ .../sis/referencing/internal/Resources.properties | 4 - .../referencing/internal/Resources_fr.properties | 4 - .../referencing/internal/ServicesForMetadata.java | 85 ++++++++++----------- .../internal/ServicesForMetadataTest.java | 30 ++++---- .../apache/sis/storage/base/MetadataBuilder.java | 10 ++- 21 files changed, 241 insertions(+), 122 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java index 464b9644bd..bac7853556 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java @@ -1090,12 +1090,20 @@ public class GridGeometry implements LenientComparable, Serializable { GeographicBoundingBox bbox = geographicBBox; if (bbox == null) { if (getCoordinateReferenceSystem(envelope) != null && !envelope.isAllNaN()) { + DefaultGeographicBoundingBox db; + NilReason reason = null; try { - final DefaultGeographicBoundingBox db = ReferencingServices.getInstance().setBounds(envelope, null, null); + db = ReferencingServices.getInstance().setBounds(envelope, null, null); + } catch (TransformException e) { + db = null; + reason = NilReason.INAPPLICABLE; + } + if (db != null) { db.transitionTo(DefaultGeographicBoundingBox.State.FINAL); bbox = db; - } catch (TransformException e) { - bbox = NilReason.INAPPLICABLE.createNilObject(GeographicBoundingBox.class); + } else { + if (reason == null) reason = NilReason.MISSING; + bbox = reason.createNilObject(GeographicBoundingBox.class); } geographicBBox = bbox; } diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ReferencingServices.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ReferencingServices.java index cc0f7bf69f..ccb68a66a2 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ReferencingServices.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ReferencingServices.java @@ -128,16 +128,21 @@ public class ReferencingServices extends OptionalDependency { * to a geographic CRS (without datum shift if possible). Otherwise, the envelope is assumed already * in a geographic CRS using (<var>longitude</var>, <var>latitude</var>) axis order. * - * <p>If {@code findOpCaller} is non-null, then this method will be executed in optional mode: - * some failures will cause this method to return {@code null} instead of throwing an exception. - * Note that {@link TransformException} may still be thrown but not directly by this method. - * Warning may be logged, but in such case this method presumes that public caller is the named method from - * {@code Envelopes} — typically {@link org.apache.sis.geometry.Envelopes#findOperation(Envelope, Envelope)}.</p> + * <p>If {@code findOpCaller} is non-null, then this method is invoked for computing a <em>hint</em> + * for choosing a coordinate operation between a pair of reference systems. It changes the behavior + * of this methods in two ways:</p> + * + * <ul> + * <li>Some failures will cause this method to return {@code null} instead of throwing an exception. + * Those exception will be logged on the assumption that {@code findOpCaller} is a public method + * of {@code Envelopes}.</li> + * <li>The bounding box may be conservatively expanded to the whole world.</li> + * </ul> * * @param envelope the source envelope. * @param target the target bounding box, or {@code null} for creating it automatically. - * @param findOpCaller non-null for replacing some (not all) exceptions by {@code null} return value. - * @return the bounding box or {@code null} on failure. Never {@code null} if {@code findOpCaller} argument is {@code null}. + * @param findOpCaller non-null for computing a hint rather than an exact bounding box. + * @return the bounding box, or {@code null} on failure (in hint mode) or if no horizontal component was found. * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. * @throws TransformException if the given envelope cannot be transformed. */ @@ -153,10 +158,10 @@ public class ReferencingServices extends OptionalDependency { * * @param envelope the source envelope. * @param target the target vertical extent. - * @throws TransformException if no vertical component can be extracted from the given envelope. + * @return whether the envelope contains a vertical component. * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. */ - public void setBounds(Envelope envelope, DefaultVerticalExtent target) throws TransformException { + public boolean setBounds(Envelope envelope, DefaultVerticalExtent target) { throw moduleNotFound(); } @@ -166,10 +171,10 @@ public class ReferencingServices extends OptionalDependency { * * @param envelope the source envelope. * @param target the target temporal extent. - * @throws TransformException if no temporal component can be extracted from the given envelope. + * @return whether the envelope contains a temporal component. * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. */ - public void setBounds(Envelope envelope, DefaultTemporalExtent target) throws TransformException { + public boolean setBounds(Envelope envelope, DefaultTemporalExtent target) { throw moduleNotFound(); } @@ -189,10 +194,11 @@ public class ReferencingServices extends OptionalDependency { * * @param envelope the source envelope. * @param target the target spatiotemporal extent. - * @throws TransformException if no temporal component can be extracted from the given envelope. + * @return whether the envelope contains a spatial or temporal component. + * @throws TransformException if a coordinate transformation was required and failed. * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. */ - public void setBounds(Envelope envelope, DefaultSpatialTemporalExtent target) throws TransformException { + public boolean setBounds(Envelope envelope, DefaultSpatialTemporalExtent target) throws TransformException { throw moduleNotFound(); } @@ -201,10 +207,11 @@ public class ReferencingServices extends OptionalDependency { * * @param envelope the source envelope. * @param target the target extent. + * @return whether the envelope contains a spatial or temporal component. * @throws TransformException if a coordinate transformation was required and failed. * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. */ - public void addElements(Envelope envelope, DefaultExtent target) throws TransformException { + public boolean addElements(Envelope envelope, DefaultExtent target) throws TransformException { throw moduleNotFound(); } diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java index dba3fb97d4..fcec478484 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.java @@ -78,6 +78,12 @@ public class Resources extends IndexedResourceBundle { */ public static final short ExpectedInterface_2 = 5; + /** + * No {0,choice,0#horizontal|1#vertical|2#temporal|3#spatial or temporal} dimension has been + * found in “{1}”. + */ + public static final short MissingDimension_2 = 10; + /** * Multiline record */ diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.properties b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.properties index 7dcbf33cf8..e930fb1f25 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.properties +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources.properties @@ -24,6 +24,7 @@ ConnectionAlreadyInitialized_1 = Connection to \u201c{0}\u201d database is al ElementAlreadyInitialized_1 = This metadata element is already initialized with value \u201c{0}\u201d. ElementsOmitted_1 = \u2026 {0} elements omitted \u2026 ExpectedInterface_2 = Illegal class `{1}`. Specify the `{0}` interface instead. +MissingDimension_2 = No {0,choice,0#horizontal|1#vertical|2#temporal|3#spatial or temporal} dimension has been found in \u201c{1}\u201d. MultilineRecord = Multiline record SingleNumber = Single number SingleText = Single text diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources_fr.properties b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources_fr.properties index da3f33b5e1..885f3f1868 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources_fr.properties +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Resources_fr.properties @@ -29,6 +29,7 @@ ConnectionAlreadyInitialized_1 = La connexion \u00e0 la base de donn\u00e9es ElementAlreadyInitialized_1 = Cet \u00e9l\u00e9ment de m\u00e9ta-donn\u00e9e est d\u00e9j\u00e0 initialis\u00e9 avec la valeur \u00ab\u202f{0}\u202f\u00bb. ElementsOmitted_1 = \u2026 {0} \u00e9l\u00e9ments omis \u2026 ExpectedInterface_2 = La classe `{1}` est ill\u00e9gale. Sp\u00e9cifiez l\u2019interface `{0}` \u00e0 la place. +MissingDimension_2 = Aucune dimension {0,choice,0#horizontale|1#verticale|2#temporelle|3#spatiale ou temporelle} n\u2019a \u00e9t\u00e9 trouv\u00e9e dans \u00ab\u202f{1}\u202f\u00bb. MultilineRecord = Enregistrement multilignes SingleNumber = Nombre seul SingleText = Texte seul diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java index 2d6dc6eb98..d15364992d 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java @@ -309,7 +309,9 @@ public class DefaultExtent extends ISOMetadata implements Extent { public void addElements(final Envelope envelope) throws TransformException { checkWritePermission(isNonEmpty()); ArgumentChecks.ensureNonNull("envelope", envelope); - ReferencingServices.getInstance().addElements(envelope, this); + if (!ReferencingServices.getInstance().addElements(envelope, this)) { + throw new NotSpatioTemporalException(3, envelope); + } } /** diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java index 7af343ffad..46713f1767 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java @@ -516,7 +516,9 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple public void setBounds(final Envelope envelope) throws TransformException { ArgumentChecks.ensureNonNull("envelope", envelope); checkWritePermission(isNonEmpty()); - ReferencingServices.getInstance().setBounds(envelope, this, null); + if (ReferencingServices.getInstance().setBounds(envelope, this, null) == null) { + throw new NotSpatioTemporalException(0, envelope); + } } /** diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java index 89e5d1154d..286ee8ece0 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java @@ -224,6 +224,8 @@ public class DefaultSpatialTemporalExtent extends DefaultTemporalExtent implemen @Override public void setBounds(final Envelope envelope) throws TransformException { checkWritePermission(valueIfDefined(spatialExtent)); - ReferencingServices.getInstance().setBounds(envelope, this); + if (!ReferencingServices.getInstance().setBounds(envelope, this)) { + throw new NotSpatioTemporalException(3, envelope); + } } } diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java index 5a94df1bb1..1f585c9aab 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java @@ -238,7 +238,9 @@ public class DefaultTemporalExtent extends ISOMetadata implements TemporalExtent */ public void setBounds(final Envelope envelope) throws TransformException { checkWritePermission(extent); - ReferencingServices.getInstance().setBounds(envelope, this); + if (!ReferencingServices.getInstance().setBounds(envelope, this)) { + throw new NotSpatioTemporalException(2, envelope); + } } /** diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java index 801b71b8ba..f4b83c32d0 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java @@ -260,7 +260,9 @@ public class DefaultVerticalExtent extends ISOMetadata implements VerticalExtent */ public void setBounds(final Envelope envelope) throws TransformException { checkWritePermission(value()); - ReferencingServices.getInstance().setBounds(envelope, this); + if (!ReferencingServices.getInstance().setBounds(envelope, this)) { + throw new NotSpatioTemporalException(1, envelope); + } } /** diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/NotSpatioTemporalException.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/NotSpatioTemporalException.java new file mode 100644 index 0000000000..b0cd09874f --- /dev/null +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/NotSpatioTemporalException.java @@ -0,0 +1,86 @@ +/* + * 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.metadata.iso.extent; + +import org.opengis.geometry.Envelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.TransformException; +import org.apache.sis.metadata.internal.Resources; +import org.apache.sis.util.resources.Errors; +import org.apache.sis.util.Workaround; + + +/** + * Thrown when an envelope cannot be transformed to a geographic, vertical or temporal extent. + * This exception occurs when the envelope Coordinate Reference System (CRS) has no spatial or temporal component. + * For example, it may be an engineering CRS. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.5 + * @since 1.5 + */ +public class NotSpatioTemporalException extends TransformException { + /** + * Serial number for inter-operability with different versions. + */ + private static final long serialVersionUID = -6964320493942299039L; + + /** + * Constructs a new exception with no detail message. + */ + public NotSpatioTemporalException() { + } + + /** + * Constructs a new exception with the specified detail message. + * + * @param message the details message, or {@code null} if none. + */ + public NotSpatioTemporalException(final String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * @param message the details message, or {@code null} if none. + * @param cause the cause, or {@code null} if none. + */ + public NotSpatioTemporalException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * Creates an exception with a message for a spatial, vertical or temporal dimension not found. + * + * @param type 0=horizontal, 1=vertical, 2=temporal, 3=spatial or temporal. + * @param envelope the envelope where the dimension was not found. + */ + NotSpatioTemporalException(final int type, final Envelope envelope) { + super(message(type, envelope.getCoordinateReferenceSystem())); + } + + /** + * Work around for RFE #4093999 in Sun's bug database + * ("Relax constraint on placement of this()/super() call in constructors"). + */ + @Workaround(library="JDK", version="1.7") + private static String message(final int type, final CoordinateReferenceSystem crs) { + return (crs != null) ? Resources.format(Resources.Keys.MissingDimension_2, type, crs.getName()) + : Errors.format(Errors.Keys.UnspecifiedCRS); + } +} diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/package-info.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/package-info.java index e00ce97747..f54a6c2304 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/package-info.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/package-info.java @@ -136,7 +136,7 @@ * @author Cédric Briançon (Geomatys) * @author Guilhem Legal (Geomatys) * @author Cullen Rombach (Image Matters) - * @version 1.4 + * @version 1.5 * @since 0.3 */ @XmlSchema(location="https://schemas.isotc211.org/19115/-3/gex/1.0/gex.xsd", diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/EnvelopeReducer.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/EnvelopeReducer.java index 209488de8f..18316ca1d4 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/EnvelopeReducer.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/EnvelopeReducer.java @@ -62,6 +62,8 @@ class EnvelopeReducer { /** * The public method from {@link Envelopes} which is using this envelope reducer. + * Used for logging purposes in case of error during the calculation of the envelope + * to use as a hint for finding an operation between a pair of CRS. */ private final String caller; diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundAdjustment.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundAdjustment.java index cb2554ab3c..154cd20644 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundAdjustment.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundAdjustment.java @@ -63,6 +63,8 @@ public class WraparoundAdjustment { /** * The geographic bounds of {@link #domainOfValidity}, or {@code null} if not applicable. + * This is used for more accurate selection of a coordinate operation between a pair of CRS, + * so it is okay to conservatively use an area covering the whole world. * * @see CRS#findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox) */ @@ -185,7 +187,7 @@ public class WraparoundAdjustment { */ if (!geographicDomainKnown && !Utilities.equalsIgnoreMetadata(source, target)) try { geographicDomainKnown = true; // Shall be set even in case of failure. - geographicDomain = ReferencingServices.getInstance().setBounds(domainOfValidity, null, null); + geographicDomain = ReferencingServices.getInstance().setBounds(domainOfValidity, null, "shift"); } catch (TransformException e) { Logging.ignorableException(Envelopes.LOGGER, WraparoundAdjustment.class, "<init>", e); // No more attempt will be done. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java index 1dad08c7ac..ca0cba5a49 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java @@ -139,7 +139,7 @@ import org.opengis.metadata.extent.GeographicExtent; * * @author Martin Desruisseaux (IRD, Geomatys) * @author Alexis Manin (Geomatys) - * @version 1.4 + * @version 1.5 * @since 0.3 */ public final class CRS extends Static { @@ -1134,6 +1134,32 @@ public final class CRS extends Static { return 0; } + /** + * Returns {@code true} if the given coordinate reference system has an horizontal component. + * The horizontal component may be part of a higher dimensional CRS, either in the form of a + * three-dimensional CRS (with an ellipsoidal height) or a compound CRS. + * + * @param crs the coordinate reference system, or {@code null}. + * @return whether the given CRS has an horizontal component. + * + * @category information + * + * @since 1.5 + */ + public static boolean hasHorizontalComponent(final CoordinateReferenceSystem crs) { + if (horizontalCode(crs) != 0) { + return true; + } + if (crs instanceof CompoundCRS) { + for (CoordinateReferenceSystem c : ((CompoundCRS) crs).getComponents()) { + if (hasHorizontalComponent(c)) { + return true; + } + } + } + return false; + } + /** * Returns the first horizontal coordinate reference system found in the given CRS, or {@code null} if there is * none. If the given CRS is already horizontal according {@link #isHorizontalCRS(CoordinateReferenceSystem)}, @@ -1203,8 +1229,7 @@ public final class CRS extends Static { } } if (crs instanceof CompoundCRS) { - final CompoundCRS cp = (CompoundCRS) crs; - for (final CoordinateReferenceSystem c : cp.getComponents()) { + for (CoordinateReferenceSystem c : ((CompoundCRS) crs).getComponents()) { final SingleCRS candidate = getHorizontalComponent(c); if (candidate != null) { return candidate; diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java index f68672eb9b..7abce1e979 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.java @@ -114,7 +114,7 @@ public class Resources extends IndexedResourceBundle { /** * Cannot linearize the localization grid. */ - public static final short CanNotLinearizeLocalizationGrid = 100; + public static final short CanNotLinearizeLocalizationGrid = 45; /** * Cannot map an axis from the specified coordinate system to the “{0}” direction. @@ -224,7 +224,7 @@ public class Resources extends IndexedResourceBundle { * Definitions from public sources. When a definition corresponds to an EPSG object (ignoring * metadata), the EPSG code is provided as a reference where to find the complete definition. */ - public static final short FallbackAuthorityNotice = 102; + public static final short FallbackAuthorityNotice = 42; /** * There is no local registry for version {1} of “{0}” authority. Fallback on default version @@ -360,11 +360,6 @@ public class Resources extends IndexedResourceBundle { */ public static final short MissingAuthority_1 = 39; - /** - * No horizontal dimension found in “{0}”. - */ - public static final short MissingHorizontalDimension_1 = 40; - /** * Not enough dimension in ‘MathTransform’ input or output coordinates for the interpolation * points. @@ -376,16 +371,6 @@ public class Resources extends IndexedResourceBundle { */ public static final short MissingParameterValues_1 = 74; - /** - * No spatial or temporal dimension found in “{0}” - */ - public static final short MissingSpatioTemporalDimension_1 = 42; - - /** - * No temporal dimension found in “{0}” - */ - public static final short MissingTemporalDimension_1 = 43; - /** * Missing value for “{0}” parameter. */ @@ -396,11 +381,6 @@ public class Resources extends IndexedResourceBundle { */ public static final short MissingValuesInLocalizationGrid = 81; - /** - * No vertical dimension found in “{0}” - */ - public static final short MissingVerticalDimension_1 = 45; - /** * No convergence. */ @@ -495,7 +475,7 @@ public class Resources extends IndexedResourceBundle { /** * Operation “{1}” of class ‘{0}’ has no mathematical transform. */ - public static final short OperationHasNoTransform_2 = 101; + public static final short OperationHasNoTransform_2 = 43; /** * No parameter named “{1}” has been found in “{0}”. @@ -505,7 +485,7 @@ public class Resources extends IndexedResourceBundle { /** * Points are not on a regular grid. */ - public static final short PointsAreNotOnRegularGrid = 99; + public static final short PointsAreNotOnRegularGrid = 40; /** * Recursive call while creating an object of type ‘{0}’ for code “{1}”. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.properties b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.properties index c29b47c3b1..0e27e2af44 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.properties +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources.properties @@ -91,10 +91,6 @@ MismatchedPrimeMeridian_2 = Expected the \u201c{0}\u201d prime meridian MissingAuthority_1 = No authority was specified for code \u201c{0}\u201d. The expected syntax is \u201cAUTHORITY:CODE\u201d. MissingAuthorityCode_1 = Missing or empty \u201cID[\u2026]\u201d element for \u201c{0}\u201d. MissingInterpolationOrdinates = Not enough dimension in \u2018MathTransform\u2019 input or output coordinates for the interpolation points. -MissingHorizontalDimension_1 = No horizontal dimension found in \u201c{0}\u201d. -MissingVerticalDimension_1 = No vertical dimension found in \u201c{0}\u201d -MissingTemporalDimension_1 = No temporal dimension found in \u201c{0}\u201d -MissingSpatioTemporalDimension_1 = No spatial or temporal dimension found in \u201c{0}\u201d MissingParameterValues_1 = Missing parameter values for \u201c{0}\u201d coordinate operation. MissingValueForParameter_1 = Missing value for \u201c{0}\u201d parameter. MissingValuesInLocalizationGrid = The localization grid still have some undefined source or target coordinates. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources_fr.properties b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources_fr.properties index 648456144a..ef2324ec12 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources_fr.properties +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Resources_fr.properties @@ -96,10 +96,6 @@ MismatchedPrimeMeridian_2 = Le m\u00e9ridien d\u2019origine \u00ab\u202f MissingAuthority_1 = Aucune autorit\u00e9 n\u2019a \u00e9t\u00e9 sp\u00e9cifi\u00e9e pour le code \u00ab\u202f{0}\u202f\u00bb. Le format attendu est \u00ab\u202fAUTORIT\u00c9:CODE\u202f\u00bb. MissingAuthorityCode_1 = L\u2019\u00e9l\u00e9ment \u00ab\u202fID[\u2026]\u202f\u00bb est manquant ou vide pour \u00ab\u202f{0}\u202f\u00bb. MissingInterpolationOrdinates = La dimension des coordonn\u00e9es en entr\u00e9 ou en sortie du \u2018MathTransform\u2019 n\u2019est pas suffisante pour contenir les points d\u2019interpolation. -MissingHorizontalDimension_1 = Aucune dimension horizontale n\u2019a \u00e9t\u00e9 trouv\u00e9e dans \u00ab\u202f{0}\u202f\u00bb. -MissingVerticalDimension_1 = Aucune dimension verticale n\u2019a \u00e9t\u00e9 trouv\u00e9e dans \u00ab\u202f{0}\u202f\u00bb. -MissingTemporalDimension_1 = Aucune dimension temporelle n\u2019a \u00e9t\u00e9 trouv\u00e9e dans \u00ab\u202f{0}\u202f\u00bb. -MissingSpatioTemporalDimension_1 = Aucune dimension spatiale ou temporelle n\u2019a \u00e9t\u00e9 trouv\u00e9e dans \u00ab\u202f{0}\u202f\u00bb. MissingParameterValues_1 = Il manque les valeurs des param\u00e8tres pour l\u2019op\u00e9ration \u00ab\u202f{0}\u202f\u00bb. MissingValueForParameter_1 = Aucune valeur n\u2019a \u00e9t\u00e9 d\u00e9finie pour le param\u00e8tre \u00ab\u202f{0}\u202f\u00bb. MissingValuesInLocalizationGrid = Il manque encore des coordonn\u00e9es sources ou destinations dans la grille de localisation. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java index 1cbe288787..5e65868b06 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java @@ -59,15 +59,14 @@ import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent; import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent; import org.apache.sis.metadata.iso.extent.DefaultSpatialTemporalExtent; import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox; +import org.apache.sis.metadata.internal.ReferencingServices; import org.apache.sis.measure.Latitude; import org.apache.sis.measure.Longitude; -import org.apache.sis.metadata.internal.ReferencingServices; import org.apache.sis.system.Modules; import org.apache.sis.util.Exceptions; import org.apache.sis.util.Utilities; import org.apache.sis.util.internal.Constants; import org.apache.sis.util.resources.Vocabulary; -import org.apache.sis.util.resources.Errors; import org.apache.sis.util.logging.Logging; // Specific to the geoapi-3.1 and geoapi-4.0 branches: @@ -100,34 +99,20 @@ public final class ServicesForMetadata extends ReferencingServices { //// //// /////////////////////////////////////////////////////////////////////////////////////// - /** - * Creates an exception message for a spatial, vertical or temporal dimension not found. - * The given key must be one of {@code Resources.Keys} constants. - */ - private static String dimensionNotFound(final short resourceKey, final CoordinateReferenceSystem crs) { - if (crs == null) { - return Errors.format(Errors.Keys.UnspecifiedCRS); - } else { - return Resources.format(resourceKey, crs.getName()); - } - } - /** * Implementation of the public {@code setBounds(…, DefaultGeographicBoundingBox, …)} methods for * the horizontal extent. If the {@code crs} argument is null, then it is caller's responsibility * to ensure that the given envelope is two-dimensional. * - * <p>If {@code findOpCaller} is non-null, then this method will be executed in optional mode: - * some failures will cause this method to return {@code null} instead of throwing an exception. - * Note that {@link TransformException} may still be thrown but not directly by this method. - * Warning may be logged, but in such case this method presumes that public caller is the named - * method from {@link Envelopes} — typically {@link Envelopes#findOperation(Envelope, Envelope)}.</p> + * <p>If {@code findOpCaller} is non-null, then this method is assumed to be invoked by something + * equivalent to {@link Envelopes#findOperation(Envelope, Envelope)} for the purpose of computing + * a <em>hint</em>, not a bounding box that needs to be exact.</p> * * @param envelope the source envelope. * @param target the target bounding box, or {@code null} for creating it automatically. * @param crs the envelope CRS, or {@code null} if unknown. * @param normalizedCRS the horizontal component of the given CRS, or null if the {@code crs} argument is null. - * @param findOpCaller non-null for replacing some (not all) exceptions by {@code null} return value. + * @param findOpCaller non-null for computing a hint rather than an exact bounding box. * @return the bounding box or {@code null} on failure. Never {@code null} if {@code findOpCaller} argument is {@code null}. * @throws TransformException if the given envelope cannot be transformed. */ @@ -240,15 +225,15 @@ public final class ServicesForMetadata extends ReferencingServices { /** * Sets a geographic bounding box from the specified envelope. * If the envelope has no CRS, then (<var>longitude</var>, <var>latitude</var>) axis order is assumed. - * If the envelope CRS is not geographic, then the envelope will be transformed to a geographic CRS. - * If {@code findOpCaller} is {@code true}, then some failures will cause this method to return {@code null} - * instead of throwing an exception, and warning may be logged with assumption that caller is the named - * method from {@link Envelopes} — typically {@link Envelopes#findOperation(Envelope, Envelope)}. + * + * <p>If {@code findOpCaller} is {@code true}, then the envelope will be computed in <em>hint</em> mode: + * some exception may be logged instead of thrown, and the envelope may be expanded to the whole world. + * This mode is for {@link Envelopes#findOperation(Envelope, Envelope)} usage of equivalent functions.</p> * * @param envelope the source envelope. * @param target the target bounding box, or {@code null} for creating it automatically. - * @param findOpCaller non-null for replacing some (not all) exceptions by {@code null} return value. - * @return the bounding box or {@code null} on failure. Never {@code null} if {@code findOpCaller} argument is {@code null}. + * @param findOpCaller non-null for computing a hint rather than an exact bounding box. + * @return the bounding box, or {@code null} on failure (in hint mode) or if no horizontal component was found. * @throws TransformException if the given envelope cannot be transformed. */ @Override @@ -261,8 +246,7 @@ public final class ServicesForMetadata extends ReferencingServices { if (crs != null) { normalizedCRS = CommonCRS.defaultGeographic(); } else if (envelope.getDimension() != 2) { - if (findOpCaller != null) return null; - throw new TransformException(dimensionNotFound(Resources.Keys.MissingHorizontalDimension_1, crs)); + return null; } } return setGeographicExtent(envelope, target, crs, normalizedCRS, findOpCaller); @@ -274,16 +258,17 @@ public final class ServicesForMetadata extends ReferencingServices { * * @param envelope the source envelope. * @param target the target vertical extent where to store envelope information. - * @throws TransformException if no vertical component can be extracted from the given envelope. + * @return whether the envelope contains a vertical component. */ @Override - public void setBounds(final Envelope envelope, final DefaultVerticalExtent target) throws TransformException { + public boolean setBounds(final Envelope envelope, final DefaultVerticalExtent target) { final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem(); final VerticalCRS verticalCRS = CRS.getVerticalComponent(crs, true); if (verticalCRS == null && envelope.getDimension() != 1) { - throw new TransformException(dimensionNotFound(Resources.Keys.MissingVerticalDimension_1, crs)); + return false; } setVerticalExtent(envelope, target, crs, verticalCRS); + return true; } /** @@ -292,16 +277,17 @@ public final class ServicesForMetadata extends ReferencingServices { * * @param envelope the source envelope. * @param target the target temporal extent where to store envelope information. - * @throws TransformException if no temporal component can be extracted from the given envelope. + * @return whether the envelope contains a temporal component. */ @Override - public void setBounds(final Envelope envelope, final DefaultTemporalExtent target) throws TransformException { + public boolean setBounds(final Envelope envelope, final DefaultTemporalExtent target) { final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem(); final TemporalAccessor accessor = TemporalAccessor.of(crs, 0); if (accessor == null) { // Mandatory for the conversion from numbers to dates. - throw new TransformException(dimensionNotFound(Resources.Keys.MissingTemporalDimension_1, crs)); + return false; } accessor.setTemporalExtent(envelope, target); + return true; } /** @@ -311,16 +297,17 @@ public final class ServicesForMetadata extends ReferencingServices { * * @param envelope the source envelope. * @param target the target spatiotemporal extent where to store envelope information. - * @throws TransformException if no temporal component can be extracted from the given envelope. + * @return whether the envelope contains a spatial or temporal component. + * @throws TransformException if a coordinate transformation was required and failed. */ @Override - public void setBounds(final Envelope envelope, final DefaultSpatialTemporalExtent target) throws TransformException { + public boolean setBounds(final Envelope envelope, final DefaultSpatialTemporalExtent target) throws TransformException { final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem(); final SingleCRS horizontalCRS = CRS.getHorizontalComponent(crs); final VerticalCRS verticalCRS = CRS.getVerticalComponent(crs, true); final TemporalAccessor accessor = TemporalAccessor.of(crs, 0); if (horizontalCRS == null && verticalCRS == null && accessor == null) { - throw new TransformException(dimensionNotFound(Resources.Keys.MissingSpatioTemporalDimension_1, crs)); + return false; } /* * Try to set the geographic bounding box first, because this operation may fail with a @@ -371,6 +358,7 @@ public final class ServicesForMetadata extends ReferencingServices { } else { target.setExtent(null); } + return true; } /** @@ -378,32 +366,37 @@ public final class ServicesForMetadata extends ReferencingServices { * * @param envelope the source envelope. * @param target the target extent where to store envelope information. + * @return whether the envelope contains a spatial or temporal component. * @throws TransformException if a coordinate transformation was required and failed. * @throws UnsupportedOperationException if this method requires an Apache SIS module * which has been found on the module path. */ @Override - public void addElements(final Envelope envelope, final DefaultExtent target) throws TransformException { + public boolean addElements(final Envelope envelope, final DefaultExtent target) throws TransformException { + boolean found = false; final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem(); - final SingleCRS horizontalCRS = CRS.getHorizontalComponent(crs); - final VerticalCRS verticalCRS = CRS.getVerticalComponent(crs, true); - final TemporalAccessor accessor = TemporalAccessor.of(crs, 0); - if (horizontalCRS == null && verticalCRS == null && accessor == null) { - throw new TransformException(dimensionNotFound(Resources.Keys.MissingSpatioTemporalDimension_1, crs)); - } - if (horizontalCRS != null) { - target.getGeographicElements().add(setBounds(envelope, null, null)); + if (CRS.hasHorizontalComponent(crs)) { + DefaultGeographicBoundingBox horizontal = setBounds(envelope, null, null); + if (horizontal != null) { + target.getGeographicElements().add(horizontal); + found = true; + } } + final VerticalCRS verticalCRS = CRS.getVerticalComponent(crs, true); if (verticalCRS != null) { final DefaultVerticalExtent extent = new DefaultVerticalExtent(); setVerticalExtent(envelope, extent, crs, verticalCRS); target.getVerticalElements().add(extent); + found = true; } + final TemporalAccessor accessor = TemporalAccessor.of(crs, 0); if (accessor != null) { final DefaultTemporalExtent extent = new DefaultTemporalExtent(); accessor.setTemporalExtent(envelope, extent); target.getTemporalElements().add(extent); + found = true; } + return found; } /** diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/ServicesForMetadataTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/ServicesForMetadataTest.java index be7169c9bf..4440d0f793 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/ServicesForMetadataTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/ServicesForMetadataTest.java @@ -31,7 +31,7 @@ import org.apache.sis.referencing.CommonCRS; // Test dependencies import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import org.apache.sis.test.DependsOnMethod; import org.apache.sis.test.DependsOn; import org.apache.sis.test.TestCase; @@ -87,10 +87,10 @@ public final class ServicesForMetadataTest extends TestCase { * Verifies the values of the given geographic bounding box. */ private static void verifySpatialExtent(final GeographicBoundingBox box) { - assertEquals(-40, box.getWestBoundLongitude(), STRICT); - assertEquals( 60, box.getEastBoundLongitude(), STRICT); - assertEquals(-20, box.getSouthBoundLatitude(), STRICT); - assertEquals( 30, box.getNorthBoundLatitude(), STRICT); + assertEquals(-40, box.getWestBoundLongitude()); + assertEquals( 60, box.getEastBoundLongitude()); + assertEquals(-20, box.getSouthBoundLatitude()); + assertEquals( 30, box.getNorthBoundLatitude()); assertEquals(Boolean.TRUE, box.getInclusion()); } @@ -98,8 +98,8 @@ public final class ServicesForMetadataTest extends TestCase { * Verifies the values of the given vertical extent. */ private static void verifyVerticalExtent(final CommonCRS.Vertical expectedCRS, final VerticalExtent extent) { - assertEquals(-10, extent.getMinimumValue(), STRICT); - assertEquals( 70, extent.getMaximumValue(), STRICT); + assertEquals(-10, extent.getMinimumValue()); + assertEquals( 70, extent.getMaximumValue()); assertEqualsIgnoreMetadata(expectedCRS.crs(), extent.getVerticalCRS()); } @@ -181,14 +181,14 @@ public final class ServicesForMetadataTest extends TestCase { final GeneralEnvelope envelope = createEnvelope(HardCodedCRS.WGS84); envelope.setRange(0, 170, 195); box.setBounds(envelope); - assertEquals( 170, box.getWestBoundLongitude(), STRICT); - assertEquals(-165, box.getEastBoundLongitude(), STRICT); + assertEquals( 170, box.getWestBoundLongitude()); + assertEquals(-165, box.getEastBoundLongitude()); envelope.setRange(0, 0, 360); box.setBounds(envelope); - assertEquals(-180, box.getWestBoundLongitude(), STRICT); - assertEquals(+180, box.getEastBoundLongitude(), STRICT); - assertEquals( -20, box.getSouthBoundLatitude(), STRICT); - assertEquals( 30, box.getNorthBoundLatitude(), STRICT); + assertEquals(-180, box.getWestBoundLongitude()); + assertEquals(+180, box.getEastBoundLongitude()); + assertEquals( -20, box.getSouthBoundLatitude()); + assertEquals( 30, box.getNorthBoundLatitude()); assertEquals(Boolean.TRUE, box.getInclusion()); } @@ -221,7 +221,7 @@ public final class ServicesForMetadataTest extends TestCase { e1.setBounds(t1, t3); e2.setBounds(t2, t4); e1.intersect(e2); - assertEquals("startTime", t2, e1.getStartTime()); - assertEquals("endTime", t3, e1.getEndTime()); + assertEquals(t2, e1.getStartTime(), "startTime"); + assertEquals(t3, e1.getEndTime(), "endTime"); } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java index 2ffaaa2e51..24953fbd3a 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java @@ -30,6 +30,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; +import java.util.logging.Level; import java.net.URI; import java.nio.charset.Charset; import javax.measure.Unit; @@ -1884,9 +1885,14 @@ parse: for (int i = 0; i < length;) { if (!(envelope instanceof AbstractEnvelope && ((AbstractEnvelope) envelope).isAllNaN())) { if (crs != null) try { extent().addElements(envelope); - } catch (TransformException | UnsupportedOperationException e) { + } catch (TransformException e) { + final boolean ignorable = (e instanceof NotSpatioTemporalException); if (listeners != null) { - listeners.warning(e); + if (ignorable) { + listeners.warning(Level.FINE, null, e); + } else { + listeners.warning(e); + } } else { Logging.recoverableException(StoreUtilities.LOGGER, null, null, e); }