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