This is an automated email from the ASF dual-hosted git repository. jsorel pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new d747d8924b feat(Shapefile): implement ResourceOnFileSystem d747d8924b is described below commit d747d8924bba34be21f506ed2fe1e12ffa0cfb02 Author: jsorel <johann.so...@geomatys.com> AuthorDate: Mon Nov 27 09:17:59 2023 +0100 feat(Shapefile): implement ResourceOnFileSystem --- .../org.apache.sis.storage/main/module-info.java | 1 + .../sis/storage/shapefile/ShapefileStore.java | 26 ++- .../sis/storage/shapefile/ShapefileStoreTest.java | 196 +++++++++++---------- 3 files changed, 131 insertions(+), 92 deletions(-) diff --git a/endorsed/src/org.apache.sis.storage/main/module-info.java b/endorsed/src/org.apache.sis.storage/main/module-info.java index 0866bdc06c..b7ce508e35 100644 --- a/endorsed/src/org.apache.sis.storage/main/module-info.java +++ b/endorsed/src/org.apache.sis.storage/main/module-info.java @@ -54,6 +54,7 @@ module org.apache.sis.storage { org.apache.sis.storage.geotiff, org.apache.sis.storage.earthobservation, org.apache.sis.storage.coveragejson, // In the "incubator" sub-project. + org.apache.sis.storage.shapefile, // In the "incubator" sub-project. org.apache.sis.util, // For the "About" command. org.apache.sis.console, org.apache.sis.openoffice, diff --git a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java index c419a714bb..303b6d6f20 100644 --- a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java +++ b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java @@ -89,6 +89,7 @@ import org.apache.sis.storage.Query; import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.UnsupportedQueryException; import org.apache.sis.storage.WritableFeatureSet; +import org.apache.sis.storage.base.ResourceOnFileSystem; import org.apache.sis.storage.shapefile.cpg.CpgFiles; import org.apache.sis.storage.shapefile.dbf.DBFField; import org.apache.sis.storage.shapefile.dbf.DBFHeader; @@ -125,7 +126,7 @@ import org.opengis.filter.ValueReference; * * @author Johann Sorel (Geomatys) */ -public final class ShapefileStore extends DataStore implements WritableFeatureSet { +public final class ShapefileStore extends DataStore implements WritableFeatureSet, ResourceOnFileSystem { private static final String GEOMETRY_NAME = "geometry"; private static final Logger LOGGER = Logger.getLogger("org.apache.sis.storage.shapefile"); @@ -220,7 +221,12 @@ public final class ShapefileStore extends DataStore implements WritableFeatureSe featureSetView.replaceIf(predicate, unaryOperator); } - private class AsFeatureSet extends AbstractFeatureSet implements WritableFeatureSet { + @Override + public Path[] getComponentFiles() throws DataStoreException { + return featureSetView.getComponentFiles(); + } + + private class AsFeatureSet extends AbstractFeatureSet implements WritableFeatureSet, ResourceOnFileSystem { private final Rectangle2D.Double filter; private final Set<String> dbfProperties; @@ -692,6 +698,22 @@ public final class ShapefileStore extends DataStore implements WritableFeatureSe if (!isDefaultView()) throw new DataStoreException("Resource not writable in current filter state"); throw new UnsupportedOperationException("Not supported yet."); } + + @Override + public Path[] getComponentFiles() throws DataStoreException { + final List<Path> paths = new ArrayList<>(); + final Path shp = files.shpFile; + final Path shx = files.getShx(false); + final Path dbf = files.getDbf(false); + final Path prj = files.getPrj(false); + final Path cpg = files.getCpg(false); + if (shp != null && Files.exists(shp)) paths.add(shp); + if (shx != null && Files.exists(shx)) paths.add(shx); + if (dbf != null && Files.exists(dbf)) paths.add(dbf); + if (prj != null && Files.exists(prj)) paths.add(prj); + if (cpg != null && Files.exists(cpg)) paths.add(cpg); + return paths.toArray(Path[]::new); + } } /** diff --git a/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java b/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java index 81d2da30a7..6d0152954f 100644 --- a/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java +++ b/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java @@ -18,6 +18,7 @@ package org.apache.sis.storage.shapefile; import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDate; import java.util.Iterator; @@ -51,49 +52,50 @@ public class ShapefileStoreTest { @Test public void testStream() throws URISyntaxException, DataStoreException { final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp"); - final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI())); - - //check feature type - final FeatureType type = store.getType(); - assertEquals("point", type.getName().toString()); - assertEquals(9, type.getProperties(true).size()); - assertNotNull(type.getProperty("sis:identifier")); - assertNotNull(type.getProperty("sis:envelope")); - assertNotNull(type.getProperty("sis:geometry")); - final var geomProp = (AttributeType) type.getProperty("geometry"); - final var idProp = (AttributeType) type.getProperty("id"); - final var textProp = (AttributeType) type.getProperty("text"); - final var integerProp = (AttributeType) type.getProperty("integer"); - final var floatProp = (AttributeType) type.getProperty("float"); - final var dateProp = (AttributeType) type.getProperty("date"); - assertEquals(Point.class, geomProp.getValueClass()); - assertEquals(Long.class, idProp.getValueClass()); - assertEquals(String.class, textProp.getValueClass()); - assertEquals(Long.class, integerProp.getValueClass()); - assertEquals(Double.class, floatProp.getValueClass()); - assertEquals(LocalDate.class, dateProp.getValueClass()); - - try (Stream<Feature> stream = store.features(false)) { - Iterator<Feature> iterator = stream.iterator(); - assertTrue(iterator.hasNext()); - Feature feature1 = iterator.next(); - assertEquals(1L, feature1.getPropertyValue("id")); - assertEquals("text1", feature1.getPropertyValue("text")); - assertEquals(10L, feature1.getPropertyValue("integer")); - assertEquals(20.0, feature1.getPropertyValue("float")); - assertEquals(LocalDate.of(2023, 10, 27), feature1.getPropertyValue("date")); - Point pt1 = (Point) feature1.getPropertyValue("geometry"); - - assertTrue(iterator.hasNext()); - Feature feature2 = iterator.next(); - assertEquals(2L, feature2.getPropertyValue("id")); - assertEquals("text2", feature2.getPropertyValue("text")); - assertEquals(40L, feature2.getPropertyValue("integer")); - assertEquals(60.0, feature2.getPropertyValue("float")); - assertEquals(LocalDate.of(2023, 10, 28), feature2.getPropertyValue("date")); - Point pt2 = (Point) feature2.getPropertyValue("geometry"); - - assertFalse(iterator.hasNext()); + try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + + //check feature type + final FeatureType type = store.getType(); + assertEquals("point", type.getName().toString()); + assertEquals(9, type.getProperties(true).size()); + assertNotNull(type.getProperty("sis:identifier")); + assertNotNull(type.getProperty("sis:envelope")); + assertNotNull(type.getProperty("sis:geometry")); + final var geomProp = (AttributeType) type.getProperty("geometry"); + final var idProp = (AttributeType) type.getProperty("id"); + final var textProp = (AttributeType) type.getProperty("text"); + final var integerProp = (AttributeType) type.getProperty("integer"); + final var floatProp = (AttributeType) type.getProperty("float"); + final var dateProp = (AttributeType) type.getProperty("date"); + assertEquals(Point.class, geomProp.getValueClass()); + assertEquals(Long.class, idProp.getValueClass()); + assertEquals(String.class, textProp.getValueClass()); + assertEquals(Long.class, integerProp.getValueClass()); + assertEquals(Double.class, floatProp.getValueClass()); + assertEquals(LocalDate.class, dateProp.getValueClass()); + + try (Stream<Feature> stream = store.features(false)) { + Iterator<Feature> iterator = stream.iterator(); + assertTrue(iterator.hasNext()); + Feature feature1 = iterator.next(); + assertEquals(1L, feature1.getPropertyValue("id")); + assertEquals("text1", feature1.getPropertyValue("text")); + assertEquals(10L, feature1.getPropertyValue("integer")); + assertEquals(20.0, feature1.getPropertyValue("float")); + assertEquals(LocalDate.of(2023, 10, 27), feature1.getPropertyValue("date")); + Point pt1 = (Point) feature1.getPropertyValue("geometry"); + + assertTrue(iterator.hasNext()); + Feature feature2 = iterator.next(); + assertEquals(2L, feature2.getPropertyValue("id")); + assertEquals("text2", feature2.getPropertyValue("text")); + assertEquals(40L, feature2.getPropertyValue("integer")); + assertEquals(60.0, feature2.getPropertyValue("float")); + assertEquals(LocalDate.of(2023, 10, 28), feature2.getPropertyValue("date")); + Point pt2 = (Point) feature2.getPropertyValue("geometry"); + + assertFalse(iterator.hasNext()); + } } } @@ -103,32 +105,33 @@ public class ShapefileStoreTest { @Test public void testEnvelopeFilter() throws URISyntaxException, DataStoreException { final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp"); - final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI())); - - final FilterFactory<Feature, Object, Object> ff = DefaultFilterFactory.forFeatures(); - - final GeneralEnvelope env = new GeneralEnvelope(CommonCRS.WGS84.normalizedGeographic()); - env.setRange(0, 2, 3); - env.setRange(1, 42, 43); - - final FeatureQuery query = new FeatureQuery(); - query.setSelection(ff.bbox(ff.property("geometry"), env)); - FeatureSet featureset = store.subset(query); - //ensure we obtained an optimized version - assertEquals("org.apache.sis.storage.shapefile.ShapefileStore$AsFeatureSet", featureset.getClass().getName()); - - try (Stream<Feature> stream = featureset.features(false)) { - Iterator<Feature> iterator = stream.iterator(); - assertTrue(iterator.hasNext()); - Feature feature = iterator.next(); - assertEquals(2L, feature.getPropertyValue("id")); - assertEquals("text2", feature.getPropertyValue("text")); - assertEquals(40L, feature.getPropertyValue("integer")); - assertEquals(60.0, feature.getPropertyValue("float")); - assertEquals(LocalDate.of(2023, 10, 28), feature.getPropertyValue("date")); - Point pt2 = (Point) feature.getPropertyValue("geometry"); - - assertFalse(iterator.hasNext()); + try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + + final FilterFactory<Feature, Object, Object> ff = DefaultFilterFactory.forFeatures(); + + final GeneralEnvelope env = new GeneralEnvelope(CommonCRS.WGS84.normalizedGeographic()); + env.setRange(0, 2, 3); + env.setRange(1, 42, 43); + + final FeatureQuery query = new FeatureQuery(); + query.setSelection(ff.bbox(ff.property("geometry"), env)); + FeatureSet featureset = store.subset(query); + //ensure we obtained an optimized version + assertEquals("org.apache.sis.storage.shapefile.ShapefileStore$AsFeatureSet", featureset.getClass().getName()); + + try (Stream<Feature> stream = featureset.features(false)) { + Iterator<Feature> iterator = stream.iterator(); + assertTrue(iterator.hasNext()); + Feature feature = iterator.next(); + assertEquals(2L, feature.getPropertyValue("id")); + assertEquals("text2", feature.getPropertyValue("text")); + assertEquals(40L, feature.getPropertyValue("integer")); + assertEquals(60.0, feature.getPropertyValue("float")); + assertEquals(LocalDate.of(2023, 10, 28), feature.getPropertyValue("date")); + Point pt2 = (Point) feature.getPropertyValue("geometry"); + + assertFalse(iterator.hasNext()); + } } } @@ -138,28 +141,41 @@ public class ShapefileStoreTest { @Test public void testFieldFilter() throws URISyntaxException, DataStoreException { final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp"); - final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI())); - - - final FeatureQuery query = new FeatureQuery(); - query.setProjection("text", "float"); - FeatureSet featureset = store.subset(query); - //ensure we obtained an optimized version - assertEquals("org.apache.sis.storage.shapefile.ShapefileStore$AsFeatureSet", featureset.getClass().getName()); - - try (Stream<Feature> stream = featureset.features(false)) { - Iterator<Feature> iterator = stream.iterator(); - assertTrue(iterator.hasNext()); - Feature feature1 = iterator.next(); - assertEquals("text1", feature1.getPropertyValue("text")); - assertEquals(20.0, feature1.getPropertyValue("float")); - - assertTrue(iterator.hasNext()); - Feature feature2 = iterator.next(); - assertEquals("text2", feature2.getPropertyValue("text")); - assertEquals(60.0, feature2.getPropertyValue("float")); + try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + final FeatureQuery query = new FeatureQuery(); + query.setProjection("text", "float"); + FeatureSet featureset = store.subset(query); + //ensure we obtained an optimized version + assertEquals("org.apache.sis.storage.shapefile.ShapefileStore$AsFeatureSet", featureset.getClass().getName()); + + try (Stream<Feature> stream = featureset.features(false)) { + Iterator<Feature> iterator = stream.iterator(); + assertTrue(iterator.hasNext()); + Feature feature1 = iterator.next(); + assertEquals("text1", feature1.getPropertyValue("text")); + assertEquals(20.0, feature1.getPropertyValue("float")); + + assertTrue(iterator.hasNext()); + Feature feature2 = iterator.next(); + assertEquals("text2", feature2.getPropertyValue("text")); + assertEquals(60.0, feature2.getPropertyValue("float")); + + assertFalse(iterator.hasNext()); + } + } + } - assertFalse(iterator.hasNext()); + @Test + public void testFiles() throws URISyntaxException, DataStoreException { + final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp"); + try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + Path[] componentFiles = store.getComponentFiles(); + assertEquals(5, componentFiles.length); + componentFiles[0].toString().endsWith("point.shp"); + componentFiles[1].toString().endsWith("point.shx"); + componentFiles[2].toString().endsWith("point.dbf"); + componentFiles[3].toString().endsWith("point.prj"); + componentFiles[4].toString().endsWith("point.cpg"); } }