QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgswfsgetcapabilities.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswfsgecapabilities.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"
25
26#include "qgsproject.h"
27#include "qgsexception.h"
28#include "qgsvectorlayer.h"
32
33namespace QgsWfs
34{
35
39 void writeGetCapabilities( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response )
40 {
41#ifdef HAVE_SERVER_PYTHON_PLUGINS
42 QgsAccessControl *accessControl = serverIface->accessControls();
43#endif
44 QDomDocument doc;
45 const QDomDocument *capabilitiesDocument = nullptr;
46
47#ifdef HAVE_SERVER_PYTHON_PLUGINS
48 QgsServerCacheManager *cacheManager = serverIface->cacheManager();
49 if ( cacheManager && cacheManager->getCachedDocument( &doc, project, request, accessControl ) )
50 {
51 capabilitiesDocument = &doc;
52 }
53 else //capabilities xml not in cache. Create a new one
54 {
55 doc = createGetCapabilitiesDocument( serverIface, project, version, request );
56
57 if ( cacheManager )
58 {
59 cacheManager->setCachedDocument( &doc, project, request, accessControl );
60 }
61 capabilitiesDocument = &doc;
62 }
63#else
64 doc = createGetCapabilitiesDocument( serverIface, project, version, request );
65 capabilitiesDocument = &doc;
66#endif
67 response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
68 response.write( capabilitiesDocument->toByteArray() );
69 }
70
71
72 QDomDocument createGetCapabilitiesDocument( QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request )
73 {
74 Q_UNUSED( version )
75
76 QDomDocument doc;
77
78 //wfs:WFS_Capabilities element
79 QDomElement wfsCapabilitiesElement = doc.createElement( QStringLiteral( "WFS_Capabilities" ) /*wms:WFS_Capabilities*/ );
80 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE );
81 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
82 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
83 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE );
84 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
85 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) );
86 wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
87 wfsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), implementationVersion() );
88 wfsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
89 doc.appendChild( wfsCapabilitiesElement );
90
91 //ows:ServiceIdentification
92 wfsCapabilitiesElement.appendChild( getServiceIdentificationElement( doc, project ) );
93
94 //ows:ServiceProvider
95 wfsCapabilitiesElement.appendChild( getServiceProviderElement( doc, project ) );
96
97 //wfs:OperationsMetadata
98 wfsCapabilitiesElement.appendChild( getOperationsMetadataElement( doc, project, request, serverIface->serverSettings() ) );
99
100 //wfs:FeatureTypeList
101 wfsCapabilitiesElement.appendChild( getFeatureTypeListElement( doc, serverIface, project ) );
102
103 /*
104 * Adding ogc:Filter_Capabilities in wfsCapabilitiesElement
105 */
106 //ogc:Filter_Capabilities element
107 QDomElement filterCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Filter_Capabilities" ) /*ogc:Filter_Capabilities*/ );
108 wfsCapabilitiesElement.appendChild( filterCapabilitiesElement );
109 QDomElement spatialCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Spatial_Capabilities" ) /*ogc:Spatial_Capabilities*/ );
110 filterCapabilitiesElement.appendChild( spatialCapabilitiesElement );
111 //GeometryOperands
112 QStringList geometryOperands;
113 geometryOperands << QStringLiteral( "gml:Point" ) << QStringLiteral( "gml:LineString" ) << QStringLiteral( "gml:Polygon" )
114 << QStringLiteral( "gml:Envelope" );
115 QDomElement geometryOperandsElem = doc.createElement( QStringLiteral( "ogc:GeometryOperands" ) );
116 for ( const QString &geometryOperand : geometryOperands )
117 {
118 QDomElement geometryOperandElem = doc.createElement( QStringLiteral( "ogc:GeometryOperand" ) );
119 const QDomText geometryOperandText = doc.createTextNode( geometryOperand );
120 geometryOperandElem.appendChild( geometryOperandText );
121 geometryOperandsElem.appendChild( geometryOperandElem );
122 }
123 spatialCapabilitiesElement.appendChild( geometryOperandsElem );
124 //SpatialOperators
125 QStringList spatialOperators;
126 spatialOperators << QStringLiteral( "Equals" ) << QStringLiteral( "Disjoint" ) << QStringLiteral( "Touches" )
127 << QStringLiteral( "Within" ) << QStringLiteral( "Overlaps" ) << QStringLiteral( "Crosses" )
128 << QStringLiteral( "Intersects" ) << QStringLiteral( "Contains" ) << QStringLiteral( "BBOX" );
129 QDomElement spatialOperatorsElem = doc.createElement( QStringLiteral( "ogc:SpatialOperators" ) );
130 for ( const QString &spatialOperator : spatialOperators )
131 {
132 QDomElement spatialOperatorElem = doc.createElement( QStringLiteral( "ogc:SpatialOperator" ) );
133 spatialOperatorElem.setAttribute( QStringLiteral( "name" ), spatialOperator );
134 spatialOperatorsElem.appendChild( spatialOperatorElem );
135 }
136 spatialCapabilitiesElement.appendChild( spatialOperatorsElem );
137 QDomElement scalarCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Scalar_Capabilities" ) /*ogc:Scalar_Capabilities*/ );
138 filterCapabilitiesElement.appendChild( scalarCapabilitiesElement );
139 const QDomElement logicalOperatorsElement = doc.createElement( QStringLiteral( "ogc:LogicalOperators" ) );
140 scalarCapabilitiesElement.appendChild( logicalOperatorsElement );
141 // ComparisonOperators
142 QStringList comparisonOperators;
143 comparisonOperators << QStringLiteral( "LessThan" ) << QStringLiteral( "GreaterThan" )
144 << QStringLiteral( "LessThanEqualTo" ) << QStringLiteral( "GreaterThanEqualTo" )
145 << QStringLiteral( "EqualTo" ) << QStringLiteral( "Like" ) << QStringLiteral( "Between" );
146 QDomElement comparisonOperatorsElem = doc.createElement( QStringLiteral( "ogc:ComparisonOperators" ) );
147 for ( const QString &comparisonOperator : comparisonOperators )
148 {
149 QDomElement comparisonOperatorElem = doc.createElement( QStringLiteral( "ogc:ComparisonOperator" ) );
150 const QDomText comparisonOperatorText = doc.createTextNode( comparisonOperator );
151 comparisonOperatorElem.appendChild( comparisonOperatorText );
152 comparisonOperatorsElem.appendChild( comparisonOperatorElem );
153 }
154 scalarCapabilitiesElement.appendChild( comparisonOperatorsElem );
155
156 QDomElement idCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Id_Capabilities" ) );
157 const QDomElement fidElem = doc.createElement( QStringLiteral( "ogc:FID" ) );
158 idCapabilitiesElement.appendChild( fidElem );
159 filterCapabilitiesElement.appendChild( idCapabilitiesElement );
160
161 return doc;
162 }
163
164 QDomElement getServiceIdentificationElement( QDomDocument &doc, const QgsProject *project )
165 {
166 //Service element
167 QDomElement serviceElem = doc.createElement( QStringLiteral( "ows:ServiceIdentification" ) );
168
169 const QString title = QgsServerProjectUtils::owsServiceTitle( *project );
170 QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
171 const QDomText titleText = doc.createTextNode( title );
172 titleElem.appendChild( titleText );
173 serviceElem.appendChild( titleElem );
174
175 const QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project );
176 if ( !abstract.isEmpty() )
177 {
178 QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
179 const QDomText abstractText = doc.createCDATASection( abstract );
180 abstractElem.appendChild( abstractText );
181 serviceElem.appendChild( abstractElem );
182 }
183
184 const QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project );
185 if ( !keywords.isEmpty() && !keywords.join( QLatin1String( ", " ) ).isEmpty() )
186 {
187 QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
188 for ( const QString &keyword : keywords )
189 {
190 if ( !keyword.isEmpty() )
191 {
192 QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
193 const QDomText keywordText = doc.createTextNode( keyword );
194 keywordElem.appendChild( keywordText );
195 keywordsElem.appendChild( keywordElem );
196 }
197 }
198 serviceElem.appendChild( keywordsElem );
199 }
200
201 //Service type
202 QDomElement serviceTypeElem = doc.createElement( QStringLiteral( "ows:ServiceType" ) );
203 const QDomText serviceTypeText = doc.createTextNode( "WFS" );
204 serviceTypeElem.appendChild( serviceTypeText );
205 serviceElem.appendChild( serviceTypeElem );
206
207 //Service type version
208 QDomElement serviceTypeVersionElem = doc.createElement( QStringLiteral( "ows:ServiceTypeVersion" ) );
209 const QDomText serviceTypeVersionText = doc.createTextNode( "1.1.0" );
210 serviceTypeVersionElem.appendChild( serviceTypeVersionText );
211 serviceElem.appendChild( serviceTypeVersionElem );
212
213 QDomElement feesElem = doc.createElement( QStringLiteral( "ows:Fees" ) );
214 QDomText feesText = doc.createTextNode( "None" );
215 const QString fees = QgsServerProjectUtils::owsServiceFees( *project );
216 if ( !fees.isEmpty() )
217 {
218 feesText = doc.createTextNode( fees );
219 }
220 feesElem.appendChild( feesText );
221 serviceElem.appendChild( feesElem );
222
223 QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( "ows:AccessConstraints" ) );
224 const QString accessConstraints = QgsServerProjectUtils::owsServiceAccessConstraints( *project );
225 QDomText accessConstraintsText = doc.createTextNode( "None" );
226 if ( !accessConstraints.isEmpty() )
227 {
228 accessConstraintsText = doc.createTextNode( accessConstraints );
229 }
230 accessConstraintsElem.appendChild( accessConstraintsText );
231 serviceElem.appendChild( accessConstraintsElem );
232
233 return serviceElem;
234 }
235
236 QDomElement getServiceProviderElement( QDomDocument &doc, const QgsProject *project )
237 {
238 //Service element
239 QDomElement serviceElem = doc.createElement( QStringLiteral( "ows:ServiceProvider" ) );
240
241 //ProviderName
242 const QString contactOrganization = QgsServerProjectUtils::owsServiceContactOrganization( *project );
243 if ( !contactOrganization.isEmpty() )
244 {
245 QDomElement providerNameElem = doc.createElement( QStringLiteral( "ows:ProviderName" ) );
246 const QDomText providerNameText = doc.createTextNode( contactOrganization );
247 providerNameElem.appendChild( providerNameText );
248 serviceElem.appendChild( providerNameElem );
249 }
250
251 const QString contactPerson = QgsServerProjectUtils::owsServiceContactPerson( *project );
252 const QString contactPosition = QgsServerProjectUtils::owsServiceContactPosition( *project );
253 if ( !contactPerson.isEmpty() || !contactPosition.isEmpty() )
254 {
255 //Contact information
256 QDomElement serviceContactElem = doc.createElement( QStringLiteral( "ows:ServiceContact" ) );
257
258 if ( !contactPerson.isEmpty() )
259 {
260 QDomElement individualNameElem = doc.createElement( QStringLiteral( "ows:IndividualName" ) );
261 const QDomText individualNameText = doc.createTextNode( contactPerson );
262 individualNameElem.appendChild( individualNameText );
263 serviceContactElem.appendChild( individualNameElem );
264 }
265
266 if ( !contactPosition.isEmpty() )
267 {
268 QDomElement positionNameElem = doc.createElement( QStringLiteral( "ows:PositionName" ) );
269 const QDomText positionNameText = doc.createTextNode( contactPosition );
270 positionNameElem.appendChild( positionNameText );
271 serviceContactElem.appendChild( positionNameElem );
272 }
273
274 const QString contactMail = QgsServerProjectUtils::owsServiceContactMail( *project );
275 const QString contactPhone = QgsServerProjectUtils::owsServiceContactPhone( *project );
276 const QString onlineResource = QgsServerProjectUtils::owsServiceOnlineResource( *project );
277 if ( !contactMail.isEmpty() || !contactPhone.isEmpty() || !onlineResource.isEmpty() )
278 {
279 //Contact information
280 QDomElement contactInfoElem = doc.createElement( QStringLiteral( "ows:ContactInfo" ) );
281
282 if ( !contactPhone.isEmpty() )
283 {
284 QDomElement phoneElem = doc.createElement( QStringLiteral( "ows:Phone" ) );
285 QDomElement voiceElem = doc.createElement( QStringLiteral( "ows:Voice" ) );
286 const QDomText voiceText = doc.createTextNode( contactPhone );
287 voiceElem.appendChild( voiceText );
288 phoneElem.appendChild( voiceElem );
289 contactInfoElem.appendChild( phoneElem );
290 }
291
292 if ( !contactMail.isEmpty() )
293 {
294 QDomElement addressElem = doc.createElement( QStringLiteral( "ows:Address" ) );
295 QDomElement mailElem = doc.createElement( QStringLiteral( "ows:ElectronicMailAddress" ) );
296 const QDomText mailText = doc.createTextNode( contactMail );
297 mailElem.appendChild( mailText );
298 addressElem.appendChild( mailElem );
299 contactInfoElem.appendChild( addressElem );
300 }
301
302 if ( !onlineResource.isEmpty() )
303 {
304 QDomElement onlineResourceElem = doc.createElement( QStringLiteral( "ows:OnlineResource" ) );
305 onlineResourceElem.setAttribute( "xlink:href", onlineResource );
306 contactInfoElem.appendChild( onlineResourceElem );
307 }
308 }
309
310 QDomElement roleElem = doc.createElement( QStringLiteral( "ows:Role" ) );
311 const QDomText roleText = doc.createTextNode( "PointOfContact" );
312 roleElem.appendChild( roleText );
313 serviceContactElem.appendChild( roleElem );
314
315 serviceElem.appendChild( serviceContactElem );
316 }
317
318 return serviceElem;
319 }
320
321 QDomElement getParameterElement( QDomDocument &doc, const QString &name, const QStringList &values )
322 {
323 QDomElement parameterElement = doc.createElement( QStringLiteral( "ows:Parameter" ) );
324 parameterElement.setAttribute( QStringLiteral( "name" ), name );
325
326 for ( const QString &v : values )
327 {
328 QDomElement valueElement = doc.createElement( QStringLiteral( "ows:Value" ) );
329 const QDomText valueText = doc.createTextNode( v );
330 valueElement.appendChild( valueText );
331 parameterElement.appendChild( valueElement );
332 }
333
334 return parameterElement;
335 }
336
337 QDomElement getOperationsMetadataElement( QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request, const QgsServerSettings *settings )
338 {
339 QDomElement oprationsElement = doc.createElement( QStringLiteral( "ows:OperationsMetadata" ) );
340
341 // Prepare url
342 const QString hrefString = serviceUrl( request, project, *settings );
343
344 QDomElement operationElement = doc.createElement( QStringLiteral( "ows:Operation" ) );
345 QDomElement dcpElement = doc.createElement( QStringLiteral( "ows:DCP" ) );
346 QDomElement httpElement = doc.createElement( QStringLiteral( "ows:HTTP" ) );
347 QDomElement getElement = doc.createElement( QStringLiteral( "ows:Get" ) );
348 getElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
349 httpElement.appendChild( getElement );
350
351 QDomElement postElement = doc.createElement( QStringLiteral( "ows:Post" ) );
352 postElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
353 httpElement.appendChild( postElement );
354
355 dcpElement.appendChild( httpElement );
356 operationElement.appendChild( dcpElement );
357
358 // GetCapabilities
359 QDomElement getCapabilitiesElement = operationElement.cloneNode().toElement();
360 getCapabilitiesElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "GetCapabilities" ) );
361 // GetCapabilities service
362 const QDomElement serviceParameterElement = getParameterElement( doc, QStringLiteral( "service" ), QStringList() << QStringLiteral( "WFS" ) );
363 getCapabilitiesElement.appendChild( serviceParameterElement );
364 // GetCapabilities AcceptVersions
365 const QDomElement acceptVersionsParameterElement = getParameterElement( doc, QStringLiteral( "AcceptVersions" ), QStringList() << QStringLiteral( "1.1.0" ) << QStringLiteral( "1.0.0" ) );
366 getCapabilitiesElement.appendChild( acceptVersionsParameterElement );
367 // GetCapabilities AcceptFormats
368 const QDomElement acceptFormatsParameterElement = getParameterElement( doc, QStringLiteral( "AcceptFormats" ), QStringList() << QStringLiteral( "text/xml" ) );
369 getCapabilitiesElement.appendChild( acceptFormatsParameterElement );
370 // Add
371 oprationsElement.appendChild( getCapabilitiesElement );
372
373 // DescribeFeatureType
374 QDomElement describeFeatureTypeElement = operationElement.cloneNode().toElement();
375 describeFeatureTypeElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "DescribeFeatureType" ) );
376 // DescribeFeatureType outputFormat
377 const QDomElement dftOutputFormatParameterElement = getParameterElement( doc, QStringLiteral( "outputFormat" ), QStringList() << QStringLiteral( "XMLSCHEMA" ) << QStringLiteral( "text/xml; subtype=gml/2.1.2" ) << QStringLiteral( "text/xml; subtype=gml/3.1.1" ) );
378 describeFeatureTypeElement.appendChild( dftOutputFormatParameterElement );
379 // Add
380 oprationsElement.appendChild( describeFeatureTypeElement );
381
382 // GetFeature
383 QDomElement getFeatureElement = operationElement.cloneNode().toElement();
384 getFeatureElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "GetFeature" ) );
385 // GetFeature outputFormat
386 const QDomElement gfOutputFormatParameterElement = getParameterElement( doc, QStringLiteral( "outputFormat" ), QStringList() << QStringLiteral( "text/xml; subtype=gml/2.1.2" ) << QStringLiteral( "text/xml; subtype=gml/3.1.1" ) << QStringLiteral( "application/vnd.geo+json" ) );
387 getFeatureElement.appendChild( gfOutputFormatParameterElement );
388 // GetFeature resultType
389 const QDomElement resultTypeParameterElement = getParameterElement( doc, QStringLiteral( "resultType" ), QStringList() << QStringLiteral( "results" ) << QStringLiteral( "hits" ) );
390 getFeatureElement.appendChild( resultTypeParameterElement );
391 // Add
392 oprationsElement.appendChild( getFeatureElement );
393
394 // Transaction
395 QDomElement transactionElement = operationElement.cloneNode().toElement();
396 transactionElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "Transaction" ) );
397 // GetFeature inputFormat
398 const QDomElement inputFormatParameterElement = getParameterElement( doc, QStringLiteral( "inputFormat" ), QStringList() << QStringLiteral( "text/xml; subtype=gml/2.1.2" ) << QStringLiteral( "text/xml; subtype=gml/3.1.1" ) << QStringLiteral( "application/vnd.geo+json" ) );
399 transactionElement.appendChild( inputFormatParameterElement );
400 // Add
401 oprationsElement.appendChild( transactionElement );
402
403 return oprationsElement;
404 }
405
406 QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project )
407 {
408#ifdef HAVE_SERVER_PYTHON_PLUGINS
409 QgsAccessControl *accessControl = serverIface->accessControls();
410#else
411 ( void ) serverIface;
412#endif
413
414 //wfs:FeatureTypeList element
415 QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" ) /*wfs:FeatureTypeList*/ );
416 //wfs:Operations element
417 QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" ) /*wfs:Operations*/ );
418 featureTypeListElement.appendChild( operationsElement );
419 //wfs:Query element
420 QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
421 const QDomText queryText = doc.createTextNode( "Query" );
422 operationElement.appendChild( queryText );
423 operationsElement.appendChild( operationElement );
424
425 const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
426 const QStringList wfstUpdateLayersId = QgsServerProjectUtils::wfstUpdateLayerIds( *project );
427 const QStringList wfstInsertLayersId = QgsServerProjectUtils::wfstInsertLayerIds( *project );
428 const QStringList wfstDeleteLayersId = QgsServerProjectUtils::wfstDeleteLayerIds( *project );
429 for ( const QString &wfsLayerId : wfsLayerIds )
430 {
431 QgsMapLayer *layer = project->mapLayer( wfsLayerId );
432 if ( !layer )
433 {
434 continue;
435 }
436 if ( layer->type() != Qgis::LayerType::Vector )
437 {
438 continue;
439 }
440#ifdef HAVE_SERVER_PYTHON_PLUGINS
441 if ( accessControl && !accessControl->layerReadPermission( layer ) )
442 {
443 continue;
444 }
445#endif
446 QDomElement layerElem = doc.createElement( QStringLiteral( "FeatureType" ) );
447
448 //create Name
449 QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
450 const QDomText nameText = doc.createTextNode( layerTypeName( layer ) );
451 nameElem.appendChild( nameText );
452 layerElem.appendChild( nameElem );
453
454 //create Title
455 QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
456 QString title = layer->serverProperties()->wfsTitle();
457 if ( title.isEmpty() )
458 {
459 title = layer->name();
460 }
461 const QDomText titleText = doc.createTextNode( title );
462 titleElem.appendChild( titleText );
463 layerElem.appendChild( titleElem );
464
465 //create Abstract
466 const QString abstract = layer->serverProperties()->abstract();
467 if ( !abstract.isEmpty() )
468 {
469 QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
470 const QDomText abstractText = doc.createTextNode( abstract );
471 abstractElem.appendChild( abstractText );
472 layerElem.appendChild( abstractElem );
473 }
474
475 //create keywords
476 const QString keywords = layer->serverProperties()->keywordList();
477 if ( !keywords.isEmpty() )
478 {
479 QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
480 for ( const QString &keyword : keywords.split( ',' ) )
481 {
482 if ( !keyword.trimmed().isEmpty() )
483 {
484 QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
485 const QDomText keywordText = doc.createTextNode( keyword.trimmed() );
486 keywordElem.appendChild( keywordText );
487 keywordsElem.appendChild( keywordElem );
488 }
489 }
490 layerElem.appendChild( keywordsElem );
491 }
492
493 //create DefaultSRS element
494 const QString defaultSrs = layer->crs().authid();
495 QDomElement srsElem = doc.createElement( QStringLiteral( "DefaultSRS" ) );
496 const QDomText srsText = doc.createTextNode( defaultSrs );
497 srsElem.appendChild( srsText );
498 layerElem.appendChild( srsElem );
499
500 //create OtherSRS elements
501 const QStringList outputCrsList = QgsServerProjectUtils::wmsOutputCrsList( *project );
502 for ( const QString &crs : outputCrsList )
503 {
504 if ( crs == defaultSrs )
505 continue;
506 QDomElement otherSrsElem = doc.createElement( QStringLiteral( "OtherSRS" ) );
507 const QDomText otherSrsText = doc.createTextNode( crs );
508 otherSrsElem.appendChild( otherSrsText );
509 layerElem.appendChild( otherSrsElem );
510 }
511
512 //wfs:Operations element
513 QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" ) /*wfs:Operations*/ );
514 //wfs:Query element
515 QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
516 const QDomText queryText = doc.createTextNode( QStringLiteral( "Query" ) );
517 operationElement.appendChild( queryText );
518 operationsElement.appendChild( operationElement );
519
520 if ( wfstUpdateLayersId.contains( layer->id() ) || wfstInsertLayersId.contains( layer->id() ) || wfstDeleteLayersId.contains( layer->id() ) )
521 {
522 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
523 QgsVectorDataProvider *provider = vlayer->dataProvider();
524 if ( ( provider->capabilities() & Qgis::VectorProviderCapability::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
525 {
526 //wfs:Insert element
527 QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
528 const QDomText insertText = doc.createTextNode( QStringLiteral( "Insert" ) /*wfs:Insert*/ );
529 operationElement.appendChild( insertText );
530 operationsElement.appendChild( operationElement );
531 }
532
533 if ( ( provider->capabilities() & Qgis::VectorProviderCapability::ChangeAttributeValues ) && ( provider->capabilities() & Qgis::VectorProviderCapability::ChangeGeometries ) && wfstUpdateLayersId.contains( layer->id() ) )
534 {
535 //wfs:Update element
536 QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
537 const QDomText updateText = doc.createTextNode( QStringLiteral( "Update" ) /*wfs:Update*/ );
538 operationElement.appendChild( updateText );
539 operationsElement.appendChild( operationElement );
540 }
541
542 if ( ( provider->capabilities() & Qgis::VectorProviderCapability::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
543 {
544 //wfs:Delete element
545 QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
546 const QDomText deleteText = doc.createTextNode( QStringLiteral( "Delete" ) /*wfs:Delete*/ );
547 operationElement.appendChild( deleteText );
548 operationsElement.appendChild( operationElement );
549 }
550 }
551
552 layerElem.appendChild( operationsElement );
553
554 //create WGS84BoundingBox
555 const QgsRectangle layerExtent = layer->extent();
556 //transform the layers native CRS into WGS84
558 const int wgs84precision = 6;
559 QgsRectangle wgs84BoundingRect( 0, 0, 0, 0 );
560 if ( !layerExtent.isNull() )
561 {
562 const QgsCoordinateTransform exGeoTransform( layer->crs(), wgs84, project );
563 try
564 {
565 wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
566 }
567 catch ( const QgsCsException & )
568 {
569 wgs84BoundingRect = QgsRectangle( 0, 0, 0, 0 );
570 }
571 }
572
573 //create WGS84BoundingBox element
574 QDomElement bBoxElement = doc.createElement( QStringLiteral( "ows:WGS84BoundingBox" ) );
575 bBoxElement.setAttribute( QStringLiteral( "dimensions" ), QStringLiteral( "2" ) );
576 QDomElement lCornerElement = doc.createElement( QStringLiteral( "ows:LowerCorner" ) );
577 const QDomText lCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.xMinimum(), wgs84precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.yMinimum(), wgs84precision ), wgs84precision ) );
578 lCornerElement.appendChild( lCornerText );
579 bBoxElement.appendChild( lCornerElement );
580 QDomElement uCornerElement = doc.createElement( QStringLiteral( "ows:UpperCorner" ) );
581 const QDomText uCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.xMaximum(), wgs84precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.yMaximum(), wgs84precision ), wgs84precision ) );
582 uCornerElement.appendChild( uCornerText );
583 bBoxElement.appendChild( uCornerElement );
584 layerElem.appendChild( bBoxElement );
585
586 // layer metadata URL
587 const QList<QgsMapLayerServerProperties::MetadataUrl> urls = layer->serverProperties()->metadataUrls();
588 for ( const QgsMapLayerServerProperties::MetadataUrl &url : urls )
589 {
590 QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
591 const QString metadataUrlType = url.type;
592 metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType );
593 const QString metadataUrlFormat = url.format;
594 metaUrlElem.setAttribute( QStringLiteral( "format" ), metadataUrlFormat );
595 const QDomText metaUrlText = doc.createTextNode( url.url );
596 metaUrlElem.appendChild( metaUrlText );
597 layerElem.appendChild( metaUrlElem );
598 }
599
600 featureTypeListElement.appendChild( layerElem );
601 }
602
603 return featureTypeListElement;
604 }
605
606} // namespace QgsWfs
@ AddFeatures
Allows adding features.
@ ChangeGeometries
Allows modifications of geometries.
@ DeleteFeatures
Allows deletion of features.
@ ChangeAttributeValues
Allows modification of attribute values.
@ Vector
Vector layer.
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.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
Class for doing transforms between two map coordinate systems.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
QString keywordList() const
Returns the keyword list of the layerused by QGIS Server in GetCapabilities request.
QString wfsTitle() const
Returns the optional WFS title if set or the title of the layer used by QGIS WFS in GetCapabilities r...
QString abstract() const
Returns the abstract of the layerused by QGIS Server in GetCapabilities request.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:83
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QString id
Definition qgsmaplayer.h:79
Qgis::LayerType type
Definition qgsmaplayer.h:86
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 rectangle specified with double values.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
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.
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
QList< QgsServerMetadataUrlProperties::MetadataUrl > metadataUrls() const
Returns a list of metadataUrl resources associated for the layer.
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...
Provides a way to retrieve settings by prioritizing according to environment variables,...
This is the base class for vector data providers.
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
Represents a vector layer which manages a vector based data sets.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
SERVER_EXPORT double ceilWithPrecision(double number, int places)
Returns a double greater than number to the specified number of places.
SERVER_EXPORT QString owsServiceAccessConstraints(const QgsProject &project)
Returns the owsService access constraints defined in project.
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
SERVER_EXPORT QString owsServiceOnlineResource(const QgsProject &project)
Returns the owsService online resource defined in project.
SERVER_EXPORT QString owsServiceFees(const QgsProject &project)
Returns the owsService fees defined in project.
SERVER_EXPORT QStringList owsServiceKeywords(const QgsProject &project)
Returns the owsService keywords defined in project.
SERVER_EXPORT QString owsServiceContactPosition(const QgsProject &project)
Returns the owsService contact position defined in project.
SERVER_EXPORT QStringList wfstUpdateLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with update capabilities.
SERVER_EXPORT QStringList wfstInsertLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with insert capabilities.
SERVER_EXPORT QStringList wmsOutputCrsList(const QgsProject &project)
Returns the WMS output CRS list.
SERVER_EXPORT QString owsServiceContactOrganization(const QgsProject &project)
Returns the owsService contact organization defined in project.
SERVER_EXPORT QString owsServiceTitle(const QgsProject &project)
Returns the owsService title defined in project.
SERVER_EXPORT QString owsServiceContactMail(const QgsProject &project)
Returns the owsService contact mail defined in project.
SERVER_EXPORT QString owsServiceAbstract(const QgsProject &project)
Returns the owsService abstract defined in project.
SERVER_EXPORT double floorWithPrecision(double number, int places)
Returns a double less than number to the specified number of places.
SERVER_EXPORT QStringList wfstDeleteLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with delete capabilities.
SERVER_EXPORT QString owsServiceContactPhone(const QgsProject &project)
Returns the owsService contact phone defined in project.
SERVER_EXPORT QString owsServiceContactPerson(const QgsProject &project)
Returns the owsService contact person defined in project.
WMS implementation.
Definition qgswfs.cpp:36
QString layerTypeName(const QgsMapLayer *layer)
Returns typename from vector layer.
QString implementationVersion()
Returns the highest version supported by this implementation.
QDomElement getParameterElement(QDomDocument &doc, const QString &name, const QStringList &values)
Create a parameter element.
QString serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Service URL string.
const QString OGC_NAMESPACE
Definition qgswfsutils.h:76
QDomElement getOperationsMetadataElement(QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request, const QgsServerSettings *settings)
Create OperationsMetadata element for get capabilities document.
const QString GML_NAMESPACE
Definition qgswfsutils.h:75
const QString WFS_NAMESPACE
Definition qgswfsutils.h:74
QDomElement getFeatureTypeListElement(QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project)
Create FeatureTypeList element for get capabilities document.
void writeGetCapabilities(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WFS GetCapabilities response.
QDomDocument createGetCapabilitiesDocument(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Create get capabilities document.
QDomElement getServiceIdentificationElement(QDomDocument &doc, const QgsProject *project)
Create Service Identification element for get capabilities document.
QDomElement getServiceProviderElement(QDomDocument &doc, const QgsProject *project)
Create Service Provider element for get capabilities document.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:5983
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition qgis.h:6555
const QgsCoordinateReferenceSystem & crs