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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new 0173414d34 `Extents.getVerticalRange(…)` may throw an exception when a value is NaN. 0173414d34 is described below commit 0173414d344b26bad49f4984ec03637a4313267f Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Dec 20 18:49:05 2024 +0100 `Extents.getVerticalRange(…)` may throw an exception when a value is NaN. --- .../apache/sis/metadata/iso/extent/Extents.java | 5 +- .../main/org/apache/sis/io/wkt/Formatter.java | 56 ++++++++++++++++------ .../sis/gui/metadata/IdentificationInfo.java | 14 ++++-- .../org/apache/sis/gui/metadata/MetadataTree.java | 15 +++--- .../sis/gui/metadata/StandardMetadataTree.java | 8 ++-- .../org/apache/sis/gui/metadata/package-info.java | 2 +- 6 files changed, 67 insertions(+), 33 deletions(-) diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java index 704c490bcc..50475c36c8 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java @@ -411,6 +411,7 @@ public final class Extents extends Static { * * @param extent the extent to convert to a vertical measurement range, or {@code null}. * @return a vertical measurement range created from the given extent, or {@code null} if none. + * @throws InvalidMetadataException if a vertical range contains a {@link Double#NaN} value. * * @since 0.4 */ @@ -418,7 +419,7 @@ public final class Extents extends Static { public static MeasurementRange<Double> getVerticalRange(final Extent extent) { MeasurementRange<Double> range = null; RealizationMethod selectedMethod = null; - if (extent != null) { + if (extent != null) try { for (final VerticalExtent element : nonNull(extent.getVerticalElements())) { double min = element.getMinimumValue(); double max = element.getMaximumValue(); @@ -477,6 +478,8 @@ public final class Extents extends Static { range = MeasurementRange.create(min, true, max, true, unit); selectedMethod = method; } + } catch (IllegalArgumentException e) { + throw new InvalidMetadataException(e.toString(), e); } return range; } diff --git 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 index 42e99bd399..25629c7250 100644 --- 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 @@ -75,6 +75,7 @@ import org.apache.sis.util.privy.Constants; import org.apache.sis.temporal.TemporalDate; import org.apache.sis.temporal.LenientDateFormat; import org.apache.sis.system.Configuration; +import org.apache.sis.metadata.InvalidMetadataException; import org.apache.sis.metadata.simple.SimpleExtent; import org.apache.sis.metadata.iso.extent.Extents; import org.apache.sis.metadata.iso.citation.Citations; @@ -923,9 +924,16 @@ public class Formatter implements Localized { appendOnNewLine(WKTKeywords.Scope, scope, ElementKind.SCOPE); } if (area != null && !(area instanceof NilObject)) { + GeographicBoundingBox bbox; + try { + bbox = Extents.getGeographicBoundingBox(area); + } catch (InvalidMetadataException e) { + warning(e, WKTKeywords.BBox, WKTKeywords.Usage); + bbox = null; + } appendOnNewLine(WKTKeywords.Area, area.getDescription(), ElementKind.EXTENT); - append(Extents.getGeographicBoundingBox(area), BBOX_ACCURACY); - appendVerticalExtent(Extents.getVerticalRange(area)); + append(bbox, BBOX_ACCURACY); + appendVerticalExtent(area); appendTemporalExtent(area); } } @@ -962,7 +970,7 @@ public class Formatter implements Localized { } /** - * Appends the given vertical extent, if non-null. + * Appends the vertical of the given area. * This method chooses an accuracy from the vertical span. * Examples: * @@ -974,7 +982,14 @@ public class Formatter implements Localized { * Note that according ISO 19162, heights are positive toward up and relative to an unspecified mean sea level. * It is caller's responsibility to ensure that the given range complies with that specification as much as possible. */ - private void appendVerticalExtent(final MeasurementRange<Double> range) { + private void appendVerticalExtent(final Extent area) { + final MeasurementRange<Double> range; + try { + range = Extents.getVerticalRange(area); + } catch (InvalidMetadataException e) { + warning(e, WKTKeywords.VerticalExtent, WKTKeywords.Usage); + return; + } if (range != null) { final double min = range.getMinDouble(); final double max = range.getMaxDouble(); @@ -1659,7 +1674,7 @@ public class Formatter implements Localized { } else if (value instanceof GeographicBoundingBox) { append((GeographicBoundingBox) value, BBOX_ACCURACY); } else if (value instanceof VerticalExtent) { - appendVerticalExtent(Extents.getVerticalRange(new SimpleExtent(null, (VerticalExtent) value, null))); + appendVerticalExtent(new SimpleExtent(null, (VerticalExtent) value, null)); } else if (value instanceof TemporalExtent) { appendTemporalExtent(new SimpleExtent(null, null, (TemporalExtent) value)); } else if (value instanceof DirectPosition) { @@ -1833,16 +1848,6 @@ public class Formatter implements Localized { */ } - /** - * Returns the object where to store warnings. - */ - private Warnings warnings() { - if (warnings == null) { - warnings = new Warnings(errorLocale, false, Map.of()); - } - return warnings; - } - /** * Marks the current WKT representation of the given object as not strictly compliant with the WKT specification. * This method can be invoked by implementations of {@link FormattableObject#formatTo(Formatter)} when the object @@ -1901,6 +1906,27 @@ public class Formatter implements Localized { return Classes.getShortName(unformattable); } + /** + * Adds a warning for for an exception that occurred while fetching an optional property. + * + * @param e the exception that occurred. + * @param element WKT keyword of the element where the exception occurred. + * @param parent WKT keyword of the parent element. + */ + private void warning(final Exception e, final String element, final String parent) { + warnings().add(null, e, new String[] {element, parent}); + } + + /** + * Returns the object where to store warnings. + */ + private Warnings warnings() { + if (warnings == null) { + warnings = new Warnings(errorLocale, false, Map.of()); + } + return warnings; + } + /** * Returns the warnings, or {@code null} if none. */ diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java index e19547f7da..f3d7f62a5e 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java @@ -42,6 +42,7 @@ import org.opengis.metadata.extent.GeographicDescription; import org.opengis.metadata.extent.GeographicExtent; import org.opengis.metadata.identification.Identification; import org.opengis.metadata.distribution.Format; +import org.apache.sis.metadata.InvalidMetadataException; import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.metadata.iso.extent.Extents; import org.apache.sis.referencing.IdentifiedObjects; @@ -56,9 +57,11 @@ import org.apache.sis.storage.Resource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.util.CharSequences; import org.apache.sis.util.Workaround; +import org.apache.sis.util.logging.Logging; import org.apache.sis.util.collection.BackingStoreException; import org.apache.sis.util.resources.Vocabulary; import static org.apache.sis.util.privy.CollectionsExt.nonNull; +import static org.apache.sis.gui.internal.LogHandler.LOGGER; // Specific to the geoapi-4.0 branch: import org.opengis.util.InternationalString; @@ -388,8 +391,13 @@ final class IdentificationInfo extends Section<Identification> { isWorld = drawOnMap((GeographicBoundingBox) ge); } } - final MeasurementRange<Double> v = Extents.getVerticalRange(extent); - if (v != null) heights = (heights != null) ? heights.union(v) : v; + try { + final MeasurementRange<Double> v = Extents.getVerticalRange(extent); + if (v != null) heights = (heights != null) ? heights.union(v) : v; + } catch (InvalidMetadataException e) { + // `MetadataSummary` is (indirectly) the public caller of this method. + Logging.recoverableException(LOGGER, MetadataSummary.class, "setMetadata", e); + } final Range<Date> t = Extents.getTimeRange(extent); if (t != null) timeRange = (timeRange != null) ? timeRange.union(t) : t; } @@ -420,7 +428,7 @@ final class IdentificationInfo extends Section<Identification> { final Double min = heights.getMinValue(); final Double max = heights.getMaxValue(); if (min != null || max != null) { - StringBuffer b = new StringBuffer(20); + final var b = new StringBuffer(20); if (min != null && max != null && !min.equals(max)) { owner.formats.formatPair(min, " … ", max, b); } else { diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java index badcf6e190..6b1481a41d 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java @@ -51,8 +51,6 @@ import org.apache.sis.gui.internal.ExceptionReporter; import org.apache.sis.util.collection.TreeTable; import org.apache.sis.util.collection.TableColumn; import org.apache.sis.util.resources.Vocabulary; -import org.apache.sis.util.logging.Logging; -import static org.apache.sis.gui.internal.LogHandler.LOGGER; /** @@ -261,7 +259,7 @@ check: if (data != null) { private static void applyChange(final ObservableValue<? extends TreeTable> property, final TreeTable oldValue, final TreeTable newValue) { - final MetadataTree s = (MetadataTree) ((ContentProperty) property).getBean(); + final var s = (MetadataTree) ((ContentProperty) property).getBean(); if (s.propertyViewer != null) { s.propertyViewer.clear(); } @@ -335,7 +333,7 @@ check: if (data != null) { final CharSequence value = getValue(cell, TableColumn.NAME); final String text; if (value instanceof InternationalString) { - final MetadataTree view = (MetadataTree) cell.getTreeTableView(); + final var view = (MetadataTree) cell.getTreeTableView(); text = ((InternationalString) value).toString(view.getLocale()); } else { text = (value != null) ? value.toString() : null; @@ -363,21 +361,20 @@ check: if (data != null) { */ @Override public ObservableValue<Object> call(final CellDataFeatures<TreeTable.Node, Object> cell) { - final MetadataTree view = (MetadataTree) cell.getTreeTableView(); + final var view = (MetadataTree) cell.getTreeTableView(); Object value = getValue(cell, view.valueSourceColumn); if (value instanceof IdentifiedObject) { value = IdentifiedObjects.getDisplayName((IdentifiedObject) value, getLocale()); } try { clear(); - final StringBuilder buffer = (StringBuilder) out; + final var buffer = (StringBuilder) out; buffer.setLength(0); appendValue(value); flush(); value = buffer.toString(); } catch (IOException e) { // Should never happen because we append in a StringBuilder. - Logging.unexpectedException(LOGGER, Formatter.class, "call", e); - // Leave `value` as-is. It will be formatted using `Object.toString()`. + throw new AssertionError(e); } return new ReadOnlyObjectWrapper<>(value); } @@ -401,7 +398,7 @@ check: if (data != null) { * Creates a new row for the given tree table. */ Row(final TreeTableView<TreeTable.Node> owner) { - final MetadataTree md = (MetadataTree) owner; + final var md = (MetadataTree) owner; final Resources localized = Resources.forLocale(md.getLocale()); view = new MenuItem(localized.getString(Resources.Keys.View)); copy = new MenuItem(localized.getString(Resources.Keys.Copy)); diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java index 40da2e1081..fb28e823ac 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java @@ -130,7 +130,7 @@ public class StandardMetadataTree extends MetadataTree { */ Row(final TreeTableView<TreeTable.Node> view) { super(view); - final StandardMetadataTree md = (StandardMetadataTree) view; + final var md = (StandardMetadataTree) view; final Resources localized = Resources.forLocale(md.getLocale()); copyAsXML = new MenuItem(); copyAsWKT = new MenuItem("WKT — Well Known Text"); @@ -186,17 +186,17 @@ public class StandardMetadataTree extends MetadataTree { super.handle(event); } else { final Object source = event.getSource(); - final ClipboardContent content = new ClipboardContent(); + final var content = new ClipboardContent(); final String text; try { if (source == copyAsWKT) { // Well Known Text. - final WKTFormat f = new WKTFormat(); + final var f = new WKTFormat(); text = f.format(obj); } else if (source == copyAsXML) { // GML or ISO 19115-3:2016. text = XML.marshal(obj); content.put(DataFormats.XML, text); } else if (source == copyAsLegacy) { // ISO 19139:2007. - final StringWriter output = new StringWriter(); + final var output = new StringWriter(); XML.marshal(obj, new StreamResult(output), Map.of( XML.METADATA_VERSION, LegacyNamespaces.VERSION_2007)); text = output.toString(); diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/package-info.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/package-info.java index 3e4d1644cb..d532c789fc 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/package-info.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/package-info.java @@ -23,7 +23,7 @@ * @author Smaniotto Enzo (GSoC) * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.4 + * @version 1.5 * @since 1.1 */ package org.apache.sis.gui.metadata;