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;

Reply via email to