|
Quantum GIS API Documentation
master-693a1fe
|
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