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