sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/15: Remove sis-javafx, sis-raster and sis-shapefile modules from 0.8 branch.
Date Thu, 21 Jun 2018 09:19:41 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to tag 0.8
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 93dba40c901364abf71a2bc1f350c98048de0f99
Author: Martin Desruisseaux <desruisseaux@apache.org>
AuthorDate: Mon Oct 30 10:16:02 2017 +0000

    Remove sis-javafx, sis-raster and sis-shapefile modules from 0.8 branch.
    
    
    git-svn-id: https://svn.apache.org/repos/asf/sis/branches/0.8@1813745 13f79535-47bb-0310-9956-ffa450edef68
---
 application/sis-javafx/pom.xml                     |   93 --
 .../java/org/apache/sis/gui/ClientApplication.java |   46 -
 core/pom.xml                                       |    1 -
 core/sis-raster/pom.xml                            |  118 --
 .../java/org/apache/sis/image/DefaultIterator.java |  615 ---------
 .../java/org/apache/sis/image/PixelIterator.java   |  610 ---------
 .../java/org/apache/sis/image/TransferType.java    |  164 ---
 .../apache/sis/image/WritablePixelIterator.java    |  244 ----
 .../java/org/apache/sis/image/package-info.java    |   41 -
 .../org/apache/sis/internal/raster/Resources.java  |  170 ---
 .../sis/internal/raster/Resources.properties       |   28 -
 .../sis/internal/raster/Resources_fr.properties    |   33 -
 .../apache/sis/internal/raster/package-info.java   |   31 -
 .../org/apache/sis/image/DefaultIteratorTest.java  | 1135 -----------------
 .../test/java/org/apache/sis/image/TiledImage.java |  275 -----
 .../org/apache/sis/test/suite/RasterTestSuite.java |   45 -
 .../org/apache/sis/test/suite/package-info.txt     |    3 -
 ide-project/NetBeans/build.xml                     |   14 -
 ide-project/NetBeans/nbproject/build-impl.xml      |   60 +-
 ide-project/NetBeans/nbproject/genfiles.properties |    4 +-
 ide-project/NetBeans/nbproject/project.properties  |    4 -
 ide-project/NetBeans/nbproject/project.xml         |    4 -
 storage/pom.xml                                    |    1 -
 storage/sis-shapefile/pom.xml                      |  131 --
 .../apache/sis/internal/shapefile/AutoChecker.java |  185 ---
 ...nvalidRecordNumberForDirectAccessException.java |   65 -
 .../SQLNoDirectAccessAvailableException.java       |   50 -
 .../shapefile/SQLShapefileNotFoundException.java   |   50 -
 .../internal/shapefile/ShapefileByteReader.java    |  466 -------
 .../internal/shapefile/ShapefileDescriptor.java    |  201 ---
 .../shapefile/jdbc/AbstractDbase3ByteReader.java   |  283 -----
 .../sis/internal/shapefile/jdbc/AbstractJDBC.java  |  162 ---
 .../internal/shapefile/jdbc/CommonByteReader.java  |  132 --
 .../sis/internal/shapefile/jdbc/DBFDriver.java     |  145 ---
 .../shapefile/jdbc/DBase3FieldDescriptor.java      |  153 ---
 .../sis/internal/shapefile/jdbc/DBaseDataType.java |  103 --
 .../internal/shapefile/jdbc/Dbase3ByteReader.java  |  130 --
 .../internal/shapefile/jdbc/MappedByteReader.java  |  312 -----
 .../jdbc/SQLConnectionClosedException.java         |   63 -
 .../jdbc/SQLDbaseFileNotFoundException.java        |   50 -
 .../jdbc/SQLInvalidDbaseFileFormatException.java   |   50 -
 .../jdbc/connection/AbstractConnection.java        |  418 -------
 .../shapefile/jdbc/connection/DBFConnection.java   |  335 -----
 .../connection/SQLClosingIOFailureException.java   |   63 -
 .../shapefile/jdbc/connection/package-info.java    |   19 -
 .../jdbc/metadata/AbstractDatabaseMetaData.java    |  202 ---
 .../jdbc/metadata/DBFDatabaseMetaData.java         | 1300 --------------------
 .../jdbc/metadata/DBFResultSetMataData.java        |  473 -------
 .../shapefile/jdbc/metadata/package-info.java      |   21 -
 .../sis/internal/shapefile/jdbc/package-info.java  |   26 -
 .../jdbc/resultset/AbstractResultSet.java          |  707 -----------
 .../jdbc/resultset/BuiltInMemoryResultSet.java     |  196 ---
 ...iltInMemoryResultSetForCatalogNamesListing.java |   51 -
 ...DBFBuiltInMemoryResultSetForColumnsListing.java |  460 -------
 .../DBFBuiltInMemoryResultSetForSchemaListing.java |   51 -
 .../DBFBuiltInMemoryResultSetForTablesListing.java |   88 --
 ...uiltInMemoryResultSetForTablesTypesListing.java |   74 --
 .../jdbc/resultset/DBFRecordBasedResultSet.java    |  632 ----------
 .../shapefile/jdbc/resultset/DBFResultSet.java     |  965 ---------------
 .../resultset/SQLIllegalColumnIndexException.java  |   76 --
 .../jdbc/resultset/SQLNoResultException.java       |   63 -
 .../jdbc/resultset/SQLNoSuchFieldException.java    |   76 --
 .../jdbc/resultset/SQLNotDateException.java        |   89 --
 .../jdbc/resultset/SQLNotNumericException.java     |   89 --
 .../shapefile/jdbc/resultset/package-info.java     |   21 -
 .../shapefile/jdbc/sql/ClauseResolver.java         |  382 ------
 .../jdbc/sql/ConditionalClauseResolver.java        |   38 -
 .../shapefile/jdbc/sql/CrudeSQLParser.java         |  137 ---
 .../jdbc/sql/SQLIllegalParameterException.java     |   89 --
 .../jdbc/sql/SQLInvalidStatementException.java     |   63 -
 .../sql/SQLUnsupportedParsingFeatureException.java |   63 -
 .../internal/shapefile/jdbc/sql/package-info.java  |   20 -
 .../jdbc/statement/AbstractStatement.java          |  308 -----
 .../shapefile/jdbc/statement/DBFStatement.java     |  243 ----
 .../shapefile/jdbc/statement/package-info.java     |   19 -
 .../sis/internal/shapefile/package-info.java       |   25 -
 .../storage/shapefile/DataStoreQueryException.java |   50 -
 .../shapefile/DataStoreQueryResultException.java   |   50 -
 .../shapefile/DbaseFileNotFoundException.java      |   50 -
 .../sis/storage/shapefile/InputFeatureStream.java  |  373 ------
 .../shapefile/InvalidDbaseFileFormatException.java |   32 -
 .../shapefile/InvalidShapefileFormatException.java |   49 -
 .../apache/sis/storage/shapefile/ShapeFile.java    |  207 ----
 .../sis/storage/shapefile/ShapeTypeEnum.java       |   74 --
 .../shapefile/ShapefileNotFoundException.java      |   50 -
 .../apache/sis/storage/shapefile/package-info.java |   27 -
 .../shapefile/ShapefileByteReader.properties       |   36 -
 .../shapefile/ShapefileByteReader_fr.properties    |   36 -
 .../jdbc/AbstractDbase3ByteReader.properties       |   14 -
 .../jdbc/AbstractDbase3ByteReader_fr.properties    |   14 -
 .../shapefile/jdbc/AbstractJDBC.properties         |   23 -
 .../shapefile/jdbc/AbstractJDBC_fr.properties      |    1 -
 .../shapefile/jdbc/CommonByteReader.properties     |    3 -
 .../jdbc/DBase3FieldDescriptor.properties          |    7 -
 .../jdbc/DBase3FieldDescriptor_fr.properties       |    1 -
 .../shapefile/jdbc/MappedByteReader.properties     |   30 -
 .../shapefile/jdbc/MappedByteReader_fr.properties  |   30 -
 .../jdbc/connection/AbstractConnection.properties  |    6 -
 .../connection/AbstractConnection_fr.properties    |    6 -
 .../jdbc/connection/DBFConnection.properties       |   49 -
 .../jdbc/connection/DBFConnection_fr.properties    |   39 -
 .../jdbc/metadata/DBFResultSetMataData.properties  |   14 -
 .../metadata/DBFResultSetMataData_fr.properties    |    4 -
 .../jdbc/resultset/AbstractResultSet.properties    |    1 -
 .../jdbc/resultset/AbstractResultSet_fr.properties |    1 -
 ...ltInMemoryResultSetForColumnsListing.properties |    8 -
 ...nMemoryResultSetForColumnsListing_fr.properties |    8 -
 ...iltInMemoryResultSetForTablesListing.properties |    2 -
 ...MemoryResultSetForTablesTypesListing.properties |    2 -
 .../resultset/DBFRecordBasedResultSet.properties   |   28 -
 .../DBFRecordBasedResultSet_fr.properties          |   28 -
 .../jdbc/resultset/DBFResultSet.properties         |   10 -
 .../jdbc/resultset/DBFResultSet_fr.properties      |    4 -
 .../shapefile/jdbc/sql/ClauseResolver.properties   |   25 -
 .../jdbc/sql/ClauseResolver_fr.properties          |   16 -
 .../shapefile/jdbc/sql/CrudeSQLParser.properties   |   12 -
 .../jdbc/statement/DBFStatement.properties         |   22 -
 .../jdbc/statement/DBFStatement_fr.properties      |   12 -
 .../shapefile/InputFeatureStream.properties        |    9 -
 .../shapefile/InputFeatureStream_fr.properties     |    9 -
 .../jdbc/AbstractTestBaseForInternalJDBC.java      |   68 -
 .../internal/shapefile/jdbc/DBFConnectionTest.java |   92 --
 .../internal/shapefile/jdbc/DBFResultSetTest.java  |  205 ---
 .../internal/shapefile/jdbc/DBFStatementTest.java  |   97 --
 .../apache/sis/internal/shapefile/jdbc/readme.txt  |   58 -
 .../shapefile/jdbc/sql/WhereClauseTest.java        |  155 ---
 .../sis/storage/shapefile/ShapeFileTest.java       |  205 ---
 .../apache/sis/test/suite/ShapefileTestSuite.java  |   44 -
 .../org/apache/sis/test/suite/package-info.txt     |    3 -
 .../shapefile/ABRALicenseePt_4326_clipped.dbf      |  Bin 5861 -> 0 bytes
 .../shapefile/ABRALicenseePt_4326_clipped.prj      |    1 -
 .../shapefile/ABRALicenseePt_4326_clipped.shp      |  Bin 184 -> 0 bytes
 .../shapefile/ABRALicenseePt_4326_clipped.shx      |  Bin 124 -> 0 bytes
 .../org/apache/sis/storage/shapefile/NOTES.md      |   12 -
 .../shapefile/SignedBikeRoute_4326_clipped.dbf     |  Bin 7363 -> 0 bytes
 .../shapefile/SignedBikeRoute_4326_clipped.prj     |    1 -
 .../shapefile/SignedBikeRoute_4326_clipped.shp     |  Bin 1148 -> 0 bytes
 .../shapefile/SignedBikeRoute_4326_clipped.shx     |  Bin 148 -> 0 bytes
 138 files changed, 10 insertions(+), 16755 deletions(-)

diff --git a/application/sis-javafx/pom.xml b/application/sis-javafx/pom.xml
deleted file mode 100644
index c434029..0000000
--- a/application/sis-javafx/pom.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-  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.
--->
-
-<project xmlns              = "http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
-                               http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.apache.sis</groupId>
-    <artifactId>application</artifactId>
-    <version>0.8-SNAPSHOT</version>
-  </parent>
-
-
-  <!-- ===========================================================
-           Module Description
-       =========================================================== -->
-  <groupId>org.apache.sis.application</groupId>
-  <artifactId>sis-javafx</artifactId>
-  <packaging>bundle</packaging>
-  <name>Apache SIS application for JavaFX</name>
-  <description>
-  <!-- Left alignment because this description will be copied in META-INF/MANIFEST.MF
-       The leading space after the first line is necessary for proper formatting. -->
-Client application for JavaFX.
-  </description>
-
-
-  <!-- ===========================================================
-           Developers and Contributors
-       =========================================================== -->
-  <developers>
-    <developer>
-      <name>Roshan Lakmal</name>
-      <roles>
-        <role>developer</role>
-      </roles>
-    </developer>
-  </developers>
-
-
-  <!-- ===========================================================
-           Build configuration
-       =========================================================== -->
-  <build>
-    <plugins>
-
-      <!-- Package as OSGi bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>org.apache.sis.gui</Bundle-SymbolicName>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-
-  <!-- ===========================================================
-           Dependencies
-       =========================================================== -->
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.sis.core</groupId>
-      <artifactId>sis-metadata</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-  </dependencies>
-
-</project>
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/ClientApplication.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/ClientApplication.java
deleted file mode 100644
index b5f7d55..0000000
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/ClientApplication.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.gui;
-
-import javafx.application.Application;
-import javafx.stage.Stage;
-
-
-/**
- * The starting point of SIS application for JavaFX.
- *
- * @author  Roshan Lakmal
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class ClientApplication extends Application {
-    /**
-     * Creates a new SIS application.
-     */
-    public ClientApplication() {
-    }
-
-    /**
-     * Creates and show the Graphical User Interface (GUI).
-     *
-     * @param stage The window where to display the GUI.
-     */
-    @Override
-    public void start(final Stage stage) {
-    }
-}
diff --git a/core/pom.xml b/core/pom.xml
index a747cef..30a5c31 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -192,7 +192,6 @@
     <module>sis-referencing</module>
     <module>sis-referencing-by-identifiers</module>
     <module>sis-feature</module>
-    <module>sis-raster</module>
   </modules>
 
 </project>
