Skip to content

Commit 0f00a52

Browse files
committedMay 26, 2017
[Server] WMS GetContext refactoring
1 parent 95a5cce commit 0f00a52

File tree

1 file changed

+393
-3
lines changed

1 file changed

+393
-3
lines changed
 

‎src/server/services/wms/qgswmsgetcontext.cpp

Lines changed: 393 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,36 @@
2020
***************************************************************************/
2121
#include "qgswmsutils.h"
2222
#include "qgswmsgetcontext.h"
23+
#include "qgsserverprojectutils.h"
24+
25+
#include "qgslayertreenode.h"
26+
#include "qgslayertreegroup.h"
27+
#include "qgslayertreelayer.h"
28+
#include "qgslayertreemodel.h"
29+
#include "qgslayertree.h"
30+
#include "qgsmaplayerstylemanager.h"
31+
32+
#include "qgscsexception.h"
2333

2434
namespace QgsWms
2535
{
36+
namespace
37+
{
38+
void appendOwsLayerStyles( QDomDocument &doc, QDomElement &layerElem, QgsMapLayer *currentLayer );
39+
40+
void appendOwsLayersFromTreeGroup( QDomDocument &doc,
41+
QDomElement &parentLayer,
42+
QgsServerInterface *serverIface,
43+
const QgsProject *project,
44+
const QgsServerRequest &request,
45+
const QgsLayerTreeGroup *layerTreeGroup,
46+
QgsRectangle &combinedBBox,
47+
const QString &strGroup );
48+
49+
void appendOwsGeneralAndResourceList( QDomDocument &doc, QDomElement &parentElement,
50+
QgsServerInterface *serverIface, const QgsProject *project,
51+
const QgsServerRequest &request );
52+
}
2653

2754
void writeGetContext( QgsServerInterface *serverIface, const QgsProject *project,
2855
const QString &version, const QgsServerRequest &request,
@@ -40,7 +67,7 @@ namespace QgsWms
4067
{
4168
Q_UNUSED( version );
4269

43-
QgsWmsConfigParser *configParser = getConfigParser( serverIface );
70+
//QgsWmsConfigParser *configParser = getConfigParser( serverIface );
4471

4572
QDomDocument doc;
4673
QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( QStringLiteral( "xml" ),
@@ -64,11 +91,374 @@ namespace QgsWms
6491
owsContextElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "0.3.1" ) );
6592
doc.appendChild( owsContextElem );
6693

67-
QString hrefString = serviceUrl( request, project ).toString( QUrl::FullyDecoded );
68-
configParser->owsGeneralAndResourceList( owsContextElem, doc, hrefString );
94+
appendOwsGeneralAndResourceList( doc, owsContextElem, serverIface, project, request );
6995

7096
return doc;
7197
}
98+
namespace
99+
{
100+
void appendOwsGeneralAndResourceList( QDomDocument &doc, QDomElement &parentElement,
101+
QgsServerInterface *serverIface, const QgsProject *project,
102+
const QgsServerRequest &request )
103+
{
104+
parentElement.setAttribute( QStringLiteral( "id" ), "ows-context-" + project->fileInfo().baseName() );
105+
106+
// OWSContext General element
107+
QDomElement generalElem = doc.createElement( QStringLiteral( "General" ) );
108+
109+
// OWSContext Window element
110+
QDomElement windowElem = doc.createElement( QStringLiteral( "Window" ) );
111+
windowElem.setAttribute( QStringLiteral( "height" ), QStringLiteral( "600" ) );
112+
windowElem.setAttribute( QStringLiteral( "width" ), QStringLiteral( "800" ) );
113+
generalElem.appendChild( windowElem );
114+
115+
//OWS title
116+
//why not use project title ?
117+
QString title = QgsServerProjectUtils::owsServiceTitle( *project );
118+
if ( !title.isEmpty() )
119+
{
120+
QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
121+
QDomText titleText = doc.createTextNode( title );
122+
titleElem.appendChild( titleText );
123+
generalElem.appendChild( titleElem );
124+
}
125+
126+
//OWS abstract
127+
QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project );
128+
if ( !abstract.isEmpty() )
129+
{
130+
QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
131+
QDomText abstractText = doc.createCDATASection( abstract );
132+
abstractElem.appendChild( abstractText );
133+
generalElem.appendChild( abstractElem );
134+
}
135+
136+
//OWS Keywords
137+
QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project );
138+
if ( !keywords.isEmpty() )
139+
{
140+
bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *project );
141+
142+
QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
143+
144+
for ( int i = 0; i < keywords.size(); ++i )
145+
{
146+
QString keyword = keywords.at( i );
147+
if ( !keyword.isEmpty() )
148+
{
149+
QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
150+
QDomText keywordText = doc.createTextNode( keyword );
151+
keywordElem.appendChild( keywordText );
152+
if ( sia2045 )
153+
{
154+
keywordElem.setAttribute( QStringLiteral( "vocabulary" ), QStringLiteral( "SIA_Geo405" ) );
155+
}
156+
keywordsElem.appendChild( keywordElem );
157+
}
158+
}
159+
generalElem.appendChild( keywordsElem );
160+
}
161+
162+
// OWSContext General element is complete
163+
parentElement.appendChild( generalElem );
164+
165+
// OWSContext ResourceList element
166+
QDomElement resourceListElem = doc.createElement( QStringLiteral( "ResourceList" ) );
167+
const QgsLayerTree *projectLayerTreeRoot = project->layerTreeRoot();
168+
QgsRectangle combinedBBox;
169+
appendOwsLayersFromTreeGroup( doc, resourceListElem, serverIface, project, request, projectLayerTreeRoot, combinedBBox, QString() );
170+
parentElement.appendChild( resourceListElem );
171+
172+
// OWSContext BoundingBox
173+
QgsCoordinateReferenceSystem projectCrs = project->crs();
174+
QgsRectangle mapRect = QgsServerProjectUtils::wmsExtent( *project );
175+
if ( mapRect.isEmpty() )
176+
{
177+
mapRect = combinedBBox;
178+
}
179+
QDomElement bboxElem = doc.createElement( QStringLiteral( "ows:BoundingBox" ) );
180+
bboxElem.setAttribute( QStringLiteral( "crs" ), projectCrs.authid() );
181+
if ( projectCrs.hasAxisInverted() )
182+
{
183+
mapRect.invert();
184+
}
185+
QDomElement lowerCornerElem = doc.createElement( QStringLiteral( "ows:LowerCorner" ) );
186+
QDomText lowerCornerText = doc.createTextNode( QString::number( mapRect.xMinimum() ) + " " + QString::number( mapRect.yMinimum() ) );
187+
lowerCornerElem.appendChild( lowerCornerText );
188+
bboxElem.appendChild( lowerCornerElem );
189+
QDomElement upperCornerElem = doc.createElement( QStringLiteral( "ows:UpperCorner" ) );
190+
QDomText upperCornerText = doc.createTextNode( QString::number( mapRect.xMaximum() ) + " " + QString::number( mapRect.yMaximum() ) );
191+
upperCornerElem.appendChild( upperCornerText );
192+
bboxElem.appendChild( upperCornerElem );
193+
generalElem.appendChild( bboxElem );
194+
}
195+
196+
void appendOwsLayersFromTreeGroup( QDomDocument &doc,
197+
QDomElement &parentLayer,
198+
QgsServerInterface *serverIface,
199+
const QgsProject *project,
200+
const QgsServerRequest &request,
201+
const QgsLayerTreeGroup *layerTreeGroup,
202+
QgsRectangle &combinedBBox,
203+
const QString &strGroup )
204+
{
205+
QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
206+
207+
QList< QgsLayerTreeNode * > layerTreeGroupChildren = layerTreeGroup->children();
208+
for ( int i = 0; i < layerTreeGroupChildren.size(); ++i )
209+
{
210+
QgsLayerTreeNode *treeNode = layerTreeGroupChildren.at( i );
211+
212+
if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
213+
{
214+
QgsLayerTreeGroup *treeGroupChild = static_cast<QgsLayerTreeGroup *>( treeNode );
215+
216+
QString name = treeGroupChild->name();
217+
if ( restrictedLayers.contains( name ) ) //unpublished group
218+
{
219+
continue;
220+
}
221+
222+
QString group;
223+
if ( strGroup.isEmpty() )
224+
{
225+
group = name;
226+
}
227+
else
228+
{
229+
group = strGroup + "/" + name;
230+
}
231+
232+
appendOwsLayersFromTreeGroup( doc, parentLayer, serverIface, project, request, treeGroupChild, combinedBBox, group );
233+
}
234+
else
235+
{
236+
QgsLayerTreeLayer *treeLayer = static_cast<QgsLayerTreeLayer *>( treeNode );
237+
QgsMapLayer *l = treeLayer->layer();
238+
if ( restrictedLayers.contains( l->name() ) ) //unpublished layer
239+
{
240+
continue;
241+
}
242+
243+
QgsAccessControl *accessControl = serverIface->accessControls();
244+
if ( accessControl && !accessControl->layerReadPermission( l ) )
245+
{
246+
continue;
247+
}
248+
249+
QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
250+
251+
// queryable layer
252+
if ( project->nonIdentifiableLayers().contains( l->id() ) )
253+
{
254+
layerElem.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "false" ) );
255+
}
256+
else
257+
{
258+
layerElem.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "true" ) );
259+
}
260+
261+
// visibility
262+
if ( treeLayer->itemVisibilityChecked() )
263+
{
264+
layerElem.setAttribute( QStringLiteral( "hidden" ), QStringLiteral( "true" ) );
265+
}
266+
else
267+
{
268+
layerElem.setAttribute( QStringLiteral( "hidden" ), QStringLiteral( "false" ) );
269+
}
270+
271+
// layer group
272+
if ( !strGroup.isEmpty() )
273+
{
274+
layerElem.setAttribute( QStringLiteral( "group" ), strGroup );
275+
}
276+
277+
// Because Layer transparency is used for the rendering
278+
// OWSContext Layer opacity is set to 1
279+
layerElem.setAttribute( QStringLiteral( "opacity" ), 1 );
280+
281+
QString wmsName = l->name();
282+
if ( QgsServerProjectUtils::wmsUseLayerIds( *project ) )
283+
{
284+
wmsName = l->id();
285+
}
286+
else if ( !l->shortName().isEmpty() )
287+
{
288+
wmsName = l->shortName();
289+
}
290+
// layer wms name
291+
layerElem.setAttribute( QStringLiteral( "name" ), wmsName );
292+
// define an id based on layer wms name
293+
layerElem.setAttribute( QStringLiteral( "id" ), wmsName.replace( QRegExp( "[\\W]" ), QStringLiteral( "_" ) ) );
294+
295+
// layer title
296+
QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
297+
QString title = l->title();
298+
if ( title.isEmpty() )
299+
{
300+
title = l->name();
301+
}
302+
QDomText titleText = doc.createTextNode( title );
303+
titleElem.appendChild( titleText );
304+
layerElem.appendChild( titleElem );
305+
306+
// WMS GetMap output format
307+
QDomElement formatElem = doc.createElement( QStringLiteral( "ows:OutputFormat" ) );
308+
QDomText formatText = doc.createTextNode( QStringLiteral( "image/png" ) );
309+
formatElem.appendChild( formatText );
310+
layerElem.appendChild( formatElem );
311+
312+
// Get WMS service URL for Server Element
313+
QUrl href = serviceUrl( request, project );
314+
315+
//href needs to be a prefix
316+
QString hrefString = href.toString( QUrl::FullyDecoded );
317+
hrefString.append( href.hasQuery() ? "&" : "?" );
318+
319+
// COntext Server Element with WMS service URL
320+
QDomElement serverElem = doc.createElement( QStringLiteral( "Server" ) );
321+
serverElem.setAttribute( QStringLiteral( "service" ), QStringLiteral( "urn:ogc:serviceType:WMS" ) );
322+
serverElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.3.0" ) );
323+
serverElem.setAttribute( QStringLiteral( "default" ), QStringLiteral( "true" ) );
324+
QDomElement orServerElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
325+
orServerElem.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
326+
serverElem.appendChild( orServerElem );
327+
layerElem.appendChild( serverElem );
328+
329+
QString abstract = l->abstract();
330+
if ( !abstract.isEmpty() )
331+
{
332+
QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
333+
QDomText abstractText = doc.createTextNode( abstract );
334+
abstractElem.appendChild( abstractText );
335+
layerElem.appendChild( abstractElem );
336+
}
337+
338+
//min/max scale denominatorScaleBasedVisibility
339+
if ( l->hasScaleBasedVisibility() )
340+
{
341+
QString minScaleString = QString::number( l->minimumScale() );
342+
QString maxScaleString = QString::number( l->maximumScale() );
343+
QDomElement minScaleElem = doc.createElement( QStringLiteral( "sld:MinScaleDenominator" ) );
344+
QDomText minScaleText = doc.createTextNode( minScaleString );
345+
minScaleElem.appendChild( minScaleText );
346+
layerElem.appendChild( minScaleElem );
347+
QDomElement maxScaleElem = doc.createElement( QStringLiteral( "sld:MaxScaleDenominator" ) );
348+
QDomText maxScaleText = doc.createTextNode( maxScaleString );
349+
maxScaleElem.appendChild( maxScaleText );
350+
layerElem.appendChild( maxScaleElem );
351+
}
352+
353+
// Style list
354+
appendOwsLayerStyles( doc, layerElem, l );
355+
356+
//keyword list
357+
if ( !l->keywordList().isEmpty() )
358+
{
359+
QStringList keywordStringList = l->keywordList().split( QStringLiteral( "," ) );
360+
bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *project );
361+
362+
QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
363+
for ( int i = 0; i < keywordStringList.size(); ++i )
364+
{
365+
QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
366+
QDomText keywordText = doc.createTextNode( keywordStringList.at( i ).trimmed() );
367+
keywordElem.appendChild( keywordText );
368+
if ( sia2045 )
369+
{
370+
keywordElem.setAttribute( QStringLiteral( "vocabulary" ), QStringLiteral( "SIA_Geo405" ) );
371+
}
372+
keywordsElem.appendChild( keywordElem );
373+
}
374+
layerElem.appendChild( keywordsElem );
375+
}
376+
377+
// layer data URL
378+
QString dataUrl = l->dataUrl();
379+
if ( !dataUrl.isEmpty() )
380+
{
381+
QDomElement dataUrlElem = doc.createElement( QStringLiteral( "DataURL" ) );
382+
QString dataUrlFormat = l->dataUrlFormat();
383+
dataUrlElem.setAttribute( QStringLiteral( "format" ), dataUrlFormat );
384+
QDomElement dataORElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
385+
dataORElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
386+
dataORElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) );
387+
dataORElem.setAttribute( QStringLiteral( "xlink:href" ), dataUrl );
388+
dataUrlElem.appendChild( dataORElem );
389+
layerElem.appendChild( dataUrlElem );
390+
}
391+
392+
// layer metadata URL
393+
QString metadataUrl = l->metadataUrl();
394+
if ( !metadataUrl.isEmpty() )
395+
{
396+
QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
397+
QString metadataUrlFormat = l->metadataUrlFormat();
398+
metaUrlElem.setAttribute( QStringLiteral( "format" ), metadataUrlFormat );
399+
QDomElement metaUrlORElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
400+
metaUrlORElem.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
401+
metaUrlORElem.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "simple" ) );
402+
metaUrlORElem.setAttribute( QStringLiteral( "xlink:href" ), metadataUrl );
403+
metaUrlElem.appendChild( metaUrlORElem );
404+
layerElem.appendChild( metaUrlElem );
405+
}
406+
407+
// update combineBBox
408+
try
409+
{
410+
QgsCoordinateTransform t( l->crs(), project->crs() );
411+
QgsRectangle BBox = t.transformBoundingBox( l->extent() );
412+
if ( combinedBBox.isEmpty() )
413+
{
414+
combinedBBox = BBox;
415+
}
416+
else
417+
{
418+
combinedBBox.combineExtentWith( BBox );
419+
}
420+
}
421+
catch ( const QgsCsException &cse )
422+
{
423+
Q_UNUSED( cse );
424+
}
425+
426+
if ( parentLayer.hasChildNodes() )
427+
{
428+
parentLayer.insertBefore( layerElem, parentLayer.firstChild() );
429+
}
430+
else
431+
{
432+
parentLayer.appendChild( layerElem );
433+
}
434+
}// end of treeNode type
435+
}// end of for
436+
}
437+
438+
void appendOwsLayerStyles( QDomDocument &doc, QDomElement &layerElem, QgsMapLayer *currentLayer )
439+
{
440+
Q_FOREACH ( QString styleName, currentLayer->styleManager()->styles() )
441+
{
442+
if ( styleName.isEmpty() )
443+
styleName = EMPTY_STYLE_NAME;
444+
445+
QDomElement styleListElem = doc.createElement( QStringLiteral( "StyleList" ) );
446+
//only one default style in project file mode
447+
QDomElement styleElem = doc.createElement( QStringLiteral( "Style" ) );
448+
styleElem.setAttribute( QStringLiteral( "current" ), QStringLiteral( "true" ) );
449+
QDomElement styleNameElem = doc.createElement( QStringLiteral( "Name" ) );
450+
QDomText styleNameText = doc.createTextNode( styleName );
451+
styleNameElem.appendChild( styleNameText );
452+
QDomElement styleTitleElem = doc.createElement( QStringLiteral( "Title" ) );
453+
QDomText styleTitleText = doc.createTextNode( styleName );
454+
styleTitleElem.appendChild( styleTitleText );
455+
styleElem.appendChild( styleNameElem );
456+
styleElem.appendChild( styleTitleElem );
457+
styleListElem.appendChild( styleElem );
458+
layerElem.appendChild( styleListElem );
459+
}
460+
}
461+
}
72462

73463
} // samespace QgsWms
74464

0 commit comments

Comments
 (0)
Please sign in to comment.