Skip to content

Commit

Permalink
[Server] wfs utils: Update the way parsing filter and adding a test
Browse files Browse the repository at this point in the history
  • Loading branch information
rldhont committed Jul 2, 2019
1 parent bceba8d commit 56d3b16
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/server/services/wfs/qgswfsgetfeature.cpp
Expand Up @@ -771,7 +771,7 @@ namespace QgsWfs

QDomElement filterElem = filter.firstChildElement();
QStringList serverFids;
query.featureRequest = parseFilterElement( query.typeName, filterElem, project, &serverFids );
query.featureRequest = parseFilterElement( query.typeName, filterElem, serverFids, project );
query.serverFids = serverFids;

if ( filterIt != filterList.constEnd() )
Expand Down Expand Up @@ -929,7 +929,7 @@ namespace QgsWfs
}
else if ( queryChildElem.tagName() == QLatin1String( "Filter" ) )
{
featureRequest = parseFilterElement( typeName, queryChildElem, project, &serverFids );
featureRequest = parseFilterElement( typeName, queryChildElem, serverFids, project );
}
else if ( queryChildElem.tagName() == QLatin1String( "SortBy" ) )
{
Expand Down
6 changes: 3 additions & 3 deletions src/server/services/wfs/qgswfstransaction.cpp
Expand Up @@ -1081,7 +1081,7 @@ namespace QgsWfs

QDomElement filterElem = filter.firstChildElement();
QStringList serverFids;
action.featureRequest = parseFilterElement( action.typeName, filterElem, project, &serverFids );
action.featureRequest = parseFilterElement( action.typeName, filterElem, serverFids, project );
action.serverFids = serverFids;

if ( filterIt != filterList.constEnd() )
Expand Down Expand Up @@ -1142,7 +1142,7 @@ namespace QgsWfs
}

QStringList serverFids;
QgsFeatureRequest featureRequest = parseFilterElement( typeName, filterElem, project, &serverFids );
QgsFeatureRequest featureRequest = parseFilterElement( typeName, filterElem, serverFids, project );

transactionDelete action;
action.typeName = typeName;
Expand Down Expand Up @@ -1198,7 +1198,7 @@ namespace QgsWfs
if ( filterNodeList.size() != 0 )
{
QDomElement filterElem = filterNodeList.at( 0 ).toElement();
featureRequest = parseFilterElement( typeName, filterElem, project, &serverFids );
featureRequest = parseFilterElement( typeName, filterElem, serverFids, project );
}
QgsMessageLog::logMessage( QStringLiteral( "parseUpdateActionElement: serverFids length %1" ).arg( serverFids.count() ), QStringLiteral( "Server" ), Qgis::Info );

Expand Down
6 changes: 3 additions & 3 deletions src/server/services/wfs/qgswfstransaction_1_0_0.cpp
Expand Up @@ -1056,7 +1056,7 @@ namespace QgsWfs

QDomElement filterElem = filter.firstChildElement();
QStringList serverFids;
action.featureRequest = parseFilterElement( action.typeName, filterElem, project, &serverFids );
action.featureRequest = parseFilterElement( action.typeName, filterElem, serverFids, project );
action.serverFids = serverFids;

if ( filterIt != filterList.constEnd() )
Expand Down Expand Up @@ -1117,7 +1117,7 @@ namespace QgsWfs
}

QStringList serverFids;
QgsFeatureRequest featureRequest = parseFilterElement( typeName, filterElem, project, &serverFids );
QgsFeatureRequest featureRequest = parseFilterElement( typeName, filterElem, serverFids, project );

transactionDelete action;
action.typeName = typeName;
Expand Down Expand Up @@ -1172,7 +1172,7 @@ namespace QgsWfs
if ( filterNodeList.size() != 0 )
{
QDomElement filterElem = filterNodeList.at( 0 ).toElement();
featureRequest = parseFilterElement( typeName, filterElem, project, &serverFids );
featureRequest = parseFilterElement( typeName, filterElem, serverFids, project );
}

