Quantum GIS API Documentation  master-693a1fe
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 <QMetaType>
00020 #include <QStringList>
00021 #include <QVariant>
00022 #include <QList>
00023 #include <QDomDocument>
00024 
00025 #include "qgsfield.h"
00026 #include "qgsdistancearea.h"
00027 
00028 class QgsFeature;
00029 class QgsGeometry;
00030 class QgsOgcUtils;
00031 class QgsVectorLayer;
00032 
00033 class QDomElement;
00034 
00088 class CORE_EXPORT QgsExpression
00089 {
00090   public:
00091     QgsExpression( const QString& expr );
00092     ~QgsExpression();
00093 
00095     bool hasParserError() const { return !mParserErrorString.isNull(); }
00097     QString parserErrorString() const { return mParserErrorString; }
00098 
00099     class Node;
00100 
00102     const Node* rootNode() const { return mRootNode; }
00103 
00105     bool prepare( const QgsFields& fields );
00106 
00108     QStringList referencedColumns();
00110     bool needsGeometry();
00111 
00112     // evaluation
00113 
00116     QVariant evaluate( QgsFeature* f = NULL );
00117 
00120     QVariant evaluate( QgsFeature* f, const QgsFields& fields );
00121 
00123     bool hasEvalError() const { return !mEvalErrorString.isNull(); }
00125     QString evalErrorString() const { return mEvalErrorString; }
00127     void setEvalErrorString( QString str ) { mEvalErrorString = str; }
00128 
00130     void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
00132     int currentRowNumber() { return mRowNumber; }
00133 
00135     static void setSpecialColumn( const QString& name, QVariant value );
00137     static void unsetSpecialColumn( const QString& name );
00139     static QVariant specialColumn( const QString& name );
00140 
00141     void setScale( double scale ) { mScale = scale; }
00142 
00143     int scale() {return mScale; }
00144 
00145     const QString& expression() const { return mExpression; }
00146 
00148     QString dump() const;
00149 
00152     QgsDistanceArea* geomCalculator() { return & mCalc; }
00153 
00155     // instead of the default.
00156     void setGeomCalculator( QgsDistanceArea& calc );
00157 
00165     static QString replaceExpressionText( QString action, QgsFeature* feat,
00166                                           QgsVectorLayer* layer,
00167                                           const QMap<QString, QVariant> *substitutionMap = 0 );
00168 
00169 
00170     static QString replaceExpressionText( QString action, QgsFeature& feat,
00171                                           QgsVectorLayer* layer,
00172                                           const QMap<QString, QVariant> *substitutionMap = 0 );
00173     enum UnaryOperator
00174     {
00175       uoNot,
00176       uoMinus,
00177     };
00178     enum BinaryOperator
00179     {
00180       // logical
00181       boOr,
00182       boAnd,
00183 
00184       // comparison
00185       boEQ,  // =
00186       boNE,  // <>
00187       boLE,  // <=
00188       boGE,  // >=
00189       boLT,  // <
00190       boGT,  // >
00191       boRegexp,
00192       boLike,
00193       boNotLike,
00194       boILike,
00195       boNotILike,
00196       boIs,
00197       boIsNot,
00198 
00199       // math
00200       boPlus,
00201       boMinus,
00202       boMul,
00203       boDiv,
00204       boMod,
00205       boPow,
00206 
00207       // strings
00208       boConcat,
00209     };
00210     enum SpatialOperator
00211     {
00212       soBbox,
00213       soIntersects,
00214       soContains,
00215       soCrosses,
00216       soEquals,
00217       soDisjoint,
00218       soOverlaps,
00219       soTouches,
00220       soWithin,
00221     };
00222 
00223     static const char* BinaryOperatorText[];
00224     static const char* UnaryOperatorText[];
00225 
00226     typedef QVariant( *FcnEval )( const QVariantList& values, QgsFeature* f, QgsExpression* parent );
00227 
00228 
00232     class CORE_EXPORT Function
00233     {
00234       public:
00235         Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false )
00236             : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ) {}
00238         QString name() { return mName; }
00240         int params() { return mParams; }
00242         bool usesgeometry() { return mUsesGeometry; }
00244         QString group() { return mGroup; }
00246         QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
00247 
00248         virtual QVariant func( const QVariantList& values, QgsFeature* f, QgsExpression* parent ) = 0;
00249 
00250         bool operator==( const Function& other ) const
00251         {
00252           if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
00253             return true;
00254 
00255           return false;
00256         }
00257 
00258       private:
00259         QString mName;
00260         int mParams;
00261         bool mUsesGeometry;
00262         QString mGroup;
00263         QString mHelpText;
00264     };
00265 
00266     class StaticFunction : public Function
00267     {
00268       public:
00269         StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false )
00270             : Function( fnname, params, group, helpText, usesGeometry ), mFnc( fcn ) {}
00271 
00272         virtual QVariant func( const QVariantList& values, QgsFeature* f, QgsExpression* parent )
00273         {
00274           return mFnc( values, f, parent );
00275         }
00276 
00277       private:
00278         FcnEval mFnc;
00279     };
00280 
00281     const static QList<Function*> &Functions();
00282     static QList<Function*> gmFunctions;
00283 
00284     static QStringList gmBuiltinFunctions;
00285     const static QStringList &BuiltinFunctions();
00286 
00287     static bool registerFunction( Function* function );
00288     static bool unregisterFunction( QString name );
00289 
00290     // tells whether the identifier is a name of existing function
00291     static bool isFunctionName( QString name );
00292 
00293     // return index of the function in Functions array
00294     static int functionIndex( QString name );
00295 
00299     static int functionCount();
00300 
00304     static QList<Function*> specialColumns();
00305 
00307     static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); }
00309     static QString quotedString( QString text ) { return QString( "'%1'" ).arg( text.replace( "'", "''" ) ); }
00310 
00312 
00313     class Visitor; // visitor interface is defined below
00314 
00315     enum NodeType
00316     {
00317       ntUnaryOperator,
00318       ntBinaryOperator,
00319       ntInOperator,
00320       ntFunction,
00321       ntLiteral,
00322       ntColumnRef,
00323       ntCondition
00324     };
00325 
00326     class CORE_EXPORT Node
00327     {
00328       public:
00329         virtual ~Node() {}
00330         virtual NodeType nodeType() const = 0;
00331         // abstract virtual eval function
00332         // errors are reported to the parent
00333         virtual QVariant eval( QgsExpression* parent, QgsFeature* f ) = 0;
00334 
00335         // abstract virtual preparation function
00336         // errors are reported to the parent
00337         virtual bool prepare( QgsExpression* parent, const QgsFields& fields ) = 0;
00338 
00339         virtual QString dump() const = 0;
00340 
00341         virtual QStringList referencedColumns() const = 0;
00342         virtual bool needsGeometry() const = 0;
00343 
00344         // support for visitor pattern
00345         virtual void accept( Visitor& v ) const = 0;
00346     };
00347 
00348     class CORE_EXPORT NodeList
00349     {
00350       public:
00351         NodeList() {}
00352         virtual ~NodeList() { foreach ( Node* n, mList ) delete n; }
00353         void append( Node* node ) { mList.append( node ); }
00354         int count() { return mList.count(); }
00355         QList<Node*> list() { return mList; }
00356 
00357         virtual QString dump() const;
00358 
00359       protected:
00360         QList<Node*> mList;
00361     };
00362 
00363     class CORE_EXPORT Interval
00364     {
00365         // YEAR const value taken from postgres query
00366         // SELECT EXTRACT(EPOCH FROM interval '1 year')
00367         static const int YEARS = 31557600;
00368         static const int MONTHS = 60 * 60 * 24 * 30;
00369         static const int WEEKS = 60 * 60 * 24 * 7;
00370         static const int DAY = 60 * 60 * 24;
00371         static const int HOUR = 60 * 60;
00372         static const int MINUTE = 60;
00373       public:
00374         Interval( double seconds = 0 ): mSeconds( seconds ), mValid( true ) { }
00375         ~Interval();
00376         double years() { return mSeconds / YEARS;}
00377         double months() { return mSeconds / MONTHS; }
00378         double weeks() { return mSeconds / WEEKS;}
00379         double days() { return mSeconds / DAY;}
00380         double hours() { return mSeconds / HOUR;}
00381         double minutes() { return mSeconds / MINUTE;}
00382         bool isValid() { return mValid; }
00383         void setValid( bool valid ) { mValid = valid; }
00384         double seconds() { return mSeconds; }
00385         bool operator==( const QgsExpression::Interval& other ) const;
00386         static QgsExpression::Interval invalidInterVal();
00387         static QgsExpression::Interval fromString( QString string );
00388       private:
00389         double mSeconds;
00390         bool mValid;
00391     };
00392 
00393     class CORE_EXPORT NodeUnaryOperator : public Node
00394     {
00395       public:
00396         NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
00397         ~NodeUnaryOperator() { delete mOperand; }
00398 
00399         UnaryOperator op() const { return mOp; }
00400         Node* operand() const { return mOperand; }
00401 
00402         virtual NodeType nodeType() const { return ntUnaryOperator; }
00403         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00404         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00405         virtual QString dump() const;
00406 
00407         virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
00408         virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
00409         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00410 
00411       protected:
00412         UnaryOperator mOp;
00413         Node* mOperand;
00414     };
00415 
00416     class CORE_EXPORT NodeBinaryOperator : public Node
00417     {
00418       public:
00419         NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
00420         ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
00421 
00422         BinaryOperator op() const { return mOp; }
00423         Node* opLeft() const { return mOpLeft; }
00424         Node* opRight() const { return mOpRight; }
00425 
00426         virtual NodeType nodeType() const { return ntBinaryOperator; }
00427         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00428         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00429         virtual QString dump() const;
00430 
00431         virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
00432         virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
00433         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00434 
00435       protected:
00436         bool compare( double diff );
00437         int computeInt( int x, int y );
00438         double computeDouble( double x, double y );
00439         QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
00440 
00441         BinaryOperator mOp;
00442         Node* mOpLeft;
00443         Node* mOpRight;
00444     };
00445 
00446     class CORE_EXPORT NodeInOperator : public Node
00447     {
00448       public:
00449         NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
00450         virtual ~NodeInOperator() { delete mNode; delete mList; }
00451 
00452         Node* node() const { return mNode; }
00453         bool isNotIn() const { return mNotIn; }
00454         NodeList* list() const { return mList; }
00455 
00456         virtual NodeType nodeType() const { return ntInOperator; }
00457         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00458         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00459         virtual QString dump() const;
00460 
00461         virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
00462         virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
00463         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00464 
00465       protected:
00466         Node* mNode;
00467         NodeList* mList;
00468         bool mNotIn;
00469     };
00470 
00471     class CORE_EXPORT NodeFunction : public Node
00472     {
00473       public:
00474         NodeFunction( int fnIndex, NodeList* args ): mFnIndex( fnIndex ), mArgs( args ) {}
00475         //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
00476         virtual ~NodeFunction() { delete mArgs; }
00477 
00478         int fnIndex() const { return mFnIndex; }
00479         NodeList* args() const { return mArgs; }
00480 
00481         virtual NodeType nodeType() const { return ntFunction; }
00482         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00483         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00484         virtual QString dump() const;
00485 
00486         virtual QStringList referencedColumns() const { QStringList lst; if ( !mArgs ) return lst; foreach ( Node* n, mArgs->list() ) lst.append( n->referencedColumns() ); return lst; }
00487         virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
00488         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00489 
00490       protected:
00491         //QString mName;
00492         int mFnIndex;
00493         NodeList* mArgs;
00494     };
00495 
00496     class CORE_EXPORT NodeLiteral : public Node
00497     {
00498       public:
00499         NodeLiteral( QVariant value ) : mValue( value ) {}
00500 
00501         QVariant value() const { return mValue; }
00502 
00503         virtual NodeType nodeType() const { return ntLiteral; }
00504         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00505         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00506         virtual QString dump() const;
00507 
00508         virtual QStringList referencedColumns() const { return QStringList(); }
00509         virtual bool needsGeometry() const { return false; }
00510         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00511 
00512       protected:
00513         QVariant mValue;
00514     };
00515 
00516     class CORE_EXPORT NodeColumnRef : public Node
00517     {
00518       public:
00519         NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
00520 
00521         QString name() const { return mName; }
00522 
00523         virtual NodeType nodeType() const { return ntColumnRef; }
00524         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00525         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00526         virtual QString dump() const;
00527 
00528         virtual QStringList referencedColumns() const { return QStringList( mName ); }
00529         virtual bool needsGeometry() const { return false; }
00530         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00531 
00532       protected:
00533         QString mName;
00534         int mIndex;
00535     };
00536 
00537     class CORE_EXPORT WhenThen
00538     {
00539       public:
00540         WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
00541         ~WhenThen() { delete mWhenExp; delete mThenExp; }
00542 
00543         //protected:
00544         Node* mWhenExp;
00545         Node* mThenExp;
00546     };
00547     typedef QList<WhenThen*> WhenThenList;
00548 
00549     class CORE_EXPORT NodeCondition : public Node
00550     {
00551       public:
00552         NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
00553         ~NodeCondition() { delete mElseExp; foreach ( WhenThen* cond, mConditions ) delete cond; }
00554 
00555         virtual NodeType nodeType() const { return ntCondition; }
00556         virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
00557         virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
00558         virtual QString dump() const;
00559 
00560         virtual QStringList referencedColumns() const;
00561         virtual bool needsGeometry() const;
00562         virtual void accept( Visitor& v ) const { v.visit( *this ); }
00563 
00564       protected:
00565         WhenThenList mConditions;
00566         Node* mElseExp;
00567     };
00568 
00570 
00573     class CORE_EXPORT Visitor
00574     {
00575       public:
00576         virtual ~Visitor() {}
00577         virtual void visit( const NodeUnaryOperator& n ) = 0;
00578         virtual void visit( const NodeBinaryOperator& n ) = 0;
00579         virtual void visit( const NodeInOperator& n ) = 0;
00580         virtual void visit( const NodeFunction& n ) = 0;
00581         virtual void visit( const NodeLiteral& n ) = 0;
00582         virtual void visit( const NodeColumnRef& n ) = 0;
00583         virtual void visit( const NodeCondition& n ) = 0;
00584     };
00585 
00587     void acceptVisitor( Visitor& v ) const;
00588 
00589     static QString helptext( QString name );
00590     static QString group( QString group );
00591 
00592   protected:
00593     // internally used to create an empty expression
00594     QgsExpression() : mRootNode( NULL ), mRowNumber( 0 ) {}
00595 
00596     void initGeomCalculator();
00597 
00598     QString mExpression;
00599     Node* mRootNode;
00600 
00601     QString mParserErrorString;
00602     QString mEvalErrorString;
00603 
00604     int mRowNumber;
00605     double mScale;
00606 
00607     static QMap<QString, QVariant> gmSpecialColumns;
00608     QgsDistanceArea mCalc;
00609 
00610     friend class QgsOgcUtils;
00611 
00612     static void initFunctionHelp();
00613     static QHash<QString, QString> gFunctionHelpTexts;
00614     static QHash<QString, QString> gGroups;
00615 };
00616 
00617 Q_DECLARE_METATYPE( QgsExpression::Interval );
00618 
00619 #endif // QGSEXPRESSION_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines