QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsexpression.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.h
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #ifndef QGSEXPRESSION_H
17 #define QGSEXPRESSION_H
18 
19 #include <QMetaType>
20 #include <QStringList>
21 #include <QVariant>
22 #include <QList>
23 #include <QDomDocument>
24 
25 #include "qgsfield.h"
26 #include "qgsdistancearea.h"
27 
28 class QgsFeature;
29 class QgsGeometry;
30 class QgsOgcUtils;
31 class QgsVectorLayer;
32 
33 class QDomElement;
34 
88 class CORE_EXPORT QgsExpression
89 {
90  public:
91  QgsExpression( const QString& expr );
92  ~QgsExpression();
93 
95  bool hasParserError() const { return !mParserErrorString.isNull(); }
97  QString parserErrorString() const { return mParserErrorString; }
98 
99  class Node;
100 
102  const Node* rootNode() const { return mRootNode; }
103 
105  bool prepare( const QgsFields& fields );
106 
108  QStringList referencedColumns();
110  bool needsGeometry();
111 
112  // evaluation
113 
116  QVariant evaluate( const QgsFeature* f = NULL );
117 
120  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
121 
124  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
125 
128  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
129 
131  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
133  QString evalErrorString() const { return mEvalErrorString; }
135  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
136 
138  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
140  int currentRowNumber() { return mRowNumber; }
141 
143  static void setSpecialColumn( const QString& name, QVariant value );
145  static void unsetSpecialColumn( const QString& name );
147  static QVariant specialColumn( const QString& name );
148 
149  void setScale( double scale ) { mScale = scale; }
150 
151  int scale() {return mScale; }
152 
153  const QString& expression() const { return mExpression; }
154 
156  QString dump() const;
157 
160  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
161 
163  // instead of the default.
164  void setGeomCalculator( QgsDistanceArea &calc );
165 
173  static QString replaceExpressionText( QString action, QgsFeature* feat,
174  QgsVectorLayer* layer,
175  const QMap<QString, QVariant> *substitutionMap = 0 );
176 
177 
178  static QString replaceExpressionText( QString action, QgsFeature& feat,
179  QgsVectorLayer* layer,
180  const QMap<QString, QVariant> *substitutionMap = 0 );
182  {
185  };
187  {
188  // logical
191 
192  // comparison
193  boEQ, // =
194  boNE, // <>
195  boLE, // <=
196  boGE, // >=
197  boLT, // <
198  boGT, // >
206 
207  // math
214 
215  // strings
217  };
219  {
229  };
230 
231  static const char* BinaryOperatorText[];
232  static const char* UnaryOperatorText[];
233 
234  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
235 
236 
240  class CORE_EXPORT Function
241  {
242  public:
243  Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false )
244  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ) {}
246  QString name() { return mName; }
248  int params() { return mParams; }
250  bool usesgeometry() { return mUsesGeometry; }
252  QString group() { return mGroup; }
254  QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
255 
256  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
257 
258  bool operator==( const Function& other ) const
259  {
260  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
261  return true;
262 
263  return false;
264  }
265 
266  private:
267  QString mName;
268  int mParams;
270  QString mGroup;
271  QString mHelpText;
272  };
273 
274  class StaticFunction : public Function
275  {
276  public:
277  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false )
278  : Function( fnname, params, group, helpText, usesGeometry ), mFnc( fcn ) {}
279 
280  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
281  {
282  return mFnc( values, f, parent );
283  }
284 
285  private:
286  FcnEval mFnc;
287  };
288 
289  const static QList<Function*> &Functions();
290  static QList<Function*> gmFunctions;
291 
292  static QStringList gmBuiltinFunctions;
293  const static QStringList &BuiltinFunctions();
294 
295  static bool registerFunction( Function* function );
296  static bool unregisterFunction( QString name );
297 
298  // tells whether the identifier is a name of existing function
299  static bool isFunctionName( QString name );
300 
301  // return index of the function in Functions array
302  static int functionIndex( QString name );
303 
307  static int functionCount();
308 
312  static QList<Function*> specialColumns();
313 
315  static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); }
317  static QString quotedString( QString text ) { return QString( "'%1'" ).arg( text.replace( "'", "''" ) ); }
318 
320 
321  class Visitor; // visitor interface is defined below
322 
323  enum NodeType
324  {
331  ntCondition
332  };
333 
334  class CORE_EXPORT Node
335  {
336  public:
337  virtual ~Node() {}
338  virtual NodeType nodeType() const = 0;
339  // abstract virtual eval function
340  // errors are reported to the parent
341  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
342 
343  // abstract virtual preparation function
344  // errors are reported to the parent
345  virtual bool prepare( QgsExpression* parent, const QgsFields& fields ) = 0;
346 
347  virtual QString dump() const = 0;
348 
349  virtual QStringList referencedColumns() const = 0;
350  virtual bool needsGeometry() const = 0;
351 
352  // support for visitor pattern
353  virtual void accept( Visitor& v ) const = 0;
354  };
355 
356  class CORE_EXPORT NodeList
357  {
358  public:
359  NodeList() {}
360  virtual ~NodeList() { foreach ( Node* n, mList ) delete n; }
361  void append( Node* node ) { mList.append( node ); }
362  int count() { return mList.count(); }
363  QList<Node*> list() { return mList; }
364 
365  virtual QString dump() const;
366 
367  protected:
368  QList<Node*> mList;
369  };
370 
371  class CORE_EXPORT Interval
372  {
373  // YEAR const value taken from postgres query
374  // SELECT EXTRACT(EPOCH FROM interval '1 year')
375  static const int YEARS = 31557600;
376  static const int MONTHS = 60 * 60 * 24 * 30;
377  static const int WEEKS = 60 * 60 * 24 * 7;
378  static const int DAY = 60 * 60 * 24;
379  static const int HOUR = 60 * 60;
380  static const int MINUTE = 60;
381  public:
382  Interval( double seconds = 0 ): mSeconds( seconds ), mValid( true ) { }
383  ~Interval();
384  double years() { return mSeconds / YEARS;}
385  double months() { return mSeconds / MONTHS; }
386  double weeks() { return mSeconds / WEEKS;}
387  double days() { return mSeconds / DAY;}
388  double hours() { return mSeconds / HOUR;}
389  double minutes() { return mSeconds / MINUTE;}
390  bool isValid() { return mValid; }
391  void setValid( bool valid ) { mValid = valid; }
392  double seconds() { return mSeconds; }
393  bool operator==( const QgsExpression::Interval& other ) const;
394  static QgsExpression::Interval invalidInterVal();
395  static QgsExpression::Interval fromString( QString string );
396  private:
397  double mSeconds;
398  bool mValid;
399  };
400 
401  class CORE_EXPORT NodeUnaryOperator : public Node
402  {
403  public:
404  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
405  ~NodeUnaryOperator() { delete mOperand; }
406 
407  UnaryOperator op() const { return mOp; }
408  Node* operand() const { return mOperand; }
409 
410  virtual NodeType nodeType() const { return ntUnaryOperator; }
411  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
412  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
413  virtual QString dump() const;
414 
415  virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
416  virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
417  virtual void accept( Visitor& v ) const { v.visit( *this ); }
418 
419  protected:
422  };
423 
424  class CORE_EXPORT NodeBinaryOperator : public Node
425  {
426  public:
427  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
428  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
429 
430  BinaryOperator op() const { return mOp; }
431  Node* opLeft() const { return mOpLeft; }
432  Node* opRight() const { return mOpRight; }
433 
434  virtual NodeType nodeType() const { return ntBinaryOperator; }
435  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
436  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
437  virtual QString dump() const;
438 
439  virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
440  virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
441  virtual void accept( Visitor& v ) const { v.visit( *this ); }
442 
443  protected:
444  bool compare( double diff );
445  int computeInt( int x, int y );
446  double computeDouble( double x, double y );
447  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
448 
452  };
453 
454  class CORE_EXPORT NodeInOperator : public Node
455  {
456  public:
457  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
458  virtual ~NodeInOperator() { delete mNode; delete mList; }
459 
460  Node* node() const { return mNode; }
461  bool isNotIn() const { return mNotIn; }
462  NodeList* list() const { return mList; }
463 
464  virtual NodeType nodeType() const { return ntInOperator; }
465  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
466  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
467  virtual QString dump() const;
468 
469  virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
470  virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
471  virtual void accept( Visitor& v ) const { v.visit( *this ); }
472 
473  protected:
476  bool mNotIn;
477  };
478 
479  class CORE_EXPORT NodeFunction : public Node
480  {
481  public:
482  NodeFunction( int fnIndex, NodeList* args ): mFnIndex( fnIndex ), mArgs( args ) {}
483  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
484  virtual ~NodeFunction() { delete mArgs; }
485 
486  int fnIndex() const { return mFnIndex; }
487  NodeList* args() const { return mArgs; }
488 
489  virtual NodeType nodeType() const { return ntFunction; }
490  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
491  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
492  virtual QString dump() const;
493 
494  virtual QStringList referencedColumns() const { QStringList lst; if ( !mArgs ) return lst; foreach ( Node* n, mArgs->list() ) lst.append( n->referencedColumns() ); return lst; }
495  virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
496  virtual void accept( Visitor& v ) const { v.visit( *this ); }
497 
498  protected:
499  //QString mName;
500  int mFnIndex;
502  };
503 
504  class CORE_EXPORT NodeLiteral : public Node
505  {
506  public:
507  NodeLiteral( QVariant value ) : mValue( value ) {}
508 
509  QVariant value() const { return mValue; }
510 
511  virtual NodeType nodeType() const { return ntLiteral; }
512  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
513  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
514  virtual QString dump() const;
515 
516  virtual QStringList referencedColumns() const { return QStringList(); }
517  virtual bool needsGeometry() const { return false; }
518  virtual void accept( Visitor& v ) const { v.visit( *this ); }
519 
520  protected:
521  QVariant mValue;
522  };
523 
524  class CORE_EXPORT NodeColumnRef : public Node
525  {
526  public:
527  NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
528 
529  QString name() const { return mName; }
530 
531  virtual NodeType nodeType() const { return ntColumnRef; }
532  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
533  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
534  virtual QString dump() const;
535 
536  virtual QStringList referencedColumns() const { return QStringList( mName ); }
537  virtual bool needsGeometry() const { return false; }
538  virtual void accept( Visitor& v ) const { v.visit( *this ); }
539 
540  protected:
541  QString mName;
542  int mIndex;
543  };
544 
545  class CORE_EXPORT WhenThen
546  {
547  public:
548  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
549  ~WhenThen() { delete mWhenExp; delete mThenExp; }
550 
551  //protected:
554  };
555  typedef QList<WhenThen*> WhenThenList;
556 
557  class CORE_EXPORT NodeCondition : public Node
558  {
559  public:
560  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
561  ~NodeCondition() { delete mElseExp; foreach ( WhenThen* cond, mConditions ) delete cond; }
562 
563  virtual NodeType nodeType() const { return ntCondition; }
564  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
565  virtual bool prepare( QgsExpression* parent, const QgsFields& fields );
566  virtual QString dump() const;
567 
568  virtual QStringList referencedColumns() const;
569  virtual bool needsGeometry() const;
570  virtual void accept( Visitor& v ) const { v.visit( *this ); }
571 
572  protected:
575  };
576 
578 
581  class CORE_EXPORT Visitor
582  {
583  public:
584  virtual ~Visitor() {}
585  virtual void visit( const NodeUnaryOperator& n ) = 0;
586  virtual void visit( const NodeBinaryOperator& n ) = 0;
587  virtual void visit( const NodeInOperator& n ) = 0;
588  virtual void visit( const NodeFunction& n ) = 0;
589  virtual void visit( const NodeLiteral& n ) = 0;
590  virtual void visit( const NodeColumnRef& n ) = 0;
591  virtual void visit( const NodeCondition& n ) = 0;
592  };
593 
595  void acceptVisitor( Visitor& v ) const;
596 
597  static QString helptext( QString name );
598  static QString group( QString group );
599 
600  protected:
601  // internally used to create an empty expression
602  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mCalc( 0 ) {}
603 
604  void initGeomCalculator();
605 
606  QString mExpression;
608 
611 
613  double mScale;
614 
615  static QMap<QString, QVariant> gmSpecialColumns;
617 
618  friend class QgsOgcUtils;
619 
620  static void initFunctionHelp();
621  static QHash<QString, QString> gFunctionHelpTexts;
622  static QHash<QString, QString> gGroups;
623 };
624 
626 
627 #endif // QGSEXPRESSION_H