112 changes: 112 additions & 0 deletions src/core/qgsogcutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1810,3 +1810,115 @@ QgsExpression::NodeBinaryOperator* QgsOgcUtils::nodePropertyIsNullFromOgcFilter(
return new QgsExpression::NodeBinaryOperator( QgsExpression::boIs, opLeft, opRight );
}



// -----------------------------------------



class QgsExpressionOGCVisitor : public QgsExpression::Visitor
{
public:
QgsExpressionOGCVisitor( QDomDocument& doc )
: mDoc( doc ), mRoot( doc.createElement("Filter") ), mParent( mRoot ), mResult( false )
{}

QDomElement root() { return mRoot; }
bool result() { return mResult; }

void visit( const QgsExpression::NodeUnaryOperator& n )
{
mResult = false;

if ( n.op() == QgsExpression::uoNot && n.operand() )
{
QDomElement notElemParent = mParent;
QDomElement notElem = mDoc.createElement( "Not" );

mParent = notElem;
n.operand()->accept( *this );
if ( !mResult )
return; // visit failed

mParent = notElemParent;
mParent.appendChild( notElem );
mResult = true;
}
}

void visit( const QgsExpression::NodeBinaryOperator& n )
{
QString opName;
switch ( n.op() )
{
case QgsExpression::boEQ: opName = "PropertyIsEqualTo"; break;
case QgsExpression::boNE: opName = "PropertyIsNotEqualTo"; break;
case QgsExpression::boLE: opName = "PropertyIsLessThanOrEqualTo"; break;
case QgsExpression::boGE: opName = "PropertyIsGreaterThanOrEqualTo"; break;
case QgsExpression::boLT: opName = "PropertyIsLessThan"; break;
case QgsExpression::boGT: opName = "PropertyIsGreaterThan"; break;
case QgsExpression::boOr: opName = "Or"; break;
case QgsExpression::boAnd: opName = "And"; break;
default: break;
}

mResult = false;
if ( opName.isEmpty() || !n.opLeft() || !n.opRight() )
return; // unknown operation -> fail

QDomElement opElem = mDoc.createElement( opName );
QDomElement opElemParent = mParent;

mParent = opElem;
n.opLeft()->accept( *this );
if ( !mResult )
return; // visit failed

mParent = opElem;
n.opRight()->accept( *this );
if ( !mResult )
return; // visit failed

mParent = opElemParent;
mParent.appendChild( opElem );
mResult = true;
}

void visit( const QgsExpression::NodeInOperator& ) { mResult = false; }
void visit( const QgsExpression::NodeFunction& ) { mResult = false; }

void visit( const QgsExpression::NodeLiteral& n )
{
QDomElement literalElem = mDoc.createElement( "Literal" );
QDomText literalText = mDoc.createTextNode( n.value().toString() );
literalElem.appendChild( literalText );
mParent.appendChild( literalElem );
mResult = true;
}

void visit( const QgsExpression::NodeColumnRef& n )
{
QDomElement propertyElem = mDoc.createElement( "PropertyName" );
QDomText propertyText = mDoc.createTextNode( n.name() );
propertyElem.appendChild( propertyText );
mParent.appendChild( propertyElem );
mResult = true;
}

void visit( const QgsExpression::NodeCondition& n ) { Q_UNUSED( n ); mResult = false; }

protected:
QDomDocument mDoc;
QDomElement mRoot;
QDomElement mParent;
bool mResult;
};



QDomElement QgsOgcUtils::expressionToOgcFilter( const QgsExpression& exp, QDomDocument& doc )
{
QgsExpressionOGCVisitor v( doc );
exp.acceptVisitor( v );
return v.result() ? v.root() : QDomElement();
}
4 changes: 4 additions & 0 deletions src/core/qgsogcutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class CORE_EXPORT QgsOgcUtils
/** Parse XML with OGC filter into QGIS expression */
static QgsExpression* expressionFromOgcFilter( const QDomElement& element );

