From 5509a898926d548e77f5de97b2a9efada12ed70a Mon Sep 17 00:00:00 2001
From: ebocher
Date: Fri, 13 Jan 2023 11:04:35 +0100
Subject: [PATCH 1/2] Start to link H2GIS GT module to GeoScript
---
pom.xml | 5 +
.../workspace/DatabaseExtensionModule.groovy | 183 +++++++++++++++
.../groovy/geoscript/workspace/H2GIS.groovy | 212 ++++++++++++++++++
...rg.codehaus.groovy.runtime.ExtensionModule | 2 +-
.../geoscript/workspace/H2GISTest.groovy | 96 ++++++++
5 files changed, 497 insertions(+), 1 deletion(-)
create mode 100644 src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy
create mode 100644 src/main/groovy/geoscript/workspace/H2GIS.groovy
create mode 100644 src/test/groovy/geoscript/workspace/H2GISTest.groovy
diff --git a/pom.xml b/pom.xml
index d08a5f2a..6f7ff649 100755
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,11 @@
gt-jdbc-postgis
${gt.version}
+
+ org.geotools.jdbc
+ gt-jdbc-h2gis
+ ${gt.version}
+
org.geotools.jdbc
gt-jdbc-h2
diff --git a/src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy b/src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy
new file mode 100644
index 00000000..65f84033
--- /dev/null
+++ b/src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy
@@ -0,0 +1,183 @@
+package geoscript.workspace
+
+import org.apache.commons.lang3.StringUtils
+import org.H2GIS.functions.io.utility.IOMethods
+import org.geotools.util.logging.Logging
+import java.sql.SQLException
+import java.util.logging.Logger
+
+/**
+ * A Groovy Extension Module that adds static methods to some Database drivers.
+ * @author Erwan Bocher (CNRS)
+ */
+class DatabaseExtensionModule {
+ /**
+ * The Logger
+ */
+ private static final Logger LOGGER = Logging.getLogger("geoscript.workspace.DatabaseExtensionModule")
+
+ private static IOMethods ioMethods = null;
+
+ /**
+ * Create a dynamic link from a file to a H2GIS database.
+ *
+ * @param sql connection to the database.
+ * @param path The path of the file.
+ * @param table The name of the table created to store the file.
+ * @param delete True to delete the table if exists. Default to true.
+ * @throws java.sql.SQLException Exception throw on database error.
+ */
+ static String linkedFile(H2GIS h2GIS, String path, String table, boolean delete = false) throws SQLException {
+ return IOMethods.linkedFile(h2GIS.getDataSource().getConnection(), path, table, delete)
+ }
+
+ /**
+ * Create a dynamic link from a file to a H2GIS database.
+ *
+ * @param sql connection to the database.
+ * @param path The path of the file.
+ * @param table The name of the table created to store the file.
+ * @param delete True to delete the table if exists. Default to true.
+ * @throws java.sql.SQLException Exception throw on database error.
+ */
+ static String linkedFile(H2GIS h2GIS, String path, boolean delete = false) throws SQLException {
+ File pathFile = new File(path)
+ String fileName = pathFile.name
+ String name = fileName.substring(0, fileName.lastIndexOf('.'))
+ return linkedFile(h2GIS, path, StringUtils.deleteWhitespace(name), delete)
+ }
+
+
+ /**
+ * Save a table into a file
+ * @param database
+ * @param tableName
+ * @param filePath
+ * @param delete
+ * @return
+ */
+ static boolean save(Database database, String tableName, String filePath, boolean delete = false) {
+ if (database instanceof H2GIS || database instanceof PostGIS) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.warning("No connection, cannot save.");
+ return false;
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods();
+ }
+ ioMethods.exportToFile(con, tableName, filePath, null, delete);
+ return true;
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath);
+ }
+ }
+ LOGGER.warning("Unsuported method for this Database ")
+ return false;
+ }
+
+ /**
+ * Save a table into a file
+ * @param database
+ * @param tableName
+ * @param filePath
+ * @param delete
+ * @return
+ */
+ static boolean save(Database database, String tableName, String filePath, String encoding) {
+ if (database instanceof H2GIS || database instanceof PostGIS) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.severe("No connection, cannot save.");
+ return false;
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods();
+ }
+ ioMethods.exportToFile(con, tableName, filePath, encoding, false);
+ return true;
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath);
+ }
+ }
+ LOGGER.warning("Unsuported method for this Database ")
+ return false;
+ }
+
+ /**
+ * Load a file to the database
+ * @param database
+ * @param filePath
+ * @param encoding
+ * @param delete
+ * @return
+ */
+ static String load(Database database, String filePath,
+ boolean delete = false) {
+ File pathFile = new File(filePath)
+ String fileName = pathFile.name
+ String name = fileName.substring(0, fileName.lastIndexOf('.'))
+ return load(database, filePath, StringUtils.deleteWhitespace(name), null, delete)
+ }
+
+
+ /**
+ * Load a file to the database
+ * @param database
+ * @param filePath
+ * @param tableName
+ * @param encoding
+ * @param delete
+ * @return
+ */
+ static String load(Database database, String filePath, String tableName) {
+ return load(database, filePath, tableName, null,
+ false)
+ }
+
+ /**
+ * Load a file to the database
+ * @param database
+ * @param filePath
+ * @param tableName
+ * @param encoding
+ * @param delete
+ * @return
+ */
+ static String load(Database database, String filePath, String tableName,
+ delete) {
+ return load(database, filePath, tableName, null,
+ delete)
+ }
+
+ /**
+ * Load a file to the database
+ * @param database
+ * @param filePath
+ * @param tableName
+ * @param encoding
+ * @param delete
+ * @return
+ */
+ static String load(Database database, String filePath, String tableName, String encoding,
+ boolean delete = false) {
+ if (database instanceof H2GIS || database instanceof PostGIS) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.severe("No connection, cannot load the file $filePath.");
+ return false;
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods();
+ }
+ return ioMethods.importFile(con, filePath, tableName, encoding, delete)
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath);
+ }
+ }
+ return null
+ }
+}
diff --git a/src/main/groovy/geoscript/workspace/H2GIS.groovy b/src/main/groovy/geoscript/workspace/H2GIS.groovy
new file mode 100644
index 00000000..7788db01
--- /dev/null
+++ b/src/main/groovy/geoscript/workspace/H2GIS.groovy
@@ -0,0 +1,212 @@
+package geoscript.workspace
+
+import org.geotools.data.DataStore
+import org.geotools.jdbc.JDBCDataStore
+import org.geotools.jdbc.JDBCDataStoreFactory
+import org.geotools.util.logging.Logging
+import org.h2gis.geotools.H2GISDataStoreFactory
+
+import java.sql.Connection
+import java.sql.SQLException
+import java.util.logging.Logger
+
+/**
+ * A H2GIS Workspace connects to a spatially enabled H2GIS database.
+ *
+ * H2GIS H2GIS = new H2GIS("acme", "target/H2GIS")
+ * Layer layer = H2GIS.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ * layer.add([new Point(1,1), "one"])
+ * layer.add([new Point(2,2), "two"])
+ * layer.add([new Point(3,3), "three"])
+ *
+ * @author Jared Erickson
+ * @author Erwan Bocher (CNRS)
+ */
+class H2GIS extends Database {
+
+
+ /**
+ * The Logger
+ */
+ private static final Logger LOGGER = Logging.getLogger("geoscript.workspace.H2GIS");
+
+ /**
+ * Create a new H2GIS Workspace with a name and directory
+ * @param name The name of the database
+ * @param dir The File containing the database
+ */
+ H2GIS(String name, File dir) {
+ super(createDataStore(name, dir))
+ }
+
+ /**
+ * Create a new H2GIS Workspace with a name and directory
+ * @param name The name of the database
+ * @param dir The File containing the database
+ */
+ H2GIS(String name, String dir) {
+ this(name, new File(dir).absoluteFile)
+ }
+
+
+ /**
+ * Create a new H2GIS Workspace from a database file
+ * @param file The H2 database file
+ */
+ H2GIS(File file) {
+ this(file.name, file.parentFile)
+ }
+
+ /**
+ * Create a new H2GIS Workspace with a name, host, port, schema, user, and password.
+ * @param database The database name
+ * @param host The host
+ * @param port The port
+ * @param schema The schema
+ * @param user The user name
+ * @param password The password
+ */
+ H2GIS(String database, String host, String port, String schema, String user, String password) {
+ super(createDataStore(database, host, port, schema, user, password))
+ }
+
+ /**
+ * Create a new H2GIS Workspace
+ * @param options The named parameters
+ *
+ * - host = The host (defaults to localhost)
+ * - port = The port (defaults to an empty string)
+ * - schema = The schema (defaults to null)
+ * - user = The user name (defaults to sa)
+ * - password = The password (defaults to an empty string)
+ *
+ * @param database The database name (or JNDI reference name)
+ */
+ H2GIS(Map options, String database) {
+ this(database, options.get("host", "localhost"), options.get("port", ""), options.get("schema"),
+ options.get("user", "sa"), options.get("password", ""))
+ }
+
+ /**
+ * Create a new H2GIS Workspace
+ *
+ * @param database the name of the database
+ */
+ H2GIS(String database) {
+ this(new File(database))
+ }
+
+ /**
+ * Create a new H2GIS Workspace from a GeoTools JDBCDataStore
+ * @param ds The GeoTools JDBCDataStore
+ */
+ H2GIS(JDBCDataStore ds) {
+ super(ds)
+ }
+
+ /**
+ * Get the format
+ * @return The workspace format name
+ */
+ @Override
+ String getFormat() {
+ return "H2GIS"
+ }
+
+ /**
+ * Load the H2GIS Network function in the current H2GIS DataSource.
+ *
+ * @return True if the functions have been successfully loaded, false otherwise.
+ */
+ boolean addNetworkFunctions() {
+ Connection connection = getDataSource().getConnection();
+ if (connection == null) {
+ LOGGER.error("Cannot load the H2GIS Network extension.\n");
+ return false;
+ }
+ try {
+ NetworkFunctions.load(connection);
+ } catch (SQLException e) {
+ LOGGER.error("Cannot load the H2GIS Network extension.\n", e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Create a new H2GIS Workspace with a name and directory
+ */
+ private static DataStore createDataStore(String name, File dir) {
+ HashMap params = new HashMap<>();
+ params.put(JDBCDataStoreFactory.DATABASE.key, new File(dir, name).absolutePath)
+ params.put(JDBCDataStoreFactory.DBTYPE.key, "h2gis")
+ params.put(JDBCDataStoreFactory.FETCHSIZE.key, 100)
+ H2GISDataStoreFactory h2gisf = new H2GISDataStoreFactory()
+ h2gisf.createDataStore(params)
+ }
+
+ /**
+ * Create a new H2GIS Workspace with a TCP connections
+ */
+ private static DataStore createDataStore(String database, String host, String port, String schema, String user, String password) {
+ Map params = new java.util.HashMap()
+ params.put("dbtype", "h2gis")
+ params.put(JDBCDataStoreFactory.USER.key, user)
+ params.put(JDBCDataStoreFactory.FETCHSIZE.key, 100);
+ params.put("database", database)
+ params.put("schema", schema)
+ params.put("host", host)
+ params.put("port", port)
+ params.put("user", user)
+ params.put("passwd", password)
+ def h2gisf = new H2GISDataStoreFactory()
+ h2gisf.createDataStore(params)
+ }
+
+ /**
+ * The H2GIS WorkspaceFactory
+ */
+ static class Factory extends WorkspaceFactory {
+
+ @Override
+ Map getParametersFromString(String str) {
+ Map params = [:]
+ if (!str.contains("=") && str.endsWith(".mv.db")) {
+ params.put("dbtype", "H2GIS")
+ params.put("database", new File(str).absolutePath)
+ } else {
+ params = super.getParametersFromString(str)
+ }
+ params
+ }
+
+ @Override
+ H2GIS create(String type, Map params) {
+ if (type.equalsIgnoreCase('H2GIS')) {
+ params['dbtype'] = 'H2GIS'
+ if (params.containsKey('file')) {
+ params['database'] = params['file']
+ }
+ if (params['database'] instanceof File) {
+ params['database'] = (params['database'] as File).absolutePath
+ }
+ super.create(params)
+ } else {
+ null
+ }
+ }
+
+ @Override
+ H2GIS create(DataStore dataStore) {
+ H2GIS h2GIS = null
+ if (dataStore instanceof org.geotools.jdbc.JDBCDataStore) {
+ def jdbcds = dataStore as org.geotools.jdbc.JDBCDataStore
+ if (jdbcds.dataStoreFactory instanceof org.h2gis.geotools.H2GISDataStoreFactory ||
+ jdbcds.dataStoreFactory instanceof org.h2gis.geotools.H2GISJNDIDataStoreFactory) {
+ h2GIS = new H2GIS(dataStore)
+ }
+ }
+ h2GIS
+ }
+ }
+}
diff --git a/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
index ea2267f6..2a3b1b2b 100644
--- a/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
+++ b/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
@@ -1,4 +1,4 @@
moduleName = geoscript-groovy-module
moduleVersion = 1.0
-extensionClasses = geoscript.geom.io.GeometryExtensionModule, geoscript.feature.io.FeatureExtensionModule, geoscript.layer.io.LayerExtensionModule, geoscript.layer.io.PyramidExtensionModule, geoscript.layer.WMSMapExtensionModule, geoscript.style.io.StyleExtensionModule
+extensionClasses = geoscript.geom.io.GeometryExtensionModule, geoscript.feature.io.FeatureExtensionModule, geoscript.layer.io.LayerExtensionModule, geoscript.layer.io.PyramidExtensionModule, geoscript.layer.WMSMapExtensionModule, geoscript.style.io.StyleExtensionModule,geoscript.workspace.DatabaseExtensionModule
staticExtensionClasses = geoscript.geom.io.StaticGeometryExtensionModule, geoscript.feature.io.StaticFeatureExtensionModule, geoscript.plot.ViewerExtensionModule, geoscript.layer.io.StaticPyramidExtensionModule, geoscript.style.io.StaticStyleExtensionModule
\ No newline at end of file
diff --git a/src/test/groovy/geoscript/workspace/H2GISTest.groovy b/src/test/groovy/geoscript/workspace/H2GISTest.groovy
new file mode 100644
index 00000000..4623bf5c
--- /dev/null
+++ b/src/test/groovy/geoscript/workspace/H2GISTest.groovy
@@ -0,0 +1,96 @@
+package geoscript.workspace
+
+import geoscript.feature.Field
+import geoscript.geom.Point
+import geoscript.layer.Layer
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.io.TempDir
+
+import static org.junit.jupiter.api.Assertions.*
+
+/**
+ * The H2 Workspace Unit Test
+ */
+
+class H2GISTest {
+ @TempDir
+ File folder
+
+ @Test void loadShapeFile() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ File file = new File(getClass().getClassLoader().getResource("states.shp").toURI())
+ String tableName = h2gis.load(file.getAbsolutePath(), true)
+ println(tableName)
+ }
+
+ @Test void remove() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ assertEquals "H2GIS", h2gis.format
+ // Add
+ Layer l = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(l)
+ l.add([new Point(1,1), "one"])
+ l.add([new Point(2,2), "two"])
+ l.add([new Point(3,3), "three"])
+ assertEquals 3, l.count()
+ // Get
+ assertNotNull(h2gis.get("widgets"))
+ // Remove
+ h2gis.remove("widgets")
+ boolean exceptionThrown = false
+ try {
+ h2gis.get("widgets")
+ } catch (IOException ex) {
+ exceptionThrown = true
+ }
+ assertTrue(exceptionThrown)
+ h2gis.close()
+ }
+
+ @Test void createFromPath() {
+ H2GIS h2gis = new H2GIS("./target/mydb")
+ assertEquals "H2GIS", h2gis.format
+ Layer l = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(l)
+ l.add([new Point(1,1), "one"])
+ l.add([new Point(2,2), "two"])
+ l.add([new Point(3,3), "three"])
+ assertEquals 3, l.count()
+ h2gis.close()
+ }
+
+ @Test void writeLinkShapeFile() {
+ H2GIS h2gis = new H2GIS("./target/mydb")
+ h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
+ assertEquals "H2GIS", h2gis.format
+ Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(layer)
+ layer.add([new Point(1,1), "one"])
+ layer.add([new Point(2,2), "two"])
+ layer.add([new Point(3,3), "three"])
+ assertEquals 3, layer.count()
+ File outputFile = new File("./target/widgets.shp")
+ h2gis.save("widgets", outputFile.getAbsolutePath())
+ def outputTable = h2gis.linkedFile(outputFile.getAbsolutePath(), true)
+ assertEquals(3, h2gis.get(outputTable).count)
+ h2gis.close()
+ }
+
+ @Test void writeSaveLoadShapeFile() {
+ H2GIS h2gis = new H2GIS("./target/mydb")
+ h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
+ assertEquals "H2GIS", h2gis.format
+ Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(layer)
+ layer.add([new Point(1,1), "one"])
+ layer.add([new Point(2,2), "two"])
+ layer.add([new Point(3,3), "three"])
+ assertEquals 3, layer.count()
+ File outputFile = new File("./target/widgets.shp")
+ h2gis.save("widgets", outputFile.getAbsolutePath())
+ def outputTable = h2gis.load(outputFile.getAbsolutePath(), "\"test_imported\"")
+ assertEquals(3, h2gis.get("test_imported").count)
+ h2gis.close()
+ }
+
+}
From aea8a6b657adff0fbe7f57b849a58b6452552e1c Mon Sep 17 00:00:00 2001
From: ebocher
Date: Fri, 20 Jan 2023 12:32:15 +0100
Subject: [PATCH 2/2] Update H2GIS workspace - add new methods on H2GIS module
- add new unit tests
---
.../workspace/DatabaseExtensionModule.groovy | 183 -----------
.../H2GISDatabaseExtensionModule.groovy | 304 ++++++++++++++++++
...rg.codehaus.groovy.runtime.ExtensionModule | 2 +-
.../geoscript/workspace/H2GISTest.groovy | 152 ++++++++-
4 files changed, 445 insertions(+), 196 deletions(-)
delete mode 100644 src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy
create mode 100644 src/main/groovy/geoscript/workspace/H2GISDatabaseExtensionModule.groovy
diff --git a/src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy b/src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy
deleted file mode 100644
index 65f84033..00000000
--- a/src/main/groovy/geoscript/workspace/DatabaseExtensionModule.groovy
+++ /dev/null
@@ -1,183 +0,0 @@
-package geoscript.workspace
-
-import org.apache.commons.lang3.StringUtils
-import org.H2GIS.functions.io.utility.IOMethods
-import org.geotools.util.logging.Logging
-import java.sql.SQLException
-import java.util.logging.Logger
-
-/**
- * A Groovy Extension Module that adds static methods to some Database drivers.
- * @author Erwan Bocher (CNRS)
- */
-class DatabaseExtensionModule {
- /**
- * The Logger
- */
- private static final Logger LOGGER = Logging.getLogger("geoscript.workspace.DatabaseExtensionModule")
-
- private static IOMethods ioMethods = null;
-
- /**
- * Create a dynamic link from a file to a H2GIS database.
- *
- * @param sql connection to the database.
- * @param path The path of the file.
- * @param table The name of the table created to store the file.
- * @param delete True to delete the table if exists. Default to true.
- * @throws java.sql.SQLException Exception throw on database error.
- */
- static String linkedFile(H2GIS h2GIS, String path, String table, boolean delete = false) throws SQLException {
- return IOMethods.linkedFile(h2GIS.getDataSource().getConnection(), path, table, delete)
- }
-
- /**
- * Create a dynamic link from a file to a H2GIS database.
- *
- * @param sql connection to the database.
- * @param path The path of the file.
- * @param table The name of the table created to store the file.
- * @param delete True to delete the table if exists. Default to true.
- * @throws java.sql.SQLException Exception throw on database error.
- */
- static String linkedFile(H2GIS h2GIS, String path, boolean delete = false) throws SQLException {
- File pathFile = new File(path)
- String fileName = pathFile.name
- String name = fileName.substring(0, fileName.lastIndexOf('.'))
- return linkedFile(h2GIS, path, StringUtils.deleteWhitespace(name), delete)
- }
-
-
- /**
- * Save a table into a file
- * @param database
- * @param tableName
- * @param filePath
- * @param delete
- * @return
- */
- static boolean save(Database database, String tableName, String filePath, boolean delete = false) {
- if (database instanceof H2GIS || database instanceof PostGIS) {
- def con = database.getDataSource().getConnection()
- if (con == null) {
- LOGGER.warning("No connection, cannot save.");
- return false;
- }
- try {
- if (ioMethods == null) {
- ioMethods = new IOMethods();
- }
- ioMethods.exportToFile(con, tableName, filePath, null, delete);
- return true;
- } catch (SQLException e) {
- LOGGER.severe("Cannot import the file : " + filePath);
- }
- }
- LOGGER.warning("Unsuported method for this Database ")
- return false;
- }
-
- /**
- * Save a table into a file
- * @param database
- * @param tableName
- * @param filePath
- * @param delete
- * @return
- */
- static boolean save(Database database, String tableName, String filePath, String encoding) {
- if (database instanceof H2GIS || database instanceof PostGIS) {
- def con = database.getDataSource().getConnection()
- if (con == null) {
- LOGGER.severe("No connection, cannot save.");
- return false;
- }
- try {
- if (ioMethods == null) {
- ioMethods = new IOMethods();
- }
- ioMethods.exportToFile(con, tableName, filePath, encoding, false);
- return true;
- } catch (SQLException e) {
- LOGGER.severe("Cannot import the file : " + filePath);
- }
- }
- LOGGER.warning("Unsuported method for this Database ")
- return false;
- }
-
- /**
- * Load a file to the database
- * @param database
- * @param filePath
- * @param encoding
- * @param delete
- * @return
- */
- static String load(Database database, String filePath,
- boolean delete = false) {
- File pathFile = new File(filePath)
- String fileName = pathFile.name
- String name = fileName.substring(0, fileName.lastIndexOf('.'))
- return load(database, filePath, StringUtils.deleteWhitespace(name), null, delete)
- }
-
-
- /**
- * Load a file to the database
- * @param database
- * @param filePath
- * @param tableName
- * @param encoding
- * @param delete
- * @return
- */
- static String load(Database database, String filePath, String tableName) {
- return load(database, filePath, tableName, null,
- false)
- }
-
- /**
- * Load a file to the database
- * @param database
- * @param filePath
- * @param tableName
- * @param encoding
- * @param delete
- * @return
- */
- static String load(Database database, String filePath, String tableName,
- delete) {
- return load(database, filePath, tableName, null,
- delete)
- }
-
- /**
- * Load a file to the database
- * @param database
- * @param filePath
- * @param tableName
- * @param encoding
- * @param delete
- * @return
- */
- static String load(Database database, String filePath, String tableName, String encoding,
- boolean delete = false) {
- if (database instanceof H2GIS || database instanceof PostGIS) {
- def con = database.getDataSource().getConnection()
- if (con == null) {
- LOGGER.severe("No connection, cannot load the file $filePath.");
- return false;
- }
- try {
- if (ioMethods == null) {
- ioMethods = new IOMethods();
- }
- return ioMethods.importFile(con, filePath, tableName, encoding, delete)
- } catch (SQLException e) {
- LOGGER.severe("Cannot import the file : " + filePath);
- }
- }
- return null
- }
-}
diff --git a/src/main/groovy/geoscript/workspace/H2GISDatabaseExtensionModule.groovy b/src/main/groovy/geoscript/workspace/H2GISDatabaseExtensionModule.groovy
new file mode 100644
index 00000000..5ac3a8fa
--- /dev/null
+++ b/src/main/groovy/geoscript/workspace/H2GISDatabaseExtensionModule.groovy
@@ -0,0 +1,304 @@
+package geoscript.workspace
+
+import org.apache.commons.lang3.StringUtils
+import org.geotools.util.logging.Logging
+import org.h2gis.functions.io.utility.IOMethods
+
+import java.sql.SQLException
+import java.util.logging.Logger
+
+/**
+ * A Groovy Extension Module that adds static methods to H2GIS workspace.
+ * @author Erwan Bocher (CNRS)
+ */
+class H2GISDatabaseExtensionModule {
+ /**
+ * The Logger
+ */
+ private static final Logger LOGGER = Logging.getLogger("geoscript.workspace.H2GISDatabaseExtensionModule")
+
+ private static IOMethods ioMethods = null;
+
+ /**
+ * Create a dynamic link from a file to the H2GIS database.
+ *
+ * @param sql connection to the database.
+ * @param path The path of the file.
+ * @param table The name of the table created to store the file.
+ * @param delete True to delete the table if exists. Default to true.
+ * @throws java.sql.SQLException Exception throw on database error.
+ */
+ static String link(H2GIS h2GIS, String path, String table, boolean delete = false) throws SQLException {
+ return IOMethods.linkedFile(h2GIS.getDataSource().getConnection(), path, table, delete)
+ }
+
+ /**
+ * Create a dynamic link from a file to the H2GIS database.
+ *
+ * @param sql connection to the database.
+ * @param path The path of the file.
+ * @param table The name of the table created to store the file.
+ * @param delete True to delete the table if exists. Default to true.
+ * @throws java.sql.SQLException Exception throw on database error.
+ */
+ static String link(H2GIS h2GIS, String path, boolean delete = false) throws SQLException {
+ File pathFile = new File(path)
+ String fileName = pathFile.name
+ String name = fileName.substring(0, fileName.lastIndexOf('.'))
+ return link(h2GIS, path, StringUtils.deleteWhitespace(name), delete)
+ }
+
+ /**
+ * Link a table from an external database to a H2GIS database.
+ * Databases supported are H2 [H2GIS], PostgreSQL [PostGIS]
+ * Note : the jdb driver of the external database must be in the classpath
+ *
+ * @param sql connection to the database.
+ * @param path The path of the file.
+ * @param table The name of the table created to store the file.
+ * @param delete True to delete the table if exists. Default to true.
+ * @throws java.sql.SQLException Exception throw on database error.
+ */
+ static String link(H2GIS h2GIS, String dbname, String host, String port, String user, String password, String schema = "",
+ String table, String newTable = "", boolean delete = false,
+ int batch_size = 100) throws SQLException {
+ def properties = [:]
+ properties.put("user", user)
+ properties.put("password": password)
+ def url = "jdbc:$host"
+ if (port) {
+ url += "/$port"
+ }
+ properties.put("url": "$url/$dbname")
+ def sourceTable = table
+
+ if (schema) {
+ sourceTable = "(select * from $schema.$table)"
+ }
+ return IOMethods.linkedTable(h2GIS.getDataSource().getConnection(), properties, sourceTable, newTable ? newTable : table, delete, batch_size)
+ }
+
+ /**
+ * Save a PostGIS table into a file
+ * @param database PostGIS database
+ * @param table the name of the table
+ * @param filePath the path of the file
+ * @param delete the file is exist
+ * @param encoding encode the file is supported
+ * @return true if success
+ */
+ static boolean save(PostGIS database, String table, String filePath, boolean delete = false, String encoding = null) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.severe("No connection, cannot save.")
+ return false
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods()
+ }
+ ioMethods.exportToFile(con, "\"$table\"", filePath, encoding, delete)
+ return true;
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath)
+ }
+ return false;
+ }
+
+ /**
+ * Save an H2GIS table into a file
+ * @param database PostGIS database
+ * @param table the name of the table
+ * @param filePath the path of the file
+ * @param delete the file is exist
+ * @param encoding encode the file is supported
+ * @return true if success
+ */
+ static boolean save(H2GIS database, String table, String filePath, boolean delete = false, String encoding = null) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.severe("No connection, cannot save.");
+ return false;
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods();
+ }
+ ioMethods.exportToFile(con, "\"$table\"", filePath, encoding, delete)
+ return true;
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath)
+ }
+ return false;
+ }
+
+
+ /**
+ * Load a file to H2GIS database
+ * @param database H2GIS database
+ * @param filePath the input file path
+ * @param delete remove the table if exists
+ * @return the names of the created tables
+ */
+ static String[] load(H2GIS database, String filePath,
+ boolean delete = false) {
+ File pathFile = new File(filePath)
+ String fileName = pathFile.name
+ String name = fileName.substring(0, fileName.lastIndexOf('.'))
+ return load(database, filePath, StringUtils.deleteWhitespace(name), null, delete)
+ }
+
+ /**
+ * Load a file to PostGIS database
+ * @param database PostGIS database
+ * @param filePath the input file path
+ * @param delete remove the table if exists
+ * @return the names of the created tables
+ */
+ static String[] load(PostGIS database, String filePath,
+ boolean delete = false) {
+ File pathFile = new File(filePath)
+ String fileName = pathFile.name
+ String name = fileName.substring(0, fileName.lastIndexOf('.'))
+ return load(database, filePath, StringUtils.deleteWhitespace(name), null, delete)
+ }
+
+ /**
+ * Load a file to PostGIS database
+ * @param database PostGIS database
+ * @param filePath the input file path
+ * @param table a name for the created table
+ * @param encoding input file encoding if supported
+ * @param delete remove the table if exists
+ * @return the names of the created tables
+ */
+ static String[] load(PostGIS database, String filePath, String table, String encoding = null,
+ boolean delete = false) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.severe("No connection, cannot load the file $filePath.");
+ return false;
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods();
+ }
+ return ioMethods.importFile(con, filePath, table, encoding, delete)
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath);
+ }
+ return null
+ }
+
+ /**
+ * Load a file to H2GIS database
+ * @param database H2GIS database
+ * @param filePath the input file path
+ * @param table a name for the created table
+ * @param encoding input file encoding if supported
+ * @param delete remove the table if exists
+ * @return the names of the created tables
+ */
+ static String[] load(H2GIS database, String filePath, String table, String encoding = null,
+ boolean delete = false) {
+ def con = database.getDataSource().getConnection()
+ if (con == null) {
+ LOGGER.severe("No connection, cannot load the file $filePath.");
+ return false;
+ }
+ try {
+ if (ioMethods == null) {
+ ioMethods = new IOMethods();
+ }
+ return ioMethods.importFile(con, filePath, table, encoding, delete)
+ } catch (SQLException e) {
+ LOGGER.severe("Cannot import the file : " + filePath);
+ }
+ return null
+ }
+
+ /**
+ * Load a table from an external database to H2GIS
+ *
+ * @param h2GIS database
+ * @param database destination database connection
+ * @param table the name of the table to export or a select query
+ * @param newTable target table name
+ * @param mode -1 delete the target table if exists and create a new table,
+ * 0 create a new table, 1 update the target table if exists
+ * @param batch_size batch size value before sending the data
+ * @return the name of the created table
+ */
+ static String load(H2GIS h2GIS, Database database, String table, int mode = 0, int batch_size = 100) {
+ return IOMethods.exportToDataBase(database.getDataSource().getConnection(),
+ "\"$table\"", h2GIS.getDataSource().getConnection(), "\"$table\"", mode, batch_size)
+ }
+ /**
+ * Load a table from an external database to H2GIS
+ *
+ * @param h2GIS database
+ * @param database destination database connection
+ * @param table the name of the table to export or a select query
+ * @param newTable target table name
+ * @param mode -1 delete the target table if exists and create a new table,
+ * 0 create a new table, 1 update the target table if exists
+ * @param batch_size batch size value before sending the data
+ * @return the name of the created table
+ */
+ static String load(H2GIS h2GIS, Database database, String table, String newTable , int mode = 0, int batch_size = 100) {
+ return IOMethods.exportToDataBase(database.getDataSource().getConnection(),
+ table, h2GIS.getDataSource().getConnection(), newTable ? newTable : table, mode, batch_size)
+ }
+
+
+ /**
+ * Save a table to an external database
+ * @param h2GIS database
+ * @param database destination database connection
+ * @param table the name of the table to export or a select query
+ * @param newTable target table name
+ * @param mode -1 delete the target table if exists and create a new table,
+ * 0 create a new table, 1 update the target table if exists
+ * @param batch_size batch size value before sending the data
+ * @return the name of the created table
+ */
+ static String save(H2GIS h2GIS, Database database, String table, String newTable, boolean delete=false, int batch_size =100) {
+ //The save method support select when the user set the table with '(select * from mytable)'
+ if(!table.startsWith("(")){
+ //Escapte the table name because it's not a query
+ table = "\"$table\""
+ }
+ return IOMethods.exportToDataBase(h2GIS.getDataSource().getConnection(),
+ table, database.getDataSource().getConnection(), "\"$newTable\"", delete?-1:0, batch_size)
+ }
+
+ /**
+ * Save a table to an external database
+ * @param h2GIS database
+ * @param database destination database connection
+ * @param table the name of the table to export
+ * @param newTable target table name
+ * @param delete true to delete the existing table
+ * @param batch_size batch size value before sending the data
+ * @return the name of the created table
+ */
+ static String save(H2GIS h2GIS, Database database, String table, boolean delete=false, int batch_size =100) {
+ return IOMethods.exportToDataBase(h2GIS.getDataSource().getConnection(),
+ "\"$table\"", database.getDataSource().getConnection(), "\"$table\"", delete?-1:0, batch_size)
+ }
+
+ /**
+ * Insert to an existing table stored in an external database
+ * @param h2GIS database
+ * @param database destination database connection
+ * @param table the name of the table to export
+ * @param newTable target table name
+ * @param batch_size batch size value before sending the data
+ * @return the name of the created table
+ */
+ static String insert(H2GIS h2GIS, Database database, String table, int batch_size =100) {
+ return IOMethods.exportToDataBase(h2GIS.getDataSource().getConnection(),
+ "\"$table\"", database.getDataSource().getConnection(), "\"$table\"", 1, batch_size)
+ }
+
+}
diff --git a/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
index 2a3b1b2b..b17c7af0 100644
--- a/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
+++ b/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
@@ -1,4 +1,4 @@
moduleName = geoscript-groovy-module
moduleVersion = 1.0
-extensionClasses = geoscript.geom.io.GeometryExtensionModule, geoscript.feature.io.FeatureExtensionModule, geoscript.layer.io.LayerExtensionModule, geoscript.layer.io.PyramidExtensionModule, geoscript.layer.WMSMapExtensionModule, geoscript.style.io.StyleExtensionModule,geoscript.workspace.DatabaseExtensionModule
+extensionClasses = geoscript.geom.io.GeometryExtensionModule, geoscript.feature.io.FeatureExtensionModule, geoscript.layer.io.LayerExtensionModule, geoscript.layer.io.PyramidExtensionModule, geoscript.layer.WMSMapExtensionModule, geoscript.style.io.StyleExtensionModule,geoscript.workspace.H2GISDatabaseExtensionModule
staticExtensionClasses = geoscript.geom.io.StaticGeometryExtensionModule, geoscript.feature.io.StaticFeatureExtensionModule, geoscript.plot.ViewerExtensionModule, geoscript.layer.io.StaticPyramidExtensionModule, geoscript.style.io.StaticStyleExtensionModule
\ No newline at end of file
diff --git a/src/test/groovy/geoscript/workspace/H2GISTest.groovy b/src/test/groovy/geoscript/workspace/H2GISTest.groovy
index 4623bf5c..810ce8cd 100644
--- a/src/test/groovy/geoscript/workspace/H2GISTest.groovy
+++ b/src/test/groovy/geoscript/workspace/H2GISTest.groovy
@@ -3,8 +3,15 @@ package geoscript.workspace
import geoscript.feature.Field
import geoscript.geom.Point
import geoscript.layer.Layer
+import geoscript.proj.Projection
+import geoscript.render.Map
+import geoscript.style.Fill
+import geoscript.style.Stroke
+import geoscript.style.Symbolizer
+import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
+import static geoscript.render.Draw.*
import static org.junit.jupiter.api.Assertions.*
@@ -19,8 +26,25 @@ class H2GISTest {
@Test void loadShapeFile() {
H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
File file = new File(getClass().getClassLoader().getResource("states.shp").toURI())
- String tableName = h2gis.load(file.getAbsolutePath(), true)
- println(tableName)
+ def tableName = h2gis.load(file.getAbsolutePath(), true)
+ assertEquals("STATES", tableName[0])
+ Layer layer = h2gis.get("STATES")
+ assertEquals(49, layer.getCount())
+ def minMax = layer.minmax("SAMP_POP")
+ assertEquals 72696.0, minMax.min, 0.1
+ assertEquals 3792553.0, minMax.max, 0.1
+ }
+
+ @Test void linkShapeFile() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ File file = new File(getClass().getClassLoader().getResource("states.shp").toURI())
+ def tableName = h2gis.link(file.getAbsolutePath(), true)
+ assertEquals("states", tableName)
+ Layer layer = h2gis.get("STATES")
+ assertEquals(49, layer.getCount())
+ def minMax = layer.minmax("SAMP_POP")
+ assertEquals 72696.0, minMax.min, 0.1
+ assertEquals 3792553.0, minMax.max, 0.1
}
@Test void remove() {
@@ -48,7 +72,7 @@ class H2GISTest {
}
@Test void createFromPath() {
- H2GIS h2gis = new H2GIS("./target/mydb")
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
assertEquals "H2GIS", h2gis.format
Layer l = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
assertNotNull(l)
@@ -60,7 +84,7 @@ class H2GISTest {
}
@Test void writeLinkShapeFile() {
- H2GIS h2gis = new H2GIS("./target/mydb")
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
assertEquals "H2GIS", h2gis.format
Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
@@ -69,15 +93,90 @@ class H2GISTest {
layer.add([new Point(2,2), "two"])
layer.add([new Point(3,3), "three"])
assertEquals 3, layer.count()
- File outputFile = new File("./target/widgets.shp")
- h2gis.save("widgets", outputFile.getAbsolutePath())
- def outputTable = h2gis.linkedFile(outputFile.getAbsolutePath(), true)
+ File outputFile = new File(folder, "widgets.shp")
+ h2gis.save("widgets", outputFile.getAbsolutePath(), true)
+ def outputTable = h2gis.link(outputFile.getAbsolutePath(), true)
assertEquals(3, h2gis.get(outputTable).count)
h2gis.close()
}
@Test void writeSaveLoadShapeFile() {
- H2GIS h2gis = new H2GIS("./target/mydb")
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
+ assertEquals "H2GIS", h2gis.format
+ Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(layer)
+ layer.add([new Point(1,1), "one"])
+ layer.add([new Point(2,2), "two"])
+ layer.add([new Point(3,3), "three"])
+ assertEquals 3, layer.count()
+ File outputFile = new File(folder, "widgets.shp")
+ h2gis.save(layer.getName(), outputFile.getAbsolutePath(), true)
+ def outputTable = h2gis.load(outputFile.getAbsolutePath(), "test_imported")
+ assertEquals(3, h2gis.get(outputTable[0]).count)
+ h2gis.close()
+ }
+
+ @Test void loadFromDatabase() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ H2GIS h2gis_target = new H2GIS(new File(folder,"h2gis_target.db"))
+ h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
+ assertEquals "H2GIS", h2gis.format
+ Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(layer)
+ layer.add([new Point(1,1), "one"])
+ layer.add([new Point(2,2), "two"])
+ layer.add([new Point(3,3), "three"])
+ assertEquals 3, layer.count()
+ h2gis_target.load(h2gis, layer.getName(), -1)
+ Layer target_Layer = h2gis_target.get(layer.getName())
+ assertNotNull(target_Layer)
+ assertEquals 3, target_Layer.count()
+ h2gis.close()
+ h2gis_target.close()
+ }
+
+ @Test void saveToDatabase() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ H2GIS h2gis_target = new H2GIS(new File(folder,"h2gis_target.db"))
+ h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
+ assertEquals "H2GIS", h2gis.format
+ Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(layer)
+ layer.add([new Point(1,1), "one"])
+ layer.add([new Point(2,2), "two"])
+ layer.add([new Point(3,3), "three"])
+ assertEquals 3, layer.count()
+ h2gis.save(h2gis_target,layer.getName(), true)
+ Layer target_Layer = h2gis_target.get(layer.getName())
+ assertNotNull(target_Layer)
+ assertEquals 3, target_Layer.count()
+ h2gis.close()
+ h2gis_target.close()
+ }
+
+ @Test void saveQueryToDatabase() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ H2GIS h2gis_target = new H2GIS(new File(folder,"h2gis_target.db"))
+ h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
+ assertEquals "H2GIS", h2gis.format
+ Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
+ assertNotNull(layer)
+ layer.add([new Point(1,1), "one"])
+ layer.add([new Point(2,2), "two"])
+ layer.add([new Point(3,3), "three"])
+ assertEquals 3, layer.count()
+ h2gis.save(h2gis_target,"(SELECT * FROM \"${layer.getName()}\" WHERE \"name\"= 'two')", "output_layer", true)
+ Layer target_Layer = h2gis_target.get("output_layer")
+ assertNotNull(target_Layer)
+ assertEquals 1, target_Layer.count()
+ h2gis.close()
+ h2gis_target.close()
+ }
+
+ @Test void saveAndInsertToDatabase() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ H2GIS h2gis_target = new H2GIS(new File(folder,"h2gis_target.db"))
h2gis.getSql().execute("drop table if exists \"widgets\"".toString())
assertEquals "H2GIS", h2gis.format
Layer layer = h2gis.create('widgets',[new Field("geom", "Point"), new Field("name", "String")])
@@ -86,11 +185,40 @@ class H2GISTest {
layer.add([new Point(2,2), "two"])
layer.add([new Point(3,3), "three"])
assertEquals 3, layer.count()
- File outputFile = new File("./target/widgets.shp")
- h2gis.save("widgets", outputFile.getAbsolutePath())
- def outputTable = h2gis.load(outputFile.getAbsolutePath(), "\"test_imported\"")
- assertEquals(3, h2gis.get("test_imported").count)
+ h2gis.save(h2gis_target,layer.getName(), true)
+ Layer target_Layer = h2gis_target.get(layer.getName())
+ assertNotNull(target_Layer)
+ assertEquals 3, target_Layer.count()
+ h2gis.insert(h2gis_target,layer.getName())
+ target_Layer = h2gis_target.get(layer.getName())
+ assertNotNull(target_Layer)
+ assertEquals 6, target_Layer.count()
h2gis.close()
+ h2gis_target.close()
}
+ @Disabled
+ //TODO the map is weel rendered but there is an error message on org.geotools.renderer.lite.StreamingRenderer getStyleQuery
+ @Test void drawLinkedShapeFile() {
+ H2GIS h2gis = new H2GIS(new File(folder,"h2gis.db"))
+ File file = new File(getClass().getClassLoader().getResource("states.shp").toURI())
+ def tableName = h2gis.link(file.getAbsolutePath(), true)
+ assertEquals("states", tableName)
+ Layer layer = h2gis.get("STATES")
+ Symbolizer symbolizer = new Fill("gray") + new Stroke("#ffffff")
+ layer.setStyle(symbolizer)
+ layer.setProj(new Projection("EPSG:2927"))
+ Map map = new Map()
+ map.proj = new Projection("EPSG:2927")
+ map.addLayer(layer)
+ map.bounds = layer.bounds
+ def image = map.renderToImage()
+ assertNotNull(image)
+
+ File out = new File(folder,"map.png")
+ javax.imageio.ImageIO.write(image, "png", out);
+ assertTrue(out.exists())
+ map.close()
+ h2gis.close()
+ }
}