From 8e5ef77686b2ce965de48d21c1c611206c2fd155 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 28 Jan 2022 17:46:36 +0100 Subject: [PATCH] added WFSParameter and FeatureParser --- .classpath | 5 +- .settings/org.eclipse.jdt.core.prefs | 5 + pom.xml | 12 ++ .../org/gcube/spatial/data/GeoUtility.gwt.xml | 10 ++ .../shared/wfs/FeatureGeometry.java | 74 +++++++++ .../geoutility/shared/wfs/FeatureRow.java | 89 +++++++++++ .../geoutility/shared/wfs/WFSGeometry.java | 27 ++++ .../geoutility/shared/wfs/WFSParameter.java | 60 +++++++ .../data/geoutility/wfs/FeatureParser.java | 151 ++++++++++++++++++ .../data/geoutility/wfs/WFSQueryBuilder.java | 70 ++++++++ .../org/gcube/spatial/data/GeoUtility.gwt.xml | 10 ++ .../spatial/data/geoutility/GeoJUnitTest.java | 86 ++++++++-- src/test/resources/.gitignore | 6 + 13 files changed, 589 insertions(+), 16 deletions(-) create mode 100644 src/main/java/org/gcube/spatial/data/GeoUtility.gwt.xml create mode 100644 src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureGeometry.java create mode 100644 src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureRow.java create mode 100644 src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSGeometry.java create mode 100644 src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSParameter.java create mode 100644 src/main/java/org/gcube/spatial/data/geoutility/wfs/FeatureParser.java create mode 100644 src/main/java/org/gcube/spatial/data/geoutility/wfs/WFSQueryBuilder.java create mode 100644 src/main/resources/org/gcube/spatial/data/GeoUtility.gwt.xml create mode 100644 src/test/resources/.gitignore diff --git a/.classpath b/.classpath index 107e885..c278245 100644 --- a/.classpath +++ b/.classpath @@ -6,17 +6,18 @@ + + - - + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index cac0df4..8b5c4dc 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error diff --git a/pom.xml b/pom.xml index 280ae3f..323e66c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,18 @@ UTF-8 + + + Francesco Mangiacrapa + francesco.mangiacrapa@isti.cnr.it + CNR Pisa, Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" + + architect + developer + + + + diff --git a/src/main/java/org/gcube/spatial/data/GeoUtility.gwt.xml b/src/main/java/org/gcube/spatial/data/GeoUtility.gwt.xml new file mode 100644 index 0000000..f41ea40 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/GeoUtility.gwt.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureGeometry.java b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureGeometry.java new file mode 100644 index 0000000..74706c5 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureGeometry.java @@ -0,0 +1,74 @@ +package org.gcube.spatial.data.geoutility.shared.wfs; + +import java.io.Serializable; + +/** + * The Class FeatureGeometry. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Sep 6, 2021 + */ +public class FeatureGeometry implements WFSGeometry, Serializable { + + + /** + * + */ + private static final long serialVersionUID = 8231377594468260590L; + private String type; + private String coordinatesJSON; + private String toJSON; + + /** + * Instantiates a new feature geometry. + */ + public FeatureGeometry() { + } + + /** + * Instantiates a new feature geometry. + * + * @param type the type + * @param coordinatesJSON the coordinates JSON + */ + public FeatureGeometry(String type, String coordinatesJSON) { + super(); + this.type = type; + this.coordinatesJSON = coordinatesJSON; + } + + public String getType() { + return type; + } + + public String getCoordinatesJSON() { + return coordinatesJSON; + } + + public void setType(String type) { + this.type = type; + } + + public void setCoordinatesJSON(String coordinatesJSON) { + this.coordinatesJSON = coordinatesJSON; + } + + public String getToJSONObject() { + if(toJSON==null) + toJSON = "{\"type\":\""+type+"\",\"coordinates\":"+coordinatesJSON+"}"; + return toJSON; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("FeatureGeometry [type="); + builder.append(type); + builder.append(", coordinatesJSON="); + builder.append(coordinatesJSON); + builder.append("]"); + return builder.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureRow.java b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureRow.java new file mode 100644 index 0000000..9c130bc --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/FeatureRow.java @@ -0,0 +1,89 @@ +/** + * + */ +package org.gcube.spatial.data.geoutility.shared.wfs; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * The Class FeatureRow. + * + * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) + * + * Oct 29, 2020 + */ +public class FeatureRow implements Serializable { + + + /** + * + */ + private static final long serialVersionUID = 8741559784800931747L; + + private String id; + + private Map> mapProperties; + + private FeatureGeometry geometry; + + private String crsName; + + public FeatureRow() { + } + + public FeatureRow(Map> mapProperties, FeatureGeometry geometry) { + super(); + this.mapProperties = mapProperties; + this.setGeometry(geometry); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Map> getMapProperties() { + return mapProperties; + } + + public void setMapProperties(Map> mapProperties) { + this.mapProperties = mapProperties; + } + + public String getCrsName() { + return crsName; + } + + public void setCrsName(String crsName) { + this.crsName = crsName; + } + + public FeatureGeometry getGeometry() { + return geometry; + } + + public void setGeometry(FeatureGeometry geometry) { + this.geometry = geometry; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("FeatureRow [id="); + builder.append(id); + builder.append(", mapProperties="); + builder.append(mapProperties); + builder.append(", geometry="); + builder.append(geometry); + builder.append(", crsName="); + builder.append(crsName); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSGeometry.java b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSGeometry.java new file mode 100644 index 0000000..ee9c387 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSGeometry.java @@ -0,0 +1,27 @@ +package org.gcube.spatial.data.geoutility.shared.wfs; + + +/** + * The Interface WFSGeometry. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Sep 6, 2021 + */ +public interface WFSGeometry { + + /** + * Gets the type. + * + * @return the type + */ + String getType(); + + /** + * Gets the coordinates JSON. + * + * @return the coordinates JSON + */ + String getCoordinatesJSON(); + +} diff --git a/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSParameter.java b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSParameter.java new file mode 100644 index 0000000..7609f02 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/geoutility/shared/wfs/WFSParameter.java @@ -0,0 +1,60 @@ +package org.gcube.spatial.data.geoutility.shared.wfs; + + +/** + * The Enum WFSParameter with default value (parameter,value) + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jan 28, 2022 + */ +public enum WFSParameter { + + SERVICE("SERVICE", "WFS"), + VERSION("VERSION", "1.1.0"), + REQUEST("REQUEST", "GetFeature"), + TYPENAME("TYPENAME", ""), + STYLES("STYLES", ""), + BBOX("BBOX", "-180,-90,180,90"), + WIDTH("WIDTH", "676"), + HEIGHT("HEIGHT", "230"), + SRSNAME("srsName", "EPSG:4326"), + CRS("CRS","EPSG:4326"), //WMS 1.3.0 COMPLIANT + OUTPUTFORMAT("OUTPUTFORMAT", "application/json"), + MAXFEATURES("MAXFEATURES", "10"), + PROPERTYNAME("PROPERTYNAME",""), + CQL_FILTER("CQL_FILTER",""); + + private String parameter; + private String value; + + /** + * Instantiates a new wfs parameters. + * + * @param parameter the parameter + * @param value the value + */ + WFSParameter(String parameter, String value) { + this.parameter = parameter; + this.value = value; + } + + /** + * Gets the parameter. + * + * @return the parameter + */ + public String getParameter() { + return parameter; + } + + /** + * Gets the value. + * + * @return the value + */ + public String getValue() { + return value; + } + +} diff --git a/src/main/java/org/gcube/spatial/data/geoutility/wfs/FeatureParser.java b/src/main/java/org/gcube/spatial/data/geoutility/wfs/FeatureParser.java new file mode 100644 index 0000000..fcceaf8 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/geoutility/wfs/FeatureParser.java @@ -0,0 +1,151 @@ +/** + * + */ +package org.gcube.spatial.data.geoutility.wfs; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.gcube.spatial.data.geoutility.shared.wfs.FeatureGeometry; +import org.gcube.spatial.data.geoutility.shared.wfs.FeatureRow; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class FeatureParser. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jan 28, 2022 + */ +public class FeatureParser { + + private static Logger LOG = LoggerFactory.getLogger(FeatureParser.class); + + /** + * Gets the WFS features. + * + * @param wfsEndPoint the wfs end point + * @param wfsQB the wfs QB + * @return the WFS features + */ + public static List getWFSFeatures(String wfsEndPoint, WFSQueryBuilder wfsQB) { + + return getWFSFeatureProperties(wfsEndPoint + "?" + wfsQB.getQuery()); + } + + /** + * Gets the WFS feature properties. + * + * @param wfsURLRequest the wfs URL request + * @return the WFS feature properties + */ + @SuppressWarnings("unchecked") + private static List getWFSFeatureProperties(String wfsURLRequest) { + LOG.info("getWFSFeatureProperties for url: " + wfsURLRequest); + InputStream is = null; + List listFeaturesRow = new ArrayList(); + try { + + LOG.info("Built WFS URL: " + wfsURLRequest); + is = new URL(wfsURLRequest).openStream(); + String jsonTxt = IOUtils.toString(is); + + if (jsonTxt == null || jsonTxt.isEmpty()) { + jsonTxt = "{\"type\":\"FeatureCollection\",\"features\":[]}"; + } + + // get json object + JSONObject json = new JSONObject(jsonTxt); + // iterate features + JSONArray features = json.getJSONArray("features"); + if (features.length() == 0) { + LOG.info("No features detected in the response, returning empty list"); + return listFeaturesRow; + } + + String featureCRSName = ""; + try { + JSONObject crs = json.getJSONObject("crs"); + JSONObject crsProp = crs.getJSONObject("properties"); + featureCRSName = crsProp.getString("name"); + LOG.info("Crs name found: " + featureCRSName); + } catch (Exception e) { + LOG.warn("Unable to read the field 'crs'"); + } + + LOG.info("Features are: " + features.length()); + + for (int i = 0; i < features.length(); i++) { + final FeatureRow row = new FeatureRow(); + row.setCrsName(featureCRSName); + JSONObject theFeature = ((JSONObject) features.get(i)); + LOG.debug("Building at index: " + i); + + try { + String fetaureId = theFeature.getString("id"); + row.setId(fetaureId); + JSONObject geometry = theFeature.getJSONObject("geometry"); + String typeValue = geometry.getString("type"); + FeatureGeometry fg = new FeatureGeometry(); + fg.setType(typeValue); + + try { + JSONArray coordinates = geometry.getJSONArray("coordinates"); + String coordinateJSONString = coordinates.toString(); + LOG.debug("coordinates are: " + coordinateJSONString); + fg.setCoordinatesJSON(coordinates.toString()); + } catch (Exception e) { + LOG.warn("Not able to parse the 'coordinates' field: ", e); + } + + row.setGeometry(fg); + } catch (Exception e) { + LOG.debug("Unable to parse geometry at index: " + i); + } + +// // iterate properties + JSONObject properties = theFeature.getJSONObject("properties"); + Map> mapProperties = new HashMap>(); + @SuppressWarnings("unchecked") + Iterator ii = properties.keys(); + while (ii.hasNext()) { + String key = ii.next(); + String value = properties.optString(key, ""); + + List theValues = mapProperties.get(key); + if (theValues == null) + mapProperties.put(key, Arrays.asList(value)); + else { + theValues.add(value); + mapProperties.put(key, theValues); + } + } + row.setMapProperties(mapProperties); + listFeaturesRow.add(row); + LOG.info("Added row " + row + " to exported properties"); + } + + } catch (IOException e) { + LOG.error("Error on requesting properties for url: " + wfsURLRequest, e); + } catch (JSONException e) { + LOG.error("Error on requesting properties for url: " + wfsURLRequest, e); + } finally { + IOUtils.closeQuietly(is); + } + + LOG.info("Returning " + listFeaturesRow.size() + " features"); + return listFeaturesRow; + } +} diff --git a/src/main/java/org/gcube/spatial/data/geoutility/wfs/WFSQueryBuilder.java b/src/main/java/org/gcube/spatial/data/geoutility/wfs/WFSQueryBuilder.java new file mode 100644 index 0000000..f3b2ce6 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/geoutility/wfs/WFSQueryBuilder.java @@ -0,0 +1,70 @@ +package org.gcube.spatial.data.geoutility.wfs; + +import java.util.List; + +import org.gcube.spatial.data.geoutility.shared.wfs.WFSParameter; + +/** + * The Class WFSQueryBuilder. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Jan 28, 2022 + */ +public class WFSQueryBuilder { + + private String query = ""; + + /** + * Instantiates a new WFS query builder. + */ + public WFSQueryBuilder() { + + } + + /** + * Adds the parameter. + * + * @param param the param + * @param value the value + */ + public void addParameter(WFSParameter param, String value) { + + if (!query.isEmpty()) + query += "&"; + + query += param + "=" + value; + } + + /** + * Adds the parameter. + * + * @param param the param + * @param values the values + * @param separtor the separtor + */ + public void addParameter(WFSParameter param, List values, String separtor) { + + if (!query.isEmpty()) + query += "&"; + + String value = ""; + for (int i = 0; i < values.size() - 1; i++) { + value += values.get(i) + separtor; + } + + value += values.get(values.size() - 1); + + query += param + "=" + value; + } + + /** + * Gets the query. + * + * @return the query + */ + public String getQuery() { + return query; + } + +} diff --git a/src/main/resources/org/gcube/spatial/data/GeoUtility.gwt.xml b/src/main/resources/org/gcube/spatial/data/GeoUtility.gwt.xml new file mode 100644 index 0000000..f41ea40 --- /dev/null +++ b/src/main/resources/org/gcube/spatial/data/GeoUtility.gwt.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/test/java/org/gcube/spatial/data/geoutility/GeoJUnitTest.java b/src/test/java/org/gcube/spatial/data/geoutility/GeoJUnitTest.java index 71ee207..af92621 100644 --- a/src/test/java/org/gcube/spatial/data/geoutility/GeoJUnitTest.java +++ b/src/test/java/org/gcube/spatial/data/geoutility/GeoJUnitTest.java @@ -3,23 +3,28 @@ */ package org.gcube.spatial.data.geoutility; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +import org.gcube.spatial.data.geoutility.shared.wfs.FeatureRow; +import org.gcube.spatial.data.geoutility.shared.wfs.WFSParameter; +import org.gcube.spatial.data.geoutility.wfs.FeatureParser; +import org.gcube.spatial.data.geoutility.wfs.WFSQueryBuilder; import org.gcube.spatial.data.geoutility.wms.WmsUrlValidator; import org.junit.Test; - - /** * The Class GeoJUnitTest. * - * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it - * Jan 22, 2016 + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jan 22, 2016 */ public class GeoJUnitTest { /** * Test get styles. */ - @Test + //@Test public void testGetStyles() { // String wmsRequest = "http://repoigg.services.iit.cnr.it:8080/geoserver/IGG/ows?service=wms&version=1.1.0&request=GetMap&layers==IGG:area_temp_1000&width=676&height=330&srs=EPSG:4326&crs=EPSG:4326&format=application/openlayers&bbox=-85.5,-180.0,90.0,180.0"; // String wmsRequest = "http://thredds-d-d4s.d4science.org/thredds/wms/public/netcdf/test20.nc?service=wms&version=1.3.0&request=GetMap&layers=analyzed_field&styles=&width=640&height=480&srs=EPSG:4326&CRS=EPSG:4326&format=image/png&COLORSCALERANGE=auto&bbox=-85.0,-180.0,85.0,180.0"; @@ -28,16 +33,14 @@ public class GeoJUnitTest { GeoNcWMSMetadataUtility geo; try { geo = new GeoNcWMSMetadataUtility(wmsRequest); - System.out.println("Returned styles: "+geo.loadStyles()); - } - catch (Exception e) { + System.out.println("Returned styles: " + geo.loadStyles()); + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } - /** * Test get styles. */ @@ -49,9 +52,8 @@ public class GeoJUnitTest { GeoNcWMSMetadataUtility geo; try { geo = new GeoNcWMSMetadataUtility(wmsRequest); - System.out.println("Returned Z-Axis: "+geo.loadZAxis()); - } - catch (Exception e) { + System.out.println("Returned Z-Axis: " + geo.loadZAxis()); + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } @@ -68,9 +70,65 @@ public class GeoJUnitTest { WmsUrlValidator wms; try { wms = new WmsUrlValidator(wmsRequest); - System.out.println("Returned wms: "+wms.toString()); + System.out.println("Returned wms: " + wms.toString()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); } - catch (Exception e) { + + } + + //@Test + public void testWFSRequest() { + String wfsEndPoint = "https://geoserver1.dev.d4science.org/geoserver/devvre/wfs"; + try { + //REGIONI + String layerName = "devvre:Reg01012021_g_WGS84"; + List propertyName = new ArrayList(); + propertyName.add("devvre:COD_REG"); + propertyName.add("devvre:DEN_REG"); + //Querying list of Regioni + WFSQueryBuilder queryBuilder = new WFSQueryBuilder(); + queryBuilder.addParameter(WFSParameter.SERVICE, WFSParameter.SERVICE.getValue()); + queryBuilder.addParameter(WFSParameter.VERSION, "2.0.0"); + queryBuilder.addParameter(WFSParameter.REQUEST, "GetFeature"); + queryBuilder.addParameter(WFSParameter.TYPENAME, layerName); + queryBuilder.addParameter(WFSParameter.OUTPUTFORMAT, WFSParameter.OUTPUTFORMAT.getValue()); + queryBuilder.addParameter(WFSParameter.PROPERTYNAME, propertyName, ","); + FeatureParser fp = new FeatureParser(); + List rows = fp.getWFSFeatures(wfsEndPoint, queryBuilder); + System.out.println("Regioni: "); + for (FeatureRow featureRow : rows) { + System.out.println(featureRow); + } + + + //PROVINCE + layerName = "devvre:ProvCM01012021_g_WGS84"; + propertyName = new ArrayList(); + propertyName.add("devvre:COD_REG"); + propertyName.add("devvre:COD_PROV"); + propertyName.add("devvre:DEN_PROV"); + propertyName.add("devvre:DEN_CM"); //รจ pieno per i capoluoghi di provincia + + queryBuilder = new WFSQueryBuilder(); + queryBuilder.addParameter(WFSParameter.SERVICE, WFSParameter.SERVICE.getValue()); + queryBuilder.addParameter(WFSParameter.VERSION, "2.0.0"); + queryBuilder.addParameter(WFSParameter.REQUEST, "GetFeature"); + queryBuilder.addParameter(WFSParameter.TYPENAME, layerName); + queryBuilder.addParameter(WFSParameter.OUTPUTFORMAT, WFSParameter.OUTPUTFORMAT.getValue()); + queryBuilder.addParameter(WFSParameter.PROPERTYNAME, propertyName, ","); + queryBuilder.addParameter(WFSParameter.CQL_FILTER, URLEncoder.encode("devvre:COD_REG=9", "UTF-8")); + fp = new FeatureParser(); + rows = fp.getWFSFeatures(wfsEndPoint, queryBuilder); + System.out.println("PROVINCE: "); + for (FeatureRow featureRow : rows) { + System.out.println(featureRow); + } + + + System.out.println(queryBuilder.getQuery()); + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } diff --git a/src/test/resources/.gitignore b/src/test/resources/.gitignore new file mode 100644 index 0000000..3197e17 --- /dev/null +++ b/src/test/resources/.gitignore @@ -0,0 +1,6 @@ +/devNext.gcubekey +/devsec.gcubekey +/gcube.gcubekey +/log4j.properties +/pred4s.gcubekey +/preprod.gcubekey