diff --git a/bdtopo_v2/pom.xml b/bdtopo_v2/pom.xml index 2266ddc748..f8f926d760 100644 --- a/bdtopo_v2/pom.xml +++ b/bdtopo_v2/pom.xml @@ -60,8 +60,8 @@ slf4j-api - org.slf4j - slf4j-simple + ch.qos.logback + logback-classic diff --git a/bdtopo_v2/src/main/groovy/org/orbisgis/geoclimate/bdtopo_v2/BDTopo_V2.groovy b/bdtopo_v2/src/main/groovy/org/orbisgis/geoclimate/bdtopo_v2/BDTopo_V2.groovy index 97a9ece26f..559f66f87a 100644 --- a/bdtopo_v2/src/main/groovy/org/orbisgis/geoclimate/bdtopo_v2/BDTopo_V2.groovy +++ b/bdtopo_v2/src/main/groovy/org/orbisgis/geoclimate/bdtopo_v2/BDTopo_V2.groovy @@ -1,19 +1,24 @@ package org.orbisgis.geoclimate.bdtopo_v2 +import ch.qos.logback.classic.Logger import org.locationtech.jts.geom.Envelope import org.locationtech.jts.geom.Geometry import org.orbisgis.geoclimate.geoindicators.WorkflowUtilities import org.orbisgis.process.GroovyProcessFactory import org.slf4j.LoggerFactory - /** * Class to manage and access to the BDTOPO processes * */ abstract class BDTopo_V2 extends GroovyProcessFactory { - public static def logger = LoggerFactory.getLogger(BDTopo_V2.class) + public static Logger logger + + BDTopo_V2(){ + logger = LoggerFactory.getLogger(BDTopo_V2.class) + WorkflowUtilities.setLoggerLevel("INFO") + } public static WorkflowBDTopo_V2 = new WorkflowBDTopo_V2() public static InputDataLoading = new InputDataLoading() diff --git a/geoclimate/pom.xml b/geoclimate/pom.xml index 086948ce5f..a6f1ac5adf 100644 --- a/geoclimate/pom.xml +++ b/geoclimate/pom.xml @@ -89,14 +89,16 @@ org.orbisgis.geoclimate osmtools + org.slf4j slf4j-api - org.slf4j - slf4j-simple + ch.qos.logback + logback-classic + org.junit.jupiter diff --git a/geoclimate/src/main/groovy/org/orbisgis/geoclimate/Geoclimate.groovy b/geoclimate/src/main/groovy/org/orbisgis/geoclimate/Geoclimate.groovy index 46b0b18784..86af673e70 100644 --- a/geoclimate/src/main/groovy/org/orbisgis/geoclimate/Geoclimate.groovy +++ b/geoclimate/src/main/groovy/org/orbisgis/geoclimate/Geoclimate.groovy @@ -1,5 +1,7 @@ package org.orbisgis.geoclimate +import ch.qos.logback.classic.Logger +import org.slf4j.LoggerFactory import picocli.CommandLine import java.util.concurrent.Callable @@ -41,18 +43,18 @@ class Geoclimate implements Callable { description = "The configuration file used to set up the workflow") String configFile - @CommandLine.Option(names = ["verbose"], + @CommandLine.Option(names = ["-l"], required = false, - description = "Use it to activate the verbose") - boolean verbose + description = "Use it to manage the log level. Allowed values are : INFO, DEBUG, TRACE, OFF\"\n ") + String verbose @Override Integer call() { if (verbose) { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "INFO") + Geoindicators.WorkflowUtilities.setLoggerLevel(verbose.trim()) } else { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "OFF") + Geoindicators.WorkflowUtilities.setLoggerLevel("INFO") } if (workflow.trim().equalsIgnoreCase("OSM")) { println("The OSM workflow has been started.\nPlease wait...") diff --git a/geoclimate/src/test/groovy/org/orbisgis/geoclimate/GeoclimateTest.groovy b/geoclimate/src/test/groovy/org/orbisgis/geoclimate/GeoclimateTest.groovy index 3bb1de0aa5..f33af119e2 100644 --- a/geoclimate/src/test/groovy/org/orbisgis/geoclimate/GeoclimateTest.groovy +++ b/geoclimate/src/test/groovy/org/orbisgis/geoclimate/GeoclimateTest.groovy @@ -35,7 +35,9 @@ class GeoclimateTest { assert 2 == exitCode exitCode = cmd.execute("-w osm", "-f /tmp/conf.json") assert 1 == exitCode - exitCode = cmd.execute("-w osm", "-f /tmp/conf.json", "verbose") + exitCode = cmd.execute("-w osm", "-f /tmp/conf.json", "-l") + assert 2 == exitCode + exitCode = cmd.execute("-w osm", "-f /tmp/conf.json", "-l debug") assert 1 == exitCode } @@ -78,7 +80,7 @@ class GeoclimateTest { def cmd = new CommandLine(app) def sw = new StringWriter() cmd.setOut(new PrintWriter(sw)) - def exitCode = cmd.execute("-w osm", "-f $configFile") + def exitCode = cmd.execute("-w osm", "-f $configFile", "-l info") assert 0 == exitCode } diff --git a/geoindicators/pom.xml b/geoindicators/pom.xml index 4d6b5bf15a..15ac173d3a 100644 --- a/geoindicators/pom.xml +++ b/geoindicators/pom.xml @@ -69,8 +69,8 @@ slf4j-api - org.slf4j - slf4j-simple + ch.qos.logback + logback-classic org.codehaus.groovy diff --git a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/Geoindicators.groovy b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/Geoindicators.groovy index b8175b0510..fc1878ae03 100644 --- a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/Geoindicators.groovy +++ b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/Geoindicators.groovy @@ -1,5 +1,7 @@ package org.orbisgis.geoclimate +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.LoggerContext import org.orbisgis.geoclimate.geoindicators.BlockIndicators import org.orbisgis.geoclimate.geoindicators.BuildingIndicators import org.orbisgis.geoclimate.geoindicators.DataUtils @@ -17,7 +19,13 @@ import org.orbisgis.process.GroovyProcessFactory import org.slf4j.LoggerFactory abstract class Geoindicators extends GroovyProcessFactory { - public static def logger = LoggerFactory.getLogger(Geoindicators.class) + public static def logger + + Geoindicators(){ + logger = LoggerFactory.getLogger(Geoindicators.class) + var context = (LoggerContext) LoggerFactory.getILoggerFactory() + context.getLogger(Geoindicators.class).setLevel(Level.INFO) + } //Processes public static BuildingIndicators = new BuildingIndicators() diff --git a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy index 777ecf030b..ae763c780f 100644 --- a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy +++ b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy @@ -1,11 +1,19 @@ package org.orbisgis.geoclimate.geoindicators +import ch.qos.logback.classic.Logger +import ch.qos.logback.classic.LoggerContext +import ch.qos.logback.classic.Level import groovy.json.JsonSlurper import groovy.transform.BaseScript import org.h2gis.functions.io.utility.PRJUtil import org.orbisgis.data.H2GIS import org.orbisgis.data.POSTGIS import org.orbisgis.geoclimate.Geoindicators +import org.slf4j.LoggerFactory + +import java.util.logging.FileHandler +import java.util.logging.Handler +import java.util.logging.LogManager @BaseScript Geoindicators geoindicators @@ -14,9 +22,9 @@ import org.orbisgis.geoclimate.Geoindicators * - create a connection to a specified output DataBase * - check if specified output table names to save are allowed * - * @param outputDBProperties properties to define the db connection - * @param outputTables list of tables to save - * @parm allowedOutputTables list of supported tables + * @param outputDBProperties properties to define the db connection + * @param outputTables list of tables to save + * @parm allowedOutputTables list of supported tables * * @return a map with the allowed tables (tables) and a connection to the database (datasource) * @@ -77,8 +85,8 @@ def createDatasource(def database_properties) { /** * Method to check the output tables that can be saved * - * @param outputFolder properties to store in a folder (path and table names) - * @parm allowedOutputTables list of supported tables + * @param outputFolder properties to store in a folder (path and table names) + * @parm allowedOutputTables list of supported tables * * @return a map with the allowed tables (tables) and a connection to the database (datasource) * @@ -104,7 +112,7 @@ def buildOutputFolderParameters(def outputFolder, def allowedOutputTables) { * @param jsonFile * @return */ - Map readJSON(def jsonFile) { +Map readJSON(def jsonFile) { def jsonSlurper = new JsonSlurper() if (jsonFile) { return jsonSlurper.parse(jsonFile) @@ -157,7 +165,7 @@ def saveToAscGrid(def outputTable, def subFolder, def filePrefix, def h2gis_data //Save each grid columnNames.each { it -> - def outputFile = new File(subFolder + File.separator + filePrefix + "_"+it.toLowerCase()+".asc") + def outputFile = new File(subFolder + File.separator + filePrefix + "_" + it.toLowerCase() + ".asc") if (deleteOutputData) { outputFile.delete() } @@ -176,7 +184,7 @@ def saveToAscGrid(def outputTable, def subFolder, def filePrefix, def h2gis_data } //Save the PRJ file if (outputSRID >= 0) { - File outPrjFile = new File(subFolder + File.separator + filePrefix + "_"+it.toLowerCase()+".prj") + File outPrjFile = new File(subFolder + File.separator + filePrefix + "_" + it.toLowerCase() + ".prj") PRJUtil.writePRJ(h2gis_datasource.getConnection(), outputSRID, outPrjFile) } info "$outputTable has been saved in $outputFile" @@ -223,22 +231,24 @@ def saveToCSV(def outputTable, def filePath, def h2gis_datasource, def deleteOut } /** - * Utility class to change log level + * Utility class to change log level for all loggers * */ -def applyVerbose(String verboseOption) { - if(verboseOption){ - if (verboseOption.equalsIgnoreCase("INFO")) { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "INFO") - } - else if (verboseOption.equalsIgnoreCase("DEBUG")) { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG") - } - else if (verboseOption.equalsIgnoreCase("TRACE")) { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG") - } - else if (verboseOption.equalsIgnoreCase("OFF")) { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "OFF") +static def setLoggerLevel(String loggerLevel) { + if (loggerLevel) { + Level level + if (loggerLevel.equalsIgnoreCase("INFO")) { + level = Level.INFO + } else if (loggerLevel.equalsIgnoreCase("DEBUG")) { + level = Level.DEBUG + } else if (loggerLevel.equalsIgnoreCase("TRACE")) { + level = Level.TRACE + } else if (loggerLevel.equalsIgnoreCase("OFF")) { + level = Level.OFF + } else { + throw new RuntimeException("Invalid log level. Allowed values are : INFO, DEBUG, TRACE, OFF") } + var context = (LoggerContext) LoggerFactory.getILoggerFactory() + context.getLoggerList().each { it -> it.setLevel(level) } } } \ No newline at end of file diff --git a/geoindicators/src/test/groovy/org/orbisgis/geoclimate/geoindicators/BuildingIndicatorsTests.groovy b/geoindicators/src/test/groovy/org/orbisgis/geoclimate/geoindicators/BuildingIndicatorsTests.groovy index d827cd88d0..c21edb47fa 100644 --- a/geoindicators/src/test/groovy/org/orbisgis/geoclimate/geoindicators/BuildingIndicatorsTests.groovy +++ b/geoindicators/src/test/groovy/org/orbisgis/geoclimate/geoindicators/BuildingIndicatorsTests.groovy @@ -83,16 +83,16 @@ class BuildingIndicatorsTests { "raw_compactness", "perimeter_convexity"], prefixName : "test",datasource:h2GIS]) def concat = ["", "", "", ""] - h2GIS.eachRow("SELECT * FROM test_building_form_properties WHERE id_build = 1 OR id_build = 7 ORDER BY id_build ASC"){ + h2GIS.eachRow("SELECT * FROM test_building_form_properties WHERE id_build = 1 OR id_build = 7 ORDER BY id_build ASC".toString()){ row -> concat[0]+= "${row.area_concavity}\n" concat[1]+= "${row.form_factor.round(5)}\n" } - h2GIS.eachRow("SELECT * FROM test_building_form_properties WHERE id_build = 2 ORDER BY id_build ASC"){ + h2GIS.eachRow("SELECT * FROM test_building_form_properties WHERE id_build = 2 ORDER BY id_build ASC".toString()){ row -> concat[2]+= "${row.raw_compactness.round(3)}\n" } h2GIS.eachRow("SELECT * FROM test_building_form_properties WHERE id_build = 1 OR id_build = 7 OR " + - "id_build = 30 ORDER BY id_build ASC"){ + "id_build = 30 ORDER BY id_build ASC".toString()){ row -> concat[3]+= "${row.perimeter_convexity.round(5)}\n" } assertEquals("1.0\n0.94\n".toString(),concat[0].toString()) @@ -112,7 +112,7 @@ class BuildingIndicatorsTests { datasource:h2GIS]) def concat = "" h2GIS.eachRow("SELECT * FROM test_building_minimum_building_spacing WHERE id_build = 2 OR id_build = 4 " + - "OR id_build = 6 ORDER BY id_build ASC"){ + "OR id_build = 6 ORDER BY id_build ASC".toString()){ row -> concat+= "${row.minimum_building_spacing}\n" } assertEquals("2.0\n0.0\n7.0\n", concat) @@ -200,7 +200,7 @@ class BuildingIndicatorsTests { IProcess process = Geoindicators.BuildingIndicators.buildingPopulation() assertTrue process.execute([inputBuilding: "building", inputPopulation: "population_grid", inputPopulationColumns :["pop"],datasource: h2GIS]) - def rows = h2GIS.rows("select pop from ${process.results.buildingTableName} order by id_build") + def rows = h2GIS.rows("select pop from ${process.results.buildingTableName} order by id_build".toString()) assertEquals(5f, (float)rows[0].pop) assertEquals(5f, (float)rows[1].pop) } @@ -216,7 +216,7 @@ class BuildingIndicatorsTests { IProcess process = Geoindicators.BuildingIndicators.buildingPopulation() assertTrue process.execute([inputBuilding: "building", inputPopulation: "population_grid", inputPopulationColumns :["pop"],datasource: h2GIS]) - def rows = h2GIS.rows("select pop from ${process.results.buildingTableName} order by id_build") + def rows = h2GIS.rows("select pop from ${process.results.buildingTableName} order by id_build".toString()) assertEquals(3.33f, (float)rows[0].pop, 0.01) assertEquals(6.666f, (float)rows[1].pop, 0.01) } @@ -234,7 +234,7 @@ class BuildingIndicatorsTests { IProcess process = Geoindicators.BuildingIndicators.buildingPopulation() assertTrue process.execute([inputBuilding: "building", inputPopulation: "population_grid", inputPopulationColumns :["pop"], datasource: h2GIS]) - def rows = h2GIS.rows("select pop, id_build from ${process.results.buildingTableName} order by id_build") + def rows = h2GIS.rows("select pop, id_build from ${process.results.buildingTableName} order by id_build".toString()) assertEquals(13.33f, (float)rows[0].pop, 0.01) assertEquals(6.666f, (float)rows[1].pop, 0.01) } @@ -252,7 +252,7 @@ class BuildingIndicatorsTests { IProcess process = Geoindicators.BuildingIndicators.buildingPopulation() assertTrue process.execute([inputBuilding: "building", inputPopulation: "population_grid", inputPopulationColumns :["pop"],datasource: h2GIS]) - def rows = h2GIS.rows("select pop, id_build from ${process.results.buildingTableName} order by id_build") + def rows = h2GIS.rows("select pop, id_build from ${process.results.buildingTableName} order by id_build".toString()) assertEquals(15f, (float)rows[0].pop, 0.01) assertEquals(5f, (float)rows[1].pop, 0.01) } @@ -270,7 +270,7 @@ class BuildingIndicatorsTests { IProcess process = Geoindicators.BuildingIndicators.buildingPopulation() assertTrue process.execute([inputBuilding: "building", inputPopulation: "population_grid", inputPopulationColumns :["pop"],datasource: h2GIS]) - def rows = h2GIS.rows("select pop, id_build from ${process.results.buildingTableName} order by id_build") + def rows = h2GIS.rows("select pop, id_build from ${process.results.buildingTableName} order by id_build".toString()) assertEquals(12f, (float)rows[0].pop, 0.01) assertEquals(8f, (float)rows[1].pop, 0.01) } diff --git a/osm/pom.xml b/osm/pom.xml index 5f90bd24ec..98b29e1884 100644 --- a/osm/pom.xml +++ b/osm/pom.xml @@ -60,8 +60,8 @@ slf4j-api - org.slf4j - slf4j-simple + ch.qos.logback + logback-classic diff --git a/osm/src/main/groovy/org/orbisgis/geoclimate/osm/OSM.groovy b/osm/src/main/groovy/org/orbisgis/geoclimate/osm/OSM.groovy index 99e1947b55..3a4a3e1930 100644 --- a/osm/src/main/groovy/org/orbisgis/geoclimate/osm/OSM.groovy +++ b/osm/src/main/groovy/org/orbisgis/geoclimate/osm/OSM.groovy @@ -2,10 +2,9 @@ package org.orbisgis.geoclimate.osm import org.locationtech.jts.geom.Envelope import org.locationtech.jts.geom.Geometry -import org.orbisgis.geoclimate.Geoindicators +import org.orbisgis.geoclimate.geoindicators.WorkflowUtilities import org.orbisgis.geoclimate.osmtools.utils.Utilities import org.orbisgis.process.GroovyProcessFactory -import org.slf4j.Logger import org.slf4j.LoggerFactory /** @@ -14,7 +13,12 @@ import org.slf4j.LoggerFactory */ abstract class OSM extends GroovyProcessFactory { - public static Logger logger = LoggerFactory.getLogger(OSM.class) + public static def logger + + OSM() { + logger = LoggerFactory.getLogger(OSM.class) + WorkflowUtilities.setLoggerLevel("INFO") + } public static WorkflowOSM = new WorkflowOSM() public static InputDataLoading = new InputDataLoading() @@ -64,7 +68,7 @@ abstract class OSM extends GroovyProcessFactory { * @return */ static List bbox(Geometry geometry) { - if(geometry){ + if (geometry) { Envelope env = geometry.getEnvelopeInternal() return [env.getMinY(), env.getMinX(), env.getMaxY(), env.getMaxX()] } @@ -74,11 +78,11 @@ abstract class OSM extends GroovyProcessFactory { * Utility method to create bbox represented by a list of values : * [minY, minX, maxY, maxX] * from an envelope - * @param env JTS envelope + * @param env JTS envelope * @return */ static List bbox(Envelope env) { - if(env){ + if (env) { return [env.getMinY(), env.getMinX(), env.getMaxY(), env.getMaxX()] } } diff --git a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataLoadingTest.groovy b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataLoadingTest.groovy index ff131d341f..8e42c1068b 100644 --- a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataLoadingTest.groovy +++ b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataLoadingTest.groovy @@ -16,8 +16,6 @@ class InputDataLoadingTest { @TempDir static File folder - private static final Logger logger = LoggerFactory.getLogger(InputDataLoadingTest.class) - static H2GIS h2GIS @BeforeAll diff --git a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy index 730e6237d7..01c97a131b 100644 --- a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy +++ b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy @@ -545,7 +545,6 @@ class WorflowOSMTest extends WorkflowAbstractTest { File dirFile = new File(directory) dirFile.delete() dirFile.mkdir() - def nominatim = Utilities.getNominatimData("Pont-de-Veyle") def osm_parmeters = [ @@ -556,11 +555,11 @@ class WorflowOSMTest extends WorkflowAbstractTest { "delete" :false ], "input" : [ - "locations" : [[43.610352,1.340075,43.628279,1.376853]],//[nominatim["bbox"]], + "locations" : ["Redon"],//[nominatim["bbox"]], - "timeout":182, + /*"timeout":182, "maxsize": 536870918, - "endpoint":"https://lz4.overpass-api.de/api"], + "endpoint":"https://lz4.overpass-api.de/api"*/], "output" :[ "folder" : directory] , @@ -578,7 +577,7 @@ class WorflowOSMTest extends WorkflowAbstractTest { "LCZ_FRACTION", "LCZ_PRIMARY", "FREE_EXTERNAL_FACADE_DENSITY", "BUILDING_HEIGHT_WEIGHTED", "BUILDING_SURFACE_DENSITY", "BUILDING_HEIGHT_DIST", "FRONTAL_AREA_INDEX", "SEA_LAND_FRACTION"] - ], "worldpop_indicators" : false,*/ + ], */ "worldpop_indicators" : true, "road_traffic" : true, "noise_indicators": [ "ground_acoustic" : true diff --git a/osmtools/pom.xml b/osmtools/pom.xml index 3e7599f3d4..369be94a29 100644 --- a/osmtools/pom.xml +++ b/osmtools/pom.xml @@ -54,8 +54,8 @@ slf4j-api - org.slf4j - slf4j-simple + ch.qos.logback + logback-classic diff --git a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/OSMTools.groovy b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/OSMTools.groovy index 8e00c1e861..422440671c 100644 --- a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/OSMTools.groovy +++ b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/OSMTools.groovy @@ -36,6 +36,8 @@ */ package org.orbisgis.geoclimate.osmtools +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.LoggerContext import org.orbisgis.process.GroovyProcessFactory import org.orbisgis.geoclimate.osmtools.Loader as LOADER import org.orbisgis.geoclimate.osmtools.Transform as TRANSFORM @@ -54,9 +56,21 @@ abstract class OSMTools extends GroovyProcessFactory { def static Loader = new LOADER() def static Transform = new TRANSFORM() def static Utilities = new UTILITIES() + public static def logger - public static def logger = LoggerFactory.getLogger(OSMTools.class) - static def info = { obj -> logger.info(obj.toString()) } + OSMTools() { + logger = LoggerFactory.getLogger(OSMTools.class) + var context = (LoggerContext) LoggerFactory.getILoggerFactory() + context.getLogger(OSMTools.class).setLevel(Level.INFO) + } + + /** {@link Closure} returning a {@link String} prefix/suffix build from a random {@link UUID} with '-' replaced by '_'. */ + static def getUuid() { UUID.randomUUID().toString().replaceAll("-", "_") } + + static def uuid() { getUuid() } + + static def info = { obj -> + logger.info(obj.toString()) } static def warn = { obj -> logger.warn(obj.toString()) } static def error = { obj -> logger.error(obj.toString()) } static def debug = { obj -> logger.debug(obj.toString()) } diff --git a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/Transform.groovy b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/Transform.groovy index 4b1a9e208c..37792f7d51 100644 --- a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/Transform.groovy +++ b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/Transform.groovy @@ -40,7 +40,9 @@ import groovy.transform.BaseScript import org.orbisgis.data.jdbc.JdbcDataSource import static org.orbisgis.geoclimate.osmtools.utils.TransformUtils.* -import static org.orbisgis.geoclimate.osmtools.utils.TransformUtils.Types.* +import static org.orbisgis.process.GroovyProcessFactory.postfix +import static org.orbisgis.process.GroovyProcessFactory.prefix +import static org.orbisgis.geoclimate.osmtools.utils.GeometryTypes.* @BaseScript OSMTools pf diff --git a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/GeometryTypes.groovy b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/GeometryTypes.groovy new file mode 100644 index 0000000000..82e7e4e222 --- /dev/null +++ b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/GeometryTypes.groovy @@ -0,0 +1,45 @@ +/* + * Bundle OSMTools is part of the GeoClimate tool + * + * GeoClimate is a geospatial processing toolbox for environmental and climate studies . + * GeoClimate is developed by the GIS group of the DECIDE team of the + * Lab-STICC CNRS laboratory, see . + * + * The GIS group of the DECIDE team is located at : + * + * Laboratoire Lab-STICC – CNRS UMR 6285 + * Equipe DECIDE + * UNIVERSITÉ DE BRETAGNE-SUD + * Institut Universitaire de Technologie de Vannes + * 8, Rue Montaigne - BP 561 56017 Vannes Cedex + * + * OSMTools is distributed under LGPL 3 license. + * + * Copyright (C) 2019-2021 CNRS (Lab-STICC UMR CNRS 6285) + * + * + * OSMTools is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * OSMTools is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * OSMTools. If not, see . + * + * For more information, please consult: + * or contact directly: + * info_at_ orbisgis.org + */ +package org.orbisgis.geoclimate.osmtools.utils + +/** + * Type of geometry to transform + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + */ +enum GeometryTypes { LINES, POLYGONS +} \ No newline at end of file diff --git a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtils.groovy b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtils.groovy index da5bc60516..3ead5f9445 100644 --- a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtils.groovy +++ b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtils.groovy @@ -72,30 +72,19 @@ */ package org.orbisgis.geoclimate.osmtools.utils -import org.orbisgis.geoclimate.osmtools.OSMTools -import org.orbisgis.data.jdbc.JdbcDataSource -import org.slf4j.Logger -import org.slf4j.LoggerFactory - /** * Class containing utility methods for the {@link org.orbisgis.geoclimate.osmtools.Transform} script to keep only processes inside * the groovy script. */ -class TransformUtils { - private static Logger LOGGER = LoggerFactory.getLogger(TransformUtils) +import groovy.transform.BaseScript +import org.orbisgis.geoclimate.osmtools.OSMTools +import org.orbisgis.data.jdbc.JdbcDataSource + + +@BaseScript OSMTools pf + - /** {@link Closure} returning a {@link String} prefix/suffix build from a random {@link UUID} with '-' replaced by '_'. */ - static def getUuid() { UUID.randomUUID().toString().replaceAll("-", "_") } - static def uuid = {getUuid()} - /** {@link Closure} logging with INFO level the given {@link Object} {@link String} representation. */ - static def info = { obj -> LOGGER.info(obj.toString()) } - /** {@link Closure} logging with WARN level the given {@link Object} {@link String} representation. */ - static def warn = { obj -> LOGGER.warn(obj.toString()) } - /** {@link Closure} logging with ERROR level the given {@link Object} {@link String} representation. */ - static def error = { obj -> LOGGER.error(obj.toString()) } - /** {@link Closure} logging with DEBUG level the given {@link Object} {@link String} representation. */ - static def debug = { obj -> LOGGER.debug(obj.toString()) } /** * Merge arrays into one. @@ -129,7 +118,7 @@ class TransformUtils { * * @return The name for the table that contains all polygons/lines */ - static def toPolygonOrLine(Types type, datasource, osmTablesPrefix, epsgCode, tags, columnsToKeep, valid_geom=true) { + static def toPolygonOrLine(GeometryTypes type, datasource, osmTablesPrefix, epsgCode, tags, columnsToKeep, valid_geom=true) { //Check if parameters a good if (!datasource) { error "Please set a valid database connection" @@ -148,11 +137,11 @@ class TransformUtils { def waysProcess def relationsProcess switch (type) { - case Types.POLYGONS: + case GeometryTypes.POLYGONS: waysProcess = OSMTools.Transform.extractWaysAsPolygons() relationsProcess = OSMTools.Transform.extractRelationsAsPolygons() break - case Types.LINES: + case GeometryTypes.LINES: waysProcess = OSMTools.Transform.extractWaysAsLines() relationsProcess = OSMTools.Transform.extractRelationsAsLines() break @@ -482,5 +471,4 @@ class TransformUtils { return true } - enum Types {LINES, POLYGONS} -} + diff --git a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/Utilities.groovy b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/Utilities.groovy index 79e6df8ffe..9512d7154e 100644 --- a/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/Utilities.groovy +++ b/osmtools/src/main/groovy/org/orbisgis/geoclimate/osmtools/utils/Utilities.groovy @@ -37,11 +37,13 @@ package org.orbisgis.geoclimate.osmtools.utils import groovy.json.JsonSlurper +import groovy.transform.BaseScript +import groovy.transform.Field import org.cts.util.UTMUtils import org.h2gis.utilities.GeographyUtilities import org.locationtech.jts.geom.* import org.orbisgis.data.jdbc.JdbcDataSource -import org.slf4j.LoggerFactory +import org.orbisgis.geoclimate.osmtools.OSMTools import java.util.concurrent.TimeUnit import java.util.regex.Matcher @@ -49,762 +51,742 @@ import java.util.regex.Pattern import static java.nio.charset.StandardCharsets.UTF_8 -class Utilities { - - static def LOGGER = LoggerFactory.getLogger(Utilities) - - /** {@link Closure} returning a {@link String} prefix/suffix build from a random {@link UUID} with '-' replaced by '_'. */ - static def getUuid() { UUID.randomUUID().toString().replaceAll("-", "_") } - - static def uuid() { getUuid() } - /** {@link Closure} logging with INFO level the given {@link Object} {@link String} representation. */ - static def info(def obj) { LOGGER.info(obj.toString()) } - /** {@link Closure} logging with WARN level the given {@link Object} {@link String} representation. */ - static def warn(def obj) { LOGGER.warn(obj.toString()) } - /** {@link Closure} logging with ERROR level the given {@link Object} {@link String} representation. */ - static def error(def obj) { LOGGER.error(obj.toString()) } - /** {@link Closure} logging with DEBUG level the given {@link Object} {@link String} representation. */ - static def debug(def obj) { LOGGER.debug(obj.toString()) } - - - - /** - * Return all data from a place name with nominatim api. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param placeName The nominatim place name. - * - * @return a New geometry. - */ - static Map getNominatimData(def placeName) { - if (!placeName) { - error "The place name should not be null or empty." - return null - } - def outputOSMFile = File.createTempFile("nominatim_osm", ".geojson") - if (!executeNominatimQuery(placeName, outputOSMFile)) { - if (!outputOSMFile.delete()) { - warn "Unable to delete the file '$outputOSMFile'." - } - warn "Unable to execute the Nominatim query." - return null - } +@BaseScript OSMTools pf - def jsonRoot = new JsonSlurper().parse(outputOSMFile) - if (jsonRoot == null) { - error "Cannot find any data from the place $placeName." - return null - } - if (jsonRoot.features.size() == 0) { - error "Cannot find any features from the place $placeName." - if (!outputOSMFile.delete()) { - warn "Unable to delete the file '$outputOSMFile'." - } - return null +/** + * Return all data from a place name with nominatim api. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param placeName The nominatim place name. + * + * @return a New geometry. + */ +static Map getNominatimData(def placeName) { + if (!placeName) { + error "The place name should not be null or empty." + return null + } + def outputOSMFile = File.createTempFile("nominatim_osm", ".geojson") + if (!executeNominatimQuery(placeName, outputOSMFile)) { + if (!outputOSMFile.delete()) { + warn "Unable to delete the file '$outputOSMFile'." } + warn "Unable to execute the Nominatim query." + return null + } - GeometryFactory geometryFactory = new GeometryFactory() + def jsonRoot = new JsonSlurper().parse(outputOSMFile) + if (jsonRoot == null) { + error "Cannot find any data from the place $placeName." + return null + } - def data = [:] - jsonRoot.features.find() { feature -> - if (feature.geometry != null) { - if (feature.geometry.type.equalsIgnoreCase("polygon")) { - def area = parsePolygon(feature.geometry.coordinates, geometryFactory) - area.setSRID(4326) - data.put("geom", area) - //Add properties and extrat tags - data.putAll(feature.properties) - def bbox = feature.bbox - data.put("bbox", [bbox[1], bbox[0], bbox[3], bbox[2]]) - } else if (feature.geometry.type.equalsIgnoreCase("multipolygon")) { - def mp = feature.geometry.coordinates.collect { it -> - parsePolygon(it, geometryFactory) - }.toArray(new Polygon[0]) - def area = geometryFactory.createMultiPolygon(mp) - area.setSRID(4326) - data.put("geom", area) - //Add properties and extrat tags - data.putAll(feature.properties) - def bbox = feature.bbox - data.put("bbox", [bbox[1], bbox[0], bbox[3], bbox[2]]) - } else { - return false - } - return true - } - return false - } + if (jsonRoot.features.size() == 0) { + error "Cannot find any features from the place $placeName." if (!outputOSMFile.delete()) { warn "Unable to delete the file '$outputOSMFile'." } - return data - } - - /** - * Create a geometry from two coordinates and a distance - * Expand the geometry in x and y directions - * @param lat latitude - * @param lon longitude - * @param distance in meters - * @return - */ - static Geometry getAreaFromPoint(def lat, def lon, float distance) { - org.locationtech.jts.geom.Geometry geom = new GeometryFactory().toGeometry(GeographyUtilities.createEnvelope(new Coordinate(lat,lon), distance, distance)) - geom.setSRID(4326) - return geom - } - - /** - * Create a bbox represented by a list of values - * @param lat - * @param lon - * @param distance - * @return - */ - static List createBBox(def lat, def lon, float distance){ - Envelope env = GeographyUtilities.createEnvelope(new Coordinate(lat,lon), distance, distance) - if(env){ - return [(float)env.getMinX(),(float)env.getMinY(), (float)env.getMaxX(),(float)env.getMaxY()] - } return null } - /** - * Generic method to return one OSM polygon (area) from - * - * - a place name. e.g Redon - * - a bbox defined by an array of 4 values - * - a point and a distance defined by an array of 3 values - * - * - * @author Erwan Bocher (CNRS LAB-STICC) - * - * @param placeName The nominatim place name. - * - * @return a New geometry. - */ - static Geometry getArea(def location) { - Geometry geom - if (location in Collection) { - return Utilities.geometryFromValues(location) - } else if (location instanceof String) { - return Utilities.getNominatimData(location)["geom"] - } else { - return null; + GeometryFactory geometryFactory = new GeometryFactory() + + def data = [:] + jsonRoot.features.find() { feature -> + if (feature.geometry != null) { + if (feature.geometry.type.equalsIgnoreCase("polygon")) { + def area = parsePolygon(feature.geometry.coordinates, geometryFactory) + area.setSRID(4326) + data.put("geom", area) + //Add properties and extrat tags + data.putAll(feature.properties) + def bbox = feature.bbox + data.put("bbox", [bbox[1], bbox[0], bbox[3], bbox[2]]) + } else if (feature.geometry.type.equalsIgnoreCase("multipolygon")) { + def mp = feature.geometry.coordinates.collect { it -> + parsePolygon(it, geometryFactory) + }.toArray(new Polygon[0]) + def area = geometryFactory.createMultiPolygon(mp) + area.setSRID(4326) + data.put("geom", area) + //Add properties and extrat tags + data.putAll(feature.properties) + def bbox = feature.bbox + data.put("bbox", [bbox[1], bbox[0], bbox[3], bbox[2]]) + } else { + return false + } + return true } + return false + } + if (!outputOSMFile.delete()) { + warn "Unable to delete the file '$outputOSMFile'." + } + return data +} + +/** + * Create a geometry from two coordinates and a distance + * Expand the geometry in x and y directions + * @param lat latitude + * @param lon longitude + * @param distance in meters + * @return + */ +static Geometry getAreaFromPoint(def lat, def lon, float distance) { + org.locationtech.jts.geom.Geometry geom = new GeometryFactory().toGeometry(GeographyUtilities.createEnvelope(new Coordinate(lat, lon), distance, distance)) + geom.setSRID(4326) + return geom +} + +/** + * Create a bbox represented by a list of values + * @param lat + * @param lon + * @param distance + * @return + */ +static List createBBox(def lat, def lon, float distance) { + Envelope env = GeographyUtilities.createEnvelope(new Coordinate(lat, lon), distance, distance) + if (env) { + return [(float) env.getMinX(), (float) env.getMinY(), (float) env.getMaxX(), (float) env.getMaxY()] } + return null +} - /** - * Parse geojson coordinates to create a polygon. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param coordinates Coordinates to parse. - * @param geometryFactory Geometry factory used for the geometry creation. - * - * @return A polygon. - */ - static Polygon parsePolygon(def coordinates, GeometryFactory geometryFactory) { - if (!coordinates in Collection || !coordinates || - !coordinates[0] in Collection || !coordinates[0] || - !coordinates[0][0] in Collection || !coordinates[0][0]) { - error "The given coordinate should be an array of an array of an array of coordinates (3D array)." - return null - } - def ring - try { - ring = geometryFactory.createLinearRing(arrayToCoordinate(coordinates[0])) - } - catch (IllegalArgumentException e) { - error e.getMessage() - return null - } - if (coordinates.size() == 1) { - return geometryFactory.createPolygon(ring) - } else { - def holes = coordinates[1..coordinates.size() - 1].collect { it -> - geometryFactory.createLinearRing(arrayToCoordinate(it)) - }.toArray(new LinearRing[0]) - return geometryFactory.createPolygon(ring, holes) - } +/** + * Generic method to return one OSM polygon (area) from + * + * - a place name. e.g Redon + * - a bbox defined by an array of 4 values + * - a point and a distance defined by an array of 3 values + * + * + * @author Erwan Bocher (CNRS LAB-STICC) + * + * @param placeName The nominatim place name. + * + * @return a New geometry. + */ +static Geometry getArea(def location) { + Geometry geom + if (location in Collection) { + return Utilities.geometryFromValues(location) + } else if (location instanceof String) { + return Utilities.getNominatimData(location)["geom"] + } else { + return null; } +} - /** - * Convert and array of numeric coordinates into of an array of {@link Coordinate}. - * - * @param coordinates Array of array of numeric value (array of numeric coordinates) - * - * @return Array of {@link Coordinate}. - */ - static Coordinate[] arrayToCoordinate(def coordinates) { - coordinates.collect { it -> - if (it.size() == 2) { - def (x, y) = it - new Coordinate(x, y) - } else if (it.size() == 3) { - def (x, y, z) = it - new Coordinate(x, y, z) - } - }.findAll { it != null }.toArray(new Coordinate[0]) - } - - /** - * Method to execute an Nominatim query and save the result in a file. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param query The Nominatim query. - * @param outputNominatimFile The output file. - * - * @return True if the file has been downloaded, false otherwise. - * - */ - static boolean executeNominatimQuery(def query, def outputOSMFile) { - if (!query) { - error "The Nominatim query should not be null." - return false - } - if (!(outputOSMFile instanceof File)) { - error "The OSM file should be an instance of File" - return false - } - def endPoint = System.getProperty("NOMINATIM_ENPOINT"); - if(!endPoint){ - /** nominatim server endpoint as defined by WSDL2 definition */ - endPoint="https://nominatim.openstreetmap.org/"; - } +/** + * Parse geojson coordinates to create a polygon. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param coordinates Coordinates to parse. + * @param geometryFactory Geometry factory used for the geometry creation. + * + * @return A polygon. + */ +static Polygon parsePolygon(def coordinates, GeometryFactory geometryFactory) { + if (!coordinates in Collection || !coordinates || + !coordinates[0] in Collection || !coordinates[0] || + !coordinates[0][0] in Collection || !coordinates[0][0]) { + error "The given coordinate should be an array of an array of an array of coordinates (3D array)." + return null + } + def ring + try { + ring = geometryFactory.createLinearRing(arrayToCoordinate(coordinates[0])) + } + catch (IllegalArgumentException e) { + error e.getMessage() + return null + } + if (coordinates.size() == 1) { + return geometryFactory.createPolygon(ring) + } else { + def holes = coordinates[1..coordinates.size() - 1].collect { it -> + geometryFactory.createLinearRing(arrayToCoordinate(it)) + }.toArray(new LinearRing[0]) + return geometryFactory.createPolygon(ring, holes) + } +} - def apiUrl = "${endPoint}search?q=" - def request = "&limit=5&format=geojson&polygon_geojson=1&extratags=1" - - URL url = new URL(apiUrl + Utilities.utf8ToUrl(query) + request) - final String proxyHost = System.getProperty("http.proxyHost"); - final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); - - def connection - if (proxyHost != null) { - def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost,proxyPort )); - connection = url.openConnection(proxy) as HttpURLConnection - } else { - connection = url.openConnection() - } - connection.requestMethod = "GET" - def user_agent = System.getProperty("OVERPASS_USER_AGENT") - if(!user_agent){ - user_agent = OSM_USER_AGENT - } - connection.setRequestProperty("User-Agent", user_agent) +/** + * Convert and array of numeric coordinates into of an array of {@link Coordinate}. + * + * @param coordinates Array of array of numeric value (array of numeric coordinates) + * + * @return Array of {@link Coordinate}. + */ +static Coordinate[] arrayToCoordinate(def coordinates) { + coordinates.collect { it -> + if (it.size() == 2) { + def (x, y) = it + new Coordinate(x, y) + } else if (it.size() == 3) { + def (x, y, z) = it + new Coordinate(x, y, z) + } + }.findAll { it != null }.toArray(new Coordinate[0]) +} + +/** + * Method to execute an Nominatim query and save the result in a file. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param query The Nominatim query. + * @param outputNominatimFile The output file. + * + * @return True if the file has been downloaded, false otherwise. + * + */ +static boolean executeNominatimQuery(def query, def outputOSMFile) { + if (!query) { + error "The Nominatim query should not be null." + return false + } + if (!(outputOSMFile instanceof File)) { + error "The OSM file should be an instance of File" + return false + } + def endPoint = System.getProperty("NOMINATIM_ENPOINT"); + if (!endPoint) { + /** nominatim server endpoint as defined by WSDL2 definition */ + endPoint = "https://nominatim.openstreetmap.org/"; + } - connection.connect() + def apiUrl = "${endPoint}search?q=" + def request = "&limit=5&format=geojson&polygon_geojson=1&extratags=1" - debug url - debug "Executing query... $query" - //Save the result in a file - if (connection.responseCode == 200) { - info "Downloading the Nominatim data." - outputOSMFile << connection.inputStream - return true - } else { - error "Cannot execute the Nominatim query." - return false - } + URL url = new URL(apiUrl + Utilities.utf8ToUrl(query) + request) + final String proxyHost = System.getProperty("http.proxyHost"); + final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); + + def connection + if (proxyHost != null) { + def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); + connection = url.openConnection(proxy) as HttpURLConnection + } else { + connection = url.openConnection() } + connection.requestMethod = "GET" + def user_agent = System.getProperty("OVERPASS_USER_AGENT") + if (!user_agent) { + user_agent = OSM_USER_AGENT + } + connection.setRequestProperty("User-Agent", user_agent) - /** - * Extract the OSM bbox signature from a Geometry. - * e.g. (bbox:"50.7 7.1 50.7 7.12 50.71 7.11") - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param geometry Input geometry. - * - * @return OSM bbox. - */ - static String toBBox(Geometry geometry) { - if (!geometry) { - error "Cannot convert to an overpass bounding box." - return null - } - def env = geometry.getEnvelopeInternal() - return "(bbox:${env.getMinY()},${env.getMinX()},${env.getMaxY()},${env.getMaxX()})".toString() - } - - /** - * Extract the OSM poly signature from a Geometry - * e.g. (poly:"50.7 7.1 50.7 7.12 50.71 7.11") - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param geometry Input geometry. - * - * @return The OSM polygon. - */ - static String toPoly(Geometry geometry) { - if (!geometry) { - error "Cannot convert to an overpass poly filter." - return null - } - if (!(geometry instanceof Polygon)) { - error "The input geometry must be polygon." - return null - } - def poly = (Polygon) geometry - if (poly.isEmpty()) { - error "The input geometry must be polygon." - return null - } - Coordinate[] coordinates = poly.getExteriorRing().getCoordinates() - def polyStr = "(poly:\"" - for (i in 0..coordinates.size() - 3) { - def coord = coordinates[i] - polyStr += "${coord.getY()} ${coord.getX()} " - } - def coord = coordinates[coordinates.size() - 2] - polyStr += "${coord.getY()} ${coord.getX()}" - return polyStr + "\")" - } - - /** - * Method to build a valid OSM query with a bbox. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param envelope The envelope to filter. - * @param keys A list of OSM keys. - * @param osmElement A list of OSM elements to build the query (node, way, relation). - * - * @return A string representation of the OSM query. - */ - static String buildOSMQuery(Envelope envelope, def keys, OSMElement... osmElement) { - if (!envelope) { - error "Cannot create the overpass query from the bbox $envelope." - return null - } - def query = "[bbox:${envelope.getMinY()},${envelope.getMinX()},${envelope.getMaxY()},${envelope.getMaxX()}];\n(\n" - osmElement.each { i -> - if (keys == null || keys.isEmpty()) { - query += "\t${i.toString().toLowerCase()};\n" - } else { - keys.each { - query += "\t${i.toString().toLowerCase()}[\"${it.toLowerCase()}\"];\n" - } - } - } - query += ");\n(._;>;);\nout;" - return query - } - - /** - * Method to build a valid OSM query with a bbox to - * download all the osm data concerning - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param envelope The envelope to filter. - * @param keys A list of OSM keys. - * @param osmElement A list of OSM elements to build the query (node, way, relation). - * - * @return A string representation of the OSM query. - */ - static String buildOSMQueryWithAllData(Envelope envelope, def keys, OSMElement... osmElement) { - if (!envelope) { - error "Cannot create the overpass query from the bbox $envelope." - return null - } - def query = "[bbox:${envelope.getMinY()},${envelope.getMinX()},${envelope.getMaxY()},${envelope.getMaxX()}];\n((\n" - osmElement.each { i -> - if (keys == null || keys.isEmpty()) { - query += "\t${i.toString().toLowerCase()};\n" - } else { - keys.each { - query += "\t${i.toString().toLowerCase()}[\"${it.toLowerCase()}\"];\n" - } - } - } - query += ");\n>;);\nout;" - return query - } - - /** - * Method to build a valid and optimized OSM query - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param polygon The polygon to filter. - * @param keys A list of OSM keys. - * @param osmElement A list of OSM elements to build the query (node, way, relation). - * - * @return A string representation of the OSM query. - */ - static String buildOSMQuery(Polygon polygon, def keys, OSMElement... osmElement) { - if (polygon == null) { - error "Cannot create the overpass query from a null polygon." - return null - } - if (polygon.isEmpty()) { - error "Cannot create the overpass query from an empty polygon." - return null - } - Envelope envelope = polygon.getEnvelopeInternal() - def query = "[bbox:${envelope.getMinY()},${envelope.getMinX()},${envelope.getMaxY()},${envelope.getMaxX()}];\n(\n" - String filterArea = toPoly(polygon) - def nokeys = false; - osmElement.each { i -> - if (keys == null || keys.isEmpty()) { - query += "\t${i.toString().toLowerCase()}$filterArea;\n" - nokeys = true - } else { - keys.each { - query += "\t${i.toString().toLowerCase()}[\"${it.toLowerCase()}\"]$filterArea;\n" - nokeys = false - } + connection.connect() + + debug url + debug "Executing query... $query" + //Save the result in a file + if (connection.responseCode == 200) { + info "Downloading the Nominatim data." + outputOSMFile << connection.inputStream + return true + } else { + error "Cannot execute the Nominatim query." + return false + } +} + +/** + * Extract the OSM bbox signature from a Geometry. + * e.g. (bbox:"50.7 7.1 50.7 7.12 50.71 7.11") + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param geometry Input geometry. + * + * @return OSM bbox. + */ +static String toBBox(Geometry geometry) { + if (!geometry) { + error "Cannot convert to an overpass bounding box." + return null + } + def env = geometry.getEnvelopeInternal() + return "(bbox:${env.getMinY()},${env.getMinX()},${env.getMaxY()},${env.getMaxX()})".toString() +} + +/** + * Extract the OSM poly signature from a Geometry + * e.g. (poly:"50.7 7.1 50.7 7.12 50.71 7.11") + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param geometry Input geometry. + * + * @return The OSM polygon. + */ +static String toPoly(Geometry geometry) { + if (!geometry) { + error "Cannot convert to an overpass poly filter." + return null + } + if (!(geometry instanceof Polygon)) { + error "The input geometry must be polygon." + return null + } + def poly = (Polygon) geometry + if (poly.isEmpty()) { + error "The input geometry must be polygon." + return null + } + Coordinate[] coordinates = poly.getExteriorRing().getCoordinates() + def polyStr = "(poly:\"" + for (i in 0..coordinates.size() - 3) { + def coord = coordinates[i] + polyStr += "${coord.getY()} ${coord.getX()} " + } + def coord = coordinates[coordinates.size() - 2] + polyStr += "${coord.getY()} ${coord.getX()}" + return polyStr + "\")" +} + +/** + * Method to build a valid OSM query with a bbox. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param envelope The envelope to filter. + * @param keys A list of OSM keys. + * @param osmElement A list of OSM elements to build the query (node, way, relation). + * + * @return A string representation of the OSM query. + */ +static String buildOSMQuery(Envelope envelope, def keys, OSMElement... osmElement) { + if (!envelope) { + error "Cannot create the overpass query from the bbox $envelope." + return null + } + def query = "[bbox:${envelope.getMinY()},${envelope.getMinX()},${envelope.getMaxY()},${envelope.getMaxX()}];\n(\n" + osmElement.each { i -> + if (keys == null || keys.isEmpty()) { + query += "\t${i.toString().toLowerCase()};\n" + } else { + keys.each { + query += "\t${i.toString().toLowerCase()}[\"${it.toLowerCase()}\"];\n" } } - if (nokeys) { - query += ");\nout;" + } + query += ");\n(._;>;);\nout;" + return query +} + +/** + * Method to build a valid OSM query with a bbox to + * download all the osm data concerning + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param envelope The envelope to filter. + * @param keys A list of OSM keys. + * @param osmElement A list of OSM elements to build the query (node, way, relation). + * + * @return A string representation of the OSM query. + */ +static String buildOSMQueryWithAllData(Envelope envelope, def keys, OSMElement... osmElement) { + if (!envelope) { + error "Cannot create the overpass query from the bbox $envelope." + return null + } + def query = "[bbox:${envelope.getMinY()},${envelope.getMinX()},${envelope.getMaxY()},${envelope.getMaxX()}];\n((\n" + osmElement.each { i -> + if (keys == null || keys.isEmpty()) { + query += "\t${i.toString().toLowerCase()};\n" } else { - query += ");\n(._;>;);\nout;" + keys.each { + query += "\t${i.toString().toLowerCase()}[\"${it.toLowerCase()}\"];\n" + } } + } + query += ");\n>;);\nout;" + return query +} - return query - } - - /** - * Parse a json file to a Map. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param jsonFile JSON file to parse. - * - * @return A Map of parameters. - */ - static Map readJSONParameters(def jsonFile) { - if (!jsonFile) { - error "The given file should not be null" - return null - } - def file - if (jsonFile instanceof InputStream) { - file = jsonFile +/** + * Method to build a valid and optimized OSM query + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param polygon The polygon to filter. + * @param keys A list of OSM keys. + * @param osmElement A list of OSM elements to build the query (node, way, relation). + * + * @return A string representation of the OSM query. + */ +static String buildOSMQuery(Polygon polygon, def keys, OSMElement... osmElement) { + if (polygon == null) { + error "Cannot create the overpass query from a null polygon." + return null + } + if (polygon.isEmpty()) { + error "Cannot create the overpass query from an empty polygon." + return null + } + Envelope envelope = polygon.getEnvelopeInternal() + def query = "[bbox:${envelope.getMinY()},${envelope.getMinX()},${envelope.getMaxY()},${envelope.getMaxX()}];\n(\n" + String filterArea = toPoly(polygon) + def nokeys = false; + osmElement.each { i -> + if (keys == null || keys.isEmpty()) { + query += "\t${i.toString().toLowerCase()}$filterArea;\n" + nokeys = true } else { - file = new File(jsonFile) - if (!file.exists()) { - warn "No file named ${jsonFile} doesn't exists." - return null - } - if (!file.isFile()) { - warn "No file named ${jsonFile} found." - return null + keys.each { + query += "\t${i.toString().toLowerCase()}[\"${it.toLowerCase()}\"]$filterArea;\n" + nokeys = false } } - def parsed = new JsonSlurper().parse(file) - if (parsed in Map) { - return parsed - } - error "The json file doesn't contains only parameter." - } - - /** - * This method is used to build a new geometry from the following input parameters : - * min Longitude , min Latitude , max Longitude , max Latitude - * - * @author Erwan Bocher (CNRS LAB-STICC) - * - * @param bbox 4 values - * @return a JTS polygon - * - */ - static Geometry buildGeometry(def bbox) { - if (!bbox) { - error "The BBox should not be null" - return null - } - if (!bbox.class.isArray() && !(bbox instanceof Collection)) { - error "The BBox should be an array" - return null - } - if (bbox.size() != 4) { - error "The BBox should be an array of 4 values" - return null - } - def minLong = bbox[0] - def minLat = bbox[1] - def maxLong = bbox[2] - def maxLat = bbox[3] - //Check values - if (UTMUtils.isValidLatitude(minLat) && UTMUtils.isValidLatitude(maxLat) - && UTMUtils.isValidLongitude(minLong) && UTMUtils.isValidLongitude(maxLong)) { - GeometryFactory geometryFactory = new GeometryFactory() - Geometry geom = geometryFactory.toGeometry(new Envelope(minLong, maxLong, minLat, maxLat)) - geom.setSRID(4326) - return geom.isValid() ? geom : null + } + if (nokeys) { + query += ");\nout;" + } else { + query += ");\n(._;>;);\nout;" + } - } - error("Invalid latitude longitude values") - } - - /** - * This method is used to build a geometry following the Nominatim bbox signature - * Nominatim API returns a boundingbox property of the form: - * south Latitude, north Latitude, west Longitude, east Longitude - * south : float -> southern latitude of bounding box - * west : float -> western longitude of bounding box - * north : float -> northern latitude of bounding box - * east : float -> eastern longitude of bounding box - * - * @author Erwan Bocher (CNRS LAB-STICC) - * - * @param bbox 4 values - * @return a JTS polygon - */ - //TODO why not merging methods - static Geometry geometryFromNominatim(def bbox) { - if (!bbox) { - error "The latitude and longitude values cannot be null or empty" - return null - } - if (!(bbox instanceof Collection) && !bbox.class.isArray()) { - error "The latitude and longitude values must be set as an array" - return null - } - if (bbox.size() == 4) { - return buildGeometry([bbox[1], bbox[0], bbox[3], bbox[2]]); - } - error("The bbox must be defined with 4 values") - } - - /** - * This method is used to build a geometry from 4 values (bbox) - * - * The order of the 4 values to defined in the bounding box is : - * south ,west, north, east - * - * south : float -> southern latitude of bounding box - * west : float -> western longitude of bounding box - * north : float -> northern latitude of bounding box - * east : float -> eastern longitude of bounding box - * - * So : minimum latitude, minimum longitude, maximum latitude, maximum longitude - * - * @author Erwan Bocher (CNRS LAB-STICC) - * - * @param bbox 4 values to define a bbox - * @return a JTS polygon - */ - static Geometry geometryFromValues(def bbox) { - if (!bbox) { + return query +} + +/** + * Parse a json file to a Map. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param jsonFile JSON file to parse. + * + * @return A Map of parameters. + */ +static Map readJSONParameters(def jsonFile) { + if (!jsonFile) { + error "The given file should not be null" + return null + } + def file + if (jsonFile instanceof InputStream) { + file = jsonFile + } else { + file = new File(jsonFile) + if (!file.exists()) { + warn "No file named ${jsonFile} doesn't exists." return null } - if (!(bbox instanceof Collection)) { + if (!file.isFile()) { + warn "No file named ${jsonFile} found." return null } - if (bbox.size() == 4) { - return buildGeometry([bbox[1], bbox[0], bbox[3], bbox[2]]); - } } + def parsed = new JsonSlurper().parse(file) + if (parsed in Map) { + return parsed + } + error "The json file doesn't contains only parameter." +} +/** + * This method is used to build a new geometry from the following input parameters : + * min Longitude , min Latitude , max Longitude , max Latitude + * + * @author Erwan Bocher (CNRS LAB-STICC) + * + * @param bbox 4 values + * @return a JTS polygon + * + */ +static Geometry buildGeometry(def bbox) { + if (!bbox) { + error "The BBox should not be null" + return null + } + if (!bbox.class.isArray() && !(bbox instanceof Collection)) { + error "The BBox should be an array" + return null + } + if (bbox.size() != 4) { + error "The BBox should be an array of 4 values" + return null + } + def minLong = bbox[0] + def minLat = bbox[1] + def maxLong = bbox[2] + def maxLat = bbox[3] + //Check values + if (UTMUtils.isValidLatitude(minLat) && UTMUtils.isValidLatitude(maxLat) + && UTMUtils.isValidLongitude(minLong) && UTMUtils.isValidLongitude(maxLong)) { + GeometryFactory geometryFactory = new GeometryFactory() + Geometry geom = geometryFactory.toGeometry(new Envelope(minLong, maxLong, minLat, maxLat)) + geom.setSRID(4326) + return geom.isValid() ? geom : null - /** - ** Function to drop the temp tables coming from the OSM extraction - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Le Saux (UBS LAB-STICC) - * - * @param prefix Prefix of the OSM tables. - * @param datasource Datasource where the OSM tables are. - */ - static boolean dropOSMTables(String prefix, JdbcDataSource datasource) { - if (prefix == null) { - error "The prefix should not be null" - return false - } - if (!datasource) { - error "The data source should not be null" - return false - } - datasource.execute("""DROP TABLE IF EXISTS ${prefix}_NODE, ${prefix}_NODE_MEMBER, ${prefix}_NODE_TAG, + } + error("Invalid latitude longitude values") +} + +/** + * This method is used to build a geometry following the Nominatim bbox signature + * Nominatim API returns a boundingbox property of the form: + * south Latitude, north Latitude, west Longitude, east Longitude + * south : float -> southern latitude of bounding box + * west : float -> western longitude of bounding box + * north : float -> northern latitude of bounding box + * east : float -> eastern longitude of bounding box + * + * @author Erwan Bocher (CNRS LAB-STICC) + * + * @param bbox 4 values + * @return a JTS polygon + */ +//TODO why not merging methods +static Geometry geometryFromNominatim(def bbox) { + if (!bbox) { + error "The latitude and longitude values cannot be null or empty" + return null + } + if (!(bbox instanceof Collection) && !bbox.class.isArray()) { + error "The latitude and longitude values must be set as an array" + return null + } + if (bbox.size() == 4) { + return buildGeometry([bbox[1], bbox[0], bbox[3], bbox[2]]); + } + error("The bbox must be defined with 4 values") +} + +/** + * This method is used to build a geometry from 4 values (bbox) + * + * The order of the 4 values to defined in the bounding box is : + * south ,west, north, east + * + * south : float -> southern latitude of bounding box + * west : float -> western longitude of bounding box + * north : float -> northern latitude of bounding box + * east : float -> eastern longitude of bounding box + * + * So : minimum latitude, minimum longitude, maximum latitude, maximum longitude + * + * @author Erwan Bocher (CNRS LAB-STICC) + * + * @param bbox 4 values to define a bbox + * @return a JTS polygon + */ +static Geometry geometryFromValues(def bbox) { + if (!bbox) { + return null + } + if (!(bbox instanceof Collection)) { + return null + } + if (bbox.size() == 4) { + return buildGeometry([bbox[1], bbox[0], bbox[3], bbox[2]]); + } +} + + +/** + ** Function to drop the temp tables coming from the OSM extraction + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Le Saux (UBS LAB-STICC) + * + * @param prefix Prefix of the OSM tables. + * @param datasource Datasource where the OSM tables are. + */ +static boolean dropOSMTables(String prefix, JdbcDataSource datasource) { + if (prefix == null) { + error "The prefix should not be null" + return false + } + if (!datasource) { + error "The data source should not be null" + return false + } + datasource.execute("""DROP TABLE IF EXISTS ${prefix}_NODE, ${prefix}_NODE_MEMBER, ${prefix}_NODE_TAG, ${prefix}_RELATION,${prefix}_RELATION_MEMBER,${prefix}_RELATION_TAG, ${prefix}_WAY, ${prefix}_WAY_MEMBER,${prefix}_WAY_NODE,${prefix}_WAY_TAG""".toString()) - return true + return true +} + +/** Get method for HTTP request */ +private static @Field GET = "GET" +/** Overpass server endpoint as defined by WSDL2 definition */ +static @Field OVERPASS_ENDPOINT = "https://overpass-api.de/api" +/** Overpass server base URL */ +static @Field OVERPASS_BASE_URL = "${OVERPASS_ENDPOINT}/interpreter?data=" +/** Url of the status of the Overpass server */ +static @Field OVERPASS_STATUS_URL = "${OVERPASS_ENDPOINT}/status" + +/** Default user agent*/ +static @Field OSM_USER_AGENT = "geoclimate" + +/** OVERPASS TIMEOUT */ +static @Field int OVERPASS_TIMEOUT = 180 +/** + * Return the status of the Overpass server. + * @return A string representation of the overpass status. + */ +static def getServerStatus() { + final String proxyHost = System.getProperty("http.proxyHost"); + final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); + def connection + def endPoint = System.getProperty("OVERPASS_ENPOINT"); + if (endPoint) { + OVERPASS_STATUS_URL = "${endPoint}/status" } - - /** Get method for HTTP request */ - private static def GET = "GET" - /** Overpass server endpoint as defined by WSDL2 definition */ - static def OVERPASS_ENDPOINT ="https://overpass-api.de/api" - /** Overpass server base URL */ - static def OVERPASS_BASE_URL = "${OVERPASS_ENDPOINT}/interpreter?data=" - /** Url of the status of the Overpass server */ - static def OVERPASS_STATUS_URL = "${OVERPASS_ENDPOINT}/status" - - /** Default user agent*/ - static def OSM_USER_AGENT = "geoclimate" - - /** OVERPASS TIMEOUT */ - static int OVERPASS_TIMEOUT=180 - /** - * Return the status of the Overpass server. - * @return A string representation of the overpass status. - */ - static def getServerStatus() { - final String proxyHost = System.getProperty("http.proxyHost"); - final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); - def connection - def endPoint = System.getProperty("OVERPASS_ENPOINT"); - if(endPoint){ - OVERPASS_STATUS_URL= "${endPoint}/status" - } - if (proxyHost != null) { - def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost,proxyPort )); - connection = new URL(OVERPASS_STATUS_URL).openConnection(proxy) as HttpURLConnection - } else { - connection = new URL(OVERPASS_STATUS_URL).openConnection() as HttpURLConnection - } - connection.requestMethod = GET - connection.connect() - if (connection.responseCode == 200) { - return connection.inputStream.text - } - else { - error "Cannot get the status of the server.\n Server answer with code ${connection.responseCode} : " + - "${connection.inputStream.text}" - } + if (proxyHost != null) { + def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); + connection = new URL(OVERPASS_STATUS_URL).openConnection(proxy) as HttpURLConnection + } else { + connection = new URL(OVERPASS_STATUS_URL).openConnection() as HttpURLConnection + } + connection.requestMethod = GET + connection.connect() + if (connection.responseCode == 200) { + return connection.inputStream.text + } else { + error "Cannot get the status of the server.\n Server answer with code ${connection.responseCode} : " + + "${connection.inputStream.text}" } +} - /** {@link Closure} converting and UTF-8 {@link String} into an {@link URL}. */ - static def utf8ToUrl = { utf8 -> URLEncoder.encode(utf8, UTF_8.toString()) } - - - /** - * Method to execute an Overpass query and save the result in a file - * - * @param query the Overpass query - * @param outputOSMFile the output file - * - * @return True if the query has been successfully executed, false otherwise. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Lesaux (UBS LAB-STICC) - */ - static boolean executeOverPassQuery(URL queryUrl, def outputOSMFile) { - final String proxyHost = System.getProperty("http.proxyHost"); - final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); - def connection - if (proxyHost != null) { - def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost,proxyPort )); - connection = queryUrl.openConnection(proxy) as HttpURLConnection - } else { - connection = queryUrl.openConnection() as HttpURLConnection - } - debug queryUrl - connection.requestMethod = GET +/** {@link Closure} converting and UTF-8 {@link String} into an {@link URL}. */ +static @Field utf8ToUrl = { utf8 -> URLEncoder.encode(utf8, UTF_8.toString()) } - Matcher timeoutMatcher = Pattern.compile("\\[timeout:(\\d+)\\]").matcher(queryUrl.toString()); - int timeout = OVERPASS_TIMEOUT - if (timeoutMatcher.find()) { - timeout = (int) TimeUnit.SECONDS.toMillis(Integer.parseInt(timeoutMatcher.group(1))); - } else { - timeout = (int) TimeUnit.MINUTES.toMillis(3); - } - def user_agent = System.getProperty("OVERPASS_USER_AGENT") - if(!user_agent){ - user_agent = OSM_USER_AGENT - } - connection.setRequestProperty("User-Agent", user_agent) +/** + * Method to execute an Overpass query and save the result in a file + * + * @param query the Overpass query + * @param outputOSMFile the output file + * + * @return True if the query has been successfully executed, false otherwise. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Lesaux (UBS LAB-STICC) + */ +static boolean executeOverPassQuery(URL queryUrl, def outputOSMFile) { + final String proxyHost = System.getProperty("http.proxyHost"); + final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); + def connection + if (proxyHost != null) { + def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); + connection = queryUrl.openConnection(proxy) as HttpURLConnection + } else { + connection = queryUrl.openConnection() as HttpURLConnection + } + debug queryUrl + connection.requestMethod = GET + + Matcher timeoutMatcher = Pattern.compile("\\[timeout:(\\d+)\\]").matcher(queryUrl.toString()); + int timeout = OVERPASS_TIMEOUT + if (timeoutMatcher.find()) { + timeout = (int) TimeUnit.SECONDS.toMillis(Integer.parseInt(timeoutMatcher.group(1))); + } else { + timeout = (int) TimeUnit.MINUTES.toMillis(3); + } - connection.setConnectTimeout(timeout); - connection.setReadTimeout(timeout); + def user_agent = System.getProperty("OVERPASS_USER_AGENT") + if (!user_agent) { + user_agent = OSM_USER_AGENT + } + connection.setRequestProperty("User-Agent", user_agent) - connection.connect() + connection.setConnectTimeout(timeout); + connection.setReadTimeout(timeout); - debug "Executing query... $queryUrl" - //Save the result in a file - if (connection.responseCode == 200) { - info "Downloading the OSM data from overpass api in ${outputOSMFile}" - outputOSMFile << connection.inputStream - return true - } - else { - error "Cannot execute the query.\n${getServerStatus()}" - return false - } + connection.connect() + + debug "Executing query... $queryUrl" + //Save the result in a file + if (connection.responseCode == 200) { + info "Downloading the OSM data from overpass api in ${outputOSMFile}" + outputOSMFile << connection.inputStream + return true + } else { + error "Cannot execute the query.\n${getServerStatus()}" + return false } +} - /** - * Method to execute an Overpass query and save the result in a file - * - * @param query the Overpass query - * @param outputOSMFile the output file - * - * @return True if the query has been successfully executed, false otherwise. - * - * @author Erwan Bocher (CNRS LAB-STICC) - * @author Elisabeth Lesaux (UBS LAB-STICC) - */ - static boolean executeOverPassQuery(def query, def outputOSMFile) { - if(!query){ - error "The query should not be null or empty." - return false - } - if(!outputOSMFile){ - error "The output file should not be null or empty." - return false - } - def endPoint = System.getProperty("OVERPASS_ENPOINT"); - if(endPoint){ - OVERPASS_BASE_URL= "${endPoint}/interpreter?data=" - } - def queryUrl = new URL(OVERPASS_BASE_URL + utf8ToUrl(query)) - final String proxyHost = System.getProperty("http.proxyHost"); - final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); - def connection - if (proxyHost != null) { - def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost,proxyPort )); - connection = queryUrl.openConnection(proxy) as HttpURLConnection - } else { - connection = queryUrl.openConnection() as HttpURLConnection - } - debug queryUrl - connection.requestMethod = GET - Matcher timeoutMatcher = Pattern.compile("\\[timeout:(\\d+)\\]").matcher(query) - int timeout = OVERPASS_TIMEOUT - if (timeoutMatcher.find()) { - timeout = (int) TimeUnit.SECONDS.toMillis(Integer.parseInt(timeoutMatcher.group(1))); - } else { - timeout = (int) TimeUnit.MINUTES.toMillis(3); - } - def user_agent = System.getProperty("OVERPASS_USER_AGENT") - if(!user_agent){ - user_agent = OSM_USER_AGENT - } - connection.setRequestProperty("User-Agent", user_agent) - connection.setConnectTimeout(timeout) - connection.setReadTimeout(timeout) +/** + * Method to execute an Overpass query and save the result in a file + * + * @param query the Overpass query + * @param outputOSMFile the output file + * + * @return True if the query has been successfully executed, false otherwise. + * + * @author Erwan Bocher (CNRS LAB-STICC) + * @author Elisabeth Lesaux (UBS LAB-STICC) + */ +static boolean executeOverPassQuery(def query, def outputOSMFile) { + if (!query) { + error "The query should not be null or empty." + return false + } + if (!outputOSMFile) { + error "The output file should not be null or empty." + return false + } + def endPoint = System.getProperty("OVERPASS_ENPOINT"); + if (endPoint) { + OVERPASS_BASE_URL = "${endPoint}/interpreter?data=" + } + def queryUrl = new URL(OVERPASS_BASE_URL + utf8ToUrl(query)) + final String proxyHost = System.getProperty("http.proxyHost"); + final int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); + def connection + if (proxyHost != null) { + def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); + connection = queryUrl.openConnection(proxy) as HttpURLConnection + } else { + connection = queryUrl.openConnection() as HttpURLConnection + } + debug queryUrl + connection.requestMethod = GET + Matcher timeoutMatcher = Pattern.compile("\\[timeout:(\\d+)\\]").matcher(query) + int timeout = OVERPASS_TIMEOUT + if (timeoutMatcher.find()) { + timeout = (int) TimeUnit.SECONDS.toMillis(Integer.parseInt(timeoutMatcher.group(1))); + } else { + timeout = (int) TimeUnit.MINUTES.toMillis(3); + } + def user_agent = System.getProperty("OVERPASS_USER_AGENT") + if (!user_agent) { + user_agent = OSM_USER_AGENT + } + connection.setRequestProperty("User-Agent", user_agent) + connection.setConnectTimeout(timeout) + connection.setReadTimeout(timeout) - connection.connect() + connection.connect() - debug"Executing query... $query" - //Save the result in a file - if (connection.responseCode == 200) { - info "Downloading the OSM data from overpass api in ${outputOSMFile}" - outputOSMFile << connection.inputStream - return true - } - else { - error "Cannot execute the query.\n${getServerStatus()}" - return false - } + debug "Executing query... $query" + //Save the result in a file + if (connection.responseCode == 200) { + info "Downloading the OSM data from overpass api in ${outputOSMFile}" + outputOSMFile << connection.inputStream + return true + } else { + error "Cannot execute the query.\n${getServerStatus()}" + return false } -} \ No newline at end of file +} diff --git a/osmtools/src/test/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtilsTest.groovy b/osmtools/src/test/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtilsTest.groovy index 53941e11b1..46e9edba55 100644 --- a/osmtools/src/test/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtilsTest.groovy +++ b/osmtools/src/test/groovy/org/orbisgis/geoclimate/osmtools/utils/TransformUtilsTest.groovy @@ -36,14 +36,12 @@ */ package org.orbisgis.geoclimate.osmtools.utils -import org.h2.jdbc.JdbcSQLSyntaxErrorException import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInfo import org.locationtech.jts.geom.LineString import org.locationtech.jts.geom.MultiLineString -import org.locationtech.jts.geom.Polygon import org.orbisgis.geoclimate.osmtools.AbstractOSMTest import org.orbisgis.data.H2GIS import org.slf4j.Logger @@ -924,7 +922,7 @@ class TransformUtilsTest extends AbstractOSMTest { @Test void badToPolygonOrLineTest(){ def badType = "notAType" - def lineType = TransformUtils.Types.LINES + def lineType = GeometryTypes.LINES H2GIS ds = RANDOM_DS() def prefix = "OSM_"+uuid() def epsgCode = 2145 @@ -952,8 +950,8 @@ class TransformUtilsTest extends AbstractOSMTest { */ @Test void toPolygonOrLineTest() { - def lineType = TransformUtils.Types.LINES - def polygonType = TransformUtils.Types.POLYGONS + def lineType = GeometryTypes.LINES + def polygonType = GeometryTypes.POLYGONS H2GIS ds = RANDOM_DS() def prefix = "OSM_" + uuid() def epsgCode = 2145 diff --git a/pom.xml b/pom.xml index 43351d4899..64cd3ddc61 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,8 @@ 2.1.214 1.6.0 2.0.0 - 1.7.36 + 2.0.4 + 1.4.5 3.0.11 4.6.3 2.11.0 @@ -212,9 +213,9 @@ ${slf4j-version} - org.slf4j - slf4j-simple - ${slf4j-version} + ch.qos.logback + logback-classic + ${logback-version} org.codehaus.groovy diff --git a/worldpoptools/pom.xml b/worldpoptools/pom.xml index 2b5b04a790..3843492ccb 100644 --- a/worldpoptools/pom.xml +++ b/worldpoptools/pom.xml @@ -40,8 +40,8 @@ slf4j-api - org.slf4j - slf4j-simple + ch.qos.logback + logback-classic diff --git a/worldpoptools/src/main/groovy/org/orbisgis/geoclimate/worldpoptools/WorldPopTools.groovy b/worldpoptools/src/main/groovy/org/orbisgis/geoclimate/worldpoptools/WorldPopTools.groovy index c5364cc5cf..61976be17f 100644 --- a/worldpoptools/src/main/groovy/org/orbisgis/geoclimate/worldpoptools/WorldPopTools.groovy +++ b/worldpoptools/src/main/groovy/org/orbisgis/geoclimate/worldpoptools/WorldPopTools.groovy @@ -37,6 +37,9 @@ package org.orbisgis.geoclimate.worldpoptools +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.Logger +import ch.qos.logback.classic.LoggerContext import org.orbisgis.process.GroovyProcessFactory import org.slf4j.LoggerFactory @@ -53,7 +56,14 @@ abstract class WorldPopTools extends GroovyProcessFactory { def static Extract = new WorldPopExtract() - public static def logger = LoggerFactory.getLogger(WorldPopTools.class) + public static def logger + + WorldPopTools(){ + logger = LoggerFactory.getLogger(WorldPopTools.class) + var context = (LoggerContext) LoggerFactory.getILoggerFactory() + context.getLogger(WorldPopTools.class).setLevel(Level.INFO) + } + static def info = { obj -> logger.info(obj.toString()) } static def warn = { obj -> logger.warn(obj.toString()) } static def error = { obj -> logger.error(obj.toString()) }