QGIS API Documentation 3.41.0-Master (af5edcb665c)
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 ***************************************************************************/
22#include "qgswfsutils.h"
26#include "qgswfsparameters.h"
27#include "qgsproject.h"
28#include "qgsvectorlayer.h"
29
30using namespace QgsWfs;
31
33 : wfsParameters( wfsParams )
34{}
35
36void QgsWfsDescribeFeatureTypeGml::writeDescribeFeatureType( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response ) const
37{
38#ifdef HAVE_SERVER_PYTHON_PLUGINS
39 QgsAccessControl *accessControl = serverIface->accessControls();
40#endif
41 QDomDocument doc;
42 const QDomDocument *describeDocument = nullptr;
43
44#ifdef HAVE_SERVER_PYTHON_PLUGINS
45 QgsServerCacheManager *cacheManager = serverIface->cacheManager();
46 if ( cacheManager && cacheManager->getCachedDocument( &doc, project, request, accessControl ) )
47 {
48 describeDocument = &doc;
49 }
50 else //describe feature xml not in cache. Create a new one
51 {
52 doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
53
54 if ( cacheManager )
55 {
56 cacheManager->setCachedDocument( &doc, project, request, accessControl );
57 }
58 describeDocument = &doc;
59 }
60#else
61 doc = createDescribeFeatureTypeDocument( serverIface, project, version, request );
62 describeDocument = &doc;
63#endif
64 response.setHeader( "Content-Type", "text/xml; charset=utf-8" );
65 response.write( describeDocument->toByteArray() );
66}
67
68
69QDomDocument QgsWfsDescribeFeatureTypeGml::createDescribeFeatureTypeDocument( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request ) const
70{
71 Q_UNUSED( version )
72
73 QDomDocument doc;
74
75#ifdef HAVE_SERVER_PYTHON_PLUGINS
76 QgsAccessControl *accessControl = serverIface->accessControls();
77#else
78 ( void ) serverIface;
79#endif
80
81 auto outputFormat = wfsParameters.outputFormat();
82
83 //xsd:schema
84 QDomElement schemaElement = doc.createElement( QStringLiteral( "schema" ) /*xsd:schema*/ );
85 schemaElement.setAttribute( QStringLiteral( "xmlns" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema" ) );
86 schemaElement.setAttribute( QStringLiteral( "xmlns:xsd" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema" ) );
87 schemaElement.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE );
88 schemaElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
89 schemaElement.setAttribute( QStringLiteral( "xmlns:qgs" ), QGS_NAMESPACE );
90 schemaElement.setAttribute( QStringLiteral( "targetNamespace" ), QGS_NAMESPACE );
91 schemaElement.setAttribute( QStringLiteral( "elementFormDefault" ), QStringLiteral( "qualified" ) );
92 schemaElement.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0" ) );
93 doc.appendChild( schemaElement );
94
95 //xsd:import
96 QDomElement importElement = doc.createElement( QStringLiteral( "import" ) /*xsd:import*/ );
97 importElement.setAttribute( QStringLiteral( "namespace" ), GML_NAMESPACE );
98 if ( outputFormat == QgsWfsParameters::Format::GML2 )
99 importElement.setAttribute( QStringLiteral( "schemaLocation" ), QStringLiteral( "http://schemas.opengis.net/gml/2.1.2/feature.xsd" ) );
100 else if ( outputFormat == QgsWfsParameters::Format::GML3 )
101 importElement.setAttribute( QStringLiteral( "schemaLocation" ), QStringLiteral( "http://schemas.opengis.net/gml/3.1.1/base/gml.xsd" ) );
102 schemaElement.appendChild( importElement );
103
104 QStringList typeNameList = getRequestTypeNames( request, wfsParameters );
105
106 const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
107 for ( int i = 0; i < wfsLayerIds.size(); ++i )
108 {
109 QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) );
110 if ( !layer )
111 {
112 continue;
113 }
114
115 const QString name = layerTypeName( layer );
116
117 if ( !typeNameList.isEmpty() && !typeNameList.contains( name ) )
118 {
119 continue;
120 }
121#ifdef HAVE_SERVER_PYTHON_PLUGINS
122 if ( accessControl && !accessControl->layerReadPermission( layer ) )
123 {
124 if ( !typeNameList.isEmpty() )
125 {
126 throw QgsSecurityAccessException( QStringLiteral( "Feature access permission denied" ) );
127 }
128 else
129 {
130 continue;
131 }
132 }
133#endif
134 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer );
135 QgsVectorDataProvider *provider = vLayer->dataProvider();
136 if ( !provider )
137 {
138 continue;
139 }
140 setSchemaLayer( schemaElement, doc, const_cast<QgsVectorLayer *>( vLayer ) );
141 }
142 return doc;
143}
144
145void QgsWfsDescribeFeatureTypeGml::setSchemaLayer( QDomElement &parentElement, QDomDocument &doc, const QgsVectorLayer *layer ) const
146{
147 const QgsVectorDataProvider *provider = layer->dataProvider();
148 if ( !provider )
149 {
150 return;
151 }
152
153 const QString typeName = layerTypeName( layer );
154
155 //xsd:element
156 QDomElement elementElem = doc.createElement( QStringLiteral( "element" ) /*xsd:element*/ );
157 elementElem.setAttribute( QStringLiteral( "name" ), typeName );
158 elementElem.setAttribute( QStringLiteral( "type" ), "qgs:" + typeName + "Type" );
159 elementElem.setAttribute( QStringLiteral( "substitutionGroup" ), QStringLiteral( "gml:_Feature" ) );
160 parentElement.appendChild( elementElem );
161
162 //xsd:complexType
163 QDomElement complexTypeElem = doc.createElement( QStringLiteral( "complexType" ) /*xsd:complexType*/ );
164 complexTypeElem.setAttribute( QStringLiteral( "name" ), typeName + "Type" );
165 parentElement.appendChild( complexTypeElem );
166
167 //xsd:complexType
168 QDomElement complexContentElem = doc.createElement( QStringLiteral( "complexContent" ) /*xsd:complexContent*/ );
169 complexTypeElem.appendChild( complexContentElem );
170
171 //xsd:extension
172 QDomElement extensionElem = doc.createElement( QStringLiteral( "extension" ) /*xsd:extension*/ );
173 extensionElem.setAttribute( QStringLiteral( "base" ), QStringLiteral( "gml:AbstractFeatureType" ) );
174 complexContentElem.appendChild( extensionElem );
175
176 //xsd:sequence
177 QDomElement sequenceElem = doc.createElement( QStringLiteral( "sequence" ) /*xsd:sequence*/ );
178 extensionElem.appendChild( sequenceElem );
179
180 //xsd:element
181 if ( layer->isSpatial() )
182 {
183 QDomElement geomElem = doc.createElement( QStringLiteral( "element" ) /*xsd:element*/ );
184 geomElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
185 geomElem.setAttribute( QStringLiteral( "type" ), getGmlGeometryType( layer ) );
186 geomElem.setAttribute( QStringLiteral( "minOccurs" ), QStringLiteral( "0" ) );
187 geomElem.setAttribute( QStringLiteral( "maxOccurs" ), QStringLiteral( "1" ) );
188 sequenceElem.appendChild( geomElem );
189 }
190
191 //Attributes
192 const QgsFields fields = layer->fields();
193 //hidden attributes for this layer
194 for ( int idx = 0; idx < fields.count(); ++idx )
195 {
196 const QgsField field = fields.at( idx );
197 //skip attribute if excluded from WFS publication
199 {
200 continue;
201 }
202
203 QString attributeName, attributeType;
204
205 // Defined in qgswfsdescribefeaturetype.h
206 getFieldAttributes( field, attributeName, attributeType );
207
208 //xsd:element
209 QDomElement attElem = doc.createElement( QStringLiteral( "element" ) /*xsd:element*/ );
210
211 attElem.setAttribute( QStringLiteral( "name" ), attributeName );
212 attElem.setAttribute( QStringLiteral( "type" ), attributeType );
213
215 {
216 attElem.setAttribute( QStringLiteral( "nillable" ), QStringLiteral( "true" ) );
217 }
218
219 sequenceElem.appendChild( attElem );
220
221 const QString alias = field.alias();
222 if ( !alias.isEmpty() )
223 {
224 attElem.setAttribute( QStringLiteral( "alias" ), alias );
225 }
226 }
227}
228
229QString QgsWfsDescribeFeatureTypeGml::getGmlGeometryType( const QgsVectorLayer *layer ) const
230{
231 const Qgis::WkbType wkbType = layer->wkbType();
232 switch ( wfsParameters.outputFormat() )
233 {
234 case QgsWfsParameters::Format::GML2:
235 switch ( wkbType )
236 {
239 return QStringLiteral( "gml:PointPropertyType" );
240
243 return QStringLiteral( "gml:LineStringPropertyType" );
244
247 return QStringLiteral( "gml:PolygonPropertyType" );
248
251 return QStringLiteral( "gml:MultiPointPropertyType" );
252
256 return QStringLiteral( "gml:MultiLineStringPropertyType" );
257
261 return QStringLiteral( "gml:MultiPolygonPropertyType" );
262
263 default:
264 return QStringLiteral( "gml:GeometryPropertyType" );
265 }
266 case QgsWfsParameters::Format::GML3:
267 switch ( wkbType )
268 {
271 return QStringLiteral( "gml:PointPropertyType" );
272
275 return QStringLiteral( "gml:LineStringPropertyType" );
276
279 return QStringLiteral( "gml:PolygonPropertyType" );
280
283 return QStringLiteral( "gml:MultiPointPropertyType" );
284
288 return QStringLiteral( "gml:MultiCurvePropertyType" );
289
293 return QStringLiteral( "gml:MultiSurfacePropertyType" );
294
295 default:
296 return QStringLiteral( "gml:GeometryPropertyType" );
297 }
298 default:
299 return QStringLiteral( "gml:GeometryPropertyType" );
300 }
301}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:256
@ LineString25D
LineString25D.
@ LineString
LineString.
@ MultiPolygon25D
MultiPolygon25D.
@ MultiPoint
MultiPoint.
@ Polygon
Polygon.
@ MultiLineString25D
MultiLineString25D.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ MultiPoint25D
MultiPoint25D.
@ MultiCurve
MultiCurve.
@ Point25D
Point25D.
@ MultiSurface
MultiSurface.
@ Polygon25D
Polygon25D.
@ HideFromWfs
Field is not available if layer is served as WFS from QGIS server.
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.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
Qgis::FieldConfigurationFlags configurationFlags
Definition qgsfield.h:66
QString alias
Definition qgsfield.h:63
QgsFieldConstraints constraints
Definition qgsfield.h:65
Container of fields for a vector layer.
Definition qgsfields.h:46
int count
Definition qgsfields.h:50
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Base class for all map layer types.
Definition qgsmaplayer.h:76
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
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.
QgsServerInterface Class defining 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.
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
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...
This is the base class for vector data providers.
Represents a vector layer which manages a vector based data sets.
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.
Exception thrown when data access violates access controls.
Provides an interface to retrieve and manipulate WFS parameters received from the client.
Format outputFormat() const
Returns format.
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
WMS implementation.
Definition qgswfs.cpp:36
QString layerTypeName(const QgsMapLayer *layer)
Returns typename from vector layer.
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:77
QStringList getRequestTypeNames(const QgsServerRequest &request, const QgsWfsParameters &wfsParams)
Helper for returning typename list from the request.
#define GML_NAMESPACE
#define OGC_NAMESPACE
const QString & typeName