This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 35210bcf13f913af6e829823496cb49d7c3eaa09 Author: Martin Desruisseaux <[email protected]> AuthorDate: Sat May 2 13:52:28 2026 +0200 Closer association of the resource identifier to the grid CRS of that resource. This is a complement of previous commit for ensuring that the GUI application distinguishes the engineering CRSs of unrelated resources. --- .../apache/sis/gui/coverage/CoverageCanvas.java | 40 +++++++++++++++++----- .../apache/sis/gui/coverage/CoverageControls.java | 2 +- .../apache/sis/gui/coverage/CoverageExplorer.java | 16 ++------- .../org/apache/sis/gui/coverage/GridControls.java | 6 ++-- .../main/org/apache/sis/gui/coverage/GridView.java | 27 ++++++++++----- .../org/apache/sis/gui/coverage/ImageRequest.java | 28 ++++++++++++++- .../sis/gui/coverage/StyledRenderingData.java | 6 ++++ .../apache/sis/gui/coverage/ViewAndControls.java | 3 +- .../gui/referencing/RecentReferenceSystems.java | 12 +++---- 9 files changed, 99 insertions(+), 41 deletions(-) diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java index 3571b97a07..e1ce2e3f95 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java @@ -58,11 +58,11 @@ import javax.measure.Quantity; import javax.measure.quantity.Length; import org.opengis.geometry.Envelope; import org.opengis.geometry.DirectPosition; +import org.opengis.metadata.Identifier; import org.opengis.util.FactoryException; import org.opengis.referencing.operation.TransformException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.apache.sis.referencing.CommonCRS; -import org.apache.sis.referencing.ImmutableIdentifier; import org.apache.sis.referencing.operation.transform.MathTransforms; import org.apache.sis.referencing.operation.transform.LinearTransform; import org.apache.sis.referencing.operation.matrix.AffineTransforms2D; @@ -676,6 +676,9 @@ public class CoverageCanvas extends MapCanvasAWT { }); } else { BackgroundThreads.execute(new Task<GridGeometry>() { + /** Name of the grid <abbr>CRS</abbr>, derived from the resource identifier. */ + private Identifier gridCrsName; + /** Information about all bands. */ private List<SampleDimension> ranges; @@ -693,13 +696,12 @@ public class CoverageCanvas extends MapCanvasAWT { domain = coverage.getGridGeometry(); ranges = coverage.getSampleDimensions(); scales = null; - } else try { + } else { domain = resource.getGridGeometry(); ranges = resource.getSampleDimensions(); scales = Containers.peekFirst(resource.getAvailableResolutions()); - } catch (BackingStoreException e) { - throw e.unwrapOrRethrow(DataStoreException.class); } + gridCrsName = ImageRequest.gridCrsName(resource, domain); if (domain != null) { /* * The domain should never be null and should always be complete (including envelope). @@ -742,6 +744,8 @@ public class CoverageCanvas extends MapCanvasAWT { } } } + } catch (BackingStoreException e) { + throw e.unwrapOrRethrow(DataStoreException.class); } finally { LogHandler.loadingStop(id); } @@ -755,7 +759,7 @@ public class CoverageCanvas extends MapCanvasAWT { @Override protected void succeeded() { runAfterRendering(() -> { try { - setNewSource(getValue(), ranges, visibleArea); + setNewSource(gridCrsName, getValue(), ranges, visibleArea); requestRepaint(); // Cause `Worker` class to be executed. } catch (RuntimeException ex) { // Mostly for `BackingStoreException`. clear(); @@ -810,14 +814,20 @@ public class CoverageCanvas extends MapCanvasAWT { * <p>All arguments can be {@code null} for clearing the canvas. * This method is invoked in JavaFX thread.</p> * + * @param gridCrsName name of the grid <abbr>CRS</abbr>, derived from the resource identifier. * @param domain the multi-dimensional grid geometry, or {@code null} if there is no data. * @param ranges descriptions of bands, or {@code null} if there is no data. * @param visibleArea initial "objective to display" transform to use, or {@code null} for automatic. */ - private void setNewSource(GridGeometry domain, final List<SampleDimension> ranges, final GridGeometry visibleArea) { + private void setNewSource(final Identifier gridCrsName, + GridGeometry domain, + final List<SampleDimension> ranges, + final GridGeometry visibleArea) + { if (TRACE) { trace("setNewSource(…): the new domain of data is:%n\t%s", domain); } + data.gridCrsName = null; clearRenderedImage(); data.clear(); /* @@ -855,20 +865,32 @@ public class CoverageCanvas extends MapCanvasAWT { if (domain.isDefined(GridGeometry.ENVELOPE)) { bounds = domain.getEnvelope(); if (bounds.getCoordinateReferenceSystem() == null) try { - final var name = new ImmutableIdentifier(null, null, "Cell indices"); final var copy = new GeneralEnvelope(bounds); - copy.setCoordinateReferenceSystem(domain.createGridCRS(name, PixelInCell.CELL_CORNER)); + copy.setCoordinateReferenceSystem(domain.createGridCRS(gridCrsName, PixelInCell.CELL_CORNER)); bounds = copy; } catch (FactoryException e) { unexpectedException(e); } } } + data.gridCrsName = gridCrsName; data.setImageSpace(domain, ranges, xyDimensions); initialize(visibleArea); setObjectiveBounds(bounds); } + /** + * Return a name of the grid <abbr>CRS</abbr>, derived from the resource identifier. + * This method never return {@code null}. + */ + final Identifier gridCrsName() { + Identifier name = data.gridCrsName; + if (name == null) { + name = CommonCRS.Engineering.GRID.datum().getName(); + } + return name; + } + /** * Clears all information that are derived from the raw image projected to objective CRS. * In current version this is only isolines. @@ -1478,7 +1500,7 @@ public class CoverageCanvas extends MapCanvasAWT { } finally { isCoverageAdjusting = false; } - setNewSource(null, null, null); + setNewSource(null, null, null, null); super.clear(); } diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java index 1a20a81632..bdb95744bb 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java @@ -183,7 +183,7 @@ final class CoverageControls extends ViewAndControls { final int visibleBand = 0; // TODO: provide a selector for the band to show. items.setAll(coverage.getSampleDimensions().get(visibleBand).getCategories()); } - owner.notifyDataChanged(resource, coverage); + owner.notifyDataChanged(view.gridCrsName(), resource, coverage); } /** diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java index f400d012e8..57a02f40cd 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java @@ -33,20 +33,17 @@ import javafx.scene.layout.Region; import javafx.event.ActionEvent; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; -import org.apache.sis.util.logging.Logging; -import org.apache.sis.storage.DataStoreException; +import org.opengis.metadata.Identifier; import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.portrayal.RenderException; import org.apache.sis.gui.Widget; import org.apache.sis.gui.internal.FontGIS; -import org.apache.sis.gui.internal.DataStoreOpener; import org.apache.sis.gui.internal.Resources; import org.apache.sis.gui.internal.ToolbarButton; import org.apache.sis.gui.internal.NonNullObjectProperty; import org.apache.sis.gui.internal.PrivateAccess; import org.apache.sis.gui.internal.BackgroundThreads; -import static org.apache.sis.gui.internal.LogHandler.LOGGER; import org.apache.sis.gui.referencing.RecentReferenceSystems; import org.apache.sis.gui.dataset.WindowHandler; import org.apache.sis.gui.map.StatusBar; @@ -610,20 +607,13 @@ public class CoverageExplorer extends Widget { * {@link #coverageProperty}. In the latter case, the {@code resource} and {@code coverage} arguments * given to this method may be the value that the properties already have.</p> * + * @param name an identifier for the grid <abbr>CRS</abbr>. Can be null only if {@code coverage} is null. * @param resource the new source of coverage, or {@code null} if none. * @param coverage the new coverage, or {@code null} if none. */ - final void notifyDataChanged(final GridCoverageResource resource, final GridCoverage coverage) { + final void notifyDataChanged(final Identifier name, final GridCoverageResource resource, final GridCoverage coverage) { if (coverage != null) { BackgroundThreads.execute(() -> { - String name; - try { - name = DataStoreOpener.findLabel(resource, getLocale(), true); - } catch (DataStoreException | RuntimeException e) { - // Declare `setResource` as the public method invoking (indirectly) this method. - Logging.recoverableException(LOGGER, CoverageExplorer.class, "setResource", e); - name = DataStoreOpener.fallbackLabel(resource, getLocale()); - } referenceSystems.setGridReferencing(true, Map.of(name, coverage.getGridGeometry())); }); } diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java index b0fb761481..78b2eec27d 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java @@ -23,6 +23,7 @@ import javafx.scene.control.TableView; import javafx.scene.control.TitledPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.VBox; +import org.opengis.metadata.Identifier; import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.GridCoverage; @@ -103,10 +104,11 @@ final class GridControls extends ViewAndControls { * Invoked after {@link GridView#setImage(ImageRequest)} for updating the table of sample * dimensions when information become available. This method is invoked in JavaFX thread. * + * @param name an identifier for the grid <abbr>CRS</abbr>. Can be null only if {@code coverage} is null. * @param resource the new source of coverage, or {@code null} if none. * @param coverage the new coverage, or {@code null} if none. */ - final void notifyDataChanged(final GridCoverageResource resource, final GridCoverage coverage) { + final void notifyDataChanged(final Identifier name, final GridCoverageResource resource, final GridCoverage coverage) { final ObservableList<SampleDimension> items = sampleDimensions.getItems(); if (coverage != null) { items.setAll(coverage.getSampleDimensions()); @@ -114,7 +116,7 @@ final class GridControls extends ViewAndControls { } else { items.clear(); } - owner.notifyDataChanged(resource, coverage); + owner.notifyDataChanged(name, resource, coverage); } /** diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java index 9aeed77f05..15d7a7cfe3 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java @@ -36,6 +36,7 @@ import javafx.scene.control.ScrollBar; import javafx.scene.control.Skin; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; +import org.opengis.metadata.Identifier; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.internal.shared.Numerics; import org.apache.sis.coverage.grid.GridExtent; @@ -58,7 +59,7 @@ import org.apache.sis.image.DataType; * <p>This class is designed for large images, with tiles loaded in a background thread only when first needed.</p> * * @author Martin Desruisseaux (Geomatys) - * @version 1.5 + * @version 1.7 * * @see CoverageExplorer * @@ -196,7 +197,7 @@ public class GridView extends Control { * This is used only for notifications. A future version may use a more generic listener. * We use this specific mechanism because there is no {@code coverageProperty} in this class. * - * @see GridControls#notifyDataChanged(GridCoverageResource, GridCoverage) + * @see GridControls#notifyDataChanged(Identifier, GridCoverageResource, GridCoverage) */ final GridControls controls; @@ -308,7 +309,7 @@ public class GridView extends Control { if (source == null) { setImage((RenderedImage) null); if (controls != null) { - controls.notifyDataChanged(null, null); + controls.notifyDataChanged(null, null, null); } } else { cancelLoader(); @@ -320,15 +321,19 @@ public class GridView extends Control { /** * Invoked after the image has been loaded or after failure. * + * @param name an identifier for the grid <abbr>CRS</abbr>. Can be null only if {@code coverage} is null. * @param resource the new source of coverage, or {@code null} if none. * @param coverage the new coverage, or {@code null} if none. * @param image the loaded image, or {@code null} on failure. */ - private void setLoadedImage(GridCoverageResource resource, GridCoverage coverage, RenderedImage image) { + private void setLoadedImage(final Identifier name, + final GridCoverageResource resource, + final GridCoverage coverage, + final RenderedImage image) { loader = null; // Must be first for preventing cancellation. setImage(image); if (controls != null && !controls.isAdjustingSlice) { - controls.notifyDataChanged(resource, coverage); + controls.notifyDataChanged(name, resource, coverage); } } @@ -343,6 +348,11 @@ public class GridView extends Control { */ private final ImageRequest request; + /** + * An identifier of the coverage, or {@code null} if none. + */ + private Identifier gridCrsName; + /** * The coverage that has been read. * It may either be specified explicitly in the {@link #request}, or read from the resource. @@ -373,10 +383,11 @@ public class GridView extends Control { if (isCancelled()) { return null; } + final GridGeometry gg = coverage.getGridGeometry(); + gridCrsName = ImageRequest.gridCrsName(request.resource, gg); GridExtent slice = request.slice; final GridControls c = controls; if (c != null) { - final GridGeometry gg = coverage.getGridGeometry(); slice = BackgroundThreads.runAndWait(() -> { final GridExtent s = c.configureSliceSelector(gg); final int[] xydims = c.sliceSelector.getXYDimensions(); @@ -396,7 +407,7 @@ public class GridView extends Control { */ @Override protected void succeeded() { - setLoadedImage(request.resource, coverage, getValue()); + setLoadedImage(gridCrsName, request.resource, coverage, getValue()); } /** @@ -404,7 +415,7 @@ public class GridView extends Control { */ @Override protected void cancelled() { - setLoadedImage(null, null, null); + setLoadedImage(null, null, null, null); } /** diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java index 608bd0c55e..7cf1e6ba85 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java @@ -18,9 +18,12 @@ package org.apache.sis.gui.coverage; import java.util.Objects; import java.util.Optional; +import org.opengis.metadata.Identifier; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridExtent; +import org.apache.sis.referencing.CommonCRS; +import org.apache.sis.referencing.NamedIdentifier; import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.storage.DataStoreException; @@ -31,7 +34,7 @@ import org.apache.sis.storage.DataStoreException; * {@linkplain GridCoverage#render(GridExtent) rendering} and image in a background thread. * * @author Martin Desruisseaux (Geomatys) - * @version 1.3 + * @version 1.7 * * @see GridView#setImage(ImageRequest) * @see CoverageExplorer#setCoverage(ImageRequest) @@ -164,6 +167,29 @@ public class ImageRequest { return Optional.ofNullable(coverage); } + /** + * Returns the name of the grid <abbr>CRS</abbr>, derived from the resource identifier. + * + * @param resource resource from which to get the identifier, or {@code null} if none. + * @param domain grid geometry of the resource or coverage loaded from the resource. + * @return name derived from the identifier which can be used for the grid <abbr>CRS</abbr>. + * @throws DataStoreException if an error occurred while fetching the identifier. + */ + static Identifier gridCrsName(final GridCoverageResource resource, final GridGeometry domain) + throws DataStoreException + { + if (resource != null) { + final Identifier name = NamedIdentifier.castOrCopy(resource.getIdentifier().orElse(null)); + if (name != null) { + return name; + } + } + return (domain.isDefined(GridGeometry.GRID_TO_CRS) + ? CommonCRS.Engineering.GRID.datum() // "Unknown grid" + : CommonCRS.Engineering.GRID.crs()) // "Cell indices" + .getName(); + } + /** * Returns the desired grid extent and resolution, or an empty value for reading the full domain. * This is the {@code domain} argument specified to the following constructor: diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java index 24eff709b8..dd92f4a734 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java @@ -19,6 +19,7 @@ package org.apache.sis.gui.coverage; import java.util.Map; import java.util.concurrent.Future; import java.awt.image.RenderedImage; +import org.opengis.metadata.Identifier; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.apache.sis.storage.DataStoreException; @@ -39,6 +40,11 @@ import org.apache.sis.map.coverage.RenderingData; * @author Martin Desruisseaux (Geomatys) */ final class StyledRenderingData extends RenderingData { + /** + * Name of the grid <abbr>CRS</abbr>, derived from the resource identifier. + */ + Identifier gridCrsName; + /** * Key of the currently selected alternative in {@link CoverageCanvas#derivedImages} map. * diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ViewAndControls.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ViewAndControls.java index 090742a76d..7eee8afe80 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ViewAndControls.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ViewAndControls.java @@ -32,6 +32,7 @@ import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.collections.ObservableList; +import org.opengis.metadata.Identifier; import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridGeometry; @@ -112,7 +113,7 @@ abstract class ViewAndControls { /** * The widget which contain this view. This is the widget to inform when the coverage changed. * - * @see CoverageExplorer#notifyDataChanged(GridCoverageResource, GridCoverage) + * @see CoverageExplorer#notifyDataChanged(Identifier, GridCoverageResource, GridCoverage) */ protected final CoverageExplorer owner; diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java index 1086d8c3d6..6ef9dc5307 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java @@ -37,6 +37,7 @@ import javafx.scene.control.Menu; import javafx.concurrent.Task; import org.opengis.util.FactoryException; import org.opengis.geometry.Envelope; +import org.opengis.metadata.Identifier; import org.opengis.referencing.ReferenceSystem; import org.opengis.referencing.crs.CRSAuthorityFactory; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -44,7 +45,6 @@ import org.opengis.referencing.operation.TransformException; import org.apache.sis.geometry.Envelopes; import org.apache.sis.geometry.ImmutableEnvelope; import org.apache.sis.referencing.IdentifiedObjects; -import org.apache.sis.referencing.ImmutableIdentifier; import org.apache.sis.referencing.factory.GeodeticAuthorityFactory; import org.apache.sis.referencing.factory.IdentifiedObjectFinder; import org.apache.sis.referencing.gazetteer.MilitaryGridReferenceSystem; @@ -295,7 +295,7 @@ public class RecentReferenceSystems { /** * Sets the reference systems, area of interest and "referencing by grid indices" systems. * Contrarily to other methods in this class, this method can be invoked from any thread. - * This method performs the following tasks, whith the other methods invoked from the JavaFX thread: + * This method performs the following tasks, where the methods cited below are invoked from the JavaFX thread: * * <ul> * <li>Invokes {@link #setPreferred(boolean, ReferenceSystem)} with the first <abbr>CRS</abbr> in iteration order.</li> @@ -308,6 +308,7 @@ public class RecentReferenceSystems { * For each entry, the map key should be the {@link org.apache.sis.storage.Resource#getIdentifier() identifier} of * the resource that provided the {@link GridGeometry} value, or other text allowing the user to identify the resource. * Those keys are used for naming the <abbr>CRS</abbr>s of cell coordinates, which are different for each grid coverage. + * See the {@linkplain GridGeometry#createGridCRS grid <abbr>grid CRS</abbr> documentation} for more details. * * <p>The {@code replaceByAuthoritativeDefinition} argument specifies whether the coordinate reference systems * should be replaced by authoritative definitions when such definitions are found. If {@code true} then, @@ -320,7 +321,7 @@ public class RecentReferenceSystems { * @since 1.3 */ public void setGridReferencing(final boolean replaceByAuthoritativeDefinition, - final Map<String, GridGeometry> geometries) + final Map<Identifier, GridGeometry> geometries) { /* * Fetch or compute information needed, but without modifying the state of this object yet. @@ -331,7 +332,7 @@ public class RecentReferenceSystems { final var refsys = new CoordinateReferenceSystem[geometries.size()]; final var derived = new CoordinateReferenceSystem[refsys.length]; final var envelopes = new Envelope[refsys.length]; - for (final Map.Entry<String, GridGeometry> entry : geometries.entrySet()) { + for (final Map.Entry<Identifier, GridGeometry> entry : geometries.entrySet()) { final GridGeometry gg = entry.getValue(); if (gg.isDefined(GridGeometry.CRS)) { if (gg.isDefined(GridGeometry.ENVELOPE)) { @@ -340,8 +341,7 @@ public class RecentReferenceSystems { refsys[countCRS++] = gg.getCoordinateReferenceSystem(); } try { - final var name = new ImmutableIdentifier(null, null, entry.getKey()); - derived[countCIR] = gg.createGridCRS(name, PixelInCell.CELL_CENTER); + derived[countCIR] = gg.createGridCRS(entry.getKey(), PixelInCell.CELL_CENTER); countCIR++; // Increment only if above line was successful. } catch (FactoryException e) { errorOccurred(e);