diff --git a/core/sis-raster/pom.xml b/core/sis-raster/pom.xml
deleted file mode 100644
index ec566f5..0000000
--- a/core/sis-raster/pom.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-  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.
--->
-
-<project xmlns              = "http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
-                               http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.apache.sis</groupId>
-    <artifactId>core</artifactId>
-    <version>0.8-SNAPSHOT</version>
-  </parent>
-
-
-  <!-- ===========================================================
-           Module Description
-       =========================================================== -->
-  <groupId>org.apache.sis.core</groupId>
-  <artifactId>sis-raster</artifactId>
-  <packaging>bundle</packaging>
-  <name>Apache SIS rasters</name>
-  <description>
-  <!-- Left alignment because this description will be copied in META-INF/MANIFEST.MF
-       The leading space after the first line is necessary for proper formatting. -->
-Access to raster data.
-  </description>
-
-
-  <!-- ===========================================================
-           Developers and Contributors
-       =========================================================== -->
-  <developers>
-    <developer>
-      <name>Martin Desruisseaux</name>
-      <id>desruisseaux</id>
-      <email>desruisseaux@apache.org</email>
-      <organization>Geomatys</organization>
-      <organizationUrl>http://www.geomatys.com</organizationUrl>
-      <timezone>+1</timezone>
-      <roles>
-        <role>developer</role>
-      </roles>
-    </developer>
-    <developer>
-      <name>Rémi Maréchal</name>
-      <id>rmarechal</id>
-      <email>rmarechal@apache.org</email>
-      <organization>Geomatys</organization>
-      <organizationUrl>http://www.geomatys.com</organizationUrl>
-      <timezone>+1</timezone>
-      <roles>
-        <role>developer</role>
-      </roles>
-   </developer>
-  </developers>
-
-
-  <!-- ===========================================================
-           Build configuration
-       =========================================================== -->
-  <build>
-    <plugins>
-
-      <!-- Package as OSGi bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>org.apache.sis.raster</Bundle-SymbolicName>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-
-  <!-- ===========================================================
-           Dependencies
-       =========================================================== -->
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.sis.core</groupId>
-      <artifactId>sis-utility</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-
-    <!-- Test dependencies -->
-    <dependency>
-      <groupId>org.apache.sis.core</groupId>
-      <artifactId>sis-utility</artifactId>
-      <version>${project.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-</project>
diff --git a/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java b/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java
deleted file mode 100644
index 0674138..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * 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.image;
-
-import java.awt.Point;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.image.DataBuffer;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.WritableRaster;
-import java.awt.image.WritableRenderedImage;
-import java.awt.image.RasterFormatException;
-import java.nio.Buffer;
-import java.nio.IntBuffer;
-import java.nio.FloatBuffer;
-import java.nio.DoubleBuffer;
-import org.apache.sis.internal.raster.Resources;
-import org.apache.sis.util.ArgumentChecks;
-
-// Branch-dependent imports
-import org.apache.sis.internal.jdk8.JDK8;
-
-
-/**
- * Default iterator used when no specialized implementation is available.
- * This iterator uses the {@link Raster} API for traversing the pixels in each tile.
- * Calls to {@link #next()} move the current position by increasing the following values, in order:
- *
- * <ol>
- *   <li>Column index in a single tile (from left to right)</li>
- *   <li>Row index in a single tile (from top to bottom).</li>
- *   <li>Then, {@code tileX} index from left to right.</li>
- *   <li>Then, {@code tileY} index from top to bottom.</li>
- * </ol>
- *
- * @author  Rémi Maréchal (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- *
- * @todo Change iteration order on tiles for using Hilbert iterator.
- */
-final class DefaultIterator extends WritablePixelIterator {
-    /**
-     * Tile coordinate of {@link #currentRaster}.
-     */
-    private int tileX, tileY;
-
-    /**
-     * Current column index in current raster.
-     */
-    private int x;
-
-    /**
-     * Current row index in current raster.
-     */
-    private int y;
-
-    /**
-     * Bounds of the region traversed by the iterator in current raster.
-     * When iteration reaches the upper coordinates, the iterator needs to move to next tile.
-     */
-    private int currentLowerX, currentUpperX, currentUpperY;
-
-    /**
-     * Creates an iterator for the given region in the given raster.
-     *
-     * @param  input    the raster which contains the sample values to read.
-     * @param  output   the raster where to write the sample values, or {@code null} for read-only iterator.
-     * @param  subArea  the raster region where to perform the iteration, or {@code null}
-     *                  for iterating over all the raster domain.
-     * @param  window   size of the window to use in {@link #createWindow(TransferType)} method, or {@code null} if none.
-     */
-    DefaultIterator(final Raster input, final WritableRaster output, final Rectangle subArea, final Dimension window) {
-        super(input, output, subArea, window);
-        currentLowerX = lowerX;
-        currentUpperX = upperX;
-        currentUpperY = upperY;
-        x = JDK8.decrementExact(lowerX);        // Set the position before first pixel.
-        y = lowerY;
-    }
-
-    /**
-     * Creates an iterator for the given region in the given image.
-     *
-     * @param  input    the image which contains the sample values to read.
-     * @param  output   the image where to write the sample values, or {@code null} for read-only iterator.
-     * @param  subArea  the image region where to perform the iteration, or {@code null}
-     *                  for iterating over all the image domain.
-     * @param  window   size of the window to use in {@link #createWindow(TransferType)} method, or {@code null} if none.
-     */
-    DefaultIterator(final RenderedImage input, final WritableRenderedImage output, final Rectangle subArea, final Dimension window) {
-        super(input, output, subArea, window);
-        tileX = JDK8.decrementExact(tileLowerX);
-        tileY = tileLowerY;
-        currentLowerX = lowerX;
-        currentUpperX = lowerX;                 // Really 'lower', so the position is the tile before the first tile.
-        currentUpperY = lowerY;
-        x = JDK8.decrementExact(lowerX);        // Set the position before first pixel.
-        y = lowerY;
-    }
-
-    /**
-     * Restores this iterator to the same state it was after construction.
-     */
-    @Override
-    public void rewind() {
-        close();                        // Release current writable raster, if any.
-        if (image == null) {
-            tileX = 0;
-            tileY = 0;
-            currentUpperX = upperX;
-            currentUpperY = upperY;
-        } else {
-            tileX = tileLowerX - 1;     // Note: no need for decrementExact(…) because already checked by constructor.
-            tileY = tileLowerY;
-            currentUpperX = lowerX;     // Really 'lower', so the position is the tile before the first tile.
-            currentUpperY = lowerY;
-        }
-        currentLowerX = lowerX;
-        x = lowerX - 1;                 // Set the position before first pixel.
-        y = lowerY;
-    }
-
-    /**
-     * Returns the column (x) and row (y) indices of the current pixel.
-     *
-     * @return column and row indices of current iterator position.
-     * @throws IllegalStateException if this method is invoked before the first call to {@link #next()}
-     *         or {@link #moveTo(int, int)}, or after {@code next()} returned {@code false}.
-     */
-    @Override
-    public Point getPosition() {
-        final short message;
-        if (x < lowerX) {
-            message = Resources.Keys.IterationNotStarted;
-        } else if (x >= upperX) {
-            message = Resources.Keys.IterationIsFinished;
-        } else {
-            return new Point(x,y);
-        }
-        throw new IllegalStateException(Resources.format(message));
-    }
-
-    /**
-     * Moves the pixel iterator to the given column (x) and row (y) indices.
-     *
-     * @param  px  the column index of the pixel to make current.
-     * @param  py  the row index of the pixel to make current.
-     * @throws IndexOutOfBoundsException if the given indices are outside the iteration domain.
-     */
-    @Override
-    public void moveTo(final int px, final int py) {
-        if (px < lowerX || px >= upperX ||  py < lowerY || py >= upperY) {
-            throw new IndexOutOfBoundsException(Resources.format(Resources.Keys.CoordinateOutsideDomain_2, px, py));
-        }
-        if (image != null) {
-            final int tx = JDK8.floorDiv(px - tileGridXOffset, tileWidth);
-            final int ty = JDK8.floorDiv(py - tileGridYOffset, tileHeight);
-            if (tx != tileX || ty != tileY) {
-                close();                                    // Release current writable raster, if any.
-                tileX = tx;
-                tileY = ty;
-                fetchTile();
-            }
-        }
-        x = px;
-        y = py;
-    }
-
-    /**
-     * Moves the iterator to the next pixel.
-     *
-     * @return {@code true} if the current pixel is valid, or {@code false} if there is no more pixels.
-     * @throws IllegalStateException if this iterator already reached end of iteration in a previous call
-     *         to {@code next()}, and {@link #rewind()} or {@link #moveTo(int,int)} have not been invoked.
-     */
-    @Override
-    public boolean next() {
-        if (++x >= currentUpperX) {
-            if (++y >= currentUpperY) {                     // Strict equality (==) would work, but use >= as a safety.
-                close();                                    // Release current writable raster, if any.
-                if (++tileX >= tileUpperX) {                // Strict equality (==) would work, but use >= as a safety.
-                    tileY = JDK8.incrementExact(tileY);     // 'incrementExact' because 'tileY > tileUpperY' is allowed.
-                    if (tileY >= tileUpperY) {
-                        /*
-                         * Paranoiac safety: keep the x, y and tileX values before their maximal values
-                         * in order to avoid overflow. The 'tileY' value is used for checking if next()
-                         * is invoked again, in order to avoid a common misuse pattern. In principle
-                         * 'tileY' needs to be compared only to 'tileUpperY', but we also compare to
-                         * 'tileLowerY + 1' for handling the empty iterator case.
-                         */
-                        x =  currentUpperX - 1;
-                        y =  currentUpperY - 1;
-                        tileX = tileUpperX - 1;
-                        if (tileY > Math.max(tileUpperY, tileLowerY + 1)) {
-                            throw new IllegalStateException(Resources.format(Resources.Keys.IterationIsFinished));
-                        }
-                        return false;
-                    }
-                    tileX = tileLowerX;
-                }
-                fetchTile();
-            }
-            x = currentLowerX;
-        }
-        return true;
-    }
-
-    /**
-     * Fetches from the image a tile for the current {@link #tileX} and {@link #tileY} coordinates.
-     * All fields prefixed by {@code current} are updated by this method. This method also updates
-     * the {@link #y} field, but caller is responsible for updating the {@link #x} field.
-     */
-    private void fetchTile() {
-        currentRaster = null;
-        if (destination != null) {
-            destRaster = destination.getWritableTile(tileX, tileY);
-            if (destination == image) {
-                currentRaster = destRaster;
-            }
-        }
-        if (currentRaster == null) {
-            currentRaster = image.getTile(tileX, tileY);
-        }
-        final int minX = currentRaster.getMinX();
-        final int minY = currentRaster.getMinY();
-        currentLowerX  = Math.max(lowerX, minX);
-        y              = Math.max(lowerY, minY);
-        currentUpperX  = Math.min(upperX, minX + tileWidth);
-        currentUpperY  = Math.min(upperY, minY + tileHeight);
-        if (currentRaster.getNumBands() != numBands) {
-            throw new RasterFormatException(Resources.format(Resources.Keys.IncompatibleTile_2, tileX, tileY));
-        }
-    }
-
-    /**
-     * Returns the sample value in the specified band of current pixel, rounded toward zero.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public int getSample(final int band) {
-        return currentRaster.getSample(x, y, band);
-    }
-
-    /**
-     * Returns the sample value in the specified band of current pixel as a single-precision floating point number.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public float getSampleFloat(final int band) {
-        return currentRaster.getSampleFloat(x, y, band);
-    }
-
-    /**
-     * Returns the sample value in the specified band of current pixel, without precision lost.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public double getSampleDouble(final int band) {
-        return currentRaster.getSampleDouble(x, y, band);
-    }
-
-    /**
-     * Writes a sample value in the specified band of current pixel.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public void setSample(final int band, final int value) {
-        destRaster.setSample(x, y, band, value);
-    }
-
-    /**
-     * Writes a sample value in the specified band of current pixel.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public void setSample(final int band, final float value) {
-        destRaster.setSample(x, y, band, value);
-    }
-
-    /**
-     * Writes a sample value in the specified band of current pixel.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public void setSample(final int band, final double value) {
-        destRaster.setSample(x, y, band, value);
-    }
-
-    /**
-     * Returns the sample values of current pixel for all bands.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public int[] getPixel​(int[] dest) {
-        return currentRaster.getPixel(x, y, dest);
-    }
-
-    /**
-     * Returns the sample values of current pixel for all bands.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public float[] getPixel​(float[] dest) {
-        return currentRaster.getPixel(x, y, dest);
-    }
-
-    /**
-     * Returns the sample values of current pixel for all bands.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public double[] getPixel​(double[] dest) {
-        return currentRaster.getPixel(x, y, dest);
-    }
-
-    /**
-     * Sets the sample values of current pixel for all bands.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public void setPixel​(int[] dest) {
-        destRaster.setPixel(x, y, dest);
-    }
-
-    /**
-     * Sets the sample values of current pixel for all bands.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public void setPixel​(float[] dest) {
-        destRaster.setPixel(x, y, dest);
-    }
-
-    /**
-     * Sets the sample values of current pixel for all bands.
-     * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-     */
-    @Override
-    public void setPixel​(double[] dest) {
-        destRaster.setPixel(x, y, dest);
-    }
-
-    /**
-     * Returns a moving window over the sample values in a rectangular region starting at iterator position.
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T extends Buffer> Window<T> createWindow(final TransferType<T> type) {
-        ArgumentChecks.ensureNonNull("type", type);
-        final int length = numBands * windowWidth * windowHeight;
-        final int transferLength = length - numBands * Math.min(windowWidth, windowHeight);
-        // 'transfer' will always have at least one row or one column less than 'data'.
-        switch (type.dataBufferType) {
-            case DataBuffer.TYPE_INT:    return (Window<T>) new IntWindow   (new int   [length], new int   [transferLength]);
-            case DataBuffer.TYPE_FLOAT:  return (Window<T>) new FloatWindow (new float [length], new float [transferLength]);
-            case DataBuffer.TYPE_DOUBLE: return (Window<T>) new DoubleWindow(new double[length], new double[transferLength]);
-            default: throw new AssertionError(type);  // Should never happen unless we updated TransferType and forgot to update this method.
-        }
-    }
-
-    /**
-     * The base class of all {@link Window} implementations provided by {@link DefaultIterator}.
-     * This iterator defines a callback method required by {@link DefaultIterator#update(WindowBase, Object)}.
-     *
-     * @todo keep trace of last location and use {@code System#arraycopy(…)} for moving the values that we already have.
-     */
-    private abstract static class WindowBase<T extends Buffer> extends Window<T> {
-        /**
-         * Creates a new window which will store the sample values in the given buffer.
-         */
-        WindowBase(final T buffer) {
-            super(buffer);
-        }
-
-        /**
-         * Returns an array containing all samples for a rectangle of pixels in the given raster, one sample
-         * per array element. Subclasses shall delegate to one of the {@code Raster#getPixels(…)} methods
-         * depending on the buffer data type.
-         *
-         * @param  raster     the raster from which to get the pixel values.
-         * @param  subX       the X coordinate of the upper-left pixel location.
-         * @param  subY       the Y coordinate of the upper-left pixel location.
-         * @param  subWidth   width of the pixel rectangle.
-         * @param  subHeight  height of the pixel rectangle.
-         * @param  direct     {@code true} for storing directly in the final array,
-         *                     or {@code false} for using the transfer array.
-         * @return the array in which sample values have been stored.
-         */
-        abstract Object getPixels(Raster raster, int subX, int subY, int subWidth, int subHeight, boolean direct);
-    }
-
-    /**
-     * {@link Window} implementation backed by an array of {@code int[]}.
-     */
-    private final class IntWindow extends WindowBase<IntBuffer> {
-        /**
-         * Sample values in the window ({@code data}) and a temporary array ({@code transfer}).
-         * Those arrays are overwritten when {@link #update()} is invoked.
-         */
-        private final int[] data, transfer;
-
-        /**
-         * Creates a new window which will store the sample values in the given {@code data} array.
-         */
-        IntWindow(final int[] data, final int[] transfer) {
-            super(IntBuffer.wrap(data).asReadOnlyBuffer());
-            this.data = data;
-            this.transfer = transfer;
-        }
-
-        /**
-         * Performs the transfer between the underlying raster and this window.
-         */
-        @Override
-        Object getPixels(Raster raster, int subX, int subY, int subWidth, int subHeight, boolean direct) {
-            return raster.getPixels(subX, subY, subWidth, subHeight, direct ? data : transfer);
-        }
-
-        /**
-         * Updates this window with the sample values in the region starting at current iterator position.
-         * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-         */
-        @Override
-        public void update() {
-            values.clear();
-            DefaultIterator.this.update(this, data);
-        }
-    }
-
-    /**
-     * {@link Window} implementation backed by an array of {@code float[]}.
-     */
-    private final class FloatWindow extends WindowBase<FloatBuffer> {
-        /**
-         * Sample values in the window ({@code data}) and a temporary array ({@code transfer}).
-         * Those arrays are overwritten when {@link #update()} is invoked.
-         */
-        private final float[] data, transfer;
-
-        /**
-         * Creates a new window which will store the sample values in the given {@code data} array.
-         */
-        FloatWindow(final float[] data, final float[] transfer) {
-            super(FloatBuffer.wrap(data).asReadOnlyBuffer());
-            this.data = data;
-            this.transfer = transfer;
-        }
-
-        /**
-         * Performs the transfer between the underlying raster and this window.
-         */
-        @Override
-        Object getPixels(Raster raster, int subX, int subY, int subWidth, int subHeight, boolean direct) {
-            return raster.getPixels(subX, subY, subWidth, subHeight, direct ? data : transfer);
-        }
-
-        /**
-         * Updates this window with the sample values in the region starting at current iterator position.
-         * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-         */
-        @Override
-        public void update() {
-            values.clear();
-            DefaultIterator.this.update(this, data);
-        }
-    }
-
-    /**
-     * {@link Window} implementation backed by an array of {@code double[]}.
-     */
-    private final class DoubleWindow extends WindowBase<DoubleBuffer> {
-        /**
-         * Sample values in the window ({@code data}) and a temporary array ({@code transfer}).
-         * Those arrays are overwritten when {@link #update()} is invoked.
-         */
-        private final double[] data, transfer;
-
-        /**
-         * Creates a new window which will store the sample values in the given {@code data} array.
-         */
-        DoubleWindow(final double[] data, final double[] transfer) {
-            super(DoubleBuffer.wrap(data).asReadOnlyBuffer());
-            this.data = data;
-            this.transfer = transfer;
-        }
-
-        /**
-         * Performs the transfer between the underlying raster and this window.
-         */
-        @Override
-        Object getPixels(Raster raster, int subX, int subY, int subWidth, int subHeight, boolean direct) {
-            return raster.getPixels(subX, subY, subWidth, subHeight, direct ? data : transfer);
-        }
-
-        /**
-         * Updates this window with the sample values in the region starting at current iterator position.
-         * This method assumes that {@link #next()} or {@link #moveTo(int,int)} has been invoked.
-         */
-        @Override
-        public void update() {
-            values.clear();
-            DefaultIterator.this.update(this, data);
-        }
-    }
-
-    /**
-     * Updates the content of given window with the sample values in the region starting at current iterator position.
-     *
-     * @param window  the window to update.
-     * @param data    the array of primitive type where sample values are stored.
-     */
-    @SuppressWarnings("SuspiciousSystemArraycopy")
-    final void update(final WindowBase<?> window, final Object data) {
-        Raster  raster    = currentRaster;
-        int     subEndX   = (raster.getMinX() - x) + raster.getWidth();
-        int     subEndY   = (raster.getMinY() - y) + raster.getHeight();
-        int     subWidth  = Math.min(windowWidth,  subEndX);
-        int     subHeight = Math.min(windowHeight, subEndY);
-        boolean fullWidth = (subWidth == windowWidth);
-        if (fullWidth && subHeight == windowHeight) {
-            /*
-             * Optimization for the case where the full window is inside current raster.
-             * This is the vast majority of cases, so we perform this check soon before
-             * to compute more internal variables.
-             */
-            final Object transfer = window.getPixels(raster, x, y, subWidth, subHeight, true);
-            if (transfer != data) {     // Paranoiac check (arrays should always be same).
-                System.arraycopy(transfer, 0, data, 0, numBands * subWidth * subHeight);
-            }
-            return;
-        }
-        /*
-         * At this point, we determined that the window is overlapping two or more tiles.
-         * We will need more variables for iterating over the tiles around 'currentRaster'.
-         */
-        int destOffset   = 0;                       // Index in 'window' array where to copy the sample values.
-        int subX         = 0;                       // Upper-left corner of a sub-window inside the window.
-        int subY         = 0;
-        int tileSubX     = tileX;                   // The tile where is located the (subX, subY) coordinate.
-        int tileSubY     = tileY;
-        final int stride = windowWidth * numBands;  // Number of samples between two rows in the 'windows' array.
-        final int rewind = subEndX;
-        for (;;) {
-            if (subWidth > 0 && subHeight > 0) {
-                final Object transfer = window.getPixels(raster, x + subX, y + subY, subWidth, subHeight, false);
-                if (fullWidth) {
-                    final int fullLength = stride * subHeight;
-                    System.arraycopy(transfer, 0, data, destOffset, fullLength);
-                    destOffset += fullLength;
-                } else {
-                    final int  rowLength = numBands  * subWidth;
-                    final int fullLength = rowLength * subHeight;
-                    for (int srcOffset=0; srcOffset < fullLength; srcOffset += rowLength) {
-                        System.arraycopy(transfer, srcOffset, data, destOffset, rowLength);
-                        destOffset += stride;
-                    }
-                }
-            }
-            /*
-             * At this point, we copied all sample values that we could obtain from the current tile.
-             * Move to the next tile on current row, or if we reached the end of row move to the next row.
-             */
-            if (subEndX < windowWidth) {
-                subX     = subEndX;
-                subEndX += tileWidth;                       // Next tile on the same row.
-                tileSubX++;
-            } else {
-                if (subEndY >= windowHeight) {
-                    return;                                 // Completed last row of tiles.
-                }
-                subY     = subEndY;
-                subEndY += tileHeight;                      // Tile on the next row.
-                tileSubY++;
-                tileSubX = tileX;
-                subEndX  = rewind;
-                subX     = 0;                               // Move x position back to the window left border.
-            }
-            raster     = image.getTile(tileSubX, tileSubY);
-            destOffset = (subY * windowWidth + subX) * numBands;
-            subWidth   = Math.min(windowWidth,  subEndX) - subX;
-            subHeight  = Math.min(windowHeight, subEndY) - subY;
-            fullWidth  = (subWidth == windowWidth);
-        }
-    }
-
-    /**
-     * Releases the tiles acquired by this iterator, if any.
-     * This method does nothing if the iterator is read-only.
-     */
-    @Override
-    public void close() {
-        if (destination != null && destRaster != null) {
-            destRaster = null;
-            destination.releaseWritableTile(tileX, tileY);
-        }
-    }
-}
diff --git a/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java b/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
deleted file mode 100644
index b00173b..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * 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.image;
-
-import java.nio.Buffer;
-import java.awt.Point;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.WritableRaster;
-import java.awt.image.WritableRenderedImage;
-import java.util.NoSuchElementException;
-import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.internal.jdk8.JDK8;
-
-import static org.apache.sis.internal.jdk8.JDK8.floorDiv;
-
-
-/**
- * An iterator over sample values in a raster or an image.  This iterator makes easier to read and write efficiently
- * pixel or sample values. The iterator {@linkplain RenderedImage#getTile(int,int) acquires tiles} and releases them
- * automatically. Unless otherwise specified, iterators are free to use an iteration order
- * that minimize the "acquire / release tile" operations (in other words, iterations are not necessarily from
- * left to right). Iteration can be performed on a complete image or only a sub-region of it. Some optimized iterator
- * implementations exist for a few commonly used {@linkplain java.awt.image.SampleModel sample models}.
- *
- * <div class="note"><b>Example:</b>
- * {@preformat java
- *     PixelIterator it = PixelIterator.create(image);
- *     double[] samples = null;
- *     while (it.next()) {
- *         samples = it.getPixel(samples);      // Get values in all bands.
- *         // Perform computation here...
- *     }
- * }
- * </div>
- *
- * @author  Rémi Maréchal (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-public abstract class PixelIterator {
-    /**
-     * The image in which iteration is occurring, or {@code null} if none.
-     * If {@code null}, then {@link #currentRaster} must be non-null.
-     */
-    final RenderedImage image;
-
-    /**
-     * The current raster in which iteration is occurring. This may change when the iterator
-     * reaches a new {@link #image} tile. May be {@code null} if not yet determined.
-     *
-     * @see RenderedImage#getTile(int, int)
-     */
-    Raster currentRaster;
-
-    /**
-     * Number of bands in all tiles in the {@linkplain #image}.
-     * The {@link #currentRaster} shall always have this number of bands.
-     */
-    final int numBands;
-
-    /**
-     * The domain, in pixel coordinates, of the region traversed by this pixel iterator.
-     * This may be smaller than the image or raster bounds, but not greater.
-     * The lower values are inclusive and the upper values exclusive.
-     *
-     * @see #getDomain()
-     */
-    final int lowerX, lowerY, upperX, upperY;
-
-    /**
-     * Size of all tiles in the {@link #image}.
-     */
-    final int tileWidth, tileHeight;
-
-    /**
-     * The X and Y coordinate of the upper-left pixel of tile (0,0).
-     * Note that tile (0,0) may not actually exist.
-     */
-    final int tileGridXOffset, tileGridYOffset;
-
-    /**
-     * The domain, in tile coordinates, of the region traversed by this pixel iterator.
-     * This may be smaller than the image or raster tile grid bounds, but not greater.
-     * The lower values are inclusive and the upper values exclusive.
-     */
-    final int tileLowerX, tileLowerY, tileUpperX, tileUpperY;
-
-    /**
-     * Size of the window to use in {@link #createWindow(TransferType)} method, or {@code 0} if none.
-     */
-    final int windowWidth, windowHeight;
-
-    /**
-     * Creates an iterator for the given region in the given raster.
-     *
-     * @param  data     the raster which contains the sample values on which to iterate.
-     * @param  subArea  the raster region where to perform the iteration, or {@code null}
-     *                  for iterating over all the raster domain.
-     * @param  window   size of the window to use in {@link #createWindow(TransferType)} method, or {@code null} if none.
-     */
-    PixelIterator(final Raster data, final Rectangle subArea, final Dimension window) {
-        final Rectangle bounds;
-        image           = null;
-        currentRaster   = data;
-        numBands        = data.getNumBands();
-        tileWidth       = data.getWidth();
-        tileHeight      = data.getHeight();
-        tileGridXOffset = data.getMinX();
-        tileGridYOffset = data.getMinY();
-        tileLowerX      = 0;                    // In this case only one raster: tile index is fixed to 0.
-        tileLowerY      = 0;
-        tileUpperX      = 1;
-        tileUpperY      = 1;
-        bounds          = intersection(tileGridXOffset, tileGridYOffset, tileWidth, tileHeight, subArea, window);
-        lowerX          = bounds.x;
-        lowerY          = bounds.y;
-        upperX          = JDK8.addExact(lowerX, bounds.width);
-        upperY          = JDK8.addExact(lowerY, bounds.height);
-        windowWidth     = (window != null) ? window.width  : 0;
-        windowHeight    = (window != null) ? window.height : 0;
-    }
-
-    /**
-     * Creates an iterator for the given region in the given image.
-     *
-     * @param  data     the image which contains the sample values on which to iterate.
-     * @param  subArea  the image region where to perform the iteration, or {@code null}
-     *                  for iterating over all the image domain.
-     * @param  window   size of the window to use in {@link #createWindow(TransferType)} method, or {@code null} if none.
-     */
-    PixelIterator(final RenderedImage data, final Rectangle subArea, final Dimension window) {
-        final Rectangle bounds;
-        image           = data;
-        numBands        = data.getSampleModel().getNumBands();
-        tileWidth       = data.getTileWidth();
-        tileHeight      = data.getTileHeight();
-        tileGridXOffset = data.getTileGridXOffset();
-        tileGridYOffset = data.getTileGridYOffset();
-        bounds          = intersection(data.getMinX(), data.getMinY(), data.getWidth(), data.getHeight(), subArea, window);
-        lowerX          = bounds.x;
-        lowerY          = bounds.y;
-        upperX          = JDK8.addExact(lowerX, bounds.width);
-        upperY          = JDK8.addExact(lowerY, bounds.height);
-        tileLowerX      = floorDiv(JDK8.subtractExact(lowerX, tileGridXOffset), tileWidth);
-        tileLowerY      = floorDiv(JDK8.subtractExact(lowerY, tileGridYOffset), tileHeight);
-        tileUpperX      =  ceilDiv(JDK8.subtractExact(upperX, tileGridXOffset), tileWidth);
-        tileUpperY      =  ceilDiv(JDK8.subtractExact(upperY, tileGridYOffset), tileHeight);
-        windowWidth     = (window != null) ? window.width  : 0;
-        windowHeight    = (window != null) ? window.height : 0;
-    }
-
-    /**
-     * Returns {@code numerator / denominator} rounded toward positive infinity.
-     */
-    private static int ceilDiv(final int numerator, final int denominator) {
-        return -floorDiv(-numerator, denominator);
-    }
-
-    /**
-     * Computes the intersection between the given bounds and and {@code subArea} if {@code subArea} is non-null.
-     * If the result is empty, then the width and/or height are set to zero (not negative).
-     */
-    private static Rectangle intersection(int x, int y, int width, int height, Rectangle subArea, Dimension window) {
-        if (window != null) {
-            ArgumentChecks.ensureBetween("window.width",  1, width,  window.width);
-            ArgumentChecks.ensureBetween("window.height", 1, height, window.height);
-            width  -= (window.width  - 1);
-            height -= (window.height - 1);
-        }
-        Rectangle bounds = new Rectangle(x, y, width, height);
-        if (subArea != null) {
-            bounds = bounds.intersection(subArea);
-            if (bounds.width  < 0) bounds.width  = 0;
-            if (bounds.height < 0) bounds.height = 0;
-        }
-        return bounds;
-    }
-
-    /**
-     * Builds pixel iterators for specified region of interest, window size or iteration order.
-     * By default, the builder creates iterators for all pixels in the given raster or image,
-     * with unspecified iteration order. Users can invoke setter methods for specifying
-     * desired behavior for the iterators to create.
-     *
-     * <div class="note"><b>Example:</b>
-     * {@preformat java
-     *     PixelIterator iterator = new PixelIterator.Builder().setRegionOfInterest(new Rectangle(10, 10, 5, 5).create(image);
-     * }
-     * </div>
-     */
-    public static class Builder {
-        /**
-         * The region where to perform the iteration, or {@code null} for iterating over all the domain.
-         */
-        private Rectangle subArea;
-
-        /**
-         * Size of the window to use in {@link PixelIterator#createWindow(TransferType)} method,
-         * or {@code null} if none.
-         */
-        private Dimension window;
-
-        /**
-         * Creates a new iterator builder with no region of interest, no window size and default iterator order.
-         */
-        public Builder() {
-        }
-
-        /**
-         * Sets the region (in pixel coordinates) where to perform the iteration.
-         * By default, iterators will traverse all pixels in the given image or raster.
-         *
-         * @param  subArea  region where to iterator, or {@code null} for iterating over all image domain.
-         * @return {@code this} for method call chaining.
-         */
-        public Builder setRegionOfInterest(final Rectangle subArea) {
-            this.subArea = subArea;
-            return this;
-        }
-
-        /**
-         * Sets the size of the window to use in {@link PixelIterator#createWindow(TransferType)} method.
-         * By default, iterators do not create windows.
-         *
-         * @param  window  the window size, or {@code null} if no window will be created.
-         * @return {@code this} for method call chaining.
-         */
-        public Builder setWindowSize(final Dimension window) {
-            this.window = window;
-            return this;
-        }
-
-        /**
-         * Creates a read-only iterator for the given raster.
-         *
-         * @param  data  the raster which contains the sample values on which to iterate.
-         * @return a new iterator traversing pixels in the given raster.
-         */
-        public PixelIterator create(final Raster data) {
-            ArgumentChecks.ensureNonNull("data", data);
-            // TODO: check here for cases that we can optimize (after we ported corresponding implementations).
-            return new DefaultIterator(data, null, subArea, window);
-        }
-
-        /**
-         * Creates a read-only iterator for the given image.
-         *
-         * @param  data  the image which contains the sample values on which to iterate.
-         * @return a new iterator traversing pixels in the given image.
-         */
-        public PixelIterator create(final RenderedImage data) {
-            ArgumentChecks.ensureNonNull("data", data);
-            // TODO: check here for cases that we can optimize (after we ported corresponding implementations).
-            return new DefaultIterator(data, null, subArea, window);
-        }
-
-        /**
-         * Creates a read/write iterator for the given raster.
-         *
-         * @param  data  the raster which contains the sample values on which to iterate.
-         * @return a new iterator traversing pixels in the given raster.
-         */
-        public WritablePixelIterator createWritable(final WritableRaster data) {
-            ArgumentChecks.ensureNonNull("data", data);
-            return createWritable(data, data);
-        }
-
-        /**
-         * Creates a read/write iterator for the given image.
-         *
-         * @param  data  the image which contains the sample values on which to iterate.
-         * @return a new iterator traversing pixels in the given image.
-         */
-        public WritablePixelIterator createWritable(final WritableRenderedImage data) {
-            ArgumentChecks.ensureNonNull("data", data);
-            return createWritable(data, data);
-        }
-
-        /**
-         * Creates an iterator which will read and write in two different rasters.
-         *
-         * @param  input    the raster which contains the sample values to read.
-         * @param  output   the raster where to write the sample values. Can be the same than {@code input}.
-         * @return a new writable iterator.
-         */
-        public WritablePixelIterator createWritable(final Raster input, final WritableRaster output) {
-            ArgumentChecks.ensureNonNull("input",  input);
-            ArgumentChecks.ensureNonNull("output", output);
-            // TODO: check here for cases that we can optimize (after we ported corresponding implementations).
-            return new DefaultIterator(input, output, subArea, window);
-        }
-
-        /**
-         * Creates an iterator which will read and write in two different images.
-         *
-         * @param  input    the image which contains the sample values to read.
-         * @param  output   the image where to write the sample values. Can be the same than {@code input}.
-         * @return a new writable iterator.
-         */
-        public WritablePixelIterator createWritable(final RenderedImage input, final WritableRenderedImage output) {
-            ArgumentChecks.ensureNonNull("input",  input);
-            ArgumentChecks.ensureNonNull("output", output);
-            // TODO: check here for cases that we can optimize (after we ported corresponding implementations).
-            return new DefaultIterator(input, output, subArea, window);
-        }
-    }
-
-    /**
-     * Creates an iterator for all pixels in the given image.
-     * This is a convenience method for {@code new Builder().create(data)}.
-     *
-     * @param  data  the image which contains the sample values on which to iterate.
-     * @return a new iterator traversing all pixels in the given image, in arbitrary order.
-     */
-    public static PixelIterator create(final RenderedImage data) {
-        return new Builder().create(data);
-    }
-
-    /**
-     * Returns {@code true} if this iterator can write pixel values (after cast to {@code WritablePixelIterator}).
-     * This method should be used instead than {@code instanceof} check because, for some implementations, being
-     * an instance of {@code WritablePixelIterator} is not a sufficient condition.
-     *
-     * @return {@code true} if this iterator can safely be casted to {@link WritablePixelIterator} and used for
-     *         writing pixel values.
-     */
-    public boolean isWritable() {
-        return false;
-    }
-
-    /**
-     * Returns the most efficient type ({@code int}, {@code float} or {@code double}) for transferring data between the
-     * underlying rasters and this iterator. The transfer type is not necessarily the storage type used by the rasters.
-     * For example {@code int} values will be used for transferring data even if the underlying rasters store all sample
-     * values as {@code byte}s.
-     *
-     * <p>The transfer type is only a hint since all iterator methods work for any type (conversions are applied as needed).
-     * However if this method returns {@link TransferType#INT}, then {@link #getSample(int)} and {@link #getPixel(int[])}
-     * will be slightly more efficient than equivalent methods for other types. Conversely if this method returns
-     * {@link TransferType#DOUBLE}, then {@link #getSampleDouble(int)} will be both more efficient and avoid accuracy lost.</p>
-     *
-     * @return the most efficient data type for transferring data.
-     */
-    public TransferType<?> getTransferType() {
-        return TransferType.valueOf(image != null ? image.getSampleModel().getTransferType() : currentRaster.getTransferType());
-    }
-
-    /**
-     * Returns the pixel coordinates of the region where this iterator is doing the iteration.
-     * If no region was specified at construction time, then this method returns the image or raster bounds.
-     *
-     * @return pixel coordinates of the iteration region.
-     */
-    public Rectangle getDomain() {
-        return new Rectangle(lowerX, lowerY, upperX - lowerX, upperY - lowerY);
-    }
-
-    /**
-     * Returns the column (x) and row (y) indices of the current pixel.
-     * The {@link #next()} or {@link #moveTo(int,int)} method must have been invoked before this method.
-     * Indices of the first pixel are not necessarily zero; they can even be negative.
-     *
-     * @return column and row indices of current iterator position.
-     * @throws IllegalStateException if this method is invoked before the first call to {@link #next()}
-     *         or {@link #moveTo(int,int)}, or after {@code next()} returned {@code false}.
-     */
-    public abstract Point getPosition();
-
-    /**
-     * Moves the pixel iterator to the given column (x) and row (y) indices. After this method invocation,
-     * the iterator state is as if the {@link #next()} method has been invoked just before to reach the
-     * specified position.
-     *
-     * <div class="note"><b>Usage example:</b>
-     * {@preformat java
-     *     iterator.moveTo(x, y);
-     *     do {
-     *         int sample = iterator.getSample(band);
-     *         // Use sample value here...
-     *     } while (iterator.next());
-     * }
-     * </div>
-     *
-     * @param  x  the column index of the pixel to make current.
-     * @param  y  the row index of the pixel to make current.
-     * @throws IndexOutOfBoundsException if the given indices are outside the iteration domain.
-     */
-    public abstract void moveTo(int x, int y);
-
-    /**
-     * Moves the iterator to the next pixel. A pixel iterator is initially positioned before the first pixel.
-     * The first call to {@code next()} makes the first pixel the current one; the second call makes the second
-     * pixel the current one, <i>etc.</i> The second pixel is not necessarily on the same row than the first one;
-     * iteration order is implementation dependent.
-     *
-     * <p>When a call to {@code next()} returns {@code false}, the iterator is positioned after the last pixel.
-     * Any invocation of a {@code getSample(int)} method will result in a {@link NoSuchElementException} to be
-     * thrown.</p>
-     *
-     * @return {@code true} if the current pixel is valid, or {@code false} if there is no more pixels.
-     * @throws IllegalStateException if this iterator already reached end of iteration in a previous call
-     *         to {@code next()}, and {@link #rewind()} or {@link #moveTo(int,int)} have not been invoked.
-     */
-    public abstract boolean next();
-
-    /**
-     * Returns the sample value in the specified band of current pixel, rounded toward zero.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code getSample(int)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined: it may throw any runtime exception or return a meaningless value
-     * (there is no explicit bounds check for performance reasons).
-     *
-     * @param  band  the band for which to get the sample value.
-     * @return sample value in specified band of current pixel.
-     *
-     * @see Raster#getSample(int, int, int)
-     */
-    public abstract int getSample(int band);
-
-    /**
-     * Returns the sample value in the specified band of current pixel as a single-precision floating point number.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code getSampleFloat(int)} method is invoked. If above condition is
-     * not met, then this method behavior is undefined: it may throw any runtime exception or return a meaningless
-     * value (there is no explicit bounds check for performance reasons).
-     *
-     * @param  band  the band for which to get the sample value.
-     * @return sample value in specified band of current pixel.
-     *
-     * @see Raster#getSampleFloat(int, int, int)
-     */
-    public abstract float getSampleFloat(int band);
-
-    /**
-     * Returns the sample value in the specified band of current pixel, without precision lost.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code getSampleDouble(int)} method is invoked. If above condition is
-     * not met, then this method behavior is undefined: it may throw any runtime exception or return a meaningless
-     * value (there is no explicit bounds check for performance reasons).
-     *
-     * @param  band  the band for which to get the sample value.
-     * @return sample value in specified band of current pixel.
-     *
-     * @see Raster#getSampleDouble(int, int, int)
-     */
-    public abstract double getSampleDouble(int band);
-
-    /**
-     * Returns the sample values of current pixel for all bands.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code getPixel(…)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined: it may throw any runtime exception or return a meaningless value
-     * (there is no explicit bounds check for performance reasons).
-     *
-     * @param  dest  a pre-allocated array where to store the sample values, or {@code null} if none.
-     * @return the sample values for current pixel.
-     *
-     * @see Raster#getPixel(int, int, int[])
-     */
-    public abstract int[] getPixel​(int[] dest);
-
-    /**
-     * Returns the sample values of current pixel for all bands.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code getPixel(…)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined: it may throw any runtime exception or return a meaningless value
-     * (there is no explicit bounds check for performance reasons).
-     *
-     * @param  dest  a pre-allocated array where to store the sample values, or {@code null} if none.
-     * @return the sample values for current pixel.
-     *
-     * @see Raster#getPixel(int, int, float[])
-     */
-    public abstract float[] getPixel​(float[] dest);
-
-    /**
-     * Returns the sample values of current pixel for all bands.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code getPixel(…)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined: it may throw any runtime exception or return a meaningless value
-     * (there is no explicit bounds check for performance reasons).
-     *
-     * @param  dest  a pre-allocated array where to store the sample values, or {@code null} if none.
-     * @return the sample values for current pixel.
-     *
-     * @see Raster#getPixel(int, int, double[])
-     */
-    public abstract double[] getPixel​(double[] dest);
-
-    /**
-     * Returns a moving window over the sample values in a rectangular region starting at iterator position.
-     * The <cite>window size</cite> must have been specified at {@code PixelIterator} construction time.
-     * Sample values are stored in a sequence of length
-     * <var>(number of bands)</var> × <var>(window width)</var> × <var>(window height)</var>.
-     * Values are always stored with band index varying fastest, then column index, then row index.
-     * Columns are traversed from left to right and rows are traversed from top to bottom
-     * (linear iteration order).
-     * That order is the same regardless the iteration order of this iterator.
-     *
-     * <div class="note"><b>Example:</b>
-     * for an RGB image, the 3 first values are the red, green and blue components of the pixel at
-     * {@linkplain #getPosition() current iterator position}. The 3 next values are the red, green
-     * and blue components of the pixel at the right of current iterator position (not necessarily
-     * the position where a call to {@link #next()} would have go), <i>etc.</i></div>
-     *
-     * Calls to {@link #next()} or {@link #moveTo(int,int)} followed by {@link Window#update()}
-     * replaces the window content with values starting at the new iterator position.
-     * Before the first {@link Window#update()} invocation, the window is filled with zero values.
-     *
-     * <div class="note"><b>Usage example:</b>
-     * following code creates an iterator over the full area of given image, then a window of 5×5 pixels.
-     * The window is moved over all the image area in iteration order. Inside the window, data are copied
-     * in linear order regardless the iteration order.
-     *
-     * {@preformat java
-     *     PixelIterator it = create(image, null, new Dimension(5, 5), null);     // Windows size will be 5×5 pixels.
-     *     PixelIterator<FloatBuffer> window = it.createWindow(TransferType.FLOAT);
-     *     FloatBuffer values = window.values;
-     *     while (it.next()) {
-     *         window.update();
-     *         while (buffer.hasRemaining()) {
-     *             float sample = buffer.get();
-     *             // use the sample value here.
-     *         }
-     *     }
-     * }
-     * </div>
-     *
-     * @param  <T>   the type of the data buffer to use for transferring data.
-     * @param  type  the desired type of values ({@code int}, {@code float} or {@code double}).
-     *               Use {@link #getTransferType()} if the most efficient type is desired.
-     * @return a window over the sample values in the underlying image or raster.
-     *
-     * @see Raster#getPixels(int, int, int, int, double[])
-     */
-    public abstract <T extends Buffer> Window<T> createWindow(TransferType<T> type);
-
-    /**
-     * Contains the sample values in a moving window over the image. Windows are created by calls to
-     * {@link PixelIterator#createWindow(TransferType)} and sample values are stored in {@link Buffer}s.
-     * The buffer content is replaced ever time {@link #update()} is invoked.
-     *
-     * @author  Martin Desruisseaux (Geomatys)
-     * @version 0.8
-     *
-     * @param  <T>  the type of buffer which can be used for transferring data.
-     *
-     * @since 0.8
-     * @module
-     */
-    public abstract static class Window<T extends Buffer> {
-        /**
-         * A buffer containing all sample values fetched by the last call to {@link #update()}. The buffer
-         * capacity is <var>(number of bands)</var> × <var>(window width)</var> × <var>(window height)</var>.
-         * Values are always stored with band index varying fastest, then column index, then row index.
-         * Columns are traversed from left to right and rows are traversed from top to bottom
-         * (linear iteration order).
-         * That order is the same regardless the iteration order
-         * of enclosing iterator.
-         *
-         * <p>Every time that {@link #update()} is invoked, the buffer content is replaced by sample values
-         * starting at the {@linkplain PixelIterator#getPosition() current iterator position}.
-         * Before the first {@code update()} invocation, the buffer is filled with zero values.</p>
-         */
-        public final T values;
-
-        /**
-         * Creates a new window which will store the sample values in the given buffer.
-         */
-        Window(final T buffer) {
-            values = buffer;
-        }
-
-        /**
-         * Updates this window with the sample values in the region starting at current iterator position.
-         * The buffer position, limit and mark are {@linkplain Buffer#clear() cleared}.
-         *
-         * <p>The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-         * been invoked successfully, before this {@code update()} method is invoked. If above condition is not met,
-         * then this method behavior is undefined: it may throw any runtime exception or return meaningless values
-         * (there is no explicit bounds check for performance reasons).</p>
-         */
-        public abstract void update();
-    }
-
-    /**
-     * Restores the iterator to the start position. After this method has been invoked,
-     * the iterator is in the same state than after construction.
-     */
-    public abstract void rewind();
-}
diff --git a/core/sis-raster/src/main/java/org/apache/sis/image/TransferType.java b/core/sis-raster/src/main/java/org/apache/sis/image/TransferType.java
deleted file mode 100644
index b611308..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/image/TransferType.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.image;
-
-import java.nio.Buffer;
-import java.nio.IntBuffer;
-import java.nio.FloatBuffer;
-import java.nio.DoubleBuffer;
-import java.awt.image.Raster;
-import java.awt.image.DataBuffer;
-import java.io.Serializable;
-import java.io.ObjectStreamException;
-import java.io.InvalidObjectException;
-import org.apache.sis.util.resources.Errors;
-
-
-/**
- * The type of data used to transfer pixels. Data transfers happen in various {@link Raster} methods and in
- * {@link PixelIterator#createWindow(TransferType)}. The type used for transferring data is not necessarily
- * the same than the type used by the raster for storing data. In particular, {@code byte} and {@code short}
- * (both signed and unsigned) are converted to {@code int} during the transfer.
- *
- * {@link Raster} and {@link PixelIterator} transfer data in {@code int[]}, {@code float[]} and {@code double[]} arrays.
- * Additionally, {@code PixelIterator} uses also {@link IntBuffer}, {@link FloatBuffer} and {@link DoubleBuffer}.
- *
- * <div class="note"><b>Future evolution:</b>
- * this class may be refactored as an enumeration in a future Java version if
- * <a href="http://openjdk.java.net/jeps/301">JEP 301</a> is implemented.</div>
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- *
- * @param  <T>  the type of buffer which can be used for transferring data.
- *
- * @since 0.8
- * @module
- *
- * @see Raster#getTransferType()
- * @see PixelIterator#createWindow(TransferType)
- */
-public final class TransferType<T extends Buffer> implements Serializable {
-    /**
-     * For cross-version compatibility.
-     */
-    private static final long serialVersionUID = -2891665589742927570L;
-
-    /**
-     * The enumeration name.
-     */
-    private final transient String name;
-
-    /**
-     * The type as one of the {@link DataBuffer} constants.
-     * This is the value returned by {@link Raster#getTransferType()}.
-     */
-    final int dataBufferType;
-
-    /**
-     * Specifies that sample values are transfered as 32 bits signed integer.
-     * If the raster stores sample values as {@code byte} or {@code short}, the values are casted by a widening
-     * conversion before to be transfered. If the raster stores sample values as {@code float} or {@code double},
-     * the values are rounded toward 0 before to be transfered.
-     *
-     * @see PixelIterator#getSample(int)
-     * @see PixelIterator#getPixel(int[])
-     */
-    public static final TransferType<IntBuffer> INT = new TransferType<>("INT", DataBuffer.TYPE_INT);
-
-    /**
-     * Specifies that sample values are transfered as single-precision floating point number.
-     * Values of other types are casted as needed.
-     *
-     * @see PixelIterator#getSampleFloat(int)
-     * @see PixelIterator#getPixel(float[])
-     */
-    public static final TransferType<FloatBuffer> FLOAT = new TransferType<>("FLOAT", DataBuffer.TYPE_FLOAT);
-
-    /**
-     * Specifies that sample values are transfered as double-precision floating point number.
-     * Values of other types are casted as needed. This is the safest transfer type to use
-     * when wanting to avoid any precision lost.
-     *
-     * @see PixelIterator#getSampleDouble(int)
-     * @see PixelIterator#getPixel(double[])
-     */
-    public static final TransferType<DoubleBuffer> DOUBLE = new TransferType<>("DOUBLE", DataBuffer.TYPE_DOUBLE);
-
-    /**
-     * Creates a new enumeration.
-     */
-    private TransferType(final String name, final int dataBufferType) {
-        this.name = name;
-        this.dataBufferType = dataBufferType;
-    }
-
-    /**
-     * Returns the enumeration value for the given {@code DataBuffer} constant.
-     * This method applies the following mapping:
-     *
-     * <ul>
-     *   <li>If {@code type} is {@link DataBuffer#TYPE_DOUBLE}, returns {@link #DOUBLE}.</li>
-     *   <li>If {@code type} is {@link DataBuffer#TYPE_FLOAT}, returns {@link #FLOAT}.</li>
-     *   <li>If {@code type} is {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
-     *          {@link DataBuffer#TYPE_USHORT TYPE_USHORT} or {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
-     *          returns {@link #INT}.</li>
-     *   <li>If {@code type} is {@link DataBuffer#TYPE_UNDEFINED} or any other value,
-     *       throws {@link IllegalArgumentException}.</li>
-     * </ul>
-     *
-     * The {@code type} argument given to this method is typically the {@link Raster#getTransferType()} value.
-     *
-     * @param  type  one of {@link DataBuffer} constant.
-     * @return the enumeration value for the given constant.
-     * @throws IllegalArgumentException if (@code type} is not a supported {@code DataBuffer} constant.
-     */
-    public static TransferType<?> valueOf(final int type) {
-        switch (type) {
-            case DataBuffer.TYPE_DOUBLE: return DOUBLE;
-            case DataBuffer.TYPE_FLOAT:  return FLOAT;
-            default: {
-                if (type >= DataBuffer.TYPE_BYTE && type <= DataBuffer.TYPE_INT) return INT;
-                throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "type", type));
-            }
-        }
-    }
-
-    /**
-     * Returns a unique instance on deserialization.
-     *
-     * @return the object to use after deserialization.
-     * @throws ObjectStreamException if the serialized object defines an unknown data type.
-     */
-    Object readResolve() throws ObjectStreamException {
-        try {
-            return valueOf(dataBufferType);
-        } catch (IllegalArgumentException e) {
-            throw new InvalidObjectException(e.toString());
-        }
-    }
-
-    /**
-     * Returns the name of this enumeration constant.
-     *
-     * @return the enumeration constant name.
-     */
-    @Override
-    public String toString() {
-        return name;
-    }
-}
diff --git a/core/sis-raster/src/main/java/org/apache/sis/image/WritablePixelIterator.java b/core/sis-raster/src/main/java/org/apache/sis/image/WritablePixelIterator.java
deleted file mode 100644
index 5e8a8aa..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/image/WritablePixelIterator.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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.image;
-
-import java.io.Closeable;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.WritableRaster;
-import java.awt.image.WritableRenderedImage;
-import org.apache.sis.internal.raster.Resources;
-
-
-/**
- * A pixel iterator capable to write sample values. This iterator can edit pixel values in place,
- * or write values in a different destination image than the source image. Source and destination
- * images must use the same sample model and the same coordinates (both for pixels and tiles).
- *
- * <p>Contrarily to {@code PixelIterator}, {@code WritablePixelIterator} needs to be closed after
- * iteration in order to release tiles. Example:</p>
- *
- * {@preformat java
- *     try (WritablePixelIterator it = WritablePixelIterator.create(image)) {
- *         double[] samples = null;
- *         while (it.next()) {
- *             samples = it.getPixel(samples);      // Get values in all bands.
- *             // Perform computation here...
- *             it.setPixels(sample);                // Replace values in all bands.
- *         }
- *     }
- * }
- *
- * <div class="section">Casting a {@code PixelIterator}</div>
- * To check if a {@code PixelIterator} can be used for writing pixels, a {@code … instanceof WritablePixelIterator}
- * check is not sufficient. The {@link PixelIterator#isWritable()} method should be invoked instead.
- *
- * @author  Rémi Maréchal (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-public abstract class WritablePixelIterator extends PixelIterator implements Closeable {
-    /**
-     * The image where pixels will be written, or {@code null} if the image is read-only.
-     * The destination image may or may not be the same instance than the source {@link #image}.
-     * However the sample model, the minimal X and Y values and the tile grid must be the same.
-     */
-    final WritableRenderedImage destination;
-
-    /**
-     * The current tile where pixels will be written, or {@code null} if no write operation is under way.
-     * It may or may not be the same instance than {@link #currentRaster}.
-     *
-     * @see WritableRenderedImage#getWritableTile(int, int)
-     * @see WritableRenderedImage#releaseWritableTile(int, int)
-     */
-    WritableRaster destRaster;
-
-    /**
-     * Creates an iterator for the given region in the given raster.
-     *
-     * @param  input    the raster which contains the sample values to read.
-     * @param  output   the raster where to write the sample values, or {@code null} for read-only iterator.
-     * @param  subArea  the raster region where to perform the iteration, or {@code null}
-     *                  for iterating over all the raster domain.
-     * @param  window   size of the window to use in {@link #createWindow(TransferType)} method, or {@code null} if none.
-     */
-    WritablePixelIterator(final Raster input, final WritableRaster output,
-                          final Rectangle subArea, final Dimension window)
-    {
-        super(input, subArea, window);
-        destRaster  = output;
-        destination = null;
-        if (output != null) {
-            if (!input.getSampleModel().equals(output.getSampleModel())) {
-                throw new IllegalArgumentException(Resources.format(Resources.Keys.MismatchedSampleModel));
-            } else if (!input.getBounds().equals(output.getBounds())) {
-                throw new IllegalArgumentException(Resources.format(Resources.Keys.MismatchedImageLocation));
-            }
-        }
-    }
-
-    /**
-     * Creates an iterator for the given region in the given image.
-     *
-     * @param  input    the image which contains the sample values to read.
-     * @param  output   the image where to write the sample values, or {@code null} for read-only iterator.
-     * @param  subArea  the image region where to perform the iteration, or {@code null}
-     *                  for iterating over all the image domain.
-     * @param  window   size of the window to use in {@link #createWindow(TransferType)} method, or {@code null} if none.
-     */
-    WritablePixelIterator(final RenderedImage input, final WritableRenderedImage output,
-                          final Rectangle subArea, final Dimension window)
-    {
-        super(input, subArea, window);
-        destRaster  = null;
-        destination = output;
-        if (output != null) {
-            if (!input.getSampleModel().equals(output.getSampleModel())) {
-                throw new IllegalArgumentException(Resources.format(Resources.Keys.MismatchedSampleModel));
-            } else if (input.getMinX()   != output.getMinX()  ||
-                       input.getMinY()   != output.getMinY()  ||
-                       input.getWidth()  != output.getWidth() ||
-                       input.getHeight() != output.getHeight())
-            {
-                throw new IllegalArgumentException(Resources.format(Resources.Keys.MismatchedImageLocation));
-            } else if (input.getMinTileX()   != output.getMinTileX()  ||
-                       input.getMinTileY()   != output.getMinTileY()  ||
-                       input.getTileWidth()  != output.getTileWidth() ||
-                       input.getTileHeight() != output.getTileHeight())
-            {
-                throw new IllegalArgumentException(Resources.format(Resources.Keys.MismatchedTileGrid));
-            }
-        }
-    }
-
-    /**
-     * Creates an iterator for all pixels in the given image.
-     * This is a convenience method for {@code new Builder().createWritable(data)}.
-     *
-     * @param  data  the image which contains the sample values on which to iterate.
-     * @return a new iterator traversing all pixels in the given image, in arbitrary order.
-     */
-    public static WritablePixelIterator create(WritableRenderedImage data) {
-        return new Builder().createWritable(data);
-    }
-
-    /**
-     * Returns {@code true} if this iterator can write pixel values.
-     * This method should be used instead than {@code instanceof} check because, for some implementations, being an
-     * instance of {@code WritablePixelIterator} is not a sufficient condition. However this method is guaranteed to
-     * return {@code true} for any iterator created by {@code WritablePixelIterator.create(…)} methods.
-     *
-     * @return {@code true} if this iterator can be used for writing pixel values.
-     */
-    @Override
-    public boolean isWritable() {
-        return (destination != null) || (destRaster != null);
-    }
-
-    /**
-     * Writes a sample value in the specified band of current pixel.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code setSample(int, int)} method is invoked. If above condition is
-     * not met, then this method behavior is undefined (there is no explicit bounds check for performance reasons).
-     *
-     * @param  band   the band in which to set the sample value.
-     * @param  value  the sample value to write in the specified band.
-     *
-     * @see WritableRaster#setSample(int, int, int, int)
-     * @see #getSample(int)
-     */
-    public abstract void setSample(int band, int value);
-
-    /**
-     * Writes a sample value in the specified band of current pixel.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code setSample(int, float)} method is invoked. If above condition is
-     * not met, then this method behavior is undefined (there is no explicit bounds check for performance reasons).
-     *
-     * @param  band   the band in which to set the sample value.
-     * @param  value  the sample value to write in the specified band.
-     *
-     * @see WritableRaster#setSample(int, int, int, float)
-     * @see #getSampleFloat(int)
-     */
-    public abstract void setSample(int band, float value);
-
-    /**
-     * Writes a sample value in the specified band of current pixel.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code setSample(int, double)} method is invoked. If above condition is
-     * not met, then this method behavior is undefined (there is no explicit bounds check for performance reasons).
-     *
-     * @param  band   the band in which to set the sample value.
-     * @param  value  the sample value to write in the specified band.
-     *
-     * @see WritableRaster#setSample(int, int, int, double)
-     * @see #getSampleDouble(int)
-     */
-    public abstract void setSample(int band, double value);
-
-    /**
-     * Sets the sample values of current pixel for all bands.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code setPixel(…)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined (there is no explicit bounds check for performance reasons).
-     *
-     * @param  values  the new sample values for current pixel.
-     *
-     * @see WritableRaster#setPixel(int, int, int[])
-     * @see #getPixel(int[])
-     */
-    public abstract void setPixel​(int[] values);
-
-    /**
-     * Sets the sample values of current pixel for all bands.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code setPixel(…)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined (there is no explicit bounds check for performance reasons).
-     *
-     * @param  values  the new sample values for current pixel.
-     *
-     * @see WritableRaster#setPixel(int, int, float[])
-     * @see #getPixel(float[])
-     */
-    public abstract void setPixel​(float[] values);
-
-    /**
-     * Sets the sample values of current pixel for all bands.
-     * The {@link #next()} method must have returned {@code true}, or the {@link #moveTo(int,int)} method must have
-     * been invoked successfully, before this {@code setPixel(…)} method is invoked. If above condition is not met,
-     * then this method behavior is undefined (there is no explicit bounds check for performance reasons).
-     *
-     * @param  values  the new sample values for current pixel.
-     *
-     * @see WritableRaster#setPixel(int, int, double[])
-     * @see #getPixel(double[])
-     */
-    public abstract void setPixel​(double[] values);
-
-    /**
-     * Releases any resources hold by this iterator.
-     * Invoking this method may flush some tiles content to disk.
-     */
-    @Override
-    public abstract void close();
-}
diff --git a/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java b/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java
deleted file mode 100644
index fbb7f73..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Provides helper classes for handling Java2D rendered images together with some operations.
- * This package does not provide any geospatial functionalities;
- * it works only on sample or pixel values stored in {@link java.awt.image.RenderedImage}s.
- * Those rendered images have the following capabilities:
- *
- * <ul>
- *   <li>Images may have an arbitrary number of bands (not necessarily RGB).</li>
- *   <li>Sample values can be bytes, shorts (signed or unsigned), integers or floating-point values.</li>
- *   <li>Images can be tiled.</li>
- * </ul>
- *
- * This package is used as a basis for
- * {@linkplain org.apache.sis.metadata.iso.spatial.DefaultGeorectified georectified} or
- * {@linkplain org.apache.sis.metadata.iso.spatial.DefaultGeoreferenceable georeferenceable}
- * <cite>grid coverages</cite>.
- *
- * @author  Rémi Maréchal (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-package org.apache.sis.image;
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
deleted file mode 100644
index 7287cb1..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.internal.raster;
-
-import java.net.URL;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import javax.annotation.Generated;
-import org.apache.sis.util.resources.KeyConstants;
-import org.apache.sis.util.resources.IndexedResourceBundle;
-
-
-/**
- * Warning and error messages that are specific to the {@code sis-raster} module.
- * Resources in this file should not be used by any other module. For resources shared by
- * all modules in the Apache SIS project, see {@link org.apache.sis.util.resources} package.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-public final class Resources extends IndexedResourceBundle {
-    /**
-     * Resource keys. This class is used when compiling sources, but no dependencies to
-     * {@code Keys} should appear in any resulting class files. Since the Java compiler
-     * inlines final integer values, using long identifiers will not bloat the constant
-     * pools of compiled classes.
-     *
-     * @author  Martin Desruisseaux (Geomatys)
-     * @since   0.8
-     * @module
-     */
-    @Generated("org.apache.sis.util.resources.IndexedResourceCompiler")
-    public static final class Keys extends KeyConstants {
-        /**
-         * The unique instance of key constants handler.
-         */
-        static final Keys INSTANCE = new Keys();
-
-        /**
-         * For {@link #INSTANCE} creation only.
-         */
-        private Keys() {
-        }
-
-        /**
-         * The ({0}, {1}) pixel coordinate is outside iterator domain.
-         */
-        public static final short CoordinateOutsideDomain_2 = 1;
-
-        /**
-         * The ({0}, {1}) tile has an unexpected size, number of bands or sample layout.
-         */
-        public static final short IncompatibleTile_2 = 2;
-
-        /**
-         * Iteration is finished.
-         */
-        public static final short IterationIsFinished = 3;
-
-        /**
-         * Iteration did not started.
-         */
-        public static final short IterationNotStarted = 4;
-
-        /**
-         * The two images have different size or pixel coordinates.
-         */
-        public static final short MismatchedImageLocation = 5;
-
-        /**
-         * The two images use different sample models.
-         */
-        public static final short MismatchedSampleModel = 6;
-
-        /**
-         * The two images have different tile grid.
-         */
-        public static final short MismatchedTileGrid = 7;
-    }
-
-    /**
-     * Constructs a new resource bundle loading data from the given UTF file.
-     *
-     * @param resources  the path of the binary file containing resources, or {@code null} if
-     *        there is no resources. The resources may be a file or an entry in a JAR file.
-     */
-    public Resources(final URL resources) {
-        super(resources);
-    }
-
-    /**
-     * Returns the handle for the {@code Keys} constants.
-     *
-     * @return a handler for the constants declared in the inner {@code Keys} class.
-     */
-    @Override
-    protected KeyConstants getKeyConstants() {
-        return Keys.INSTANCE;
-    }
-
-    /**
-     * Returns resources in the given locale.
-     *
-     * @param  locale  the locale, or {@code null} for the default locale.
-     * @return resources in the given locale.
-     * @throws MissingResourceException if resources can not be found.
-     */
-    public static Resources forLocale(final Locale locale) throws MissingResourceException {
-        return getBundle(Resources.class, locale);
-    }
-
-    /**
-     * Gets a string for the given key from this resource bundle or one of its parents.
-     *
-     * @param  key  the key for the desired string.
-     * @return the string for the given key.
-     * @throws MissingResourceException if no object for the given key can be found.
-     */
-    public static String format(final short key) throws MissingResourceException {
-        return forLocale(null).getString(key);
-    }
-
-    /**
-     * Gets a string for the given key are replace all occurrence of "{0}"
-     * with values of {@code arg0}.
-     *
-     * @param  key   the key for the desired string.
-     * @param  arg0  value to substitute to "{0}".
-     * @return the formatted string for the given key.
-     * @throws MissingResourceException if no object for the given key can be found.
-     */
-    public static String format(final short  key,
-                                final Object arg0) throws MissingResourceException
-    {
-        return forLocale(null).getString(key, arg0);
-    }
-
-    /**
-     * Gets a string for the given key are replace all occurrence of "{0}",
-     * "{1}", with values of {@code arg0}, {@code arg1}.
-     *
-     * @param  key   the key for the desired string.
-     * @param  arg0  value to substitute to "{0}".
-     * @param  arg1  value to substitute to "{1}".
-     * @return the formatted string for the given key.
-     * @throws MissingResourceException if no object for the given key can be found.
-     */
-    public static String format(final short  key,
-                                final Object arg0,
-                                final Object arg1) throws MissingResourceException
-    {
-        return forLocale(null).getString(key, arg0, arg1);
-    }
-}
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
deleted file mode 100644
index 510912e..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-#
-# Resources in this file are for "sis-raster" usage only and should not be used by any other module.
-# For resources shared by all modules in the Apache SIS project, see "org.apache.sis.util.resources" package.
-#
-CoordinateOutsideDomain_2         = The ({0}, {1}) pixel coordinate is outside iterator domain.
-IncompatibleTile_2                = The ({0}, {1}) tile has an unexpected size, number of bands or sample layout.
-IterationIsFinished               = Iteration is finished.
-IterationNotStarted               = Iteration did not started.
-MismatchedImageLocation           = The two images have different size or pixel coordinates.
-MismatchedSampleModel             = The two images use different sample models.
-MismatchedTileGrid                = The two images have different tile grid.
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
deleted file mode 100644
index 9ac7916..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# 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.
-#
-
-#
-# Resources in this file are for "sis-raster" usage only and should not be used by any other module.
-# For resources shared by all modules in the Apache SIS project, see "org.apache.sis.util.resources" package.
-#
-# Punctuation rules in French (source: http://unicode.org/udhr/n/notes_fra.html)
-#
-#   U+202F NARROW NO-BREAK SPACE  before  ; ! and ?
-#   U+00A0 NO-BREAK SPACE         before  :
-#
-CoordinateOutsideDomain_2         = La coordonn\u00e9e pixel ({0}, {1}) est en dehors du domaine de l\u2019it\u00e9rateur.
-IncompatibleTile_2                = La tuile ({0}, {1}) a une taille, un nombre de bandes ou une disposition des valeurs inattendu.
-IterationIsFinished               = L\u2019it\u00e9ration est termin\u00e9e.
-IterationNotStarted               = L\u2019it\u00e9ration n\u2019a pas commenc\u00e9e.
-MismatchedImageLocation           = Les deux images ont une taille ou des coordonn\u00e9es pixels diff\u00e9rentes.
-MismatchedSampleModel             = Les deux images disposent les pixels diff\u00e9remment.
-MismatchedTileGrid                = Les deux images utilisent des grilles de tuiles diff\u00e9rentes.
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/package-info.java b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/package-info.java
deleted file mode 100644
index 8a19ee5..0000000
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/package-info.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * A set of helper classes for the SIS implementation.
- *
- * <p><strong>Do not use!</strong></p>
- *
- * This package is for internal use by SIS only. Classes in this package
- * may change in incompatible ways in any future version without notice.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-package org.apache.sis.internal.raster;
diff --git a/core/sis-raster/src/test/java/org/apache/sis/image/DefaultIteratorTest.java b/core/sis-raster/src/test/java/org/apache/sis/image/DefaultIteratorTest.java
deleted file mode 100644
index 4dadfc0..0000000
--- a/core/sis-raster/src/test/java/org/apache/sis/image/DefaultIteratorTest.java
+++ /dev/null
@@ -1,1135 +0,0 @@
-/*
- * 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.image;
-
-import java.awt.Point;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.image.DataBuffer;
-import java.awt.image.PixelInterleavedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.WritableRaster;
-import java.awt.image.WritableRenderedImage;
-import java.nio.FloatBuffer;
-import org.apache.sis.test.DependsOnMethod;
-import org.apache.sis.test.TestCase;
-import org.junit.After;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-/**
- * Base class of {@link PixelIterator} tests. This base class tests the default read-write iterator
- * on signed short integer values. Subclasses will test variants, for example optimized iterators
- * for some specific sample models.
- *
- * @author  Rémi Maréchal (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-public strictfp class DefaultIteratorTest extends TestCase {
-    /**
-     * The pixel iterator being tested.
-     * This field is initialized by a call to one of the {@code createPixelIterator(…)} methods.
-     */
-    private WritablePixelIterator iterator;
-
-    /**
-     * The raster or image data type as one of the {@link DataBuffer} constants.
-     */
-    private final int dataType;
-
-    /**
-     * <var>x</var> coordinate of upper left corner in raster or image.
-     */
-    private int xmin;
-
-    /**
-     * <var>y</var> coordinate of upper left corner in raster or image.
-     */
-    private int ymin;
-
-    /**
-     * Number of pixels along the <var>x</var> axis in raster or image.
-     */
-    private int width;
-
-    /**
-     * Number of pixels along the <var>y</var> axis in raster or image.
-     */
-    private int height;
-
-    /**
-     * Number of bands in the raster or image.
-     */
-    private int numBands;
-
-    /**
-     * Number of pixels along the <var>x</var> axis of each tile in image tiles.
-     * This is zero if the tests are performed on a raster instead than a tiled image.
-     */
-    private int tileWidth;
-
-    /**
-     * Number of pixels along the <var>y</var> axis of each tile in image tiles.
-     * This is zero if the tests are performed on a raster instead than a tiled image.
-     */
-    private int tileHeight;
-
-    /**
-     * The minimum tile index.
-     */
-    private int minTileX, minTileY;
-
-    /**
-     * The expected values as a flat, row-major array. The content of this array is a copy
-     * of the sample values stored in the raster or image used as a source of test data.
-     */
-    private float[] expected;
-
-    /**
-     * {@code true} for testing write operations in addition of read operations.
-     */
-    private boolean isWritable;
-
-    /**
-     * Creates a new test case for the given data type.
-     *
-     * @param  dataType  the raster or image data type as one of the {@link DataBuffer} constants.
-     */
-    DefaultIteratorTest(final int dataType) {
-        this.dataType = dataType;
-    }
-
-    /**
-     * Creates a new test case.
-     */
-    public DefaultIteratorTest() {
-        this(DataBuffer.TYPE_SHORT);
-    }
-
-    /**
-     * Creates a {@code WritableRaster} to use as the source of test data.
-     * The raster is filled with arbitrary sample values.
-     *
-     * <p><b>Pre-conditions:</b>
-     * before invocation, the {@link #xmin}, {@link #ymin}, {@link #width}, {@link #height} and {@link #numBands}
-     * fields must be initialized.</p>
-     *
-     * @param  subArea  the raster subarea on which to perform iteration, or {@code null} for the whole area.
-     * @return a raster filled with arbitrary sample values.
-     */
-    private WritableRaster createRaster(final Rectangle subArea) {
-        final int xmax = xmin + width;                              // Maximum value is exclusive.
-        final int ymax = ymin + height;
-        final int subMinX, subMinY, subMaxX, subMaxY;
-        if (subArea == null) {
-            subMinX = xmin;
-            subMinY = ymin;
-            subMaxX = xmax;
-            subMaxY = ymax;
-        } else {
-            subMinX = StrictMath.max(xmin, subArea.x);
-            subMinY = StrictMath.max(ymin, subArea.y);
-            subMaxX = StrictMath.min(xmax, subArea.x + subArea.width);
-            subMaxY = StrictMath.min(ymax, subArea.y + subArea.height);
-        }
-        expected = new float[StrictMath.max(subMaxX - subMinX, 0) * StrictMath.max(subMaxY - subMinY, 0) * numBands];
-        final WritableRaster raster = Raster.createWritableRaster(new PixelInterleavedSampleModel(dataType,
-                width, height, numBands, width * numBands, TiledImage.bandOffsets(numBands)), new Point(xmin, ymin));
-        /*
-         * At this point, all data structures have been created an initialized to zero sample values.
-         * Now fill the data structures with arbitrary values.
-         */
-        int n = 0;
-        float value = (dataType == DataBuffer.TYPE_FLOAT) ? -100.5f : 100f;
-        for (int y=ymin; y<ymax; y++) {
-            final boolean rowIncluded = (y >= subMinY && y < subMaxY);
-            for (int x=xmin; x<xmax; x++) {
-                final boolean included = rowIncluded && (x >= subMinX && x < subMaxX);
-                for (int b = 0; b < numBands; b++) {
-                    raster.setSample(x, y, b, value);
-                    if (included) {
-                        expected[n++] = value;
-                    }
-                    value++;
-                }
-            }
-            value += 10;                // Arbitrary offset.
-        }
-        assertEquals("Number of expected values", expected.length, n);
-        return raster;
-    }
-
-    /**
-     * Creates a {@code RenderedImage} to use as the source of test data.
-     * The image is filled with arbitrary sample values.
-     *
-     * <p><b>Pre-conditions:</b>
-     * before invocation, the {@link #xmin}, {@link #ymin}, {@link #width}, {@link #height},
-     * {@link #tileWidth}, {@link #tileHeight} and {@link #numBands} fields must be initialized.</p>
-     *
-     * @param  subArea  the image subarea on which to perform iteration, or {@code null} for the whole area.
-     * @return an image filled with arbitrary sample values.
-     */
-    private WritableRenderedImage createImage(final Rectangle subArea) {
-        assertEquals(0, width  % tileWidth);
-        assertEquals(0, height % tileHeight);
-        final int numXTiles = (width  + tileWidth -1) / tileWidth;
-        final int numYTiles = (height + tileHeight-1) / tileHeight;
-        final int xmax = xmin + width;                                  // Maximum value is exclusive.
-        final int ymax = ymin + height;
-        final int subMinX, subMinY, subMaxX, subMaxY;
-        if (subArea == null) {
-            subMinX = xmin;
-            subMinY = ymin;
-            subMaxX = xmax;
-            subMaxY = ymax;
-        } else {
-            subMinX = StrictMath.max(xmin, subArea.x);
-            subMinY = StrictMath.max(ymin, subArea.y);
-            subMaxX = StrictMath.min(xmax, subArea.x + subArea.width);
-            subMaxY = StrictMath.min(ymax, subArea.y + subArea.height);
-        }
-        expected = new float[StrictMath.max(subMaxX - subMinX, 0) * StrictMath.max(subMaxY - subMinY, 0) * numBands];
-        final TiledImage image = new TiledImage(dataType, numBands, xmin, ymin, width, height, tileWidth, tileHeight, minTileX, minTileY);
-        /*
-         * At this point, all data structures have been created an initialized to zero sample values.
-         * Now fill the data structures with arbitrary values. We fill them tile-by-tile.
-         */
-        int n = 0;
-        float value = (dataType == DataBuffer.TYPE_FLOAT) ? -100.5f : 100f;
-        for (int j=0; j<numYTiles; j++) {
-            for (int i=0; i<numXTiles; i++) {
-                final int yNextTile = ymin + (j+1) * tileHeight;
-                for (int y = yNextTile - tileHeight; y < yNextTile; y++) {
-                    final boolean rowIncluded = (y >= subMinY && y < subMaxY);
-                    final int xNextTile = xmin + (i+1) * tileWidth;
-                    for (int x = xNextTile - tileWidth; x < xNextTile; x++) {
-                        final boolean included = rowIncluded && (x >= subMinX && x < subMaxX);
-                        for (int b = 0; b < numBands; b++) {
-                            image.setSample(x, y, b, value);
-                            if (included) {
-                                expected[n++] = value;
-                            }
-                            value++;
-                        }
-                    }
-                    value += 4;         // Arbitrary offset.
-                }
-                value += 7;             // Arbitrary offset.
-            }
-            value += 10;                // Arbitrary offset.
-        }
-        assertEquals("Number of expected values", expected.length, n);
-        return image;
-    }
-
-    /**
-     * Creates a {@code PixelIterator} for a sub-area of given raster.
-     * The iterator shall be assigned to the {@link #iterator} field.
-     *
-     * <p>The default implementation creates {@link DefaultIterator} instances.
-     * Tests for other kinds of iterator need to override.</p>
-     *
-     * @param  raster   the data on which to perform iteration.
-     * @param  subArea  the boundary of the raster sub-area where to perform iteration.
-     */
-    void createPixelIterator(WritableRaster raster, Rectangle subArea) {
-        iterator = new DefaultIterator(raster, isWritable ? raster : null, subArea, null);
-        assertEquals("isWritable", isWritable, iterator.isWritable());
-    }
-
-    /**
-     * Creates a {@code PixelIterator} for a sub-area of given image.
-     * The iterator shall be assigned to the {@link #iterator} field.
-     *
-     * <p>The default implementation creates {@link DefaultIterator} instances.
-     * Tests for other kinds of iterator need to override.</p>
-     *
-     * @param  image    the data on which to perform iteration.
-     * @param  subArea  the boundary of the image sub-area where to perform iteration.
-     */
-    void createPixelIterator(WritableRenderedImage image, Rectangle subArea) {
-        iterator = new DefaultIterator(image, isWritable ? image : null, subArea, null);
-        assertEquals("isWritable", isWritable, iterator.isWritable());
-    }
-
-    /**
-     * Creates a {@code PixelIterator} for a window in the given image.
-     * The iterator shall be assigned to the {@link #iterator} field.
-     *
-     * <p>The default implementation creates {@link DefaultIterator} instances.
-     * Tests for other kinds of iterator need to override.</p>
-     *
-     * @param  image    the data on which to perform iteration.
-     * @param  window   size of the window to use in {@link PixelIterator#createWindow(TransferType)} method.
-     */
-    void createWindowIterator(WritableRenderedImage image, Dimension window) {
-        iterator = new DefaultIterator(image, isWritable ? image : null, null, window);
-        assertEquals("isWritable", isWritable, iterator.isWritable());
-    }
-
-    /**
-     * Invoked after every tests for releasing resources.
-     */
-    @After
-    public void dispose() {
-        iterator.close();
-    }
-
-    /**
-     * Verifies the sample value at current iterator position.
-     * If the iterator is writable, tests also setting a value.
-     *
-     * @param  i  index in {@link #expected} array.
-     * @param  b  band number at current iterator position.
-     */
-    private void verifySample(final int i, final int b) {
-        final float e = expected[i];
-        final float a = iterator.getSampleFloat(b);
-        if (Float.floatToRawIntBits(a) != Float.floatToRawIntBits(e)) {
-            fail("Pixel iteration at index " + i + ": expected " + e + " but got " + a);
-        }
-        if (isWritable) {
-            final float newValue = a + 20;
-            iterator.setSample(b, newValue);
-            assertEquals("Verification after write", newValue, iterator.getSampleFloat(b), 0f);
-            expected[i] = newValue;
-        }
-    }
-
-    /**
-     * Iterates over all values returned by the current {@link #iterator} and compares with expected values.
-     *
-     * @param  verifyIndices  whether to verify also iterator {@code getPosition()} return values.
-     *                        This is usually {@code true} if an only if the iterator cover the full raster area.
-     *
-     * @see #verifyIterationAfterMove(int, int)
-     * @see #verifyWindow(Dimension)
-     */
-    private void verifyIteration(final boolean verifyIndices) {
-        int i = 0;
-        while (iterator.next()) {
-            for (int b=0; b<numBands; b++) {
-                verifySample(i, b);
-                if (verifyIndices) {
-                    final int p = i / numBands;
-                    final Point position = iterator.getPosition();
-                    assertEquals("x", (p % width) + xmin, position.x);
-                    assertEquals("y", (p / width) + ymin, position.y);
-                }
-                i++;
-            }
-        }
-        assertEquals("Too few elements in iteration.", expected.length, i);
-    }
-
-    /**
-     * Tests iteration over all pixels in a single raster.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    public void testOnRaster() {
-        width    =  7;
-        height   = 10;
-        numBands =  3;
-        createPixelIterator(createRaster(null), null);
-        verifyIteration(true);
-    }
-
-    /**
-     * Tests {@link PixelIterator#rewind()}.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testRasterRewind() {
-        xmin     = -3;
-        ymin     = -5;
-        width    =  8;
-        height   =  7;
-        numBands =  2;
-        createPixelIterator(createRaster(null), null);
-        verifyIteration(true);
-
-        iterator.rewind();
-        verifyIteration(true);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a single raster.
-     * This test iterates in the upper-left corner of the raster.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testOnRasterUpperLeft() {
-        xmin     =  5;
-        ymin     =  7;
-        width    =  9;
-        height   =  8;
-        numBands =  3;
-        final Rectangle subArea = new Rectangle(4, 6, 5, 4);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a single raster.
-     * This test iterates in the upper-right corner of the raster.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testOnRasterUpperRight() {
-        xmin     = 11;
-        ymin     = 12;
-        width    = 10;
-        height   = 11;
-        numBands =  1;
-        final Rectangle subArea = new Rectangle(16, 9, 10, 6);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a single raster.
-     * This test iterates in the lower-right corner of the raster.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testOnRasterLowerRight() {
-        xmin     = -4;
-        ymin     = -6;
-        width    =  8;
-        height   =  8;
-        numBands =  4;
-        final Rectangle subArea = new Rectangle(2, -2, 10, 12);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a single raster.
-     * This test iterates in the lower-left corner of the raster.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testOnRasterLowerLeft() {
-        xmin     =  6;
-        ymin     =  7;
-        width    =  5;
-        height   =  9;
-        numBands =  3;
-        final Rectangle subArea = new Rectangle(3, 10, 4, 9);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a single raster.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     * This method tests also {@link PixelIterator#rewind()}.
-     */
-    @Test
-    @DependsOnMethod({"testOnRaster", "testRasterRewind"})
-    public void testOnRasterSubArea() {
-        xmin     =  5;
-        ymin     =  7;
-        width    = 17;
-        height   = 16;
-        numBands =  2;
-        final Rectangle subArea = new Rectangle(10, 9, 8, 6);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-
-        iterator.rewind();
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area that actually contains all the raster area.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     * This method tests also {@link PixelIterator#rewind()}.
-     */
-    @Test
-    @DependsOnMethod({"testOnRaster", "testRasterRewind"})
-    public void testOnRasterFullArea() {
-        xmin     =  7;
-        ymin     =  9;
-        width    = 11;
-        height   = 17;
-        numBands =  3;
-        final Rectangle subArea = new Rectangle(2, 3, 25, 17);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(true);
-
-        iterator.rewind();
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area that do not intersect the raster area.
-     * Raster location and number of bands are different than other tests (each test uses arbitrary values).
-     * This method tests also {@link PixelIterator#rewind()}.
-     */
-    @Test
-    @DependsOnMethod({"testOnRaster", "testRasterRewind"})
-    public void testOnRasterEmptyArea() {
-        xmin     = 6;
-        ymin     = 5;
-        width    = 3;
-        height   = 2;
-        numBands = 3;
-        final Rectangle subArea = new Rectangle(-17, -20, 5, 15);
-        createPixelIterator(createRaster(subArea), subArea);
-        assertEquals("Expected an empty set of values.", 0, expected.length);
-        verifyIteration(true);
-
-        iterator.rewind();
-        verifyIteration(false);
-    }
-
-    /**
-     * Verifies that invoking {@link PixelIterator#moveTo(int, int)} with illegal indices causes
-     * an exception to be thrown.
-     */
-    @Test
-    public void testIllegalMoveOnRaster() {
-        xmin     =  4;
-        ymin     =  7;
-        width    =  5;
-        height   =  4;
-        numBands =  1;
-        createPixelIterator(createRaster(null), null);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        try {
-            iterator.moveTo(2, 3);
-            fail("Expected IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-            assertNotNull(e.getMessage());
-        }
-        try {
-            iterator.moveTo(9, 3);
-            fail("Expected IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-            assertNotNull(e.getMessage());
-        }
-        try {
-            iterator.moveTo(2, 10);
-            fail("Expected IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-            assertNotNull(e.getMessage());
-        }
-    }
-
-    /**
-     * Tests iteration over all pixels in a tiled image.
-     * Image location and number of bands are different than other tests (each test uses arbitrary values).
-     * This method tests also {@link PixelIterator#rewind()}.
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testOnImage() {
-        width      =  24;
-        height     =  15;
-        tileWidth  =   8;
-        tileHeight =   5;
-        numBands   =   3;
-        createPixelIterator(createImage(null), null);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over all pixels in a tiled image.
-     * Image location and number of bands are different than other tests (each test uses arbitrary values).
-     * This method tests also {@link PixelIterator#rewind()}.
-     */
-    @Test
-    @DependsOnMethod("testOnImage")
-    public void testImageRewind() {
-        xmin       =   1;
-        ymin       =  -4;
-        width      =  24;
-        height     =  15;
-        tileWidth  =   8;
-        tileHeight =   5;
-        numBands   =   2;
-        createPixelIterator(createImage(null), null);
-        verifyIteration(false);
-
-        iterator.rewind();
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the upper-left corner of the image.
-     * The sub-area is small enough for the iteration to happen in a single tile.
-     * Image location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testOnRasterUpperLeft"})
-    public void testOnTileUpperLeft() {
-        xmin       = -5;
-        ymin       =  5;
-        width      = 20;
-        height     = 10;
-        tileWidth  =  4;
-        tileHeight =  5;
-        numBands   =  1;
-        minTileX   = -1;
-        final Rectangle subArea = new Rectangle(-10, -20, 8, 28);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the upper-right corner of the image.
-     * The sub-area is small enough for the iteration to happen in a single tile.
-     * Image location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testOnRasterUpperRight"})
-    public void testOnTileUpperRight() {
-        xmin       = 35;
-        ymin       =  7;
-        width      = 15;
-        height     = 12;
-        tileWidth  =  5;
-        tileHeight =  3;
-        numBands   =  3;
-        minTileY   = -2;
-        final Rectangle subArea = new Rectangle(45, -20, 30, 29);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the lower-right corner of the image.
-     * The sub-area is small enough for the iteration to happen in a single tile.
-     * Image location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testOnRasterLowerRight"})
-    public void testOnTileLowerRight() {
-        xmin       = 55;
-        ymin       = -7;
-        width      = 18;
-        height     = 16;
-        tileWidth  =  6;
-        tileHeight =  4;
-        numBands   =  2;
-        minTileX   = 12;
-        minTileY   = 20;
-        final Rectangle subArea = new Rectangle(68, 5, 4, 4);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the lower-left corner of the image.
-     * The sub-area is small enough for the iteration to happen in a single tile.
-     * Image location and number of bands are different than other tests (each test uses arbitrary values).
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testOnRasterLowerLeft"})
-    public void testOnTileLowerLeft() {
-        xmin       =   2;
-        ymin       = -15;
-        width      =  21;
-        height     =  20;
-        tileWidth  =   7;
-        tileHeight =   5;
-        numBands   =   3;
-        minTileX   = -12;
-        minTileY   =  20;
-        final Rectangle subArea = new Rectangle(0, 0, 9, 50);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * The sub-area is small enough for the iteration to happen in a single tile.
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testOnRasterSubArea"})
-    public void testOnTileSubArea() {
-        xmin       = -5;
-        ymin       =  7;
-        width      = 15;
-        height     = 24;
-        tileWidth  =  5;
-        tileHeight =  6;
-        numBands   =  2;
-        minTileX   =  2;
-        minTileY   =  3;
-        final Rectangle subArea = new Rectangle(6, 20, 4, 5);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the upper-left corner of the image.
-     * The sub-area is large enough for covering more than one tile.
-     */
-    @Test
-    @DependsOnMethod("testOnTileUpperLeft")
-    public void testOnImageUpperLeft() {
-        xmin       = -5;
-        ymin       =  5;
-        width      = 27;
-        height     = 20;
-        tileWidth  =  9;
-        tileHeight =  5;
-        numBands   =  3;
-        minTileX   =  8;
-        minTileY   =  8;
-        final Rectangle subArea = new Rectangle(-10, -5, 25, 22);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the upper-right corner of the image.
-     * The sub-area is large enough for covering more than one tile.
-     */
-    @Test
-    @DependsOnMethod("testOnTileUpperRight")
-    public void testOnImageUpperRight() {
-        xmin       = 20;
-        ymin       =  0;
-        width      = 25;
-        height     = 24;
-        tileWidth  =  5;
-        tileHeight =  6;
-        numBands   =  2;
-        minTileX   = -2;
-        minTileY   = 20;
-        final Rectangle subArea = new Rectangle(27, -20, 30, 37);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the lower-right corner of the image.
-     * The sub-area is large enough for covering more than one tile.
-     */
-    @Test
-    @DependsOnMethod("testOnTileLowerRight")
-    public void testOnImageLowerRight() {
-        xmin       = 30;
-        ymin       =  1;
-        width      = 15;
-        height     = 12;
-        tileWidth  =  3;
-        tileHeight =  4;
-        numBands   =  4;
-        minTileX   =  1;
-        minTileY   =  2;
-        final Rectangle subArea = new Rectangle(36, 8, 12, 20);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * This test iterates in the lower-left corner of the image.
-     * The sub-area is large enough for covering more than one tile.
-     */
-    @Test
-    @DependsOnMethod("testOnTileLowerLeft")
-    public void testOnImageLowerLeft() {
-        xmin       = -2;
-        ymin       = -7;
-        width      = 15;
-        height     = 16;
-        tileWidth  =  5;
-        tileHeight =  4;
-        numBands   =  1;
-        minTileX   = -9;
-        minTileY   = -9;
-        final Rectangle subArea = new Rectangle(-20, -1, 30, 20);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area in a tiled image.
-     * The sub-area is large enough for covering more than one tile.
-     */
-    @Test
-    @DependsOnMethod("testOnTileSubArea")
-    public void testOnImageSubArea() {
-        xmin       =  -5;
-        ymin       =   7;
-        width      =  70;
-        height     =  48;
-        tileWidth  =   7;
-        tileHeight =   4;
-        numBands   =   2;
-        minTileX   = -12;
-        minTileY   = -20;
-        final Rectangle subArea = new Rectangle(20, 10, 30, 25);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a all the region of a tiled image.
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testOnRasterFullArea"})
-    public void testOnImageFullArea() {
-        xmin       =  -5;
-        ymin       =  -3;
-        width      =  60;
-        height     =  50;
-        tileWidth  =   6;
-        tileHeight =   5;
-        numBands   =   1;
-        minTileX   = 999;
-        minTileY   = -99;
-        final Rectangle subArea = new Rectangle(-10, -10, 150, 80);
-        createPixelIterator(createImage(subArea), subArea);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-    }
-
-    /**
-     * Tests iteration over a sub-area that do not intersect the image area.
-     */
-    @Test
-    @DependsOnMethod("testOnRasterEmptyArea")
-    public void testOnImageEmptyArea() {
-        xmin       = 5;
-        ymin       = 6;
-        width      = 8;
-        height     = 9;
-        tileWidth  = 2;
-        tileHeight = 3;
-        numBands   = 2;
-        final Rectangle subArea = new Rectangle(-100, -50, 5, 17);
-        createPixelIterator(createImage(subArea), subArea);
-        assertEquals("Expected an empty set of values.", 0, expected.length);
-        verifyIteration(true);
-    }
-
-    /**
-     * Verifies that invoking {@link PixelIterator#moveTo(int, int)} with illegal indices causes
-     * an exception to be thrown.
-     */
-    @Test
-    @DependsOnMethod("testIllegalMoveOnRaster")
-    public void testIllegalMoveOnImage() {
-        xmin       =  0;
-        ymin       =  0;
-        width      =  8;
-        height     =  6;
-        tileWidth  =  4;
-        tileHeight =  3;
-        numBands   =  1;
-        createPixelIterator(createImage(null), null);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        try {
-            iterator.moveTo(102, 53);
-            fail("Expected IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-            assertNotNull(e.getMessage());
-        }
-    }
-
-    /**
-     * Verifies that invoking {@link PixelIterator#next()} after iteration end causes an exception to be thrown.
-     */
-    @Test
-    @DependsOnMethod("testOnImage")
-    public void testIllegalNext() {
-        xmin       = -1;
-        ymin       =  3;
-        width      =  8;
-        height     =  6;
-        tileWidth  =  4;
-        tileHeight =  3;
-        numBands   =  1;
-        createPixelIterator(createImage(null), null);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyIteration(false);
-        try {
-            iterator.next();
-            fail("Expected IllegalStateException.");
-        } catch (IllegalStateException e) {
-            assertNotNull(e.getMessage());
-        }
-    }
-
-    /**
-     * Tests {@link PixelIterator#getPosition()}.
-     */
-    @Test
-    public void testGetPosition() {
-        xmin       =  56;
-        ymin       =   1;
-        width      =  20;
-        height     =  24;
-        tileWidth  =   5;
-        tileHeight =   8;
-        numBands   =   2;
-        minTileX   =  10;
-        minTileY   = 100;
-        createPixelIterator(createImage(null), null);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        int i = 0;
-        for (int ty = 0; ty < height/tileHeight; ty++) {
-            for (int tx = 0; tx < width/tileWidth; tx++) {
-                for (int y = 0; y<tileHeight; y++) {
-                    for (int x = 0; x<tileWidth; x++) {
-                        assertTrue(iterator.next());
-                        final Point position = iterator.getPosition();
-                        assertEquals("x", tx*tileWidth  + x + xmin, position.x);
-                        assertEquals("y", ty*tileHeight + y + ymin, position.y);
-                        for (int b=0; b<numBands; b++) {
-                            assertEquals(expected[i++], iterator.getSampleFloat(b), 0f);
-                        }
-                    }
-                }
-            }
-        }
-        assertEquals("Too few elements in iteration.", expected.length, i);
-    }
-
-    /**
-     * Moves the iterator to the given position and verifies the iteration.
-     * This method is used for implementation of {@code testMoveXXX()} methods.
-     *
-     * @see #verifyIteration(boolean)
-     * @see #verifyWindow(Dimension)
-     */
-    private void verifyIterationAfterMove(int x, int y) {
-        /*
-         * Move the iterator and verify location after the move.
-         */
-        iterator.moveTo(x, y);
-        final Point p = iterator.getPosition();
-        assertEquals("x", x, p.x);
-        assertEquals("y", y, p.y);
-        /*
-         * Compute index of the (x,y) position in the array of expected values.
-         * Iteration verification will need to begin at that value.
-         */
-        x -= xmin;
-        y -= ymin;
-        int i;
-        if (tileWidth == 0 && tileHeight == 0) {
-            i = y * width + x;
-        } else {
-            final int tx = x / tileWidth;
-            final int ty = y / tileHeight;
-            final int numTileX = (width + tileWidth - 1) / tileWidth;
-            i = ((ty * (numTileX - 1) + tx) * tileHeight + y - tx) * tileWidth + x;
-        }
-        i *= numBands;
-        /*
-         * Iteration verification happens here. Note that contrarily to 'verifyIteration(boolean)' method,
-         * we use a do … while loop instead than a while loop because the call to 'moveTo(x, y)' should be
-         * understood as an implicit 'next()' method call.
-         */
-        do {
-            for (int b=0; b<numBands; b++) {
-                verifySample(i++, b);
-            }
-        } while (iterator.next());
-        assertEquals("Too few elements in iteration.", expected.length, i);
-    }
-
-    /**
-     * Tests iteration after a call to {@link PixelIterator#moveTo(int, int)} in a raster.
-     */
-    @Test
-    @DependsOnMethod("testOnRaster")
-    public void testMoveIntoRaster() {
-        xmin     =  5;
-        ymin     =  7;
-        width    =  8;
-        height   =  9;
-        numBands =  2;
-        createPixelIterator(createRaster(null), null);
-        verifyIterationAfterMove(8, 10);
-    }
-
-    /**
-     * Tests iteration after a call to {@link PixelIterator#moveTo(int, int)} in a tiled image.
-     */
-    @Test
-    @DependsOnMethod({"testOnImage", "testMoveIntoRaster"})
-    public void testMoveIntoImage() {
-        xmin       =  -1;
-        ymin       =   3;
-        width      =  12;
-        height     =  15;
-        tileWidth  =   4;
-        tileHeight =   5;
-        numBands   =   1;
-        minTileX   = 120;
-        minTileY   = 200;
-        createPixelIterator(createImage(null), null);
-        verifyIterationAfterMove(7, 5);
-    }
-
-    /**
-     * Verifies {@link PixelIterator#createWindow(TransferType)}.
-     * This method assumes that the iterator traverses the full image (no sub-area).
-     *
-     * @see #verifyIteration(boolean)
-     * @see #verifyIterationAfterMove(int, int)
-     */
-    private void verifyWindow(final Dimension window) {
-        final PixelIterator.Window<FloatBuffer> w = iterator.createWindow(TransferType.FLOAT);
-        final FloatBuffer values = w.values;
-        final int tileSize   = tileWidth * tileHeight;
-        final int tileStride = tileSize * (width / tileWidth);
-        while (iterator.next()) {
-            final Point pos = iterator.getPosition();
-            pos.translate(-xmin, -ymin);
-            w.update();
-            for (int y=0; y<window.height; y++) {
-                int p,t;
-                p  = pos.y + y;
-                t  = p / tileHeight;
-                p %=     tileHeight;
-                final int start = t * tileStride + p * tileWidth;
-                for (int x=0; x<window.width; x++) {
-                    p  = pos.x + x;
-                    t  = p / tileWidth;
-                    p %=     tileWidth;
-                    int offset = (start + t * tileSize + p) * numBands;
-                    for (int b=0; b<numBands; b++) {
-                        final float e = expected[offset++];
-                        final float a = values.get();
-                        if (Float.floatToRawIntBits(a) != Float.floatToRawIntBits(e)) {
-                            fail("Index (" + x + ", " + y + ") in window starting at index ("
-                                    + pos.x + ", " + pos.y + "), band " + b + ": expected " + e + " but got " + a);
-                        }
-                    }
-                }
-            }
-            assertEquals("buffer.remaining()", 0, values.remaining());
-        }
-    }
-
-    /**
-     * Tests {@link PixelIterator#createWindow(TransferType)} on a single tile.
-     */
-    @Test
-    @DependsOnMethod("testMoveIntoImage")
-    public void testWindowOnTile() {
-        xmin       =   1;
-        ymin       =  -2;
-        width      =   8;
-        height     =  10;
-        numBands   =   2;
-        tileWidth  = width;
-        tileHeight = height;
-        final Dimension window = new Dimension(3, 4);
-        createWindowIterator(createImage(null), window);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyWindow(window);
-    }
-
-    /**
-     * Tests {@link PixelIterator#createWindow(TransferType)} on a tiled image.
-     */
-    @Test
-    @DependsOnMethod("testWindowOnTile")
-    public void testWindowOnImage() {
-        xmin       =   1;
-        ymin       =  -2;
-        width      =   9;
-        height     =  12;
-        tileWidth  =   3;
-        tileHeight =   4;
-        numBands   =   2;
-        minTileX   = 100;
-        minTileY   = 200;
-        final Dimension window = new Dimension(2, 3);
-        createWindowIterator(createImage(null), window);
-        assertTrue("Expected a non-empty set of values.", expected.length != 0);
-        verifyWindow(window);
-    }
-
-    /**
-     * Tests write operations in a single raster.
-     * The destination image is the same than the source image.
-     */
-    @Test
-    @DependsOnMethod("testOnRasterSubArea")
-    public void testOnWritableRaster() {
-        isWritable = true;
-        testOnRasterSubArea();
-    }
-
-    /**
-     * Tests write operations in a single tile of an image.
-     * The destination image is the same than the source image.
-     */
-    @Test
-    @DependsOnMethod({"testOnWritableRaster", "testOnTileSubArea"})
-    public void testOnWritableTile() {
-        isWritable = true;
-        testOnTileSubArea();
-    }
-
-    /**
-     * Tests write operations in a tiled image.
-     * The destination image is the same than the source image.
-     */
-    @Test
-    @DependsOnMethod({"testOnWritableTile", "testOnImageSubArea"})
-    public void testOnWritableImage() {
-        isWritable = true;
-        testOnImageSubArea();
-    }
-}
diff --git a/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java b/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java
deleted file mode 100644
index 23d398b..0000000
--- a/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * 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.image;
-
-import java.awt.Image;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.image.ColorModel;
-import java.awt.image.PixelInterleavedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.TileObserver;
-import java.awt.image.WritableRaster;
-import java.awt.image.WritableRenderedImage;
-import java.util.Vector;
-
-import static org.junit.Assert.*;
-
-
-/**
- * A rendered image which can contain an arbitrary number of tiles. Tiles are stored in memory.
- * We use this class for testing purpose only because tiled images in production need a more
- * sophisticated implementation capable to store some tiles on disk (for memory consumption reasons).
- *
- * @author  Rémi Maréchal (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-final class TiledImage implements WritableRenderedImage {
-    /**
-     * The minimum X or Y coordinate (inclusive) of the rendered image.
-     */
-    private final int minX, minY;
-
-    /**
-     * Number of pixels along X or Y axis in the whole rendered image.
-     */
-    private final int width, height;
-
-    /**
-     * Number of pixels along X or Y axis in a single tile of the image.
-     * All tiles must have the same size.
-     */
-    private final int tileWidth, tileHeight;
-
-    /**
-     * Number of tiles in the X or Y direction. This is computed from the image size and tile size.
-     */
-    private final int numXTiles, numYTiles;
-
-    /**
-     * The minimum tile index in the X or Y direction.
-     */
-    private final int minTileX, minTileY;
-
-    /**
-     * The tiles, created when first needed.
-     */
-    private final WritableRaster[] tiles;
-
-    /**
-     * The sample model to use for creating the tiles.
-     */
-    private final SampleModel sampleModel;
-
-    /**
-     * Indices of acquired tiles. Those indices are valid only if {@link #isTileAcquired} is {@code true}.
-     */
-    private int acquiredTileX, acquiredTileY;
-
-    /**
-     * Whether a tile has been acquired by a call to {@link #getWritableTile(int, int)} and not yet released.
-     */
-    private boolean isTileAcquired;
-
-    /**
-     * Creates a new tiled image.
-     *
-     * @param dataType  sample data type as one of the {@link java.awt.image.DataBuffer} constants.
-     * @param numBands  number of bands in the sample model to create.
-     */
-    TiledImage(final int dataType,  final int numBands,
-               final int minX,      final int minY,
-               final int width,     final int height,
-               final int tileWidth, final int tileHeight,
-               final int minTileX,  final int minTileY)
-    {
-        this.minX        = minX;
-        this.minY        = minY;
-        this.width       = width;
-        this.height      = height;
-        this.tileWidth   = tileWidth;
-        this.tileHeight  = tileHeight;
-        this.minTileX    = minTileX;
-        this.minTileY    = minTileY;
-        this.numXTiles   = (width  + tileWidth  - 1) / tileWidth;      // Round toward upper integer value.
-        this.numYTiles   = (height + tileHeight - 1) / tileHeight;
-        this.tiles       = new WritableRaster[numXTiles * numYTiles];
-        this.sampleModel = new PixelInterleavedSampleModel(dataType, tileWidth, tileHeight,
-                                numBands, tileWidth * numBands, bandOffsets(numBands));
-    }
-
-    /**
-     * Returns arbitrary band offsets for the given number of bands.
-     */
-    static int[] bandOffsets(final int numBands) {
-        final int[] bandOffsets = new int[numBands];
-        for (int i=1; i<numBands; i++) {
-            bandOffsets[i] = i;
-        }
-        return bandOffsets;
-    }
-
-    /*
-     * No source, no property, no color model since this test images is not for rendering on screen.
-     */
-    @Override public Vector<RenderedImage> getSources()             {return null;}
-    @Override public Object                getProperty(String name) {return Image.UndefinedProperty;}
-    @Override public String[]              getPropertyNames()       {return null;}
-    @Override public ColorModel            getColorModel()          {return null;}
-    @Override public SampleModel           getSampleModel()         {return sampleModel;}
-
-    /*
-     * Information specified to the constructor.
-     */
-    @Override public int getMinX()            {return minX;}
-    @Override public int getMinY()            {return minY;}
-    @Override public int getWidth()           {return width;}
-    @Override public int getHeight()          {return height;}
-    @Override public int getTileWidth()       {return tileWidth;}
-    @Override public int getTileHeight()      {return tileHeight;}
-    @Override public int getNumXTiles()       {return numXTiles;}
-    @Override public int getNumYTiles()       {return numYTiles;}
-    @Override public int getMinTileX()        {return minTileX;}
-    @Override public int getMinTileY()        {return minTileY;}
-    @Override public int getTileGridXOffset() {return minX - (minTileX * tileWidth);}
-    @Override public int getTileGridYOffset() {return minY - (minTileY * tileHeight);}
-
-    /**
-     * Sets a sample value at the given location in pixel coordinates.
-     * This is a helper method for testing purpose on small images only,
-     * since invoking this method in a loop is inefficient.
-     */
-    final void setSample(final int x, final int y, final int b, final double value) {
-        final int ox = x - minX;
-        final int oy = y - minY;
-        if (ox < 0 || ox >= width || oy < 0 || oy >= height) {
-            throw new IndexOutOfBoundsException();
-        }
-        tile(ox / tileWidth  + minTileX,
-             oy / tileHeight + minTileY).setSample(x, y, b, value);
-    }
-
-    /**
-     * Returns the tile at the given location in tile coordinates.
-     * This method verifies that no writable raster have been acquired. Actually this conditions is not part of
-     * {@link WritableRenderedImage} contract, since a readable and writable rasters can be used in same time.
-     * But we add this condition because they way {@link PixelIterator} are currently implemented, it would be
-     * a bug if we ask for a readable tile while we already have a writable one. This condition may change in
-     * any future Apache SIS version.
-     */
-    @Override
-    public Raster getTile(final int tileX, final int tileY) {
-        assertFalse("isTileAcquired", isTileAcquired);              // See javadoc.
-        return tile(tileX, tileY);
-    }
-
-    /**
-     * Returns the tile at the given location tile coordinates.
-     */
-    @Override
-    public WritableRaster getWritableTile(final int tileX, final int tileY) {
-        assertFalse("isTileAcquired", isTileAcquired);
-        isTileAcquired = true;
-        acquiredTileX  = tileX;
-        acquiredTileY  = tileY;
-        return tile(tileX, tileY);
-    }
-
-    /**
-     * Returns the tile at the given index without any verification. It is caller responsibility to verify if this
-     * method is invoked in a consistent context (for example after a writable raster has been properly acquired).
-     */
-    private WritableRaster tile(int tileX, int tileY) {
-        if ((tileX -= minTileX) < 0 || tileX >= numXTiles ||
-            (tileY -= minTileY) < 0 || tileY >= numYTiles)
-        {
-            throw new IndexOutOfBoundsException();
-        }
-        final int i = tileY * numXTiles + tileX;
-        WritableRaster raster = tiles[i];
-        if (raster == null) {
-            tiles[i] = raster = Raster.createWritableRaster(sampleModel,
-                    new Point(tileX * tileWidth  + minX,
-                              tileY * tileHeight + minY));
-        }
-        return raster;
-    }
-
-    /**
-     * Verifies that the given tile has been acquired.
-     */
-    @Override
-    public void releaseWritableTile(final int tileX, final int tileY) {
-        assertTrue("isTileAcquired", isTileAcquired);
-        assertEquals("tileX", acquiredTileX, tileX);
-        assertEquals("tileY", acquiredTileY, tileY);
-        isTileAcquired = false;
-    }
-
-    /**
-     * Returns {@code true} if the given tile indices are the one given to the last call to
-     * {@link #getWritableTile(int, int)} and that tile has not yet been released.
-     */
-    @Override
-    public boolean isTileWritable(final int tileX, final int tileY) {
-        return isTileAcquired && (tileX == acquiredTileX) && (tileY == acquiredTileY);
-    }
-
-    /**
-     * Returns {@code false} since we do not keep track of who called {@link #getWritableTile(int,int)}.
-     */
-    @Override
-    public boolean hasTileWriters() {
-        return isTileAcquired;
-    }
-
-    /**
-     * Returns the indices of acquired tile, or {@code null} if none.
-     */
-    @Override
-    public Point[] getWritableTileIndices() {
-        return isTileAcquired ? new Point[] {new Point(acquiredTileX, acquiredTileY)} : null;
-    }
-
-    /**
-     * Unsupported since we do not need tile observers for the tests.
-     */
-    @Override
-    public void addTileObserver(TileObserver to) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Ignored since no listener can have been registered.
-     */
-    @Override
-    public void removeTileObserver(TileObserver to) {
-    }
-
-    /*
-     * Not needed for the tests.
-     */
-    @Override public Raster         getData()                       {throw new UnsupportedOperationException();}
-    @Override public Raster         getData(Rectangle rect)         {throw new UnsupportedOperationException();}
-    @Override public void           setData(Raster r)               {throw new UnsupportedOperationException();}
-    @Override public WritableRaster copyData(WritableRaster raster) {throw new UnsupportedOperationException();}
-}
diff --git a/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java b/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java
deleted file mode 100644
index 1d4de31..0000000
--- a/core/sis-raster/src/test/java/org/apache/sis/test/suite/RasterTestSuite.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.test.suite;
-
-import org.apache.sis.test.TestSuite;
-import org.junit.runners.Suite;
-import org.junit.BeforeClass;
-
-
-/**
- * All tests from the {@code sis-raster} module, in approximative dependency order.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-@Suite.SuiteClasses({
-    org.apache.sis.image.DefaultIteratorTest.class
-})
-public final strictfp class RasterTestSuite extends TestSuite {
-    /**
-     * Verifies the list of tests before to run the suite.
-     * See {@link #verifyTestList(Class, Class[])} for more information.
-     */
-    @BeforeClass
-    public static void verifyTestList() {
-        assertNoMissingTest(RasterTestSuite.class);
-        verifyTestList(RasterTestSuite.class);
-    }
-}
diff --git a/core/sis-raster/src/test/java/org/apache/sis/test/suite/package-info.txt b/core/sis-raster/src/test/java/org/apache/sis/test/suite/package-info.txt
deleted file mode 100644
index ac895b5..0000000
--- a/core/sis-raster/src/test/java/org/apache/sis/test/suite/package-info.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Different modules provide classes in this package - be careful about collisions.
-This package is initially defined by the sis-utility module, which also provides
-the package-info.java file.
diff --git a/ide-project/NetBeans/build.xml b/ide-project/NetBeans/build.xml
index ad865b4..4176305 100644
--- a/ide-project/NetBeans/build.xml
+++ b/ide-project/NetBeans/build.xml
@@ -50,9 +50,6 @@
       <fileset dir="${project.root}/core/sis-feature/target/generated-resources">
         <include name="**/*.utf"/>
       </fileset>
-      <fileset dir="${project.root}/core/sis-raster/target/generated-resources">
-        <include name="**/*.utf"/>
-      </fileset>
       <fileset dir="${project.root}/storage/sis-storage/target/generated-resources">
         <include name="**/*.utf"/>
       </fileset>
@@ -62,11 +59,6 @@
       <fileset dir="${project.root}/storage/sis-geotiff/target/generated-resources">
         <include name="**/*.utf"/>
       </fileset>
-      <!-- Pending discussion about how to handle resources in the Shapefile module.
-      <fileset dir="${project.root}/storage/sis-shapefile/target/generated-resources">
-        <include name="**/*.utf"/>
-      </fileset>
-      -->
 
       <!-- Other resources (properties files, SQL scripts, native libraries). -->
       <fileset dir="${project.root}/core/sis-utility/src/main/resources">
@@ -242,12 +234,6 @@
       <fileset dir="${project.root}/storage/sis-earth-observation/src/test/resources">
         <include name="**/*.txt"/>
       </fileset>
-      <fileset dir="${project.root}/storage/sis-shapefile/src/test/resources">
-        <include name="**/*.dbf"/>
-        <include name="**/*.prj"/>
-        <include name="**/*.shp"/>
-        <include name="**/*.shx"/>
-      </fileset>
       <fileset dir="${project.root}/profiles/sis-french-profile/src/test/resources">
         <include name="**/*.xml"/>
       </fileset>
diff --git a/ide-project/NetBeans/nbproject/build-impl.xml b/ide-project/NetBeans/nbproject/build-impl.xml
index 9156f4d..55d2c83 100644
--- a/ide-project/NetBeans/nbproject/build-impl.xml
+++ b/ide-project/NetBeans/nbproject/build-impl.xml
@@ -127,11 +127,9 @@ is divided into following sections:
                 <available file="${test.earth-obs.dir}"/>
                 <available file="${test.geotiff.dir}"/>
                 <available file="${test.netcdf.dir}"/>
-                <available file="${test.shapefile.dir}"/>
                 <available file="${test.xmlstore.dir}"/>
                 <available file="${test.storage.dir}"/>
                 <available file="${test.feature.dir}"/>
-                <available file="${test.raster.dir}"/>
                 <available file="${test.referencing.dir}"/>
                 <available file="${test.ref-by-id.dir}"/>
                 <available file="${test.metadata.dir}"/>
@@ -148,11 +146,9 @@ is divided into following sections:
                 <available file="${src.earth-obs.dir}"/>
                 <available file="${src.geotiff.dir}"/>
                 <available file="${src.netcdf.dir}"/>
-                <available file="${src.shapefile.dir}"/>
                 <available file="${src.xmlstore.dir}"/>
                 <available file="${src.storage.dir}"/>
                 <available file="${src.feature.dir}"/>
-                <available file="${src.raster.dir}"/>
                 <available file="${src.referencing.dir}"/>
                 <available file="${src.ref-by-id.dir}"/>
                 <available file="${src.metadata.dir}"/>
@@ -268,11 +264,9 @@ is divided into following sections:
         <fail unless="src.earth-obs.dir">Must set src.earth-obs.dir</fail>
         <fail unless="src.geotiff.dir">Must set src.geotiff.dir</fail>
         <fail unless="src.netcdf.dir">Must set src.netcdf.dir</fail>
-        <fail unless="src.shapefile.dir">Must set src.shapefile.dir</fail>
         <fail unless="src.xmlstore.dir">Must set src.xmlstore.dir</fail>
         <fail unless="src.storage.dir">Must set src.storage.dir</fail>
         <fail unless="src.feature.dir">Must set src.feature.dir</fail>
-        <fail unless="src.raster.dir">Must set src.raster.dir</fail>
         <fail unless="src.referencing.dir">Must set src.referencing.dir</fail>
         <fail unless="src.ref-by-id.dir">Must set src.ref-by-id.dir</fail>
         <fail unless="src.metadata.dir">Must set src.metadata.dir</fail>
@@ -285,11 +279,9 @@ is divided into following sections:
         <fail unless="test.earth-obs.dir">Must set test.earth-obs.dir</fail>
         <fail unless="test.geotiff.dir">Must set test.geotiff.dir</fail>
         <fail unless="test.netcdf.dir">Must set test.netcdf.dir</fail>
-        <fail unless="test.shapefile.dir">Must set test.shapefile.dir</fail>
         <fail unless="test.xmlstore.dir">Must set test.xmlstore.dir</fail>
         <fail unless="test.storage.dir">Must set test.storage.dir</fail>
         <fail unless="test.feature.dir">Must set test.feature.dir</fail>
-        <fail unless="test.raster.dir">Must set test.raster.dir</fail>
         <fail unless="test.referencing.dir">Must set test.referencing.dir</fail>
         <fail unless="test.ref-by-id.dir">Must set test.ref-by-id.dir</fail>
         <fail unless="test.metadata.dir">Must set test.metadata.dir</fail>
@@ -316,7 +308,7 @@ is divided into following sections:
     </target>
     <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
         <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
+            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
@@ -357,7 +349,7 @@ is divided into following sections:
     </target>
     <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
         <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
+            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
@@ -390,7 +382,7 @@ is divided into following sections:
     </target>
     <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
         <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
+            <attribute default="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <sequential>
@@ -492,9 +484,6 @@ is divided into following sections:
                         <fileset dir="${test.netcdf.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
-                        <fileset dir="${test.shapefile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
                         <fileset dir="${test.xmlstore.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
@@ -504,9 +493,6 @@ is divided into following sections:
                         <fileset dir="${test.feature.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
-                        <fileset dir="${test.raster.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
                         <fileset dir="${test.referencing.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
@@ -569,9 +555,6 @@ is divided into following sections:
                     <fileset dir="${test.netcdf.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
                         <filename name="@{testincludes}"/>
                     </fileset>
-                    <fileset dir="${test.shapefile.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
-                        <filename name="@{testincludes}"/>
-                    </fileset>
                     <fileset dir="${test.xmlstore.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
                         <filename name="@{testincludes}"/>
                     </fileset>
@@ -581,9 +564,6 @@ is divided into following sections:
                     <fileset dir="${test.feature.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
                         <filename name="@{testincludes}"/>
                     </fileset>
-                    <fileset dir="${test.raster.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
-                        <filename name="@{testincludes}"/>
-                    </fileset>
                     <fileset dir="${test.referencing.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
                         <filename name="@{testincludes}"/>
                     </fileset>
@@ -726,9 +706,6 @@ is divided into following sections:
                         <fileset dir="${test.netcdf.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
-                        <fileset dir="${test.shapefile.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
                         <fileset dir="${test.xmlstore.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
@@ -738,9 +715,6 @@ is divided into following sections:
                         <fileset dir="${test.feature.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
-                        <fileset dir="${test.raster.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
                         <fileset dir="${test.referencing.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
@@ -1123,7 +1097,7 @@ is divided into following sections:
                 <include name="*"/>
             </dirset>
         </pathconvert>
-        <j2seproject3:depend srcdir="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}:${build.generated.subdirs}"/>
+        <j2seproject3:depend srcdir="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}:${build.generated.subdirs}"/>
     </target>
     <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
         <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
@@ -1134,11 +1108,9 @@ is divided into following sections:
             <fileset dir="${src.earth-obs.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.geotiff.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.netcdf.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-            <fileset dir="${src.shapefile.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.xmlstore.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.storage.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.feature.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-            <fileset dir="${src.raster.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.referencing.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.ref-by-id.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.metadata.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
@@ -1166,7 +1138,7 @@ is divided into following sections:
     <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
         <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
         <j2seproject3:force-recompile/>
-        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.shapefile.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.raster.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}"/>
+        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.local-src.dir}:${src.webapp.dir}:${src.console.dir}:${src.earth-obs.dir}:${src.geotiff.dir}:${src.netcdf.dir}:${src.xmlstore.dir}:${src.storage.dir}:${src.feature.dir}:${src.referencing.dir}:${src.ref-by-id.dir}:${src.metadata.dir}:${src.utility.dir}:${src.fra-profile.dir}:${src.gdal.dir}:${src.c.gdal.dir}"/>
     </target>
     <target name="-post-compile-single">
         <!-- Empty placeholder for easier customization. -->
@@ -1450,9 +1422,6 @@ is divided into following sections:
             <fileset dir="${src.netcdf.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                 <filename name="**/*.java"/>
             </fileset>
-            <fileset dir="${src.shapefile.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
-                <filename name="**/*.java"/>
-            </fileset>
             <fileset dir="${src.xmlstore.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                 <filename name="**/*.java"/>
             </fileset>
@@ -1462,9 +1431,6 @@ is divided into following sections:
             <fileset dir="${src.feature.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                 <filename name="**/*.java"/>
             </fileset>
-            <fileset dir="${src.raster.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
-                <filename name="**/*.java"/>
-            </fileset>
             <fileset dir="${src.referencing.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                 <filename name="**/*.java"/>
             </fileset>
@@ -1511,9 +1477,6 @@ is divided into following sections:
             <fileset dir="${src.netcdf.dir}" excludes="${excludes}" includes="${includes}">
                 <filename name="**/doc-files/**"/>
             </fileset>
-            <fileset dir="${src.shapefile.dir}" excludes="${excludes}" includes="${includes}">
-                <filename name="**/doc-files/**"/>
-            </fileset>
             <fileset dir="${src.xmlstore.dir}" excludes="${excludes}" includes="${includes}">
                 <filename name="**/doc-files/**"/>
             </fileset>
@@ -1523,9 +1486,6 @@ is divided into following sections:
             <fileset dir="${src.feature.dir}" excludes="${excludes}" includes="${includes}">
                 <filename name="**/doc-files/**"/>
             </fileset>
-            <fileset dir="${src.raster.dir}" excludes="${excludes}" includes="${includes}">
-                <filename name="**/doc-files/**"/>
-            </fileset>
             <fileset dir="${src.referencing.dir}" excludes="${excludes}" includes="${includes}">
                 <filename name="**/doc-files/**"/>
             </fileset>
@@ -1569,21 +1529,19 @@ is divided into following sections:
         <!-- You can override this target in the ../build.xml file. -->
     </target>
     <target if="do.depend.true" name="-compile-test-depend">
-        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.webapp.dir}:${test.console.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gdal.dir}"/>
+        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.webapp.dir}:${test.console.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gdal.dir}"/>
     </target>
     <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
-        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.webapp.dir}:${test.console.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utili [...]
+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.webapp.dir}:${test.console.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.utility.dir}:${test.fra-profile.dir}:${test.gd [...]
         <copy todir="${build.test.classes.dir}">
             <fileset dir="${test.webapp.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.console.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.earth-obs.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.geotiff.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.netcdf.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-            <fileset dir="${test.shapefile.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.xmlstore.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.storage.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.feature.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-            <fileset dir="${test.raster.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.referencing.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.ref-by-id.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.metadata.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
@@ -1604,18 +1562,16 @@ is divided into following sections:
     <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
         <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
         <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
-        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.webapp.dir}:${test.console.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.shapefile.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.raster.dir}:${test.referencing.dir}:${test.ref [...]
+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.webapp.dir}:${test.console.dir}:${test.earth-obs.dir}:${test.geotiff.dir}:${test.netcdf.dir}:${test.xmlstore.dir}:${test.storage.dir}:${test.feature.dir}:${test.referencing.dir}:${test.ref-by-id.dir}:${test.metadata.dir}:${test.u [...]
         <copy todir="${build.test.classes.dir}">
             <fileset dir="${test.webapp.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.console.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.earth-obs.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.geotiff.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.netcdf.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-            <fileset dir="${test.shapefile.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.xmlstore.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.storage.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.feature.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-            <fileset dir="${test.raster.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.referencing.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.ref-by-id.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${test.metadata.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
diff --git a/ide-project/NetBeans/nbproject/genfiles.properties b/ide-project/NetBeans/nbproject/genfiles.properties
index e764a56..3aee832 100644
--- a/ide-project/NetBeans/nbproject/genfiles.properties
+++ b/ide-project/NetBeans/nbproject/genfiles.properties
@@ -3,6 +3,6 @@
 build.xml.data.CRC32=58e6b21c
 build.xml.script.CRC32=462eaba0
 build.xml.stylesheet.CRC32=28e38971@1.53.1.46
-nbproject/build-impl.xml.data.CRC32=f8f4bfbb
-nbproject/build-impl.xml.script.CRC32=3d5816ed
+nbproject/build-impl.xml.data.CRC32=5cd8e010
+nbproject/build-impl.xml.script.CRC32=6e39470f
 nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48
diff --git a/ide-project/NetBeans/nbproject/project.properties b/ide-project/NetBeans/nbproject/project.properties
index 7ec76a5..ae11308 100644
--- a/ide-project/NetBeans/nbproject/project.properties
+++ b/ide-project/NetBeans/nbproject/project.properties
@@ -57,8 +57,6 @@ src.geotiff.dir      = ${project.root}/storage/sis-geotiff/src/main/java
 test.geotiff.dir     = ${project.root}/storage/sis-geotiff/src/test/java
 src.netcdf.dir       = ${project.root}/storage/sis-netcdf/src/main/java
 test.netcdf.dir      = ${project.root}/storage/sis-netcdf/src/test/java
-src.shapefile.dir    = ${project.root}/storage/sis-shapefile/src/main/java
-test.shapefile.dir   = ${project.root}/storage/sis-shapefile/src/test/java
 src.xmlstore.dir     = ${project.root}/storage/sis-xmlstore/src/main/java
 test.xmlstore.dir    = ${project.root}/storage/sis-xmlstore/src/test/java
 src.gdal.dir         = ${project.root}/storage/sis-gdal/src/main/java
@@ -68,8 +66,6 @@ src.storage.dir      = ${project.root}/storage/sis-storage/src/main/java
 test.storage.dir     = ${project.root}/storage/sis-storage/src/test/java
 src.feature.dir      = ${project.root}/core/sis-feature/src/main/java
 test.feature.dir     = ${project.root}/core/sis-feature/src/test/java
-src.raster.dir       = ${project.root}/core/sis-raster/src/main/java
-test.raster.dir      = ${project.root}/core/sis-raster/src/test/java
 src.referencing.dir  = ${project.root}/core/sis-referencing/src/main/java
 test.referencing.dir = ${project.root}/core/sis-referencing/src/test/java
 src.ref-by-id.dir    = ${project.root}/core/sis-referencing-by-identifiers/src/main/java
diff --git a/ide-project/NetBeans/nbproject/project.xml b/ide-project/NetBeans/nbproject/project.xml
index 74e7dfd..a26c622 100644
--- a/ide-project/NetBeans/nbproject/project.xml
+++ b/ide-project/NetBeans/nbproject/project.xml
@@ -29,11 +29,9 @@
                 <root id="src.earth-obs.dir" name="Earth observation"/>
                 <root id="src.geotiff.dir" name="GeoTIFF"/>
                 <root id="src.netcdf.dir" name="NetCDF"/>
-                <root id="src.shapefile.dir" name="Shapefile"/>
                 <root id="src.xmlstore.dir" name="XMLStore"/>
                 <root id="src.storage.dir" name="Storage"/>
                 <root id="src.feature.dir" name="Feature"/>
-                <root id="src.raster.dir" name="Raster"/>
                 <root id="src.referencing.dir" name="Referencing"/>
                 <root id="src.ref-by-id.dir" name="Referencing by identifiers"/>
                 <root id="src.metadata.dir" name="Metadata"/>
@@ -48,11 +46,9 @@
                 <root id="test.earth-obs.dir" name="Test Earth observation"/>
                 <root id="test.geotiff.dir" name="Test GeoTIFF"/>
                 <root id="test.netcdf.dir" name="Test NetCDF"/>
-                <root id="test.shapefile.dir" name="Test Shapefile"/>
                 <root id="test.xmlstore.dir" name="Test XMLStore"/>
                 <root id="test.storage.dir" name="Test Storage"/>
                 <root id="test.feature.dir" name="Test Feature"/>
-                <root id="test.raster.dir" name="Test Raster"/>
                 <root id="test.referencing.dir" name="Test Referencing"/>
                 <root id="test.ref-by-id.dir" name="Test Referencing by identifiers"/>
                 <root id="test.metadata.dir" name="Test Metadata"/>
diff --git a/storage/pom.xml b/storage/pom.xml
index ecf4752..8d20a6b 100644
--- a/storage/pom.xml
+++ b/storage/pom.xml
@@ -159,7 +159,6 @@
        =========================================================== -->
   <modules>
     <module>sis-storage</module>
-    <module>sis-shapefile</module>
     <module>sis-netcdf</module>
     <module>sis-geotiff</module>
     <module>sis-xmlstore</module>
diff --git a/storage/sis-shapefile/pom.xml b/storage/sis-shapefile/pom.xml
deleted file mode 100644
index 00d105d..0000000
--- a/storage/sis-shapefile/pom.xml
+++ /dev/null
@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-  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.
--->
-
-<project xmlns              = "http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
-                               http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.apache.sis</groupId>
-    <artifactId>storage</artifactId>
-    <version>0.8-SNAPSHOT</version>
-  </parent>
-
-
-   <!-- ===========================================================
-           Module Description
-       =========================================================== -->
-  <groupId>org.apache.sis.storage</groupId>
-  <artifactId>sis-shapefile</artifactId>
-  <packaging>bundle</packaging>
-  <name>Apache SIS Shapefile storage</name>
-  <description>
-  <!-- Left alignment because this description will be copied in META-INF/MANIFEST.MF
-       The leading space after the first line is necessary for proper formatting. -->
-Read and write files in the Shapefile format.
-  </description>
-
-
-  <!-- ===========================================================
-           Developers and Contributors
-       =========================================================== -->
-  <developers>
-    <developer>
-      <name>Travis L. Pinney</name>
-      <id>tlpinney</id>
-      <email>travis.pinney@gmail.com</email>
-      <roles>
-        <role>developer</role>
-      </roles>
-    </developer>
-  </developers>
-
-
-  <!-- ===========================================================
-           Build configuration
-       =========================================================== -->
-  <build>
-    <plugins>
-
-      <!-- Compile properties files into resources UTF files. -->
-      <plugin>
-        <groupId>org.apache.sis.core</groupId>
-        <artifactId>sis-build-helper</artifactId>
-        <version>${sis.plugin.version}</version>
-        <executions>
-          <execution>
-            <goals>
-              <goal>compile-resources</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-
-      <!-- Package as OSGi bundle -->
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>org.apache.sis.storage.shapefile</Bundle-SymbolicName>
-          </instructions>
-        </configuration>
-      </plugin>
-
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-checkstyle-plugin</artifactId>
-        <executions>
-          <execution>
-            <configuration>
-              <skip>true</skip>         <!-- Java code formatting in this module is different than other modules. -->
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
-
-  <!-- ===========================================================
-           Dependencies
-       =========================================================== -->
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.sis.core</groupId>
-      <artifactId>sis-feature</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.sis.storage</groupId>
-      <artifactId>sis-storage</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.esri.geometry</groupId>
-      <artifactId>esri-geometry-api</artifactId>
-      <optional>false</optional>
-    </dependency>
-  </dependencies>
-
-</project>
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java
deleted file mode 100644
index 9f69d96..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/AutoChecker.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.internal.shapefile;
-
-import java.lang.reflect.Constructor;
-import java.text.MessageFormat;
-import java.util.MissingResourceException;
-import java.util.Objects;
-import java.util.ResourceBundle;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.apache.sis.util.logging.Logging;
-
-
-/**
- * Base class for objets having auto-checking abilities
- * and easy access to Bundle and logging function.
- * @author Marc LE BIHAN
- */
-public abstract class AutoChecker {
-    /** Logger. */
-    private static Logger LOGGER = Logging.getLogger(AutoChecker.class.getSimpleName());
-
-    /**
-     * Format a resource bundle message.
-     *
-     * @param classForResourceBundleName class from which ResourceBundle name will be extracted.
-     * @param key Message key.
-     * @param args Message arguments.
-     * @return Message.
-     */
-    final protected String format(Class<?> classForResourceBundleName, String key, Object... args) {
-        Objects.requireNonNull(classForResourceBundleName, "Class from with the ResourceBundle name is extracted cannot be null.");
-        Objects.requireNonNull(key, "Message key cannot be bull.");
-
-        Class<?> candidateClass = classForResourceBundleName;
-        MessageFormat format = null;
-
-        // Find the key in the bundle having for name this class, or in one of its superclasses.
-        do {
-            try {
-                ResourceBundle rsc = ResourceBundle.getBundle(candidateClass.getName());
-                format = new MessageFormat(rsc.getString(key));
-            }
-            catch(MissingResourceException e) {
-                candidateClass = candidateClass.getSuperclass();
-            }
-        }
-        while(candidateClass != null && format == null);
-
-        if (format == null) {
-            String fmt = "Cannot find property key {0} in {1} properties file or any of its superclasses.";
-            String message = MessageFormat.format(fmt, key, classForResourceBundleName.getName());
-            throw new MissingResourceException(message, classForResourceBundleName.getName(), key);
-        }
-        else
-            return format.format(args);
-    }
-
-    /**
-     * Format a resource bundle message.
-     *
-     * @param key Message key.
-     * @param args Message arguments.
-     * @return Message.
-     */
-    final protected String format(String key, Object... args) {
-        return format(getClass(), key, args);
-    }
-
-    /**
-     * Format a resource bundle message and before returning it, log it.
-     *
-     * @param logLevel Log Level.
-     * @param key Message key.
-     * @param args Message arguments.
-     * @return Message.
-     */
-    final protected String format(Level logLevel, String key, Object... args) {
-        Objects.requireNonNull(logLevel, "The log level cannot be null.");
-
-        String message = format(key, args);
-        LOGGER.log(logLevel, message);
-        return(message);
-    }
-
-    /**
-     * Format a resource bundle message and before returning it, log it.
-     *
-     * @param classForResourceBundleName class from which ResourceBundle name will be extracted.
-     * @param logLevel Log Level.
-     * @param key Message key.
-     * @param args Message arguments.
-     * @return Message.
-     */
-    final protected String format(Level logLevel, Class<?> classForResourceBundleName, String key, Object... args) {
-        Objects.requireNonNull(logLevel, "The log level cannot be null.");
-
-        String message = format(classForResourceBundleName, key, args);
-        LOGGER.log(logLevel, message);
-        return(message);
-    }
-
-    /**
-     * Tells if the logger of the base class will log this level of log.
-     * @param level Wished level of logging.
-     * @return true if it will log it.
-     */
-    protected boolean isLoggable(Level level) {
-        return LOGGER.isLoggable(level);
-    }
-    
-    /**
-     * Logs (and take the time to format an entry log) only if the logger accepts the message.
-     * @param logLevel Log level.
-     * @param key Message key.
-     * @param args Message arguments.
-     */
-    final protected void log(Level logLevel, String key, Object... args) {
-        Objects.requireNonNull(logLevel, "The log level cannot be null.");
-
-        if (LOGGER.isLoggable(logLevel))
-            format(logLevel, key, args);
-    }
-
-    /**
-     * Throw an exception by reflection.
-     * @param <E> Class of the exception to build.
-     * @param classException Class of the exception to build.
-     * @param message Exception message.
-     * @param cause Exception root cause.
-     * @throws E wished exception.
-     */
-    public static <E extends Throwable> void throwException(Class<E> classException, String message, Throwable cause) throws E {
-       throw(exception(classException, message, cause));
-    }
-
-    /**
-     * Build an exception by reflection.
-     * @param <E> Class of the exception to build.
-     * @param classException Class of the exception to build.
-     * @param message Exception message.
-     * @param cause Exception root cause.
-     * @return E wished exception.
-     */
-    private static <E extends Throwable> E exception(Class<E> classException, String message, Throwable cause) {
-       Objects.requireNonNull(classException, "The class of the exception to throw cannot be null."); //$NON-NLS-1$
-
-       try
-       {
-            Constructor<E> cstr = classException.getConstructor(String.class, Throwable.class);
-            E exception = cstr.newInstance(message, cause);
-            return(exception);
-       }
-       catch(Exception e) {
-            // Create the error message manually to avoid re-entrance in function of this class, that if it has a trouble here could have also a problem everywhere.
-            String format = "The exception of class {0} (message ''{1}'') can''t be created by reflection. An exception of class {2} happened with the message {3}.";
-            String msg = MessageFormat.format(format, classException.getName(), message, e.getClass().getName(), e.getMessage());
-            throw new RuntimeException(msg, e);
-       }
-    }
-
-    /**
-     * Return the class logger.
-     * @return logger.
-     */
-    public Logger getLogger() {
-        return LOGGER;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLInvalidRecordNumberForDirectAccessException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLInvalidRecordNumberForDirectAccessException.java
deleted file mode 100644
index ec5642c..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLInvalidRecordNumberForDirectAccessException.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.internal.shapefile;
-
-import java.sql.SQLNonTransientException;
-
-
-/**
- * Thrown when a record number is invalid to do a direct access in a Shapefile or a DBase III file.
- *
- * @author  Marc Le Bihan
- * @version 0.7
- * @since   0.7
- * @module
- */
-public class SQLInvalidRecordNumberForDirectAccessException extends SQLNonTransientException {
-    /** Serial UID. */
-    private static final long serialVersionUID = 6828362742568015813L;
-    
-    /** Wrong record number. */
-    private int wrongRecordNumber;
-
-    /**
-     * Construct an exception.
-     * @param number Wrong record number value.
-     * @param message Message of the exception.
-     */
-    public SQLInvalidRecordNumberForDirectAccessException(int number, String message) {
-        super(message);
-        this.wrongRecordNumber = number;
-    }
-
-    /**
-     * Construct an exception.
-     * @param number Wrong record number value.
-     * @param message Message of the exception.
-     * @param cause Root cause of the exception.
-     */
-    public SQLInvalidRecordNumberForDirectAccessException(int number, String message, Throwable cause) {
-        super(message, cause);
-        this.wrongRecordNumber = number;
-    }
-    
-    /**
-     * Returns the wrong record number value.
-     * @return Record number.
-     */
-    public int getWrongRecordNumber() {
-        return this.wrongRecordNumber;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLNoDirectAccessAvailableException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLNoDirectAccessAvailableException.java
deleted file mode 100644
index a0b4d60..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLNoDirectAccessAvailableException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.internal.shapefile;
-
-import java.sql.SQLNonTransientException;
-
-
-/**
- * Thrown when a shapefile or a DBase III file cannot allow a direct acces (because it has no index).
- *
- * @author  Marc Le Bihan
- * @version 0.7
- * @since   0.7
- * @module
- */
-public class SQLNoDirectAccessAvailableException extends SQLNonTransientException {
-    /** Serial UID. */
-    private static final long serialVersionUID = 16719558033196219L;
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     */
-    public SQLNoDirectAccessAvailableException(String message) {
-        super(message);
-    }
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     * @param cause Root cause of the exception.
-     */
-    public SQLNoDirectAccessAvailableException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLShapefileNotFoundException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLShapefileNotFoundException.java
deleted file mode 100644
index 22aa585..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/SQLShapefileNotFoundException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.internal.shapefile;
-
-import java.sql.SQLNonTransientException;
-
-
-/**
- * Thrown when a shapefile has not been found.
- *
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class SQLShapefileNotFoundException extends SQLNonTransientException {
-    /** Serial UID. */
-    private static final long serialVersionUID = -3235671561698931817L;
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     */
-    public SQLShapefileNotFoundException(String message) {
-        super(message);
-    }
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     * @param cause Root cause of the exception.
-     */
-    public SQLShapefileNotFoundException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java
deleted file mode 100644
index 584f26f..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileByteReader.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * 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.internal.shapefile;
-
-import java.io.*;
-import java.nio.ByteOrder;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.apache.sis.feature.DefaultAttributeType;
-import org.apache.sis.feature.DefaultFeatureType;
-import org.apache.sis.internal.shapefile.jdbc.*;
-import org.apache.sis.storage.shapefile.InvalidShapefileFormatException;
-import org.apache.sis.storage.shapefile.ShapeTypeEnum;
-import org.apache.sis.feature.AbstractFeature;
-import org.apache.sis.util.logging.Logging;
-
-import com.esri.core.geometry.*;
-
-/**
- * Reader of a Shapefile Binary content by the way of a {@link java.nio.MappedByteBuffer}
- *
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class ShapefileByteReader extends CommonByteReader<InvalidShapefileFormatException, SQLShapefileNotFoundException> {
-    /** Name of the Geometry field. */
-    private static final String GEOMETRY_NAME = "geometry";
-
-    /** Shapefile descriptor. */
-    private ShapefileDescriptor shapefileDescriptor;
-
-    /** Database Field descriptors. */
-    private List<DBase3FieldDescriptor> databaseFieldsDescriptors;
-
-    /** Type of the features contained in this shapefile. */
-    private DefaultFeatureType featuresType;
-
-    /** Shapefile index. */
-    private File shapeFileIndex;
-
-    /** Shapefile indexes (loaded from .SHX file, if any found). */
-    private ArrayList<Integer> indexes;
-
-    /** Shapefile records lengths (loaded from .SHX file, if any found). */
-    private ArrayList<Integer> recordsLengths;
-
-    /**
-     * Construct a shapefile byte reader.
-     * @param shapefile Shapefile.
-     * @param dbaseFile underlying database file name.
-     * @param shapefileIndex Shapefile index, if any. Null else.
-     * @throws InvalidShapefileFormatException if the shapefile format is invalid.
-     * @throws SQLInvalidDbaseFileFormatException if the database file format is invalid.
-     * @throws SQLShapefileNotFoundException if the shapefile has not been found.
-     * @throws SQLDbaseFileNotFoundException if the database file has not been found.
-     */
-    public ShapefileByteReader(File shapefile, File dbaseFile, File shapefileIndex) throws InvalidShapefileFormatException, SQLInvalidDbaseFileFormatException, SQLShapefileNotFoundException, SQLDbaseFileNotFoundException {
-        super(shapefile, InvalidShapefileFormatException.class, SQLShapefileNotFoundException.class);
-        this.shapeFileIndex = shapefileIndex;
-
-        loadDatabaseFieldDescriptors(dbaseFile);
-        loadDescriptor();
-
-        if (this.shapeFileIndex != null) {
-            loadShapefileIndexes();
-        }
-
-        this.featuresType = getFeatureType(shapefile.getName());
-    }
-
-    /**
-     * Returns the DBase 3 fields descriptors.
-     * @return Fields descriptors.
-     */
-    public List<DBase3FieldDescriptor> getFieldsDescriptors() {
-        return this.databaseFieldsDescriptors;
-    }
-
-    /**
-     * Returns the shapefile descriptor.
-     * @return Shapefile descriptor.
-     */
-    public ShapefileDescriptor getShapefileDescriptor() {
-        return this.shapefileDescriptor;
-    }
-
-    /**
-     * Returns the type of the features contained in this shapefile.
-     * @return Features type.
-     */
-    public DefaultFeatureType getFeaturesType() {
-        return this.featuresType;
-    }
-
-    /**
-     * Create a feature descriptor.
-     * @param name Name of the field.
-     * @return The feature type.
-     */
-    private DefaultFeatureType getFeatureType(final String name) {
-        Objects.requireNonNull(name, "The feature name cannot be null.");
-
-        final int n = this.databaseFieldsDescriptors.size();
-        final DefaultAttributeType<?>[] attributes = new DefaultAttributeType<?>[n + 1];
-        final Map<String, Object> properties = new HashMap<>(4);
-
-        // Load data field.
-        for (int i = 0; i < n; i++) {
-            properties.put(DefaultAttributeType.NAME_KEY, this.databaseFieldsDescriptors.get(i).getName());
-            attributes[i] = new DefaultAttributeType<>(properties, String.class, 1, 1, null);
-        }
-
-        // Add geometry field.
-        properties.put(DefaultAttributeType.NAME_KEY, GEOMETRY_NAME);
-        attributes[n] = new DefaultAttributeType<>(properties, Geometry.class, 1, 1, null);
-
-        // Add name.
-        properties.put(DefaultAttributeType.NAME_KEY, name);
-        return new DefaultFeatureType(properties, false, null, attributes);
-    }
-
-    /**
-     * Load shapefile descriptor.
-     */
-    private void loadDescriptor() {
-        this.shapefileDescriptor = new ShapefileDescriptor(getByteBuffer());
-    }
-
-    /**
-     * Load shapefile indexes.
-     * @return true if shapefile indexes has been read,
-     * false if none where available or a problem occured.
-     */
-    private boolean loadShapefileIndexes() {
-        if (this.shapeFileIndex == null) {
-            return false;
-        }
-
-        try(FileInputStream fis = new FileInputStream(this.shapeFileIndex); FileChannel fc = fis.getChannel()) {
-            try {
-                int fsize = (int)fc.size();
-                MappedByteBuffer indexesByteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fsize);
-
-                // Indexes entries follow.
-                this.indexes = new ArrayList<>();
-                this.recordsLengths = new ArrayList<>();
-                indexesByteBuffer.position(100);
-                indexesByteBuffer.order(ByteOrder.BIG_ENDIAN);
-
-                while(indexesByteBuffer.hasRemaining()) {
-                    this.indexes.add(indexesByteBuffer.getInt());        // Data offset : the position of the record in the main shapefile, expressed in words (16 bits).
-                    this.recordsLengths.add(indexesByteBuffer.getInt()); // Length of this shapefile record.
-                }
-
-                log(Level.INFO, "log.index_has_been_read", this.shapeFileIndex.getAbsolutePath(), this.indexes.size(), this.getFile().getAbsolutePath());
-                return true;
-            }
-            catch(IOException e) {
-                log(Level.WARNING, "log.invalid_file_content_for_shapefile_index", this.shapeFileIndex.getAbsolutePath(), e.getMessage());
-                this.shapeFileIndex = null;
-                return false;
-            }
-        }
-        catch(FileNotFoundException e) {
-            log(Level.WARNING, "log.no_shapefile_index_found_at_location", this.shapeFileIndex.getAbsolutePath(), this.getFile().getAbsolutePath());
-            this.shapeFileIndex = null;
-            return false;
-        }
-        catch(IOException e) {
-            log(Level.WARNING, "log.invalid_file_content_for_shapefile_index", this.shapeFileIndex.getAbsolutePath(), e.getMessage());
-            this.shapeFileIndex = null;
-            return false;
-        }
-    }
-
-    /**
-     * Load database field descriptors.
-     * @param dbaseFile Database file.
-     * @throws SQLInvalidDbaseFileFormatException if the database format is incorrect.
-     * @throws SQLDbaseFileNotFoundException if the database file cannot be found.
-     */
-    private void loadDatabaseFieldDescriptors(File dbaseFile) throws SQLInvalidDbaseFileFormatException, SQLDbaseFileNotFoundException {
-        MappedByteReader databaseReader = null;
-
-        try {
-            databaseReader = new MappedByteReader(dbaseFile, null);
-            this.databaseFieldsDescriptors = databaseReader.getFieldsDescriptors();
-        }
-        finally {
-            if (databaseReader != null) {
-                try {
-                    databaseReader.close();
-                }
-                catch(IOException e) {
-                }
-            }
-        }
-    }
-
-    /**
-     * Direct access to a feature by its record number.
-     * @param recordNumber Record number.
-     * @throws SQLNoDirectAccessAvailableException if this shape file doesn't allow direct acces, because it has no index.
-     * @throws SQLInvalidRecordNumberForDirectAccessException if the record number asked for is invalid (below the start, after the end).
-     */
-    public void setRowNum(int recordNumber) throws SQLNoDirectAccessAvailableException, SQLInvalidRecordNumberForDirectAccessException {
-        // Check that the asked record number is not before the first.
-        if (recordNumber < 1) {
-            String message = format(Level.SEVERE, "excp.wrong_direct_access_before_start", recordNumber, getFile().getAbsolutePath());
-            throw new SQLInvalidRecordNumberForDirectAccessException(recordNumber, message);
-        }
-
-        // Check that the shapefile allows direct access : it won't if it has no index.
-        if (this.shapeFileIndex == null) {
-            String message = format(Level.SEVERE, "excp.no_direct_access", getFile().getAbsolutePath());
-            throw new SQLNoDirectAccessAvailableException(message);
-        }
-
-        int position = this.indexes.get(recordNumber - 1) * 2; // Indexes unit are words (16 bits).
-
-        // Check that the asked record number is not after the last.
-        if (position >= this.getByteBuffer().capacity()) {
-            String message = format(Level.SEVERE, "excp.wrong_direct_access_after_last", recordNumber, getFile().getAbsolutePath());
-            throw new SQLInvalidRecordNumberForDirectAccessException(recordNumber, message);
-        }
-
-        try {
-            getByteBuffer().position(position);
-        }
-        catch(IllegalArgumentException e) {
-            String message = format(Level.SEVERE, "assert.wrong_position", recordNumber, position, getFile().getAbsolutePath(), e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * Complete a feature with shapefile content.
-     * @param feature Feature to complete.
-     * @throws InvalidShapefileFormatException if a validation problem occurs.
-     */
-    public void completeFeature(AbstractFeature feature) throws InvalidShapefileFormatException {
-        // insert points into some type of list
-        int RecordNumber = getByteBuffer().getInt();
-        @SuppressWarnings("unused")
-        int ContentLength = getByteBuffer().getInt();
-
-        getByteBuffer().order(ByteOrder.LITTLE_ENDIAN);
-        int iShapeType = getByteBuffer().getInt();
-
-        ShapeTypeEnum type = ShapeTypeEnum.get(iShapeType);
-
-        if (type == null)
-            throw new InvalidShapefileFormatException(MessageFormat.format("The shapefile feature type {0} doesn''t match to any known feature type.", this.featuresType));
-
-        switch (type) {
-            case Point:
-                loadPointFeature(feature);
-                break;
-
-            case Polygon:
-                loadPolygonFeature(feature);
-                break;
-
-            case PolyLine:
-                loadPolylineFeature(feature);
-                break;
-
-            default:
-                throw new InvalidShapefileFormatException("Unsupported shapefile type: " + iShapeType);
-        }
-
-        getByteBuffer().order(ByteOrder.BIG_ENDIAN);
-    }
-
-    /**
-     * Load point feature.
-     * @param feature Feature to fill.
-     */
-    private void loadPointFeature(AbstractFeature feature) {
-        double x = getByteBuffer().getDouble();
-        double y = getByteBuffer().getDouble();
-        Point pnt = new Point(x, y);
-        feature.setPropertyValue(GEOMETRY_NAME, pnt);
-    }
-
-    /**
-     * Load polygon feature.
-     * @param feature Feature to fill.
-     */
-    private void loadPolygonFeature(AbstractFeature feature) {
-        /* double xmin = */getByteBuffer().getDouble();
-        /* double ymin = */getByteBuffer().getDouble();
-        /* double xmax = */getByteBuffer().getDouble();
-        /* double ymax = */getByteBuffer().getDouble();
-        int numParts = getByteBuffer().getInt();
-        int numPoints = getByteBuffer().getInt();
-
-        Polygon poly;
-
-        // Handle multiple polygon parts.
-        if (numParts > 1) {
-            Logger log = Logging.getLogger(ShapefileByteReader.class.getName());
-
-            if (log.isLoggable(Level.FINER)) {
-                String format = "Polygon with multiple linear rings encountered at position {0,number} with {1,number} parts.";
-                String message = MessageFormat.format(format, getByteBuffer().position(), numParts);
-                log.finer(message);
-            }
-
-            poly = readMultiplePolygonParts(numParts, numPoints);
-        }
-        else {
-            // Polygon with an unique part.
-            poly = readUniquePolygonPart(numPoints);
-        }
-
-        feature.setPropertyValue(GEOMETRY_NAME, poly);
-    }
-
-    /**
-     * Read a polygon that has a unique part.
-     * @param numPoints Number of the points of the polygon.
-     * @return Polygon.
-     */
-    @Deprecated // As soon as the readMultiplePolygonParts method proofs working well, this readUniquePolygonPart method can be removed and all calls be deferred to readMultiplePolygonParts.
-    private Polygon readUniquePolygonPart(int numPoints) {
-        /*int part = */ getByteBuffer().getInt();
-        Polygon poly = new Polygon();
-
-        // create a line from the points
-        double xpnt = getByteBuffer().getDouble();
-        double ypnt = getByteBuffer().getDouble();
-
-        poly.startPath(xpnt, ypnt);
-
-        for (int j = 0; j < numPoints - 1; j++) {
-            xpnt = getByteBuffer().getDouble();
-            ypnt = getByteBuffer().getDouble();
-            poly.lineTo(xpnt, ypnt);
-        }
-
-        return poly;
-    }
-
-    /**
-     * Read a polygon that has multiple parts.
-     * @param numParts Number of parts of this polygon.
-     * @param numPoints Total number of points of this polygon, all parts considered.
-     * @return a multiple part polygon.
-     */
-    private Polygon readMultiplePolygonParts(int numParts, int numPoints) {
-        /**
-         * From ESRI Specification :
-         * Parts : 0 5  (meaning : 0 designs the first v1, 5 designs the first v5 on the points list below).
-         * Points : v1 v2 v3 v4 v1 v5 v8 v7 v6 v5
-         *
-         * POSITION  FIELD       VALUE      TYPE      NUMBER     ORDER
-         * Byte 0    Shape Type  5          Integer   1          Little
-         * Byte 4    Box         Box        Double    4          Little
-         * Byte 36   NumParts    NumParts   Integer   1          Little
-         * Byte 40   NumPoints   NumPoints  Integer   1          Little
-         * Byte 44   Parts       Parts      Integer   NumParts   Little
-         * Byte X    Points      Points     Point     NumPoints  Little
-         */
-        int[] partsIndexes = new int[numParts];
-
-        // Read all the parts indexes (starting at byte 44).
-        for(int index=0; index < numParts; index ++) {
-            partsIndexes[index] = getByteBuffer().getInt();
-        }
-
-        // Read all the points.
-        double[] xPoints = new double[numPoints];
-        double[] yPoints = new double[numPoints];
-
-        for(int index=0; index < numPoints; index ++) {
-            xPoints[index] = getByteBuffer().getDouble();
-            yPoints[index] = getByteBuffer().getDouble();
-        }
-
-        // Create the polygon from the points.
-        Polygon poly = new Polygon();
-
-        // create a line from the points
-        for(int index=0; index < numPoints; index ++) {
-            // Check if this index is one that begins a new part.
-            boolean newPolygon = false;
-
-            for(int j=0; j < partsIndexes.length; j ++) {
-                if (partsIndexes[j] == index) {
-                    newPolygon = true;
-                    break;
-                }
-            }
-
-            if (newPolygon) {
-                poly.startPath(xPoints[index], yPoints[index]);
-            }
-            else {
-                poly.lineTo(xPoints[index], yPoints[index]);
-            }
-        }
-
-        return poly;
-    }
-
-    /**
-     * Load polyline feature.
-     * @param feature Feature to fill.
-     */
-    private void loadPolylineFeature(AbstractFeature feature) {
-        /* double xmin = */getByteBuffer().getDouble();
-        /* double ymin = */getByteBuffer().getDouble();
-        /* double xmax = */getByteBuffer().getDouble();
-        /* double ymax = */getByteBuffer().getDouble();
-
-        int NumParts = getByteBuffer().getInt();
-        int NumPoints = getByteBuffer().getInt();
-
-        int[] NumPartArr = new int[NumParts + 1];
-
-        for (int n = 0; n < NumParts; n++) {
-            int idx = getByteBuffer().getInt();
-            NumPartArr[n] = idx;
-        }
-        NumPartArr[NumParts] = NumPoints;
-
-        double xpnt, ypnt;
-        Polyline ply = new Polyline();
-
-        for (int m = 0; m < NumParts; m++) {
-            xpnt = getByteBuffer().getDouble();
-            ypnt = getByteBuffer().getDouble();
-            ply.startPath(xpnt, ypnt);
-
-            for (int j = NumPartArr[m]; j < NumPartArr[m + 1] - 1; j++) {
-                xpnt = getByteBuffer().getDouble();
-                ypnt = getByteBuffer().getDouble();
-                ply.lineTo(xpnt, ypnt);
-            }
-        }
-
-        feature.setPropertyValue(GEOMETRY_NAME, ply);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileDescriptor.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileDescriptor.java
deleted file mode 100644
index 9c6318f..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/ShapefileDescriptor.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.internal.shapefile;
-
-import java.nio.ByteOrder;
-import java.nio.MappedByteBuffer;
-
-import org.apache.sis.storage.shapefile.ShapeTypeEnum;
-
-/**
- * Shapefile Descriptor.
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class ShapefileDescriptor {
-    /** File code. */
-    private int fileCode; // big
-
-    /** File length. */
-    private int fileLength; // big // The value for file length is the total length of the file in 16-bit words
-
-    /** File version. */
-    private int version; // little
-
-    /** Shapefile type. */
-    private ShapeTypeEnum shapeType; // little
-
-    /** X Min. */
-    private double xmin; // little
-
-    /** Y Min. */
-    private double ymin; // little
-
-    /** X Max. */
-    private double xmax; // little
-
-    /** Y Max. */
-    private double ymax; // little
-
-    /** Z Min. */
-    private double zmin; // little
-
-    /** Z Max. */
-    private double zmax; // little
-
-    /** M Min. */
-    private double mmin; // little
-
-    /** M Max. */
-    private double mmax; // little
-
-    /**
-     * Create a shapefile descriptor.
-     * @param byteBuffer Source Bytebuffer.
-     */
-    public ShapefileDescriptor(MappedByteBuffer byteBuffer) {
-        this.fileCode = byteBuffer.getInt();
-        byteBuffer.getInt();
-        byteBuffer.getInt();
-        byteBuffer.getInt();
-        byteBuffer.getInt();
-        byteBuffer.getInt();
-        this.fileLength = byteBuffer.getInt() * 2;
-
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
-        this.version = byteBuffer.getInt();
-        this.shapeType = ShapeTypeEnum.get(byteBuffer.getInt());
-        this.xmin = byteBuffer.getDouble();
-        this.ymin = byteBuffer.getDouble();
-        this.xmax = byteBuffer.getDouble();
-        this.ymax = byteBuffer.getDouble();
-        this.zmin = byteBuffer.getDouble();
-        this.zmax = byteBuffer.getDouble();
-        this.mmin = byteBuffer.getDouble();
-        this.mmax = byteBuffer.getDouble();
-        byteBuffer.order(ByteOrder.BIG_ENDIAN);
-
-        //dbf.byteBuffer.get(); // should be 0d for field terminator
-    }
-
-    /**
-     * Returns the version of the shapefile.
-     * @return Version.
-     */
-    public int getVersion() {
-        return this.version;
-    }
-
-    /**
-     * Returns the ESRI shape type in the shapefile.
-     * @return Shape type.
-     */
-    public ShapeTypeEnum getShapeType() {
-        return this.shapeType;
-    }
-
-    /**
-     * Returns the X Min property.
-     * @return XMin.
-     */
-    public double getXmin() {
-        return this.xmin;
-    }
-
-    /**
-     * Returns the Y Min property.
-     * @return YMin.
-     */
-    public double getYmin() {
-        return this.ymin;
-    }
-
-    /**
-     * Returns the X Max property.
-     * @return XMax.
-     */
-    public double getXmax() {
-        return this.xmax;
-    }
-
-    /**
-     * Returns the Y Max property.
-     * @return YMax.
-     */
-    public double getYmax() {
-        return this.ymax;
-    }
-
-    /**
-     * Returns the Z Min property.
-     * @return ZMin.
-     */
-    public double getZmin() {
-        return this.zmin;
-    }
-
-    /**
-     * Returns the Z Max property.
-     * @return ZMax.
-     */
-    public double getZmax() {
-        return this.zmax;
-    }
-
-    /**
-     * Returns the M Min property. 
-     * @return M min.
-     */
-    public double getMmin() {
-        return this.mmin;
-    }
-    
-    /**
-     * Returns the M Max property.
-     * @return M Max.
-     */
-    public double getMmax(){
-        return this.mmax;
-    }
-
-    /**
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        StringBuilder s = new StringBuilder();
-        String lineSeparator = System.getProperty("line.separator", "\n");
-
-        s.append("FileCode: ").append(this.fileCode).append(lineSeparator);
-        s.append("FileLength: ").append(this.fileLength).append(lineSeparator);
-        s.append("Version: ").append(this.version).append(lineSeparator);
-        s.append("ShapeType: ").append(this.shapeType).append(lineSeparator);
-        s.append("xmin: ").append(this.xmin).append(lineSeparator);
-        s.append("ymin: ").append(this.ymin).append(lineSeparator);
-        s.append("xmax: ").append(this.xmax).append(lineSeparator);
-        s.append("ymax: ").append(this.ymax).append(lineSeparator);
-        s.append("zmin: ").append(this.zmin).append(lineSeparator);
-        s.append("zmax: ").append(this.zmax).append(lineSeparator);
-        s.append("mmin: ").append(this.mmin).append(lineSeparator);
-        s.append("mmax: ").append(this.mmax).append(lineSeparator);
-        s.append("------------------------").append(lineSeparator);
-
-        return s.toString();
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/AbstractDbase3ByteReader.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/AbstractDbase3ByteReader.java
deleted file mode 100644
index 7678216..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/AbstractDbase3ByteReader.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.File;
-import java.nio.charset.Charset;
-import java.nio.charset.UnsupportedCharsetException;
-import java.text.MessageFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Objects;
-import java.util.logging.Level;
-
-/**
- * The Abstract Byte Reader.
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-abstract class AbstractDbase3ByteReader extends CommonByteReader<SQLInvalidDbaseFileFormatException, SQLDbaseFileNotFoundException> implements Dbase3ByteReader {
-    /** First data record position, in bytes. */
-    protected short firstRecordPosition;
-
-    /** Size of one record, in bytes. */
-    protected short recordLength;
-
-    /** Reserved (dBASE IV) Filled with 00h. */
-    protected byte[] reservedFiller1 = new byte[2];
-
-    /**
-     * Reserved : Incomplete transaction (dBASE IV).
-     * 00h : Transaction ended (or rolled back).
-     * 01h : Transaction started.
-     */
-    protected byte reservedIncompleteTransaction;
-
-    /**
-     * Reserved : Encryption flag (dBASE IV).
-     * 00h : Not encrypted.
-     * 01h : Data encrypted.
-     */
-    protected byte reservedEncryptionFlag;
-
-    /** Reserved : Free record thread (for LAN only). */
-    protected byte[] reservedFreeRecordThread = new byte[4];
-
-    /** Reserved : For multi-user (DBase 3+). */
-    protected byte[] reservedMultiUser = new byte[8];
-
-    /** Reserved : MDX flag (dBASE IV). */
-    protected byte reservedMDXFlag;
-
-    /** Binary code page value. */
-    protected byte codePage;
-
-    /** Reserved (dBASE IV) Filled with 00h. */
-    protected byte[] reservedFiller2 = new byte[2];
-
-    /** Marks the end of the descriptor : must be 0x0D. */
-    protected byte descriptorTerminator;
-
-    /** Valid dBASE III PLUS table file (03h without a memo .DBT file; 83h with a memo). */
-    protected byte dbaseVersion;
-
-    /** Number of records in the table. */
-    protected int rowCount;
-
-    /** Database charset. */
-    protected Charset charset;
-
-    /** Date of last update; in YYMMDD format. */
-    protected byte[] dbaseLastUpdate = new byte[3];
-
-    /**
-     * Map a dbf file.
-     * @param file Database file.
-     * @throws SQLDbaseFileNotFoundException if the DBF file has not been found.
-     * @throws SQLInvalidDbaseFileFormatException if the database has an invalid format.
-     */
-    public AbstractDbase3ByteReader(File file) throws SQLDbaseFileNotFoundException, SQLInvalidDbaseFileFormatException {
-        super(file, SQLInvalidDbaseFileFormatException.class, SQLDbaseFileNotFoundException.class);
-    }
-
-    /**
-     * Returns the charset.
-     * @return Charset.
-     */
-    @Override public Charset getCharset() {
-        return this.charset;
-    }
-
-    /**
-     * Returns the database last update date.
-     * @return Date of the last update.
-     */
-    @Override public Date getDateOfLastUpdate() {
-        return toDate(this.dbaseLastUpdate);
-    }
-    
-    /**
-     * Returns the first record position, in bytes, in the DBase file.
-     * @return First record position.
-     */
-    @Override public short getFirstRecordPosition() {
-        return this.firstRecordPosition;
-    }
-
-    /**
-     * Returns the length (in bytes) of one record in this DBase file, including the delete flag. 
-     * @return Record length.
-     */
-    @Override public short getRecordLength() {
-        return this.recordLength;
-    }
-    
-    /**
-     * Returns the record count.
-     * @return Record count.
-     */
-    @Override public int getRowCount() {
-        return this.rowCount;
-    }
-
-    /**
-     * Convert the binary code page value of the Dbase 3 file to a recent Charset.
-     * @param codePageBinaryValue page code binary value.
-     * @return Charset.
-     * @throws UnsupportedCharsetException if the code page as no representation in recents Charset (legacy DOS or macintosh charsets).
-     */
-    protected Charset toCharset(byte codePageBinaryValue) throws UnsupportedCharsetException {
-        // Attempt to find a known conversion.
-        String dbfCodePage = toCodePage(codePageBinaryValue);
-
-        // If no conversion has been found, decide if the cause is an unsupported value or an illegal value to choose the good exception to return.
-        if (dbfCodePage == null) {
-            switch(codePageBinaryValue & 0xFF) {
-                case 0x04: dbfCodePage = "unsupported"; break;
-                case 0x68: dbfCodePage = "unsupported"; break; // Kamenicky (Czech) MS-DOS
-                case 0x69: dbfCodePage = "unsupported"; break; // Mazovia (Polish) MS-DOS
-                case 0x96: dbfCodePage = "unsupported"; break; // russian mac
-                case 0x97: dbfCodePage = "unsupported"; break; // eastern european macintosh
-                case 0x98: dbfCodePage = "unsupported"; break; // greek macintosh
-                case 0xC8: dbfCodePage = "unsupported"; break; // windows ee
-                default: dbfCodePage = "unsupported"; break;
-            }
-        }
-
-        assert dbfCodePage != null;
-
-        // If the code page cannot find a match for a more recent Charset, we wont be able to handle this DBF.
-        if (dbfCodePage.equals("unsupported")) {
-            String message = format(Level.WARNING, "excp.unsupported_codepage", codePageBinaryValue, getFile().getAbsolutePath());
-            throw new UnsupportedCharsetException(message);
-        }
-
-        try {
-            return Charset.forName(dbfCodePage);
-        }
-        catch(IllegalArgumentException e) {
-            // If this happens here, it means that we have selected a wrong charset. We have a bug.
-            String message = format(Level.WARNING, "assert.wrong_charset_selection", dbfCodePage, getFile().getAbsolutePath());
-            throw new RuntimeException(message);
-        }
-    }
-
-    /**
-     * Return a Charset code page from a binary code page value.
-     * @param pageCodeBinaryValue binary code page value.
-     * @return Page code.
-     */
-    private String toCodePage(byte pageCodeBinaryValue) {
-        // From http://trac.osgeo.org/gdal/ticket/2864
-        HashMap<Integer, String> knownConversions = new HashMap<>();
-        knownConversions.put(0x01, "cp437"); //  U.S. MS–DOS
-        knownConversions.put(0x02, "cp850"); // International MS–DOS
-        knownConversions.put(0x03, "cp1252"); // Windows ANSI
-        knownConversions.put(0x08, "cp865"); //  Danish OEM
-        knownConversions.put(0x09, "cp437"); //  Dutch OEM
-        knownConversions.put(0x0a, "cp850"); //  Dutch OEM*
-        knownConversions.put(0x0b, "cp437"); //  Finnish OEM
-        knownConversions.put(0x0d, "cp437"); //  French OEM
-        knownConversions.put(0x0e, "cp850"); //  French OEM*
-        knownConversions.put(0x0f, "cp437"); //  German OEM
-        knownConversions.put(0x10, "cp850"); //  German OEM*
-        knownConversions.put(0x11, "cp437"); //  Italian OEM
-        knownConversions.put(0x12, "cp850"); //  Italian OEM*
-        knownConversions.put(0x13, "cp932"); //  Japanese Shift-JIS
-        knownConversions.put(0x14, "cp850"); //  Spanish OEM*
-        knownConversions.put(0x15, "cp437"); //  Swedish OEM
-        knownConversions.put(0x16, "cp850"); //  Swedish OEM*
-        knownConversions.put(0x17, "cp865"); //  Norwegian OEM
-        knownConversions.put(0x18, "cp437"); //  Spanish OEM
-        knownConversions.put(0x19, "cp437"); //  English OEM (Britain)
-        knownConversions.put(0x1a, "cp850"); //  English OEM (Britain)*
-        knownConversions.put(0x1b, "cp437"); //  English OEM (U.S.)
-        knownConversions.put(0x1c, "cp863"); //  French OEM (Canada)
-        knownConversions.put(0x1d, "cp850"); //  French OEM*
-        knownConversions.put(0x1f, "cp852"); //  Czech OEM
-        knownConversions.put(0x22, "cp852"); //  Hungarian OEM
-        knownConversions.put(0x23, "cp852"); //  Polish OEM
-        knownConversions.put(0x24, "cp860"); //  Portuguese OEM
-        knownConversions.put(0x25, "cp850"); //  Portuguese OEM*
-        knownConversions.put(0x26, "cp866"); //  Russian OEM
-        knownConversions.put(0x37, "cp850"); //  English OEM (U.S.)*
-        knownConversions.put(0x40, "cp852"); //  Romanian OEM
-        knownConversions.put(0x4d, "cp936"); //  Chinese GBK (PRC)
-        knownConversions.put(0x4e, "cp949"); //  Korean (ANSI/OEM)
-        knownConversions.put(0x4f, "cp950"); //  Chinese Big5 (Taiwan)
-        knownConversions.put(0x50, "cp874"); //  Thai (ANSI/OEM)
-        knownConversions.put(0x57, "cp1252"); // ANSI
-        knownConversions.put(0x58, "cp1252"); // Western European ANSI
-        knownConversions.put(0x59, "cp1252"); // Spanish ANSI
-        knownConversions.put(0x64, "cp852"); //  Eastern European MS–DOS
-        knownConversions.put(0x65, "cp866"); //  Russian MS–DOS
-        knownConversions.put(0x66, "cp865"); //  Nordic MS–DOS
-        knownConversions.put(0x67, "cp861"); //  Icelandic MS–DOS
-        knownConversions.put(0x6a, "cp737"); //  Greek MS–DOS (437G)
-        knownConversions.put(0x6b, "cp857"); //  Turkish MS–DOS
-        knownConversions.put(0x6c, "cp863"); //  French–Canadian MS–DOS
-        knownConversions.put(0x78, "cp950"); //  Taiwan Big 5
-        knownConversions.put(0x79, "cp949"); //  Hangul (Wansung)
-        knownConversions.put(0x7a, "cp936"); //  PRC GBK
-        knownConversions.put(0x7b, "cp932"); //  Japanese Shift-JIS
-        knownConversions.put(0x7c, "cp874"); //  Thai Windows/MS–DOS
-        knownConversions.put(0x86, "cp737"); //  Greek OEM
-        knownConversions.put(0x87, "cp852"); //  Slovenian OEM
-        knownConversions.put(0x88, "cp857"); //  Turkish OEM
-        knownConversions.put(0xc8, "cp1250"); // Eastern European Windows
-        knownConversions.put(0xc9, "cp1251"); // Russian Windows
-        knownConversions.put(0xca, "cp1254"); // Turkish Windows
-        knownConversions.put(0xcb, "cp1253"); // Greek Windows
-        knownConversions.put(0xcc, "cp1257"); // Baltic Windows
-
-        return(knownConversions.get(pageCodeBinaryValue & 0xFF));
-    }
-    
-    /**
-     * Set a charset.
-     * @param cs Charset.
-     */
-    public void setCharset(Charset cs) {
-        this.charset = cs;
-    }
-
-    /**
-     * Return a date from a byte array.
-     * @param yymmdd byte[3] with byte[0] = year (2 digits), [1] = month, [2] = day.
-     * @return Date.
-     */
-    private Date toDate(byte[] yymmdd) {
-        Objects.requireNonNull(yymmdd, "the yymmdd bytes cannot be null");
-
-        if (yymmdd.length != 3)
-            throw new IllegalArgumentException(MessageFormat.format("Database:toDate() works only on a 3 bytes YY MM DD date. this array has {0} length", yymmdd.length));
-
-        Objects.requireNonNull(yymmdd[0], "the year byte cannot be null");
-        Objects.requireNonNull(yymmdd[1], "the month byte cannot be null");
-        Objects.requireNonNull(yymmdd[2], "the day byte cannot be null");
-
-        int year = yymmdd[0] < 70 ? 100 + yymmdd[0] : yymmdd[0];
-        int month = yymmdd[1];
-        int day = yymmdd[2];
-
-        @SuppressWarnings("deprecation") // But everything is deprecated in DBF files...
-        Date date = new Date(year, month, day);
-        return date;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/AbstractJDBC.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/AbstractJDBC.java
deleted file mode 100644
index 5c12b48..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/AbstractJDBC.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.File;
-import java.sql.*;
-import java.util.logging.Level;
-
-import org.apache.sis.internal.shapefile.AutoChecker;
-
-
-/**
- * Base class for each JDBC class.
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public abstract class AbstractJDBC extends AutoChecker implements Wrapper {
-    /**
-     * Constructs a new instance of a JDBC interface.
-     */
-    public AbstractJDBC() {
-    }
-
-    /**
-     * Returns the JDBC interface implemented by this class.
-     * This is used for formatting error messages.
-     * @return The JDBC interface implemented by this class.
-     */
-    abstract protected Class<?> getInterface();
-
-    /**
-     * Unsupported by default.
-     * @param iface the type of the wrapped object.
-     * @return The wrapped object.
-     */
-    @Override
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        throw unsupportedOperation("unwrap", iface);
-    }
-
-    /**
-     * Defaults to {@code null}.
-     * @return SQL Warning.
-     */
-    public SQLWarning getWarnings() {
-        return null;
-    }
-
-    /**
-     * Defaults to nothing, since there is no SQL warning.
-     */
-    public void clearWarnings() {
-    }
-
-    /**
-     * Returns an unsupported operation exception to be thrown.
-     * @param methodOrWishedFeatureName The feature / call the caller attempted.
-     * @return the not supported feature exception.
-     * @throws SQLFeatureNotSupportedException the not supported feature.
-     */
-    public final SQLFeatureNotSupportedException unsupportedOperation(final String methodOrWishedFeatureName) throws SQLFeatureNotSupportedException {
-        String message = format(Level.WARNING, "excp.unsupportedDriverFeature", getInterface(), methodOrWishedFeatureName, getClass().getSimpleName());
-        throw new SQLFeatureNotSupportedException(message);
-    }
-
-    /**
-     * Returns an unsupported operation exception to be thrown : this exception add parameters sent to the method that isn't implemented.
-     * @param methodOrWishedFeatureName The feature / call the caller attempted.
-     * @param args Arguments that where sent to the unimplemented function.
-     * @return the not supported feature exception.
-     * @throws SQLFeatureNotSupportedException the not supported feature.
-     */
-    public final SQLFeatureNotSupportedException unsupportedOperation(final String methodOrWishedFeatureName, Object... args) throws SQLFeatureNotSupportedException {
-        StringBuffer arguments = new StringBuffer();
-
-        for(Object arg : args) {
-            arguments.append(arguments.length() == 0 ? "" : ", ");   // Separator if needed.
-            arguments.append(arg instanceof String ? "\"" : "");     // Enclosing " for String, if needed.
-            arguments.append(arg == null ? "null" : arg.toString()); // String value of the argument.
-            arguments.append(arg instanceof String ? "\"" : "");     // Enclosing " for String, if needed.
-        }
-
-        String message = format(Level.WARNING, "excp.unsupportedDriverFeature_with_arguments", getInterface(), methodOrWishedFeatureName, getClass().getSimpleName(), arguments.toString());
-        throw new SQLFeatureNotSupportedException(message);
-    }
-
-    /**
-     * log a function call in the driver : very verbose.
-     * @param methodName The call the caller attempted.
-     */
-    public void logStep(final String methodName) {
-        log(Level.FINER, "log.step", methodName, getClass().getSimpleName());
-    }
-
-    /**
-     * log a function call in the driver : very verbose.
-     * @param methodName The call the caller attempted.
-     * @param args Arguments that where sent to the unimplemented function.
-     */
-    public void logStep(final String methodName, Object... args) {
-        if (isLoggable(Level.FINER)) { // Avoid resolution of arguments(...) if not needed.
-            log(Level.FINER, "log.step_with_arguments", methodName, getClass().getSimpleName(), arguments(args));
-        }
-    }
-
-    /**
-     * log an unsupported feature as a warning.
-     * @param methodName The call the caller attempted.
-     */
-    public void logUnsupportedOperation(final String methodName) {
-        log(Level.WARNING, "excp.unsupportedDriverFeature", getInterface(), methodName, getClass().getSimpleName());
-    }
-
-    /**
-     * log an unsupported feature as a warning.
-     * @param methodName The call the caller attempted.
-     * @param args Arguments that where sent to the unimplemented function.
-     */
-    public void logUnsupportedOperation(final String methodName, Object... args) {
-        log(Level.WARNING, "excp.unsupportedDriverFeature_with_arguments", getInterface(), methodName, getClass().getSimpleName(), arguments(args));
-    }
-
-    /**
-     * Returns the Database File.
-     * @return Database File.
-     */
-    abstract protected File getFile();
-
-    /**
-     * Concat arguments in a StringBuffer.
-     * @param args arguments.
-     * @return Arguments.
-     */
-    private StringBuffer arguments(Object... args) {
-        StringBuffer arguments = new StringBuffer();
-
-        for(Object arg : args) {
-            arguments.append(arguments.length() == 0 ? "" : ", ");   // Separator if needed.
-            arguments.append(arg instanceof String ? "\"" : "");     // Enclosing " for String, if needed.
-            arguments.append(arg == null ? "null" : arg.toString()); // String value of the argument.
-            arguments.append(arg instanceof String ? "\"" : "");     // Enclosing " for String, if needed.
-        }
-
-        return arguments;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/CommonByteReader.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/CommonByteReader.java
deleted file mode 100644
index e1fadd7..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/CommonByteReader.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.*;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Objects;
-import java.util.logging.Level;
-
-import org.apache.sis.internal.shapefile.AutoChecker;
-
-/**
- * Common byte reader.
- * @author  Marc Le Bihan
- * @version 0.5
- * @param <InvalidFormatException> Invalid format Exception to throw in case of trouble.
- * @param <FNFException> File not found Exception to throw in case of missing file.
- * @since   0.5
- * @module
- */
-public abstract class CommonByteReader<InvalidFormatException extends Exception, FNFException extends Exception> extends AutoChecker implements AutoCloseable  {
-    /** The File. */
-    private File file;
-
-    /** Input Stream on the DBF. */
-    private FileInputStream fis;
-
-    /** File channel on the file. */
-    private FileChannel fc;
-
-    /** Buffer reader. */
-    private MappedByteBuffer byteBuffer;
-
-    /** Indicates if the byte buffer is closed. */
-    private boolean isClosed = false;
-
-    /** Invalid Exception to throw in case of invalid file format. */
-    private Class<InvalidFormatException> classInvalidFormatException;
-
-    /** Invalid Exception to throw in case of file not found exception. */
-    private Class<FNFException> classFNFException;
-
-    /**
-     * Create and open a byte reader based on a file.
-     * @param f File.
-     * @param invalidFormatException Invalid Exception to throw in case of invalid file format.
-     * @param fileNotFoundException Invalid Exception to throw in case of file not found exception.
-     * @throws FNFException if the file cannot be opened.
-     * @throws InvalidFormatException if the file format is invalid.
-     */
-    public CommonByteReader(File f, Class<InvalidFormatException> invalidFormatException, Class<FNFException> fileNotFoundException) throws FNFException, InvalidFormatException {
-        Objects.requireNonNull(f, "The file cannot be null.");
-        this.classInvalidFormatException = invalidFormatException;
-        this.classFNFException = fileNotFoundException;
-
-        this.file = f;
-
-        try {
-            this.fis = new FileInputStream(this.file);
-        }
-        catch(FileNotFoundException e) {
-            throwException(this.classInvalidFormatException, e.getMessage(), e);
-            throw new RuntimeException("this place should not be reached.");
-        }
-
-        this.fc = this.fis.getChannel();
-
-        try {
-            int fsize = (int)this.fc.size();
-            this.byteBuffer = this.fc.map(FileChannel.MapMode.READ_ONLY, 0, fsize);
-        }
-        catch(IOException e) {
-            String message = format(Level.WARNING, "excp.reader_cannot_be_created", this.file.getAbsolutePath(), e.getMessage());
-            throwException(this.classFNFException, message, e);
-            throw new RuntimeException("this place should not be reached.");
-        }
-   }
-
-    /**
-     * Close the MappedByteReader.
-     * @throws IOException if the close operation fails.
-     */
-    @Override
-    public void close() throws IOException {
-        if (this.fc != null)
-            this.fc.close();
-
-        if (this.fis != null)
-            this.fis.close();
-
-        this.isClosed = true;
-    }
-
-    /**
-     * Returns the closed state of this binary reader.
-     * @return true if it is closed.
-     */
-    public boolean isClosed() {
-        return this.isClosed;
-    }
-
-    /**
-     * Returns the byte buffer.
-     * @return Byte Buffer.
-     */
-    public MappedByteBuffer getByteBuffer() {
-        return this.byteBuffer;
-    }
-
-    /**
-     * Return the file mapped.
-     * @return File.
-     */
-    public File getFile() {
-        return this.file;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBFDriver.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBFDriver.java
deleted file mode 100644
index 198ffa7..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBFDriver.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.File;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverPropertyInfo;
-import java.util.Objects;
-import java.util.Properties;
-import java.util.logging.Logger;
-
-import org.apache.sis.internal.shapefile.jdbc.connection.DBFConnection;
-import org.apache.sis.internal.system.Modules;
-
-
-/**
- * Database driver for DBF 3.
- *
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class DBFDriver extends AbstractJDBC implements Driver {
-    /**
-     * Creates a new driver.
-     */
-    public DBFDriver() {
-    }
-
-    /**
-     * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
-     */
-    @Override
-    public boolean isWrapperFor(Class<?> iface) {
-        return iface.isAssignableFrom(getInterface());
-    }
-
-    /**
-     * Returns the JDBC interface implemented by this class.
-     * This is used for formatting error messages.
-     */
-    @Override
-    final protected Class<?> getInterface() {
-        return Driver.class;
-    }
-
-    /**
-     * Attempts to make a database connection to the given filename.
-     *
-     * @param  url  The path to a {@code .dbf} file.
-     * @param  info Properties to ask for special features, behavior, or compatibility.
-     * @return A connection to the given DBF file.
-     * @throws SQLInvalidDbaseFileFormatException if the database file format is invalid.
-     * @throws SQLDbaseFileNotFoundException if the database file doesn't exist.
-     * @throws SQLInvalidDbaseFileFormatException if the database file has a wrong format.
-     */
-    @Override
-    @SuppressWarnings("resource") // the function opens a connection.
-    public Connection connect(final String url, Properties info) throws SQLInvalidDbaseFileFormatException, SQLDbaseFileNotFoundException {
-        Objects.requireNonNull(url, "the DBase3 url cannot be null");
-        File file = new File(url);
-        return new DBFConnection(file, new MappedByteReader(file, info));
-    }
-
-    /**
-     * Returns {@code true} if this driver thinks that it can open the given URL.
-     */
-    @Override
-    public boolean acceptsURL(final String url) {
-        if (!url.endsWith(".dbf")) {
-            return false;
-        }
-
-        final File datafile = new File(url);
-        return datafile.isFile(); // Future version should check for magic number.
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#getFile()
-     */
-    @Override protected File getFile() {
-        return null;
-    }
-
-    /**
-     * Gets information about the possible properties for this driver.
-     * The current version has none.
-     */
-    @Override
-    public DriverPropertyInfo[] getPropertyInfo(@SuppressWarnings("unused") String url, @SuppressWarnings("unused") Properties info) {
-        return new DriverPropertyInfo[0];
-    }
-
-    /**
-     * The major version number of this driver.
-     * This is set to the Apache SIS version.
-     */
-    @Override
-    public int getMajorVersion() {
-        return Modules.MAJOR_VERSION;
-    }
-
-    /**
-     * The minor version number of this driver.
-     * This is set to the Apache SIS version.
-     */
-    @Override
-    public int getMinorVersion() {
-        return Modules.MINOR_VERSION;
-    }
-
-    /**
-     * This driver is currently not compliant.
-     * It has to succeed these tests first:
-     * <a href="http://www.oracle.com/technetwork/java/jdbctestsuite-1-3-1-140675.html">Compliance tests</a>.
-     */
-    @Override
-    public boolean jdbcCompliant() {
-        return false; // No, and for some time...
-    }
-
-    /**
-     * The logger used by this driver.
-     */
-    @Override
-    public Logger getParentLogger() {
-        return super.getLogger();
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBase3FieldDescriptor.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBase3FieldDescriptor.java
deleted file mode 100644
index 5613ace..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBase3FieldDescriptor.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.nio.MappedByteBuffer;
-
-import org.apache.sis.internal.shapefile.AutoChecker;
-
-// Branch-dependent imports
-import org.apache.sis.internal.jdk8.JDK8;
-
-
-/**
- * Field descriptor.
- *
- * @author  Travis L. Pinney
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class DBase3FieldDescriptor extends AutoChecker {
-    /** Field name. */
-    private byte[] fieldName = new byte[11];
-
-    /** Field name as String, for performance issues. */
-    private String stringFieldName;
-
-    /** Field type. */
-    private DBaseDataType fieldType;
-
-    /** Field address (Field data address (address is set in memory; not useful on disk). */
-    private byte[] fieldAddress = new byte[4];
-
-    /** Field length. */
-    private byte fieldLength;
-
-    /** Decimal count. */
-    private byte fieldDecimalCount;
-
-    /** Reserved 2. */
-    private byte[] dbasePlusLanReserved2 = new byte[2];
-
-    /** Work area id. */
-    @SuppressWarnings("unused") // Kept in case of later ALTER TABLE sql calls.
-    private byte workAreaID;
-
-    /** Reserved 3. */
-    private byte[] dbasePlusLanReserved3 = new byte[2];
-
-    /** Undocumented use. */
-    @SuppressWarnings("unused") // Kept in case of later ALTER TABLE sql calls.
-    private byte setFields;
-
-    /**
-     * Create a field descriptor from the current position of the binary stream.
-     * @param byteBuffer ByteBuffer.
-     */
-    public DBase3FieldDescriptor(MappedByteBuffer byteBuffer) {
-        // Field name.
-        byteBuffer.get(this.fieldName);
-
-        // Field type.
-        char dt = (char)byteBuffer.get();
-        this.fieldType = DBaseDataType.valueOfDataType(dt);
-
-        // Field address.
-        byteBuffer.get(this.fieldAddress);
-
-        // Length and scale.
-        this.fieldLength = byteBuffer.get();
-        this.fieldDecimalCount = byteBuffer.get();
-
-        byteBuffer.getShort(); // reserved
-
-        byteBuffer.get(this.dbasePlusLanReserved2);
-
-        // Work area id.
-        this.workAreaID = byteBuffer.get();
-
-        byteBuffer.get(this.dbasePlusLanReserved3);
-
-        // Fields.
-        this.setFields = byteBuffer.get();
-
-        byte[] data = new byte[6];
-        byteBuffer.get(data); // reserved
-    }
-
-    /**
-     * Returns the decimal count of that field.
-     * @return Decimal count.
-     */
-    public int getDecimalCount() {
-        return this.fieldDecimalCount & 0xFF;
-    }
-
-    /**
-     * Returns the field length.
-     * @return field length.
-     */
-    public int getLength() {
-        return this.fieldLength & 0xFF;
-    }
-
-    /**
-     * Return the field name.
-     * @return Field name.
-     */
-    public String getName() {
-        // Converting bytes to String takes time. Only do that once.
-        if (this.stringFieldName == null) {
-            int length = this.fieldName.length;
-            while (length != 0 && JDK8.toUnsignedInt(this.fieldName[length - 1]) <= ' ') {
-                length--;
-            }
-
-            this.stringFieldName = new String(this.fieldName, 0, length);
-        }
-
-        return this.stringFieldName;
-    }
-
-    /**
-     * Return the field data type.
-     * @return Data type.
-     */
-    public DBaseDataType getType() {
-        return(this.fieldType);
-    }
-
-    /**
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        String text = format("toString", getName(), this.fieldType, JDK8.toUnsignedInt(this.fieldLength), JDK8.toUnsignedInt(this.fieldDecimalCount));
-        return text;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBaseDataType.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBaseDataType.java
deleted file mode 100644
index 6078a9a..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/DBaseDataType.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-
-/**
- * Provides a simple DataType class.
- *
- * @author  Travis L. Pinney
- * @version 0.5
- *
- * @see <a href="http://www.clicketyclick.dk/databases/xbase/format/data_types.html">Xbase Data Types</a>
- *
- * @since 0.5
- * @module
- */
-public enum DBaseDataType {
-    /** Character (less than 254 characters). */
-    Character('C'),
-
-    /** Number (less than 18 characters, can include sign and decimal). */
-    Number('N'),
-
-    /** Logical (3 way, ? Y,y,T,t  N,n,F,f). */
-    Logical('L'),
-
-    /** Date (YYYYMMDD format). */
-    Date('D'),
-
-    /** Memo (Pointer to ASCII text field). */
-    Memo('M'),
-
-    /** Floating point (20 digits). */
-    FloatingPoint('F'),
-
-    // CharacterNameVariable("?"),  //1-254 Characters
-
-    /** Picture (memo). */
-    Picture('P'),
-
-    /** Currency (Foxpro). */
-    Currency('Y'),
-
-    /** Date time (32 bit little-endian Julian date, 32 byte little endian milliseconds since midnight). */
-    DateTime('T'),
-
-    /** Integer (4 byte little endian). */
-    Integer('I'),
-
-    /** Varifield (???). */
-    VariField('V'),
-
-    /** Variant (???). */
-    Variant('X'),
-
-    /** Time stamp (see url). */
-    TimeStamp('@'),
-
-    /** Double. */
-    Double('O'),
-
-    /** Auto increment. */
-    AutoIncrement('+');
-
-    /** Data type. */
-    public final char datatype;
-
-    /**
-     * Construct a datatype.
-     * @param type Data type.
-     */
-    DBaseDataType(char type) {
-        this.datatype = type;
-    }
-
-    /**
-     * Return the Datatype enum of a code.
-     * @param code Character code describing the dbf datatype.
-     * @return Datatype.
-     */
-    public static DBaseDataType valueOfDataType(char code) {
-        for (DBaseDataType v : values()) {
-            if (v.datatype == code) {
-                return v;
-            }
-        }
-        throw new IllegalArgumentException("Enum datatype is incorrect");
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/Dbase3ByteReader.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/Dbase3ByteReader.java
deleted file mode 100644
index d9fecf9..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/Dbase3ByteReader.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sis.internal.shapefile.jdbc.resultset.SQLIllegalColumnIndexException;
-import org.apache.sis.internal.shapefile.jdbc.resultset.SQLNoSuchFieldException;
-import org.apache.sis.feature.AbstractFeature;
-
-/**
- * Database byte reader contract. Used to allow refactoring of core byte management of a DBase file.
- * @author Marc LE BIHAN
- */
-public interface Dbase3ByteReader {
-    /**
-     * Close the MappedByteReader.
-     * @throws IOException if the close operation fails.
-     */
-    public void close() throws IOException;
-
-    /**
-     * Checks if the ByteReader is closed.
-     * @return true if it is closed.
-     */
-    public boolean isClosed();
-
-    /**
-     * Returns the fields descriptors in their binary format.
-     * @return Fields descriptors.
-     */
-    public List<DBase3FieldDescriptor> getFieldsDescriptors();
-
-    /**
-     * Returns the column index for the given column name.
-     * The default implementation of all methods expecting a column label will invoke this method.
-     * @param columnLabel The name of the column.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return The index of the given column name : first column is 1.
-     * @throws SQLNoSuchFieldException if there is no field with this name in the query.
-     */
-    public int findColumn(String columnLabel, String sql) throws SQLNoSuchFieldException;
-
-    /**
-     * Returns the charset.
-     * @return Charset.
-     */
-    public Charset getCharset();
-
-    /**
-     * Returns the column count of the unique table of the DBase 3.
-     * @return Column count.
-     */
-    public int getColumnCount();
-
-    /**
-     * Return a field name.
-     * @param columnIndex Column index.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return Field Name.
-     * @throws SQLIllegalColumnIndexException if the index is out of bounds.
-     */
-    public String getFieldName(int columnIndex, String sql) throws SQLIllegalColumnIndexException;
-
-    /**
-     * Returns the database last update date.
-     * @return Date of the last update.
-     */
-    public Date getDateOfLastUpdate();
-    
-    /**
-     * Returns the first record position, in bytes, in the DBase file.
-     * @return First record position.
-     */
-    public short getFirstRecordPosition();
-
-    /**
-     * Returns the length (in bytes) of one record in this DBase file, including the delete flag. 
-     * @return Record length.
-     */
-    public short getRecordLength();
-    
-    /**
-     * Returns the record count.
-     * @return Record count.
-     */
-    public int getRowCount();
-
-    /**
-     * Returns the current record number.
-     * @return Current record number.
-     */
-    public int getRowNum();
-
-    /**
-     * Load a row into a feature.
-     * @param feature Feature to fill.
-     */
-    public void loadRowIntoFeature(AbstractFeature feature);
-
-    /**
-     * Checks if a next row is available. Warning : it may be a deleted one.
-     * @return true if a next row is available.
-     */
-    public boolean nextRowAvailable();
-
-    /**
-     * Read the next row as a set of objects.
-     * @return Map of field name / object value.
-     */
-    public Map<String, byte[]> readNextRowAsObjects();
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/MappedByteReader.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/MappedByteReader.java
deleted file mode 100644
index 05a7a81..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/MappedByteReader.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.File;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteOrder;
-import java.nio.charset.Charset;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.*;
-import java.util.logging.Level;
-
-import org.apache.sis.internal.shapefile.jdbc.resultset.SQLIllegalColumnIndexException;
-import org.apache.sis.internal.shapefile.jdbc.resultset.SQLNoSuchFieldException;
-import org.apache.sis.feature.AbstractFeature;
-
-// Branch-dependent imports
-import org.apache.sis.internal.jdk8.JDK8;
-
-
-/**
- * Reader of a Database Binary content by the way of a {@link java.nio.MappedByteBuffer}
- *
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class MappedByteReader extends AbstractDbase3ByteReader implements AutoCloseable {
-    /** List of field descriptors. */
-    private List<DBase3FieldDescriptor> fieldsDescriptors = new ArrayList<>();
-
-    /** Connection properties. */
-    private Properties info;
-
-    /**
-     * Construct a mapped byte reader on a file.
-     * @param dbase3File File.
-     * @param connectionInfos Connection properties, maybe null.
-     * @throws SQLInvalidDbaseFileFormatException if the database seems to be invalid.
-     * @throws SQLDbaseFileNotFoundException if the Dbase file has not been found.
-     */
-    public MappedByteReader(File dbase3File, Properties connectionInfos) throws SQLInvalidDbaseFileFormatException, SQLDbaseFileNotFoundException {
-        super(dbase3File);
-        this.info = connectionInfos;
-
-        // React to special features asked.
-        if (this.info != null) {
-            // Sometimes, DBF files have a wrong charset, or more often : none, and you have to specify it.
-            String recordCharset = (String)this.info.get("record_charset");
-
-            if (recordCharset != null) {
-                Charset cs = Charset.forName(recordCharset);
-                setCharset(cs);
-            }
-        }
-
-        loadDescriptor();
-    }
-
-    /**
-     * Load a row into a feature.
-     * @param feature Feature to fill.
-     */
-    @Override public void loadRowIntoFeature(AbstractFeature feature) {
-        // TODO: ignore deleted records
-        getByteBuffer().get(); // denotes whether deleted or current
-        // read first part of record
-
-        for (DBase3FieldDescriptor fd : this.fieldsDescriptors) {
-            byte[] data = new byte[fd.getLength()];
-            getByteBuffer().get(data);
-
-            int length = data.length;
-            while (length != 0 && JDK8.toUnsignedInt(data[length - 1]) <= ' ') {
-                length--;
-            }
-
-            String value = new String(data, 0, length);
-            feature.setPropertyValue(fd.getName(), value);
-        }
-    }
-
-    /**
-     * Checks if a next row is available. Warning : it may be a deleted one.
-     * @return true if a next row is available.
-     */
-    @Override
-    public boolean nextRowAvailable() {
-        // 1) Check for remaining bytes.
-        if (getByteBuffer().hasRemaining() == false) {
-            return false;
-        }
-
-        // 2) Check that the immediate next byte read isn't the EOF signal.
-        byte eofCheck = getByteBuffer().get();
-
-        boolean isEOF = (eofCheck == 0x1A);
-        this.log(Level.FINER, "log.delete_status", getRowNum(), eofCheck, isEOF ? "EOF" : "Active");
-
-        if (eofCheck == 0x1A) {
-            return false;
-        }
-        else {
-            // Return one byte back.
-            int position = getByteBuffer().position();
-            getByteBuffer().position(position-1);
-            return true;
-        }
-    }
-
-    /**
-     * Returns the record number of the last record red.
-     * @return The record number.
-     */
-    @Override public int getRowNum() {
-        int position = getByteBuffer().position();
-        int recordNumber = (position - (firstRecordPosition & 0xFFFF)) / (recordLength & 0xFFFF);
-        return recordNumber;
-    }
-
-    /**
-     * Read the next row as a set of objects.
-     * @return Map of field name / object value.
-     */
-    @Override
-    public Map<String, byte[]> readNextRowAsObjects() {
-        // TODO: ignore deleted records
-        /* byte isDeleted = */ getByteBuffer().get(); // denotes whether deleted or current
-
-        // read first part of record
-        HashMap<String, byte[]> fieldsValues = new HashMap<>();
-
-        for (DBase3FieldDescriptor fd : this.fieldsDescriptors) {
-            byte[] data = new byte[fd.getLength()];
-            getByteBuffer().get(data);
-
-            // Trim the bytes right.
-            int length = data.length;
-
-            while (length != 0 && JDK8.toUnsignedInt(data[length - 1]) <= ' ') {
-                length--;
-            }
-
-            if (length != data.length) {
-                byte[] dataTrimmed = new byte[length];
-
-                for(int index=0; index < length; index ++) {
-                    dataTrimmed[index] = data[index];
-                }
-
-                fieldsValues.put(fd.getName(), dataTrimmed);
-            }
-            else {
-                fieldsValues.put(fd.getName(), data);
-            }
-        }
-
-        return fieldsValues;
-    }
-
-    /**
-     * Loading the database file content from binary .dbf file.
-     * @throws SQLInvalidDbaseFileFormatException if descriptor is not readable.
-     */
-    private void loadDescriptor() throws SQLInvalidDbaseFileFormatException {
-        try {
-            this.dbaseVersion = getByteBuffer().get();
-            getByteBuffer().get(this.dbaseLastUpdate);
-
-            getByteBuffer().order(ByteOrder.LITTLE_ENDIAN);
-            this.rowCount = getByteBuffer().getInt();
-            this.firstRecordPosition = getByteBuffer().getShort();
-            this.recordLength = getByteBuffer().getShort();
-            getByteBuffer().order(ByteOrder.BIG_ENDIAN);
-
-            getByteBuffer().get(this.reservedFiller1);
-            this.reservedIncompleteTransaction = getByteBuffer().get();
-            this.reservedEncryptionFlag = getByteBuffer().get();
-            getByteBuffer().get(this.reservedFreeRecordThread);
-            getByteBuffer().get(this.reservedMultiUser);
-            this.reservedMDXFlag = getByteBuffer().get();
-
-            // Translate code page value to a known charset.
-            this.codePage = getByteBuffer().get();
-
-            if (this.charset == null) {
-                try {
-                    this.charset = toCharset(this.codePage);
-                }
-                catch(UnsupportedCharsetException e) {
-                    // Warn the caller that he will have to perform is own conversions.
-                    log(Level.WARNING, "log.no_valid_charset", getFile().getAbsolutePath(), e.getMessage());
-                }
-            }
-            else {
-                log(Level.INFO, "log.record_charset", this.charset.name());
-            }
-
-            getByteBuffer().get(this.reservedFiller2);
-
-            while(getByteBuffer().position() < this.firstRecordPosition - 1) {
-                DBase3FieldDescriptor fd = new DBase3FieldDescriptor(getByteBuffer());
-                this.fieldsDescriptors.add(fd);
-                // loop until you hit the 0Dh field terminator
-            }
-
-            this.descriptorTerminator = getByteBuffer().get();
-
-            // If the last character read after the field descriptor isn't 0x0D, the expected mark has not been found and the DBF is corrupted.
-            if (this.descriptorTerminator != 0x0D) {
-                String message = format(Level.WARNING, "excp.filedescriptor_problem", getFile().getAbsolutePath(), "Character marking the end of the fields descriptors (0x0D) has not been found.");
-                throw new SQLInvalidDbaseFileFormatException(message);
-            }
-        }
-        catch(BufferUnderflowException e) {
-            // This exception doesn't denote a trouble of file opening because the file has been checked before
-            // the calling of this private function.
-            // Therefore, an internal structure problem cause maybe a premature End of file or anything else, but the only thing
-            // we can conclude is : we are not before a device trouble, but a file format trouble.
-            String message = format(Level.WARNING, "excp.filedescriptor_problem", getFile().getAbsolutePath(), e.getMessage());
-            throw new SQLInvalidDbaseFileFormatException(message);
-        }
-    }
-
-    /**
-     * Returns the fields descriptors in their binary format.
-     * @return Fields descriptors.
-     */
-    @Override
-    public List<DBase3FieldDescriptor> getFieldsDescriptors() {
-        return this.fieldsDescriptors;
-    }
-
-    /**
-     * Return a field name.
-     * @param columnIndex Column index.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return Field Name.
-     * @throws SQLIllegalColumnIndexException if the index is out of bounds.
-     */
-    @Override
-    public String getFieldName(int columnIndex, String sql) throws SQLIllegalColumnIndexException {
-        return getField(columnIndex, sql).getName();
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.Dbase3ByteReader#getColumnCount()
-     */
-    @Override
-    public int getColumnCount() {
-        return this.fieldsDescriptors.size();
-    }
-
-    /**
-     * Returns the column index for the given column name.
-     * The default implementation of all methods expecting a column label will invoke this method.
-     * @param columnLabel The name of the column.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return The index of the given column name : first column is 1.
-     * @throws SQLNoSuchFieldException if there is no field with this name in the query.
-     */
-    @Override
-    public int findColumn(String columnLabel, String sql) throws SQLNoSuchFieldException {
-        // If the column name is null, no search is needed.
-        if (columnLabel == null) {
-            String message = format(Level.WARNING, "excp.no_such_column_in_resultset", columnLabel, sql, getFile().getName());
-            throw new SQLNoSuchFieldException(message, sql, getFile(), columnLabel);
-        }
-
-        // Search the field among the fields descriptors.
-        for(int index=0; index < this.fieldsDescriptors.size(); index ++) {
-            if (this.fieldsDescriptors.get(index).getName().equals(columnLabel)) {
-                return index + 1;
-            }
-        }
-
-        // If we are here, we haven't found our field. Throw an exception.
-        String message = format(Level.WARNING, "excp.no_such_column_in_resultset", columnLabel, sql, getFile().getName());
-        throw new SQLNoSuchFieldException(message, sql, getFile(), columnLabel);
-    }
-
-    /**
-     * Returns the field descriptor of a given ResultSet column index.
-     * @param columnIndex Column index, first column is 1, second is 2, etc.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return Field Descriptor.
-     * @throws SQLIllegalColumnIndexException if the index is out of bounds.
-     */
-    private DBase3FieldDescriptor getField(int columnIndex, String sql) throws SQLIllegalColumnIndexException {
-        if (columnIndex < 1 || columnIndex > getColumnCount()) {
-            String message = format(Level.WARNING, "excp.illegal_column_index", columnIndex, getColumnCount());
-            throw new SQLIllegalColumnIndexException(message, sql, getFile(), columnIndex);
-        }
-
-        return this.fieldsDescriptors.get(columnIndex-1);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLConnectionClosedException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLConnectionClosedException.java
deleted file mode 100644
index 118f6d9..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLConnectionClosedException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.io.File;
-import java.sql.SQLException;
-
-/**
- * Exception thrown when a connection is closed.
- * @author Marc LE BIHAN
- */
-public class SQLConnectionClosedException extends SQLException {
-    /** Serial ID. */
-    private static final long serialVersionUID = -7806101485624353416L;
-
-    /** The SQL Statement that whas attempted (if known). */
-    private String sql;
-
-    /** The database file. */
-    private File database;
-
-    /**
-     * Build the exception.
-     * @param message Exception message.
-     * @param sqlStatement SQL Statement who encountered the trouble, if known.
-     * @param dbf The database that was queried.
-     */
-    public SQLConnectionClosedException(String message, String sqlStatement, File dbf) {
-        super(message);
-        this.sql = sqlStatement;
-        this.database = dbf;
-    }
-
-    /**
-     * Returns the SQL statement who encountered the "connection closed" alert, if known.
-     * @return SQL statement or null.
-     */
-    public String getSQL() {
-        return this.sql;
-    }
-
-    /**
-     * Returns the database file that is not opened for connection.
-     * @return Database file.
-     */
-    public File getDatabase() {
-        return this.database;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLDbaseFileNotFoundException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLDbaseFileNotFoundException.java
deleted file mode 100644
index 73572f4..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLDbaseFileNotFoundException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.sql.SQLNonTransientException;
-
-
-/**
- * Thrown when a DBF file has not been found.
- *
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class SQLDbaseFileNotFoundException extends SQLNonTransientException {
-    /** Serial UID. */
-    private static final long serialVersionUID = 2572691456125734352L;
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     */
-    public SQLDbaseFileNotFoundException(String message) {
-        super(message);
-    }
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     * @param cause Root cause of the exception.
-     */
-    public SQLDbaseFileNotFoundException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLInvalidDbaseFileFormatException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLInvalidDbaseFileFormatException.java
deleted file mode 100644
index ba44980..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/SQLInvalidDbaseFileFormatException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc;
-
-import java.sql.SQLNonTransientException;
-
-
-/**
- * Thrown when the DBF file format seems to be invalid.
- *
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class SQLInvalidDbaseFileFormatException extends SQLNonTransientException {
-    /** Serial UID. */
-    private static final long serialVersionUID = 3924612615300490837L;
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     */
-    public SQLInvalidDbaseFileFormatException(String message) {
-        super(message);
-    }
-
-    /**
-     * Construct an exception.
-     * @param message Message of the exception.
-     * @param cause Root cause of the exception.
-     */
-    public SQLInvalidDbaseFileFormatException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/AbstractConnection.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/AbstractConnection.java
deleted file mode 100644
index 89d1845..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/AbstractConnection.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc.connection;
-
-import java.sql.*;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executor;
-import java.util.logging.Level;
-
-import org.apache.sis.internal.shapefile.jdbc.AbstractJDBC;
-
-
-/**
- * This base class holds most of the unimplemented feature of a {@code Connection}.
- * This is used in order to avoid having a Connection implementation of thousand lines and unreadable.
- *
- * <table class="sis">
- *   <caption>Connection default values</caption>
- *   <tr><th>Property</th>                           <th>Value</th></tr>
- *   <tr><td>{@link #isReadOnly()}</td>              <td>{@code false}</td></tr>
- *   <tr><td>{@link #getAutoCommit()}</td>           <td>{@code true}</td></tr>
- *   <tr><td>{@link #getNetworkTimeout()}</td>       <td>0</td></tr>
- *   <tr><td>{@link #getTransactionIsolation()}</td> <td>{@link #TRANSACTION_NONE}</td></tr>
- *   <tr><td>{@link #getTypeMap()}</td>              <td>Empty map</td></tr>
- *   <tr><td>{@link #nativeSQL(String)}</td>         <td>No change</td></tr>
- *   <tr><td>{@link #getWarnings()}</td>             <td>{@code null}</td></tr>
- *   <tr><td>{@link #clearWarnings()}</td>           <td>Ignored</td></tr>
- * </table>
- *
- * @author  Marc Le Bihan
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
- * @since   0.5
- * @module
- */
-@SuppressWarnings("unused")
-abstract class AbstractConnection extends AbstractJDBC implements Connection {
-    /**
-     * Constructs a new {@code Connection} instance.
-     */
-    AbstractConnection() {
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setCatalog(String catalog) {
-        logUnsupportedOperation("setCatalog");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public String getSchema() throws SQLException {
-        throw unsupportedOperation("getSchema");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setSchema(String schema) throws SQLException {
-        throw unsupportedOperation("setSchema");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Map<String, Class<?>> getTypeMap() {
-        return Collections.emptyMap();
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setTypeMap(Map<String, Class<?>> map) {
-        if (!map.isEmpty()) {
-            throw new UnsupportedOperationException("setTypeMap");
-        }
-    }
-
-    /**
-     * Returns {@code true} by default, assuming a driver without write capabilities.
-     */
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setReadOnly(boolean readOnly) {
-        if (!readOnly) {
-            throw new UnsupportedOperationException("setReadOnly");
-        }
-    }
-
-    /**
-     * Defaults to {@link #TRANSACTION_NONE}.
-     */
-    @Override
-    public int getTransactionIsolation() {
-        return TRANSACTION_NONE; // No guarantees of anything.
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setTransactionIsolation(int level) {
-        if (level != TRANSACTION_NONE) {
-            throw new UnsupportedOperationException("setTransactionIsolation");
-        }
-    }
-
-    /**
-     * Defaults to {@code true}, assuming that auto-commit state is not handled.
-     */
-    @Override
-    public boolean getAutoCommit() {
-        return true;
-    }
-
-    /**
-     * Defaults to ignoring the commit / rollback.
-     * The auto-commit mode is assumed fixed to {@code true}.
-     */
-    @Override
-    public void setAutoCommit(boolean autoCommit) {
-        log(Level.FINE, "log.auto_commit_ignored", autoCommit);
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void commit() {
-        log(Level.FINE, "log.commit_rollback_ignored");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void rollback() {
-        log(Level.FINE, "log.commit_rollback_ignored");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void rollback(Savepoint savepoint) throws SQLException {
-        throw unsupportedOperation("rollback");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Savepoint setSavepoint() throws SQLException {
-        throw unsupportedOperation("setSavepoint");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Savepoint setSavepoint(String name) throws SQLException {
-        throw unsupportedOperation("setSavepoint");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-        throw unsupportedOperation("releaseSavepoint");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public int getHoldability() throws SQLException {
-        throw unsupportedOperation("getHoldability");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setHoldability(int holdability) {
-        logUnsupportedOperation("setHoldability");
-    }
-
-    /**
-     * Returns the given string unchanged by default.
-     */
-    @Override
-    public String nativeSQL(String sql) {
-        return sql; // We do nothing at the moment.
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
-        throw unsupportedOperation("createStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        throw unsupportedOperation("createStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql) throws SQLException {
-        throw unsupportedOperation("prepareStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        throw unsupportedOperation("prepareStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        throw unsupportedOperation("prepareStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        throw unsupportedOperation("prepareCall");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-        throw unsupportedOperation("prepareStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
-        throw unsupportedOperation("prepareStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
-        throw unsupportedOperation("prepareStatement");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public CallableStatement prepareCall(String sql) throws SQLException {
-        throw unsupportedOperation("prepareCall");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        throw unsupportedOperation("prepareCall");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Clob createClob() throws SQLException {
-        throw unsupportedOperation("createClob");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Blob createBlob() throws SQLException {
-        throw unsupportedOperation("createBlob");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public NClob createNClob() throws SQLException {
-        throw unsupportedOperation("createNClob");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public SQLXML createSQLXML() throws SQLException {
-        throw unsupportedOperation("createSQLXML");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
-        throw unsupportedOperation("createArrayOf");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
-        throw unsupportedOperation("createStruct");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public String getClientInfo(String name) throws SQLException {
-        throw unsupportedOperation("getClientInfo");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public Properties getClientInfo() throws SQLException {
-        throw unsupportedOperation("getClientInfo");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setClientInfo(String name, String value) {
-        logUnsupportedOperation("setClientInfo");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setClientInfo(Properties properties) {
-        logUnsupportedOperation("setClientInfo");
-    }
-
-    /**
-     * Defaults to 0, which means there is no limit.
-     */
-    @Override
-    public int getNetworkTimeout() {
-        return 0; // Means there is no limt.
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void setNetworkTimeout(Executor executor, int milliseconds) {
-        logUnsupportedOperation("setNetworkTimeout");
-    }
-
-    /**
-     * Unsupported by default.
-     */
-    @Override
-    public void abort(Executor executor) throws SQLException {
-        throw unsupportedOperation("abort");
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/DBFConnection.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/DBFConnection.java
deleted file mode 100644
index 6e7528c..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/DBFConnection.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc.connection;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.sql.*;
-import java.util.*;
-import java.util.logging.Level;
-
-import org.apache.sis.internal.shapefile.jdbc.*;
-import org.apache.sis.internal.shapefile.jdbc.metadata.DBFDatabaseMetaData;
-import org.apache.sis.internal.shapefile.jdbc.resultset.*;
-import org.apache.sis.internal.shapefile.jdbc.statement.DBFStatement;
-
-
-/**
- * Connection to a DBF database.
- * @author  Marc Le Bihan
- * @version 0.5
- * @since   0.5
- * @module
- */
-public class DBFConnection extends AbstractConnection {
-    /** The object to use for reading the database content. */
-    final File databaseFile;
-
-    /** Opened statement. */
-    private HashSet<DBFStatement> openedStatements = new HashSet<>();
-
-    /** ByteReader. */
-    private Dbase3ByteReader byteReader;
-
-    /**
-     * Constructs a connection to the given database.
-     * @param datafile Data file ({@code .dbf} extension).
-     * @param br Byte reader to use for reading binary content.
-     * @throws SQLDbaseFileNotFoundException if the Database file cannot be found or is not a file.
-     */
-    public DBFConnection(final File datafile, Dbase3ByteReader br) throws SQLDbaseFileNotFoundException {
-        // Check that file exists.
-        if (!datafile.exists()) {
-            throw new SQLDbaseFileNotFoundException(format(Level.WARNING, "excp.file_not_found", datafile.getAbsolutePath()));
-        }
-
-        // Check that its not a directory.
-        if (datafile.isDirectory()) {
-            throw new SQLDbaseFileNotFoundException(format(Level.WARNING, "excp.directory_not_expected", datafile.getAbsolutePath()));
-        }
-
-        this.databaseFile = datafile;
-        this.byteReader = br;
-        log(Level.FINE, "log.database_connection_opened", this.databaseFile.getAbsolutePath(), "FIXME : column desc.");
-    }
-
-    /**
-     * Closes the connection to the database.
-     */
-    @Override
-    public void close() {
-        if (isClosed())
-            return;
-
-        try {
-            // Check if all the underlying connections that has been opened with this connection has been closed.
-            // If not, we log a warning to help the developper.
-            if (this.openedStatements.size() > 0) {
-                log(Level.WARNING, "log.statements_left_opened", this.openedStatements.size(), openedStatements.toString());
-            }
-
-            this.byteReader.close();
-        } catch (IOException e) {
-            log(Level.FINE, e.getMessage(), e);
-        }
-    }
-
-    /**
-     * Creates an object for sending SQL statements to the database.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override
-    public Statement createStatement() throws SQLConnectionClosedException {
-        assertNotClosed();
-
-        DBFStatement stmt = new DBFStatement(this);
-        this.openedStatements.add(stmt);
-        return stmt;
-    }
-
-    /**
-     * @see java.sql.Connection#getCatalog()
-     */
-    @Override
-    public String getCatalog() {
-        return null; // DBase 3 offers no catalog.
-    }
-
-    /**
-     * Returns the charset.
-     * @return Charset.
-     */
-    public Charset getCharset() {
-        return this.byteReader.getCharset();
-    }
-
-    /**
-     * Returns the database File.
-     * @return File.
-     */
-    @Override
-    public File getFile() {
-        return this.databaseFile;
-    }
-
-    /**
-     * Returns the JDBC interface implemented by this class.
-     * This is used for formatting error messages.
-     */
-    @Override
-    final protected Class<?> getInterface() {
-        return Connection.class;
-    }
-
-    /**
-     * @see java.sql.Connection#getMetaData()
-     */
-    @Override
-    public DatabaseMetaData getMetaData() {
-        return new DBFDatabaseMetaData(this);
-    }
-
-    /**
-     * Returns {@code true} if this connection has been closed.
-     */
-    @Override
-    public boolean isClosed() {
-        return this.byteReader.isClosed();
-    }
-
-    /**
-     * Returns {@code true} if the connection has not been closed and is still valid.
-     * The timeout parameter is ignored and this method bases itself only on {@link #isClosed()} state.
-     */
-    @Override
-    public boolean isValid(@SuppressWarnings("unused") int timeout) {
-        return !isClosed();
-    }
-
-    /**
-     * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
-     */
-    @Override
-    public boolean isWrapperFor(Class<?> iface) {
-        return iface.isAssignableFrom(getInterface());
-    }
-
-    /**
-     * Asserts that the connection is opened.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    public void assertNotClosed() throws SQLConnectionClosedException {
-        // If closed throw an exception specifying the name if the DBF that is closed.
-        if (isClosed()) {
-            throw new SQLConnectionClosedException(format(Level.WARNING, "excp.closed_connection", getFile().getName()), null, getFile());
-        }
-    }
-
-    /**
-     * Method called by Statement class to notity this connection that a statement has been closed.
-     * @param stmt Statement that has been closed.
-     */
-    public void notifyCloseStatement(DBFStatement stmt) {
-        Objects.requireNonNull(stmt, "The statement notified being closed cannot be null.");
-
-        if (this.openedStatements.remove(stmt) == false) {
-            throw new RuntimeException(format(Level.SEVERE, "assert.statement_not_opened_by_me", stmt, toString()));
-        }
-    }
-
-    /**
-     * Returns the column index for the given column name.
-     * The default implementation of all methods expecting a column label will invoke this method.
-     * @param columnLabel The name of the column.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return The index of the given column name : first column is 1.
-     * @throws SQLNoSuchFieldException if there is no field with this name in the query.
-     */
-    public int findColumn(String columnLabel, String sql) throws SQLNoSuchFieldException {
-        return this.byteReader.findColumn(columnLabel, sql);
-    }
-
-    /**
-     * Returns the column count of the table of the database.
-     * @return Column count.
-     */
-    public int getColumnCount() {
-        return this.byteReader.getColumnCount();
-    }
-
-    /**
-     * Get a field description.
-     * @param columnLabel Column label.
-     * @param sql SQL Statement.
-     * @return ResultSet with current row set on the wished field.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     * @throws SQLNoSuchFieldException if no column with that name exists.
-     */
-    public ResultSet getFieldDesc(String columnLabel, String sql) throws SQLConnectionClosedException, SQLNoSuchFieldException {
-        Objects.requireNonNull(columnLabel, "The column name cannot be null.");
-
-        DBFBuiltInMemoryResultSetForColumnsListing rs = (DBFBuiltInMemoryResultSetForColumnsListing)((DBFDatabaseMetaData)getMetaData()).getColumns(null, null, null, null);
-
-        try {
-            while(rs.next()) {
-                try {
-                    if (rs.getString("COLUMN_NAME").equalsIgnoreCase(columnLabel)) {
-                        return rs;
-                    }
-                }
-                catch(SQLNoSuchFieldException e) {
-                    // if it is the COLUMN_NAME column that has not been found in the desc ResultSet, we have an internal error.
-                    rs.close();
-                    throw new RuntimeException(e.getMessage(), e);
-                }
-            }
-        }
-        catch(SQLNoResultException e) {
-            // if we run out of bound of the ResultSet, the boolean returned by next() has not been checked well, and it's an internal error.
-            rs.close();
-            throw new RuntimeException(e.getMessage(), e);
-        }
-
-        // But if we are here, we have not found the column with this name, and we have to throw an SQLNoSuchFieldException exception ourselves.
-        String message = format("excp.no_such_column_in_resultset", columnLabel, sql, getFile().getName());
-        throw new SQLNoSuchFieldException(message, sql, getFile(), columnLabel);
-    }
-
-    /**
-     * Get a field description.
-     * @param column Column index.
-     * @param sql SQL Statement.
-     * @return ResultSet with current row set on the wished field.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     * @throws SQLIllegalColumnIndexException if the column index is out of bounds.
-     */
-    public ResultSet getFieldDesc(int column, String sql) throws SQLConnectionClosedException, SQLIllegalColumnIndexException {
-        DBFBuiltInMemoryResultSetForColumnsListing rs = (DBFBuiltInMemoryResultSetForColumnsListing)((DBFDatabaseMetaData)getMetaData()).getColumns(null, null, null, null);
-
-        if (column <= 0 || column > getColumnCount()) {
-            rs.close();
-            String message = format("excp.illegal_column_index_metadata", column, getColumnCount());
-            throw new SQLIllegalColumnIndexException(message, sql, getFile(), column);
-        }
-
-        // TODO Implements ResultSet:absolute(int) instead.
-        for(int index=1; index <= column; index ++) {
-            try {
-                rs.next();
-            }
-            catch(SQLNoResultException e) {
-                // We encounter an internal API error in this case.
-                rs.close();
-                throw new RuntimeException(e.getMessage(), e);
-            }
-        }
-
-        return rs;
-    }
-
-    /**
-     * Returns the fields descriptors in their binary format.
-     * @return Fields descriptors.
-     */
-    public List<DBase3FieldDescriptor> getFieldsDescriptors() {
-        return this.byteReader.getFieldsDescriptors();
-    }
-
-    /**
-     * Return a field name.
-     * @param columnIndex Column index.
-     * @param sql For information, the SQL statement that is attempted.
-     * @return Field Name.
-     * @throws SQLIllegalColumnIndexException if the index is out of bounds.
-     */
-    public String getFieldName(int columnIndex, String sql) throws SQLIllegalColumnIndexException {
-        return this.byteReader.getFieldName(columnIndex, sql);
-    }
-
-    /**
-     * Checks if a next row is available. Warning : it may be a deleted one.
-     * @return true if a next row is available.
-     */
-    public boolean nextRowAvailable() {
-        return this.byteReader.nextRowAvailable();
-    }
-
-    /**
-     * Read the next row as a set of objects.
-     * @return Map of field name / object value, or null if EoF has been encountered.
-     */
-    public Map<String, byte[]> readNextRowAsObjects() {
-        return this.byteReader.readNextRowAsObjects();
-    }
-
-    /**
-     * Returns the record number of the last record red.
-     * @return The record number.
-     */
-    public int getRowNum() {
-        return this.byteReader.getRowNum();
-    }
-
-    /**
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return format("toString", this.databaseFile.getAbsolutePath(), isClosed() == false);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/SQLClosingIOFailureException.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/SQLClosingIOFailureException.java
deleted file mode 100644
index e20e58c..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/SQLClosingIOFailureException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc.connection;
-
-import java.io.File;
-import java.sql.SQLException;
-
-/**
- * Exception thrown when a connection cannot be closed due to an environement trouble.
- * @author Marc LE BIHAN
- */
-public class SQLClosingIOFailureException extends SQLException {
-    /** Serial ID. */
-    private static final long serialVersionUID = -3327372119927661463L;
-
-    /** The SQL Statement that whas attempted (if known). */
-    private String sql;
-
-    /** The database file. */
-    private File database;
-
-    /**
-     * Build the exception.
-     * @param message Exception message.
-     * @param sqlStatement SQL Statement who encountered the trouble, if known.
-     * @param dbf The database that was queried.
-     */
-    public SQLClosingIOFailureException(String message, String sqlStatement, File dbf) {
-        super(message);
-        this.sql = sqlStatement;
-        this.database = dbf;
-    }
-
-    /**
-     * Returns the SQL statement who encountered the "connection closed" alert, if known.
-     * @return SQL statement or null.
-     */
-    public String getSQL() {
-        return this.sql;
-    }
-
-    /**
-     * Returns the database file that is not opened for connection.
-     * @return Database file.
-     */
-    public File getDatabase() {
-        return this.database;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/package-info.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/package-info.java
deleted file mode 100644
index e10322c..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/connection/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.
- */
-
-/** Connections */
-package org.apache.sis.internal.shapefile.jdbc.connection;
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/AbstractDatabaseMetaData.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/AbstractDatabaseMetaData.java
deleted file mode 100644
index 91d0f0d..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/AbstractDatabaseMetaData.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc.metadata;
-
-import java.sql.*;
-
-import org.apache.sis.internal.shapefile.jdbc.AbstractJDBC;
-
-/**
- * Unimplemented methods of DatabaseMetaData.
- * @author Marc LE BIHAN
- */
-public abstract class AbstractDatabaseMetaData extends AbstractJDBC implements DatabaseMetaData {
-    /**
-     * @see java.sql.DatabaseMetaData#getAttributes(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException {
-        throw unsupportedOperation("getAttributes", catalog, schemaPattern, typeNamePattern, attributeNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getBestRowIdentifier(java.lang.String, java.lang.String, java.lang.String, int, boolean)
-     */
-    @Override public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException {
-        throw unsupportedOperation("getBestRowIdentifier", catalog, schema, table, scope, nullable);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getClientInfoProperties()
-     */
-    @Override public ResultSet getClientInfoProperties() throws SQLException {
-        throw unsupportedOperation("getClientInfoProperties");
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getColumnPrivileges(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException {
-        throw unsupportedOperation("getColumnPrivileges", catalog, schema, table, columnNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {
-        throw unsupportedOperation("getCrossReference", parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
-        throw unsupportedOperation("getExportedKeys", catalog, schema, table);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getFunctions(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
-        throw unsupportedOperation("getFunctions", catalog, schemaPattern, functionNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getFunctionColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException {
-        throw unsupportedOperation("getFunctionColumns", catalog, schemaPattern, functionNamePattern, columnNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getIndexInfo(java.lang.String, java.lang.String, java.lang.String, boolean, boolean)
-     */
-    @Override public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException {
-        throw unsupportedOperation("getIndexInfo", catalog, schema, table, unique, approximate);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getImportedKeys(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
-        throw unsupportedOperation("getImportedKeys", catalog, schema, table);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
-        throw unsupportedOperation("getPrimaryKeys", catalog, schema, table);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getProcedures(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
-        throw unsupportedOperation("getProcedures", catalog, schemaPattern, procedureNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getProcedureColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException{
-        throw unsupportedOperation("getProcedureColumns", catalog, schemaPattern, procedureNamePattern, columnNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getPseudoColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
-        throw unsupportedOperation("getPseudoColumns", catalog, schemaPattern, tableNamePattern, columnNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getRowIdLifetime()
-     */
-    @Override public RowIdLifetime getRowIdLifetime() throws SQLException {
-        throw unsupportedOperation("getRowIdLifetime");
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSchemas(java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
-        throw unsupportedOperation("getSchemas", catalog, schemaPattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSearchStringEscape()
-     */
-    @Override public String getSearchStringEscape() throws SQLException {
-        throw unsupportedOperation("getSearchStringEscape");
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSQLStateType()
-     */
-    @Override public int getSQLStateType() throws SQLException {
-        throw unsupportedOperation("getSQLStateType");
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSuperTypes(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
-        throw unsupportedOperation("getSuperTypes", catalog, schemaPattern, typeNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSuperTables(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
-        throw unsupportedOperation("getSuperTables", catalog, schemaPattern, tableNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getTablePrivileges(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
-        throw unsupportedOperation("getTablePrivileges", catalog, schemaPattern, tableNamePattern);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getTypeInfo()
-     */
-    @Override public ResultSet getTypeInfo() throws SQLException {
-        throw unsupportedOperation("getTypeInfo");
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getUDTs(java.lang.String, java.lang.String, java.lang.String, int[])
-     */
-    @Override public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {
-        throw unsupportedOperation("getUDTs", catalog, schemaPattern, typeNamePattern, types);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getVersionColumns(java.lang.String, java.lang.String, java.lang.String)
-     */
-    @Override public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
-        throw unsupportedOperation("getVersionColumns", catalog, schema, table);
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#unwrap(java.lang.Class)
-     */
-    @Override public <T> T unwrap(Class<T> iface) throws SQLFeatureNotSupportedException {
-        throw unsupportedOperation("unwrap", iface);
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/DBFDatabaseMetaData.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/DBFDatabaseMetaData.java
deleted file mode 100644
index 931ed87..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/DBFDatabaseMetaData.java
+++ /dev/null
@@ -1,1300 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc.metadata;
-
-import java.io.File;
-import java.sql.*;
-import java.util.Arrays;
-import java.util.Objects;
-
-import org.apache.sis.internal.shapefile.jdbc.SQLConnectionClosedException;
-import org.apache.sis.internal.shapefile.jdbc.connection.DBFConnection;
-import org.apache.sis.internal.shapefile.jdbc.resultset.*;
-import org.apache.sis.internal.shapefile.jdbc.statement.DBFStatement;
-
-/**
- * Database Metadata.
- * @author Marc LE BIHAN
- */
-public class DBFDatabaseMetaData extends AbstractDatabaseMetaData {
-    /** Connection. */
-    private DBFConnection connection;
-
-    /**
-     * Construct a database Metadata.
-     * @param cnt Connection.
-     */
-    public DBFDatabaseMetaData(DBFConnection cnt) {
-        Objects.requireNonNull(cnt, "The database connection used to create Database metadata cannot be null.");
-        this.connection = cnt;
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#isWrapperFor(java.lang.Class)
-     */
-    @Override public boolean isWrapperFor(Class<?> iface) {
-        logStep("isWrapperFor", iface);
-        return getInterface().isAssignableFrom(iface);
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#allProceduresAreCallable()
-     */
-    @Override public boolean allProceduresAreCallable() {
-        logStep("allProceduresAreCallable");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#allTablesAreSelectable()
-     */
-    @Override public boolean allTablesAreSelectable() {
-        logStep("allTablesAreSelectable");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override
-    public ResultSet getColumns(@SuppressWarnings("unused") String catalog, @SuppressWarnings("unused") String schemaPattern, @SuppressWarnings("unused") String tableNamePattern, @SuppressWarnings("unused") String columnNamePattern) throws SQLConnectionClosedException {
-        try(DBFStatement stmt = (DBFStatement)this.connection.createStatement()) {
-            return new DBFBuiltInMemoryResultSetForColumnsListing(stmt, this.connection.getFieldsDescriptors());
-        }
-    }
-
-    /**
-     * Returns the Database File.
-     * @return Database File.
-     */
-    @Override
-    public File getFile() {
-        return this.connection.getFile();
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getURL()
-     */
-    @Override public String getURL() {
-        logStep("getURL");
-        return getFile().getAbsolutePath();
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getUserName()
-     */
-    @Override public String getUserName() {
-        logStep("getUserName");
-        return null;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#isReadOnly()
-     */
-    @Override public boolean isReadOnly() {
-        logStep("isReadOnly");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#nullsAreSortedHigh()
-     */
-    @Override public boolean nullsAreSortedHigh() {
-        logStep("nullsAreSortedHigh");
-        return false; // TODO : Check in documentation about this.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#nullsAreSortedLow()
-     */
-    @Override public boolean nullsAreSortedLow() {
-        logStep("nullsAreSortedLow");
-        return false; // TODO : Check in documentation about this.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#nullsAreSortedAtStart()
-     */
-    @Override public boolean nullsAreSortedAtStart() {
-        logStep("nullsAreSortedAtStart");
-        return false; // TODO : Check in documentation about this.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#nullsAreSortedAtEnd()
-     */
-    @Override public boolean nullsAreSortedAtEnd() {
-        logStep("nullsAreSortedAtEnd");
-        return false; // TODO : Check in documentation about this.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDatabaseProductName()
-     */
-    @Override public String getDatabaseProductName() {
-        logStep("getDatabaseProductName");
-        return "DBase 3";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDatabaseProductVersion()
-     */
-    @Override public String getDatabaseProductVersion() {
-        logStep("getDatabaseProductVersion");
-        return "3";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDriverName()
-     */
-    @Override public String getDriverName() {
-        logStep("getDriverName");
-        return "Apache SIS DBase 3 JDBC driver";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDriverVersion()
-     */
-    @Override public String getDriverVersion() {
-        logStep("getDriverVersion");
-        return "1.0";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDriverMajorVersion()
-     */
-    @Override public int getDriverMajorVersion() {
-        logStep("getDriverMajorVersion");
-        return 1;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDriverMinorVersion()
-     */
-    @Override public int getDriverMinorVersion() {
-        logStep("getDriverMinorVersion");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#usesLocalFiles()
-     */
-    @Override public boolean usesLocalFiles() {
-        logStep("usesLocalFiles");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#usesLocalFilePerTable()
-     */
-    @Override public boolean usesLocalFilePerTable() {
-        logStep("usesLocalFilePerTable");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsMixedCaseIdentifiers()
-     */
-    @Override public boolean supportsMixedCaseIdentifiers() {
-        logStep("supportsMixedCaseIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#storesUpperCaseIdentifiers()
-     */
-    @Override public boolean storesUpperCaseIdentifiers() {
-        logStep("storesUpperCaseIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#storesLowerCaseIdentifiers()
-     */
-    @Override public boolean storesLowerCaseIdentifiers() {
-        logStep("storesLowerCaseIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#storesMixedCaseIdentifiers()
-     */
-    @Override public boolean storesMixedCaseIdentifiers() {
-        logStep("storesMixedCaseIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsMixedCaseQuotedIdentifiers()
-     */
-    @Override public boolean supportsMixedCaseQuotedIdentifiers() {
-        logStep("supportsMixedCaseQuotedIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#storesUpperCaseQuotedIdentifiers()
-     */
-    @Override public boolean storesUpperCaseQuotedIdentifiers() {
-        logStep("storesUpperCaseQuotedIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#storesLowerCaseQuotedIdentifiers()
-     */
-    @Override public boolean storesLowerCaseQuotedIdentifiers() {
-        logStep("storesLowerCaseQuotedIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#storesMixedCaseQuotedIdentifiers()
-     */
-    @Override public boolean storesMixedCaseQuotedIdentifiers() {
-        logStep("storesMixedCaseQuotedIdentifiers");
-        return true;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getIdentifierQuoteString()
-     */
-    @Override public String getIdentifierQuoteString() {
-        logStep("getIdentifierQuoteString");
-        return " ";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSQLKeywords()
-     */
-    @Override public String getSQLKeywords() {
-        logStep("getSQLKeywords");
-        return ""; // We don't have special Keywords yet.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getNumericFunctions()
-     */
-    @Override public String getNumericFunctions() {
-        logStep("getNumericFunctions");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getStringFunctions()
-     */
-    @Override public String getStringFunctions() {
-        logStep("getStringFunctions");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSystemFunctions()
-     */
-    @Override public String getSystemFunctions() {
-        logStep("getSystemFunctions");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getTimeDateFunctions()
-     */
-    @Override public String getTimeDateFunctions() {
-        logStep("getTimeDateFunctions");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getExtraNameCharacters()
-     */
-    @Override public String getExtraNameCharacters() {
-        logStep("getExtraNameCharacters");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsAlterTableWithAddColumn()
-     */
-    @Override public boolean supportsAlterTableWithAddColumn() {
-        logStep("supportsAlterTableWithAddColumn");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsAlterTableWithDropColumn()
-     */
-    @Override public boolean supportsAlterTableWithDropColumn() {
-        logStep("supportsAlterTableWithDropColumn");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsColumnAliasing()
-     */
-    @Override public boolean supportsColumnAliasing() {
-        logStep("supportsColumnAliasing");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#nullPlusNonNullIsNull()
-     */
-    @Override public boolean nullPlusNonNullIsNull() {
-        logStep("nullPlusNonNullIsNull");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsConvert()
-     */
-    @Override public boolean supportsConvert() {
-        logStep("supportsConvert");
-        return false; // We can promote internally types, but not offer the keyword.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsConvert(int, int)
-     */
-    @Override public boolean supportsConvert(int fromType, int toType) {
-        logStep("supportsConvert", fromType, toType);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsTableCorrelationNames()
-     */
-    @Override public boolean supportsTableCorrelationNames() {
-        logStep("supportsTableCorrelationNames");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsDifferentTableCorrelationNames()
-     */
-    @Override public boolean supportsDifferentTableCorrelationNames() {
-        logStep("supportsDifferentTableCorrelationNames");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsExpressionsInOrderBy()
-     */
-    @Override public boolean supportsExpressionsInOrderBy() {
-        logStep("supportsExpressionsInOrderBy");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsOrderByUnrelated()
-     */
-    @Override public boolean supportsOrderByUnrelated() {
-        logStep("supportsOrderByUnrelated");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsGroupBy()
-     */
-    @Override public boolean supportsGroupBy() {
-        logStep("supportsGroupBy");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsGroupByUnrelated()
-     */
-    @Override public boolean supportsGroupByUnrelated() {
-        logStep("supportsGroupByUnrelated");
-        return false;
-    }
-    /**
-     * @see java.sql.DatabaseMetaData#supportsGroupByBeyondSelect()
-     */
-    @Override public boolean supportsGroupByBeyondSelect() {
-        logStep("supportsGroupByBeyondSelect");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsLikeEscapeClause()
-     */
-    @Override public boolean supportsLikeEscapeClause() {
-        logStep("supportsLikeEscapeClause");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsMultipleResultSets()
-     */
-    @Override public boolean supportsMultipleResultSets() {
-        logStep("supportsMultipleResultSets");
-        return false; // Even if the code allow creating multiple ResultSet from a statement.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsMultipleTransactions()
-     */
-    @Override public boolean supportsMultipleTransactions() {
-        logStep("supportsMultipleTransactions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsNonNullableColumns()
-     */
-    @Override public boolean supportsNonNullableColumns() {
-        logStep("supportsNonNullableColumns");
-        return false; // TODO Check in documentation.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsMinimumSQLGrammar()
-     */
-    @Override public boolean supportsMinimumSQLGrammar() {
-        logStep("supportsMinimumSQLGrammar");
-        return false; // Check what is the ODBC SQL minimum grammar.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCoreSQLGrammar()
-     */
-    @Override public boolean supportsCoreSQLGrammar() {
-        logStep("supportsCoreSQLGrammar");
-        return false; // Check what is the core SQL grammar.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsExtendedSQLGrammar()
-     */
-    @Override public boolean supportsExtendedSQLGrammar() {
-        logStep("supportsExtendedSQLGrammar");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsANSI92EntryLevelSQL()
-     */
-    @Override public boolean supportsANSI92EntryLevelSQL() {
-        logStep("supportsANSI92EntryLevelSQL");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsANSI92IntermediateSQL()
-     */
-    @Override public boolean supportsANSI92IntermediateSQL() {
-        logStep("supportsANSI92IntermediateSQL");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsANSI92FullSQL()
-     */
-    @Override public boolean supportsANSI92FullSQL() {
-        logStep("supportsANSI92FullSQL");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsIntegrityEnhancementFacility()
-     */
-    @Override public boolean supportsIntegrityEnhancementFacility() {
-        logStep("supportsIntegrityEnhancementFacility");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsOuterJoins()
-     */
-    @Override public boolean supportsOuterJoins() {
-        logStep("supportsOuterJoins");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsFullOuterJoins()
-     */
-    @Override public boolean supportsFullOuterJoins() {
-        logStep("supportsFullOuterJoins");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsLimitedOuterJoins()
-     */
-    @Override public boolean supportsLimitedOuterJoins() {
-        logStep("supportsLimitedOuterJoins");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSchemaTerm()
-     */
-    @Override public String getSchemaTerm() {
-        logStep("getSchemaTerm");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getProcedureTerm()
-     */
-    @Override public String getProcedureTerm() {
-        logStep("getProcedureTerm");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getCatalogTerm()
-     */
-    @Override public String getCatalogTerm() {
-        logStep("getCatalogTerm");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#isCatalogAtStart()
-     */
-    @Override public boolean isCatalogAtStart() {
-        logStep("isCatalogAtStart");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getCatalogSeparator()
-     */
-    @Override public String getCatalogSeparator() {
-        logStep("getCatalogSeparator");
-        return "";
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSchemasInDataManipulation()
-     */
-    @Override public boolean supportsSchemasInDataManipulation() {
-        logStep("supportsSchemasInDataManipulation");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSchemasInProcedureCalls()
-     */
-    @Override public boolean supportsSchemasInProcedureCalls() {
-        logStep("supportsSchemasInProcedureCalls");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSchemasInTableDefinitions()
-     */
-    @Override public boolean supportsSchemasInTableDefinitions() {
-        logStep("supportsSchemasInTableDefinitions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSchemasInIndexDefinitions()
-     */
-    @Override public boolean supportsSchemasInIndexDefinitions() {
-        logStep("supportsSchemasInIndexDefinitions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSchemasInPrivilegeDefinitions()
-     */
-    @Override public boolean supportsSchemasInPrivilegeDefinitions() {
-        logStep("supportsSchemasInPrivilegeDefinitions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCatalogsInDataManipulation()
-     */
-    @Override public boolean supportsCatalogsInDataManipulation() {
-        logStep("supportsCatalogsInDataManipulation");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCatalogsInProcedureCalls()
-     */
-    @Override public boolean supportsCatalogsInProcedureCalls() {
-        logStep("supportsCatalogsInProcedureCalls");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCatalogsInTableDefinitions()
-     */
-    @Override public boolean supportsCatalogsInTableDefinitions() {
-        logStep("supportsCatalogsInTableDefinitions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCatalogsInIndexDefinitions()
-     */
-    @Override public boolean supportsCatalogsInIndexDefinitions() {
-        logStep("supportsCatalogsInIndexDefinitions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCatalogsInPrivilegeDefinitions()
-     */
-    @Override public boolean supportsCatalogsInPrivilegeDefinitions() {
-        logStep("supportsCatalogsInPrivilegeDefinitions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsPositionedDelete()
-     */
-    @Override public boolean supportsPositionedDelete() {
-        logStep("supportsPositionedDelete");
-        return false; // TODO not yet, but might later.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsPositionedUpdate()
-     */
-    @Override public boolean supportsPositionedUpdate() {
-        logStep("supportsPositionedUpdate");
-        return false; // TODO not yet, but might later.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSelectForUpdate()
-     */
-    @Override public boolean supportsSelectForUpdate() {
-        logStep("supportsSelectForUpdate");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsStoredProcedures()
-     */
-    @Override public boolean supportsStoredProcedures() {
-        logStep("supportsStoredProcedures");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSubqueriesInComparisons()
-     */
-    @Override public boolean supportsSubqueriesInComparisons() {
-        logStep("supportsStoredProcedures");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSubqueriesInExists()
-     */
-    @Override public boolean supportsSubqueriesInExists() {
-        logStep("supportsSubqueriesInExists");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSubqueriesInIns()
-     */
-    @Override public boolean supportsSubqueriesInIns() {
-        logStep("supportsSubqueriesInIns");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSubqueriesInQuantifieds()
-     */
-    @Override public boolean supportsSubqueriesInQuantifieds() {
-        logStep("supportsSubqueriesInQuantifieds");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsCorrelatedSubqueries()
-     */
-    @Override public boolean supportsCorrelatedSubqueries() {
-        logStep("supportsCorrelatedSubqueries");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsUnion()
-     */
-    @Override public boolean supportsUnion() {
-        logStep("supportsUnion");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsUnionAll()
-     */
-    @Override public boolean supportsUnionAll() {
-        logStep("supportsUnionAll");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsOpenCursorsAcrossCommit()
-     */
-    @Override public boolean supportsOpenCursorsAcrossCommit() {
-        logStep("supportsOpenCursorsAcrossCommit");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsOpenCursorsAcrossRollback()
-     */
-    @Override public boolean supportsOpenCursorsAcrossRollback() {
-        logStep("supportsOpenCursorsAcrossRollback");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsOpenStatementsAcrossCommit()
-     */
-    @Override public boolean supportsOpenStatementsAcrossCommit() {
-        logStep("supportsOpenStatementsAcrossCommit");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsOpenStatementsAcrossRollback()
-     */
-    @Override public boolean supportsOpenStatementsAcrossRollback() {
-        logStep("supportsOpenStatementsAcrossRollback");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxBinaryLiteralLength()
-     */
-    @Override public int getMaxBinaryLiteralLength() {
-        logStep("getMaxBinaryLiteralLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxCharLiteralLength()
-     */
-    @Override public int getMaxCharLiteralLength() {
-        logStep("getMaxCharLiteralLength");
-        return 254;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxColumnNameLength()
-     */
-    @Override public int getMaxColumnNameLength() {
-        logStep("getMaxColumnNameLength");
-        return 10;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxColumnsInGroupBy()
-     */
-    @Override public int getMaxColumnsInGroupBy() {
-        logStep("getMaxColumnsInGroupBy");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxColumnsInIndex()
-     */
-    @Override public int getMaxColumnsInIndex() {
-        logStep("getMaxColumnsInIndex");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxColumnsInOrderBy()
-     */
-    @Override public int getMaxColumnsInOrderBy() {
-        logStep("getMaxColumnsInOrderBy");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxColumnsInSelect()
-     */
-    @Override public int getMaxColumnsInSelect() {
-        logStep("getMaxColumnsInSelect");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxColumnsInTable()
-     */
-    @Override public int getMaxColumnsInTable() {
-        logStep("getMaxColumnsInTable");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxConnections()
-     */
-    @Override public int getMaxConnections() {
-        logStep("getMaxConnections");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxCursorNameLength()
-     */
-    @Override public int getMaxCursorNameLength() {
-        logStep("getMaxCursorNameLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxIndexLength()
-     */
-    @Override public int getMaxIndexLength() {
-        logStep("getMaxIndexLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxSchemaNameLength()
-     */
-    @Override public int getMaxSchemaNameLength() {
-        logStep("getMaxSchemaNameLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxProcedureNameLength()
-     */
-    @Override public int getMaxProcedureNameLength() {
-        logStep("getMaxProcedureNameLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxCatalogNameLength()
-     */
-    @Override public int getMaxCatalogNameLength() {
-        logStep("getMaxCatalogNameLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxRowSize()
-     */
-    @Override public int getMaxRowSize() {
-        logStep("getMaxRowSize");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#doesMaxRowSizeIncludeBlobs()
-     */
-    @Override public boolean doesMaxRowSizeIncludeBlobs() {
-        logStep("doesMaxRowSizeIncludeBlobs");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxStatementLength()
-     */
-    @Override public int getMaxStatementLength() {
-        logStep("getMaxStatementLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxStatements()
-     */
-    @Override public int getMaxStatements() {
-        logStep("getMaxStatements");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxTableNameLength()
-     */
-    @Override public int getMaxTableNameLength() {
-        logStep("getMaxTableNameLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxTablesInSelect()
-     */
-    @Override public int getMaxTablesInSelect() {
-        logStep("getMaxTablesInSelect");
-        return 1; // We only handle one table at this time.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getMaxUserNameLength()
-     */
-    @Override public int getMaxUserNameLength() {
-        logStep("getMaxUserNameLength");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDefaultTransactionIsolation()
-     */
-    @Override public int getDefaultTransactionIsolation() {
-        logStep("getDefaultTransactionIsolation");
-        return 0; // No guaranties of anything.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsTransactions()
-     */
-    @Override public boolean supportsTransactions() {
-        logStep("supportsTransactions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel(int)
-     */
-    @Override public boolean supportsTransactionIsolationLevel(int level) {
-        logStep("supportsTransactionIsolationLevel", level);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsDataDefinitionAndDataManipulationTransactions()
-     */
-    @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() {
-        logStep("supportsDataDefinitionAndDataManipulationTransactions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsDataManipulationTransactionsOnly()
-     */
-    @Override public boolean supportsDataManipulationTransactionsOnly() {
-        logStep("supportsDataManipulationTransactionsOnly");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()
-     */
-    @Override public boolean dataDefinitionCausesTransactionCommit() {
-        logStep("dataDefinitionCausesTransactionCommit");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#dataDefinitionIgnoredInTransactions()
-     */
-    @Override public boolean dataDefinitionIgnoredInTransactions() {
-        logStep("dataDefinitionIgnoredInTransactions");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
-     */
-    @SuppressWarnings("resource") // The statement will be closed by the caller.
-    @Override public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) {
-        logStep("getTables", catalog, schemaPattern, tableNamePattern, types != null ? Arrays.asList(types) : null);
-
-        DBFStatement stmt = new DBFStatement(this.connection);
-        DBFBuiltInMemoryResultSetForTablesListing tables = new DBFBuiltInMemoryResultSetForTablesListing(stmt);
-        stmt.registerResultSet(tables);
-        return tables;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getSchemas()
-     */
-    @SuppressWarnings("resource") // The statement will be closed by the caller.
-    @Override public ResultSet getSchemas() {
-        logStep("getSchemas");
-
-        DBFStatement stmt = new DBFStatement(this.connection);
-        DBFBuiltInMemoryResultSetForSchemaListing schemas = new DBFBuiltInMemoryResultSetForSchemaListing(stmt);
-        stmt.registerResultSet(schemas);
-        return schemas;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getCatalogs()
-     */
-    @SuppressWarnings("resource") // The statement will be closed by the caller.
-    @Override public ResultSet getCatalogs() {
-        logStep("getCatalogs");
-
-        DBFStatement stmt = new DBFStatement(this.connection);
-        DBFBuiltInMemoryResultSetForCatalogNamesListing catalogNames = new DBFBuiltInMemoryResultSetForCatalogNamesListing(stmt);
-        stmt.registerResultSet(catalogNames);
-        return catalogNames;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getTableTypes()
-     */
-    @SuppressWarnings("resource") // The statement will be closed by the caller.
-    @Override public ResultSet getTableTypes() {
-        logStep("getTableTypes");
-
-        DBFStatement stmt = new DBFStatement(this.connection);
-        DBFBuiltInMemoryResultSetForTablesTypesListing tablesTypes = new DBFBuiltInMemoryResultSetForTablesTypesListing(stmt);
-        stmt.registerResultSet(tablesTypes);
-        return tablesTypes;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsResultSetType(int)
-     */
-    @Override public boolean supportsResultSetType(int type) {
-        logStep("supportsResultSetType", type);
-
-        switch(type) {
-            case ResultSet.FETCH_FORWARD:
-            case ResultSet.FETCH_UNKNOWN:
-            case ResultSet.TYPE_FORWARD_ONLY:
-            return true;
-
-            default :
-                return false;
-        }
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsResultSetConcurrency(int, int)
-     */
-    @Override public boolean supportsResultSetConcurrency(int type, int concurrency) {
-        logStep("supportsResultSetConcurrency", type, concurrency);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#ownUpdatesAreVisible(int)
-     */
-    @Override public boolean ownUpdatesAreVisible(int type) {
-        logStep("ownUpdatesAreVisible", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#ownDeletesAreVisible(int)
-     */
-    @Override public boolean ownDeletesAreVisible(int type) {
-        logStep("ownDeletesAreVisible", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#ownInsertsAreVisible(int)
-     */
-    @Override public boolean ownInsertsAreVisible(int type) {
-        logStep("ownInsertsAreVisible", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#othersUpdatesAreVisible(int)
-     */
-    @Override public boolean othersUpdatesAreVisible(int type) {
-        logStep("othersUpdatesAreVisible", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#othersDeletesAreVisible(int)
-     */
-    @Override public boolean othersDeletesAreVisible(int type) {
-        logStep("othersDeletesAreVisible", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#othersInsertsAreVisible(int)
-     */
-    @Override public boolean othersInsertsAreVisible(int type) {
-        logStep("othersInsertsAreVisible", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#updatesAreDetected(int)
-     */
-    @Override public boolean updatesAreDetected(int type) {
-        logStep("updatesAreDetected", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#deletesAreDetected(int)
-     */
-    @Override public boolean deletesAreDetected(int type) {
-        logStep("deletesAreDetected", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#insertsAreDetected(int)
-     */
-    @Override public boolean insertsAreDetected(int type) {
-        logStep("insertsAreDetected", type);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsBatchUpdates()
-     */
-    @Override public boolean supportsBatchUpdates() {
-        logStep("supportsBatchUpdates");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getConnection()
-     */
-    @Override public Connection getConnection() {
-        logStep("getConnection");
-        return this.connection;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsSavepoints()
-     */
-    @Override public boolean supportsSavepoints() {
-        logStep("supportsSavepoints");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsNamedParameters()
-     */
-    @Override public boolean supportsNamedParameters() {
-        logStep("supportsNamedParameters");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsMultipleOpenResults()
-     */
-    @Override public boolean supportsMultipleOpenResults() {
-        logStep("supportsMultipleOpenResults");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys()
-     */
-    @Override public boolean supportsGetGeneratedKeys() {
-        logStep("supportsGetGeneratedKeys");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsResultSetHoldability(int)
-     */
-    @Override public boolean supportsResultSetHoldability(int holdability) {
-        logStep("supportsResultSetHoldability", holdability);
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getResultSetHoldability()
-     */
-    @Override public int getResultSetHoldability() {
-        logStep("getResultSetHoldability");
-        return ResultSet.HOLD_CURSORS_OVER_COMMIT; // TODO : No matters, as we don't handle transactions.
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDatabaseMajorVersion()
-     */
-    @Override public int getDatabaseMajorVersion() {
-        logStep("getDatabaseMajorVersion");
-        return 3;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getDatabaseMinorVersion()
-     */
-    @Override public int getDatabaseMinorVersion() {
-        logStep("getDatabaseMinorVersion");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getJDBCMajorVersion()
-     */
-    @Override public int getJDBCMajorVersion() {
-        logStep("getJDBCMajorVersion");
-        return 1;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#getJDBCMinorVersion()
-     */
-    @Override public int getJDBCMinorVersion() {
-        logStep("getJDBCMinorVersion");
-        return 0;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
-     */
-    @Override public boolean locatorsUpdateCopy() {
-        logStep("locatorsUpdateCopy");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsStatementPooling()
-     */
-    @Override public boolean supportsStatementPooling() {
-        logStep("supportsStatementPooling");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#supportsStoredFunctionsUsingCallSyntax()
-     */
-    @Override public boolean supportsStoredFunctionsUsingCallSyntax() {
-        logStep("supportsStoredFunctionsUsingCallSyntax");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#autoCommitFailureClosesAllResultSets()
-     */
-    @Override public boolean autoCommitFailureClosesAllResultSets() {
-        logStep("autoCommitFailureClosesAllResultSets");
-        return false;
-    }
-
-    /**
-     * @see java.sql.DatabaseMetaData#generatedKeyAlwaysReturned()
-     */
-    @Override public boolean generatedKeyAlwaysReturned() {
-        logStep("generatedKeyAlwaysReturned");
-        return false;
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#getInterface()
-     */
-    @Override protected Class<?> getInterface() {
-        return DatabaseMetaData.class;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/DBFResultSetMataData.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/DBFResultSetMataData.java
deleted file mode 100644
index f3ae694..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/DBFResultSetMataData.java
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * 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.internal.shapefile.jdbc.metadata;
-
-import java.io.File;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.Objects;
-import java.util.logging.Level;
-
-import org.apache.sis.internal.shapefile.jdbc.AbstractJDBC;
-import org.apache.sis.internal.shapefile.jdbc.SQLConnectionClosedException;
-import org.apache.sis.internal.shapefile.jdbc.connection.DBFConnection;
-import org.apache.sis.internal.shapefile.jdbc.statement.DBFStatement;
-import org.apache.sis.internal.shapefile.jdbc.resultset.*;
-
-/**
- * ResultSet Metadata.
- * @author Marc LE BIHAN
- */
-public class DBFResultSetMataData extends AbstractJDBC implements ResultSetMetaData {
-    /** ResultSet. */
-    private DBFRecordBasedResultSet rs;
-
-    /** Database metadata. */
-    private DBFDatabaseMetaData metadata;
-
-    /**
-     * Construct a ResultSetMetaData.
-     * @param resultset ResultSet.
-     */
-    public DBFResultSetMataData(DBFRecordBasedResultSet resultset) {
-        Objects.requireNonNull(resultset, "A non null ResultSet is required.");
-        this.rs = resultset;
-
-        try {
-            this.metadata = (DBFDatabaseMetaData)resultset.getStatement().getConnection().getMetaData();
-        }
-        catch(SQLException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * @see java.sql.Wrapper#unwrap(java.lang.Class)
-     */
-    @Override public <T> T unwrap(Class<T> iface) throws SQLFeatureNotSupportedException {
-        throw unsupportedOperation("unwrap", iface);
-    }
-
-    /**
-     * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
-     */
-    @Override
-    public boolean isWrapperFor(Class<?> iface) {
-        logStep("isWrapperFor", iface);
-        return iface.isAssignableFrom(getInterface());
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnCount()
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @SuppressWarnings("resource") // The current connection is only used and has not to be closed.
-    @Override public int getColumnCount() throws SQLConnectionClosedException {
-        logStep("getColumnCount");
-        DBFConnection cnt = (DBFConnection)(((DBFStatement)this.rs.getStatement()).getConnection());
-
-        return cnt.getColumnCount();
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isAutoIncrement(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public boolean isAutoIncrement(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("isAutoIncrement", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getString("TYPE_NAME").equals("AUTO_INCREMENT");
-        }
-        catch(SQLNoSuchFieldException e) {
-            // We encounter an internal API error in this case.
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "TYPE_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isCaseSensitive(int)
-     */
-    @Override public boolean isCaseSensitive(int column) {
-        logStep("isCaseSensitive", column);
-        return true; // Yes, because behind, there's a HashMap.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isSearchable(int)
-     */
-    @Override public boolean isSearchable(int column) {
-        logStep("isSearchable", column);
-        return true; // All currently are searcheable.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isCurrency(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public boolean isCurrency(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("isCurrency", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getString("TYPE_NAME").equals("CURRENCY");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "TYPE_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isNullable(int)
-     */
-    @Override public int isNullable(int column) {
-        logStep("isNullable", column);
-        return ResultSetMetaData.columnNullableUnknown; // TODO Check if somes settings exists for that in field descriptor.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isSigned(int)
-     */
-    @Override public boolean isSigned(int column) {
-        logStep("isSigned", column);
-        return true;  // TODO Check if somes settings exists for that in field descriptor.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnDisplaySize(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public int getColumnDisplaySize(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getColumnDisplaySize", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            switch(rsDatabase.getString("TYPE_NAME")) {
-                case "AUTO_INCREMENT":
-                case "CHAR":
-                case "INTEGER":
-                   return rsDatabase.getInt("COLUMN_SIZE");
-
-                case "DATE":
-                    return 8;
-
-                // Add decimal separator for decimal numbers.
-                case "DOUBLE":
-                case "FLOAT":
-                case "DECIMAL":
-                    return rsDatabase.getInt("COLUMN_SIZE") + 1;
-
-                case "BOOLEAN":
-                    return 5; // Translation for true, false, null.
-
-                // Unhandled types default to field length.
-                case "CURRENCY":
-                case "DATETIME":
-                case "TIMESTAMP":
-                case "MEMO":
-                case "PICTURE":
-                case "VARIFIELD":
-                case "VARIANT":
-                case "UNKNOWN":
-                    return rsDatabase.getInt("COLUMN_SIZE");
-
-                default:
-                    return rsDatabase.getInt("COLUMN_SIZE");
-            }
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "TYPE_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnLabel(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public String getColumnLabel(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getColumnLabel", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getString("COLUMN_NAME");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "COLUMN_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnName(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public String getColumnName(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getColumnName", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getString("COLUMN_NAME");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "COLUMN_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getSchemaName(int)
-     */
-    @Override public String getSchemaName(int column) {
-        logStep("getSchemaName", column);
-        return ""; // No schema name in DBase 3.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getPrecision(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public int getPrecision(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getPrecision", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getInt("COLUMN_SIZE");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "COLUMN_SIZE", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getScale(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public int getScale(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getScale", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getInt("DECIMAL_DIGITS");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "DECIMAL_DIGITS", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getTableName(int)
-     */
-    @Override public String getTableName(int column) {
-        logStep("getTableName", column);
-
-        // The table default to the file name (without its extension .dbf).
-        String fileName = this.rs.getFile().getName();
-        int indexDBF = fileName.lastIndexOf(".");
-        String tableName = fileName.substring(0, indexDBF);
-
-        return tableName;
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getCatalogName(int)
-     */
-    @Override public String getCatalogName(int column) {
-        logStep("getCatalogName", column);
-        return "";
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnType(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     */
-    @Override public int getColumnType(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getColumnType", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getInt("DATA_TYPE");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "DATA_TYPE", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnTypeName(int)
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public String getColumnTypeName(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getColumnTypeName", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            return rsDatabase.getString("TYPE_NAME");
-        }
-        catch(SQLNoSuchFieldException e) {
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "TYPE_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isReadOnly(int)
-     */
-    @Override public boolean isReadOnly(int column) {
-        logStep("isReadOnly", column);
-        return false; // TODO Check if somes settings exists for that in field descriptor.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isWritable(int)
-     */
-    @Override public boolean isWritable(int column) {
-        logStep("isWritable", column);
-        return true;  // TODO Check if somes settings exists for that in field descriptor.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#isDefinitelyWritable(int)
-     */
-    @Override public boolean isDefinitelyWritable(int column) {
-        logStep("isDefinitelyWritable", column);
-        return true; // TODO Check if somes settings exists for that in field descriptor.
-    }
-
-    /**
-     * @see java.sql.ResultSetMetaData#getColumnClassName(int)
-     * @throws SQLFeatureNotSupportedException if underlying class implementing a type isn't currently set.
-     * @throws SQLIllegalColumnIndexException if the column index is illegal.
-     * @throws SQLConnectionClosedException if the connection is closed.
-     */
-    @Override public String getColumnClassName(int column) throws SQLFeatureNotSupportedException, SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        logStep("getColumnClassName", column);
-
-        try(DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = desc(column)) {
-            switch(rsDatabase.getString("TYPE_NAME")) {
-                case "AUTO_INCREMENT":
-                    return Integer.class.getName();
-
-                case "CHAR":
-                    return String.class.getName();
-
-                case "INTEGER":
-                   return Integer.class.getName();
-
-                case "DATE":
-                    return java.sql.Date.class.getName();
-
-                case "DOUBLE":
-                    return Double.class.getName();
-
-                case "FLOAT":
-                    return Float.class.getName();
-
-                case "DECIMAL":
-                    return Double.class.getName();
-
-                case "BOOLEAN":
-                    return Boolean.class.getName();
-
-                case "CURRENCY":
-                    return Double.class.getName();
-
-                case "DATETIME":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on DateTime");
-
-                case "TIMESTAMP":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on TimeStamp");
-
-                case "MEMO":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on Memo");
-
-                case "PICTURE":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on Picture");
-
-                case "VARIFIELD":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on VariField");
-
-                case "VARIANT":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on Variant");
-
-                case "UNKNOWN":
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on " + rsDatabase.getString("TYPE_NAME"));
-
-                default:
-                    throw unsupportedOperation("ResultSetMetaData.getColumnClassName(..) on " + rsDatabase.getString("TYPE_NAME"));
-            }
-        }
-        catch(SQLNoSuchFieldException e) {
-            // We encounter an internal API error in this case.
-            String message = format(Level.SEVERE, "assert.expected_databasemetadata_not_found", "TYPE_NAME", e.getMessage());
-            throw new RuntimeException(message, e);
-        }
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#getInterface()
-     */
-    @Override protected Class<?> getInterface() {
-        return ResultSetMetaData.class;
-    }
-
-    /**
-     * @see org.apache.sis.internal.shapefile.jdbc.AbstractJDBC#getFile()
-     */
-    @Override
-    protected File getFile() {
-        return this.rs.getFile();
-    }
-
-    /**
-     * Returns a ResultSet set on the wished column.
-     * @param column Column.
-     * @return ResultSet describing to wished column?
-     * @throws SQLIllegalColumnIndexException if the column index is out of bounds.
-     * @throws SQLConnectionClosedException if the underlying connection is closed.
-     */
-    private DBFBuiltInMemoryResultSetForColumnsListing desc(int column) throws SQLIllegalColumnIndexException, SQLConnectionClosedException {
-        DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = (DBFBuiltInMemoryResultSetForColumnsListing)this.metadata.getColumns(null, null, null, null);
-
-        if (column > getColumnCount()) {
-            rsDatabase.close();
-            String message = format(Level.WARNING, "excp.illegal_column_index_metadata", column, getColumnCount());
-            throw new SQLIllegalColumnIndexException(message, this.rs.getSQL(), getFile(), column);
-        }
-
-        // TODO Implements ResultSet:absolute(int) instead.
-        for(int index=1; index <= column; index ++) {
-            try {
-                rsDatabase.next();
-            }
-            catch(SQLNoResultException e) {
-                // We encounter an internal API error in this case.
-                rsDatabase.close();
-                String message = format(Level.SEVERE, "assert.less_column_in_metadata_than_expected", column, getColumnCount());
-                throw new RuntimeException(message, e);
-            }
-        }
-
-        return rsDatabase;
-    }
-}
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/package-info.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/package-info.java
deleted file mode 100644
index 68e310d..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/metadata/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Metadata classes and dedicated forged ResultSets for JDBC DBase 3 driver.
- */
-package org.apache.sis.internal.shapefile.jdbc.metadata;
diff --git a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/package-info.java b/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/package-info.java
deleted file mode 100644
index fc8155d..0000000
--- a/storage/sis-shapefile/src/main/java/org/apache/sis/internal/shapefile/jdbc/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
... 7981 lines suppressed ...


Mime
View raw message