From 24ad5f2f22710ecf2a5077da0ec50d84b8a80de0 Mon Sep 17 00:00:00 2001 From: jampukka Date: Thu, 22 Jun 2023 14:19:00 +0300 Subject: [PATCH 1/6] Add support for writing GML3 geometry with y/x order --- .../java/fi/nls/oskari/util/GML3Writer.java | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java b/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java index 665d16384a..ed1b93691d 100755 --- a/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java +++ b/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java @@ -19,129 +19,138 @@ public class GML3Writer { public static void writeGeometry(XMLStreamWriter xsw, Geometry geometry) throws XMLStreamException { + writeGeometry(xsw, geometry, true); + } + + public static void writeGeometry(XMLStreamWriter xsw, Geometry geometry, boolean xyOrder) + throws XMLStreamException { if (geometry instanceof Point) { - writePoint(xsw, (Point) geometry); + writePoint(xsw, (Point) geometry, xyOrder); } else if (geometry instanceof LineString) { - writeLineString(xsw, (LineString) geometry); + writeLineString(xsw, (LineString) geometry, xyOrder); } else if (geometry instanceof Polygon) { - writePolygon(xsw, (Polygon) geometry); + writePolygon(xsw, (Polygon) geometry, xyOrder); } else if (geometry instanceof MultiPoint) { - writeMultiPoint(xsw, (MultiPoint) geometry); + writeMultiPoint(xsw, (MultiPoint) geometry, xyOrder); } else if (geometry instanceof MultiLineString) { - writeMultiLineString(xsw, (MultiLineString) geometry); + writeMultiLineString(xsw, (MultiLineString) geometry, xyOrder); } else if (geometry instanceof MultiPolygon) { - writeMultiPolygon(xsw, (MultiPolygon) geometry); + writeMultiPolygon(xsw, (MultiPolygon) geometry, xyOrder); } else if (geometry instanceof GeometryCollection) { - writeMultiGeometry(xsw, (GeometryCollection) geometry); + writeMultiGeometry(xsw, (GeometryCollection) geometry, xyOrder); } else { throw new IllegalArgumentException(); } } - private static void writePoint(XMLStreamWriter xsw, Point geometry) + private static void writePoint(XMLStreamWriter xsw, Point geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_POINT); writeSRID(xsw, geometry.getSRID()); - writePos(xsw, geometry.getCoordinate()); + writePos(xsw, geometry.getCoordinate(), xyOrder); xsw.writeEndElement(); } - private static void writeLineString(XMLStreamWriter xsw, LineString geometry) + private static void writeLineString(XMLStreamWriter xsw, LineString geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_LINESTRING); writeSRID(xsw, geometry.getSRID()); - writePosList(xsw, geometry.getCoordinates()); + writePosList(xsw, geometry.getCoordinates(), xyOrder); xsw.writeEndElement(); } - private static void writePolygon(XMLStreamWriter xsw, Polygon geometry) + private static void writePolygon(XMLStreamWriter xsw, Polygon geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_POLYGON); writeSRID(xsw, geometry.getSRID()); xsw.writeStartElement(GMLConstants.GML_NAMESPACE, "exterior"); - writeLinearRing(xsw, (LinearRing) geometry.getExteriorRing()); + writeLinearRing(xsw, (LinearRing) geometry.getExteriorRing(), xyOrder); xsw.writeEndElement(); for (int i = 0; i < geometry.getNumInteriorRing(); i++) { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, "interior"); - writeLinearRing(xsw, (LinearRing) geometry.getInteriorRingN(i)); + writeLinearRing(xsw, (LinearRing) geometry.getInteriorRingN(i), xyOrder); xsw.writeEndElement(); } xsw.writeEndElement(); } - private static void writeMultiPoint(XMLStreamWriter xsw, MultiPoint geometry) + private static void writeMultiPoint(XMLStreamWriter xsw, MultiPoint geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_MULTI_POINT); writeSRID(xsw, geometry.getSRID()); for (int i = 0; i < geometry.getNumGeometries(); i++) { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_POINT_MEMBER); - writePoint(xsw, (Point) geometry.getGeometryN(i)); + writePoint(xsw, (Point) geometry.getGeometryN(i), xyOrder); xsw.writeEndElement(); } xsw.writeEndElement(); } - private static void writeMultiLineString(XMLStreamWriter xsw, MultiLineString geometry) + private static void writeMultiLineString(XMLStreamWriter xsw, MultiLineString geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_MULTI_LINESTRING); writeSRID(xsw, geometry.getSRID()); for (int i = 0; i < geometry.getNumGeometries(); i++) { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_LINESTRING_MEMBER); - writeLineString(xsw, (LineString) geometry.getGeometryN(i)); + writeLineString(xsw, (LineString) geometry.getGeometryN(i), xyOrder); xsw.writeEndElement(); } xsw.writeEndElement(); } - private static void writeMultiPolygon(XMLStreamWriter xsw, MultiPolygon geometry) + private static void writeMultiPolygon(XMLStreamWriter xsw, MultiPolygon geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_MULTI_POLYGON); writeSRID(xsw, geometry.getSRID()); for (int i = 0; i < geometry.getNumGeometries(); i++) { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_POLYGON_MEMBER); - writePolygon(xsw, (Polygon) geometry.getGeometryN(i)); + writePolygon(xsw, (Polygon) geometry.getGeometryN(i), xyOrder); xsw.writeEndElement(); } xsw.writeEndElement(); } - private static void writeMultiGeometry(XMLStreamWriter xsw, GeometryCollection geometry) + private static void writeMultiGeometry(XMLStreamWriter xsw, GeometryCollection geometry, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_MULTI_GEOMETRY); writeSRID(xsw, geometry.getSRID()); for (int i = 0; i < geometry.getNumGeometries(); i++) { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_GEOMETRY_MEMBER); - writeGeometry(xsw, geometry.getGeometryN(i)); + writeGeometry(xsw, geometry.getGeometryN(i), xyOrder); xsw.writeEndElement(); } xsw.writeEndElement(); } - private static void writePos(XMLStreamWriter xsw, Coordinate coordinate) + private static void writePos(XMLStreamWriter xsw, Coordinate coordinate, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, "pos"); xsw.writeAttribute("srsDimension", "2"); - String pos = coordinate.x + " " + coordinate.y; + String pos = xyOrder ? coordinate.x + " " + coordinate.y : coordinate.y + " " + coordinate.x; xsw.writeCharacters(pos); xsw.writeEndElement(); } - private static void writePosList(XMLStreamWriter xsw, Coordinate[] coordinates) + private static void writePosList(XMLStreamWriter xsw, Coordinate[] coordinates, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, "posList"); xsw.writeAttribute("srsDimension", "2"); StringBuilder sb = new StringBuilder(); for (Coordinate coordinate : coordinates) { - sb.append(' ').append(coordinate.x).append(' ').append(coordinate.y); + if (xyOrder) { + sb.append(' ').append(coordinate.x).append(' ').append(coordinate.y); + } else { + sb.append(' ').append(coordinate.y).append(' ').append(coordinate.x); + } } xsw.writeCharacters(sb.substring(1)); xsw.writeEndElement(); } - private static void writeLinearRing(XMLStreamWriter xsw, LinearRing linearRing) + private static void writeLinearRing(XMLStreamWriter xsw, LinearRing linearRing, boolean xyOrder) throws XMLStreamException { xsw.writeStartElement(GMLConstants.GML_NAMESPACE, GMLConstants.GML_LINEARRING); - writePosList(xsw, linearRing.getCoordinates()); + writePosList(xsw, linearRing.getCoordinates(), xyOrder); xsw.writeEndElement(); } From 385fdf8e7557833d7c27bc24fb19b4705305b338 Mon Sep 17 00:00:00 2001 From: jampukka Date: Thu, 22 Jun 2023 14:19:30 +0300 Subject: [PATCH 2/6] Remove unused Logger --- .../nls/oskari/control/feature/FeatureWFSTRequestBuilder.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java index 999c98f88f..fe996af8a1 100755 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java @@ -2,8 +2,6 @@ import fi.nls.oskari.domain.map.Feature; -import fi.nls.oskari.log.LogFactory; -import fi.nls.oskari.log.Logger; import fi.nls.oskari.util.GML3Writer; import org.oskari.wfst.WFSTRequestBuilder; @@ -13,7 +11,6 @@ import java.util.Map; public class FeatureWFSTRequestBuilder extends WFSTRequestBuilder { - private final static Logger LOG = LogFactory.getLogger(FeatureWFSTRequestBuilder.class); public static void updateFeature(OutputStream out, Feature feature) throws XMLStreamException { From 728553b710805b134a31e62f79eff29cef73598c Mon Sep 17 00:00:00 2001 From: jampukka Date: Thu, 22 Jun 2023 14:43:01 +0300 Subject: [PATCH 3/6] Write wfs 1.1.0 geometry in y/x order if crs is north-east --- .../feature/FeatureWFSTRequestBuilder.java | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java index fe996af8a1..d7765e115f 100755 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java @@ -1,8 +1,11 @@ package fi.nls.oskari.control.feature; import fi.nls.oskari.domain.map.Feature; - +import fi.nls.oskari.map.geometry.ProjectionHelper; import fi.nls.oskari.util.GML3Writer; + +import org.locationtech.jts.geom.Geometry; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.oskari.wfst.WFSTRequestBuilder; import javax.xml.stream.XMLStreamException; @@ -12,8 +15,17 @@ public class FeatureWFSTRequestBuilder extends WFSTRequestBuilder { + @Deprecated + /** + * @deprecated see updateFeature(OutputStream, Feature, CoordinateReferenceSystem) + */ public static void updateFeature(OutputStream out, Feature feature) throws XMLStreamException { + updateFeature(out, feature, null); + } + + public static void updateFeature(OutputStream out, Feature feature, CoordinateReferenceSystem crs) + throws XMLStreamException { XMLStreamWriter xsw = XOF.createXMLStreamWriter(out); writeStartTransaction(xsw, "1.1.0"); @@ -34,7 +46,7 @@ public static void updateFeature(OutputStream out, Feature feature) xsw.writeEndElement(); } - writeGeometryProperty(xsw, feature); + writeGeometryProperty(xsw, feature, crs); writeFeatureIdFilter(xsw, feature.getId()); xsw.writeEndElement(); // close @@ -43,8 +55,17 @@ public static void updateFeature(OutputStream out, Feature feature) xsw.close(); } + @Deprecated + /** + * @deprecated see insertFeature(OutputStream, Feature, CoordinateReferenceSystem) + */ public static void insertFeature(OutputStream out, Feature feature) throws XMLStreamException { + insertFeature(out, feature, null); + } + + public static void insertFeature(OutputStream out, Feature feature, CoordinateReferenceSystem crs) + throws XMLStreamException { XMLStreamWriter xsw = XOF.createXMLStreamWriter(out); writeStartTransaction(xsw, "1.1.0"); @@ -59,7 +80,7 @@ public static void insertFeature(OutputStream out, Feature feature) if (feature.hasGeometry()) { xsw.writeStartElement(feature.getGMLGeometryProperty()); - GML3Writer.writeGeometry(xsw, feature.getGeometry()); + writeGeometry(xsw, feature.getGeometry(), crs); xsw.writeEndElement(); } @@ -86,7 +107,7 @@ public static void deleteFeature(OutputStream out, Feature feature) xsw.close(); } - private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature) throws XMLStreamException { + private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature, CoordinateReferenceSystem crs) throws XMLStreamException { if(!feature.hasGeometry()) { return; } @@ -98,10 +119,18 @@ private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature) xsw.writeEndElement(); xsw.writeStartElement(WFS, "Value"); - GML3Writer.writeGeometry(xsw, feature.getGeometry()); + writeGeometry(xsw, feature.getGeometry(), crs); xsw.writeEndElement(); xsw.writeEndElement(); } + private static void writeGeometry(XMLStreamWriter xsw, Geometry geometry, CoordinateReferenceSystem crs) throws XMLStreamException { + boolean xyOrder = true; + if (crs != null) { + xyOrder = ProjectionHelper.isFirstAxisNorth(crs); + } + GML3Writer.writeGeometry(xsw, geometry, xyOrder); + } + } From 59ca41f022e42d4d1db47471a4b3206c6cfa1706 Mon Sep 17 00:00:00 2001 From: jampukka Date: Thu, 22 Jun 2023 14:45:23 +0300 Subject: [PATCH 4/6] Provide target coordRefSys to WFS-T request builder --- .../feature/FeatureWFSTRequestBuilder.java | 2 +- .../feature/VectorFeatureWriterHandler.java | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java index d7765e115f..57e82f500c 100755 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java @@ -128,7 +128,7 @@ private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature, private static void writeGeometry(XMLStreamWriter xsw, Geometry geometry, CoordinateReferenceSystem crs) throws XMLStreamException { boolean xyOrder = true; if (crs != null) { - xyOrder = ProjectionHelper.isFirstAxisNorth(crs); + xyOrder = !ProjectionHelper.isFirstAxisNorth(crs); } GML3Writer.writeGeometry(xsw, geometry, xyOrder); } diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java b/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java index 6b27eb516f..3f4a02a29b 100644 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java @@ -12,9 +12,12 @@ import fi.nls.oskari.util.JSONHelper; import fi.nls.oskari.util.ResponseHelper; import fi.nls.oskari.util.XmlHelper; + +import org.geotools.referencing.CRS; import org.json.JSONException; import org.json.JSONObject; import org.opengis.referencing.FactoryException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -74,10 +77,12 @@ public void handlePost(ActionParameters params) throws ActionException { } try { + CoordinateReferenceSystem coordRefSys = CRS.decode(crs); + JSONObject geojson = params.getPayLoadJSON(); Feature feature = getFeature(geojson, layerId, crs, geojson.optString("id")); - final String wfstMessage = createWFSTMessageForInsert(feature); + final String wfstMessage = createWFSTMessageForInsert(feature, coordRefSys); LOG.debug("Inserting feature to service at", layer.getUrl(), "with payload:\n", wfstMessage); final String responseString = postPayload(layer.getUsername(), layer.getPassword(), wfstMessage, getURLForNamespace(layer.getName(),layer.getUrl())); @@ -106,10 +111,12 @@ public void handlePut(ActionParameters params) throws ActionException { } try { + CoordinateReferenceSystem coordRefSys = CRS.decode(crs); + JSONObject geojson = params.getPayLoadJSON(); Feature feature = getFeature(geojson, layerId, crs, geojson.optString("id")); - final String wfstMessage = createWFSTMessageForUpdate(feature); + final String wfstMessage = createWFSTMessageForUpdate(feature, coordRefSys); LOG.debug("Updating feature to service at", layer.getUrl(), "with payload:\n", wfstMessage); String responseString = postPayload(layer.getUsername(), layer.getPassword(), wfstMessage, getURLForNamespace(layer.getName(),layer.getUrl())); @@ -126,21 +133,21 @@ public void handlePut(ActionParameters params) throws ActionException { } } - private String createWFSTMessageForUpdate(Feature feature) + private String createWFSTMessageForUpdate(Feature feature, CoordinateReferenceSystem crs) throws ActionException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FeatureWFSTRequestBuilder.updateFeature(baos, feature); + FeatureWFSTRequestBuilder.updateFeature(baos, feature, crs); return baos.toString(); } catch (XMLStreamException e) { throw new ActionException("Failed to create WFS-T request", e); } } - private String createWFSTMessageForInsert(Feature feature) + private String createWFSTMessageForInsert(Feature feature, CoordinateReferenceSystem coordRefSys) throws ActionException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FeatureWFSTRequestBuilder.insertFeature(baos, feature); + FeatureWFSTRequestBuilder.insertFeature(baos, feature, coordRefSys); return baos.toString(); } catch (XMLStreamException e) { throw new ActionException("Failed to create WFS-T request", e); From fcb9ee2e9fe27ee47be2b3f720084c572dccfb5a Mon Sep 17 00:00:00 2001 From: jampukka Date: Thu, 22 Jun 2023 15:24:44 +0300 Subject: [PATCH 5/6] Add unit tests, change private methods to package-private static for easier testing --- .../feature/VectorFeatureWriterHandler.java | 5 +- .../VectorFeatureWriterHandlerTest.java | 100 ++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java b/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java index 3f4a02a29b..6edede5a38 100644 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java @@ -133,7 +133,7 @@ public void handlePut(ActionParameters params) throws ActionException { } } - private String createWFSTMessageForUpdate(Feature feature, CoordinateReferenceSystem crs) + static String createWFSTMessageForUpdate(Feature feature, CoordinateReferenceSystem crs) throws ActionException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -143,7 +143,8 @@ private String createWFSTMessageForUpdate(Feature feature, CoordinateReferenceSy throw new ActionException("Failed to create WFS-T request", e); } } - private String createWFSTMessageForInsert(Feature feature, CoordinateReferenceSystem coordRefSys) + + static String createWFSTMessageForInsert(Feature feature, CoordinateReferenceSystem coordRefSys) throws ActionException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java b/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java new file mode 100644 index 0000000000..ed27bacece --- /dev/null +++ b/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java @@ -0,0 +1,100 @@ +package fi.nls.oskari.control.feature; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.geotools.referencing.CRS; +import org.junit.Test; +import org.locationtech.jts.geom.CoordinateSequence; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import fi.nls.oskari.domain.map.Feature; + +public class VectorFeatureWriterHandlerTest { + + @Test + public void testUpdateXYAxisOrder() throws Exception { + String epsg = "EPSG:3067"; + CoordinateReferenceSystem crs = CRS.decode(epsg); + + double[] pts = { + 473183.20423224,6680301.618281904, + 473257.20423224,6680411.618281904, + 473365.70423224,6680308.118281904, + 473251.20423224,6680215.618281904, + 473183.20423224,6680301.618281904 + }; + + Feature oskariFeature = new Feature(); + oskariFeature.setLayerName("foo"); + oskariFeature.setId("12345"); + oskariFeature.setProperties(new HashMap<>()); + oskariFeature.setGMLGeometryProperty("geometry"); + oskariFeature.setGeometry(createPolygon(pts)); + + String wfsTransaction = VectorFeatureWriterHandler.createWFSTMessageForUpdate(oskariFeature, crs); + double[] actual = readPosList(wfsTransaction); + + assertArrayEquals(pts, actual, 1e-10); + } + + @Test + public void testInsertYXAxisOrder() throws Exception { + String epsg = "EPSG:3879"; + CoordinateReferenceSystem crs = CRS.decode(epsg); + + double[] pts = { + 25473183.20423224,6680301.618281904, + 25473257.20423224,6680411.618281904, + 25473365.70423224,6680308.118281904, + 25473251.20423224,6680215.618281904, + 25473183.20423224,6680301.618281904 + }; + + Feature oskariFeature = new Feature(); + oskariFeature.setLayerName("foo"); + oskariFeature.setProperties(new HashMap<>()); + oskariFeature.setGMLGeometryProperty("geometry"); + oskariFeature.setGeometry(createPolygon(pts)); + + String wfsTransaction = VectorFeatureWriterHandler.createWFSTMessageForInsert(oskariFeature, crs); + double[] actual = readPosList(wfsTransaction); + for (int i = 0; i < pts.length / 2; i++) { + assertEquals(pts[i * 2 + 0], actual[i * 2 + 1], 1e-10); + assertEquals(pts[i * 2 + 1], actual[i * 2 + 0], 1e-10); + } + } + + private Polygon createPolygon(double[] pts) { + GeometryFactory gf = new GeometryFactory(); + CoordinateSequence seq = gf.getCoordinateSequenceFactory().create(pts.length / 2, 2); + for (int i = 0; i < pts.length / 2; i++) { + seq.setOrdinate(i, 0, pts[i * 2 + 0]); + seq.setOrdinate(i, 1, pts[i * 2 + 1]); + } + return gf.createPolygon(seq); + } + + private double[] readPosList(String wfsTransaction) throws SAXException, IOException, ParserConfigurationException { + byte[] wfsTransactionUTF8 = wfsTransaction.getBytes(StandardCharsets.UTF_8); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + Document doc = dbf.newDocumentBuilder().parse(new ByteArrayInputStream(wfsTransactionUTF8)); + String posList = doc.getElementsByTagNameNS("http://www.opengis.net/gml", "posList").item(0).getTextContent(); + return Arrays.stream(posList.split(" ")).mapToDouble(Double::parseDouble).toArray(); + } + +} From 93dad11240edb24f20b88386fef89183ef15c47c Mon Sep 17 00:00:00 2001 From: jampukka Date: Fri, 4 Aug 2023 14:01:59 +0300 Subject: [PATCH 6/6] Revert some changes --- .../feature/FeatureWFSTRequestBuilder.java | 45 +++++++++---------- .../feature/VectorFeatureWriterHandler.java | 16 +++---- .../VectorFeatureWriterHandlerTest.java | 21 ++++----- .../java/fi/nls/oskari/util/GML3Writer.java | 6 ++- 4 files changed, 40 insertions(+), 48 deletions(-) diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java index 57e82f500c..c6ad28bcaf 100755 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/FeatureWFSTRequestBuilder.java @@ -1,10 +1,14 @@ package fi.nls.oskari.control.feature; import fi.nls.oskari.domain.map.Feature; +import fi.nls.oskari.log.LogFactory; +import fi.nls.oskari.log.Logger; import fi.nls.oskari.map.geometry.ProjectionHelper; import fi.nls.oskari.util.GML3Writer; +import org.geotools.referencing.CRS; import org.locationtech.jts.geom.Geometry; +import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.oskari.wfst.WFSTRequestBuilder; @@ -15,16 +19,9 @@ public class FeatureWFSTRequestBuilder extends WFSTRequestBuilder { - @Deprecated - /** - * @deprecated see updateFeature(OutputStream, Feature, CoordinateReferenceSystem) - */ - public static void updateFeature(OutputStream out, Feature feature) - throws XMLStreamException { - updateFeature(out, feature, null); - } + private final static Logger LOG = LogFactory.getLogger(FeatureWFSTRequestBuilder.class); - public static void updateFeature(OutputStream out, Feature feature, CoordinateReferenceSystem crs) + public static void updateFeature(OutputStream out, Feature feature) throws XMLStreamException { XMLStreamWriter xsw = XOF.createXMLStreamWriter(out); writeStartTransaction(xsw, "1.1.0"); @@ -46,7 +43,7 @@ public static void updateFeature(OutputStream out, Feature feature, CoordinateRe xsw.writeEndElement(); } - writeGeometryProperty(xsw, feature, crs); + writeGeometryProperty(xsw, feature); writeFeatureIdFilter(xsw, feature.getId()); xsw.writeEndElement(); // close @@ -55,17 +52,8 @@ public static void updateFeature(OutputStream out, Feature feature, CoordinateRe xsw.close(); } - @Deprecated - /** - * @deprecated see insertFeature(OutputStream, Feature, CoordinateReferenceSystem) - */ public static void insertFeature(OutputStream out, Feature feature) throws XMLStreamException { - insertFeature(out, feature, null); - } - - public static void insertFeature(OutputStream out, Feature feature, CoordinateReferenceSystem crs) - throws XMLStreamException { XMLStreamWriter xsw = XOF.createXMLStreamWriter(out); writeStartTransaction(xsw, "1.1.0"); @@ -80,7 +68,7 @@ public static void insertFeature(OutputStream out, Feature feature, CoordinateRe if (feature.hasGeometry()) { xsw.writeStartElement(feature.getGMLGeometryProperty()); - writeGeometry(xsw, feature.getGeometry(), crs); + writeGeometry(xsw, feature.getGeometry()); xsw.writeEndElement(); } @@ -107,7 +95,7 @@ public static void deleteFeature(OutputStream out, Feature feature) xsw.close(); } - private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature, CoordinateReferenceSystem crs) throws XMLStreamException { + private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature) throws XMLStreamException { if(!feature.hasGeometry()) { return; } @@ -119,16 +107,23 @@ private static void writeGeometryProperty(XMLStreamWriter xsw, Feature feature, xsw.writeEndElement(); xsw.writeStartElement(WFS, "Value"); - writeGeometry(xsw, feature.getGeometry(), crs); + writeGeometry(xsw, feature.getGeometry()); xsw.writeEndElement(); xsw.writeEndElement(); } - private static void writeGeometry(XMLStreamWriter xsw, Geometry geometry, CoordinateReferenceSystem crs) throws XMLStreamException { + private static void writeGeometry(XMLStreamWriter xsw, Geometry geometry) throws XMLStreamException { boolean xyOrder = true; - if (crs != null) { - xyOrder = !ProjectionHelper.isFirstAxisNorth(crs); + if (geometry.getSRID() != 0) { + String srsName = GML3Writer.getSrsName(geometry.getSRID()); + try { + CoordinateReferenceSystem crs = CRS.decode(srsName); + xyOrder = !ProjectionHelper.isFirstAxisNorth(crs); + LOG.debug("srsName:", srsName, "xyOrder:", xyOrder); + } catch (FactoryException e) { + LOG.warn(e); + } } GML3Writer.writeGeometry(xsw, geometry, xyOrder); } diff --git a/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java b/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java index 6edede5a38..36e38e9a68 100644 --- a/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java +++ b/control-base/src/main/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandler.java @@ -77,12 +77,10 @@ public void handlePost(ActionParameters params) throws ActionException { } try { - CoordinateReferenceSystem coordRefSys = CRS.decode(crs); - JSONObject geojson = params.getPayLoadJSON(); Feature feature = getFeature(geojson, layerId, crs, geojson.optString("id")); - final String wfstMessage = createWFSTMessageForInsert(feature, coordRefSys); + final String wfstMessage = createWFSTMessageForInsert(feature); LOG.debug("Inserting feature to service at", layer.getUrl(), "with payload:\n", wfstMessage); final String responseString = postPayload(layer.getUsername(), layer.getPassword(), wfstMessage, getURLForNamespace(layer.getName(),layer.getUrl())); @@ -111,12 +109,10 @@ public void handlePut(ActionParameters params) throws ActionException { } try { - CoordinateReferenceSystem coordRefSys = CRS.decode(crs); - JSONObject geojson = params.getPayLoadJSON(); Feature feature = getFeature(geojson, layerId, crs, geojson.optString("id")); - final String wfstMessage = createWFSTMessageForUpdate(feature, coordRefSys); + final String wfstMessage = createWFSTMessageForUpdate(feature); LOG.debug("Updating feature to service at", layer.getUrl(), "with payload:\n", wfstMessage); String responseString = postPayload(layer.getUsername(), layer.getPassword(), wfstMessage, getURLForNamespace(layer.getName(),layer.getUrl())); @@ -133,22 +129,22 @@ public void handlePut(ActionParameters params) throws ActionException { } } - static String createWFSTMessageForUpdate(Feature feature, CoordinateReferenceSystem crs) + static String createWFSTMessageForUpdate(Feature feature) throws ActionException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FeatureWFSTRequestBuilder.updateFeature(baos, feature, crs); + FeatureWFSTRequestBuilder.updateFeature(baos, feature); return baos.toString(); } catch (XMLStreamException e) { throw new ActionException("Failed to create WFS-T request", e); } } - static String createWFSTMessageForInsert(Feature feature, CoordinateReferenceSystem coordRefSys) + static String createWFSTMessageForInsert(Feature feature) throws ActionException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FeatureWFSTRequestBuilder.insertFeature(baos, feature, coordRefSys); + FeatureWFSTRequestBuilder.insertFeature(baos, feature); return baos.toString(); } catch (XMLStreamException e) { throw new ActionException("Failed to create WFS-T request", e); diff --git a/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java b/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java index ed27bacece..989b71311a 100644 --- a/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java +++ b/control-base/src/test/java/fi/nls/oskari/control/feature/VectorFeatureWriterHandlerTest.java @@ -12,12 +12,11 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.geotools.referencing.CRS; import org.junit.Test; import org.locationtech.jts.geom.CoordinateSequence; +import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Polygon; -import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -27,9 +26,6 @@ public class VectorFeatureWriterHandlerTest { @Test public void testUpdateXYAxisOrder() throws Exception { - String epsg = "EPSG:3067"; - CoordinateReferenceSystem crs = CRS.decode(epsg); - double[] pts = { 473183.20423224,6680301.618281904, 473257.20423224,6680411.618281904, @@ -43,9 +39,11 @@ public void testUpdateXYAxisOrder() throws Exception { oskariFeature.setId("12345"); oskariFeature.setProperties(new HashMap<>()); oskariFeature.setGMLGeometryProperty("geometry"); - oskariFeature.setGeometry(createPolygon(pts)); + Geometry g = createPolygon(pts); + g.setSRID(3067); + oskariFeature.setGeometry(g); - String wfsTransaction = VectorFeatureWriterHandler.createWFSTMessageForUpdate(oskariFeature, crs); + String wfsTransaction = VectorFeatureWriterHandler.createWFSTMessageForUpdate(oskariFeature); double[] actual = readPosList(wfsTransaction); assertArrayEquals(pts, actual, 1e-10); @@ -53,9 +51,6 @@ public void testUpdateXYAxisOrder() throws Exception { @Test public void testInsertYXAxisOrder() throws Exception { - String epsg = "EPSG:3879"; - CoordinateReferenceSystem crs = CRS.decode(epsg); - double[] pts = { 25473183.20423224,6680301.618281904, 25473257.20423224,6680411.618281904, @@ -68,9 +63,11 @@ public void testInsertYXAxisOrder() throws Exception { oskariFeature.setLayerName("foo"); oskariFeature.setProperties(new HashMap<>()); oskariFeature.setGMLGeometryProperty("geometry"); - oskariFeature.setGeometry(createPolygon(pts)); + Geometry g = createPolygon(pts); + g.setSRID(3879); + oskariFeature.setGeometry(g); - String wfsTransaction = VectorFeatureWriterHandler.createWFSTMessageForInsert(oskariFeature, crs); + String wfsTransaction = VectorFeatureWriterHandler.createWFSTMessageForInsert(oskariFeature); double[] actual = readPosList(wfsTransaction); for (int i = 0; i < pts.length / 2; i++) { assertEquals(pts[i * 2 + 0], actual[i * 2 + 1], 1e-10); diff --git a/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java b/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java index ed1b93691d..2e5ad1c39a 100755 --- a/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java +++ b/service-base/src/main/java/fi/nls/oskari/util/GML3Writer.java @@ -157,8 +157,12 @@ private static void writeLinearRing(XMLStreamWriter xsw, LinearRing linearRing, private static void writeSRID(XMLStreamWriter xsw, int srid) throws XMLStreamException { if (srid != 0) { - xsw.writeAttribute("srsName", "http://www.opengis.net/def/crs/EPSG/0/" + srid); + xsw.writeAttribute("srsName", getSrsName(srid)); } } + public static String getSrsName(int srid) { + return "http://www.opengis.net/def/crs/EPSG/0/" + srid; + } + }