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