Skip to content

Commit 839de2e

Browse files
authoredMay 23, 2018
Merge pull request #7057 from rouault/fix_18882_alternate
[WFS provider] Revert to using singular TYPENAME keyword for WFS 2.0 DescribeFeatureType (fixes #18882, refs #17872)
2 parents 2bbacb6 + 2330b7f commit 839de2e

File tree

7 files changed

+363
-437
lines changed

7 files changed

+363
-437
lines changed
 

‎src/providers/wfs/qgswfsdescribefeaturetype.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,20 @@
1414
***************************************************************************/
1515

1616
#include "qgswfsdescribefeaturetype.h"
17-
#include "qgswfsutils.h"
1817

1918
QgsWFSDescribeFeatureType::QgsWFSDescribeFeatureType( QgsWFSDataSourceURI &uri )
2019
: QgsWfsRequest( uri )
2120
{
2221
}
2322

2423
bool QgsWFSDescribeFeatureType::requestFeatureType( const QString &WFSVersion,
25-
const QString &typeName, bool forceSingularTypeName )
24+
const QString &typeName, bool bUsePlural )
2625
{
2726
QUrl url( mUri.requestUrl( QStringLiteral( "DescribeFeatureType" ) ) );
2827
url.addQueryItem( QStringLiteral( "VERSION" ), WFSVersion );
29-
// The specs are not consistent: is it singular in 1.0.x and plural in 2.0.0?
30-
// see http://docs.opengeospatial.org/is/09-025r2/09-025r2.html#147
31-
if ( ! forceSingularTypeName )
32-
url.addQueryItem( QgsWFSUtils::typeNameParameterForVersion( WFSVersion ).toUpper( ), typeName );
33-
else
34-
url.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
28+
url.addQueryItem( bUsePlural ?
29+
QStringLiteral( "TYPENAMES" ) : QStringLiteral( "TYPENAME" ), typeName );
30+
3531
return sendGET( url, true, false );
3632
}
3733

‎src/providers/wfs/qgswfsdescribefeaturetype.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ class QgsWFSDescribeFeatureType : public QgsWfsRequest
2525
explicit QgsWFSDescribeFeatureType( QgsWFSDataSourceURI &uri );
2626

2727
//! Issue the request
28-
bool requestFeatureType( const QString &WFSVersion, const QString &typeName,
29-
bool forceSingularTypeName = false );
28+
bool requestFeatureType( const QString &WFSVersion, const QString &typeName, bool bUsePlural );
3029

3130
protected:
3231
QString errorMessageWithReason( const QString &reason ) override;

‎src/providers/wfs/qgswfsprovider.cpp

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -420,15 +420,31 @@ bool QgsWFSProvider::processSQL( const QString &sqlString, QString &errorMsg, QS
420420
}
421421

422422
QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
423-
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
424-
concatenatedTypenames ) )
423+
bool bUsePlural = false;
424+
QByteArray response;
425+
for ( int i = 0; i < 2; i++ )
425426
{
426-
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
427-
arg( dataSourceUri(), describeFeatureType.errorMessage() );
428-
return false;
429-
}
427+
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
428+
concatenatedTypenames, bUsePlural ) )
429+
{
430+
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
431+
arg( dataSourceUri(), describeFeatureType.errorMessage() );
432+
return false;
433+
}
430434

431-
const QByteArray &response = describeFeatureType.response();
435+
response = describeFeatureType.response();
436+
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
437+
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
438+
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
439+
{
440+
QgsDebugMsg( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" );
441+
bUsePlural = true;
442+
}
443+
else
444+
{
445+
break;
446+
}
447+
}
432448

433449
QDomDocument describeFeatureDocument;
434450
errorMsg.clear();
@@ -919,7 +935,7 @@ bool QgsWFSProvider::deleteFeatures( const QgsFeatureIds &id )
919935
transactionDoc.appendChild( transactionElem );
920936
//delete element
921937
QDomElement deleteElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Delete" ) );
922-
deleteElem.setAttribute( QgsWFSUtils::typeNameParameterForVersion( mShared->mWFSVersion ), tname );
938+
deleteElem.setAttribute( QStringLiteral( "typeName" ), tname );
923939
QDomElement filterElem = transactionDoc.createElementNS( QgsWFSConstants::OGC_NAMESPACE, QStringLiteral( "Filter" ) );
924940

925941

@@ -984,7 +1000,7 @@ bool QgsWFSProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
9841000
continue;
9851001
}
9861002
QDomElement updateElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Update" ) );
987-
updateElem.setAttribute( QgsWFSUtils::typeNameParameterForVersion( mShared->mWFSVersion ), tname );
1003+
updateElem.setAttribute( QStringLiteral( "typeName" ), tname );
9881004
//Property
9891005
QDomElement propertyElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Property" ) );
9901006
QDomElement nameElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Name" ) );
@@ -1040,7 +1056,6 @@ QString QgsWFSProvider::convertToXML( const QVariant &value )
10401056
return valueStr;
10411057
}
10421058

1043-
10441059
bool QgsWFSProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_map )
10451060
{
10461061
//find out typename from uri and strip namespace prefix
@@ -1066,7 +1081,7 @@ bool QgsWFSProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
10661081
}
10671082

10681083
QDomElement updateElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Update" ) );
1069-
updateElem.setAttribute( QgsWFSUtils::typeNameParameterForVersion( mShared->mWFSVersion ), tname );
1084+
updateElem.setAttribute( QStringLiteral( "typeName" ), tname );
10701085

10711086
QgsAttributeMap::const_iterator attMapIt = attIt.value().constBegin();
10721087
for ( ; attMapIt != attIt.value().constEnd(); ++attMapIt )
@@ -1159,25 +1174,38 @@ QString QgsWFSProvider::translateMetadataValue( const QString &mdKey, const QVar
11591174
{
11601175
return value.toString();
11611176
}
1162-
}
1177+
};
11631178

1164-
bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute,
1165-
QgsFields &fields,
1166-
QgsWkbTypes::Type &geomType,
1167-
bool forceSingularTypeNames )
1179+
bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields &fields, QgsWkbTypes::Type &geomType )
11681180
{
11691181
fields.clear();
11701182

11711183
QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
1172-
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1173-
mShared->mURI.typeName(), forceSingularTypeNames ) )
1184+
bool bUsePlural = false;
1185+
QByteArray response;
1186+
for ( int i = 0; i < 2; i++ )
11741187
{
1175-
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
1176-
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
1177-
return false;
1178-
}
1188+
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1189+
mShared->mURI.typeName(), bUsePlural ) )
1190+
{
1191+
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
1192+
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
1193+
return false;
1194+
}
11791195

1180-
const QByteArray &response = describeFeatureType.response();
1196+
response = describeFeatureType.response();
1197+
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
1198+
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
1199+
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
1200+
{
1201+
QgsDebugMsg( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" );
1202+
bUsePlural = true;
1203+
}
1204+
else
1205+
{
1206+
break;
1207+
}
1208+
}
11811209

11821210
QDomDocument describeFeatureDocument;
11831211
QString errorMsg;
@@ -1193,19 +1221,11 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute,
11931221
mShared->mURI.typeName(),
11941222
geometryAttribute, fields, geomType, errorMsg ) )
11951223
{
1196-
// If 2.0.0, let's assume it was a server that only accepted TYPENAME singular form
1197-
// and try with that ...
1198-
if ( ! forceSingularTypeNames && mShared->mWFSVersion.startsWith( '2' ) )
1199-
{
1200-
return QgsWFSProvider::describeFeatureType( geometryAttribute,
1201-
fields,
1202-
geomType,
1203-
true );
1204-
}
12051224
QgsMessageLog::logMessage( tr( "Analysis of DescribeFeatureType response failed for url %1: %2" ).
12061225
arg( dataSourceUri(), errorMsg ), tr( "WFS" ) );
12071226
return false;
12081227
}
1228+
12091229
return true;
12101230
}
12111231

@@ -1479,8 +1499,7 @@ QDomElement QgsWFSProvider::createTransactionElement( QDomDocument &doc ) const
14791499
describeFeatureTypeURL.addQueryItem( QStringLiteral( "REQUEST" ), QStringLiteral( "DescribeFeatureType" ) );
14801500
}
14811501
describeFeatureTypeURL.addQueryItem( QStringLiteral( "VERSION" ), QStringLiteral( "1.0.0" ) );
1482-
//TODO: proper support of 2.0.0, for now hardcoded
1483-
describeFeatureTypeURL.addQueryItem( QgsWFSUtils::typeNameParameterForVersion( WfsVersion ).toUpper(), mShared->mURI.typeName() );
1502+
describeFeatureTypeURL.addQueryItem( QStringLiteral( "TYPENAME" ), mShared->mURI.typeName() );
14841503

14851504
transactionElem.setAttribute( QStringLiteral( "xsi:schemaLocation" ), mApplicationNamespace + ' '
14861505
+ describeFeatureTypeURL.toEncoded() );

‎src/providers/wfs/qgswfsprovider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class QgsWFSProvider : public QgsVectorDataProvider
151151
The method gives back the name of
152152
the geometry attribute and the thematic attributes with their types*/
153153
bool describeFeatureType( QString &geometryAttribute,
154-
QgsFields &fields, QgsWkbTypes::Type &geomType, bool forceSingularTypeNames = false );
154+
QgsFields &fields, QgsWkbTypes::Type &geomType );
155155

156156
/**
157157
* For a given typename, reads the name of the geometry attribute, the

‎src/providers/wfs/qgswfsutils.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,6 @@ bool QgsWFSUtils::removeDir( const QString &dirName )
138138
return dir.rmdir( dirName );
139139
}
140140

141-
QString QgsWFSUtils::typeNameParameterForVersion( const QString &WfsVersion )
142-
{
143-
// WFS 2.0 uses the plural form TYPENAMES
144-
if ( WfsVersion.startsWith( '2' ) )
145-
{
146-
return QString( "typeNames" );
147-
}
148-
else
149-
{
150-
return QString( "typeName" );
151-
}
152-
}
153-
154141

155142
// We use a keep alive mechanism where every KEEP_ALIVE_DELAY ms we update
156143
// a shared memory segment with the current timestamp. This way, other QGIS

‎src/providers/wfs/qgswfsutils.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ class QgsWFSUtils
4545
//! Return a unique identifier made from feature content
4646
static QString getMD5( const QgsFeature &f );
4747

48-
//! Return the correct form of typeName(s) according to the specified \a WfsVersion
49-
static QString typeNameParameterForVersion( const QString &WfsVersion );
50-
5148
protected:
5249
friend class QgsWFSUtilsKeepAlive;
5350
static QSharedMemory *createAndAttachSHM();
@@ -65,7 +62,6 @@ class QgsWFSUtils
6562

6663
//! Remove (recursively) a directory.
6764
static bool removeDir( const QString &dirName );
68-
6965
};
7066

7167
//! For internal use of QgsWFSUtils

‎tests/src/python/test_provider_wfs.py

Lines changed: 304 additions & 375 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.