Skip to content

Commit 1a7ad76

Browse files
committedApr 2, 2014
Re-enable GetCapabilities in WFS server
1 parent db87e4d commit 1a7ad76

9 files changed

+443
-13
lines changed
 

‎src/mapserver/qgsconfigcache.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,30 @@ QgsWCSProjectParser* QgsConfigCache::wcsConfiguration( const QString& filePath )
5050

5151
QgsWFSProjectParser* QgsConfigCache::wfsConfiguration( const QString& filePath )
5252
{
53-
return 0; //todo...
53+
QgsWFSProjectParser* p = mWFSConfigCache.object( filePath );
54+
if ( p )
55+
{
56+
return p;
57+
}
58+
59+
QDomDocument* doc = xmlDocument( filePath );
60+
if ( !doc )
61+
{
62+
return 0;
63+
}
64+
65+
p = new QgsWFSProjectParser( doc, filePath );
66+
mWFSConfigCache.insert( filePath, p );
67+
return p;
5468
}
5569

5670
QgsWMSConfigParser* QgsConfigCache::wmsConfiguration( const QString& filePath )
5771
{
5872
QgsWMSConfigParser* p = mWMSConfigCache.object( filePath );
73+
if ( p )
74+
{
75+
return p;
76+
}
5977

6078
QDomDocument* doc = xmlDocument( filePath );
6179
if ( !doc )

‎src/mapserver/qgsconfigparserutils.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include <QDomDocument>
2727
#include <QDomElement>
28+
#include <QFile>
2829
#include <QString>
2930

3031
#include <sqlite3.h>
@@ -184,3 +185,21 @@ QStringList QgsConfigParserUtils::createCRSListForLayer( QgsMapLayer* theMapLaye
184185
sqlite3_close( myDatabase );
185186
return crsNumbers;
186187
}
188+
189+
void QgsConfigParserUtils::fallbackServiceCapabilities( QDomElement& parentElement, QDomDocument& doc )
190+
{
191+
Q_UNUSED( doc );
192+
QFile wmsService( "wms_metadata.xml" );
193+
if ( wmsService.open( QIODevice::ReadOnly ) )
194+
{
195+
QDomDocument externServiceDoc;
196+
QString parseError;
197+
int errorLineNo;
198+
if ( externServiceDoc.setContent( &wmsService, false, &parseError, &errorLineNo ) )
199+
{
200+
wmsService.close();
201+
QDomElement service = externServiceDoc.firstChildElement();
202+
parentElement.appendChild( service );
203+
}
204+
}
205+
}

‎src/mapserver/qgsconfigparserutils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class QgsConfigParserUtils
3838
const QgsCoordinateReferenceSystem& layerCRS );
3939
/**Returns a list of supported EPSG coordinate system numbers from a layer*/
4040
static QStringList createCRSListForLayer( QgsMapLayer* theMapLayer );
41+
42+
/**Returns default service capabilities from wms_metadata.xml if nothing else is defined*/
43+
static void fallbackServiceCapabilities( QDomElement& parentElement, QDomDocument& doc );
4144
};
4245

4346
#endif // QGSCONFIGPARSERUTILS_H

‎src/mapserver/qgsserverprojectparser.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,27 @@ QString QgsServerProjectParser::layerName( const QDomElement& layerElem ) const
303303
return nameElem.text().replace( "," , "%60" ); //commas are not allowed in layer names
304304
}
305305

