diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 06076833d..ff901e9db 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,4 +1,4 @@ [cygnus-ngsi] [mongo-sink] Add mongo_ssl, mongo_ssl_invalid_host_allowed, mongo_ssl_keystore_path_file, mongo_ssl_keystore_password, mongo_ssl_truststore_path_file and mongo_ssl_truststore_password options for mongoDB connections [cygnus-common] [mongo-backend] Use sslEnabled, sslInvalidHostNameAllowed, sslKeystorePathFile, sslKeystorePassword, sslTruststorePathFile and sslTruststorePassword options for mongoDB connections [cygnus-common] [mongo-backend] Allow mongodb autodiscover at connect when just one server is provided -[cygnus-ngsi] [arcgis-sink] Add esri Geometry PolyLine support (#2392) +[cygnus-ngsi] [arcgis-sink] Add esri Geometry PolyLine, MultiPoint and Polygon support (#2392) diff --git a/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Feature.java b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Feature.java index 00c036ee0..796bf8c78 100644 --- a/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Feature.java +++ b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Feature.java @@ -168,6 +168,34 @@ public static Feature createPolyLineFeature(String paths) { } } + /** + * + * @param rings + * @return + */ + public static Feature createPolygonFeature(String rings) { + try { + return new Feature(new Polygon(rings)); + } catch (Exception e) { + LOGGER.error(e.getClass().getSimpleName() + " " + e.getMessage()); + return null; + } + } + + /** + * + * @param points + * @return + */ + public static Feature createMultiPointFeature(String points) { + try { + return new Feature(new MultiPoint(points)); + } catch (Exception e) { + LOGGER.error(e.getClass().getSimpleName() + " " + e.getMessage()); + return null; + } + } + /** * This method merges unexistent attributes from sourceFeature. * @@ -332,11 +360,10 @@ public static Feature createInstanceFromJson(JsonObject json) throws ArcgisExcep geometry = Point.createInstanceFromJson(jsonGeometry); } else if (jsonGeometry.get("paths") != null) { geometry = PolyLine.createInstanceFromJson(jsonGeometry); - // FIXME when MultiPoint and Polygon will be implemented - // } else if (jsonGeometry.get("points") != null) { - // // geometry = MultiPoint.createInstance(jsonGeometry); - // } else if (jsonGeometry.get("rings") != null) { - // // geometry = Polygon.createInstance(jsonGeometry); + } else if (jsonGeometry.get("points") != null) { + geometry = MultiPoint.createInstanceFromJson(jsonGeometry); + } else if (jsonGeometry.get("rings") != null) { + geometry = Polygon.createInstanceFromJson(jsonGeometry); } } } diff --git a/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/MultiPoint.java b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/MultiPoint.java new file mode 100644 index 000000000..555f4292f --- /dev/null +++ b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/MultiPoint.java @@ -0,0 +1,196 @@ +/** + * Copyright 2014-2017 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-cygnus (FIWARE project). + * + * fiware-cygnus is free software: you can redistribute it and/or modify it under the terms of the GNU Affero + * General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * fiware-cygnus 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License along with fiware-cygnus. If not, see + * http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License please contact with iot_support at tid dot es + */ + +package com.telefonica.iot.cygnus.backends.arcgis.model; + +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; + +import com.telefonica.iot.cygnus.backends.arcgis.exceptions.ArcgisException; +import com.telefonica.iot.cygnus.log.CygnusLogger; + +/** + * + * @author avega + * + */ +public class MultiPoint implements Geometry { + private static final CygnusLogger LOGGER = new CygnusLogger(MultiPoint.class); + + private static final String SPATIAL_REFERENCE_TAG = "spatialReference"; + private static final String WKID_TAG = "wkid"; + private static final String POINTS_TAG = "points"; + + public List points; + + private SpatialReference spatialReference; + private int type = Geometry.TYPE_SHAPE; // TBD + + /** + * Constructor. + * + * @param points + * @param spatialReference + */ + public MultiPoint(List points, SpatialReference spatialReference) { + this.points = points; + this.spatialReference = spatialReference; + } + + /** + * Constructor. + * + * @param points + */ + public MultiPoint(List points) { + this(points, SpatialReference.WGS84); + } + + /** + * SetValue. + */ + public void setValue(Geometry g) throws ArcgisException { + if (g.getGeometryType() == Geometry.TYPE_SHAPE) { + MultiPoint multipoint = (MultiPoint) g; + this.points = multipoint.points; + } else { + throw new ArcgisException("Invalid Geometry Type, MultiPoint expected."); + } + } + + /** + * Constructor. + * + * @param strPoint + * @throws ArcgisException + */ + public MultiPoint(String strPolyline) throws ArcgisException { + try { + JsonObject jsonObject = JsonParser.parseString(strPolyline).getAsJsonObject(); + String thePointsStr = jsonObject.get("points").toString(); + Gson gson = new Gson(); + Type listType = new TypeToken>() {}.getType(); + this.points = gson.fromJson(thePointsStr, listType); + this.spatialReference = SpatialReference.WGS84; + } catch (NumberFormatException e) { + LOGGER.error(e.getClass().getSimpleName() + " " + e.getMessage()); + throw new ArcgisException("Unexpected string format for type MultiPoint."); + } + } + + /** + * Sets Geometry From JSON. + */ + public void setGeometryFromJSON(String json) { + // TODO Auto-generated method stub + + } + + /** + * @return JsonObject + */ + public JsonObject toJSON() { + JsonObject result = new JsonObject(); + LOGGER.debug("toJSON "); + result.addProperty(POINTS_TAG, this.toString()); + + JsonObject spatialRef = new JsonObject(); + spatialRef.addProperty(WKID_TAG, spatialReference.getWkid()); + + result.add(SPATIAL_REFERENCE_TAG, spatialRef); + return result; + } + + /** + * Factroy method. + * + * @param json + * @return + * @throws ArcgisException + */ + public static Geometry createInstanceFromJson(JsonObject json) throws ArcgisException { + try { + return new MultiPoint(json.get(POINTS_TAG).getAsString()); + } catch (Exception e) { + LOGGER.error(e.getClass().getSimpleName() + " " + e.getMessage()); + throw new ArcgisException("Unable to parse MultiPoint from json " + e.getMessage()); + } + + } + + /** + * @return String + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{ \"points\": ["); + for (int i = 0; i < this.points.size(); i++) { + sb.append("["); + double[] array = points.get(i); + for (double value : array) { + sb.append(" ").append(value).append(","); + } + sb.setLength(sb.length() - 2); + sb.append(" ],"); + } + sb.setLength(sb.length() - 2); + sb.append(" ]}"); + return sb.toString(); + } + + /** + * @return geometry type + */ + public int getGeometryType() { + return type; + } + + /** + * + */ + public void setSpatialReference(SpatialReference spatialReference) { + this.spatialReference = spatialReference; + } + + /** + * + */ + public SpatialReference getSpatialReference() { + return this.spatialReference; + } + + /** + * + * @return + */ + public List getPoints() { + return this.points; + } + + @Override + public Object getValue() { + return null; + } + +} diff --git a/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/PolyLine.java b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/PolyLine.java index a6a625d1c..bfc2ddcdb 100644 --- a/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/PolyLine.java +++ b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/PolyLine.java @@ -61,8 +61,7 @@ public PolyLine(List> paths, SpatialReference spatialReference) { /** * Constructor. * - * @param lat - * @param lng + * @param paths */ public PolyLine(List> paths) { this(paths, SpatialReference.WGS84); @@ -76,7 +75,7 @@ public void setValue(Geometry g) throws ArcgisException { PolyLine polyline = (PolyLine) g; this.paths = polyline.paths; } else { - throw new ArcgisException("Invalid Geometry Type, Point expected."); + throw new ArcgisException("Invalid Geometry Type, PolyLine expected."); } } diff --git a/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Polygon.java b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Polygon.java new file mode 100644 index 000000000..4466831df --- /dev/null +++ b/cygnus-common/src/main/java/com/telefonica/iot/cygnus/backends/arcgis/model/Polygon.java @@ -0,0 +1,201 @@ +/** + * Copyright 2014-2017 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-cygnus (FIWARE project). + * + * fiware-cygnus is free software: you can redistribute it and/or modify it under the terms of the GNU Affero + * General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * fiware-cygnus 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License along with fiware-cygnus. If not, see + * http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License please contact with iot_support at tid dot es + */ + +package com.telefonica.iot.cygnus.backends.arcgis.model; + +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; + +import com.telefonica.iot.cygnus.backends.arcgis.exceptions.ArcgisException; +import com.telefonica.iot.cygnus.log.CygnusLogger; + +/** + * + * @author avega + * + */ +public class Polygon implements Geometry { + private static final CygnusLogger LOGGER = new CygnusLogger(Polygon.class); + + private static final String SPATIAL_REFERENCE_TAG = "spatialReference"; + private static final String WKID_TAG = "wkid"; + private static final String RINGS_TAG = "rings"; + + public List> rings; + + private SpatialReference spatialReference; + private int type = Geometry.TYPE_SHAPE; // TBD + + /** + * Constructor. + * + * @param rings + * @param spatialReference + */ + public Polygon(List> rings, SpatialReference spatialReference) { + this.rings = rings; + this.spatialReference = spatialReference; + } + + /** + * Constructor. + * + * @param rings + */ + public Polygon(List> rings) { + this(rings, SpatialReference.WGS84); + } + + /** + * SetValue. + */ + public void setValue(Geometry g) throws ArcgisException { + if (g.getGeometryType() == Geometry.TYPE_SHAPE) { + Polygon polygon = (Polygon) g; + this.rings = polygon.rings; + } else { + throw new ArcgisException("Invalid Geometry Type, Polygon expected."); + } + } + + /** + * Constructor. + * + * @param strPoint + * @throws ArcgisException + */ + public Polygon(String strPolyline) throws ArcgisException { + try { + JsonObject jsonObject = JsonParser.parseString(strPolyline).getAsJsonObject(); + String theRingsStr = jsonObject.get("rings").toString(); + Gson gson = new Gson(); + Type listType = new TypeToken>>() {}.getType(); + this.rings = gson.fromJson(theRingsStr, listType); + this.spatialReference = SpatialReference.WGS84; + } catch (NumberFormatException e) { + LOGGER.error(e.getClass().getSimpleName() + " " + e.getMessage()); + throw new ArcgisException("Unexpected string format for type Polygon."); + } + } + + /** + * Sets Geometry From JSON. + */ + public void setGeometryFromJSON(String json) { + // TODO Auto-generated method stub + + } + + /** + * @return JsonObject + */ + public JsonObject toJSON() { + JsonObject result = new JsonObject(); + LOGGER.debug("toJSON "); + result.addProperty(RINGS_TAG, this.toString()); + + JsonObject spatialRef = new JsonObject(); + spatialRef.addProperty(WKID_TAG, spatialReference.getWkid()); + + result.add(SPATIAL_REFERENCE_TAG, spatialRef); + return result; + } + + /** + * Factroy method. + * + * @param json + * @return + * @throws ArcgisException + */ + public static Geometry createInstanceFromJson(JsonObject json) throws ArcgisException { + try { + return new Polygon(json.get(RINGS_TAG).getAsString()); + } catch (Exception e) { + LOGGER.error(e.getClass().getSimpleName() + " " + e.getMessage()); + throw new ArcgisException("Unable to parse Polygon from json " + e.getMessage()); + } + + } + + /** + * @return String + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{ \"rings\": ["); + for (int i = 0; i < this.rings.size(); i++) { + List innerList = this.rings.get(i); + for (int j = 0; j < innerList.size(); j++) { + sb.append(" ["); + sb.append("["); + double[] array = innerList.get(j); + for (double value : array) { + sb.append(" ").append(value).append(","); + } + sb.append(" ]"); + sb.setLength(sb.length() - 2); + sb.append(" ],"); + } + } + sb.setLength(sb.length() - 2); + sb.append(" ]}"); + return sb.toString(); + } + + /** + * @return geometry type + */ + public int getGeometryType() { + return type; + } + + /** + * + */ + public void setSpatialReference(SpatialReference spatialReference) { + this.spatialReference = spatialReference; + } + + /** + * + */ + public SpatialReference getSpatialReference() { + return this.spatialReference; + } + + /** + * + * @return + */ + public List> getRings() { + return this.rings; + } + + @Override + public Object getValue() { + return null; + } + +} diff --git a/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTest.java b/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTest.java index 32a3aa579..529212cfe 100644 --- a/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTest.java +++ b/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTest.java @@ -37,6 +37,8 @@ import com.telefonica.iot.cygnus.backends.arcgis.exceptions.ArcgisException; import com.telefonica.iot.cygnus.backends.arcgis.model.Feature; import com.telefonica.iot.cygnus.backends.arcgis.model.PolyLine; +import com.telefonica.iot.cygnus.backends.arcgis.model.Polygon; +import com.telefonica.iot.cygnus.backends.arcgis.model.MultiPoint; import java.util.List; import java.util.Arrays; @@ -173,16 +175,57 @@ public void getPolyFeatureTest() { System.out.println("---------------- getNewPolyLineFeature"); try { String paths = "{ \"paths\": [ [ [-97.06138, 32.837], [-97.06133, 33.836], [-98.2, 34.834], [-97, 40] ] ] }"; - PolyLine poly = new PolyLine(paths); - System.out.println("POLY: " + poly.toString()); + PolyLine polyline = new PolyLine(paths); + System.out.println("POLYLINE: " + polyline.toString()); } catch (Exception e) { System.out.println("Exception"); System.out.println(e.getClass().getSimpleName() + " " + e.getMessage()); } - Feature poly = FeatureTestFactory.getNewPolyLineFeature("Mi PolyLine", 33); - System.out.println("feature poly - " + poly.toJson()); + Feature polyline = FeatureTestFactory.getNewPolyLineFeature("Mi PolyLine", 33); + System.out.println("feature with polyline - " + polyline.toJson()); assertTrue("ok.", true); } + + /** + * + */ + @Test + public void getPolygonTest() { + System.out.println("---------------- getNewPolygonFeature"); + try { + String rings = "{ \"rings\": [ [ [-97.06138,32.837,35.1,4.8], [-97.06133,32.836,35.2,4.1], [-97.06124,32.834,35.3,4.2], [-97.06138,32.837,35.1,4.8] ], [ [-97.06326,32.759,35.4], [-97.06298,32.755,35.5], [-97.06153,32.749,35.6], [-97.06326,32.759,35.4] ] ] }"; + Polygon poly = new Polygon(rings); + System.out.println("POLYGON: " + poly.toString()); + + } catch (Exception e) { + System.out.println("Exception"); + System.out.println(e.getClass().getSimpleName() + " " + e.getMessage()); + } + Feature polygon = FeatureTestFactory.getNewPolygonFeature("Mi Polygon", 33); + System.out.println("feature with polygon - " + polygon.toJson()); + assertTrue("ok.", true); + } + + /** + * + */ + @Test + public void getMultiPointTest() { + System.out.println("---------------- getNewMultiPointFeature"); + try { + String points = "{ \"points\": [ [-97.06138, 32.837], [-97.06133, 33.836], [-98.2, 34.834], [-97, 40] ] }"; + MultiPoint multipoint = new MultiPoint(points); + System.out.println("MULTIPOINT: " + multipoint.toString()); + + } catch (Exception e) { + System.out.println("Exception"); + System.out.println(e.getClass().getSimpleName() + " " + e.getMessage()); + } + Feature multipoint = FeatureTestFactory.getNewMultiPointFeature("Mi MultiPoint", 33); + System.out.println("feature with multipoint - " + multipoint.toJson()); + assertTrue("ok.", true); + } + } diff --git a/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTestFactory.java b/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTestFactory.java index d44d6a5c1..c4aa9feab 100644 --- a/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTestFactory.java +++ b/cygnus-common/src/test/java/com/telefonica/iot/cygnus/backends/arcgis/FeatureTestFactory.java @@ -143,6 +143,74 @@ public static Feature getNewPolyLineFeature(String description, Integer external return feature; } + /** + * + * @param description + * @param externalId + * @return + */ + public static Feature getNewPolygonFeature(String description, Integer externalId) { + Map attributes = new LinkedHashMap(); + attributes.put("IDEXTERNO", externalId); + attributes.put("DESCRIPCION", description); + attributes.put("RAZONSOCIAL", "Razon social"); + attributes.put("NUMEROPOSTAL", null); + attributes.put("TIPOOCUPACION", 0); + attributes.put("FINI", new Date()); + attributes.put("UNIDADMEDIDA", null); + attributes.put("EXCSABDOM", 0); + attributes.put("EXCFESTIVOS", 0); + attributes.put("PRESENCIAPOLICIAL", 0); + attributes.put("REVISADO", 0); + attributes.put("IDACTIVIDAD", 0); + attributes.put("ACTIVIDAD", "actividad"); + attributes.put("IDCLASE", 0); + attributes.put("CLASE", "clase"); + attributes.put("IDESTADO", 0); + attributes.put("ESTADO", "estado"); + attributes.put("CALLE", "calle"); + attributes.put("FFIN", new GregorianCalendar()); + attributes.put("CANTIDADOCUPADA", null); + String jsonString = "{ \"rings\": [ [ [-97.06138,32.837,35.1,4.8], [-97.06133,32.836,35.2,4.1], [-97.06124,32.834,35.3,4.2], [-97.06138,32.837,35.1,4.8] ], [ [-97.06326,32.759,35.4], [-97.06298,32.755,35.5], [-97.06153,32.749,35.6], [-97.06326,32.759,35.4] ] ] }"; + Feature feature = Feature.createPolygonFeature(jsonString); + feature.setAttributes(attributes); + return feature; + } + + /** + * + * @param description + * @param externalId + * @return + */ + public static Feature getNewMultiPointFeature(String description, Integer externalId) { + Map attributes = new LinkedHashMap(); + attributes.put("IDEXTERNO", externalId); + attributes.put("DESCRIPCION", description); + attributes.put("RAZONSOCIAL", "Razon social"); + attributes.put("NUMEROPOSTAL", null); + attributes.put("TIPOOCUPACION", 0); + attributes.put("FINI", new Date()); + attributes.put("UNIDADMEDIDA", null); + attributes.put("EXCSABDOM", 0); + attributes.put("EXCFESTIVOS", 0); + attributes.put("PRESENCIAPOLICIAL", 0); + attributes.put("REVISADO", 0); + attributes.put("IDACTIVIDAD", 0); + attributes.put("ACTIVIDAD", "actividad"); + attributes.put("IDCLASE", 0); + attributes.put("CLASE", "clase"); + attributes.put("IDESTADO", 0); + attributes.put("ESTADO", "estado"); + attributes.put("CALLE", "calle"); + attributes.put("FFIN", new GregorianCalendar()); + attributes.put("CANTIDADOCUPADA", null); + String jsonString = "{ \"points\": [ [-97.06138, 32.837], [-97.06133, 33.836], [-98.2, 34.834], [-97, 40] ] }"; + Feature feature = Feature.createMultiPointFeature(jsonString); + feature.setAttributes(attributes); + return feature; + } + /** * * @return