transactionUpdate action;
Expand Down
86 changes: 56 additions & 30 deletions src/server/services/wfs/qgswfsutils.cpp
Expand Up @@ -101,7 +101,14 @@ namespace QgsWfs
return nullptr;
}

QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem, const QgsProject *project, QStringList *serverFids )
QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem, const QgsProject *project )
{
// Get the server feature ids in filter element
QStringList collectedServerFids;
return parseFilterElement( typeName, filterElem, collectedServerFids, project );
}

QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem, QStringList &serverFids, const QgsProject *project )
{
QgsFeatureRequest request;

Expand Down Expand Up @@ -135,7 +142,7 @@ namespace QgsWfs
throw QgsRequestNotWellFormedException( QStringLiteral( "No FeatureId element correctly parse against typeName '%1'" ).arg( typeName ) );
}
// update server feature ids
serverFids->append( collectedServerFids );
serverFids.append( collectedServerFids );
request.setFlags( QgsFeatureRequest::NoFlags );
return request;
}
Expand Down Expand Up @@ -169,7 +176,7 @@ namespace QgsWfs
throw QgsRequestNotWellFormedException( QStringLiteral( "No GmlObjectId element correctly parse against typeName '%1'" ).arg( typeName ) );
}
// update server feature ids
serverFids->append( collectedServerFids );
serverFids.append( collectedServerFids );
request.setFlags( QgsFeatureRequest::NoFlags );
return request;
}
Expand Down Expand Up @@ -199,50 +206,69 @@ namespace QgsWfs
else if ( filterElem.firstChildElement().tagName() == QLatin1String( "And" ) &&
!filterElem.firstChildElement().firstChildElement( QLatin1String( "BBOX" ) ).isNull() )
{
QDomElement childElem = filterElem.firstChildElement().firstChildElement();
while ( !childElem.isNull() )
{
// Create a filter element to parse And child
QDomElement childFilterElement = filterElem.ownerDocument().createElement( QLatin1String( "Filter" ) );
// Clone And child
childFilterElement.appendChild( childElem.cloneNode( true ) );
int nbChildElem = filterElem.firstChildElement().childNodes().size();

// Parse the filter element with the cloned And child
QStringList collectedServerFids;
QgsFeatureRequest childRequest = parseFilterElement( typeName, childFilterElement, project, &collectedServerFids );
// Create a filter element to parse And child not BBOX
QDomElement childFilterElement = filterElem.ownerDocument().createElement( QLatin1String( "Filter" ) );
if ( nbChildElem > 2 )
{
QDomElement childAndElement = filterElem.ownerDocument().createElement( QLatin1String( "And" ) );
childFilterElement.appendChild( childAndElement );
}

// Update server feature ids
if ( !collectedServerFids.isEmpty() )
{
serverFids->append( collectedServerFids );
}
// Create a filter element to parse BBOX
QDomElement bboxFilterElement = filterElem.ownerDocument().createElement( QLatin1String( "Filter" ) );

QDomElement childElem = filterElem.firstChildElement().firstChildElement();
while ( !childElem.isNull() )
{
// Update request based on BBOX
if ( childElem.tagName() == QLatin1String( "BBOX" ) )
{
if ( request.filterRect().isEmpty() )
{
request.setFilterRect( childRequest.filterRect() );
}
else
{
request.setFilterRect( request.filterRect().intersect( childRequest.filterRect() ) );
}
// Clone BBOX
bboxFilterElement.appendChild( childElem.cloneNode( true ) );
}
// Update expression
else
{
if ( !request.filterExpression() )
// Clone And child
if ( nbChildElem > 2 )
{
request.setFilterExpression( childRequest.filterExpression()->expression() );
childFilterElement.firstChildElement().appendChild( childElem.cloneNode( true ) );
}
else
{
request.setFilterExpression( QStringLiteral( "( %1 ) AND ( %2 )" ).arg( request.filterExpression()->expression(), childRequest.filterExpression()->expression() ) );
childFilterElement.appendChild( childElem.cloneNode( true ) );
}
}
childElem = childElem.nextSiblingElement();
}

// Parse the filter element with the cloned BBOX
QStringList collectedServerFids;
QgsFeatureRequest bboxRequest = parseFilterElement( typeName, bboxFilterElement, collectedServerFids, project );

// Update request based on BBOX
if ( request.filterRect().isEmpty() )
{
request.setFilterRect( bboxRequest.filterRect() );
}
else
{
request.setFilterRect( request.filterRect().intersect( bboxRequest.filterRect() ) );
}

// Parse the filter element with the cloned And child
QgsFeatureRequest childRequest = parseFilterElement( typeName, childFilterElement, collectedServerFids, project );

// Update server feature ids
if ( !collectedServerFids.isEmpty() )
{
serverFids.append( collectedServerFids );
}

// Update expression
request.setFilterExpression( childRequest.filterExpression()->expression() );

request.setFlags( QgsFeatureRequest::ExactIntersect | QgsFeatureRequest::NoFlags );
return request;
}
Expand Down
7 changes: 6 additions & 1 deletion src/server/services/wfs/qgswfsutils.h
Expand Up @@ -57,10 +57,15 @@ namespace QgsWfs
*/
QgsVectorLayer *layerByTypeName( const QgsProject *project, const QString &typeName );

/**
* Transform a Filter element to a feature request
*/
QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem, const QgsProject *project = nullptr );

