package org.gcube.dataanalysis.geo.algorithms; import it.cnr.aquamaps.CSquare; import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.dataanalysis.ecoengine.configuration.AlgorithmConfiguration; import org.gcube.dataanalysis.ecoengine.interfaces.StandardLocalExternalAlgorithm; import org.gcube.dataanalysis.ecoengine.utils.DatabaseFactory; import org.gcube.dataanalysis.ecoengine.utils.DatabaseUtils; import org.gcube.dataanalysis.geo.meta.PolyMapMetadata; import org.gcube.spatial.data.gis.model.report.PublishResponse; import org.hibernate.SessionFactory; import scala.collection.Iterator; public abstract class MapsCreator extends StandardLocalExternalAlgorithm { static String databaseParameterName = "TimeSeriesDataStore"; static String dbuserParameterName = "user"; static String dbpasswordParameterName = "password"; static String dburlParameterName = "STOREURL"; static String inputTableParameter = "InputTable"; static String outputTableParameter = "OutputTable"; static String xParameter = "xDimension"; static String yParameter = "yDimension"; static String csquareParameter = "csquaresDimension"; static String probabilityParameter = "Probability"; static String infoParameter = "Info"; static String resolutionParameter = "Resolution"; static String layerNameParameter = "MapName"; static int maxNPoints = 259000; SessionFactory gisdbconnection = null; SessionFactory smdbconnection = null; private static String createProbTable = "create table %1$s (geomid serial, x real, y real, probability real);"; private static String columnsProbNames = " geomid, x , y, probability, the_geom"; private static String createInfoTable = "create table %1$s (geomid serial, x real, y real, info character varying);"; private static String columnsInfoNames = " geomid, x , y, info, the_geom"; private static String addGeometryColumn = "Select AddGeometryColumn('%1$s','the_geom',4326,'POLYGON',2);"; static String makeSquare = "ST_GeomFromText('POLYGON((%1$s ,%2$s, %3$s, %4$s, %1$s))',4326)"; //changeable parameters for application purposes String datastore = ""; String defaultStyle = ""; String workspace = ""; String username = ""; String purpose = ""; String credits = ""; String keyword = ""; @Override public String getDescription() { return "A transducer algorithm to produce a GIS map from a probability distribution or from a set of points. A maximum of " + maxNPoints + " is allowed"; } @Override public abstract void init() throws Exception; @Override protected void process() throws Exception { try { status = 0; log("Beginning process"); log("Set scope from outside:"+config.getGcubeScope()); String scope = config.getGcubeScope(); if (scope == null) scope = ScopeProvider.instance.get(); log("Using scope:"+scope); //initialize Gis DB parameters String databaseJdbc = getInputParameter(dburlParameterName); String databaseUser = getInputParameter(dbuserParameterName); String databasePwd = getInputParameter(dbpasswordParameterName); log("GIS Database Parameters to use: " + databaseJdbc + " , " + databaseUser); //getting resolution String res$ = config.getParam(resolutionParameter); double resolution = res$!=null?Double.parseDouble(res$):0; //connection to the GIS DB log("Connecting to gisDB..."); AlgorithmConfiguration gisconfig = new AlgorithmConfiguration(); gisconfig.setParam("DatabaseDriver", "org.postgresql.Driver"); gisconfig.setParam("DatabaseURL", "jdbc:postgresql://geoserver-test.d4science-ii.research-infrastructures.eu/timeseriesgisdb"); gisconfig.setParam("DatabaseUserName", databaseUser); gisconfig.setParam("DatabasePassword", databasePwd); gisconfig.setConfigPath(config.getConfigPath()); gisdbconnection = DatabaseUtils.initDBSession(gisconfig); log("Initialized gisDBConnection!"); status = 10; // connect to the SM DB smdbconnection = DatabaseUtils.initDBSession(config); log("Initialized SMDBConnection!"); //select info to attach String infoPar = config.getParam(probabilityParameter); if (infoPar == null) infoPar = config.getParam(infoParameter); // points retrieval List points = null; log("Retrieving points.."); if (config.getParam(xParameter) != null && config.getParam(yParameter) != null) { log("..from coordinates"); // select the points from the SM DB up to a maximum of 190000 points points = DatabaseFactory.executeSQLQuery("select " + config.getParam(xParameter) + "," + config.getParam(yParameter) + "," +infoPar + " from " + config.getParam(inputTableParameter) + " limit " + maxNPoints, smdbconnection); } //points from csquares else if (config.getParam(csquareParameter)!=null){ log("..from csquares"); String queryCsquare = "select " + config.getParam(csquareParameter) + "," + infoPar +" from " + config.getParam(inputTableParameter) + " limit " + maxNPoints; List csquares= DatabaseFactory.executeSQLQuery(queryCsquare, smdbconnection); points = new ArrayList(); //build points from csquares for (Object csquare:csquares){ Object[] csquareandprob = (Object[]) csquare; CSquare c = it.cnr.aquamaps.CSquare.apply(""+csquareandprob[0]); if (resolution==0) resolution=c.size(); // x,y Iterator iterator = c.center().valuesIterator(); String x = ""+iterator.next(); String y = ""+iterator.next(); String prob = ""+csquareandprob[1]; Object[] pair = {x,y,prob}; points.add(pair); } log("Points built from csquares!"); } //GIS Table creation log("Creating GIS table"); String gisTableName = "stat" + UUID.randomUUID().toString().replace("-", ""); status = 30; String createTable$ = String.format(createProbTable, gisTableName); String columnNames$ = columnsProbNames; if (config.getParam(probabilityParameter)==null){ createTable$ = String.format(createInfoTable, gisTableName); columnNames$=columnsInfoNames; } log(createTable$); //drop previous table try { DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(gisTableName), gisdbconnection); } catch (Exception e) { log("Impossible to drop table:" + e.getLocalizedMessage()); } //table creation DatabaseFactory.executeSQLUpdate(createTable$, gisdbconnection); DatabaseFactory.executeSQLQuery(String.format(addGeometryColumn, gisTableName), gisdbconnection); log("Fulfilling elements"); log("Resolution:" + resolution); //points fulfilling List values = new ArrayList(); int i = 0; for (Object point : points) { Object[] elements = (Object[]) point; double x = Double.parseDouble("" + elements[0]); double y = Double.parseDouble("" + elements[1]); String probS = "" + elements[2]; double x1 = x - resolution; double x2 = x + resolution; double y1 = y - resolution; double y2 = y + resolution; String square = String.format(makeSquare, "" + x1 + " " + y1, x1 + " " + y2, x2 + " " + y2, x2 + " " + y1); // System.out.println(square); String[] selements = { "" + i, "" + x, "" + y, probS,square }; values.add(selements); i++; } status = 50; log("Writing chunks"); // write chunks into the DB insertGeoChunksIntoTable(gisTableName, columnNames$, values, 5000, gisdbconnection); log("Publishing Table"); String usernameP = config.getParam("ServiceUserName"); if (usernameP != null) username = usernameP; String layerName = config.getParam(layerNameParameter); PublishResponse response = PolyMapMetadata.publishTable(scope, gisTableName, resolution, username, layerName, defaultStyle, workspace, datastore, purpose, credits, keyword); status = 80; //analyzing response if (response == null) { log("Error in generating map - dropping gis table"); try { DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(gisTableName), gisdbconnection); log("gis table dropped"); } catch (Exception e) { log("Impossible to drop table:" + e.getLocalizedMessage()); } throw new Exception("Impossible to publish on GeoNetwork or GeoServer: " + gisTableName); } else { //writing output addOutputString("GIS map title", layerName); addOutputString("GIS map UUID", "" + response.getPublishedMetadata().getFileIdentifier()); addOutputString("Associated Geospatial Table", gisTableName); addOutputString("Generated by ", username); addOutputString("Resolution", "" + resolution); addOutputString("Style", "" + defaultStyle); addOutputString("Keyword", "" + keyword); } log("Output:"+outputParameters); log("All Done!"); status = 100; } catch (Exception e) { e.printStackTrace(); throw e; } finally { if (smdbconnection != null) DatabaseUtils.closeDBConnection(smdbconnection); if (gisdbconnection != null) DatabaseUtils.closeDBConnection(gisdbconnection); } } public static void insertGeoChunksIntoTable(String table, String columnsNames, List values, int chunkSize,SessionFactory dbconnection) throws Exception{ int valuesize = values.size(); StringBuffer sb = new StringBuffer(); int stopIndex =0; for (int i=0;i0 && stopIndex%chunkSize==0){ DatabaseFactory.executeSQLUpdate(DatabaseUtils.insertFromBuffer(table, columnsNames, sb), dbconnection); stopIndex=chunkSize; sb = new StringBuffer(); } else if (i0){ try{ DatabaseFactory.executeSQLUpdate(DatabaseUtils.insertFromBuffer(table, columnsNames, sb), dbconnection); }catch(Exception e){ System.out.println("Query:"+sb); throw e; } } } } @Override public void shutdown() { log("shutdown invoked!"); } @Override protected abstract void setInputParameters(); }