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 558c65499f8996695ab7d8e62a3da459432f54fb Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sat Dec 9 16:40:30 2023 +0100 Add a "--metadata" option to the command line for making possible to specify the auxiliary metadata. --- .../main/org/apache/sis/console/Command.java | 11 ++-- .../main/org/apache/sis/console/CommandRunner.java | 61 +++++++++++++++++++++- .../apache/sis/console/FormattedOutputCommand.java | 15 +++--- .../main/org/apache/sis/console/InfoCommand.java | 2 +- .../org/apache/sis/console/MetadataCommand.java | 5 +- .../main/org/apache/sis/console/Option.java | 5 ++ .../main/org/apache/sis/console/Options.properties | 7 +-- .../org/apache/sis/console/Options_fr.properties | 7 +-- .../main/org/apache/sis/console/SIS.java | 26 +++++++++ .../org/apache/sis/console/TransformCommand.java | 4 +- .../org/apache/sis/console/TranslateCommand.java | 4 +- .../main/org/apache/sis/setup/OptionKey.java | 2 +- 12 files changed, 121 insertions(+), 28 deletions(-) diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java index e6062a0e9b..530ad9a788 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java @@ -41,10 +41,12 @@ import org.apache.sis.util.logging.MonolineFormatter; * <tr><td>{@code help} </td><td>Show a help overview.</td></tr> * <tr><td>{@code about} </td><td>Show information about Apache SIS and system configuration.</td></tr> * <tr><td>{@code mime-type} </td><td>Show MIME type for the given file.</td></tr> + * <tr><td>{@code identifier} </td><td>Show identifiers for metadata and referencing systems in the given file.</td></tr> * <tr><td>{@code metadata} </td><td>Show metadata information for the given file.</td></tr> * <tr><td>{@code crs} </td><td>Show Coordinate Reference System information for the given file or code.</td></tr> - * <tr><td>{@code identifier} </td><td>Show identifiers for metadata and referencing systems in the given file.</td></tr> + * <tr><td>{@code info} </td><td>Show resource-specific information (e.g., grid geometry).</td></tr> * <tr><td>{@code transform} </td><td>Convert or transform coordinates from given source CRS to target CRS.</td></tr> + * <tr><td>{@code translate} </td><td>Rewrite a data file in another format.</td></tr> * </table></blockquote> * * Each command can accepts some of the following options: @@ -53,10 +55,11 @@ import org.apache.sis.util.logging.MonolineFormatter; * <caption>Supported command-line options</caption> * <tr><td>{@code --sourceCRS} </td><td>The Coordinate Reference System of input data.</td></tr> * <tr><td>{@code --targetCRS} </td><td>The Coordinate Reference System of output data.</td></tr> + * <tr><td>{@code --metadata} </td><td>Relative path to an auxiliary metadata file.</td></tr> * <tr><td>{@code --format} </td><td>The output format: {@code xml}, {@code wkt}, {@code wkt1} or {@code text}.</td></tr> - * <tr><td>{@code --locale} </td><td>The locale to use for the command output.</td></tr> - * <tr><td>{@code --timezone} </td><td>The timezone for the dates to be formatted.</td></tr> - * <tr><td>{@code --encoding} </td><td>The encoding to use for the command outputs and some inputs.</td></tr> + * <tr><td>{@code --locale} </td><td>The locale to use for the console output.</td></tr> + * <tr><td>{@code --timezone} </td><td>The timezone for the dates printed to the console output.</td></tr> + * <tr><td>{@code --encoding} </td><td>The encoding to use for some text inputs and for console output.</td></tr> * <tr><td>{@code --colors} </td><td>Whether colorized output shall be enabled.</td></tr> * <tr><td>{@code --brief} </td><td>Whether the output should contain only brief information.</td></tr> * <tr><td>{@code --verbose} </td><td>Whether the output should contain more detailed information.</td></tr> diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java index 581834dfa6..8de71c01f9 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java @@ -29,12 +29,16 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.io.OutputStreamWriter; import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.InvalidPathException; import org.apache.sis.util.Locales; import org.apache.sis.util.Exceptions; import org.apache.sis.util.Workaround; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.internal.X364; import org.apache.sis.pending.jdk.JDK17; +import org.apache.sis.storage.DataOptionKey; +import org.apache.sis.storage.StorageConnector; /** @@ -302,8 +306,29 @@ abstract class CommandRunner { if (value instanceof CharSequence) { return value.toString(); } - final String name = key.label(); - throw new InvalidOptionException(Errors.format(Errors.Keys.IllegalOptionValue_2, name, value), name); + throw invalidOption(key, value, null); + } + + /** + * Returns the value of the specified option as a path. + * + * @param key the option for which to get a value. + * @return the requested option, or {@code null} if not present. + * @throws InvalidOptionException if the value is not convertible to a path. + */ + final Path getOptionAsPath(final Option key) throws InvalidOptionException { + final Object value = options.get(key); + if (value == null) return null; + if (value instanceof Path) { + return (Path) value; + } + Throwable cause = null; + if (value instanceof CharSequence) try { + return Path.of(value.toString()); + } catch (InvalidPathException e) { + cause = e; + } + throw invalidOption(key, value, cause); } /** @@ -376,6 +401,38 @@ abstract class CommandRunner { return files.isEmpty() && System.console() == null; } + /** + * Returns a storage connector for the specified input. + * This method should be invoked only for the input, not for the output, because it uses input-specific options. + * Conversely, this storage connector does <strong>not</strong> include the options intended for console output + * such as {@linkplain #locale}, {@link #timezone} and {@linkplain #encoding}. + * + * @param input the storage input. + * @return storage connector for the specified input. + * @throws InvalidOptionException if an option has an invalid value. + */ + final StorageConnector inputConnector(final Object input) throws InvalidOptionException { + final var connector = new StorageConnector(input); + final Path p = getOptionAsPath(Option.METADATA); + if (p != null) { + connector.setOption(DataOptionKey.METADATA_PATH, p); + } + return connector; + } + + /** + * Returns the exception to throw for an invalid option. + * + * @param key the requested option. + * @param value the value associated to the specified option. + * @param cause cause of the invalidity, or {@code null} if none. + * @return the exception to throw. + */ + private static InvalidOptionException invalidOption(Option key, Object value, Throwable cause) { + final String name = key.label(); + return new InvalidOptionException(Errors.format(Errors.Keys.IllegalOptionValue_2, name, value), cause, name); + } + /** * Prints the <q>Cannot open …</q> error message followed by the message in the given exception. * diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java index f268dbbff2..e65fd49cce 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java @@ -178,14 +178,14 @@ abstract class FormattedOutputCommand extends CommandRunner { * The input format is detected automatically (this is <strong>not</strong> {@link #outputFormat}). * * @return a {@link Metadata} or {@link CoordinateReferenceSystem} instance, or {@code null} if none. + * @throws InvalidOptionException if an option has an invalid value. * @throws DataStoreException if an error occurred while reading the file. * @throws FactoryException if an error occurred while looking for a CRS identifier. */ - final Object readMetadataOrCRS() throws DataStoreException, FactoryException { + final Object readMetadataOrCRS() throws InvalidOptionException, DataStoreException, FactoryException { + final Object input; if (useStandardInput()) { - try (DataStore store = DataStores.open(System.in)) { - return store.getMetadata(); - } + input = System.in; } else if (hasUnexpectedFileCount(1, 1)) { hasUnexpectedFileCount = true; return null; @@ -197,9 +197,10 @@ abstract class FormattedOutputCommand extends CommandRunner { return CRS.forCode(c); } } - try (DataStore store = DataStores.open(file)) { - return store.getMetadata(); - } + input = file; + } + try (DataStore store = DataStores.open(inputConnector(input))) { + return store.getMetadata(); } } diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/InfoCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/InfoCommand.java index b09ab42c2f..286a7e8bc2 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/InfoCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/InfoCommand.java @@ -48,7 +48,7 @@ final class InfoCommand extends FormattedOutputCommand { * Returns valid options for the {@code "metadata"} command. */ static EnumSet<Option> options() { - return EnumSet.of(Option.LOCALE, Option.TIMEZONE, Option.COLORS, Option.VERBOSE, Option.HELP, Option.DEBUG); + return EnumSet.of(Option.METADATA, Option.LOCALE, Option.TIMEZONE, Option.COLORS, Option.VERBOSE, Option.HELP, Option.DEBUG); } /** diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/MetadataCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/MetadataCommand.java index b12a6b4010..365cf47610 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/MetadataCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/MetadataCommand.java @@ -32,7 +32,8 @@ import org.apache.sis.util.collection.TreeTable; * Some available options are: * * <ul> - * <li>{@code --format}: the output format (text, XML or GPX).</li> + * <li>{@code --metadata}: relative path to auxiliary metadata to combine with the main metadata.</li> + * <li>{@code --format}: the output format (text, XML or GPX).</li> * </ul> * * @author Martin Desruisseaux (Geomatys) @@ -42,7 +43,7 @@ final class MetadataCommand extends FormattedOutputCommand { * Returns valid options for the {@code "metadata"} command. */ static EnumSet<Option> options() { - return EnumSet.of(Option.FORMAT, Option.LOCALE, Option.TIMEZONE, + return EnumSet.of(Option.METADATA, Option.FORMAT, Option.LOCALE, Option.TIMEZONE, Option.ENCODING, Option.COLORS, Option.VERBOSE, Option.HELP, Option.DEBUG); } diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Option.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Option.java index 23e6f2f1f3..8fdead8c96 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Option.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Option.java @@ -37,6 +37,11 @@ enum Option { */ TARGET_CRS(true), + /** + * Relative path to an auxiliary metadata file. + */ + METADATA(true), + /** * The file to write. */ diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options.properties b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options.properties index e8c984cb5d..ae275090d8 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options.properties +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options.properties @@ -2,11 +2,12 @@ # and to You under the Apache License, Version 2.0. sourceCRS=The Coordinate Reference System of input data. targetCRS=The Coordinate Reference System of output data. +metadata=Relative path to an auxiliary metadata file. output=The output file. format=The output format. Examples: xml, wkt, wkt1 or text. -locale=The locale to use for the command output. -timezone=The timezone for the dates to be formatted. -encoding=The encoding to use for the command outputs and some inputs. +locale=The locale to use for the console output. +timezone=The timezone for the dates printed to the console output. +encoding=The encoding to use for some text inputs and for console output. colors=Whether colorized output shall be enabled. brief=Reduce the output to only brief information. verbose=Request the output to contain more detailed information. diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options_fr.properties b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options_fr.properties index 1828e7be7d..6e7bf7227f 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options_fr.properties +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Options_fr.properties @@ -2,11 +2,12 @@ # and to You under the Apache License, Version 2.0. sourceCRS=Le syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es source. targetCRS=Le syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es destination. +metadata=Chemin relatif vers un fichier auxiliaire de m\u00e9ta-donn\u00e9es. output=Le fichier de sortie. format=Le format de sortie. Exemples: xml, wkt, wkt1 ou text. -locale=Les param\u00e8tres r\u00e9gionaux \u00e0 utiliser pour la sortie de la commande. -timezone=Le fuseau horaire des dates \u00e0 \u00e9crire. -encoding=L\u2019encodage des caract\u00e8res \u00e0 utiliser pour la sortie de la commande et certaines entr\u00e9es. +locale=Les param\u00e8tres r\u00e9gionaux \u00e0 utiliser pour la sortie vers la console. +timezone=Le fuseau horaire des dates \u00e0 \u00e9crire dans la sortie console. +encoding=L\u2019encodage des caract\u00e8res \u00e0 utiliser pour certaines entr\u00e9es textuels et la sortie vers la console. colors=Indique si l\u2019affichage peut \u00eatre en couleurs. brief=Indique que la sortie de la commande ne doit contenir que de br\u00e8ves informations. verbose=Indique que la sortie de la commande doit contenir des informations plus d\u00e9taill\u00e9es. diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java index 2f78e06b7e..b6f6d15934 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java @@ -432,6 +432,19 @@ public final class SIS extends Static { /** Creates the instance for metadata or CRS. */ Metadata(String command) {super(command);} + /** + * Sets the path to auxiliary metadata, relative to the main file. + * The {@code '*'} character stands for the name of the main file. + * For example if the main file is {@code "city-center.tiff"}, + * then {@code "*.xml"} stands for {@code "city-center.xml"}. + * + * @param value relative path to auxiliary metadata. + * @return a new builder or {@code this}, for method call chaining. + */ + public Metadata metadata(String value) { + return set(Option.METADATA, value); + } + /** * Sets the output format. * @@ -699,6 +712,19 @@ public final class SIS extends Static { /** Creates the unique instance. */ Translate() {super("translate");} + /** + * Sets the path to auxiliary metadata, relative to the main file. + * The {@code '*'} character stands for the name of the main file. + * For example if the main file is {@code "city-center.tiff"}, + * then {@code "*.xml"} stands for {@code "city-center.xml"}. + * + * @param value relative path to auxiliary metadata. + * @return a new builder or {@code this}, for method call chaining. + */ + public Translate metadata(String value) { + return set(Option.METADATA, value); + } + /** * Sets the destination file. * diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java index ea45f0ee88..698ee27bfa 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java @@ -77,7 +77,6 @@ import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox; import org.apache.sis.util.resources.Vocabulary; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.logging.Logging; -import org.apache.sis.setup.OptionKey; // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.referencing.ObjectDomain; @@ -219,8 +218,7 @@ final class TransformCommand extends FormattedOutputCommand { } } else { for (final Object file : files) { - final var c = new StorageConnector(file); - c.setOption(OptionKey.ENCODING, encoding); + final StorageConnector c = inputConnector(file); try (BufferedReader in = IOUtilities.toBuffered(c.commit(Reader.class, "transform"))) { points = readCoordinates(in, file); } diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TranslateCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TranslateCommand.java index 38864f912e..142fe59bbe 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TranslateCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TranslateCommand.java @@ -49,7 +49,7 @@ final class TranslateCommand extends CommandRunner { * @throws InvalidOptionException if an illegal option has been provided, or the option has an illegal value. */ TranslateCommand(final int commandIndex, final Object[] arguments) throws InvalidOptionException { - super(commandIndex, arguments, EnumSet.of(Option.OUTPUT, Option.FORMAT, Option.HELP, Option.DEBUG)); + super(commandIndex, arguments, EnumSet.of(Option.METADATA, Option.OUTPUT, Option.FORMAT, Option.HELP, Option.DEBUG)); } /** @@ -72,7 +72,7 @@ final class TranslateCommand extends CommandRunner { }); try (DataStore target = DataStores.openWritable(connector, format)) { for (final Object file : files) { - try (DataStore source = DataStores.open(file)) { + try (DataStore source = DataStores.open(inputConnector(file))) { if (target instanceof WritableAggregate) { ((WritableAggregate) target).add(source); } else if (target instanceof WritableGridCoverageResource) { diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionKey.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionKey.java index 19b1f40705..03377c606d 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionKey.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/OptionKey.java @@ -108,7 +108,7 @@ public class OptionKey<T> implements Serializable { /** * The character encoding of document content. - * This option can be used when the file to read does not describe itself its encoding. + * This option can be used when the file to read or write does not describe itself its encoding. * For example, this option can be used when reading plain text files, but is ignored when * reading XML files having a {@code <?xml version="1.0" encoding="…"?>} declaration. *