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 c54e64e4650f742104d0c23323a686e19d2fe0f2 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sun Jan 28 16:33:38 2024 +0100 Consolidation in the warnings about auxiliary files. --- .../org/apache/sis/console/OperationParser.java | 2 +- .../org/apache/sis/storage/base/PRJDataStore.java | 18 ++++++---- .../org/apache/sis/storage/base/URIDataStore.java | 35 +++++++++++++++--- .../main/org/apache/sis/storage/csv/Store.java | 2 +- .../apache/sis/storage/esri/AsciiGridStore.java | 2 +- .../org/apache/sis/storage/esri/RasterStore.java | 16 ++++----- .../apache/sis/storage/esri/RawRasterStore.java | 2 +- .../apache/sis/storage/image/WorldFileStore.java | 8 ++--- .../main/org/apache/sis/storage/wkt/Store.java | 6 ++-- .../org/apache/sis/storage/wkt/StoreFormat.java | 41 ++++++++++++---------- .../main/org/apache/sis/storage/xml/Store.java | 2 +- 11 files changed, 83 insertions(+), 51 deletions(-) diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/OperationParser.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/OperationParser.java index d31192845c..6c019724ac 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/OperationParser.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/OperationParser.java @@ -46,7 +46,7 @@ final class OperationParser extends PRJDataStore { * @throws DataStoreException if an error occurred while reading the file. */ final Optional<CoordinateOperation> read() throws DataStoreException { - return readWKT(CoordinateOperation.class, null); + return readWKT(OperationParser.class, "read", CoordinateOperation.class, null); } /** diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PRJDataStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PRJDataStore.java index 7dcbe0f4c9..eff3b39cd7 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PRJDataStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PRJDataStore.java @@ -116,27 +116,33 @@ public abstract class PRJDataStore extends URIDataStore { * <p>This method does not verify if it has been invoked multiple time. * Caller should track whether the data store has been initialized.</p> * + * @param caller the class to report as the warning source if a log record is created. + * @param method the method to report as the warning source if a log record is created. * @throws DataStoreException if an error occurred while reading the file. */ - protected final void readPRJ() throws DataStoreException { - readWKT(CoordinateReferenceSystem.class, PRJ).ifPresent((result) -> crs = result); + protected final void readPRJ(final Class<? extends DataStore> caller, final String method) throws DataStoreException { + readWKT(caller, method, CoordinateReferenceSystem.class, PRJ).ifPresent((result) -> crs = result); } /** * Reads an auxiliary file in WKT or GML format. Standard PRJ files use WKT only, * but the GML format is also accepted by this method as an extension specific to Apache SIS. * + * @param caller the class to report as the warning source if a log record is created. + * @param method the method to report as the warning source if a log record is created. * @param type base class or interface of the object to read. * @param extension extension of the file to read (usually {@link #PRJ}), or {@code null} for the main file. * @return the parsed object, or an empty value if the file does not exist. * @throws DataStoreException if an error occurred while reading the file. */ - protected final <T> Optional<T> readWKT(final Class<T> type, final String extension) throws DataStoreException { + protected final <T> Optional<T> readWKT(final Class<? extends DataStore> caller, final String method, + final Class<T> type, final String extension) throws DataStoreException + { Exception cause = null, suppressed = null; try { final AuxiliaryContent content = readAuxiliaryFile(extension, true); if (content == null) { - listeners.warning(cannotReadAuxiliaryFile(extension)); + cannotReadAuxiliaryFile(caller, method, extension, null, true); return Optional.empty(); } if (content.source != null) try { @@ -163,11 +169,11 @@ public abstract class PRJDataStore extends URIDataStore { * defined twice: as a WKT on the first line, followed by key-value pairs on next lines. * Current Apache SIS implementation ignores all characters after the WKT. */ - format.validate(result); + format.validate(null, caller, method, result); return Optional.of(result); } } catch (NoSuchFileException | FileNotFoundException e) { - listeners.warning(cannotReadAuxiliaryFile(extension), e); + cannotReadAuxiliaryFile(caller, method, extension, e, true); return Optional.empty(); } catch (IOException | ParseException | ClassCastException e) { cause = e; diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStore.java index 0862772199..4f84919c94 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStore.java @@ -22,6 +22,8 @@ import java.util.Arrays; import java.util.Optional; import java.util.Locale; import java.util.TimeZone; +import java.util.logging.Level; +import java.util.logging.LogRecord; import java.io.BufferedWriter; import java.io.BufferedInputStream; import java.io.InputStream; @@ -49,6 +51,7 @@ import org.apache.sis.io.stream.IOUtilities; import org.apache.sis.setup.OptionKey; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.iso.Names; +import org.apache.sis.util.resources.Errors; import org.apache.sis.xml.XML; import org.apache.sis.xml.util.URISource; import org.apache.sis.xml.util.ExceptionSimplifier; @@ -325,10 +328,12 @@ public abstract class URIDataStore extends DataStore implements StoreResource, R * If an auxiliary metadata file has been specified, merges that file to the given metadata. * This step should be done only after the data store added its own metadata. * Failure to load auxiliary metadata are only a warning. + * If a warning is logged, declared source will be the {@code getMetadata()} method of the given class. * + * @param caller the source class to declare if a warning is logged. * @param builder where to merge the metadata. */ - protected final void mergeAuxiliaryMetadata(final MetadataBuilder builder) { + protected final void mergeAuxiliaryMetadata(final Class<? extends DataStore> caller, final MetadataBuilder builder) { Object spec = null; // Used only for formatting error message. Object metadata = null; try { @@ -347,11 +352,11 @@ public abstract class URIDataStore extends DataStore implements StoreResource, R } metadata = readXML(input, source); } catch (URISyntaxException | IOException e) { - listeners.warning(cannotReadAuxiliaryFile("xml"), e); + cannotReadAuxiliaryFile(caller, "getMetadata", "xml", e, true); } catch (JAXBException e) { Throwable cause = e.getCause(); if (cause instanceof IOException) { - listeners.warning(cannotReadAuxiliaryFile("xml"), (Exception) cause); + cannotReadAuxiliaryFile(caller, "getMetadata", "xml", (Exception) cause, true); } else { listeners.warning(new ExceptionSimplifier(spec, e).record(URIDataStore.class, "mergeAuxiliaryMetadata")); } @@ -526,10 +531,30 @@ public abstract class URIDataStore extends DataStore implements StoreResource, R * * @param extension file extension (without leading dot) of the auxiliary file, or null for the main file. */ - protected final String cannotReadAuxiliaryFile(String extension) { + protected final String cannotReadAuxiliaryFile(final String extension) { if (extension == null) { - extension = IOUtilities.extension(location); + return Errors.getResources(getLocale()).getString(Errors.Keys.CanNotRead_1, location); } return Resources.forLocale(getLocale()).getString(Resources.Keys.CanNotReadAuxiliaryFile_1, extension); } + + /** + * Logs an error message saying that an auxiliary file cannot be read. + * + * @param classe the class to report as the source of the warning to log. + * @param method the method to report as the source of the warning to log. + * @param extension file extension (without leading dot) of the auxiliary file. + * @param cause the reason why the auxiliary file cannot be read. + * @param warning {@code true} for logging at warning level, or {@code false} for fine level. + */ + protected final void cannotReadAuxiliaryFile(final Class<? extends DataStore> classe, final String method, + final String extension, final Exception cause, final boolean warning) + { + final LogRecord record = Resources.forLocale(getLocale()) + .getLogRecord(warning ? Level.WARNING : Level.FINE, Resources.Keys.CanNotReadAuxiliaryFile_1, extension); + record.setSourceClassName(classe.getCanonicalName()); + record.setSourceMethodName(method); + record.setThrown(cause); + listeners.warning(record); // Logger name will be inferred by this method. + } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java index f977152722..6e73be1de0 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java @@ -642,7 +642,7 @@ final class Store extends URIDataStore implements FeatureSet { builder.addResourceScope(ScopeCode.FEATURE, null); builder.addExtent(envelope, listeners); builder.addFeatureType(featureType, -1); - mergeAuxiliaryMetadata(builder); + mergeAuxiliaryMetadata(Store.class, builder); builder.addTitleOrIdentifier(getFilename(), MetadataBuilder.Scope.ALL); builder.setISOStandards(false); metadata = builder.buildAndFreeze(); diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java index 2b69ad8aa0..4f8a9b36c3 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java @@ -321,7 +321,7 @@ cellsize: if (value != null) { * Read the auxiliary PRJ file after we finished parsing the header file. * A future version could skip this step if we add a non-standard "CRS" property in the header. */ - readPRJ(); + readPRJ(AsciiGridStore.class, "getGridGeometry"); gridGeometry = new GridGeometry(new GridExtent(width, height), anchor, MathTransforms.linear(gridToCRS), crs); /* * If there is any unprocessed properties, log a warning about them. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java index e8b41b97f5..431e86d9f8 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java @@ -20,7 +20,6 @@ import java.util.List; import java.util.Arrays; import java.util.Hashtable; import java.util.Locale; -import java.util.logging.Level; import java.io.IOException; import java.io.FileNotFoundException; import java.nio.file.NoSuchFileException; @@ -171,7 +170,7 @@ abstract class RasterStore extends PRJDataStore implements GridCoverageResource builder.addNewBand(band); } } - mergeAuxiliaryMetadata(builder); + mergeAuxiliaryMetadata(RasterStore.class, builder); builder.addTitleOrIdentifier(getFilename(), MetadataBuilder.Scope.ALL); builder.setISOStandards(false); metadata = builder.buildAndFreeze(); @@ -334,7 +333,7 @@ abstract class RasterStore extends PRJDataStore implements GridCoverageResource try { stats = readStatistics(name, sm); } catch (IOException | NumberFormatException e) { - canNotReadAuxiliaryFile(STX, e); + cannotReadAuxiliaryFile(STX, e); } /* * Build the sample dimensions and the color model. @@ -403,7 +402,7 @@ abstract class RasterStore extends PRJDataStore implements GridCoverageResource try { colorModel = readColorMap(dataType, (int) (maximum + 1), bands.length); } catch (IOException | NumberFormatException e) { - canNotReadAuxiliaryFile(CLR, e); + cannotReadAuxiliaryFile(CLR, e); } if (colorModel == null) { colorModel = ColorModelFactory.createGrayScale(dataType, bands.length, band, minimum, maximum); @@ -421,12 +420,9 @@ abstract class RasterStore extends PRJDataStore implements GridCoverageResource * @param suffix suffix of the auxiliary file. * @param exception error that occurred while reading the auxiliary file. */ - private void canNotReadAuxiliaryFile(final String suffix, final Exception exception) { - Level level = Level.WARNING; - if (exception instanceof NoSuchFileException || exception instanceof FileNotFoundException) { - level = Level.FINE; - } - listeners.warning(level, cannotReadAuxiliaryFile(suffix), exception); + private void cannotReadAuxiliaryFile(final String suffix, final Exception exception) { + boolean warning = !(exception instanceof NoSuchFileException || exception instanceof FileNotFoundException); + cannotReadAuxiliaryFile(RasterStore.class, "loadBandDescriptions", suffix, exception, warning); } /** diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RawRasterStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RawRasterStore.java index 8296557b59..3d76c13e0d 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RawRasterStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RawRasterStore.java @@ -440,7 +440,7 @@ final class RawRasterStore extends RasterStore { throw missingProperty(header, keyword); } } - readPRJ(); + readPRJ(RawRasterStore.class, "getGridGeometry"); final GridGeometry gg = new GridGeometry(new GridExtent(ncols, nrows), CELL_ANCHOR, new AffineTransform2D(xdim, 0, 0, -ydim, ulxmap, ulymap), crs); /* diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WorldFileStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WorldFileStore.java index bf06e72815..60a2edcff1 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WorldFileStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WorldFileStore.java @@ -359,7 +359,7 @@ loop: for (int convention=0;; convention++) { } } if (warning != null) { - listeners.warning(cannotReadAuxiliaryFile(preferred), warning); + cannotReadAuxiliaryFile(WorldFileStore.class, "getGridGeometry", preferred, warning, true); } return null; } @@ -375,7 +375,7 @@ loop: for (int convention=0;; convention++) { private AffineTransform2D readWorldFile(final String wld) throws IOException, DataStoreException { final AuxiliaryContent content = readAuxiliaryFile(wld, false); if (content == null) { - listeners.warning(cannotReadAuxiliaryFile(wld)); + cannotReadAuxiliaryFile(WorldFileStore.class, "getGridGeometry", wld, null, true); return null; } final String filename = content.getFilename(); @@ -473,7 +473,7 @@ loop: for (int convention=0;; convention++) { width = reader.getWidth (MAIN_IMAGE); height = reader.getHeight(MAIN_IMAGE); gridToCRS = readWorldFile(); - readPRJ(); + readPRJ(WorldFileStore.class, "getGridGeometry"); gridGeometry = new GridGeometry(new GridExtent(width, height), CELL_ANCHOR, gridToCRS, crs); } if (index != MAIN_IMAGE) { @@ -536,7 +536,7 @@ loop: for (int convention=0;; convention++) { if (gridGeometry.isDefined(GridGeometry.ENVELOPE)) { builder.addExtent(gridGeometry.getEnvelope(), listeners); } - mergeAuxiliaryMetadata(builder); + mergeAuxiliaryMetadata(WorldFileStore.class, builder); builder.addTitleOrIdentifier(getFilename(), MetadataBuilder.Scope.ALL); builder.setISOStandards(false); metadata = builder.buildAndFreeze(); diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/Store.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/Store.java index acb4923da4..c3ea161c3c 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/Store.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/Store.java @@ -145,7 +145,7 @@ final class Store extends URIDataStore { final Object obj = parser.parse(wkt, pos); objects.add(obj); pos.setIndex(CharSequences.skipLeadingWhitespaces(wkt, pos.getIndex(), wkt.length())); - parser.validate(obj); + parser.validate(null, Store.class, "getMetadata", obj); } while (pos.getIndex() < wkt.length()); } catch (ParseException e) { throw new DataStoreContentException(getLocale(), StoreProvider.NAME, getDisplayName(), in).initCause(e); @@ -181,9 +181,9 @@ final class Store extends URIDataStore { } if (count == 1) { // Set the citation title only if non-ambiguous. builder.addTitle(name); - mergeAuxiliaryMetadata(builder); + mergeAuxiliaryMetadata(Store.class, builder); } else { - mergeAuxiliaryMetadata(builder); + mergeAuxiliaryMetadata(Store.class, builder); builder.addTitleOrIdentifier(getFilename(), MetadataBuilder.Scope.ALL); } metadata = builder.buildAndFreeze(); diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/StoreFormat.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/StoreFormat.java index 78833ee26d..8220a5e57b 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/StoreFormat.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/wkt/StoreFormat.java @@ -109,7 +109,7 @@ public final class StoreFormat extends WKTFormat { for (final String ct : wkt) { if (ct != null) { final Object crs = parseObject(ct); - validate(crs); + validate(Loggers.WKT, listeners.getSource().getClass(), "getMetadata", crs); components[n++] = (CoordinateReferenceSystem) crs; } } @@ -129,21 +129,33 @@ public final class StoreFormat extends WKTFormat { * so often in practice that we are better to check and warn users. * * <p>This method does not need to be invoked after {@code parseGeometry(…)} or {@code parseCRS(…)} - * since it is already done.</p> + * because above-cited methods already invoke this method.</p> * + * @param logger name of the logger where to send warnings, or {@code null} for the provider's logger. + * @param caller the class to report as the warning source if a log record is created. + * @param method the method to report as the warning source if a log record is created. * @param parsed the object parsed from WKT, or {@code null} if none. */ - public void validate(final Object parsed) { + public void validate(final String logger, final Class<?> caller, final String method, final Object parsed) { final Warnings warnings = getWarnings(); if (warnings != null) { - log(new LogRecord(Level.WARNING, warnings.toString())); + final var record = new LogRecord(Level.WARNING, warnings.toString()); + record.setSourceClassName(caller.getCanonicalName()); + record.setSourceMethodName(method); + record.setLoggerName(logger); + listeners.warning(record); } if (parsed instanceof CoordinateReferenceSystem) try { final DefinitionVerifier v = DefinitionVerifier.withAuthority( (CoordinateReferenceSystem) parsed, null, false, getLocale()); if (v != null) { - final LogRecord warning = v.warning(false); - if (warning != null) log(warning); + final LogRecord record = v.warning(false); + if (record != null) { + record.setSourceClassName(caller.getCanonicalName()); + record.setSourceMethodName(method); + record.setLoggerName(logger); + listeners.warning(record); + } } } catch (FactoryException e) { listeners.warning(e); @@ -152,20 +164,13 @@ public final class StoreFormat extends WKTFormat { /** * Reports a warning for a WKT that cannot be read. This method should be invoked only when the CRS - * cannot be created at all; it should not be invoked if the CRS has been created with some warnings. + * cannot be created at all. It should not be invoked if the CRS has been created with some warnings. + * This method pretends that the warning come from {@code getMetadata()} method, which is the public + * facade for the parsing method. */ private void log(final Exception e) { - listeners.warning(Resources.forLocale(listeners.getLocale()) - .getString(Resources.Keys.CanNotReadCRS_WKT_1, listeners.getSourceName()), e); - } - - /** - * Reports a warning in the {@code "org.apache.sis.io.wkt"} logger. This method pretends that the - * warning come from {@code getMetadata()} method, which is the public facade for the parsing method. - * - * @param record the warning to report. - */ - private void log(final LogRecord record) { + final LogRecord record = Resources.forLocale(listeners.getLocale()) + .getLogRecord(Level.WARNING, Resources.Keys.CanNotReadCRS_WKT_1, listeners.getSourceName()); record.setSourceClassName(listeners.getSource().getClass().getName()); record.setSourceMethodName("getMetadata"); record.setLoggerName(Loggers.WKT); diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/xml/Store.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/xml/Store.java index a432ff8673..31f3caf0a4 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/xml/Store.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/xml/Store.java @@ -207,7 +207,7 @@ final class Store extends URIDataStore implements Filter { final MetadataBuilder builder = new MetadataBuilder(); builder.addReferenceSystem((ReferenceSystem) object); builder.addTitle(getDisplayName()); - mergeAuxiliaryMetadata(builder); + mergeAuxiliaryMetadata(Store.class, builder); metadata = builder.buildAndFreeze(); } }