QGIS API Documentation 3.99.0-Master (e9821da5c6b)
Loading...
Searching...
No Matches
qgswfsdescribefeaturetypegml.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswfsdescribefeaturetypegml.cpp
3 --------------------------------
4 begin : December 20 , 2016
5 copyright : (C) 2007 by Marco Hugentobler (original code)
6 (C) 2012 by René-Luc D'Hont (original code)
7 (C) 2014 by Alessandro Pasotti (original code)
8 (C) 2017 by David Marteau
9 email : marco dot hugentobler at karto dot baug dot ethz dot ch
10 a dot pasotti at itopen dot it
11 david dot marteau at 3liz dot com
12 ***************************************************************************/
13
14/***************************************************************************
15 * *
16 * This program is free software; you can redistribute it and/or modify *
17 * it under the terms of the GNU General Public License as published by *
18 * the Free Software Foundation; either version 2 of the License, or *
19 * (at your option) any later version. *
20 * *
21 ***************************************************************************/
23
24#include "qgsproject.h"
26#include "qgsvectorlayer.h"
28#include "qgswfsparameters.h"
29#include "qgswfsutils.h"
30
31#include <QString>
32
33using namespace Qt::StringLiterals;
34
35using namespace QgsWfs;
36
38 : wfsParameters( wfsParams )
39{}
40
41void QgsWfsDescribeFeatureTypeGml::writeDescribeFeatureType( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response ) const
42{
43#ifdef HAVE_SERVER_PYTHON_PLUGINS
44 QgsAccessControl *accessControl = serverIface->accessControls();
45#endif
46 QDomDocument doc;
47 const QDomDocument *describeDocument = nullptr;
48
49#ifdef HAVE_SERVER_PYTHON_PLUGINS
50 QgsServerCacheManager *cacheManager = serverIface->cacheManager();
51 if ( cacheManager && cacheManager->getCachedDocument( &doc, project, request, accessControl ) )
52 {
53 describeDocument = &doc;
54 }
55 else //describe feature xml not in cache. Create a new one
56 {
57 doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
58
59 if ( cacheManager )
60 {
61 cacheManager->setCachedDocument( &doc, project, request, accessControl );
62 }
63 describeDocument = &doc;
64 }
65#else
66 doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
67 describeDocument = &doc;
68#endif
69 response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
70 response.write( describeDocument->toByteArray() );
71}
72
73
74QDomDocument QgsWfsDescribeFeatureTypeGml::createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request ) const
75{
76 Q_UNUSED( version )
77
78 QDomDocument doc;
79
80#ifdef HAVE_SERVER_PYTHON_PLUGINS
81 QgsAccessControl *accessControl = serverIface->accessControls();
82#else
83 ( void ) serverIface;
84#endif
85
86 auto outputFormat = wfsParameters.outputFormat();
87
88 //xsd:schema
89 QDomElement schemaElement = doc.createElement( u"schema"_s /*xsd:schema*/ );
90 schemaElement.setAttribute( u"xmlns"_s, u"http://www.w3.org/2001/XMLSchema"_s );
91 schemaElement.setAttribute( u"xmlns:xsd"_s, u"http://www.w3.org/2001/XMLSchema"_s );
92 schemaElement.setAttribute( u"xmlns:ogc"_s, OGC_NAMESPACE );
93 schemaElement.setAttribute( u"xmlns:gml"_s, GML_NAMESPACE );
94 schemaElement.setAttribute( u"xmlns:qgs"_s, QGS_NAMESPACE );
95 schemaElement.setAttribute( u"targetNamespace"_s, QGS_NAMESPACE );
96 schemaElement.setAttribute( u"elementFormDefault"_s, u"qualified"_s );
97 schemaElement.setAttribute( u"version"_s, u"1.0"_s );
98 doc.appendChild( schemaElement );
99
100 //xsd:import
101 QDomElement importElement = doc.createElement( u"import"_s /*xsd:import*/ );
102 importElement.setAttribute( u"namespace"_s, GML_NAMESPACE );
103 if ( outputFormat == QgsWfsParameters::Format::GML2 )
104 importElement.setAttribute( u"schemaLocation"_s, u"http://schemas.opengis.net/gml/2.1.2/feature.xsd"_s );
105 else if ( outputFormat == QgsWfsParameters::Format::GML3 )
106 importElement.setAttribute( u"schemaLocation"_s, u"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd"_s );
107 schemaElement.appendChild( importElement );
108
109 QStringList typeNameList = getRequestTypeNames( request, wfsParameters );
110
111 const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
112 for ( int i = 0; i < wfsLayerIds.size(); ++i )
113 {
114 QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) );
115 if ( !layer )
116 {
117 continue;
118 }
119
120 const QString name = layer->serverProperties()->wfsTypeName();
121
122 if ( !typeNameList.isEmpty() && !typeNameList.contains( name ) )
123 {
124 continue;
125 }
126#ifdef HAVE_SERVER_PYTHON_PLUGINS
127 if ( accessControl && !accessControl->layerReadPermission( layer ) )
128 {
129 if ( !typeNameList.isEmpty() )
130 {
131 throw QgsSecurityAccessException( u"Feature access permission denied"_s );
132 }
133 else
134 {
135 continue;
136 }
137 }
138#endif
139 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer );
140 QgsVectorDataProvider *provider = vLayer->dataProvider();
141 if ( !provider )
142 {
143 continue;
144 }
145 setSchemaLayer( schemaElement, doc, const_cast<QgsVectorLayer *>( vLayer ) );
146 }
147 return doc;
148}
149
150void QgsWfsDescribeFeatureTypeGml::setSchemaLayer( QDomElement &parentElement, QDomDocument &doc, const QgsVectorLayer *layer ) const
151{
152 const QgsVectorDataProvider *provider = layer->dataProvider();
153 if ( !provider )
154 {
155 return;
156 }
157
158 const QString typeName = layer->serverProperties()->wfsTypeName();
159
160 //xsd:element
161 QDomElement elementElem = doc.createElement( u"element"_s /*xsd:element*/ );
162 elementElem.setAttribute( u"name"_s, typeName );
163 elementElem.setAttribute( u"type"_s, "qgs:" + typeName + "Type" );
164 elementElem.setAttribute( u"substitutionGroup"_s, u"gml:_Feature"_s );
165 parentElement.appendChild( elementElem );
166
167 //xsd:complexType
168 QDomElement complexTypeElem = doc.createElement( u"complexType"_s /*xsd:complexType*/ );
169 complexTypeElem.setAttribute( u"name"_s, typeName + "Type" );
170 parentElement.appendChild( complexTypeElem );
171
172 //xsd:complexType
173 QDomElement complexContentElem = doc.createElement( u"complexContent"_s /*xsd:complexContent*/ );
174 complexTypeElem.appendChild( complexContentElem );
175
176 //xsd:extension
177 QDomElement extensionElem = doc.createElement( u"extension"_s /*xsd:extension*/ );
178 extensionElem.setAttribute( u"base"_s, u"gml:AbstractFeatureType"_s );
179 complexContentElem.appendChild( extensionElem );
180
181 //xsd:sequence
182 QDomElement sequenceElem = doc.createElement( u"sequence"_s /*xsd:sequence*/ );
183 extensionElem.appendChild( sequenceElem );
184
185 //xsd:element
186 if ( layer->isSpatial() )
187 {
188 QDomElement geomElem = doc.createElement( u"element"_s /*xsd:element*/ );
189 geomElem.setAttribute( u"name"_s, u"geometry"_s );
190 geomElem.setAttribute( u"type"_s, getGmlGeometryType( layer ) );
191 geomElem.setAttribute( u"minOccurs"_s, u"0"_s );
192 geomElem.setAttribute( u"maxOccurs"_s, u"1"_s );
193 sequenceElem.appendChild( geomElem );
194 }
195
196 //Attributes
197 const QgsFields fields = layer->fields();
198 //hidden attributes for this layer
199 for ( int idx = 0; idx < fields.count(); ++idx )
200 {
201 const QgsField field = fields.at( idx );
202 //skip attribute if excluded from WFS publication
204 {
205 continue;
206 }
207
208 QString attributeName, attributeType;
209
210 // Defined in qgswfsdescribefeaturetype.h
211 getFieldAttributes( field, attributeName, attributeType );
212
213 //xsd:element
214 QDomElement attElem = doc.createElement( u"element"_s /*xsd:element*/ );
215
216 attElem.setAttribute( u"name"_s, attributeName );
217 attElem.setAttribute( u"type"_s, attributeType );
218
220 {
221 attElem.setAttribute( u"nillable"_s, u"true"_s );
222 }
223
224 sequenceElem.appendChild( attElem );
225
226 const QString alias = field.alias();
227 if ( !alias.isEmpty() )
228 {
229 attElem.setAttribute( u"alias"_s, alias );
230 }
231 }
232}
233
234QString QgsWfsDescribeFeatureTypeGml::getGmlGeometryType( const QgsVectorLayer *layer ) const
235{
236 const Qgis::WkbType wkbType = layer->wkbType();
237 switch ( wfsParameters.outputFormat() )
238 {
239 case QgsWfsParameters::Format::GML2:
240 switch ( wkbType )
241 {
245 return u"gml:PointPropertyType"_s;
246
250 return u"gml:LineStringPropertyType"_s;
251
255 return u"gml:PolygonPropertyType"_s;
256
260 return u"gml:MultiPointPropertyType"_s;
261
267 return u"gml:MultiLineStringPropertyType"_s;
268
274 return u"gml:MultiPolygonPropertyType"_s;
275
276 default:
277 return u"gml:GeometryPropertyType"_s;
278 }
279 case QgsWfsParameters::Format::GML3:
280 switch ( wkbType )
281 {
285 return u"gml:PointPropertyType"_s;
286
290 return u"gml:LineStringPropertyType"_s;
291
295 return u"gml:PolygonPropertyType"_s;
296
299 return u"gml:MultiPointPropertyType"_s;
300
306 return u"gml:MultiCurvePropertyType"_s;
307
312 return u"gml:MultiSurfacePropertyType"_s;
313
314 default:
315 return u"gml:GeometryPropertyType"_s;
316 }
317 default:
318 return u"gml:GeometryPropertyType"_s;
319 }
320}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:280
@ LineString25D
LineString25D.
Definition qgis.h:348
@ MultiPointZ
MultiPointZ.
Definition qgis.h:303
@ Point
Point.
Definition qgis.h:282
@ LineString
LineString.
Definition qgis.h:283
@ MultiPolygon25D
MultiPolygon25D.
Definition qgis.h:352
@ MultiPoint
MultiPoint.
Definition qgis.h:286
@ Polygon
Polygon.
Definition qgis.h:284
@ MultiLineString25D
MultiLineString25D.
Definition qgis.h:351
@ MultiPolygon
MultiPolygon.
Definition qgis.h:288
@ MultiSurfaceZ
MultiSurfaceZ.
Definition qgis.h:311
@ MultiLineString
MultiLineString.
Definition qgis.h:287
@ MultiPoint25D
MultiPoint25D.
Definition qgis.h:350
@ PointZ
PointZ.
Definition qgis.h:299
@ MultiLineStringZ
MultiLineStringZ.
Definition qgis.h:304
@ MultiPolygonZ
MultiPolygonZ.
Definition qgis.h:305
@ MultiCurve
MultiCurve.
Definition qgis.h:293
@ MultiCurveZ
MultiCurveZ.
Definition qgis.h:310
@ Point25D
Point25D.
Definition qgis.h:347
@ LineStringZ
LineStringZ.
Definition qgis.h:300
@ MultiSurface
MultiSurface.
Definition qgis.h:294
@ PolygonZ
PolygonZ.
Definition qgis.h:301
@ Polygon25D
Polygon25D.
Definition qgis.h:349
@ HideFromWfs
Field is not available if layer is served as WFS from QGIS server.
Definition qgis.h:1783
A helper class that centralizes restrictions given by all the access control filter plugins.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
@ ConstraintNotNull
Field may not be null.
Qgis::FieldConfigurationFlags configurationFlags
Definition qgsfield.h:69
QString alias
Definition qgsfield.h:66
QgsFieldConstraints constraints
Definition qgsfield.h:68
int count
Definition qgsfields.h:50
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
QString wfsTypeName() const
Returns WFS typename for the layer.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:113
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A helper class that centralizes caches accesses given by all the server cache filter plugins.
bool setCachedDocument(const QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Updates or inserts the document in cache like capabilities.
bool getCachedDocument(QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Returns cached document (or 0 if document not in cache) like capabilities.
Defines interfaces exposed by QGIS Server and made available to plugins.
virtual QgsServerCacheManager * cacheManager() const =0
Gets the registered server cache filters.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
static QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
Defines requests passed to QgsService classes.
Defines the response interface passed to QgsService.
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
Represents a vector layer which manages a vector based dataset.
bool isSpatial() const final
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Q_INVOKABLE Qgis::WkbType wkbType() const final
Returns the WKBType or WKBUnknown in case of error.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
void writeDescribeFeatureType(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response) const
Output GML response.
QgsWfsDescribeFeatureTypeGml(const QgsWfs::QgsWfsParameters wfsParams)
Constructor.
Provides an interface to retrieve and manipulate WFS parameters received from the client.
Format outputFormat() const
Returns format.
WMS implementation.
Definition qgswfs.cpp:40
void getFieldAttributes(const QgsField &field, QString &fieldName, QString &fieldType)
Helper for returning the field type and type name.
const QString QGS_NAMESPACE
Definition qgswfsutils.h:76
QStringList getRequestTypeNames(const QgsServerRequest &request, const QgsWfsParameters &wfsParams)
Helper for returning typename list from the request.
#define GML_NAMESPACE
#define OGC_NAMESPACE