From 27a9053490c7f0246f1469534f76fba994f7c57b Mon Sep 17 00:00:00 2001 From: rldhont Date: Thu, 20 Apr 2017 15:15:56 +0200 Subject: [PATCH] [Server] WMS GetCapabilities refactoring - Part 1 Part 1 for removing QgsWMSProjectParser from GetCapabilities --- src/server/qgsserverprojectutils.cpp | 52 ++ src/server/qgsserverprojectutils.h | 54 ++ .../services/wms/qgswmsgetcapabilities.cpp | 543 ++++++++++++++++-- .../services/wms/qgswmsgetcapabilities.h | 26 + .../testdata/qgis_server/getcapabilities.txt | 3 - .../qgis_server/getcapabilities_inspire.txt | 2 - .../qgis_server/getprojectsettings.txt | 3 - 7 files changed, 615 insertions(+), 68 deletions(-) diff --git a/src/server/qgsserverprojectutils.cpp b/src/server/qgsserverprojectutils.cpp index d56d25f9084..6ddbfb91667 100644 --- a/src/server/qgsserverprojectutils.cpp +++ b/src/server/qgsserverprojectutils.cpp @@ -87,6 +87,58 @@ int QgsServerProjectUtils::wmsMaxHeight( const QgsProject &project ) return project.readNumEntry( QStringLiteral( "WMSMaxHeight" ), QStringLiteral( "/" ), -1 ); } +bool QgsServerProjectUtils::wmsUseLayerIds( const QgsProject &project ) +{ + return project.readBoolEntry( QStringLiteral( "WMSUseLayerIDs" ), QStringLiteral( "/" ) ); +} + +bool QgsServerProjectUtils::wmsInfoFormatSIA2045( const QgsProject &project ) +{ + QString sia2045 = project.readEntry( QStringLiteral( "WMSInfoFormatSIA2045" ), QStringLiteral( "/" ), "" ); + + if ( sia2045.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0 + || sia2045.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 ) + { + return true; + } + return false; +} + +bool QgsServerProjectUtils::wmsInspireActivated( const QgsProject &project ) +{ + return project.readBoolEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/activated" ) ); +} + +QString QgsServerProjectUtils::wmsInspireLanguage( const QgsProject &project ) +{ + return project.readEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/language" ) ); +} + +QString QgsServerProjectUtils::wmsInspireMetadataUrl( const QgsProject &project ) +{ + return project.readEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/metadataUrl" ) ); +} + +QString QgsServerProjectUtils::wmsInspireMetadataUrlType( const QgsProject &project ) +{ + return project.readEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/metadataUrlType" ) ); +} + +QString QgsServerProjectUtils::wmsInspireTemporalReference( const QgsProject &project ) +{ + return project.readEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/temporalReference" ) ); +} + +QString QgsServerProjectUtils::wmsInspireMetadataDate( const QgsProject &project ) +{ + return project.readEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/metadataDate" ) ); +} + +QStringList QgsServerProjectUtils::wmsRestrictedComposers( const QgsProject &project ) +{ + return project.readListEntry( QStringLiteral( "WMSRestrictedComposers" ), QStringLiteral( "/" ), QStringList() ); +} + QString QgsServerProjectUtils::wmsServiceUrl( const QgsProject &project ) { return project.readEntry( QStringLiteral( "WMSUrl" ), QStringLiteral( "/" ), "" ); diff --git a/src/server/qgsserverprojectutils.h b/src/server/qgsserverprojectutils.h index 266b97908c1..3fc785336b1 100644 --- a/src/server/qgsserverprojectutils.h +++ b/src/server/qgsserverprojectutils.h @@ -113,6 +113,60 @@ namespace QgsServerProjectUtils */ SERVER_EXPORT int wmsMaxHeight( const QgsProject &project ); + /** Returns if layer ids are used as name in WMS. + * \param project the QGIS project + * \returns if layer ids are used as name. + */ + SERVER_EXPORT bool wmsUseLayerIds( const QgsProject &project ); + + /** Returns if the info format is SIA20145. + * \param project the QGIS project + * \returns if the info format is SIA20145. + */ + SERVER_EXPORT bool wmsInfoFormatSIA2045( const QgsProject &project ); + + /** Returns if Inspire is activated. + * \param project the QGIS project + * \returns if Inspire is activated. + */ + SERVER_EXPORT bool wmsInspireActivated( const QgsProject &project ); + + /** Returns the Inspire language. + * \param project the QGIS project + * \returns the Inspire language if defined in project. + */ + SERVER_EXPORT QString wmsInspireLanguage( const QgsProject &project ); + + /** Returns the Inspire metadata URL. + * \param project the QGIS project + * \returns the Inspire metadata URL if defined in project. + */ + SERVER_EXPORT QString wmsInspireMetadataUrl( const QgsProject &project ); + + /** Returns the Inspire metadata URL type. + * \param project the QGIS project + * \returns the Inspire metadata URL type if defined in project. + */ + SERVER_EXPORT QString wmsInspireMetadataUrlType( const QgsProject &project ); + + /** Returns the Inspire temporal reference. + * \param project the QGIS project + * \returns the Inspire temporal reference if defined in project. + */ + SERVER_EXPORT QString wmsInspireTemporalReference( const QgsProject &project ); + + /** Returns the Inspire metadata date. + * \param project the QGIS project + * \returns the Inspire metadata date if defined in project. + */ + SERVER_EXPORT QString wmsInspireMetadataDate( const QgsProject &project ); + + /** Returns the restricted composer list. + * \param project the QGIS project + * \returns the restricted composer list if defined in project. + */ + SERVER_EXPORT QStringList wmsRestrictedComposers( const QgsProject &project ); + /** Returns the WMS service url defined in a QGIS project. * \param project the QGIS project * \returns url if defined in project, an empty string otherwise. diff --git a/src/server/services/wms/qgswmsgetcapabilities.cpp b/src/server/services/wms/qgswmsgetcapabilities.cpp index a774d86e52a..005f5e928a0 100644 --- a/src/server/services/wms/qgswmsgetcapabilities.cpp +++ b/src/server/services/wms/qgswmsgetcapabilities.cpp @@ -22,6 +22,14 @@ #include "qgswmsgetcapabilities.h" #include "qgsserverprojectutils.h" +#include "qgslayoutmanager.h" +#include "qgscomposition.h" +#include "qgscomposermap.h" +#include "qgscomposerlabel.h" +#include "qgscomposerhtml.h" +#include "qgscomposerframe.h" + + namespace QgsWms { void writeGetCapabilities( QgsServerInterface *serverIface, const QgsProject *project, @@ -120,7 +128,7 @@ namespace QgsWms schemaLocation += QLatin1String( " http://www.opengis.net/sld" ); schemaLocation += QLatin1String( " http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd" ); schemaLocation += QLatin1String( " http://www.qgis.org/wms" ); - if ( configParser && configParser->wmsInspireActivated() ) + if ( QgsServerProjectUtils::wmsInspireActivated( *project ) ) { wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:inspire_common" ), QStringLiteral( "http://inspire.ec.europa.eu/schemas/common/1.0" ) ); wmsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:inspire_vs" ), QStringLiteral( "http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" ) ); @@ -134,49 +142,272 @@ namespace QgsWms wmsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), version ); doc.appendChild( wmsCapabilitiesElement ); - configParser->serviceCapabilities( wmsCapabilitiesElement, doc ); + //INSERT Service + wmsCapabilitiesElement.appendChild( getServiceElement( doc, project, version ) ); //wms:Capability element - QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wms:Capability*/ ); + QDomElement capabilityElement = getCapabilityElement( doc, project, version, request, projectSettings ); wmsCapabilitiesElement.appendChild( capabilityElement ); - //wms:Request element - QDomElement requestElement = doc.createElement( QStringLiteral( "Request" )/*wms:Request*/ ); - capabilityElement.appendChild( requestElement ); - QDomElement dcpTypeElement = doc.createElement( QStringLiteral( "DCPType" )/*wms:DCPType*/ ); - QDomElement httpElement = doc.createElement( QStringLiteral( "HTTP" )/*wms:HTTP*/ ); - dcpTypeElement.appendChild( httpElement ); + if ( projectSettings ) + { + //Insert elements derived from wms:_ExtendedCapabilities + capabilityElement.appendChild( getComposerTemplatesElement( doc, project ) ); + + //WFS layers + capabilityElement.appendChild( getWFSLayersElement( doc, project ) ); + } + + //add the xml content for the individual layers/styles + QString wmsServiceUrl = QgsServerProjectUtils::wmsServiceUrl( *project ); + configParser->layersAndStylesCapabilities( capabilityElement, doc, version, + wmsServiceUrl, projectSettings ); + + return doc; + } + + QDomElement getServiceElement( QDomDocument &doc, const QgsProject *project, const QString &version ) + { + bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSIA2045( *project ); + + //Service element + QDomElement serviceElem = doc.createElement( QStringLiteral( "Service" ) ); + + //Service name + QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) ); + QDomText nameText = doc.createTextNode( QStringLiteral( "WMS" ) ); + nameElem.appendChild( nameText ); + serviceElem.appendChild( nameElem ); + + QString title = QgsServerProjectUtils::owsServiceTitle( *project ); + if ( !title.isEmpty() ) + { + QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) ); + QDomText titleText = doc.createTextNode( title ); + titleElem.appendChild( titleText ); + serviceElem.appendChild( titleElem ); + } + + QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project ); + if ( !abstract.isEmpty() ) + { + QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) ); + QDomText abstractText = doc.createCDATASection( abstract ); + abstractElem.appendChild( abstractText ); + serviceElem.appendChild( abstractElem ); + } + + QDomElement keywordsElem = doc.createElement( QStringLiteral( "KeywordList" ) ); + //add default keyword + QDomElement keywordElem = doc.createElement( QStringLiteral( "Keyword" ) ); + keywordElem.setAttribute( QStringLiteral( "vocabulary" ), QStringLiteral( "ISO" ) ); + QDomText keywordText = doc.createTextNode( QStringLiteral( "infoMapAccessService" ) ); + keywordElem.appendChild( keywordText ); + keywordsElem.appendChild( keywordElem ); + serviceElem.appendChild( keywordsElem ); + QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project ); + if ( !keywords.isEmpty() ) + { + for ( int i = 0; i < keywords.size(); ++i ) + { + QString keyword = keywords.at( i ); + if ( !keyword.isEmpty() ) + { + keywordElem = doc.createElement( QStringLiteral( "Keyword" ) ); + keywordText = doc.createTextNode( keyword ); + keywordElem.appendChild( keywordText ); + if ( sia2045 ) + { + keywordElem.setAttribute( QStringLiteral( "vocabulary" ), QStringLiteral( "SIA_Geo405" ) ); + } + keywordsElem.appendChild( keywordElem ); + } + } + serviceElem.appendChild( keywordsElem ); + } + + QString onlineResource = QgsServerProjectUtils::owsServiceOnlineResource( *project ); + if ( !onlineResource.isEmpty() ) + { + QDomElement onlineResourceElem = doc.createElement( QStringLiteral( "OnlineResource" ) ); + onlineResourceElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); + onlineResourceElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); + onlineResourceElem.setAttribute( QStringLiteral( "xlink:href" ), onlineResource ); + serviceElem.appendChild( onlineResourceElem ); + } + + QString contactPerson = QgsServerProjectUtils::owsServiceContactPerson( *project ); + QString contactOrganization = QgsServerProjectUtils::owsServiceContactOrganization( *project ); + QString contactPosition = QgsServerProjectUtils::owsServiceContactPosition( *project ); + QString contactMail = QgsServerProjectUtils::owsServiceContactMail( *project ); + QString contactPhone = QgsServerProjectUtils::owsServiceContactPhone( *project ); + if ( !contactPerson.isEmpty() || + !contactOrganization.isEmpty() || + !contactPosition.isEmpty() || + !contactMail.isEmpty() || + !contactPhone.isEmpty() ) + { + //Contact information + QDomElement contactInfoElem = doc.createElement( QStringLiteral( "ContactInformation" ) ); + + //Contact person primary + if ( !contactPerson.isEmpty() || + !contactOrganization.isEmpty() || + !contactPosition.isEmpty() ) + { + QDomElement contactPersonPrimaryElem = doc.createElement( QStringLiteral( "ContactPersonPrimary" ) ); + + if ( !contactPerson.isEmpty() ) + { + QDomElement contactPersonElem = doc.createElement( QStringLiteral( "ContactPerson" ) ); + QDomText contactPersonText = doc.createTextNode( contactPerson ); + contactPersonElem.appendChild( contactPersonText ); + contactPersonPrimaryElem.appendChild( contactPersonElem ); + } + + if ( !contactOrganization.isEmpty() ) + { + QDomElement contactOrganizationElem = doc.createElement( QStringLiteral( "ContactOrganization" ) ); + QDomText contactOrganizationText = doc.createTextNode( contactOrganization ); + contactOrganizationElem.appendChild( contactOrganizationText ); + contactPersonPrimaryElem.appendChild( contactOrganizationElem ); + } + + if ( !contactPosition.isEmpty() ) + { + QDomElement contactPositionElem = doc.createElement( QStringLiteral( "ContactPosition" ) ); + QDomText contactPositionText = doc.createTextNode( contactPosition ); + contactPositionElem.appendChild( contactPositionText ); + contactPersonPrimaryElem.appendChild( contactPositionElem ); + } + + contactInfoElem.appendChild( contactPersonPrimaryElem ); + } + + if ( !contactPhone.isEmpty() ) + { + QDomElement phoneElem = doc.createElement( QStringLiteral( "ContactVoiceTelephone" ) ); + QDomText phoneText = doc.createTextNode( contactPhone ); + phoneElem.appendChild( phoneText ); + contactInfoElem.appendChild( phoneElem ); + } + + if ( !contactMail.isEmpty() ) + { + QDomElement mailElem = doc.createElement( QStringLiteral( "ContactElectronicMailAddress" ) ); + QDomText mailText = doc.createTextNode( contactMail ); + mailElem.appendChild( mailText ); + contactInfoElem.appendChild( mailElem ); + } + + serviceElem.appendChild( contactInfoElem ); + } + + QDomElement feesElem = doc.createElement( QStringLiteral( "Fees" ) ); + QDomText feesText = doc.createTextNode( QStringLiteral( "None" ) ); // default value if fees are unknown + QString fees = QgsServerProjectUtils::owsServiceFees( *project ); + if ( !fees.isEmpty() ) + { + feesText = doc.createTextNode( fees ); + } + feesElem.appendChild( feesText ); + serviceElem.appendChild( feesElem ); + + QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( "AccessConstraints" ) ); + QDomText accessConstraintsText = doc.createTextNode( QStringLiteral( "None" ) ); // default value if access constraints are unknown + QString accessConstraints = QgsServerProjectUtils::owsServiceAccessConstraints( *project ); + if ( !accessConstraints.isEmpty() ) + { + accessConstraintsText = doc.createTextNode( accessConstraints ); + } + accessConstraintsElem.appendChild( accessConstraintsText ); + serviceElem.appendChild( accessConstraintsElem ); + + if ( version == QLatin1String( "1.3.0" ) ) + { + int maxWidth = QgsServerProjectUtils::wmsMaxWidth( *project ); + if ( maxWidth > 0 ) + { + QDomElement maxWidthElem = doc.createElement( QStringLiteral( "MaxWidth" ) ); + QDomText maxWidthText = doc.createTextNode( QString::number( maxWidth ) ); + maxWidthElem.appendChild( maxWidthText ); + serviceElem.appendChild( maxWidthElem ); + } + + int maxHeight = QgsServerProjectUtils::wmsMaxHeight( *project ); + if ( maxHeight > 0 ) + { + QDomElement maxHeightElem = doc.createElement( QStringLiteral( "MaxHeight" ) ); + QDomText maxHeightText = doc.createTextNode( QString::number( maxHeight ) ); + maxHeightElem.appendChild( maxHeightText ); + serviceElem.appendChild( maxHeightElem ); + } + } + + return serviceElem; + } + + QDomElement getCapabilityElement( QDomDocument &doc, const QgsProject *project, + const QString &version, const QgsServerRequest &request, + bool projectSettings ) + { + QgsServerRequest::Parameters parameters = request.parameters(); + + // Get service URL + QUrl href = serviceUrl( request, project ); + + //href needs to be a prefix + QString hrefString = href.toString( QUrl::FullyDecoded ); + hrefString.append( href.hasQuery() ? "&" : "?" ); + + QDomElement capabilityElem = doc.createElement( QStringLiteral( "Capability" )/*wms:Capability*/ ); + + //wms:Request element + QDomElement requestElem = doc.createElement( QStringLiteral( "Request" )/*wms:Request*/ ); + capabilityElem.appendChild( requestElem ); + + QDomElement dcpTypeElem = doc.createElement( QStringLiteral( "DCPType" )/*wms:DCPType*/ ); + QDomElement httpElem = doc.createElement( QStringLiteral( "HTTP" )/*wms:HTTP*/ ); + dcpTypeElem.appendChild( httpElem ); + + // Append format helper + std::function < void ( QDomElement &, const QString & ) > appendFormat = [&doc]( QDomElement & elem, const QString & format ) + { + QDomElement formatElem = doc.createElement( QStringLiteral( "Format" )/*wms:Format*/ ); + formatElem.appendChild( doc.createTextNode( format ) ); + elem.appendChild( formatElem ); + }; QDomElement elem; //wms:GetCapabilities elem = doc.createElement( QStringLiteral( "GetCapabilities" )/*wms:GetCapabilities*/ ); appendFormat( elem, ( version == QLatin1String( "1.1.1" ) ? "application/vnd.ogc.wms_xml" : "text/xml" ) ); - elem.appendChild( dcpTypeElement ); - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem ); + requestElem.appendChild( elem ); // SOAP platform //only give this information if it is not a WMS request to be in sync with the WMS capabilities schema // XXX Not even sure that cam be ever true if ( parameters.value( QStringLiteral( "SERVICE" ) ).compare( QLatin1String( "WMS" ), Qt::CaseInsensitive ) != 0 ) { - QDomElement soapElement = doc.createElement( QStringLiteral( "SOAP" )/*wms:SOAP*/ ); - httpElement.appendChild( soapElement ); - QDomElement soapResourceElement = doc.createElement( QStringLiteral( "OnlineResource" )/*wms:OnlineResource*/ ); - soapResourceElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); - soapResourceElement.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); - soapResourceElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString ); - soapElement.appendChild( soapResourceElement ); + QDomElement soapElem = doc.createElement( QStringLiteral( "SOAP" )/*wms:SOAP*/ ); + httpElem.appendChild( soapElem ); + QDomElement soapResourceElem = doc.createElement( QStringLiteral( "OnlineResource" )/*wms:OnlineResource*/ ); + soapResourceElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); + soapResourceElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); + soapResourceElem.setAttribute( QStringLiteral( "xlink:href" ), hrefString ); + soapElem.appendChild( soapResourceElem ); } //only Get supported for the moment - QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wms:Get*/ ); - httpElement.appendChild( getElement ); - QDomElement olResourceElement = doc.createElement( QStringLiteral( "OnlineResource" )/*wms:OnlineResource*/ ); - olResourceElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); - olResourceElement.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); - olResourceElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString ); - getElement.appendChild( olResourceElement ); + QDomElement getElem = doc.createElement( QStringLiteral( "Get" )/*wms:Get*/ ); + httpElem.appendChild( getElem ); + QDomElement olResourceElem = doc.createElement( QStringLiteral( "OnlineResource" )/*wms:OnlineResource*/ ); + olResourceElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) ); + olResourceElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) ); + olResourceElem.setAttribute( QStringLiteral( "xlink:href" ), hrefString ); + getElem.appendChild( olResourceElem ); //wms:GetMap elem = doc.createElement( QStringLiteral( "GetMap" )/*wms:GetMap*/ ); @@ -186,8 +417,8 @@ namespace QgsWms appendFormat( elem, QStringLiteral( "image/png; mode=8bit" ) ); appendFormat( elem, QStringLiteral( "image/png; mode=1bit" ) ); appendFormat( elem, QStringLiteral( "application/dxf" ) ); - elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' + requestElem.appendChild( elem ); //wms:GetFeatureInfo elem = doc.createElement( QStringLiteral( "GetFeatureInfo" ) ); @@ -196,27 +427,27 @@ namespace QgsWms appendFormat( elem, QStringLiteral( "text/xml" ) ); appendFormat( elem, QStringLiteral( "application/vnd.ogc.gml" ) ); appendFormat( elem, QStringLiteral( "application/vnd.ogc.gml/3.1.1" ) ); - elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' + requestElem.appendChild( elem ); //wms:GetLegendGraphic elem = doc.createElement( ( version == QLatin1String( "1.1.1" ) ? "GetLegendGraphic" : "sld:GetLegendGraphic" )/*wms:GetLegendGraphic*/ ); appendFormat( elem, QStringLiteral( "image/jpeg" ) ); appendFormat( elem, QStringLiteral( "image/png" ) ); - elem.appendChild( dcpTypeElement.cloneNode().toElement() ); // this is the same as for 'GetCapabilities' - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' + requestElem.appendChild( elem ); //wms:DescribeLayer elem = doc.createElement( ( version == QLatin1String( "1.1.1" ) ? "DescribeLayer" : "sld:DescribeLayer" )/*wms:GetLegendGraphic*/ ); appendFormat( elem, QStringLiteral( "text/xml" ) ); - elem.appendChild( dcpTypeElement.cloneNode().toElement() ); // this is the same as for 'GetCapabilities' - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' + requestElem.appendChild( elem ); //wms:GetStyles elem = doc.createElement( ( version == QLatin1String( "1.1.1" ) ? "GetStyles" : "qgs:GetStyles" )/*wms:GetStyles*/ ); appendFormat( elem, QStringLiteral( "text/xml" ) ); - elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' + requestElem.appendChild( elem ); if ( projectSettings ) //remove composer templates from GetCapabilities in the long term { @@ -225,14 +456,14 @@ namespace QgsWms appendFormat( elem, QStringLiteral( "svg" ) ); appendFormat( elem, QStringLiteral( "png" ) ); appendFormat( elem, QStringLiteral( "pdf" ) ); - elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' - requestElement.appendChild( elem ); + elem.appendChild( dcpTypeElem.cloneNode().toElement() ); //this is the same as for 'GetCapabilities' + requestElem.appendChild( elem ); } //Exception element is mandatory elem = doc.createElement( QStringLiteral( "Exception" ) ); appendFormat( elem, ( version == QLatin1String( "1.1.1" ) ? "application/vnd.ogc.se_xml" : "XML" ) ); - capabilityElement.appendChild( elem ); + capabilityElem.appendChild( elem ); //UserDefinedSymbolization element if ( version == QLatin1String( "1.3.0" ) ) @@ -244,40 +475,232 @@ namespace QgsWms elem.setAttribute( QStringLiteral( "RemoteWFS" ), QStringLiteral( "0" ) ); elem.setAttribute( QStringLiteral( "InlineFeature" ), QStringLiteral( "0" ) ); elem.setAttribute( QStringLiteral( "RemoteWCS" ), QStringLiteral( "0" ) ); - capabilityElement.appendChild( elem ); + capabilityElem.appendChild( elem ); - if ( configParser->wmsInspireActivated() ) + if ( QgsServerProjectUtils::wmsInspireActivated( *project ) ) { - configParser->inspireCapabilities( capabilityElement, doc ); + capabilityElem.appendChild( getInspireCapabilitiesElement( doc, project ) ); } } - if ( projectSettings ) + return capabilityElem; + } + + QDomElement getInspireCapabilitiesElement( QDomDocument &doc, const QgsProject *project ) + { + QDomElement inspireCapabilitiesElem; + + if ( !QgsServerProjectUtils::wmsInspireActivated( *project ) ) + return inspireCapabilitiesElem; + + inspireCapabilitiesElem = doc.createElement( QStringLiteral( "inspire_vs:ExtendedCapabilities" ) ); + + QString inspireMetadataUrl = QgsServerProjectUtils::wmsInspireMetadataUrl( *project ); + // inspire scenario 1 + if ( !inspireMetadataUrl.isEmpty() ) { - //Insert elements derived from wms:_ExtendedCapabilities - configParser->printCapabilities( capabilityElement, doc ); + QDomElement inspireCommonMetadataUrlElem = doc.createElement( QStringLiteral( "inspire_common:MetadataUrl" ) ); + inspireCommonMetadataUrlElem.setAttribute( QStringLiteral( "xsi:type" ), QStringLiteral( "inspire_common:resourceLocatorType" ) ); - //WFS layers - QStringList wfsLayers = configParser->wfsLayerNames(); - if ( !wfsLayers.isEmpty() ) + QDomElement inspireCommonMetadataUrlUrlElem = doc.createElement( QStringLiteral( "inspire_common:URL" ) ); + inspireCommonMetadataUrlUrlElem.appendChild( doc.createTextNode( inspireMetadataUrl ) ); + inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlUrlElem ); + + QString inspireMetadataUrlType = QgsServerProjectUtils::wmsInspireMetadataUrlType( *project ); + if ( !inspireMetadataUrlType.isNull() ) { - QDomElement wfsLayersElem = doc.createElement( QStringLiteral( "WFSLayers" ) ); - for ( auto wfsIt = wfsLayers.constBegin() ; wfsIt != wfsLayers.constEnd(); ++wfsIt ) - { - QDomElement wfsLayerElem = doc.createElement( QStringLiteral( "WFSLayer" ) ); - wfsLayerElem.setAttribute( QStringLiteral( "name" ), *wfsIt ); - wfsLayersElem.appendChild( wfsLayerElem ); - } - capabilityElement.appendChild( wfsLayersElem ); + QDomElement inspireCommonMetadataUrlMediaTypeElem = doc.createElement( QStringLiteral( "inspire_common:MediaType" ) ); + inspireCommonMetadataUrlMediaTypeElem.appendChild( doc.createTextNode( inspireMetadataUrlType ) ); + inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlMediaTypeElem ); + } + + inspireCapabilitiesElem.appendChild( inspireCommonMetadataUrlElem ); + } + else + { + QDomElement inspireCommonResourceTypeElem = doc.createElement( QStringLiteral( "inspire_common:ResourceType" ) ); + inspireCommonResourceTypeElem.appendChild( doc.createTextNode( QStringLiteral( "service" ) ) ); + inspireCapabilitiesElem.appendChild( inspireCommonResourceTypeElem ); + + QDomElement inspireCommonSpatialDataServiceTypeElem = doc.createElement( QStringLiteral( "inspire_common:SpatialDataServiceType" ) ); + inspireCommonSpatialDataServiceTypeElem.appendChild( doc.createTextNode( QStringLiteral( "view" ) ) ); + inspireCapabilitiesElem.appendChild( inspireCommonSpatialDataServiceTypeElem ); + + QString inspireTemporalReference = QgsServerProjectUtils::wmsInspireTemporalReference( *project ); + if ( !inspireTemporalReference.isNull() ) + { + QDomElement inspireCommonTemporalReferenceElem = doc.createElement( QStringLiteral( "inspire_common:TemporalReference" ) ); + QDomElement inspireCommonDateOfLastRevisionElem = doc.createElement( QStringLiteral( "inspire_common:DateOfLastRevision" ) ); + inspireCommonDateOfLastRevisionElem.appendChild( doc.createTextNode( inspireTemporalReference ) ); + inspireCommonTemporalReferenceElem.appendChild( inspireCommonDateOfLastRevisionElem ); + inspireCapabilitiesElem.appendChild( inspireCommonTemporalReferenceElem ); + } + + QDomElement inspireCommonMetadataPointOfContactElem = doc.createElement( QStringLiteral( "inspire_common:MetadataPointOfContact" ) ); + + QString contactOrganization = QgsServerProjectUtils::owsServiceContactOrganization( *project ); + QDomElement inspireCommonOrganisationNameElem = doc.createElement( QStringLiteral( "inspire_common:OrganisationName" ) ); + if ( !contactOrganization.isNull() ) + { + inspireCommonOrganisationNameElem.appendChild( doc.createTextNode( contactOrganization ) ); + } + inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonOrganisationNameElem ); + + QString contactMail = QgsServerProjectUtils::owsServiceContactMail( *project ); + QDomElement inspireCommonEmailAddressElem = doc.createElement( QStringLiteral( "inspire_common:EmailAddress" ) ); + if ( !contactMail.isNull() ) + { + inspireCommonEmailAddressElem.appendChild( doc.createTextNode( contactMail ) ); + } + inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonEmailAddressElem ); + + inspireCapabilitiesElem.appendChild( inspireCommonMetadataPointOfContactElem ); + + QString inspireMetadataDate = QgsServerProjectUtils::wmsInspireMetadataDate( *project ); + if ( !inspireMetadataDate.isNull() ) + { + QDomElement inspireCommonMetadataDateElem = doc.createElement( QStringLiteral( "inspire_common:MetadataDate" ) ); + inspireCommonMetadataDateElem.appendChild( doc.createTextNode( inspireMetadataDate ) ); + inspireCapabilitiesElem.appendChild( inspireCommonMetadataDateElem ); } } - //add the xml content for the individual layers/styles - QString wmsServiceUrl = QgsServerProjectUtils::wmsServiceUrl( *project ); - configParser->layersAndStylesCapabilities( capabilityElement, doc, version, - wmsServiceUrl, projectSettings ); + // Supported languages + QDomElement inspireCommonSupportedLanguagesElem = doc.createElement( QStringLiteral( "inspire_common:SupportedLanguages" ) ); + inspireCommonSupportedLanguagesElem.setAttribute( QStringLiteral( "xsi:type" ), QStringLiteral( "inspire_common:supportedLanguagesType" ) ); - return doc; + QDomElement inspireCommonLanguageElem = doc.createElement( QStringLiteral( "inspire_common:Language" ) ); + inspireCommonLanguageElem.appendChild( doc.createTextNode( QgsServerProjectUtils::wmsInspireLanguage( *project ) ) ); + + QDomElement inspireCommonDefaultLanguageElem = doc.createElement( QStringLiteral( "inspire_common:DefaultLanguage" ) ); + inspireCommonDefaultLanguageElem.appendChild( inspireCommonLanguageElem ); + inspireCommonSupportedLanguagesElem.appendChild( inspireCommonDefaultLanguageElem ); + +#if 0 + /* Supported language has to be different from default one */ + QDomElement inspireCommonSupportedLanguageElem = doc.createElement( "inspire_common:SupportedLanguage" ); + inspireCommonSupportedLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() ); + inspireCommonSupportedLanguagesElem.appendChild( inspireCommonSupportedLanguageElem ); +#endif + + inspireCapabilitiesElem.appendChild( inspireCommonSupportedLanguagesElem ); + + QDomElement inspireCommonResponseLanguageElem = doc.createElement( QStringLiteral( "inspire_common:ResponseLanguage" ) ); + inspireCommonResponseLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() ); + inspireCapabilitiesElem.appendChild( inspireCommonResponseLanguageElem ); + + return inspireCapabilitiesElem; + } + + QDomElement getComposerTemplatesElement( QDomDocument &doc, const QgsProject *project ) + { + QList projectComposers = project->layoutManager()->compositions(); + if ( projectComposers.size() == 0 ) + return QDomElement(); + + QStringList restrictedComposers = QgsServerProjectUtils::wmsRestrictedComposers( *project ); + + QDomElement composerTemplatesElem = doc.createElement( QStringLiteral( "ComposerTemplates" ) ); + QList::const_iterator cIt = projectComposers.constBegin(); + for ( ; cIt != projectComposers.constEnd(); ++cIt ) + { + QgsComposition *composer = *cIt; + if ( restrictedComposers.contains( composer->name() ) ) + continue; + + QDomElement composerTemplateElem = doc.createElement( QStringLiteral( "ComposerTemplate" ) ); + composerTemplateElem.setAttribute( QStringLiteral( "name" ), composer->name() ); + + //get paper width and hight in mm from composition + composerTemplateElem.setAttribute( QStringLiteral( "width" ), composer->paperWidth() ); + composerTemplateElem.setAttribute( QStringLiteral( "height" ), composer->paperHeight() ); + + //add available composer maps and their size in mm + QList composerMapList = composer->composerMapItems(); + QList::const_iterator cmIt = composerMapList.constBegin(); + for ( ; cmIt != composerMapList.constEnd(); ++cmIt ) + { + const QgsComposerMap *composerMap = *cmIt; + + QDomElement composerMapElem = doc.createElement( QStringLiteral( "ComposerMap" ) ); + composerMapElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "map%s" ).arg( composerMap->id() ) ); + composerMapElem.setAttribute( QStringLiteral( "width" ), composerMap->rect().width() ); + composerMapElem.setAttribute( QStringLiteral( "height" ), composerMap->rect().height() ); + composerTemplateElem.appendChild( composerMapElem ); + } + + //add available composer labels + QList composerLabelList; + composer->composerItems( composerLabelList ); + QList::const_iterator clIt = composerLabelList.constBegin(); + for ( ; clIt != composerLabelList.constEnd(); ++clIt ) + { + QgsComposerLabel *composerLabel = *clIt; + QString id = composerLabel->id(); + if ( id.isEmpty() ) + continue; + + QDomElement composerLabelElem = doc.createElement( QStringLiteral( "ComposerLabel" ) ); + composerLabelElem.setAttribute( QStringLiteral( "name" ), id ); + composerTemplateElem.appendChild( composerLabelElem ); + } + + //add available composer HTML + QList composerHtmlList; + composer->composerItems( composerHtmlList ); + QList::const_iterator chIt = composerHtmlList.constBegin(); + for ( ; chIt != composerHtmlList.constEnd(); ++chIt ) + { + QgsComposerHtml *composerHtml = *chIt; + if ( composerHtml->frameCount() == 0 ) + continue; + + QString id = composerHtml->frame( 0 )->id(); + if ( id.isEmpty() ) + continue; + + QDomElement composerHtmlElem = doc.createElement( QStringLiteral( "ComposerHtml" ) ); + composerHtmlElem.setAttribute( QStringLiteral( "name" ), id ); + composerTemplateElem.appendChild( composerHtmlElem ); + } + + composerTemplatesElem.appendChild( composerTemplateElem ); + } + + if ( composerTemplatesElem.childNodes().size() == 0 ) + return QDomElement(); + + return composerTemplatesElem; + } + + QDomElement getWFSLayersElement( QDomDocument &doc, const QgsProject *project ) + { + QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project ); + if ( wfsLayerIds.size() == 0 ) + return QDomElement(); + + QDomElement wfsLayersElem = doc.createElement( QStringLiteral( "WFSLayers" ) ); + for ( int i = 0; i < wfsLayerIds.size(); ++i ) + { + QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) ); + if ( layer->type() != QgsMapLayer::LayerType::VectorLayer ) + { + continue; + } + + QDomElement wfsLayerElem = doc.createElement( QStringLiteral( "WFSLayer" ) ); + if ( QgsServerProjectUtils::wmsUseLayerIds( *project ) ) + { + wfsLayerElem.setAttribute( QStringLiteral( "name" ), layer->id() ); + } + else + { + wfsLayerElem.setAttribute( QStringLiteral( "name" ), layer->name() ); + } + wfsLayersElem.appendChild( wfsLayerElem ); + } + + return wfsLayersElem; } } // namespace QgsWms diff --git a/src/server/services/wms/qgswmsgetcapabilities.h b/src/server/services/wms/qgswmsgetcapabilities.h index 6cda859c115..5c32146e516 100644 --- a/src/server/services/wms/qgswmsgetcapabilities.h +++ b/src/server/services/wms/qgswmsgetcapabilities.h @@ -24,6 +24,32 @@ namespace QgsWms { + /** + * Create WFSLayers element for get capabilities document + */ + QDomElement getWFSLayersElement( QDomDocument &doc, const QgsProject *project ); + + /** + * Create ComposerTemplates element for get capabilities document + */ + QDomElement getComposerTemplatesElement( QDomDocument &doc, const QgsProject *project ); + + /** + * Create InspireCapabilities element for get capabilities document + */ + QDomElement getInspireCapabilitiesElement( QDomDocument &doc, const QgsProject *project ); + + /** + * Create Capability element for get capabilities document + */ + QDomElement getCapabilityElement( QDomDocument &doc, const QgsProject *project, const QString &version, + const QgsServerRequest &request, bool projectSettings ); + + /** + * Create Service element for get capabilities document + */ + QDomElement getServiceElement( QDomDocument &doc, const QgsProject *project, const QString &version ); + /** Output GetCapabilities response */ void writeGetCapabilities( QgsServerInterface *serverIface, const QgsProject *project, diff --git a/tests/testdata/qgis_server/getcapabilities.txt b/tests/testdata/qgis_server/getcapabilities.txt index e0cebb7208f..142f625ade5 100644 --- a/tests/testdata/qgis_server/getcapabilities.txt +++ b/tests/testdata/qgis_server/getcapabilities.txt @@ -10,14 +10,11 @@ Content-Type: text/xml; charset=utf-8 infoMapAccessService - Alessandro Pasotti QGIS dev team - - elpaso@itopen.it conditions unknown diff --git a/tests/testdata/qgis_server/getcapabilities_inspire.txt b/tests/testdata/qgis_server/getcapabilities_inspire.txt index 695abb9e4ce..6c1a976bd37 100644 --- a/tests/testdata/qgis_server/getcapabilities_inspire.txt +++ b/tests/testdata/qgis_server/getcapabilities_inspire.txt @@ -10,14 +10,12 @@ Content-Type: text/xml; charset=utf-8 infoMapAccessService - Alessandro Pasotti QGIS dev team originator - elpaso@itopen.it conditions unknown diff --git a/tests/testdata/qgis_server/getprojectsettings.txt b/tests/testdata/qgis_server/getprojectsettings.txt index 287bfcb7dc9..e4378592d57 100644 --- a/tests/testdata/qgis_server/getprojectsettings.txt +++ b/tests/testdata/qgis_server/getprojectsettings.txt @@ -10,14 +10,11 @@ Content-Type: text/xml; charset=utf-8 infoMapAccessService - Alessandro Pasotti QGIS dev team - - elpaso@itopen.it conditions unknown