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 6cdeffb8f511a66b66465b3eb6be9d4b176f834d
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Dec 6 14:32:59 2024 +0100

    Add a `DataStores.open(Object, String)` method which allows to specify the 
preferred data store implementation.
---
 .../org/apache/sis/storage/DataStoreRegistry.java  |  2 +-
 .../main/org/apache/sis/storage/DataStores.java    | 63 +++++++++++++++++++++-
 .../apache/sis/storage/image/DataStoreFilter.java  | 21 ++++----
 3 files changed, 75 insertions(+), 11 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStoreRegistry.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStoreRegistry.java
index 6d1ce5d717..cd117b737b 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStoreRegistry.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStoreRegistry.java
@@ -269,7 +269,7 @@ search:     for (final Category category : 
Category.values()) {
                     if (md == null) {
                         accept = isFirstIteration;      // If no metadata, 
test only during one iteration.
                     } else {
-                        accept = (md.yieldPriority() == 
category.yieldPriority) &&
+                        accept = (category.preferred || md.yieldPriority() == 
category.yieldPriority) &&
                                  ArraysExt.contains(md.capabilities(), 
capability);
                         if (accept & useSuffix) {
                             accept = 
ArraysExt.containsIgnoreCase(md.fileSuffixes(), extension) == 
category.useSuffix;
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStores.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStores.java
index c4ce0b2eb9..a5739a4d76 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStores.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStores.java
@@ -37,7 +37,10 @@ import org.apache.sis.coverage.grid.DisjointExtentException;
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
  * @version 1.5
- * @since   0.4
+ *
+ * <a href="https://sis.apache.org/formats.html";>Data formats supported by 
Apache SIS</a>
+ *
+ * @since 0.4
  */
 public final class DataStores extends Static {
     /**
@@ -84,6 +87,9 @@ public final class DataStores extends Static {
      *   <li>An existing {@link StorageConnector} instance.</li>
      * </ul>
      *
+     * The file format is detected automatically by inspection of the file 
header.
+     * The file suffix may also be used in case of ambiguity.
+     *
      * @param  storage  the input object as a URL, file, image input stream, 
<i>etc.</i>.
      * @return the object to use for reading geospatial data from the given 
storage.
      * @throws UnsupportedStorageException if no {@link DataStoreProvider} is 
found for the given storage object.
@@ -93,6 +99,61 @@ public final class DataStores extends Static {
         return DataStoreRegistry.INSTANCE.open(storage, Capability.READ, null);
     }
 
+    /**
+     * Creates a {@link DataStore} capable to read the given storage, with a 
preference for the specified reader.
+     * The {@code storage} argument can be of the same types as documented in 
{@link #open(Object)}.
+     * The {@code preferredFormat} argument can be one of the following 
(non-exhaustive list).
+     * Note that which formats are available depend on which modules are on 
the module-path.
+     *
+     * <table class="sis">
+     *   <caption>Common formats</caption>
+     *   <tr><th>Format</th> <th>Description</th></tr>
+     *   <tr><td>{@code "ASCII Grid"}</td>  <td>ESRI ASCII Grid raster 
format</td></tr>
+     *   <tr><td>{@code "BIL/BIP/BSQ"}</td> <td>ESRI RAW binary 
encoding</td></tr>
+     *   <tr><td>{@code "CSV"}</td>         <td>Comma-Separated Values, 
optionally with Moving Features</td></tr>
+     *   <tr><td>{@code "folder"}</td>      <td>Directory of more 
files</td></tr>
+     *   <tr><td>{@code "GDAL"}</td>        <td>Binding to the 
<abbr>GDAL</abbr> C/C++ library</td></tr>
+     *   <tr><td>{@code "GeoTIFF"}</td>     <td>GeoTIFF, including big and 
<abbr>COG</abbr> variants</td></tr>
+     *   <tr><td>{@code "GPX"}</td>         <td><abbr>GPS</abbr> Exchange 
Format</td></tr>
+     *   <tr><td>{@code "Landsat"}</td>     <td>Landsat 8 level 1-2 
data</td></tr>
+     *   <tr><td>{@code "NetCDF"}</td>      <td>NetCDF 3 (or 4 if UCAR 
dependency is included)</td></tr>
+     *   <tr><td>{@code "SQL"}</td>         <td>Connection to a 
<abbr>SQL</abbr> database</td></tr>
+     *   <tr><td>{@code "WKT"}</td>         <td>CRS definition in Well-Known 
Text format</td></tr>
+     *   <tr><td>{@code "World file"}</td>  <td>World File image read through 
Java Image I/O</td></tr>
+     *   <tr><td>{@code "XML"}</td>         <td>Metadata in <abbr>GML</abbr> 
format</td></tr>
+     * </table>
+     *
+     * The preferred format is only a hint. If the {@link DataStore} 
identified by {@code preferredFormat}
+     * cannot open the given storage, another data store will be searched as 
with {@link #open(Object)}.
+     * The actual format which has been selected is given by {@code 
DataStore.getProvider().getShortName()}.
+     *
+     * <h4>Example</h4>
+     * If both the {@code org.apache.sis.storage.geotiff} and {@code 
org.apache.sis.storage.gdal} modules
+     * are present on the module-path, then the Apache <abbr>SIS</abbr> 
implementation is used by default
+     * for opening GeoTIFF files. For using <abbr>GDAL</abbr> instead, use 
this method with {@code "GDAL"}
+     * argument value.
+     *
+     * @param  storage          the input object as a URL, file, image input 
stream, <i>etc.</i>.
+     * @param  preferredFormat  identification of the preferred {@code 
DataStore} implementation, or {@code null}.
+     * @return the object to use for reading geospatial data from the given 
storage.
+     * @throws UnsupportedStorageException if no {@link DataStoreProvider} is 
found for the given storage object.
+     * @throws DataStoreException if an error occurred while opening the 
storage in read mode.
+     *
+     * @see DataStore#getProvider()
+     * @see DataStoreProvider#getShortName()
+     *
+     * @since 1.5
+     */
+    public static DataStore open(final Object storage, final String 
preferredFormat)
+            throws UnsupportedStorageException, DataStoreException
+    {
+        Predicate<DataStoreProvider> preferred = null;
+        if (preferredFormat != null) {
+            preferred = new DataStoreFilter(preferredFormat, false);
+        }
+        return DataStoreRegistry.INSTANCE.open(storage, Capability.READ, 
preferred);
+    }
+
     /**
      * Creates a {@link DataStore} capable to write or update the given 
storage.
      * The {@code storage} argument can be any of the types documented in 
{@link #open(Object)}.
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/DataStoreFilter.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/DataStoreFilter.java
index a4639d0c6c..9b86a20d75 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/DataStoreFilter.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/DataStoreFilter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.storage.image;
 
+import java.util.Objects;
 import java.util.function.Predicate;
 import javax.imageio.ImageIO;
 import org.apache.sis.util.ArraysExt;
@@ -57,7 +58,7 @@ public final class DataStoreFilter implements 
Predicate<DataStoreProvider> {
      * Creates a new filter for the given data store name.
      *
      * @param  preferred  name of the data store to search, or Image I/O 
format name.
-     * @param  writer     whether to search among writers intead of readers.
+     * @param  writer     whether to search among writers instead of readers.
      */
     public DataStoreFilter(final String preferred, final boolean writer) {
         this.preferred = preferred;
@@ -84,13 +85,15 @@ public final class DataStoreFilter implements 
Predicate<DataStoreProvider> {
      */
     @Override
     public boolean test(final DataStoreProvider candidate) {
-        final String formatName = StoreUtilities.getFormatName(candidate);
-        if (CharSequences.equalsFiltered(formatName, preferred, 
Characters.Filter.UNICODE_IDENTIFIER, true)) {
-            return true;
-        }
-        if (WorldFileStoreProvider.NAME.equals(formatName)) {
-            String[] formats = writer ? ImageIO.getWriterFormatNames() : 
ImageIO.getReaderFormatNames();
-            return ArraysExt.containsIgnoreCase(formats, preferred);
+        if (other == null || other.test(candidate)) {
+            final String formatName = StoreUtilities.getFormatName(candidate);
+            if (CharSequences.equalsFiltered(formatName, preferred, 
Characters.Filter.UNICODE_IDENTIFIER, true)) {
+                return true;
+            }
+            if (WorldFileStoreProvider.NAME.equals(formatName)) {
+                String[] formats = writer ? ImageIO.getWriterFormatNames() : 
ImageIO.getReaderFormatNames();
+                return ArraysExt.containsIgnoreCase(formats, preferred);
+            }
         }
         return false;
     }
@@ -102,6 +105,6 @@ public final class DataStoreFilter implements 
Predicate<DataStoreProvider> {
      */
     @Override
     public Predicate<DataStoreProvider> and(Predicate<? super 
DataStoreProvider> other) {
-        return new DataStoreFilter(this, other);
+        return new DataStoreFilter(this, Objects.requireNonNull(other));
     }
 }

Reply via email to