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 c82e6ab  TileMatrix : add TileMatrixSet API
c82e6ab is described below

commit c82e6abffa0deb6b4e8dbd6d54b3456073bfb09d
Author: jsorel <johann.so...@geomatys.com>
AuthorDate: Tue Mar 8 17:33:49 2022 +0100

    TileMatrix : add TileMatrixSet API
---
 .../sis/storage/IncompatibleResourceException.java |  59 +++++++++
 .../java/org/apache/sis/storage/tiling/Tile.java   |  93 +++++++++++++
 .../org/apache/sis/storage/tiling/TileMatrix.java  | 145 +++++++++++++++++++++
 .../apache/sis/storage/tiling/TileMatrixSet.java   |  91 +++++++++++++
 .../org/apache/sis/storage/tiling/TileStatus.java  |  69 ++++++++++
 .../apache/sis/storage/tiling/TiledResource.java   |  52 ++++++++
 .../sis/storage/tiling/WritableTileMatrix.java     |  61 +++++++++
 .../sis/storage/tiling/WritableTileMatrixSet.java  |  84 ++++++++++++
 .../sis/storage/tiling/WritableTiledResource.java  |  76 +++++++++++
 .../apache/sis/storage/tiling/package-info.java    |  75 +++++++++++
 10 files changed, 805 insertions(+)

diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/IncompatibleResourceException.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/IncompatibleResourceException.java
new file mode 100644
index 0000000..717762e
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/IncompatibleResourceException.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage;
+
+
+/**
+ * Thrown when a write operation can not be performed because the resource to 
write
+ * is incompatible with the data store.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public class IncompatibleResourceException extends DataStoreException {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -1833794980891065300L;
+
+    /**
+     * Creates an exception with no cause and no details message.
+     */
+    public IncompatibleResourceException() {
+    }
+
+    /**
+     * Creates an exception with the specified details message.
+     *
+     * @param message  the detail message.
+     */
+    public IncompatibleResourceException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates an exception with the specified details message and cause.
+     *
+     * @param message  the detail message.
+     * @param cause    the cause for this exception.
+     */
+    public IncompatibleResourceException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/Tile.java 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/Tile.java
new file mode 100644
index 0000000..c131cae
--- /dev/null
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/Tile.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.storage.Resource;
+
+
+/**
+ * A small hyper-rectangular representation of data which is part of a tiling 
scheme.
+ * A tile is uniquely defined in a tile matrix by an integer index in each 
dimension.
+ * Tiles can be a coverage subsets, or a feature based representation (e.g. 
vector tiles).
+ *
+ * <p>All methods in this interface return non-null values.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ *
+ * @see TileMatrix#getTiles(GridExtent, boolean)
+ *
+ * @since 1.2
+ * @module
+ */
+public interface Tile {
+    /**
+     * Returns the indices of this tile in the {@code TileMatrix}.
+     * If this tile was obtained by a call to {@link 
TileMatrix#getTile(long...)},
+     * then the returned array contains the indices that were given in that 
call.
+     *
+     * <p>The returned array contains coordinates in the space defined by
+     * the {@linkplain GridGeometry#getExtent() extent} of
+     * the {@linkplain TileMatrix#getTilingScheme() tiling scheme}.
+     * As such, it complies with the following constraints:</p>
+     * <ul>
+     *   <li>The array length is equal to {@link 
GridExtent#getDimension()}.</li>
+     *   <li>The axis order — usually (<var>column</var>, <var>row/</var>) — 
is the
+     *       {@linkplain GridExtent#getAxisType(int) extent axis} order.</li>
+     *   <li>Values are between the {@linkplain GridExtent#getLow(int) extent 
low}
+     *       and {@linkplain GridExtent#getHigh(int) high} values, 
inclusive.</li>
+     * </ul>
+     *
+     * @return indices of this tile in the {@link TileMatrix},
+     *         as coordinates inside the matrix {@link GridExtent}.
+     *
+     * @see TileMatrix#getTile(long...)
+     */
+    long[] getIndices();
+
+    /**
+     * Returns information about whether the tile failed to load.
+     * The return value can be {@link TileStatus#EXISTS} or {@link 
TileStatus#IN_ERROR};
+     * other enumeration values should not happen after a user successfully 
obtained this {@code Tile} instance.
+     *
+     * <h4>State transition</h4>
+     * {@link TileStatus#EXISTS} is not a guarantee that a call to {@link 
#getResource()} will succeed.
+     * The error may be detected only during the first attempt to read the 
resource.
+     * Consequently this method may initially return {@code EXISTS},
+     * then return {@code IN_ERROR} later after the first read attempt.
+     *
+     * @return information about the availability of this tile.
+     *
+     * @see TileMatrix#getTileStatus(long...)
+     */
+    TileStatus getStatus();
+
+    /**
+     * Returns the tile content as a resource.
+     * The resource type is typically {@link GridCoverageResource},
+     * but it may also be other types (e.g. vector tiles).
+     *
+     * @return the tile content.
+     * @throws DataStoreException if an error occurred while reading the 
content.
+     */
+    Resource getResource() throws DataStoreException;
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileMatrix.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileMatrix.java
new file mode 100644
index 0000000..6598b5f
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileMatrix.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.NoSuchDataException;
+import org.opengis.referencing.datum.PixelInCell;
+import org.opengis.util.GenericName;
+
+
+/**
+ * A collection of tiles with the same size and properties placed on a regular 
grid with no overlapping.
+ * A tile matrix usually has 2 dimensions (width and height), but this API 
allows any number of dimensions.
+ * The number of dimensions is given by {@code 
getTilingScheme().getDimension()}.
+ *
+ * <p>Unless otherwise specified in the Javadoc,
+ * all methods in this interface expect non-null arguments are return non-null 
values.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public interface TileMatrix {
+    /**
+     * Returns an alphanumeric identifier which is unique in the {@link 
TileMatrixSet} that contains
+     * this {@code TileMatrix}. The identifier is often a zoom level (as a 
number encoded in ASCII),
+     * but this is not mandatory.
+     *
+     * @return a unique (within {@link TileMatrixSet}) identifier.
+     */
+    GenericName getIdentifier();
+
+    /**
+     * Returns a description about how space is partitioned into individual 
tiled units.
+     * The description contains the extent of valid tile indices, the spatial 
reference system,
+     * and the conversion from tile indices to the spatial reference system 
coordinates.
+     * The CRS <em>shall</em> be the same as {@link 
TileMatrixSet#getCoordinateReferenceSystem()}.
+     * The "grid to CRS" transform <em>should</em> be defined and 
<em>should</em> be affine.
+     * The grid geometry <em>shall</em> have a {@link GridExtent} which gives 
the range of valid indices
+     * that can be used in calls to {@link #getTile(long...)} and {@link 
#getTileStatus(long...)} methods.
+     *
+     * <p>The "grid to CRS" transform converts tile indices to "real world" 
coordinates.
+     * This conversion can follow two conventions:</p>
+     *
+     * <ul class="verbose">
+     *   <li>The {@link PixelInCell#CELL_CORNER} convention maps tile indices 
to the extreme corner
+     *       (in the direction of smallest indices) of the bounding box of the 
tile.
+     *       In a two-dimensional space having the usual display axis 
orientations,
+     *       this is the top-left corner of the top-left pixel.</li>
+     *   <li>The {@link PixelInCell#CELL_CENTER} convention maps tile indices 
to the median value
+     *       of the tile bounding box in all dimensions.</li>
+     * </ul>
+     *
+     * <h4>Relationship with OGC specification</h4>
+     * OGC has a more generic definition of <cite>tiling scheme</cite>,
+     * where the scheme specifies which space a uniquely identified tile 
occupies.
+     * Reversely, the tiling scheme makes possible to find which unique 
identifier
+     * corresponds to a space satisfying the geometric properties to be a tile.
+     * In {@code TileMatrix}, the unique identifier of a tile is the sequence 
of
+     * tile indices stored in a {@code long[]} array.
+     * The space occupied by a tile can be computed by the above-cited "grid 
to CRS" transform.
+     * Reversely the tile indices for a given space can be computed by the 
inverse of the "grid to CRS" transform.
+     *
+     * @return extent of valid tile indices (mandatory) and their relationship 
with "real world" coordinates (optional).
+     *
+     * @see TileMatrixSet#getCoordinateReferenceSystem()
+     */
+    GridGeometry getTilingScheme();
+
+    /**
+     * Fetches information about whether a tile exists, is missing or failed 
to load.
+     * The accuracy of a tile status greatly varies with each protocol.
+     * If the returned value is different than {@link TileStatus#UNKNOWN}, 
then:
+     *
+     * <table class="sis">
+     * <caption>Relationship between return value and tile fetching 
behavior}</caption>
+     * <tr><th>Return value</th>                      <th>Consequence</th></tr>
+     * <tr><td>{@link TileStatus#EXISTS}</td>         <td>{@code 
getTile(indices)} should return a non-empty value.</td></tr>
+     * <tr><td>{@link TileStatus#MISSING}</td>        <td>{@code 
getTile(indices)} should return an empty value.</td></tr>
+     * <tr><td>{@link TileStatus#OUTSIDE_EXTENT}</td> <td>{@code 
getTile(indices)} should throw {@link NoSuchDataException}.</td></tr>
+     * <tr><td>{@link TileStatus#IN_ERROR}</td>       <td>{@code 
getTile(indices)} should throw {@link DataStoreException} (or a 
sub-type).</td></tr>
+     * </table>
+     *
+     * @param  indices  indices of the requested tile (may be outside the tile 
matrix extent).
+     * @return information about the availability of the specified tile,
+     *         or {@link TileStatus#OUTSIDE_EXTENT} if the given indices are 
invalid.
+     * @throws DataStoreException if fetching the tile status failed.
+     *
+     * @see Tile#getStatus()
+     */
+    TileStatus getTileStatus(long... indices) throws DataStoreException;
+
+    /**
+     * Gets a tile at the given indices.
+     *
+     * @param  indices  indices of the tile to fetch, as coordinates inside 
the matrix {@link GridExtent}.
+     * @return the tile if it {@linkplain TileStatus#EXISTS exists},
+     *         or an empty value if the tile is {@linkplain TileStatus#MISSING 
missing}.
+     * @throws NoSuchDataException if the given indices are
+     *         {@linkplain TileStatus#OUTSIDE_EXTENT outside the matrix 
extent}.
+     * @throws DataStoreException if fetching the tile failed for another 
reason.
+     */
+    Optional<Tile> getTile(long... indices) throws DataStoreException;
+
+    /**
+     * Retrieves a stream of existing tiles in the specified region. The 
stream contains
+     * the {@linkplain TileStatus#EXISTS existing} tiles that are inside the 
given region
+     * and excludes all {@linkplain TileStatus#MISSING missing} tiles.
+     * If a tile is {@linkplain TileStatus#IN_ERROR in error},
+     * then the stream should nevertheless return a {@link Tile} instance
+     * but its {@link Tile#getResource()} method should throw the exception.
+     *
+     * <p>The {@code parallel} argument specifies whether a parallelized 
stream is desired.
+     * If {@code false}, the stream is guaranteed to be sequential.
+     * If {@code true}, the stream may or may not be parallel;
+     * implementations are free to ignore this argument if they do not support 
parallelism.</p>
+     *
+     * @param  indicesRanges  ranges of tile indices in all dimensions, or 
{@code null} for all tiles.
+     * @param  parallel  {@code true} for a parallel stream (if supported), or 
{@code false} for a sequential stream.
+     * @return stream of tiles, excluding {@linkplain TileStatus#MISSING 
missing} tiles.
+     *         Iteration order of the stream may vary from one implementation 
to another and from one call to another.
+     * @throws DataStoreException if the stream creation failed.
+     */
+    Stream<Tile> getTiles(GridExtent indicesRanges, boolean parallel) throws 
DataStoreException;
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileMatrixSet.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileMatrixSet.java
new file mode 100644
index 0000000..277d9ee
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileMatrixSet.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.util.Optional;
+import java.util.SortedMap;
+import org.opengis.geometry.Envelope;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.util.GenericName;
+
+
+/**
+ * A collection of {@code TileMatrix} in the same CRS but at different scale 
levels.
+ * Each {@code TileMatrix} is optimized for a particular scale and is 
identified by a tile matrix identifier.
+ * Tile matrices usually have 2 dimensions (width and height), but this API 
allows any number of dimensions.
+ * However the number of dimensions must be the same for all tile matrices.
+ *
+ * <p>The {@code TileMatrixSet} concept is derived from OGC standards. The 
same concept is called
+ * <cite>image pyramid</cite> or <cite>resolution levels</cite> in some other 
standards.
+ * Some standards require that all scales must be related by a power of 2,
+ * but {@code TileMatrixSet} does not have this restriction.</p>
+ *
+ * <h2>Tile matrix identification</h2>
+ * Each {@link TileMatrix} in a {@code TileMatrixSet} is identified by a 
{@link GenericName}.
+ * Identifiers can be any character strings.
+ * A common practice is to use zoom levels as identifiers, but this is not 
mandatory.
+ * However tile matrices must be sorted from coarser resolution (highest scale 
denominator)
+ * to most detailed resolution (lowest scale denominator).
+ *
+ * <p>All methods in this interface return non-null values.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public interface TileMatrixSet {
+    /**
+     * Returns an alphanumeric identifier which is unique in the {@link 
TiledResource} that contains
+     * this {@code TileMatrixSet}. A tiled resource may contains more than one 
tile matrix set if the
+     * resource prepared different set of tiles for different CRS.
+     *
+     * @return a unique (within {@link TiledResource}) identifier.
+     */
+    GenericName getIdentifier();
+
+    /**
+     * Returns the coordinate reference system of all {@code TileMatrix} 
instances in this set.
+     * This is the value returned by {@code 
TileMatrix.getTilingScheme().getCoordinateReferenceSystem()}.
+     *
+     * @return the CRS used by all {@code TileMatrix} instances in this set.
+     *
+     * @see TileMatrix#getTilingScheme()
+     */
+    CoordinateReferenceSystem getCoordinateReferenceSystem();
+
+    /**
+     * Returns an envelope that encompasses all {@code TileMatrix} instances 
in this set.
+     * This is the {@linkplain 
org.apache.sis.geometry.GeneralEnvelope#add(Envelope) union}
+     * of all values returned by {@code 
TileMatrix.getTilingScheme().getEnvelope()}.
+     * May be empty if too costly to compute.
+     *
+     * @return the bounding box for all tile matrices in CRS coordinates, if 
available.
+     */
+    Optional<Envelope> getEnvelope();
+
+    /**
+     * Returns all {@link TileMatrix} instances in this set, together with 
their identifiers.
+     * For each value in the map, the associated key is {@link 
TileMatrix#getIdentifier()}.
+     * Entries are sorted from coarser resolution (highest scale denominator) 
to most detailed
+     * resolution (lowest scale denominator).
+     *
+     * @return unmodifiable collection of all {@code TileMatrix} instances 
with their identifiers.
+     */
+    SortedMap<GenericName, ? extends TileMatrix> getTileMatrices();
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileStatus.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileStatus.java
new file mode 100644
index 0000000..d23f14f
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TileStatus.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.io.IOException;
+
+
+/**
+ * Information about the availability of a tile. Some {@link TileMatrix} 
implementations
+ * may not know whether a tile exists or not before the first attempt to read 
that tile.
+ * Consequently a tile status may be initially {@link #UNKNOWN} and transitions
+ * at a later time to a state such as {@link #EXISTS}, {@link #MISSING} or 
{@link #IN_ERROR}.
+ *
+ * @author  Alexis Manin (Geomatys)
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ *
+ * @see Tile#getStatus()
+ * @see TileMatrix#getTileStatus(long...)
+ *
+ * @since 1.2
+ * @module
+ */
+public enum TileStatus {
+    /**
+     * The tile status can not be known unless the tile is read. This value is 
returned
+     * by some {@link TileMatrix} implementations when determining the 
availability of
+     * a tile would require relatively costly I/O operations.
+     */
+    UNKNOWN,
+
+    /**
+     * The tile exists. However this is not a guarantee that no I/O error will 
happen when reading the tile,
+     * neither that the tile will be non-empty. If an I/O error happens at 
tile reading time,
+     * then the tile status should transition from {@code EXISTS} to {@link 
#IN_ERROR}.
+     */
+    EXISTS,
+
+    /**
+     * The tile is flagged as missing. It may happen in regions where no data 
is available.
+     */
+    MISSING,
+
+    /**
+     * The tile for which a status has been requested is outside the {@link 
TileMatrix} extent.
+     */
+    OUTSIDE_EXTENT,
+
+    /**
+     * The tile exists but attempt to read it failed.
+     * It may be because an {@link IOException} occurred while reading the 
tile.
+     */
+    IN_ERROR
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TiledResource.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TiledResource.java
new file mode 100644
index 0000000..fef9de3
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/TiledResource.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.util.Collection;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.Resource;
+
+
+/**
+ * A resource which content can be accessed by smaller chunks called tiles.
+ * The use of {@code TiledResource} is not strictly necessary for efficient 
data loading because
+ * {@code Resource} implementations should automatically take advantage of 
tiling when answering requests.
+ * However clients may use this information for optimizing their loading 
strategy.
+ *
+ * <p>A {@code TiledResource} may contain multiple {@link TileMatrixSet} 
instances,
+ * each one for a different {@link 
org.opengis.referencing.crs.CoordinateReferenceSystem}.
+ * Most format specifications only support a single {@link TileMatrixSet},
+ * but a few ones like WMTS may have several.</p>
+ *
+ * <p>All methods in this interface return non-null values.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public interface TiledResource extends Resource {
+    /**
+     * Returns the collection of all available tile matrix sets in this 
resource.
+     * The returned collection typically contains exactly one instance.
+     *
+     * @return all available {@link TileMatrixSet} instances, or an empty 
collection if none.
+     * @throws DataStoreException if an error occurred while fetching the tile 
matrix sets.
+     */
+    Collection<? extends TileMatrixSet> getTileMatrixSets() throws 
DataStoreException;
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTileMatrix.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTileMatrix.java
new file mode 100644
index 0000000..24d2f65
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTileMatrix.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.util.stream.Stream;
+import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.IncompatibleResourceException;
+import org.apache.sis.storage.ReadOnlyStorageException;
+
+
+/**
+ * A {@code TileMatrix} that can write and delete tiles.
+ *
+ * <p>All methods in this interface expect non-null arguments.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public interface WritableTileMatrix extends TileMatrix {
+    /**
+     * Writes a stream of tiles. The caller must ensure that all tiles are 
compatible
+     * with the {@linkplain #getTilingScheme() tiling scheme} of this tile 
matrix set.
+     * If a tile already exists, it will be overwritten.
+     *
+     * @param  tiles  the tiles to write.
+     * @throws ReadOnlyStorageException if this tile matrix is not writable. 
It may be caused by insufficient credentials.
+     * @throws IncompatibleResourceException if a tile is not compatible with 
the tiling scheme of this tile matrix.
+     * @throws DataStoreException if writing the tiles failed for another 
reason.
+     */
+    void writeTiles(Stream<Tile> tiles) throws DataStoreException;
+
+    /**
+     * Deletes all existing tiles in the given region.
+     * After this method call, the status of all tiles in the given region 
become {@link TileStatus#MISSING}.
+     * Tiles that were already missing are silently ignored.
+     *
+     * @param  indicesRanges  ranges of tile indices in all dimensions, or 
{@code null} for all tiles.
+     * @return number of tiles deleted (i.e. not counting the tiles that were 
already missing).
+     * @throws ReadOnlyStorageException if this tile matrix is not writable. 
It may be caused by insufficient credentials.
+     * @throws DataStoreException if deleting the tile failed for another 
reason.
+     */
+    long deleteTiles(GridExtent indicesRanges) throws DataStoreException;
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTileMatrixSet.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTileMatrixSet.java
new file mode 100644
index 0000000..961b9f2
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTileMatrixSet.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.util.SortedMap;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.IncompatibleResourceException;
+import org.apache.sis.storage.NoSuchDataException;
+import org.apache.sis.storage.ReadOnlyStorageException;
+import org.opengis.util.GenericName;
+
+
+/**
+ * A {@code TileMatrixSet} that can write and delete tile matrices.
+ *
+ * <p>All methods in this interface expect non-null arguments are return 
non-null values.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public interface WritableTileMatrixSet extends TileMatrixSet {
+    /**
+     * Returns all {@link WritableTileMatrix} instances in this set, together 
with their identifiers.
+     * For each value in the map, the associated key is {@link 
WritableTileMatrix#getIdentifier()}.
+     * Entries are sorted from coarser resolution (highest scale denominator)
+     * to most detailed resolution (lowest scale denominator).
+     *
+     * <p>The returned view is unmodifiable but live: creations or removals of 
tile matrices
+     * in this set will be reflected on the returned map.</p>
+     *
+     * @return an unmodifiable view of all {@code WritableTileMatrix} 
instances with their identifiers.
+     */
+    @Override
+    SortedMap<GenericName, ? extends WritableTileMatrix> getTileMatrices();
+
+    /**
+     * Adds the given tile matrix to this set and returns a writable instance 
for later completion.
+     * Typically the given {@link TileMatrix} instance contains no tile and is 
used only as a template.
+     * If the {@code TileMatrix} is not empty, then the tiles that it contains 
are written immediately.
+     *
+     * <p>The {@linkplain TileMatrix#getTilingScheme() tiling scheme} of the 
given tile matrix must
+     * be compatible with this set. In particular, it must use the same CRS 
than the value returned
+     * by {@link #getCoordinateReferenceSystem()}. If not, an {@link 
IncompatibleResourceException}
+     * is thrown.</p>
+     *
+     * <p>This method returns a writable tile matrix with the same tiles than 
the given {@code TileMatrix}.
+     * However the identifier of the returned tile matrix may be different.</p>
+     *
+     * @param  tiles  the (potentially empty) tile matrix to create.
+     * @return a writable tile matrix to use for adding more tiles.
+     * @throws ReadOnlyStorageException if this tile matrix set is not 
writable. It may be caused by insufficient credentials.
+     * @throws IncompatibleResourceException if the tiling scheme of the given 
tile matrix is not compatible with this set.
+     * @throws DataStoreException if creating the tile matrix failed for 
another reason.
+     */
+    WritableTileMatrix createTileMatrix(TileMatrix tiles) throws 
DataStoreException;
+
+    /**
+     * Deletes a {@code TileMatrix} identified by the given name. The given 
identifier shall be the
+     * <code>{@linkplain TileMatrix#getIdentifier()}.toString()</code> value 
of the tile matrix to delete.
+     *
+     * @param  identifier  identifier of the {@link TileMatrix} to delete.
+     * @throws NoSuchDataException if there is no tile matrix associated to 
the given identifier in this set.
+     * @throws ReadOnlyStorageException if this tile matrix set is not 
writable. It may be caused by insufficient credentials.
+     * @throws DataStoreException if deleting the tile matrix failed for 
another reason.
+     */
+    void deleteTileMatrix(String identifier) throws DataStoreException;
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTiledResource.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTiledResource.java
new file mode 100644
index 0000000..b4d95ab
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/WritableTiledResource.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.tiling;
+
+import java.util.Collection;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.IncompatibleResourceException;
+import org.apache.sis.storage.NoSuchDataException;
+import org.apache.sis.storage.ReadOnlyStorageException;
+
+
+/**
+ * A {@code TiledResource} that can write and delete tile matrix sets.
+ *
+ * <p>All methods in this interface expect non-null arguments are return 
non-null values.</p>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public interface WritableTiledResource extends TiledResource {
+    /**
+     * Returns the collection of all available tile matrix sets in this 
resource.
+     * The returned collection is unmodifiable but live: additions or removals 
of
+     * tile matrix sets in this resource are reflected in the returned 
collection.
+     *
+     * @return an unmodifiable view of all {@link TileMatrixSet} instances in 
this resource.
+     * @throws DataStoreException if an error occurred while fetching the tile 
matrix sets.
+     */
+    @Override
+    Collection<? extends WritableTileMatrixSet> getTileMatrixSets() throws 
DataStoreException;
+
+    /**
+     * Adds the given tile matrix set to this resource and returns a writable 
instance for later completion.
+     * Typically the given {@link TileMatrixSet} instance contains no tile and 
is used only as a template.
+     * If the {@code TileMatrixSet} is not empty, then the tiles that it 
contains are written immediately.
+     *
+     * <p>This method returns a writable tile matrix set with the same tiles 
than the given {@code TileMatrixSet}.
+     * The identifier and the envelope of the returned set may be different, 
but the CRS and tiling scheme shall
+     * be equivalent with a tolerance for rounding errors.</p>
+     *
+     * @param  tiles  the (potentially empty) tile matrix set to create.
+     * @return a writable tile matrix set to use for adding more tiles.
+     * @throws ReadOnlyStorageException if this resource is not writable. It 
may be caused by insufficient credentials.
+     * @throws IncompatibleResourceException if the given tile matrix set is 
incompatible with this resource.
+     * @throws DataStoreException if creating the tile matrix set failed for 
another reason.
+     */
+    WritableTileMatrixSet createTileMatrixSet(TileMatrixSet tiles) throws 
DataStoreException;
+
+    /**
+     * Deletes a {@code TileMatrixSet} identified by the given name. The given 
identifier shall be the
+     * <code>{@linkplain TileMatrixSet#getIdentifier()}.toString()</code> 
value of the set to delete.
+     *
+     * @param  identifier  identifier of the {@link TileMatrixSet} to delete.
+     * @throws NoSuchDataException if there is no tile matrix set associated 
to the given identifier in this resource.
+     * @throws ReadOnlyStorageException if this resource is not writable. It 
may be caused by insufficient credentials.
+     * @throws DataStoreException if deleting the tile matrix set failed for 
another reason.
+     */
+    void removeTileMatrixSet(String identifier) throws DataStoreException;
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/package-info.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/package-info.java
new file mode 100644
index 0000000..7e1fe91
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/storage/tiling/package-info.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Base types for retrieving and saving tiles in resources.
+ * A {@link TiledResource} if a resource capable to describe its tiling 
schemes as {@link TileMatrixSet} instances.
+ * A {@link TileMatrixSet} is a collection of {@link TileMatrix} instances in 
the same CRS but at different scale levels.
+ * A {@link TileMatrix} is a collection of {@link Tile} instances with the 
same size and properties placed on a regular grid with no overlapping.
+ * The "tile" word is used because of its wide usage with two-dimensional 
data, but actually this package has no restriction
+ * on the number of dimensions and can work with multi-dimensional "tiles" as 
well.
+ *
+ * <h2>References</h2>
+ * <ul>
+ *   <li><a href="https://www.ogc.org/standards/tms";>OGC Two Dimensional Tile 
Matrix Set</a> — the core standard used in this package.</li>
+ *   <li><a href="https://www.ogc.org/standards/wmts";>OGC Web Map Tile Service 
(WMTS)</a> — a common use of above standard.</li>
+ *   <li><a 
href="https://docs.opengeospatial.org/is/17-066r1/17-066r1.html";>OGC 
Geopackage: Extension for Tiled Gridded Coverage Data</a> — another common 
use.</li>
+ *   <li><a href="https://docs.ogc.org/per/18-074.html";>OGC Geopackage: 
Extension for vector tiles</a> — experimental work for tiled geometries.</li>
+ * </ul>
+ *
+ * The concepts developed in above references are also used, often with 
different names, by other projects such as
+ * <a href="https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification";>OSGeo 
Tile Map Service Specification</a>,
+ * <a href="https://github.com/CesiumGS/quantized-mesh";>Cesium 
QuantizedMesh</a>,
+ * <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames";>Open 
Street Map: Slippy Map</a>,
+ * <a 
href="https://developers.google.com/maps/documentation/javascript/coordinates";>Google
 Map</a> and
+ * <a href="https://docs.mapbox.com/mapbox-tiling-service/guides/";>MapBox 
Tiling service</a>.
+ *
+ *
+ * <h2>Relationship with OGC specifications</h2>
+ * The {@code TileMatrix} and {@code TileMatrixSet} class names are reused as 
defined by OGC.
+ * The "2D" suffix in class names is omitted because this package is fully 
multi-dimensional.
+ * The concept of "tiling scheme" is encapsulated in a {@link 
org.apache.sis.coverage.grid.GridGeometry}.
+ *
+ * <h3>Departures with OGC specifications</h3>
+ * The OGC {@code TileMatrixLimits} class is replaced by {@link 
org.apache.sis.coverage.grid.GridExtent}.
+ * The OGC restriction against negative numbers is removed (Apache SIS accepts 
negative tile indices).
+ * The <var>tile span</var> and <var>tile matrix min/max</var> coefficients 
are replaced by a more generic
+ * "grid to CRS" {@link org.opengis.referencing.operation.MathTransform}, 
usually affine but not necessarily.
+ * Users may need to enforce above OGC restrictions themselves if 
compatibility with OGC specification is desired).
+ *
+ *
+ * <h2>Relationship with Java2D rendered image</h2>
+ * OGC tiles can be mapped to {@linkplain 
java.awt.image.RenderedImage#getTile(int, int) Java2D tiles}
+ * with the following restrictions:
+ *
+ * <ul>
+ *   <li>Java2D tile indices and pixel indices are 32 bits integer instead of 
64 bits.
+ *       See {@linkplain org.apache.sis.coverage.grid.GridCoverage#render grid 
coverage render}
+ *       (in particular the relative pixel coordinates) for the workaround 
applied in Apache SIS.</li>
+ *   <li>Java2D does not support coalescence coefficient (used in OGC tiles 
for compensating distortions near poles).
+ *       Tiles in Java2D are expanded as needed as if the {@code TileMatrix} 
had no coalescence.</li>
+ * </ul>
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Alexis Manin (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+package org.apache.sis.storage.tiling;

Reply via email to