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 <[email protected]>
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;