Quantum GIS API Documentation  1.8
src/core/qgsexpression.h
Go to the documentation of this file.
00001 /***************************************************************************
00002                                qgsexpression.h
00003                              -------------------
00004     begin                : August 2011
00005     copyright            : (C) 2011 Martin Dobias
00006     email                : wonder.sk at gmail dot com
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 #ifndef QGSEXPRESSION_H
00017 #define QGSEXPRESSION_H
00018 
00019 #include <QStringList>
00020 #include <QVariant>
00021 #include <QList>
00022 #include <QDomDocument>
00023 
00024 #include "qgsfield.h"
00025 
00026 class QgsDistanceArea;
00027 class QgsFeature;
00028 class QDomElement;
00029 
00082 class CORE_EXPORT QgsExpression
00083 {
00084   public:
00085     QgsExpression( const QString& expr );
00086     ~QgsExpression();
00087 
00089     bool hasParserError() const { return !mParserErrorString.isNull(); }
00091     QString parserErrorString() const { return mParserErrorString; }
00092 
00094     bool prepare( const QgsFieldMap& fields );
00095 
00097     QStringList referencedColumns();
00099     bool needsGeometry();
00100 
00101     // evaluation
00102 
00105     QVariant evaluate( QgsFeature* f = NULL );
00106 
00109     QVariant evaluate( QgsFeature* f, const QgsFieldMap& fields );
00110 
00112     bool hasEvalError() const { return !mEvalErrorString.isNull(); }
00114     QString evalErrorString() const { return mEvalErrorString; }
00116     void setEvalErrorString( QString str ) { mEvalErrorString = str; }
00117 
00119     void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
00121     int currentRowNumber() { return mRowNumber; }
00122 
00124     QString dump() const;
00125 
00128     QgsDistanceArea* geomCalculator() { if ( !mCalc ) initGeomCalculator(); return mCalc; }
00129 
00130     //
00131 
00132     enum UnaryOperator
00133     {
00134       uoNot,
00135       uoMinus,
00136     };
00137     enum BinaryOperator
00138     {
00139       // logical
00140       boOr,
00141       boAnd,
00142 
00143       // comparison
00144       boEQ,  // =
00145       boNE,  // <>
00146       boLE,  // <=
00147       boGE,  // >=
00148       boLT,  // <
00149       boGT,  // >
00150       boRegexp,
00151       boLike,
00152       boNotLike,
00153       boILike,
00154       boNotILike,
00155       boIs,
00156       boIsNot,
00157 
00158       // math
00159       boPlus,
00160       boMinus,
00161       boMul,
00162       boDiv,
00163       boMod,
00164       boPow,
00165 
00166       // strings
00167       boConcat,
00168     };
00169 
00170     static const char* BinaryOperatorText[];
00171     static const char* UnaryOperatorText[];
00172 
00173     static const char* BinaryOgcOperatorText[];
00174     static const char* UnaryOgcOperatorText[];
00175 
00176     typedef QVariant( *FcnEval )( const QVariantList& values, QgsFeature* f, QgsExpression* parent );
00177 
00178     struct FunctionDef
00179     {
00180       FunctionDef( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false )
00181           : mName( fnname ), mParams( params ), mFcn( fcn ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ) {}
00183       QString mName;
00185       int mParams;
00187       FcnEval mFcn;
00189       bool mUsesGeometry;
00191       QString mGroup;
00193       QString mHelpText;
00194     };
00195 
00196     static const QList<FunctionDef> &BuiltinFunctions();
00197     static QList<FunctionDef> gmBuiltinFunctions;
00198 
00199     // tells whether the identifier is a name of existing function
00200     static bool isFunctionName( QString name );
00201 
00202     // return index of the function in BuiltinFunctions array
00203     static int functionIndex( QString name );
00204 
00208     static int functionCount();
00209 
00211     static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); }
00213     static QString quotedString( QString text ) { return QString( "'%1'" ).arg( text.replace( "'", "''" ) ); }
00214 
00216 
00217     class Visitor; // visitor interface is defined below
00218 
00219     class CORE_EXPORT Node
00220     {
00221       public:
00222         virtual ~Node() {}
00223         // abstract virtual eval function
00224         // errors are reported to the parent
00225         virtual QVariant eval( QgsExpression* parent, QgsFeature* f ) = 0;
00226 
00227         // abstract virtual preparation function
00228         // errors are reported to the parent
00229         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields ) = 0;
00230 
00231         virtual QString dump() const = 0;
00232 
00233         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const { Q_UNUSED( doc ); Q_UNUSED( element ); }
00234         static QgsExpression::Node* createFromOgcFilter( QDomElement &element, QString &errorMessage );
00235 
00236         virtual QStringList referencedColumns() const = 0;
00237         virtual bool needsGeometry() const = 0;
00238 
00239         // support for visitor pattern
00240         virtual void accept( Visitor& v ) = 0;
00241     };
00242 
00243     class CORE_EXPORT NodeList
00244     {
00245       public:
00246         NodeList() {}
00247         virtual ~NodeList() { foreach( Node* n, mList ) delete n; }
00248         void append( Node* node ) { mList.append( node ); }
00249         int count() { return mList.count(); }
00250         QList<Node*> list() { return mList; }
00251 
00252         virtual QString dump() const;
00253         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00254 
00255       protected:
00256         QList<Node*> mList;
00257     };
00258 
00259     class CORE_EXPORT NodeUnaryOperator : public Node
00260     {
00261       public:
00262         NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
00263         ~NodeUnaryOperator() { delete mOperand; }
00264 
00265         UnaryOperator op() { return mOp; }
00266         Node* operand() { return mOperand; }
00267 
00268         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00269         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00270         virtual QString dump() const;
00271 
00272         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00273         static QgsExpression::Node* createFromOgcFilter( QDomElement &element, QString &errorMessage );
00274 
00275         virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
00276         virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
00277         virtual void accept( Visitor& v ) { v.visit( this ); }
00278 
00279       protected:
00280         UnaryOperator mOp;
00281         Node* mOperand;
00282     };
00283 
00284     class CORE_EXPORT NodeBinaryOperator : public Node
00285     {
00286       public:
00287         NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
00288         ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
00289 
00290         BinaryOperator op() { return mOp; }
00291         Node* opLeft() { return mOpLeft; }
00292         Node* opRight() { return mOpRight; }
00293 
00294         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00295         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00296         virtual QString dump() const;
00297 
00298         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00299         static QgsExpression::Node* createFromOgcFilter( QDomElement &element, QString &errorMessage );
00300 
00301         virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
00302         virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
00303         virtual void accept( Visitor& v ) { v.visit( this ); }
00304 
00305       protected:
00306         bool compare( double diff );
00307         int computeInt( int x, int y );
00308         double computeDouble( double x, double y );
00309 
00310         BinaryOperator mOp;
00311         Node* mOpLeft;
00312         Node* mOpRight;
00313     };
00314 
00315     class CORE_EXPORT NodeInOperator : public Node
00316     {
00317       public:
00318         NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
00319         virtual ~NodeInOperator() { delete mNode; delete mList; }
00320 
00321         Node* node() { return mNode; }
00322         bool isNotIn() { return mNotIn; }
00323         NodeList* list() { return mList; }
00324 
00325         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00326         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00327         virtual QString dump() const;
00328 
00329         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00330 
00331         virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
00332         virtual bool needsGeometry() const { bool needs = false; foreach( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
00333         virtual void accept( Visitor& v ) { v.visit( this ); }
00334 
00335       protected:
00336         Node* mNode;
00337         NodeList* mList;
00338         bool mNotIn;
00339     };
00340 
00341     class CORE_EXPORT NodeFunction : public Node
00342     {
00343       public:
00344         NodeFunction( int fnIndex, NodeList* args ): mFnIndex( fnIndex ), mArgs( args ) {}
00345         //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
00346         virtual ~NodeFunction() { delete mArgs; }
00347 
00348         int fnIndex() { return mFnIndex; }
00349         NodeList* args() { return mArgs; }
00350 
00351         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00352         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00353         virtual QString dump() const;
00354 
00355         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00356         static QgsExpression::Node* createFromOgcFilter( QDomElement &element, QString &errorMessage );
00357 
00358         virtual QStringList referencedColumns() const { QStringList lst; if ( !mArgs ) return lst; foreach( Node* n, mArgs->list() ) lst.append( n->referencedColumns() ); return lst; }
00359         virtual bool needsGeometry() const { bool needs = BuiltinFunctions()[mFnIndex].mUsesGeometry; if ( mArgs ) { foreach( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
00360         virtual void accept( Visitor& v ) { v.visit( this ); }
00361 
00362       protected:
00363         //QString mName;
00364         int mFnIndex;
00365         NodeList* mArgs;
00366     };
00367 
00368     class CORE_EXPORT NodeLiteral : public Node
00369     {
00370       public:
00371         NodeLiteral( QVariant value ) : mValue( value ) {}
00372 
00373         QVariant value() { return mValue; }
00374 
00375         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00376         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00377         virtual QString dump() const;
00378 
00379         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00380         static QgsExpression::Node* createFromOgcFilter( QDomElement &element, QString &errorMessage );
00381 
00382         virtual QStringList referencedColumns() const { return QStringList(); }
00383         virtual bool needsGeometry() const { return false; }
00384         virtual void accept( Visitor& v ) { v.visit( this ); }
00385 
00386       protected:
00387         QVariant mValue;
00388     };
00389 
00390     class CORE_EXPORT NodeColumnRef : public Node
00391     {
00392       public:
00393         NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
00394 
00395         QString name() { return mName; }
00396 
00397         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00398         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00399         virtual QString dump() const;
00400 
00401         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00402         static QgsExpression::Node* createFromOgcFilter( QDomElement &element, QString &errorMessage );
00403 
00404         virtual QStringList referencedColumns() const { return QStringList( mName ); }
00405         virtual bool needsGeometry() const { return false; }
00406         virtual void accept( Visitor& v ) { v.visit( this ); }
00407 
00408       protected:
00409         QString mName;
00410         int mIndex;
00411     };
00412 
00413     class CORE_EXPORT WhenThen
00414     {
00415       public:
00416         WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
00417         ~WhenThen() { delete mWhenExp; delete mThenExp; }
00418 
00419         //protected:
00420         Node* mWhenExp;
00421         Node* mThenExp;
00422     };
00423     typedef QList<WhenThen*> WhenThenList;
00424 
00425     class CORE_EXPORT NodeCondition : public Node
00426     {
00427       public:
00428         NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
00429         ~NodeCondition() { delete mElseExp; foreach( WhenThen* cond, mConditions ) delete cond; }
00430 
00431         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00432         virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
00433         virtual QString dump() const;
00434 
00435         virtual void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00436 
00437         virtual QStringList referencedColumns() const;
00438         virtual bool needsGeometry() const;
00439         virtual void accept( Visitor& v ) { v.visit( this ); }
00440 
00441       protected:
00442         WhenThenList mConditions;
00443         Node* mElseExp;
00444     };
00445 
00447 
00450     class CORE_EXPORT Visitor
00451     {
00452       public:
00453         virtual ~Visitor() {}
00454         virtual void visit( NodeUnaryOperator* n ) = 0;
00455         virtual void visit( NodeBinaryOperator* n ) = 0;
00456         virtual void visit( NodeInOperator* n ) = 0;
00457         virtual void visit( NodeFunction* n ) = 0;
00458         virtual void visit( NodeLiteral* n ) = 0;
00459         virtual void visit( NodeColumnRef* n ) = 0;
00460         virtual void visit( NodeCondition* n ) = 0;
00461     };
00462 
00464     void acceptVisitor( Visitor& v );
00465 
00466     // convert from/to OGC Filter
00467     void toOgcFilter( QDomDocument &doc, QDomElement &element ) const;
00468     static QgsExpression* createFromOgcFilter( QDomElement &element );
00469 
00470   protected:
00471     // internally used to create an empty expression
00472     QgsExpression() : mRootNode( NULL ), mRowNumber( 0 ), mCalc( NULL ) {}
00473 
00474     QString mExpression;
00475     Node* mRootNode;
00476 
00477     QString mParserErrorString;
00478     QString mEvalErrorString;
00479 
00480     int mRowNumber;
00481 
00482     void initGeomCalculator();
00483     QgsDistanceArea* mCalc;
00484 };
00485 
00486 #endif // QGSEXPRESSION_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines