Skip to content

Commit

Permalink
[WFS provider] Emit TYPENAME and TYPENAMES for WFS 2.0 DescribeFeatur…
Browse files Browse the repository at this point in the history
…eType & GetFeature

Fixes Redmine #21768 and #9849

Due to confusion in the WFS 2.0 sepecification the situation is that WFS 2.0
servers 'randomly' recognize TYPENAME or
TYPENAMES depending on DescribeFeatureType and GetFeature requests. So
emit both parameters as tests show that it fixes issues and doesn't seem to
cause harm.
  • Loading branch information
rouault committed May 25, 2019
1 parent 465e6f0 commit cb7af3c
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 188 deletions.
18 changes: 13 additions & 5 deletions src/providers/wfs/qgswfsdescribefeaturetype.cpp
Expand Up @@ -22,18 +22,26 @@ QgsWFSDescribeFeatureType::QgsWFSDescribeFeatureType( QgsWFSDataSourceURI &uri )
}

bool QgsWFSDescribeFeatureType::requestFeatureType( const QString &WFSVersion,
const QString &typeName, const QgsWfsCapabilities::Capabilities &caps, bool bUsePlural )
const QString &typeName, const QgsWfsCapabilities::Capabilities &caps )
{
QUrl url( mUri.requestUrl( QStringLiteral( "DescribeFeatureType" ) ) );
url.addQueryItem( QStringLiteral( "VERSION" ), WFSVersion );

url.addQueryItem( bUsePlural ?
QStringLiteral( "TYPENAMES" ) : QStringLiteral( "TYPENAME" ), typeName );
QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );

if ( WFSVersion.startsWith( QLatin1String( "2.0" ) ) )
{
url.addQueryItem( QStringLiteral( "TYPENAMES" ), typeName );
if ( !namespaceValue.isEmpty() )
{
url.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
}
}

url.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
if ( !namespaceValue.isEmpty() )
{
url.addQueryItem( bUsePlural ?
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
url.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
}

return sendGET( url, true, false );
Expand Down
3 changes: 1 addition & 2 deletions src/providers/wfs/qgswfsdescribefeaturetype.h
Expand Up @@ -28,8 +28,7 @@ class QgsWFSDescribeFeatureType : public QgsWfsRequest
//! Issue the request
bool requestFeatureType( const QString &WFSVersion,
const QString &typeName,
const QgsWfsCapabilities::Capabilities &caps,
bool bUsePlural );
const QgsWfsCapabilities::Capabilities &caps );

protected:
QString errorMessageWithReason( const QString &reason ) override;
Expand Down
9 changes: 5 additions & 4 deletions src/providers/wfs/qgswfsfeatureiterator.cpp
Expand Up @@ -235,8 +235,8 @@ QUrl QgsWFSFeatureDownloader::buildURL( qint64 startIndex, int maxFeatures, bool
}
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), typenames );
else
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typenames );
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typenames );

if ( forHits )
{
getFeatureUrl.addQueryItem( QStringLiteral( "RESULTTYPE" ), QStringLiteral( "hits" ) );
Expand Down Expand Up @@ -392,8 +392,9 @@ QUrl QgsWFSFeatureDownloader::buildURL( qint64 startIndex, int maxFeatures, bool

if ( !namespaces.isEmpty() )
{
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ),
namespaces );
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaces );
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaces );
}

QgsDebugMsgLevel( QStringLiteral( "WFS GetFeature URL: %1" ).arg( getFeatureUrl.toDisplayString( ) ), 2 );
Expand Down
73 changes: 15 additions & 58 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -420,32 +420,17 @@ bool QgsWFSProvider::processSQL( const QString &sqlString, QString &errorMsg, QS
}

QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
bool bUsePlural = false;
QByteArray response;
for ( int i = 0; i < 2; i++ )
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
concatenatedTypenames, mShared->mCaps ) )
{
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
concatenatedTypenames, mShared->mCaps, bUsePlural ) )
{
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
arg( dataSourceUri(), describeFeatureType.errorMessage() );
return false;
}

response = describeFeatureType.response();
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
{
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
bUsePlural = true;
}
else
{
break;
}
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
arg( dataSourceUri(), describeFeatureType.errorMessage() );
return false;
}

QByteArray response = describeFeatureType.response();


QDomDocument describeFeatureDocument;
errorMsg.clear();
if ( !describeFeatureDocument.setContent( response, true, &errorMsg ) )
Expand Down Expand Up @@ -1278,44 +1263,16 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields

QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );

bool bUsePlural = false;
QByteArray response;

for ( int i = 0; i < 2; i++ )
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
mShared->mURI.typeName(), mShared->mCaps ) )
{
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
mShared->mURI.typeName(), mShared->mCaps, bUsePlural ) )
{
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
return false;
}

response = describeFeatureType.response();
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
{
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
bUsePlural = true;
}
// "http://services.cuzk.cz/wfs/inspire-cp-wfs.asp?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=cp:CadastralParcel" returns
// <!--Generated by Marushka, version 4.2.5.0, GEOVAP, spol. s r.o., 31.05.2018.-->
// <ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.0.0" xml:lang="en-US" xmlns="http://www.opengis.net/ows/1.1">
// <Exception exceptionCode="OperationProcessingFailed" />
// </ExceptionReport>
else if ( i == 0 && response.indexOf( "<!--Generated by Marushka" ) >= 0 &&
response.indexOf( "OperationProcessingFailed" ) >= 0 )
{
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
bUsePlural = true;
}
else
{
break;
}
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
return false;
}

QByteArray response = describeFeatureType.response();

QDomDocument describeFeatureDocument;
QString errorMsg;
if ( !describeFeatureDocument.setContent( response, true, &errorMsg ) )
Expand Down
18 changes: 8 additions & 10 deletions src/providers/wfs/qgswfsshareddata.cpp
Expand Up @@ -1352,16 +1352,14 @@ int QgsWFSFeatureHitsRequest::getFeatureCount( const QString &WFSVersion,
{
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), typeName );
}
else
{
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
}
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );

QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );
if ( !namespaceValue.isEmpty() )
{
getFeatureUrl.addQueryItem( WFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
if ( WFSVersion.startsWith( QLatin1String( "2.0" ) ) )
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
}

if ( !filter.isEmpty() )
Expand Down Expand Up @@ -1422,14 +1420,14 @@ QgsRectangle QgsWFSSingleFeatureRequest::getExtent()
getFeatureUrl.addQueryItem( QStringLiteral( "VERSION" ), mShared->mWFSVersion );
if ( mShared->mWFSVersion .startsWith( QLatin1String( "2.0" ) ) )
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), mUri.typeName() );
else
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );

QString namespaceValue( mShared->mCaps.getNamespaceParameterValue( mShared->mWFSVersion, mUri.typeName() ) );
if ( !namespaceValue.isEmpty() )
{
getFeatureUrl.addQueryItem( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
}

if ( mShared->mWFSVersion .startsWith( QLatin1String( "2.0" ) ) )
Expand Down

0 comments on commit cb7af3c

Please sign in to comment.