QGIS API Documentation  3.6.0-Noosa (5873452)
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  QgsAccessControl *accessControl = nullptr;
42 #ifdef HAVE_SERVER_PYTHON_PLUGINS
43  accessControl = serverIface->accessControls();
44 #endif
45  QDomDocument doc;
46  const QDomDocument *capabilitiesDocument = nullptr;
47 
48  QgsServerCacheManager *cacheManager = nullptr;
49 #ifdef HAVE_SERVER_PYTHON_PLUGINS
50  cacheManager = serverIface->cacheManager();
51 #endif
52  if ( cacheManager && cacheManager->getCachedDocument( &doc, project, request, accessControl ) )
53  {
54  capabilitiesDocument = &doc;
55  }
56  else //capabilities xml not in cache. Create a new one
57  {
58  doc = createGetCapabilitiesDocument( serverIface, project, version, request );
59 
60  if ( cacheManager )
61  {
62  cacheManager->setCachedDocument( &doc, project, request, accessControl );
63  }
64  capabilitiesDocument = &doc;
65  }
66 
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( "DWithin" )
130  << QStringLiteral( "Beyond" ) << 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  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  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  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  QString title = QgsServerProjectUtils::owsServiceTitle( *project );
173  if ( !title.isEmpty() )
174  {
175  QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
176  QDomText titleText = doc.createTextNode( title );
177  titleElem.appendChild( titleText );
178  serviceElem.appendChild( titleElem );
179  }
180 
181  QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project );
182  if ( !abstract.isEmpty() )
183  {
184  QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
185  QDomText abstractText = doc.createCDATASection( abstract );
186  abstractElem.appendChild( abstractText );
187  serviceElem.appendChild( abstractElem );
188  }
189 
190  QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project );
191  if ( !keywords.isEmpty() && !keywords.join( QStringLiteral( ", " ) ).isEmpty() )
192  {
193  QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
194  for ( const QString &keyword : keywords )
195  {
196  if ( !keyword.isEmpty() )
197  {
198  QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
199  QDomText keywordText = doc.createTextNode( keyword );
200  keywordElem.appendChild( keywordText );
201  keywordsElem.appendChild( keywordElem );
202  }
203  }
204  serviceElem.appendChild( keywordsElem );
205  }
206 
207  //Service type
208  QDomElement serviceTypeElem = doc.createElement( QStringLiteral( "ows:ServiceType" ) );
209  QDomText serviceTypeText = doc.createTextNode( "WFS" );
210  serviceTypeElem.appendChild( serviceTypeText );
211  serviceElem.appendChild( serviceTypeElem );
212 
213  //Service type version
214  QDomElement serviceTypeVersionElem = doc.createElement( QStringLiteral( "ows:ServiceTypeVersion" ) );
215  QDomText serviceTypeVersionText = doc.createTextNode( "1.1.0" );
216  serviceTypeVersionElem.appendChild( serviceTypeVersionText );
217  serviceElem.appendChild( serviceTypeVersionElem );
218 
219  QDomElement feesElem = doc.createElement( QStringLiteral( "ows:Fees" ) );
220  QDomText feesText = doc.createTextNode( "None" );
221  const QString fees = QgsServerProjectUtils::owsServiceFees( *project );
222  if ( !fees.isEmpty() )
223  {
224  feesText = doc.createTextNode( fees );
225  }
226  feesElem.appendChild( feesText );
227  serviceElem.appendChild( feesElem );
228 
229  QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( "ows:AccessConstraints" ) );
230  const QString accessConstraints = QgsServerProjectUtils::owsServiceAccessConstraints( *project );
231  QDomText accessConstraintsText = doc.createTextNode( "None" );
232  if ( !accessConstraints.isEmpty() )
233  {
234  accessConstraintsText = doc.createTextNode( accessConstraints );
235  }
236  accessConstraintsElem.appendChild( accessConstraintsText );
237  serviceElem.appendChild( accessConstraintsElem );
238 
239  return serviceElem;
240 
241  }
242 
243  QDomElement getServiceProviderElement( QDomDocument &doc, const QgsProject *project )
244  {
245  //Service element
246  QDomElement serviceElem = doc.createElement( QStringLiteral( "ows:ServiceProvider" ) );
247 
248  //ProviderName
249  const QString contactOrganization = QgsServerProjectUtils::owsServiceContactOrganization( *project );
250  if ( !contactOrganization.isEmpty() )
251  {
252  QDomElement providerNameElem = doc.createElement( QStringLiteral( "ows:ProviderName" ) );
253  QDomText providerNameText = doc.createTextNode( contactOrganization );
254  providerNameElem.appendChild( providerNameText );
255  serviceElem.appendChild( providerNameElem );
256  }
257 
258  const QString contactPerson = QgsServerProjectUtils::owsServiceContactPerson( *project );
259  const QString contactPosition = QgsServerProjectUtils::owsServiceContactPosition( *project );
260  if ( !contactPerson.isEmpty() ||
261  !contactPosition.isEmpty() )
262  {
263  //Contact information
264  QDomElement serviceContactElem = doc.createElement( QStringLiteral( "ows:ServiceContact" ) );
265 
266  if ( !contactPerson.isEmpty() )
267  {
268  QDomElement individualNameElem = doc.createElement( QStringLiteral( "ows:IndividualName" ) );
269  QDomText individualNameText = doc.createTextNode( contactPerson );
270  individualNameElem.appendChild( individualNameText );
271  serviceContactElem.appendChild( individualNameElem );
272  }
273 
274  if ( !contactPosition.isEmpty() )
275  {
276  QDomElement positionNameElem = doc.createElement( QStringLiteral( "ows:PositionName" ) );
277  QDomText positionNameText = doc.createTextNode( contactPosition );
278  positionNameElem.appendChild( positionNameText );
279  serviceContactElem.appendChild( positionNameElem );
280  }
281 
282  const QString contactMail = QgsServerProjectUtils::owsServiceContactMail( *project );
283  const QString contactPhone = QgsServerProjectUtils::owsServiceContactPhone( *project );
284  const QString onlineResource = QgsServerProjectUtils::owsServiceOnlineResource( *project );
285  if ( !contactMail.isEmpty() ||
286  !contactPhone.isEmpty() ||
287  !onlineResource.isEmpty() )
288  {
289  //Contact information
290  QDomElement contactInfoElem = doc.createElement( QStringLiteral( "ows:ContactInfo" ) );
291 
292  if ( !contactPhone.isEmpty() )
293  {
294  QDomElement phoneElem = doc.createElement( QStringLiteral( "ows:Phone" ) );
295  QDomElement voiceElem = doc.createElement( QStringLiteral( "ows:Voice" ) );
296  QDomText voiceText = doc.createTextNode( contactPhone );
297  voiceElem.appendChild( voiceText );
298  phoneElem.appendChild( voiceElem );
299  contactInfoElem.appendChild( phoneElem );
300  }
301 
302  if ( !contactMail.isEmpty() )
303  {
304  QDomElement addressElem = doc.createElement( QStringLiteral( "ows:Address" ) );
305  QDomElement mailElem = doc.createElement( QStringLiteral( "ows:ElectronicMailAddress" ) );
306  QDomText mailText = doc.createTextNode( contactMail );
307  mailElem.appendChild( mailText );
308  addressElem.appendChild( mailElem );
309  contactInfoElem.appendChild( addressElem );
310  }
311 
312  if ( !onlineResource.isEmpty() )
313  {
314  QDomElement onlineResourceElem = doc.createElement( QStringLiteral( "ows:OnlineResource" ) );
315  onlineResourceElem.setAttribute( "xlink:href", onlineResource );
316  contactInfoElem.appendChild( onlineResourceElem );
317  }
318  }
319 
320  QDomElement roleElem = doc.createElement( QStringLiteral( "ows:Role" ) );
321  QDomText roleText = doc.createTextNode( "PointOfContact" );
322  roleElem.appendChild( roleText );
323  serviceContactElem.appendChild( roleElem );
324 
325  serviceElem.appendChild( serviceContactElem );
326  }
327 
328  return serviceElem;
329 
330  }
331 
332  QDomElement getParameterElement( QDomDocument &doc, const QString &name, const QStringList &values )
333  {
334  QDomElement parameterElement = doc.createElement( QStringLiteral( "ows:Parameter" ) );
335  parameterElement.setAttribute( QStringLiteral( "name" ), name );
336 
337  for ( const QString &v : values )
338  {
339  QDomElement valueElement = doc.createElement( QStringLiteral( "ows:Value" ) );
340  QDomText valueText = doc.createTextNode( v );
341  valueElement.appendChild( valueText );
342  parameterElement.appendChild( valueElement );
343  }
344 
345  return parameterElement;
346  }
347 
348  QDomElement getOperationsMetadataElement( QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request )
349  {
350  QDomElement oprationsElement = doc.createElement( QStringLiteral( "ows:OperationsMetadata" ) );
351 
352  //Prepare url
353  QString hrefString = serviceUrl( request, project );
354 
355  QDomElement operationElement = doc.createElement( QStringLiteral( "ows:Operation" ) );
356  QDomElement dcpElement = doc.createElement( QStringLiteral( "ows:DCP" ) );
357  QDomElement httpElement = doc.createElement( QStringLiteral( "ows:HTTP" ) );
358  QDomElement getElement = doc.createElement( QStringLiteral( "ows:Get" ) );
359  getElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
360  httpElement.appendChild( getElement );
361 
362  QDomElement postElement = doc.createElement( QStringLiteral( "ows:Post" ) );
363  postElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
364  httpElement.appendChild( postElement );
365 
366  dcpElement.appendChild( httpElement );
367  operationElement.appendChild( dcpElement );
368 
369  // GetCapabilities
370  QDomElement getCapabilitiesElement = operationElement.cloneNode().toElement();
371  getCapabilitiesElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "GetCapabilities" ) );
372  // GetCapabilities service
373  QDomElement serviceParameterElement = getParameterElement( doc, QStringLiteral( "service" ),
374  QStringList() << QStringLiteral( "WFS" ) );
375  getCapabilitiesElement.appendChild( serviceParameterElement );
376  // GetCapabilities AcceptVersions
377  QDomElement acceptVersionsParameterElement = getParameterElement( doc, QStringLiteral( "AcceptVersions" ),
378  QStringList() << QStringLiteral( "1.1.0" ) << QStringLiteral( "1.0.0" ) );
379  getCapabilitiesElement.appendChild( acceptVersionsParameterElement );
380  // GetCapabilities AcceptFormats
381  QDomElement acceptFormatsParameterElement = getParameterElement( doc, QStringLiteral( "AcceptFormats" ),
382  QStringList() << QStringLiteral( "text/xml" ) );
383  getCapabilitiesElement.appendChild( acceptFormatsParameterElement );
384  // Add
385  oprationsElement.appendChild( getCapabilitiesElement );
386 
387  // DescribeFeatureType
388  QDomElement describeFeatureTypeElement = operationElement.cloneNode().toElement();
389  describeFeatureTypeElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "DescribeFeatureType" ) );
390  // DescribeFeatureType outputFormat
391  QDomElement dftOutputFormatParameterElement = getParameterElement( doc, QStringLiteral( "outputFormat" ),
392  QStringList() << QStringLiteral( "XMLSCHEMA" )
393  << QStringLiteral( "text/xml; subtype=gml/2.1.2" )
394  << QStringLiteral( "text/xml; subtype=gml/3.1.1" ) );
395  describeFeatureTypeElement.appendChild( dftOutputFormatParameterElement );
396  // Add
397  oprationsElement.appendChild( describeFeatureTypeElement );
398 
399  // GetFeature
400  QDomElement getFeatureElement = operationElement.cloneNode().toElement();
401  getFeatureElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "GetFeature" ) );
402  // GetFeature outputFormat
403  QDomElement gfOutputFormatParameterElement = getParameterElement( doc, QStringLiteral( "outputFormat" ),
404  QStringList() << QStringLiteral( "text/xml; subtype=gml/2.1.2" )
405  << QStringLiteral( "text/xml; subtype=gml/3.1.1" )
406  << QStringLiteral( "application/vnd.geo+json" ) );
407  getFeatureElement.appendChild( gfOutputFormatParameterElement );
408  // GetFeature resultType
409  QDomElement resultTypeParameterElement = getParameterElement( doc, QStringLiteral( "resultType" ),
410  QStringList() << QStringLiteral( "results" ) << QStringLiteral( "hits" ) );
411  getFeatureElement.appendChild( resultTypeParameterElement );
412  // Add
413  oprationsElement.appendChild( getFeatureElement );
414 
415  // Transaction
416  QDomElement transactionElement = operationElement.cloneNode().toElement();
417  transactionElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "Transaction" ) );
418  // GetFeature inputFormat
419  QDomElement inputFormatParameterElement = getParameterElement( doc, QStringLiteral( "inputFormat" ),
420  QStringList() << QStringLiteral( "text/xml; subtype=gml/2.1.2" )
421  << QStringLiteral( "text/xml; subtype=gml/3.1.1" )
422  << QStringLiteral( "application/vnd.geo+json" ) );
423  transactionElement.appendChild( inputFormatParameterElement );
424  // Add
425  oprationsElement.appendChild( transactionElement );
426 
427  return oprationsElement;
428 
429  }
430 
431  QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project )
432  {
433  QgsAccessControl *accessControl = serverIface->accessControls();
434 
435  //wfs:FeatureTypeList element
436  QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" )/*wfs:FeatureTypeList*/ );
437  //wfs:Operations element
438  QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
439  featureTypeListElement.appendChild( operationsElement );
440  //wfs:Query element
441  QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
442  QDomText queryText = doc.createTextNode( "Query" );
443  operationElement.appendChild( queryText );
444  operationsElement.appendChild( operationElement );
445 
446  const QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
447  const QStringList wfstUpdateLayersId = QgsServerProjectUtils::wfstUpdateLayerIds( *project );
448  const QStringList wfstInsertLayersId = QgsServerProjectUtils::wfstInsertLayerIds( *project );
449  const QStringList wfstDeleteLayersId = QgsServerProjectUtils::wfstDeleteLayerIds( *project );
450  for ( const QString &wfsLayerId : wfsLayerIds )
451  {
452  QgsMapLayer *layer = project->mapLayer( wfsLayerId );
453  if ( !layer )
454  {
455  continue;
456  }
457  if ( layer->type() != QgsMapLayer::LayerType::VectorLayer )
458  {
459  continue;
460  }
461  if ( accessControl && !accessControl->layerReadPermission( layer ) )
462  {
463  continue;
464  }
465 
466  QDomElement layerElem = doc.createElement( QStringLiteral( "FeatureType" ) );
467 
468  //create Name
469  QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
470  QDomText nameText = doc.createTextNode( layerTypeName( layer ) );
471  nameElem.appendChild( nameText );
472  layerElem.appendChild( nameElem );
473 
474  //create Title
475  QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
476  QString title = layer->title();
477  if ( title.isEmpty() )
478  {
479  title = layer->name();
480  }
481  QDomText titleText = doc.createTextNode( title );
482  titleElem.appendChild( titleText );
483  layerElem.appendChild( titleElem );
484 
485  //create Abstract
486  QString abstract = layer->abstract();
487  if ( !abstract.isEmpty() )
488  {
489  QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
490  QDomText abstractText = doc.createTextNode( abstract );
491  abstractElem.appendChild( abstractText );
492  layerElem.appendChild( abstractElem );
493  }
494 
495  //create keywords
496  QString keywords = layer->keywordList();
497  if ( !keywords.isEmpty() )
498  {
499  QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
500  for ( const QString &keyword : keywords.split( ',' ) )
501  {
502  if ( !keyword.trimmed().isEmpty() )
503  {
504  QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
505  QDomText keywordText = doc.createTextNode( keyword.trimmed() );
506  keywordElem.appendChild( keywordText );
507  keywordsElem.appendChild( keywordElem );
508  }
509  }
510  layerElem.appendChild( keywordsElem );
511  }
512 
513  //create DefaultSRS element
514  const QString defaultSrs = layer->crs().authid();
515  QDomElement srsElem = doc.createElement( QStringLiteral( "DefaultSRS" ) );
516  QDomText srsText = doc.createTextNode( defaultSrs );
517  srsElem.appendChild( srsText );
518  layerElem.appendChild( srsElem );
519 
520  //create OtherSRS elements
521  const QStringList outputCrsList = QgsServerProjectUtils::wmsOutputCrsList( *project );
522  for ( const QString &crs : outputCrsList )
523  {
524  if ( crs == defaultSrs )
525  continue;
526  QDomElement otherSrsElem = doc.createElement( QStringLiteral( "OtherSRS" ) );
527  QDomText otherSrsText = doc.createTextNode( crs );
528  otherSrsElem.appendChild( otherSrsText );
529  layerElem.appendChild( otherSrsElem );
530  }
531 
532  //wfs:Operations element
533  QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
534  //wfs:Query element
535  QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
536  QDomText queryText = doc.createTextNode( QStringLiteral( "Query" ) );
537  operationElement.appendChild( queryText );
538  operationsElement.appendChild( operationElement );
539 
540  if ( wfstUpdateLayersId.contains( layer->id() ) ||
541  wfstInsertLayersId.contains( layer->id() ) ||
542  wfstDeleteLayersId.contains( layer->id() ) )
543  {
544  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
545  QgsVectorDataProvider *provider = vlayer->dataProvider();
546  if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
547  {
548  //wfs:Insert element
549  QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
550  QDomText insertText = doc.createTextNode( QStringLiteral( "Insert" )/*wfs:Insert*/ );
551  operationElement.appendChild( insertText );
552  operationsElement.appendChild( operationElement );
553  }
554 
555  if ( ( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
556  ( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
557  wfstUpdateLayersId.contains( layer->id() ) )
558  {
559  //wfs:Update element
560  QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
561  QDomText updateText = doc.createTextNode( QStringLiteral( "Update" )/*wfs:Update*/ );
562  operationElement.appendChild( updateText );
563  operationsElement.appendChild( operationElement );
564  }
565 
566  if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
567  {
568  //wfs:Delete element
569  QDomElement operationElement = doc.createElement( QStringLiteral( "Operation" ) );
570  QDomText deleteText = doc.createTextNode( QStringLiteral( "Delete" )/*wfs:Delete*/ );
571  operationElement.appendChild( deleteText );
572  operationsElement.appendChild( operationElement );
573  }
574  }
575 
576  layerElem.appendChild( operationsElement );
577 
578  //create OutputFormats element
579  QDomElement outputFormatsElem = doc.createElement( QStringLiteral( "OutputFormats" ) );
580  QDomElement outputFormatElem = doc.createElement( QStringLiteral( "Format" ) );
581  QDomText outputFormatText = doc.createTextNode( QStringLiteral( "text/xml; subtype=gml/3.1.1" ) );
582  outputFormatElem.appendChild( outputFormatText );
583  outputFormatsElem.appendChild( outputFormatElem );
584  layerElem.appendChild( outputFormatsElem );
585 
586  //create WGS84BoundingBox
587  QgsRectangle layerExtent = layer->extent();
588  //transform the layers native CRS into WGS84
590  QgsRectangle wgs84BoundingRect;
591  if ( !layerExtent.isNull() )
592  {
593  QgsCoordinateTransform exGeoTransform( layer->crs(), wgs84, project );
594  try
595  {
596  wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
597  }
598  catch ( const QgsCsException & )
599  {
600  wgs84BoundingRect = QgsRectangle();
601  }
602  }
603 
604  //create WGS84BoundingBox element
605  QDomElement bBoxElement = doc.createElement( QStringLiteral( "ows:WGS84BoundingBox" ) );
606  bBoxElement.setAttribute( QStringLiteral( "dimensions" ), QStringLiteral( "2" ) );
607  QDomElement lCornerElement = doc.createElement( QStringLiteral( "ows:LowerCorner" ) );
608  QDomText lCornerText = doc.createTextNode( QString::number( wgs84BoundingRect.xMinimum() ) + " " + QString::number( wgs84BoundingRect.yMinimum() ) );
609  lCornerElement.appendChild( lCornerText );
610  bBoxElement.appendChild( lCornerElement );
611  QDomElement uCornerElement = doc.createElement( QStringLiteral( "ows:UpperCorner" ) );
612  QDomText uCornerText = doc.createTextNode( QString::number( wgs84BoundingRect.xMaximum() ) + " " + QString::number( wgs84BoundingRect.yMaximum() ) );
613  uCornerElement.appendChild( uCornerText );
614  bBoxElement.appendChild( uCornerElement );
615  layerElem.appendChild( bBoxElement );
616 
617  // layer metadata URL
618  QString metadataUrl = layer->metadataUrl();
619  if ( !metadataUrl.isEmpty() )
620  {
621  QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
622  QString metadataUrlType = layer->metadataUrlType();
623  metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType );
624  QString metadataUrlFormat = layer->metadataUrlFormat();
625  metaUrlElem.setAttribute( QStringLiteral( "format" ), metadataUrlFormat );
626  QDomText metaUrlText = doc.createTextNode( metadataUrl );
627  metaUrlElem.appendChild( metaUrlText );
628  layerElem.appendChild( metaUrlElem );
629  }
630 
631  featureTypeListElement.appendChild( layerElem );
632  }
633 
634  return featureTypeListElement;
635  }
636 
637 } // namespace QgsWfs
638 
639 
640 
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...
SERVER_EXPORT QStringList wmsOutputCrsList(const QgsProject &project)
Returns the WMS output CRS list.
QDomElement getParameterElement(QDomDocument &doc, const QString &name, const QStringList &values)
Create a parameter element.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:64
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...
QDomDocument createGetCapabilitiesDocument(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Create get capabilities document.
SERVER_EXPORT QString owsServiceContactPosition(const QgsProject &project)
Returns the owsService contact position defined in project.
SERVER_EXPORT QString owsServiceContactPerson(const QgsProject &project)
Returns the owsService contact person defined in project.
SERVER_EXPORT QStringList owsServiceKeywords(const QgsProject &project)
Returns the owsService keywords defined in project.
QDomElement getFeatureTypeListElement(QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project)
Create FeatureTypeList element for get capabilities document.
SERVER_EXPORT QString owsServiceAbstract(const QgsProject &project)
Returns the owsService abstract defined in project.
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:289
const QgsCoordinateReferenceSystem & crs
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device...
QgsMapLayer::LayerType type() const
Returns the type of the layer.
QString layerTypeName(const QgsMapLayer *layer)
Returns typename from vector layer.
Definition: qgswfsutils.cpp:71
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString metadataUrlFormat() const
Returns the metadata format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:437
QString serviceUrl(const QgsServerRequest &request, const QgsProject *project)
Service URL string.
Definition: qgswfsutils.cpp:37
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
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...
WMS implementation.
Definition: qgswfs.cpp:35
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:305
QDomElement getServiceIdentificationElement(QDomDocument &doc, const QgsProject *project)
Create Service Identification element for get capabilities document.
const QString GML_NAMESPACE
Definition: qgswfsutils.h:67
const QString WFS_NAMESPACE
Definition: qgswfsutils.h:66
A helper class that centralizes caches accesses given by all the server cache filter plugins...
Allows modifications of geometries.
Reads and writes project states.
Definition: qgsproject.h:89
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:69
QDomElement getOperationsMetadataElement(QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request)
Create OperationsMetadata element for get capabilities document.
QString implementationVersion()
Returns the highest version supported by this implementation.
Definition: qgswfsutils.cpp:32
SERVER_EXPORT QString owsServiceFees(const QgsProject &project)
Returns the owsService fees defined in project.
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.
SERVER_EXPORT QString owsServiceAccessConstraints(const QgsProject &project)
Returns the owsService access constraints defined in project.
SERVER_EXPORT QString owsServiceOnlineResource(const QgsProject &project)
Returns the owsService online resource defined in project.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:273
SERVER_EXPORT QString owsServiceContactOrganization(const QgsProject &project)
Returns the owsService contact organization defined in project.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
const QString OGC_NAMESPACE
Definition: qgswfsutils.h:68
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
This class represents a coordinate reference system (CRS).
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:436
bool setCachedDocument(const QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Updates or inserts the document in cache like capabilities.
Class for doing transforms between two map coordinate systems.
virtual QgsServerCacheManager * cacheManager() const =0
Gets the registered server cache filters.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
A helper class that centralizes restrictions given by all the access control filter plugins...
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
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...
void writeGetCapabilities(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WFS GetCapabilities response.
QString metadataUrl() const
Returns the metadata URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:401
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QString name
Definition: qgsmaplayer.h:68
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
SERVER_EXPORT QString owsServiceContactMail(const QgsProject &project)
Returns the owsService contact mail defined in project.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer&#39;s data provider, it may be null.
This is the base class for vector data providers.
QDomElement getServiceProviderElement(QDomDocument &doc, const QgsProject *project)
Create Service Provider element for get capabilities document.
Represents a vector layer which manages a vector based data sets.
Allows modification of attribute values.
QString authid() const
Returns the authority identifier for the CRS.
SERVER_EXPORT QString owsServiceTitle(const QgsProject &project)
Returns the owsService title defined in project.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:71
QString metadataUrlType() const
Returns the metadata type of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:419
SERVER_EXPORT QString owsServiceContactPhone(const QgsProject &project)
Returns the owsService contact phone defined in project.