/**
* Transform a Filter element to a feature request and update server feature ids
*/
QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem, const QgsProject *project = nullptr, QStringList *serverFids = new QStringList() );
QgsFeatureRequest parseFilterElement( const QString &typeName, QDomElement &filterElem, QStringList &serverFids, const QgsProject *project = nullptr );

// Define namespaces used in WFS documents
const QString WFS_NAMESPACE = QStringLiteral( "http://www.opengis.net/wfs" );
Expand Down
20 changes: 20 additions & 0 deletions tests/src/python/test_qgsserver_wfs.py
Expand Up @@ -310,6 +310,26 @@ def test_getfeature_post(self):
"""
tests.append(('sortby_post', sortTemplate.format("")))

andTemplate = """<?xml version="1.0" encoding="UTF-8"?>
<wfs:GetFeature service="WFS" version="1.0.0" {} xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<wfs:Query typeName="testlayer" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:And>
<ogc:PropertyIsGreaterThan>
<ogc:PropertyName>id</ogc:PropertyName>
<ogc:Literal>1</ogc:Literal>
</ogc:PropertyIsGreaterThan>
<ogc:PropertyIsLessThan>
<ogc:PropertyName>id</ogc:PropertyName>
<ogc:Literal>3</ogc:Literal>
</ogc:PropertyIsLessThan>
</ogc:And>
</ogc:Filter>
</wfs:Query>
</wfs:GetFeature>
"""
tests.append(('and_post', andTemplate.format("")))

andBboxTemplate = """<?xml version="1.0" encoding="UTF-8"?>
<wfs:GetFeature service="WFS" version="1.0.0" {} xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<wfs:Query typeName="testlayer" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
Expand Down
26 changes: 26 additions & 0 deletions tests/testdata/qgis_server/wfs_getfeature_and_post.txt
@@ -0,0 +1,26 @@
Content-Type: text/xml; subtype=gml/2.1.2; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml ?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project_wfs.qgs&amp;SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=testlayer&amp;OUTPUTFORMAT=XMLSCHEMA">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">8.20345931,44.90139484 8.20354699,44.90148253</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<qgs:testlayer fid="testlayer.1">
<gml:boundedBy>
<gml:Box srsName="EPSG:3857">
<gml:coordinates cs="," ts=" ">913214.67407005,5606017.87425818 913214.67407005,5606017.87425818</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">913214.67407005,5606017.87425818</coordinates>
</Point>
</qgs:geometry>
<qgs:id>2</qgs:id>
<qgs:name>two</qgs:name>
<qgs:utf8nameè>two àò</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>

0 comments on commit 56d3b16

Please sign in to comment.