42 #ifdef HAVE_SERVER_PYTHON_PLUGINS
46 const QDomDocument *capabilitiesDocument =
nullptr;
48 #ifdef HAVE_SERVER_PYTHON_PLUGINS
50 if ( cacheManager && cacheManager->
getCachedDocument( &doc, project, request, accessControl ) )
52 capabilitiesDocument = &doc;
62 capabilitiesDocument = &doc;
66 capabilitiesDocument = &doc;
68 response.
setHeader( QStringLiteral(
"Content-Type" ), QStringLiteral(
"text/xml; charset=utf-8" ) );
69 response.
write( capabilitiesDocument->toByteArray() );
81 QDomElement wfsCapabilitiesElement = doc.createElement( QStringLiteral(
"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" ) );
90 wfsCapabilitiesElement.setAttribute( QStringLiteral(
"updateSequence" ), QStringLiteral(
"0" ) );
91 doc.appendChild( wfsCapabilitiesElement );
109 QDomElement filterCapabilitiesElement = doc.createElement( QStringLiteral(
"ogc:Filter_Capabilities" ) );
110 wfsCapabilitiesElement.appendChild( filterCapabilitiesElement );
111 QDomElement spatialCapabilitiesElement = doc.createElement( QStringLiteral(
"ogc:Spatial_Capabilities" ) );
112 filterCapabilitiesElement.appendChild( spatialCapabilitiesElement );
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 )
120 QDomElement geometryOperandElem = doc.createElement( QStringLiteral(
"ogc:GeometryOperand" ) );
121 const QDomText geometryOperandText = doc.createTextNode( geometryOperand );
122 geometryOperandElem.appendChild( geometryOperandText );
123 geometryOperandsElem.appendChild( geometryOperandElem );
125 spatialCapabilitiesElement.appendChild( geometryOperandsElem );
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 )
134 QDomElement spatialOperatorElem = doc.createElement( QStringLiteral(
"ogc:SpatialOperator" ) );
135 spatialOperatorElem.setAttribute( QStringLiteral(
"name" ), spatialOperator );
136 spatialOperatorsElem.appendChild( spatialOperatorElem );
138 spatialCapabilitiesElement.appendChild( spatialOperatorsElem );
139 QDomElement scalarCapabilitiesElement = doc.createElement( QStringLiteral(
"ogc:Scalar_Capabilities" ) );
140 filterCapabilitiesElement.appendChild( scalarCapabilitiesElement );
141 const QDomElement logicalOperatorsElement = doc.createElement( QStringLiteral(
"ogc:LogicalOperators" ) );
142 scalarCapabilitiesElement.appendChild( logicalOperatorsElement );
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 )
151 QDomElement comparisonOperatorElem = doc.createElement( QStringLiteral(
"ogc:ComparisonOperator" ) );
152 const QDomText comparisonOperatorText = doc.createTextNode( comparisonOperator );
153 comparisonOperatorElem.appendChild( comparisonOperatorText );
154 comparisonOperatorsElem.appendChild( comparisonOperatorElem );
156 scalarCapabilitiesElement.appendChild( comparisonOperatorsElem );
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 );
170 QDomElement serviceElem = doc.createElement( QStringLiteral(
"ows:ServiceIdentification" ) );
173 QDomElement titleElem = doc.createElement( QStringLiteral(
"ows:Title" ) );
174 const QDomText titleText = doc.createTextNode( title );
175 titleElem.appendChild( titleText );
176 serviceElem.appendChild( titleElem );
179 if ( !
abstract.isEmpty() )
181 QDomElement abstractElem = doc.createElement( QStringLiteral(
"ows:Abstract" ) );
182 const QDomText abstractText = doc.createCDATASection(
abstract );
183 abstractElem.appendChild( abstractText );
184 serviceElem.appendChild( abstractElem );
188 if ( !keywords.isEmpty() && !keywords.join( QLatin1String(
", " ) ).isEmpty() )
190 QDomElement keywordsElem = doc.createElement( QStringLiteral(
"ows:Keywords" ) );
191 for (
const QString &keyword : keywords )
193 if ( !keyword.isEmpty() )
195 QDomElement keywordElem = doc.createElement( QStringLiteral(
"ows:Keyword" ) );
196 const QDomText keywordText = doc.createTextNode( keyword );
197 keywordElem.appendChild( keywordText );
198 keywordsElem.appendChild( keywordElem );
201 serviceElem.appendChild( keywordsElem );
205 QDomElement serviceTypeElem = doc.createElement( QStringLiteral(
"ows:ServiceType" ) );
206 const QDomText serviceTypeText = doc.createTextNode(
"WFS" );
207 serviceTypeElem.appendChild( serviceTypeText );
208 serviceElem.appendChild( serviceTypeElem );
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 );
216 QDomElement feesElem = doc.createElement( QStringLiteral(
"ows:Fees" ) );
217 QDomText feesText = doc.createTextNode(
"None" );
219 if ( !fees.isEmpty() )
221 feesText = doc.createTextNode( fees );
223 feesElem.appendChild( feesText );
224 serviceElem.appendChild( feesElem );
226 QDomElement accessConstraintsElem = doc.createElement( QStringLiteral(
"ows:AccessConstraints" ) );
228 QDomText accessConstraintsText = doc.createTextNode(
"None" );
229 if ( !accessConstraints.isEmpty() )
231 accessConstraintsText = doc.createTextNode( accessConstraints );
233 accessConstraintsElem.appendChild( accessConstraintsText );
234 serviceElem.appendChild( accessConstraintsElem );
243 QDomElement serviceElem = doc.createElement( QStringLiteral(
"ows:ServiceProvider" ) );
247 if ( !contactOrganization.isEmpty() )
249 QDomElement providerNameElem = doc.createElement( QStringLiteral(
"ows:ProviderName" ) );
250 const QDomText providerNameText = doc.createTextNode( contactOrganization );
251 providerNameElem.appendChild( providerNameText );
252 serviceElem.appendChild( providerNameElem );
257 if ( !contactPerson.isEmpty() ||
258 !contactPosition.isEmpty() )
261 QDomElement serviceContactElem = doc.createElement( QStringLiteral(
"ows:ServiceContact" ) );
263 if ( !contactPerson.isEmpty() )
265 QDomElement individualNameElem = doc.createElement( QStringLiteral(
"ows:IndividualName" ) );
266 const QDomText individualNameText = doc.createTextNode( contactPerson );
267 individualNameElem.appendChild( individualNameText );
268 serviceContactElem.appendChild( individualNameElem );
271 if ( !contactPosition.isEmpty() )
273 QDomElement positionNameElem = doc.createElement( QStringLiteral(
"ows:PositionName" ) );
274 const QDomText positionNameText = doc.createTextNode( contactPosition );
275 positionNameElem.appendChild( positionNameText );
276 serviceContactElem.appendChild( positionNameElem );
282 if ( !contactMail.isEmpty() ||
283 !contactPhone.isEmpty() ||
284 !onlineResource.isEmpty() )
287 QDomElement contactInfoElem = doc.createElement( QStringLiteral(
"ows:ContactInfo" ) );
289 if ( !contactPhone.isEmpty() )
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 );
299 if ( !contactMail.isEmpty() )
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 );
309 if ( !onlineResource.isEmpty() )
311 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"ows:OnlineResource" ) );
312 onlineResourceElem.setAttribute(
"xlink:href", onlineResource );
313 contactInfoElem.appendChild( onlineResourceElem );
317 QDomElement roleElem = doc.createElement( QStringLiteral(
"ows:Role" ) );
318 const QDomText roleText = doc.createTextNode(
"PointOfContact" );
319 roleElem.appendChild( roleText );
320 serviceContactElem.appendChild( roleElem );
322 serviceElem.appendChild( serviceContactElem );
329 QDomElement
getParameterElement( QDomDocument &doc,
const QString &name,
const QStringList &values )
331 QDomElement parameterElement = doc.createElement( QStringLiteral(
"ows:Parameter" ) );
332 parameterElement.setAttribute( QStringLiteral(
"name" ), name );
334 for (
const QString &v : values )
336 QDomElement valueElement = doc.createElement( QStringLiteral(
"ows:Value" ) );
337 const QDomText valueText = doc.createTextNode( v );
338 valueElement.appendChild( valueText );
339 parameterElement.appendChild( valueElement );
342 return parameterElement;
347 QDomElement oprationsElement = doc.createElement( QStringLiteral(
"ows:OperationsMetadata" ) );
350 const QString hrefString =
serviceUrl( request, project, *settings );
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 );
359 QDomElement postElement = doc.createElement( QStringLiteral(
"ows:Post" ) );
360 postElement.setAttribute( QStringLiteral(
"xlink:href" ), hrefString );
361 httpElement.appendChild( postElement );
363 dcpElement.appendChild( httpElement );
364 operationElement.appendChild( dcpElement );
367 QDomElement getCapabilitiesElement = operationElement.cloneNode().toElement();
368 getCapabilitiesElement.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"GetCapabilities" ) );
370 const QDomElement serviceParameterElement =
getParameterElement( doc, QStringLiteral(
"service" ),
371 QStringList() << QStringLiteral(
"WFS" ) );
372 getCapabilitiesElement.appendChild( serviceParameterElement );
374 const QDomElement acceptVersionsParameterElement =
getParameterElement( doc, QStringLiteral(
"AcceptVersions" ),
375 QStringList() << QStringLiteral(
"1.1.0" ) << QStringLiteral(
"1.0.0" ) );
376 getCapabilitiesElement.appendChild( acceptVersionsParameterElement );
378 const QDomElement acceptFormatsParameterElement =
getParameterElement( doc, QStringLiteral(
"AcceptFormats" ),
379 QStringList() << QStringLiteral(
"text/xml" ) );
380 getCapabilitiesElement.appendChild( acceptFormatsParameterElement );
382 oprationsElement.appendChild( getCapabilitiesElement );
385 QDomElement describeFeatureTypeElement = operationElement.cloneNode().toElement();
386 describeFeatureTypeElement.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"DescribeFeatureType" ) );
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 );
394 oprationsElement.appendChild( describeFeatureTypeElement );
397 QDomElement getFeatureElement = operationElement.cloneNode().toElement();
398 getFeatureElement.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"GetFeature" ) );
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 );
406 const QDomElement resultTypeParameterElement =
getParameterElement( doc, QStringLiteral(
"resultType" ),
407 QStringList() << QStringLiteral(
"results" ) << QStringLiteral(
"hits" ) );
408 getFeatureElement.appendChild( resultTypeParameterElement );
410 oprationsElement.appendChild( getFeatureElement );
413 QDomElement transactionElement = operationElement.cloneNode().toElement();
414 transactionElement.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"Transaction" ) );
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 );
422 oprationsElement.appendChild( transactionElement );
424 return oprationsElement;
430 #ifdef HAVE_SERVER_PYTHON_PLUGINS
437 QDomElement featureTypeListElement = doc.createElement( QStringLiteral(
"FeatureTypeList" ) );
439 QDomElement operationsElement = doc.createElement( QStringLiteral(
"Operations" ) );
440 featureTypeListElement.appendChild( operationsElement );
442 QDomElement operationElement = doc.createElement( QStringLiteral(
"Operation" ) );
443 const QDomText queryText = doc.createTextNode(
"Query" );
444 operationElement.appendChild( queryText );
445 operationsElement.appendChild( operationElement );
462 #ifdef HAVE_SERVER_PYTHON_PLUGINS
468 QDomElement layerElem = doc.createElement( QStringLiteral(
"FeatureType" ) );
471 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
472 const QDomText nameText = doc.createTextNode(
layerTypeName( layer ) );
473 nameElem.appendChild( nameText );
474 layerElem.appendChild( nameElem );
477 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
478 QString title = layer->
title();
479 if ( title.isEmpty() )
481 title = layer->
name();
483 const QDomText titleText = doc.createTextNode( title );
484 titleElem.appendChild( titleText );
485 layerElem.appendChild( titleElem );
488 const QString
abstract = layer->
abstract();
489 if ( !
abstract.isEmpty() )
491 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
492 const QDomText abstractText = doc.createTextNode(
abstract );
493 abstractElem.appendChild( abstractText );
494 layerElem.appendChild( abstractElem );
499 if ( !keywords.isEmpty() )
501 QDomElement keywordsElem = doc.createElement( QStringLiteral(
"ows:Keywords" ) );
502 for (
const QString &keyword : keywords.split(
',' ) )
504 if ( !keyword.trimmed().isEmpty() )
506 QDomElement keywordElem = doc.createElement( QStringLiteral(
"ows:Keyword" ) );
507 const QDomText keywordText = doc.createTextNode( keyword.trimmed() );
508 keywordElem.appendChild( keywordText );
509 keywordsElem.appendChild( keywordElem );
512 layerElem.appendChild( keywordsElem );
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 );
524 for (
const QString &
crs : outputCrsList )
526 if (
crs == defaultSrs )
528 QDomElement otherSrsElem = doc.createElement( QStringLiteral(
"OtherSRS" ) );
529 const QDomText otherSrsText = doc.createTextNode(
crs );
530 otherSrsElem.appendChild( otherSrsText );
531 layerElem.appendChild( otherSrsElem );
535 QDomElement operationsElement = doc.createElement( QStringLiteral(
"Operations" ) );
537 QDomElement operationElement = doc.createElement( QStringLiteral(
"Operation" ) );
538 const QDomText queryText = doc.createTextNode( QStringLiteral(
"Query" ) );
539 operationElement.appendChild( queryText );
540 operationsElement.appendChild( operationElement );
542 if ( wfstUpdateLayersId.contains( layer->
id() ) ||
543 wfstInsertLayersId.contains( layer->
id() ) ||
544 wfstDeleteLayersId.contains( layer->
id() ) )
551 QDomElement operationElement = doc.createElement( QStringLiteral(
"Operation" ) );
552 const QDomText insertText = doc.createTextNode( QStringLiteral(
"Insert" ) );
553 operationElement.appendChild( insertText );
554 operationsElement.appendChild( operationElement );
559 wfstUpdateLayersId.contains( layer->
id() ) )
562 QDomElement operationElement = doc.createElement( QStringLiteral(
"Operation" ) );
563 const QDomText updateText = doc.createTextNode( QStringLiteral(
"Update" ) );
564 operationElement.appendChild( updateText );
565 operationsElement.appendChild( operationElement );
571 QDomElement operationElement = doc.createElement( QStringLiteral(
"Operation" ) );
572 const QDomText deleteText = doc.createTextNode( QStringLiteral(
"Delete" ) );
573 operationElement.appendChild( deleteText );
574 operationsElement.appendChild( operationElement );
578 layerElem.appendChild( operationsElement );
584 const int wgs84precision = 6;
586 if ( !layerExtent.
isNull() )
591 wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
600 QDomElement bBoxElement = doc.createElement( QStringLiteral(
"ows:WGS84BoundingBox" ) );
601 bBoxElement.setAttribute( QStringLiteral(
"dimensions" ), QStringLiteral(
"2" ) );
602 QDomElement lCornerElement = doc.createElement( QStringLiteral(
"ows:LowerCorner" ) );
604 lCornerElement.appendChild( lCornerText );
605 bBoxElement.appendChild( lCornerElement );
606 QDomElement uCornerElement = doc.createElement( QStringLiteral(
"ows:UpperCorner" ) );
608 uCornerElement.appendChild( uCornerText );
609 bBoxElement.appendChild( uCornerElement );
610 layerElem.appendChild( bBoxElement );
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 );
626 featureTypeListElement.appendChild( layerElem );
629 return featureTypeListElement;