mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
Merge pull request #62394 from elpaso/server-wfs-3d-z-gml-part-2-server
[server] Server WFS Z gml transactional support
This commit is contained in:
commit
c637e42516
@ -234,30 +234,38 @@ QString QgsWfsDescribeFeatureTypeGml::getGmlGeometryType( const QgsVectorLayer *
|
||||
case QgsWfsParameters::Format::GML2:
|
||||
switch ( wkbType )
|
||||
{
|
||||
case Qgis::WkbType::PointZ:
|
||||
case Qgis::WkbType::Point25D:
|
||||
case Qgis::WkbType::Point:
|
||||
return QStringLiteral( "gml:PointPropertyType" );
|
||||
|
||||
case Qgis::WkbType::LineStringZ:
|
||||
case Qgis::WkbType::LineString25D:
|
||||
case Qgis::WkbType::LineString:
|
||||
return QStringLiteral( "gml:LineStringPropertyType" );
|
||||
|
||||
case Qgis::WkbType::PolygonZ:
|
||||
case Qgis::WkbType::Polygon25D:
|
||||
case Qgis::WkbType::Polygon:
|
||||
return QStringLiteral( "gml:PolygonPropertyType" );
|
||||
|
||||
case Qgis::WkbType::MultiPointZ:
|
||||
case Qgis::WkbType::MultiPoint25D:
|
||||
case Qgis::WkbType::MultiPoint:
|
||||
return QStringLiteral( "gml:MultiPointPropertyType" );
|
||||
|
||||
case Qgis::WkbType::MultiCurveZ:
|
||||
case Qgis::WkbType::MultiCurve:
|
||||
case Qgis::WkbType::MultiLineString25D:
|
||||
case Qgis::WkbType::MultiLineStringZ:
|
||||
case Qgis::WkbType::MultiLineString:
|
||||
return QStringLiteral( "gml:MultiLineStringPropertyType" );
|
||||
|
||||
case Qgis::WkbType::MultiSurfaceZ:
|
||||
case Qgis::WkbType::MultiSurface:
|
||||
case Qgis::WkbType::MultiPolygon25D:
|
||||
case Qgis::WkbType::MultiPolygon:
|
||||
case Qgis::WkbType::MultiPolygonZ:
|
||||
return QStringLiteral( "gml:MultiPolygonPropertyType" );
|
||||
|
||||
default:
|
||||
@ -266,16 +274,19 @@ QString QgsWfsDescribeFeatureTypeGml::getGmlGeometryType( const QgsVectorLayer *
|
||||
case QgsWfsParameters::Format::GML3:
|
||||
switch ( wkbType )
|
||||
{
|
||||
case Qgis::WkbType::PointZ:
|
||||
case Qgis::WkbType::Point25D:
|
||||
case Qgis::WkbType::Point:
|
||||
return QStringLiteral( "gml:PointPropertyType" );
|
||||
|
||||
case Qgis::WkbType::LineString25D:
|
||||
case Qgis::WkbType::LineString:
|
||||
case Qgis::WkbType::LineStringZ:
|
||||
return QStringLiteral( "gml:LineStringPropertyType" );
|
||||
|
||||
case Qgis::WkbType::Polygon25D:
|
||||
case Qgis::WkbType::Polygon:
|
||||
case Qgis::WkbType::PolygonZ:
|
||||
return QStringLiteral( "gml:PolygonPropertyType" );
|
||||
|
||||
case Qgis::WkbType::MultiPoint25D:
|
||||
@ -283,13 +294,16 @@ QString QgsWfsDescribeFeatureTypeGml::getGmlGeometryType( const QgsVectorLayer *
|
||||
return QStringLiteral( "gml:MultiPointPropertyType" );
|
||||
|
||||
case Qgis::WkbType::MultiCurve:
|
||||
case Qgis::WkbType::MultiCurveZ:
|
||||
case Qgis::WkbType::MultiLineString25D:
|
||||
case Qgis::WkbType::MultiLineString:
|
||||
case Qgis::WkbType::MultiLineStringZ:
|
||||
return QStringLiteral( "gml:MultiCurvePropertyType" );
|
||||
|
||||
case Qgis::WkbType::MultiSurface:
|
||||
case Qgis::WkbType::MultiPolygon25D:
|
||||
case Qgis::WkbType::MultiPolygon:
|
||||
case Qgis::WkbType::MultiPolygonZ:
|
||||
return QStringLiteral( "gml:MultiSurfacePropertyType" );
|
||||
|
||||
default:
|
||||
|
@ -13,8 +13,17 @@ __date__ = "28/08/2015"
|
||||
__copyright__ = "Copyright 2015, The QGIS Project"
|
||||
|
||||
from qgis.testing import unittest
|
||||
|
||||
from qgis.core import QgsProject, QgsVectorLayer, QgsGeometry, QgsOgcUtils
|
||||
from qgis.server import (
|
||||
QgsBufferServerRequest,
|
||||
QgsBufferServerResponse,
|
||||
QgsServer,
|
||||
QgsServerFilter,
|
||||
QgsServerRequest,
|
||||
)
|
||||
from test_qgsserver_accesscontrol import XML_NS, TestQgsServerAccessControl
|
||||
from test_qgsserver import QgsServerTestBase
|
||||
from osgeo import ogr
|
||||
|
||||
WFS_TRANSACTION_INSERT = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<wfs:Transaction {xml_ns}>
|
||||
@ -32,6 +41,43 @@ WFS_TRANSACTION_INSERT = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
</wfs:Insert>
|
||||
</wfs:Transaction>"""
|
||||
|
||||
WFS_TRANSACTION_Z_INSERT = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<wfs:Transaction {xml_ns}>
|
||||
<wfs:Insert idgen="GenerateNew">
|
||||
<qgs:{layer_name}>
|
||||
<qgs:geometry>
|
||||
{gml}
|
||||
</qgs:geometry>
|
||||
<qgs:gid>1</qgs:gid>
|
||||
<qgs:name>name</qgs:name>
|
||||
<qgs:color>black</qgs:color>
|
||||
</qgs:{layer_name}>
|
||||
</wfs:Insert>
|
||||
</wfs:Transaction>"""
|
||||
|
||||
WFS_TRANSACTION_Z_UPDATE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<wfs:Transaction {xml_ns}>
|
||||
<wfs:Update typeName="{layer_name}">
|
||||
<wfs:Property>
|
||||
<wfs:Name>color</wfs:Name>
|
||||
<wfs:Value>red</wfs:Value>
|
||||
</wfs:Property>
|
||||
<wfs:Property>
|
||||
<wfs:Name>name</wfs:Name>
|
||||
<wfs:Value>new_name</wfs:Value>
|
||||
</wfs:Property>
|
||||
<wfs:Property>
|
||||
<wfs:Name>geometry</wfs:Name>
|
||||
<wfs:Value>
|
||||
{gml}
|
||||
</wfs:Value>
|
||||
</wfs:Property>
|
||||
<ogc:Filter>
|
||||
<ogc:FeatureId fid="{id}"/>
|
||||
</ogc:Filter>
|
||||
</wfs:Update>
|
||||
</wfs:Transaction>"""
|
||||
|
||||
WFS_TRANSACTION_UPDATE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<wfs:Transaction {xml_ns}>
|
||||
<wfs:Update typeName="db_point">
|
||||
@ -252,5 +298,138 @@ class TestQgsServerAccessControlWFSTransactional(TestQgsServerAccessControl):
|
||||
)
|
||||
|
||||
|
||||
class TestQgsServerAccessControlWFSTransactionalZ(QgsServerTestBase):
|
||||
"""Test transactions with Z coordinate support."""
|
||||
|
||||
project = None
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
# Create a GPKG data and project with point, linestring and polygon layers
|
||||
# that supports Z coordinates
|
||||
drv = ogr.GetDriverByName("GPKG")
|
||||
ds = drv.CreateDataSource(cls.temporary_path + "/test_z.gpkg")
|
||||
layer_names = []
|
||||
for wkb_type_name in ["Point", "LineString", "Polygon"]:
|
||||
for prefix in ["", "Multi"]:
|
||||
wkb_type_name = prefix + wkb_type_name
|
||||
wkb_type = getattr(ogr, "wkb" + wkb_type_name + "25D", None)
|
||||
layer_name = "test_" + wkb_type_name.lower()
|
||||
layer_names.append(layer_name)
|
||||
layer = ds.CreateLayer(
|
||||
layer_name,
|
||||
geom_type=wkb_type,
|
||||
options=["GEOMETRY_NAME=geom"],
|
||||
)
|
||||
layer.CreateField(ogr.FieldDefn("name", ogr.OFTString))
|
||||
layer.CreateField(ogr.FieldDefn("color", ogr.OFTString))
|
||||
layer.CreateField(ogr.FieldDefn("gid", ogr.OFTInteger))
|
||||
|
||||
del ds
|
||||
|
||||
cls.project = QgsProject()
|
||||
|
||||
for layer_name in layer_names:
|
||||
layer = QgsVectorLayer(
|
||||
cls.temporary_path + "/test_z.gpkg|layername=" + layer_name,
|
||||
layer_name,
|
||||
"ogr",
|
||||
)
|
||||
assert cls.project.addMapLayer(layer)
|
||||
|
||||
# Enable WFS-T support for the layer project
|
||||
layer_ids = [layer.id() for layer in cls.project.mapLayers().values()]
|
||||
|
||||
cls.project.writeEntry("WFSLayers", "/", layer_ids)
|
||||
for method in ["Insert", "Update", "Delete"]:
|
||||
cls.project.writeEntry("WFSTLayers", method, layer_ids)
|
||||
|
||||
def do_operation(self, operation, layer_name, wkt):
|
||||
|
||||
geometry = ogr.Geometry(wkt=wkt)
|
||||
|
||||
xml = operation.format(
|
||||
layer_name=layer_name, gml=geometry.ExportToGML(), xml_ns=XML_NS, id=1
|
||||
)
|
||||
|
||||
request = QgsBufferServerRequest(
|
||||
f"http://server.qgis.org/?SERVICE=WFS&REQUEST=Transaction",
|
||||
QgsBufferServerRequest.PostMethod,
|
||||
{"Content-Type": "application/xml"},
|
||||
xml.encode("utf-8"),
|
||||
)
|
||||
|
||||
response = QgsBufferServerResponse()
|
||||
self.server.handleRequest(request, response, self.project)
|
||||
|
||||
return response
|
||||
|
||||
def do_insert(self, layer_name, wkt):
|
||||
|
||||
geometry = QgsGeometry.fromWkt(wkt)
|
||||
geom_wkt = geometry.asWkt().upper()
|
||||
|
||||
response = self.do_operation(WFS_TRANSACTION_Z_INSERT, layer_name, geom_wkt)
|
||||
|
||||
# Check layer
|
||||
layer = self.project.mapLayersByName(layer_name)[0]
|
||||
self.assertEqual(layer.featureCount(), 1)
|
||||
feature = next(layer.getFeatures())
|
||||
self.assertEqual(feature["name"], "name")
|
||||
self.assertEqual(feature["color"], "black")
|
||||
self.assertEqual(feature["gid"], 1)
|
||||
self.assertEqual(feature.geometry().asWkt().upper(), geom_wkt)
|
||||
|
||||
def do_update(self, layer_name, wkt):
|
||||
|
||||
geometry = QgsGeometry.fromWkt(wkt)
|
||||
geom_wkt = geometry.asWkt().upper()
|
||||
|
||||
response = self.do_operation(WFS_TRANSACTION_Z_UPDATE, layer_name, geom_wkt)
|
||||
|
||||
# Check layer
|
||||
layer = self.project.mapLayersByName(layer_name)[0]
|
||||
self.assertEqual(layer.featureCount(), 1)
|
||||
feature = next(layer.getFeatures())
|
||||
self.assertEqual(feature["color"], "red")
|
||||
self.assertEqual(feature["name"], "new_name")
|
||||
self.assertEqual(feature.geometry().asWkt().upper(), geom_wkt)
|
||||
|
||||
def testGeometries(self):
|
||||
|
||||
self.do_insert("test_point", "POINT Z (1 2 3)")
|
||||
self.do_update("test_point", "POINT Z (4 5 6)")
|
||||
|
||||
self.do_insert("test_linestring", "LINESTRING Z (1 2 3, 4 5 6, 7 8 9)")
|
||||
self.do_update("test_linestring", "LINESTRING Z (10 11 12, 13 14 15, 16 17 18)")
|
||||
|
||||
self.do_insert("test_polygon", "POLYGON Z ((1 2 3, 4 5 6, 7 8 9, 1 2 3))")
|
||||
self.do_update(
|
||||
"test_polygon", "POLYGON Z ((10 11 12, 13 14 15, 16 17 18, 10 11 12))"
|
||||
)
|
||||
|
||||
self.do_insert("test_multipoint", "MULTIPOINT Z (1 2 3, 4 5 6, 7 8 9)")
|
||||
self.do_update("test_multipoint", "MULTIPOINT Z (10 11 12, 13 14 15, 16 17 18)")
|
||||
|
||||
self.do_insert(
|
||||
"test_multilinestring",
|
||||
"MULTILINESTRING Z ((1 2 3, 4 5 6, 7 8 9), (10 11 12, 13 14 15, 16 17 18))",
|
||||
)
|
||||
self.do_update(
|
||||
"test_multilinestring",
|
||||
"MULTILINESTRING Z ((19 20 21, 22 23 24, 25 26 27), (28 29 30, 31 32 33, 34 35 36))",
|
||||
)
|
||||
|
||||
self.do_insert(
|
||||
"test_multipolygon",
|
||||
"MULTIPOLYGON Z (((1 2 3, 4 5 6, 7 8 9, 1 2 3)), ((10 11 12, 13 14 15, 16 17 18, 10 11 12)))",
|
||||
)
|
||||
self.do_update(
|
||||
"test_multipolygon",
|
||||
"MULTIPOLYGON Z (((10 11 12, 13 14 15, 16 17 18, 10 11 12)), ((19 20 21, 22 23 24, 25 26 27, 19 20 21)))",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user