QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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
31using namespace QgsWfs;
32
34 : wfsParameters( wfsParams )
35{}
36
37void QgsWfsDescribeFeatureTypeGml::writeDescribeFeatureType( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response ) const
38{
39#ifdef HAVE_SERVER_PYTHON_PLUGINS
40 QgsAccessControl *accessControl = serverIface->accessControls();
41#endif
42 QDomDocument doc;
43 const QDomDocument *describeDocument = nullptr;
44
45#ifdef HAVE_SERVER_PYTHON_PLUGINS
46 QgsServerCacheManager *cacheManager = serverIface->cacheManager();
47 if ( cacheManager && cacheManager->getCachedDocument( &doc, project, request, accessControl ) )
48 {
49 describeDocument = &doc;
50 }
51 else //describe feature xml not in cache. Create a new one
52 {
53 doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
54
55 if ( cacheManager )
56 {
57 cacheManager->setCachedDocument( &doc, project, request, accessControl );
58 }
59 describeDocument = &doc;
60 }
61#else
62 doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
63 describeDocument = &doc;
64#endif
65 response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
66 response.write( describeDocument->toByteArray() );
67}
68
69
70QDomDocument QgsWfsDescribeFeatureTypeGml::createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request ) const
71{
72 Q_UNUSED( version )
73
74 QDomDocument doc;
75
76#ifdef HAVE_SERVER_PYTHON_PLUGINS
77 QgsAccessControl *accessControl = serverIface->accessControls();
78#else
79 ( void ) serverIface;
80#endif
81
82 auto outputFormat = wfsParameters.outputFormat();
83
84 //xsd:schema
85 QDomElement schemaElement = doc.createElement( QStringLiteral( "schema" ) /*xsd:schema*/ );
86 schemaElement.setAttribute( QStringLiteral( "xmlns" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema" ) );
87 schemaElement.setAttribute( QStringLiteral( "xmlns:xsd" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema" ) );
88 schemaElement.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE );
89 schemaElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
90 schemaElement.setAttribute( QStringLiteral( "xmlns:qgs" ), QGS_NAMESPACE );
91 schemaElement.setAttribute( QStringLiteral( "targetNamespace" ), QGS_NAMESPACE );
92 schemaElement.setAttribute( QStringLiteral( "elementFormDefault" ), QStringLiteral( "qualified" ) );
93 schemaElement.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0" ) );
94 doc.appendChild( schemaElement );
95
96 //xsd:import
97 QDomElement importElement = doc.createElement( QStringLiteral( "import" ) /*xsd:import*/ );
98 importElement.setAttribute( QStringLiteral( "namespace" ), GML_NAMESPACE );
99 if ( outputFormat == QgsWfsParameters::Format::GML2 )
100 importElement.setAttribute( QStringLiteral( "schemaLocation" ), QStringLiteral( "http://schemas.opengis.net/gml/2.1.2/feature.xsd" ) );
101 else if ( outputFormat == QgsWfsParameters::Format::GML3 )
102 importElement.setAttribute( QStringLiteral( "schemaLocation" ), QStringLiteral( "http://schemas.opengis.net/gml/3.1.1/base/gml.xsd" ) );
103 schemaElement.appendChild( importElement );
104
105 QStringList typeNameList = getRequestTypeNames( request, wfsParameters );
106
107 const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
108 for ( int i = 0; i < wfsLayerIds.size(); ++i )
109 {
110 QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) );
111 if ( !layer )
112 {
113 continue;
114 }
115
116 const QString name = layer->serverProperties()->wfsTypeName();
117
118 if ( !typeNameList.isEmpty() && !typeNameList.contains( name ) )
119 {
120 continue;
121 }
122#ifdef HAVE_SERVER_PYTHON_PLUGINS
123 if ( accessControl && !accessControl->layerReadPermission( layer ) )
124 {
125 if ( !typeNameList.isEmpty() )
126 {
127 throw QgsSecurityAccessException( QStringLiteral( "Feature access permission denied" ) );
128 }
129 else
130 {
131 continue;
132 }
133 }
134#endif
135 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer );
136 QgsVectorDataProvider *provider = vLayer->dataProvider();
137 if ( !provider )
138 {
139 continue;
140 }
141 setSchemaLayer( schemaElement, doc, const_cast<QgsVectorLayer *>( vLayer ) );
142 }
143 return doc;
144}
145
146void QgsWfsDescribeFeatureTypeGml::setSchemaLayer( QDomElement &parentElement, QDomDocument &doc, const QgsVectorLayer *layer ) const
147{
148 const QgsVectorDataProvider *provider = layer->dataProvider();
149 if ( !provider )
150 {
151 return;
152 }
153
154 const QString typeName = layer->serverProperties()->wfsTypeName();
155
156 //xsd:element
157 QDomElement elementElem = doc.createElement( QStringLiteral( "element" ) /*xsd:element*/ );
158 elementElem.setAttribute( QStringLiteral( "name" ), typeName );
159 elementElem.setAttribute( QStringLiteral( "type" ), "qgs:" + typeName + "Type" );
160 elementElem.setAttribute( QStringLiteral( "substitutionGroup" ), QStringLiteral( "gml:_Feature" ) );
161 parentElement.appendChild( elementElem );
162
163 //xsd:complexType
164 QDomElement complexTypeElem = doc.createElement( QStringLiteral( "complexType" ) /*xsd:complexType*/ );
165 complexTypeElem.setAttribute( QStringLiteral( "name" ), typeName + "Type" );
166 parentElement.appendChild( complexTypeElem );
167
168 //xsd:complexType
169 QDomElement complexContentElem = doc.createElement( QStringLiteral( "complexContent" ) /*xsd:complexContent*/ );
170 complexTypeElem.appendChild( complexContentElem );
171
172 //xsd:extension
173 QDomElement extensionElem = doc.createElement( QStringLiteral( "extension" ) /*xsd:extension*/ );
174 extensionElem.setAttribute( QStringLiteral( "base" ), QStringLiteral( "gml:AbstractFeatureType" ) );
175 complexContentElem.appendChild( extensionElem );
176
177 //xsd:sequence
178 QDomElement sequenceElem = doc.createElement( QStringLiteral( "sequence" ) /*xsd:sequence*/ );
179 extensionElem.appendChild( sequenceElem );
180
181 //xsd:element
182 if ( layer->isSpatial() )
183 {
184 QDomElement geomElem = doc.createElement( QStringLiteral( "element" ) /*xsd:element*/ );
185 geomElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
186 geomElem.setAttribute( QStringLiteral( "type" ), getGmlGeometryType( layer ) );
187 geomElem.setAttribute( QStringLiteral( "minOccurs" ), QStringLiteral( "0" ) );
188 geomElem.setAttribute( QStringLiteral( "maxOccurs" ), QStringLiteral( "1" ) );
189 sequenceElem.appendChild( geomElem );
190 }
191
192 //Attributes
193 const QgsFields fields = layer->fields();
194 //hidden attributes for this layer
195 for ( int idx = 0; idx < fields.count(); ++idx )
196 {
197 const QgsField field = fields.at( idx );
198 //skip attribute if excluded from WFS publication
200 {
201 continue;
202 }
203
204 QString attributeName, attributeType;
205
206 // Defined in qgswfsdescribefeaturetype.h
207 getFieldAttributes( field, attributeName, attributeType );
208
209 //xsd:element
210 QDomElement attElem = doc.createElement( QStringLiteral( "element" ) /*xsd:element*/ );
211
212 attElem.setAttribute( QStringLiteral( "name" ), attributeName );
213 attElem.setAttribute( QStringLiteral( "type" ), attributeType );
214
216 {
217 attElem.setAttribute( QStringLiteral( "nillable" ), QStringLiteral( "true" ) );
218 }
219
220 sequenceElem.appendChild( attElem );
221
222 const QString alias = field.alias();
223 if ( !alias.isEmpty() )
224 {
225 attElem.setAttribute( QStringLiteral( "alias" ), alias );
226 }
227 }
228}
229
230QString QgsWfsDescribeFeatureTypeGml::getGmlGeometryType( const QgsVectorLayer *layer ) const
231{
232 const Qgis::WkbType wkbType = layer->wkbType();
233 switch ( wfsParameters.outputFormat() )
234 {
235 case QgsWfsParameters::Format::GML2:
236 switch ( wkbType )
237 {
241 return QStringLiteral( "gml:PointPropertyType" );
242
246 return QStringLiteral( "gml:LineStringPropertyType" );
247
251 return QStringLiteral( "gml:PolygonPropertyType" );
252
256 return QStringLiteral( "gml:MultiPointPropertyType" );
257
263 return QStringLiteral( "gml:MultiLineStringPropertyType" );
264
270 return QStringLiteral( "gml:MultiPolygonPropertyType" );
271
272 default:
273 return QStringLiteral( "gml:GeometryPropertyType" );
274 }
275 case QgsWfsParameters::Format::GML3:
276 switch ( wkbType )
277 {
281 return QStringLiteral( "gml:PointPropertyType" );
282
286 return QStringLiteral( "gml:LineStringPropertyType" );
287
291 return QStringLiteral( "gml:PolygonPropertyType" );
292
295 return QStringLiteral( "gml:MultiPointPropertyType" );
296
302 return QStringLiteral( "gml:MultiCurvePropertyType" );
303
308 return QStringLiteral( "gml:MultiSurfacePropertyType" );
309
310 default:
311 return QStringLiteral( "gml:GeometryPropertyType" );
312 }
313 default:
314 return QStringLiteral( "gml:GeometryPropertyType" );
315 }
316}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:277
@ LineString25D
LineString25D.
Definition qgis.h:341
@ MultiPointZ
MultiPointZ.
Definition qgis.h:299
@ Point
Point.
Definition qgis.h:279
@ LineString
LineString.
Definition qgis.h:280
@ MultiPolygon25D
MultiPolygon25D.
Definition qgis.h:345
@ MultiPoint
MultiPoint.
Definition qgis.h:283
@ Polygon
Polygon.
Definition qgis.h:281
@ MultiLineString25D
MultiLineString25D.
Definition qgis.h:344
@ MultiPolygon
MultiPolygon.
Definition qgis.h:285
@ MultiSurfaceZ
MultiSurfaceZ.
Definition qgis.h:307
@ MultiLineString
MultiLineString.
Definition qgis.h:284
@ MultiPoint25D
MultiPoint25D.
Definition qgis.h:343
@ PointZ
PointZ.
Definition qgis.h:295
@ MultiLineStringZ
MultiLineStringZ.
Definition qgis.h:300
@ MultiPolygonZ
MultiPolygonZ.
Definition qgis.h:301
@ MultiCurve
MultiCurve.
Definition qgis.h:290
@ MultiCurveZ
MultiCurveZ.
Definition qgis.h:306
@ Point25D
Point25D.
Definition qgis.h:340
@ LineStringZ
LineStringZ.
Definition qgis.h:296
@ MultiSurface
MultiSurface.
Definition qgis.h:291
@ PolygonZ
PolygonZ.
Definition qgis.h:297
@ Polygon25D
Polygon25D.
Definition qgis.h:342
@ HideFromWfs
Field is not available if layer is served as WFS from QGIS server.
Definition qgis.h:1725
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:67
QString alias
Definition qgsfield.h:64
QgsFieldConstraints constraints
Definition qgsfield.h:66
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:80
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:109
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:36
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:72
QStringList getRequestTypeNames(const QgsServerRequest &request, const QgsWfsParameters &wfsParams)
Helper for returning typename list from the request.
#define GML_NAMESPACE
#define OGC_NAMESPACE