Quantum GIS API Documentation
1.8
|
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