306+
QString QgsServerProjectParser::serviceUrl() const
307+
{
308+
QString url;
309+
310+
if ( !mXMLDoc )
311+
{
312+
return url;
313+
}
314+
315+
QDomElement propertiesElement = propertiesElem();
316+
if ( !propertiesElement.isNull() )
317+
{
318+
QDomElement wmsUrlElem = propertiesElement.firstChildElement( "WMSUrl" );
319+
if ( !wmsUrlElem.isNull() )
320+
{
321+
url = wmsUrlElem.text();
322+
}
323+
}
324+
return url;
325+
}
326+
306327
void QgsServerProjectParser::combineExtentAndCrsOfGroupChildren( QDomElement& groupElem, QDomDocument& doc, bool considerMapExtent ) const
307328
{
308329
QgsRectangle combinedBBox;

‎src/mapserver/qgsserverprojectparser.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ class QgsServerProjectParser
101101
@return id or a null string in case of error*/
102102
QString layerName( const QDomElement& layerElem ) const;
103103

104+
QString serviceUrl() const;
105+
106+
QStringList wfsLayers() const;
107+
104108
private:
105109

106110
/**Content of project file*/
@@ -135,8 +139,6 @@ class QgsServerProjectParser
135139

136140
/**Adds sublayers of an embedded group to layer set*/
137141
static void sublayersOfEmbeddedGroup( const QString& projectFilePath, const QString& groupName, QSet<QString>& layerSet );
138-
139-
QStringList wfsLayers() const;
140142
};
141143

142144
#endif // QGSSERVERPROJECTPARSER_H

‎src/mapserver/qgswfsprojectparser.cpp

Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
***************************************************************************/
1717

1818
#include "qgswfsprojectparser.h"
19+
#include "qgsconfigparserutils.h"
20+
#include "qgsvectordataprovider.h"
1921

