From 5f51fcb0491d526d6b181d89b818f0d651cd1933 Mon Sep 17 00:00:00 2001 From: Simon Templer Date: Wed, 7 Aug 2024 00:41:04 +0200 Subject: [PATCH] feat: support loading single Shapefile from folder Support for identifying and loading a single Shapefile if the source set for the ShapeSchemaReader is a folder. ING-4416 --- .../io/shp/ShapeInstanceReaderTest.groovy | 37 +++++++++++++++++++ .../reader/internal/ShapeInstanceReader.java | 35 +++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/io/plugins/eu.esdihumboldt.hale.io.shp.test/src/eu/esdihumboldt/hale/io/shp/ShapeInstanceReaderTest.groovy b/io/plugins/eu.esdihumboldt.hale.io.shp.test/src/eu/esdihumboldt/hale/io/shp/ShapeInstanceReaderTest.groovy index 6fc688e0a7..08e4db40ec 100644 --- a/io/plugins/eu.esdihumboldt.hale.io.shp.test/src/eu/esdihumboldt/hale/io/shp/ShapeInstanceReaderTest.groovy +++ b/io/plugins/eu.esdihumboldt.hale.io.shp.test/src/eu/esdihumboldt/hale/io/shp/ShapeInstanceReaderTest.groovy @@ -21,8 +21,10 @@ import static org.junit.Assert.assertNotNull import static org.junit.Assert.assertTrue import java.nio.charset.StandardCharsets +import java.nio.file.Files import java.util.function.Consumer +import org.apache.commons.io.IOUtils import org.junit.Test import org.locationtech.jts.geom.Geometry @@ -47,6 +49,9 @@ import groovy.transform.TypeCheckingMode @CompileStatic class ShapeInstanceReaderTest { + /** + * Test reading Shapefile instances using the Shapefile as schema. + */ @Test void testReadShapeInstances() { Schema xmlSchema = TestUtil.loadSchema(getClass().getClassLoader().getResource("testdata/arokfnp/ikg.shp").toURI()) @@ -63,6 +68,38 @@ class ShapeInstanceReaderTest { validateArokFnpIkg(list, 'the_geom') } + /** + * Test reading a single Shapefile from a folder. + */ + @Test + void testReadFromFolder() { + Schema xmlSchema = TestUtil.loadSchema(getClass().getClassLoader().getResource("testdata/arokfnp/ikg.shp").toURI()) + + File tempDir = Files.createTempDirectory("read-shape").toFile() + try { + def ext = ['shp', 'dbf', 'prj', 'shx'] + ext.each { + IOUtils.copy(getClass().getClassLoader().getResource("testdata/arokfnp/ikg.$it"), new File(tempDir, "ikg.$it")) + } + + InstanceCollection instances = loadInstances(xmlSchema, tempDir.toURI()) + + assertNotNull(instances) + List list = instances.toList() + + // test count + assertThat(list).hasSize(14) + + // instance validation + validateArokFnpIkg(list, 'the_geom') + } finally { + tempDir.deleteDir() + } + } + + /** + * Test reading Shapefile instances using an XML schema. + */ @Test void testReadXsdInstances() { Schema xmlSchema = TestUtil.loadSchema(getClass().getClassLoader().getResource("testdata/arokfnp/arok-fnp.xsd").toURI()) diff --git a/io/plugins/eu.esdihumboldt.hale.io.shp/src/eu/esdihumboldt/hale/io/shp/reader/internal/ShapeInstanceReader.java b/io/plugins/eu.esdihumboldt.hale.io.shp/src/eu/esdihumboldt/hale/io/shp/reader/internal/ShapeInstanceReader.java index c71be1adff..756d0ab8fc 100644 --- a/io/plugins/eu.esdihumboldt.hale.io.shp/src/eu/esdihumboldt/hale/io/shp/reader/internal/ShapeInstanceReader.java +++ b/io/plugins/eu.esdihumboldt.hale.io.shp/src/eu/esdihumboldt/hale/io/shp/reader/internal/ShapeInstanceReader.java @@ -15,7 +15,9 @@ */ package eu.esdihumboldt.hale.io.shp.reader.internal; +import java.io.File; import java.io.IOException; +import java.net.URI; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.Collection; @@ -36,6 +38,7 @@ import eu.esdihumboldt.hale.common.core.io.report.IOReport; import eu.esdihumboldt.hale.common.core.io.report.IOReporter; import eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl; +import eu.esdihumboldt.hale.common.core.io.supplier.DefaultInputSupplier; import eu.esdihumboldt.hale.common.core.parameter.AbstractParameterValueDescriptor; import eu.esdihumboldt.hale.common.instance.io.InstanceReader; import eu.esdihumboldt.hale.common.instance.io.impl.AbstractInstanceReader; @@ -98,7 +101,34 @@ protected IOReport execute(ProgressIndicator progress, IOReporter reporter) throws IOProviderConfigurationException, IOException { progress.begin(Messages.getString("ShapeSchemaProvider.1"), ProgressIndicator.UNKNOWN); //$NON-NLS-1$ - ShapefileDataStore store = new ShapefileDataStore(getSource().getLocation().toURL()); + URI loc = getSource().getLocation(); + try { + File file = new File(loc); + + // special handling for directory as source -> load single Shapefile + if (file.exists() && file.isDirectory()) { + File[] candidates = file + .listFiles(f -> f.isFile() && f.getName().toLowerCase().endsWith(".shp")); + if (candidates != null && candidates.length > 0) { + // use first Shapefile found in folder + loc = candidates[0].toURI(); + + if (candidates.length > 1) { + reporter.warn( + "Picked file {} to load from folder, other Shapefiles in folder found but ignored", + candidates[0].getName()); + } + else { + reporter.info("Picked file {} to load from folder", + candidates[0].getName()); + } + } + } + } catch (IllegalArgumentException e) { + // ignore + } + + ShapefileDataStore store = new ShapefileDataStore(loc.toURL()); store.setCharset(getCharset()); progress.setCurrentTask("Extracting shape instances"); @@ -136,7 +166,8 @@ protected IOReport execute(ProgressIndicator progress, IOReporter reporter) reporter.info(new IOMessageImpl( "No type name supplied as parameter, trying to auto-detect the schema type.", null)); - TypeDefinition dataType = ShapeSchemaReader.readShapeType(getSource()); + TypeDefinition dataType = ShapeSchemaReader + .readShapeType(new DefaultInputSupplier(loc)); if (dataType == null) { throw new IOException("Could not read shapefile structure information"); }