/** Creates OGC filter XML element. Supports minimum standard filter according to the OGC filter specs (=,!=,<,>,<=,>=,AND,OR,NOT)
@return valid <Filter> QDomElement on success, otherwise null QDomElement
*/
static QDomElement expressionToOgcFilter( const QgsExpression& exp, QDomDocument& doc );

private:
/** static method that creates geometry from GML Point */
Expand Down
1 change: 0 additions & 1 deletion src/providers/wfs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ SET(WFS_SRCS
qgswfsdataitems.cpp
qgswfsfeatureiterator.cpp
qgswfssourceselect.cpp
qgswfsutils.cpp
)

SET (WFS_MOC_HDRS
Expand Down
7 changes: 4 additions & 3 deletions src/providers/wfs/qgswfscapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "qgsexpression.h"
#include "qgslogger.h"
#include "qgsnetworkaccessmanager.h"
#include "qgswfsutils.h"
#include "qgsogcutils.h"
#include <QDomDocument>
#include <QNetworkRequest>
#include <QNetworkReply>
Expand Down Expand Up @@ -106,9 +106,10 @@ QString QgsWFSCapabilities::uriGetFeature( QString typeName, QString crsString,
{
//if not, if must be a QGIS expression
QgsExpression filterExpression( filter );
if ( !QgsWFSUtils::expressionToOGCFilter( filterExpression, filterDoc ) )
QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( filterExpression, filterDoc );
if ( !filterElem.isNull() )
{
//error
filterDoc.appendChild( filterElem );
}

}
Expand Down
127 changes: 0 additions & 127 deletions src/providers/wfs/qgswfsutils.cpp

This file was deleted.

30 changes: 0 additions & 30 deletions src/providers/wfs/qgswfsutils.h

This file was deleted.

50 changes: 50 additions & 0 deletions tests/src/core/testqgsogcutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class TestQgsOgcUtils : public QObject

void testExpressionFromOgcFilter();
void testExpressionFromOgcFilter_data();

void testExpressionToOgcFilter();
void testExpressionToOgcFilter_data();
};


Expand Down Expand Up @@ -212,6 +215,53 @@ void TestQgsOgcUtils::testExpressionFromOgcFilter()
delete expr;
}

void TestQgsOgcUtils::testExpressionToOgcFilter()
{
QFETCH( QString, exprText );
QFETCH( QString, xmlText );

QgsExpression exp( exprText );
QVERIFY( !exp.hasParserError() );

QDomDocument doc;
QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( exp, doc );
QVERIFY( !filterElem.isNull() );

doc.appendChild( filterElem );

qDebug("EXPR: %s", exp.dump().toAscii().data() );
qDebug("OGC : %s", doc.toString( -1 ).toAscii().data() );

QCOMPARE( xmlText, doc.toString( -1 ) );
}

void TestQgsOgcUtils::testExpressionToOgcFilter_data()
{
QTest::addColumn<QString>( "exprText" );
QTest::addColumn<QString>( "xmlText" );

QTest::newRow( "=" ) << QString( "NAME = 'New York'" ) << QString(
"<Filter><PropertyIsEqualTo>"
"<PropertyName>NAME</PropertyName>"
"<Literal>New York</Literal>"
"</PropertyIsEqualTo></Filter>" );

QTest::newRow( ">" ) << QString( "COUNT > 3" ) << QString(
"<Filter><PropertyIsGreaterThan>"
"<PropertyName>COUNT</PropertyName>"
"<Literal>3</Literal>"
"</PropertyIsGreaterThan></Filter>" );

/*
QTest::newRow( "is null" ) << QString( "FIRST_NAME IS NULL" ) << QString(
"<Filter>"
"<PropertyIsNull>"
"<PropertyName>FIRST_NAME</ogc:PropertyName>"
"</PropertyIsNull>"
"</Filter>" );
*/
}


QTEST_MAIN( TestQgsOgcUtils )
#include "moc_testqgsogcutils.cxx"