2022
QgsWFSProjectParser::QgsWFSProjectParser( QDomDocument* xmlDoc, const QString& filePath ):
2123
mProjectParser( xmlDoc, filePath )
@@ -25,3 +27,368 @@ QgsWFSProjectParser::QgsWFSProjectParser( QDomDocument* xmlDoc, const QString& f
2527
QgsWFSProjectParser::~QgsWFSProjectParser()
2628
{
2729
}
30+
31+
void QgsWFSProjectParser::serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const
32+
{
33+
QDomElement serviceElem = doc.createElement( "Service" );
34+
35+
QDomElement propertiesElem = mProjectParser.propertiesElem();
36+
if ( propertiesElem.isNull() )
37+
{
38+
QgsConfigParserUtils::fallbackServiceCapabilities( parentElement, doc );
39+
return;
40+
}
41+
42+
QDomElement serviceCapabilityElem = propertiesElem.firstChildElement( "WMSServiceCapabilities" );
43+
if ( serviceCapabilityElem.isNull() || serviceCapabilityElem.text().compare( "true", Qt::CaseInsensitive ) != 0 )
44+
{
45+
QgsConfigParserUtils::fallbackServiceCapabilities( parentElement, doc );
46+
return;
47+
}
48+
49+
QDomElement wmsNameElem = doc.createElement( "Name" );
50+
QDomText wmsNameText = doc.createTextNode( "WFS" );
51+
wmsNameElem.appendChild( wmsNameText );
52+
serviceElem.appendChild( wmsNameElem );
53+
54+
//WMS title
55+
QDomElement titleElem = propertiesElem.firstChildElement( "WMSServiceTitle" );
56+
if ( !titleElem.isNull() )
57+
{
58+
QDomElement wmsTitleElem = doc.createElement( "Title" );
59+
QDomText wmsTitleText = doc.createTextNode( titleElem.text() );
60+
wmsTitleElem.appendChild( wmsTitleText );
61+
serviceElem.appendChild( wmsTitleElem );
62+
}
63+
64+
//WMS abstract
65+
QDomElement abstractElem = propertiesElem.firstChildElement( "WMSServiceAbstract" );
66+
if ( !abstractElem.isNull() )
67+
{
68+
QDomElement wmsAbstractElem = doc.createElement( "Abstract" );
69+
QDomText wmsAbstractText = doc.createTextNode( abstractElem.text() );
70+
wmsAbstractElem.appendChild( wmsAbstractText );
71+
serviceElem.appendChild( wmsAbstractElem );
72+
}
73+
74+
//keyword list
75+
QDomElement keywordListElem = propertiesElem.firstChildElement( "WMSKeywordList" );
76+
if ( !keywordListElem.isNull() && !keywordListElem.text().isEmpty() )
77+
{
78+
QDomNodeList keywordList = keywordListElem.elementsByTagName( "value" );
79+
QStringList keywords;
80+
for ( int i = 0; i < keywordList.size(); ++i )
81+
{
82+
keywords << keywordList.at( i ).toElement().text();
83+
}
84+
85+
if ( keywordList.size() > 0 )
86+
{
87+
QDomElement wfsKeywordElem = doc.createElement( "Keywords" );
88+
QDomText keywordText = doc.createTextNode( keywords.join( ", " ) );
89+
wfsKeywordElem.appendChild( keywordText );
90+
serviceElem.appendChild( wfsKeywordElem );
91+
}
92+
}
93+
94+
//OnlineResource element is mandatory according to the WMS specification
95+
QDomElement wmsOnlineResourceElem = propertiesElem.firstChildElement( "WMSOnlineResource" );
96+
QDomElement onlineResourceElem = doc.createElement( "OnlineResource" );
97+
onlineResourceElem.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
98+
onlineResourceElem.setAttribute( "xlink:type", "simple" );
99+
if ( !wmsOnlineResourceElem.isNull() )
100+
{
101+
onlineResourceElem.setAttribute( "xlink:href", wmsOnlineResourceElem.text() );
102+
}
103+
104+
serviceElem.appendChild( onlineResourceElem );
105+
106+
//Fees
107+
QDomElement feesElem = propertiesElem.firstChildElement( "WMSFees" );
108+
if ( !feesElem.isNull() )
109+
{
110+
QDomElement wmsFeesElem = doc.createElement( "Fees" );
111+
QDomText wmsFeesText = doc.createTextNode( feesElem.text() );
112+
wmsFeesElem.appendChild( wmsFeesText );
113+
serviceElem.appendChild( wmsFeesElem );
114+
}
115+
116+
//AccessConstraints
117+
QDomElement accessConstraintsElem = propertiesElem.firstChildElement( "WMSAccessConstraints" );
118+
if ( !accessConstraintsElem.isNull() )
119+
{
120+
QDomElement wmsAccessConstraintsElem = doc.createElement( "AccessConstraints" );
121+
QDomText wmsAccessConstraintsText = doc.createTextNode( accessConstraintsElem.text() );
122+
wmsAccessConstraintsElem.appendChild( wmsAccessConstraintsText );
123+
serviceElem.appendChild( wmsAccessConstraintsElem );
124+
}
125+
parentElement.appendChild( serviceElem );
126+
}
127+
128+
QString QgsWFSProjectParser::serviceUrl() const
129+
{
130+
return mProjectParser.serviceUrl();
131+
}
132+
133+
QString QgsWFSProjectParser::wfsServiceUrl() const
134+
{
135+
QString url;
136+
137+
if ( !mProjectParser.xmlDocument() )
138+
{
139+
return url;
140+
}
141+
142+
QDomElement propertiesElem = mProjectParser.propertiesElem();
143+
if ( !propertiesElem.isNull() )
144+
{
145+
QDomElement wfsUrlElem = propertiesElem.firstChildElement( "WFSUrl" );
146+
if ( !wfsUrlElem.isNull() )
147+
{
148+
url = wfsUrlElem.text();
149+
}
150+
}
151+
return url;
152+
}
153+
154+
void QgsWFSProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const
155+
{
156+
const QList<QDomElement>& projectLayerElements = mProjectParser.projectLayerElements();
157+
if ( projectLayerElements.size() < 1 )
158+
{
159+
return;
160+
}
161+
162+
QStringList wfsLayersId = mProjectParser.wfsLayers();
163+
QStringList wfstUpdateLayersId = wfstUpdateLayers();
164+
QStringList wfstInsertLayersId = wfstInsertLayers();
165+
QStringList wfstDeleteLayersId = wfstDeleteLayers();
166+
167+
QMap<QString, QgsMapLayer *> layerMap;
168+
169+
foreach ( const QDomElement &elem, projectLayerElements )
170+
{
171+
QString type = elem.attribute( "type" );
172+
if ( type == "vector" )
173+
{
174+
//addJoinLayersForElement( elem ); //todo: fixme
175+
QgsMapLayer *layer = mProjectParser.createLayerFromElement( elem );
176+
if ( layer && wfsLayersId.contains( layer->id() ) )
177+
{
178+
QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) );
179+
layerMap.insert( layer->id(), layer );
180+
181+
QDomElement layerElem = doc.createElement( "FeatureType" );
182+
QDomElement nameElem = doc.createElement( "Name" );
183+
//We use the layer name even though it might not be unique.
184+
//Because the id sometimes contains user/pw information and the name is more descriptive
185+
QString typeName = layer->name();
186+
typeName = typeName.replace( " ", "_" );
187+
QDomText nameText = doc.createTextNode( typeName );
188+
nameElem.appendChild( nameText );
189+
layerElem.appendChild( nameElem );
190+
191+
QDomElement titleElem = doc.createElement( "Title" );
192+
QString titleName = layer->title();
193+
if ( titleName.isEmpty() )
194+
{
195+
titleName = layer->name();
196+
}
197+
QDomText titleText = doc.createTextNode( titleName );
198+
titleElem.appendChild( titleText );
199+
layerElem.appendChild( titleElem );
200+
201+
QDomElement abstractElem = doc.createElement( "Abstract" );
202+
QString abstractName = layer->abstract();
203+
if ( abstractName.isEmpty() )
204+
{
205+
abstractName = "";
206+
}
207+
QDomText abstractText = doc.createTextNode( abstractName );
208+
abstractElem.appendChild( abstractText );
209+
layerElem.appendChild( abstractElem );
210+
211+
//keyword list
212+
if ( !layer->keywordList().isEmpty() )
213+
{
214+
QDomElement keywordsElem = doc.createElement( "Keywords" );
215+
QDomText keywordsText = doc.createTextNode( layer->keywordList() );
216+
keywordsElem.appendChild( keywordsText );
217+
layerElem.appendChild( keywordsElem );
218+
}
219+
220+
//appendExGeographicBoundingBox( layerElem, doc, layer->extent(), layer->crs() );
221+
222+
QDomElement srsElem = doc.createElement( "SRS" );
223+
QDomText srsText = doc.createTextNode( layer->crs().authid() );
224+
srsElem.appendChild( srsText );
225+
layerElem.appendChild( srsElem );
226+
227+
//wfs:Operations element
228+
QDomElement operationsElement = doc.createElement( "Operations"/*wfs:Operations*/ );
229+
//wfs:Query element
230+
QDomElement queryElement = doc.createElement( "Query"/*wfs:Query*/ );
231+
operationsElement.appendChild( queryElement );
232+
233+
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
234+
QgsVectorDataProvider* provider = vlayer->dataProvider();
235+
if (( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
236+
{
237+
//wfs:Insert element
238+
QDomElement insertElement = doc.createElement( "Insert"/*wfs:Insert*/ );
239+
operationsElement.appendChild( insertElement );
240+
}
241+
if (( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
242+
( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
243+
wfstUpdateLayersId.contains( layer->id() ) )
244+
{
245+
//wfs:Update element
246+
QDomElement updateElement = doc.createElement( "Update"/*wfs:Update*/ );
247+
operationsElement.appendChild( updateElement );
248+
}
249+
if (( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
250+
{
251+
//wfs:Delete element
252+
QDomElement deleteElement = doc.createElement( "Delete"/*wfs:Delete*/ );
253+
operationsElement.appendChild( deleteElement );
254+
}
255+
256+
layerElem.appendChild( operationsElement );
257+
258+
QgsRectangle layerExtent = layer->extent();
259+
QDomElement bBoxElement = doc.createElement( "LatLongBoundingBox" );
260+
bBoxElement.setAttribute( "minx", QString::number( layerExtent.xMinimum() ) );
261+
bBoxElement.setAttribute( "miny", QString::number( layerExtent.yMinimum() ) );
262+
bBoxElement.setAttribute( "maxx", QString::number( layerExtent.xMaximum() ) );
263+
bBoxElement.setAttribute( "maxy", QString::number( layerExtent.yMaximum() ) );
264+
layerElem.appendChild( bBoxElement );
265+
266+
// layer metadata URL
267+
QString metadataUrl = layer->metadataUrl();
268+
if ( !metadataUrl.isEmpty() )
269+
{
270+
QDomElement metaUrlElem = doc.createElement( "MetadataURL" );
271+
QString metadataUrlType = layer->metadataUrlType();
272+
metaUrlElem.setAttribute( "type", metadataUrlType );
273+
QString metadataUrlFormat = layer->metadataUrlFormat();
274+
if ( metadataUrlFormat == "text/xml" )
275+
{
276+
metaUrlElem.setAttribute( "format", "XML" );
277+
}
278+
else
279+
{
280+
metaUrlElem.setAttribute( "format", "TXT" );
281+
}
282+
QDomText metaUrlText = doc.createTextNode( metadataUrl );
283+
metaUrlElem.appendChild( metaUrlText );
284+
layerElem.appendChild( metaUrlElem );
285+
}
286+
287+
parentElement.appendChild( layerElem );
288+
}
289+
}
290+
}
291+
return;
292+
}
293+
294+
QStringList QgsWFSProjectParser::wfstUpdateLayers() const
295+
{
296+
QStringList publiedIds = mProjectParser.wfsLayers();
297+
QStringList wfsList;
298+
if ( !mProjectParser.xmlDocument() )
299+
{
300+
return wfsList;
301+
}
302+
303+
QDomElement propertiesElem = mProjectParser.propertiesElem();
304+
if ( propertiesElem.isNull() )
305+
{
306+
return wfsList;
307+
}
308+
QDomElement wfstLayersElem = propertiesElem.firstChildElement( "WFSTLayers" );
309+
if ( wfstLayersElem.isNull() )
310+
{
311+
return wfsList;
312+
}
313+
QDomElement wfstUpdateLayersElem = wfstLayersElem.firstChildElement( "Update" );
314+
if ( wfstUpdateLayersElem.isNull() )
315+
{
316+
return wfsList;
317+
}
318+
QDomNodeList valueList = wfstUpdateLayersElem.elementsByTagName( "value" );
319+
for ( int i = 0; i < valueList.size(); ++i )
320+
{
321+
QString id = valueList.at( i ).toElement().text();
322+
if ( publiedIds.contains( id ) )
323+
wfsList << id;
324+
}
325+
return wfsList;
326+
}
327+
328+
QStringList QgsWFSProjectParser::wfstInsertLayers() const
329+
{
330+
QStringList updateIds = wfstUpdateLayers();
331+
QStringList wfsList;
332+
if ( !mProjectParser.xmlDocument() )
333+
{
334+
return wfsList;
335+
}
336+
337+
QDomElement propertiesElem = mProjectParser.propertiesElem();
338+
if ( propertiesElem.isNull() )
339+
{
340+
return wfsList;
341+
}
342+
QDomElement wfstLayersElem = propertiesElem.firstChildElement( "WFSTLayers" );
343+
if ( wfstLayersElem.isNull() )
344+
{
345+
return wfsList;
346+
}
347+
QDomElement wfstInsertLayersElem = wfstLayersElem.firstChildElement( "Insert" );
348+
if ( wfstInsertLayersElem.isNull() )
349+
{
350+
return wfsList;
351+
}
352+
QDomNodeList valueList = wfstInsertLayersElem.elementsByTagName( "value" );
353+
for ( int i = 0; i < valueList.size(); ++i )
354+
{
355+
QString id = valueList.at( i ).toElement().text();
356+
if ( updateIds.contains( id ) )
357+
wfsList << id;
358+
}
359+
return wfsList;
360+
}
361+
362+
QStringList QgsWFSProjectParser::wfstDeleteLayers() const
363+
{
364+
QStringList insertIds = wfstInsertLayers();
365+
QStringList wfsList;
366+
if ( !mProjectParser.xmlDocument() )
367+
{
368+
return wfsList;
369+
}
370+
371+
QDomElement propertiesElem = mProjectParser.propertiesElem();
372+
if ( propertiesElem.isNull() )
373+
{
374+
return wfsList;
375+
}
376+
QDomElement wfstLayersElem = propertiesElem.firstChildElement( "WFSTLayers" );
377+
if ( wfstLayersElem.isNull() )
378+
{
379+
return wfsList;
380+
}
381+
QDomElement wfstDeleteLayersElem = wfstLayersElem.firstChildElement( "Delete" );
382+
if ( wfstDeleteLayersElem.isNull() )
383+
{
384+
return wfsList;
385+
}
386+
QDomNodeList valueList = wfstDeleteLayersElem.elementsByTagName( "value" );
387+
for ( int i = 0; i < valueList.size(); ++i )
388+
{
389+
QString id = valueList.at( i ).toElement().text();
390+
if ( insertIds.contains( id ) )
391+
wfsList << id;
392+
}
393+
return wfsList;
394+
}

‎src/mapserver/qgswfsprojectparser.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,17 @@ class QgsWFSProjectParser
2626
QgsWFSProjectParser( QDomDocument* xmlDoc, const QString& filePath );
2727
~QgsWFSProjectParser();
2828

29+
void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
30+
QString serviceUrl() const;
31+
QString wfsServiceUrl() const;
32+
void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const;
33+
2934
private:
3035
QgsServerProjectParser mProjectParser;
36+
37+
QStringList wfstUpdateLayers() const;
38+
QStringList wfstInsertLayers() const;
39+
QStringList wfstDeleteLayers() const;
3140
};
3241

3342
#endif // QGSWFSPROJECTPARSER_H

‎src/mapserver/qgswfsserver.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ QDomDocument QgsWFSServer::getCapabilities()
166166
QgsDebugMsg( "Entering." );
167167
QDomDocument doc;
168168

169-
#if 0 //todo: fixme
170-
171169
//wfs:WFS_Capabilities element
172170
QDomElement wfsCapabilitiesElement = doc.createElement( "WFS_Capabilities"/*wms:WFS_Capabilities*/ );
173171
wfsCapabilitiesElement.setAttribute( "xmlns", WFS_NAMESPACE );
@@ -301,8 +299,6 @@ QDomDocument QgsWFSServer::getCapabilities()
301299
comparisonOperatorsElement.appendChild( doc.createElement( "ogc:Between"/*ogc:Between*/ ) );
302300
comparisonOperatorsElement.appendChild( doc.createElement( "ogc:Like"/*ogc:Like*/ ) );
303301

304-
#endif //0 //todo: fixme
305-
306302
return doc;
307303
}
308304

‎src/mapserver/qgswmsprojectparser.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,7 @@ QList<QgsMapLayer*> QgsWMSProjectParser::mapLayerFromStyle( const QString& lName
216216

217217
QString QgsWMSProjectParser::serviceUrl() const
218218
{
219-
QDomElement propertiesElem = mProjectParser.propertiesElem();
220-
if ( propertiesElem.isNull() )
221-
{
222-
return QString();
223-
}
224-
return propertiesElem.firstChildElement( "WMSUrl" ).text();
219+
return mProjectParser.serviceUrl();
225220
}
226221

227222
QStringList QgsWMSProjectParser::wfsLayerNames() const

0 commit comments

Comments
 (0)
Please sign in to comment.