[Server] WMS GetContext refactoring

This commit is contained in:
rldhont 2017-05-25 14:55:46 +02:00
parent 95a5ccefab
commit 0f00a5235d

View File

@ -20,9 +20,36 @@
***************************************************************************/
#include "qgswmsutils.h"
#include "qgswmsgetcontext.h"
#include "qgsserverprojectutils.h"
#include "qgslayertreenode.h"
#include "qgslayertreegroup.h"
#include "qgslayertreelayer.h"
#include "qgslayertreemodel.h"
#include "qgslayertree.h"
#include "qgsmaplayerstylemanager.h"
#include "qgscsexception.h"
namespace QgsWms
{
namespace
{
void appendOwsLayerStyles( QDomDocument &doc, QDomElement &layerElem, QgsMapLayer *currentLayer );
void appendOwsLayersFromTreeGroup( QDomDocument &doc,
QDomElement &parentLayer,
QgsServerInterface *serverIface,
const QgsProject *project,
const QgsServerRequest &request,
const QgsLayerTreeGroup *layerTreeGroup,
QgsRectangle &combinedBBox,
const QString &strGroup );
void appendOwsGeneralAndResourceList( QDomDocument &doc, QDomElement &parentElement,
QgsServerInterface *serverIface, const QgsProject *project,
const QgsServerRequest &request );
}
void writeGetContext( QgsServerInterface *serverIface, const QgsProject *project,
const QString &version, const QgsServerRequest &request,
@ -40,7 +67,7 @@ namespace QgsWms
{
Q_UNUSED( version );
QgsWmsConfigParser *configParser = getConfigParser( serverIface );
//QgsWmsConfigParser *configParser = getConfigParser( serverIface );
QDomDocument doc;
QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( QStringLiteral( "xml" ),
@ -64,11 +91,374 @@ namespace QgsWms
owsContextElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "0.3.1" ) );
doc.appendChild( owsContextElem );
QString hrefString = serviceUrl( request, project ).toString( QUrl::FullyDecoded );
configParser->owsGeneralAndResourceList( owsContextElem, doc, hrefString );
appendOwsGeneralAndResourceList( doc, owsContextElem, serverIface, project, request );
return doc;
}
namespace
{
void appendOwsGeneralAndResourceList( QDomDocument &doc, QDomElement &parentElement,
QgsServerInterface *serverIface, const QgsProject *project,
const QgsServerRequest &request )
{
parentElement.setAttribute( QStringLiteral( "id" ), "ows-context-" + project->fileInfo().baseName() );
// OWSContext General element
QDomElement generalElem = doc.createElement( QStringLiteral( "General" ) );
// OWSContext Window element
QDomElement windowElem = doc.createElement( QStringLiteral( "Window" ) );
windowElem.setAttribute( QStringLiteral( "height" ), QStringLiteral( "600" ) );
windowElem.setAttribute( QStringLiteral( "width" ), QStringLiteral( "800" ) );
generalElem.appendChild( windowElem );
//OWS title
//why not use project title ?
QString title = QgsServerProjectUtils::owsServiceTitle( *project );
if ( !title.isEmpty() )
{
QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
QDomText titleText = doc.createTextNode( title );
titleElem.appendChild( titleText );
generalElem.appendChild( titleElem );
}
//OWS abstract
QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project );
if ( !abstract.isEmpty() )
{
QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
QDomText abstractText = doc.createCDATASection( abstract );
abstractElem.appendChild( abstractText );
generalElem.appendChild( abstractElem );
}
//OWS Keywords
QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project );
if ( !keywords.isEmpty() )
{
bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *project );
QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
for ( int i = 0; i < keywords.size(); ++i )
{
QString keyword = keywords.at( i );
if ( !keyword.isEmpty() )
{
QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
QDomText keywordText = doc.createTextNode( keyword );
keywordElem.appendChild( keywordText );
if ( sia2045 )
{
keywordElem.setAttribute( QStringLiteral( "vocabulary" ), QStringLiteral( "SIA_Geo405" ) );
}
keywordsElem.appendChild( keywordElem );
}
}
generalElem.appendChild( keywordsElem );
}
// OWSContext General element is complete
parentElement.appendChild( generalElem );
// OWSContext ResourceList element
QDomElement resourceListElem = doc.createElement( QStringLiteral( "ResourceList" ) );
const QgsLayerTree *projectLayerTreeRoot = project->layerTreeRoot();
QgsRectangle combinedBBox;
appendOwsLayersFromTreeGroup( doc, resourceListElem, serverIface, project, request, projectLayerTreeRoot, combinedBBox, QString() );
parentElement.appendChild( resourceListElem );
// OWSContext BoundingBox
QgsCoordinateReferenceSystem projectCrs = project->crs();
QgsRectangle mapRect = QgsServerProjectUtils::wmsExtent( *project );
if ( mapRect.isEmpty() )
{
mapRect = combinedBBox;
}
QDomElement bboxElem = doc.createElement( QStringLiteral( "ows:BoundingBox" ) );
bboxElem.setAttribute( QStringLiteral( "crs" ), projectCrs.authid() );
if ( projectCrs.hasAxisInverted() )
{
mapRect.invert();
}
QDomElement lowerCornerElem = doc.createElement( QStringLiteral( "ows:LowerCorner" ) );
QDomText lowerCornerText = doc.createTextNode( QString::number( mapRect.xMinimum() ) + " " + QString::number( mapRect.yMinimum() ) );
lowerCornerElem.appendChild( lowerCornerText );
bboxElem.appendChild( lowerCornerElem );
QDomElement upperCornerElem = doc.createElement( QStringLiteral( "ows:UpperCorner" ) );
QDomText upperCornerText = doc.createTextNode( QString::number( mapRect.xMaximum() ) + " " + QString::number( mapRect.yMaximum() ) );
upperCornerElem.appendChild( upperCornerText );
bboxElem.appendChild( upperCornerElem );
generalElem.appendChild( bboxElem );
}
void appendOwsLayersFromTreeGroup( QDomDocument &doc,
QDomElement &parentLayer,
QgsServerInterface *serverIface,
const QgsProject *project,
const QgsServerRequest &request,
const QgsLayerTreeGroup *layerTreeGroup,
QgsRectangle &combinedBBox,
const QString &strGroup )
{
QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
QList< QgsLayerTreeNode * > layerTreeGroupChildren = layerTreeGroup->children();
for ( int i = 0; i < layerTreeGroupChildren.size(); ++i )
{
QgsLayerTreeNode *treeNode = layerTreeGroupChildren.at( i );
if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
{
QgsLayerTreeGroup *treeGroupChild = static_cast<QgsLayerTreeGroup *>( treeNode );
QString name = treeGroupChild->name();
if ( restrictedLayers.contains( name ) ) //unpublished group
{
continue;
}
QString group;
if ( strGroup.isEmpty() )
{
group = name;
}
else
{
group = strGroup + "/" + name;
}
appendOwsLayersFromTreeGroup( doc, parentLayer, serverIface, project, request, treeGroupChild, combinedBBox, group );
}
else
{
QgsLayerTreeLayer *treeLayer = static_cast<QgsLayerTreeLayer *>( treeNode );
QgsMapLayer *l = treeLayer->layer();
if ( restrictedLayers.contains( l->name() ) ) //unpublished layer
{
continue;
}
QgsAccessControl *accessControl = serverIface->accessControls();
if ( accessControl && !accessControl->layerReadPermission( l ) )
{
continue;
}
QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
// queryable layer
if ( project->nonIdentifiableLayers().contains( l->id() ) )
{
layerElem.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "false" ) );
}
else
{
layerElem.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "true" ) );
}
// visibility
if ( treeLayer->itemVisibilityChecked() )
{
layerElem.setAttribute( QStringLiteral( "hidden" ), QStringLiteral( "true" ) );
}
else
{
layerElem.setAttribute( QStringLiteral( "hidden" ), QStringLiteral( "false" ) );
}
// layer group
if ( !strGroup.isEmpty() )
{
layerElem.setAttribute( QStringLiteral( "group" ), strGroup );
}
// Because Layer transparency is used for the rendering
// OWSContext Layer opacity is set to 1
layerElem.setAttribute( QStringLiteral( "opacity" ), 1 );
QString wmsName = l->name();
if ( QgsServerProjectUtils::wmsUseLayerIds( *project ) )
{
wmsName = l->id();
}
else if ( !l->shortName().isEmpty() )
{
wmsName = l->shortName();
}
// layer wms name
layerElem.setAttribute( QStringLiteral( "name" ), wmsName );
// define an id based on layer wms name
layerElem.setAttribute( QStringLiteral( "id" ), wmsName.replace( QRegExp( "[\\W]" ), QStringLiteral( "_" ) ) );
// layer title
QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
QString title = l->title();
if ( title.isEmpty() )
{
title = l->name();
}
QDomText titleText = doc.createTextNode( title );
titleElem.appendChild( titleText );
layerElem.appendChild( titleElem );
// WMS GetMap output format
QDomElement formatElem = doc.createElement( QStringLiteral( "ows:OutputFormat" ) );
QDomText formatText = doc.createTextNode( QStringLiteral( "image/png" ) );
formatElem.appendChild( formatText );
layerElem.appendChild( formatElem );
// Get WMS service URL for Server Element
QUrl href = serviceUrl( request, project );
//href needs to be a prefix
QString hrefString = href.toString( QUrl::FullyDecoded );
hrefString.append( href.hasQuery() ? "&" : "?" );
// COntext Server Element with WMS service URL
QDomElement serverElem = doc.createElement( QStringLiteral( "Server" ) );
serverElem.setAttribute( QStringLiteral( "service" ), QStringLiteral( "urn:ogc:serviceType:WMS" ) );
serverElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.3.0" ) );
serverElem.setAttribute( QStringLiteral( "default" ), QStringLiteral( "true" ) );
QDomElement orServerElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
orServerElem.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
serverElem.appendChild( orServerElem );
layerElem.appendChild( serverElem );
QString abstract = l->abstract();
if ( !abstract.isEmpty() )
{
QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
QDomText abstractText = doc.createTextNode( abstract );
abstractElem.appendChild( abstractText );
layerElem.appendChild( abstractElem );
}
//min/max scale denominatorScaleBasedVisibility
if ( l->hasScaleBasedVisibility() )
{
QString minScaleString = QString::number( l->minimumScale() );
QString maxScaleString = QString::number( l->maximumScale() );
QDomElement minScaleElem = doc.createElement( QStringLiteral( "sld:MinScaleDenominator" ) );
QDomText minScaleText = doc.createTextNode( minScaleString );
minScaleElem.appendChild( minScaleText );
layerElem.appendChild( minScaleElem );
QDomElement maxScaleElem = doc.createElement( QStringLiteral( "sld:MaxScaleDenominator" ) );
QDomText maxScaleText = doc.createTextNode( maxScaleString );
maxScaleElem.appendChild( maxScaleText );
layerElem.appendChild( maxScaleElem );
}
// Style list
appendOwsLayerStyles( doc, layerElem, l );
//keyword list
if ( !l->keywordList().isEmpty() )
{
QStringList keywordStringList = l->keywordList().split( QStringLiteral( "," ) );
bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *project );
QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
for ( int i = 0; i < keywordStringList.size(); ++i )
{
QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
QDomText keywordText = doc.createTextNode( keywordStringList.at( i ).trimmed() );
keywordElem.appendChild( keywordText );
if ( sia2045 )
{
keywordElem.setAttribute( QStringLiteral( "vocabulary" ), QStringLiteral( "SIA_Geo405" ) );
}
keywordsElem.appendChild( keywordElem );
}
layerElem.appendChild( keywordsElem );
}
// layer data URL
QString dataUrl = l->dataUrl();
if ( !dataUrl.isEmpty() )
{
QDomElement dataUrlElem = doc.createElement( QStringLiteral( "DataURL" ) );
QString dataUrlFormat = l->dataUrlFormat();
dataUrlElem.setAttribute( QStringLiteral( "format" ), dataUrlFormat );
QDomElement dataORElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
dataORElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
dataORElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) );
dataORElem.setAttribute( QStringLiteral( "xlink:href" ), dataUrl );
dataUrlElem.appendChild( dataORElem );
layerElem.appendChild( dataUrlElem );
}
// layer metadata URL
QString metadataUrl = l->metadataUrl();
if ( !metadataUrl.isEmpty() )
{
QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
QString metadataUrlFormat = l->metadataUrlFormat();
metaUrlElem.setAttribute( QStringLiteral( "format" ), metadataUrlFormat );
QDomElement metaUrlORElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
metaUrlORElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
metaUrlORElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) );
metaUrlORElem.setAttribute( QStringLiteral( "xlink:href" ), metadataUrl );
metaUrlElem.appendChild( metaUrlORElem );
layerElem.appendChild( metaUrlElem );
}
// update combineBBox
try
{
QgsCoordinateTransform t( l->crs(), project->crs() );
QgsRectangle BBox = t.transformBoundingBox( l->extent() );
if ( combinedBBox.isEmpty() )
{
combinedBBox = BBox;
}
else
{
combinedBBox.combineExtentWith( BBox );
}
}
catch ( const QgsCsException &cse )
{
Q_UNUSED( cse );
}
if ( parentLayer.hasChildNodes() )
{
parentLayer.insertBefore( layerElem, parentLayer.firstChild() );
}
else
{
parentLayer.appendChild( layerElem );
}
}// end of treeNode type
}// end of for
}
void appendOwsLayerStyles( QDomDocument &doc, QDomElement &layerElem, QgsMapLayer *currentLayer )
{
Q_FOREACH ( QString styleName, currentLayer->styleManager()->styles() )
{
if ( styleName.isEmpty() )
styleName = EMPTY_STYLE_NAME;
QDomElement styleListElem = doc.createElement( QStringLiteral( "StyleList" ) );
//only one default style in project file mode
QDomElement styleElem = doc.createElement( QStringLiteral( "Style" ) );
styleElem.setAttribute( QStringLiteral( "current" ), QStringLiteral( "true" ) );
QDomElement styleNameElem = doc.createElement( QStringLiteral( "Name" ) );
QDomText styleNameText = doc.createTextNode( styleName );
styleNameElem.appendChild( styleNameText );
QDomElement styleTitleElem = doc.createElement( QStringLiteral( "Title" ) );
QDomText styleTitleText = doc.createTextNode( styleName );
styleTitleElem.appendChild( styleTitleText );
styleElem.appendChild( styleNameElem );
styleElem.appendChild( styleTitleElem );
styleListElem.appendChild( styleElem );
layerElem.appendChild( styleListElem );
}
}
}
} // samespace QgsWms