QGIS API Documentation  2.6.0-Brighton
 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;
33 
34 class QDomElement;
35 
87 class CORE_EXPORT QgsExpression
88 {
89  public:
90  QgsExpression( const QString& expr );
91  ~QgsExpression();
92 
94  bool hasParserError() const { return !mParserErrorString.isNull(); }
96  QString parserErrorString() const { return mParserErrorString; }
97 
98  class Node;
99 
101  const Node* rootNode() const { return mRootNode; }
102 
104  bool prepare( const QgsFields &fields );
105 
111  QStringList referencedColumns();
112 
114  bool needsGeometry();
115 
116  // evaluation
117 
120  QVariant evaluate( const QgsFeature* f = NULL );
121 
125  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
126 
129  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
130 
134  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
135 
137  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
139  QString evalErrorString() const { return mEvalErrorString; }
141  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
142 
144  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
146  int currentRowNumber() { return mRowNumber; }
147 
149  static void setSpecialColumn( const QString& name, QVariant value );
151  static void unsetSpecialColumn( const QString& name );
153  static QVariant specialColumn( const QString& name );
156  static bool hasSpecialColumn( const QString& name );
157 
158  static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
159 
160  void setScale( double scale ) { mScale = scale; }
161 
162  double scale() { return mScale; }
163 
165  const QString expression() const { return dump(); }
166 
168  QString dump() const;
169 
172  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
173 
175  // instead of the default.
176  void setGeomCalculator( const QgsDistanceArea &calc );
177 
191  static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
192  QgsVectorLayer *layer,
193  const QMap<QString, QVariant> *substitutionMap = 0,
194  const QgsDistanceArea* distanceArea = 0
195  );
197  {
200  };
202  {
203  // logical
206 
207  // comparison
208  boEQ, // =
209  boNE, // <>
210  boLE, // <=
211  boGE, // >=
212  boLT, // <
213  boGT, // >
221 
222  // math
229 
230  // strings
232  };
234  {
244  };
245 
246  static const char* BinaryOperatorText[];
247  static const char* UnaryOperatorText[];
248 
249  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
250 
251 
255  class CORE_EXPORT Function
256  {
257  public:
258  Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList() )
259  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ), mReferencedColumns( referencedColumns ) {}
261  QString name() { return mName; }
263  int params() { return mParams; }
265  bool usesgeometry() { return mUsesGeometry; }
266 
267  virtual QStringList referencedColumns() const { return mReferencedColumns; }
268 
270  QString group() { return mGroup; }
272  QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
273 
274  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
275 
276  bool operator==( const Function& other ) const
277  {
278  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
279  return true;
280 
281  return false;
282  }
283 
284  private:
285  QString mName;
286  int mParams;
287  bool mUsesGeometry;
288  QString mGroup;
289  QString mHelpText;
290  QStringList mReferencedColumns;
291  };
292 
293  class StaticFunction : public Function
294  {
295  public:
296  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList() )
297  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns ), mFnc( fcn ) {}
298 
299  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
300  {
301  return mFnc( values, f, parent );
302  }
303 
304  private:
305  FcnEval mFnc;
306  };
307 
308  static const QList<Function*> &Functions();
309  static QList<Function*> gmFunctions;
310 
311  static QStringList gmBuiltinFunctions;
312  static const QStringList &BuiltinFunctions();
313 
314  static bool registerFunction( Function* function );
315  static bool unregisterFunction( QString name );
316 
317  // tells whether the identifier is a name of existing function
318  static bool isFunctionName( QString name );
319 
320  // return index of the function in Functions array
321  static int functionIndex( QString name );
322 
326  static int functionCount();
327 
331  static QList<Function*> specialColumns();
332 
334  static QString quotedColumnRef( QString name );
336  static QString quotedString( QString text );
337 
339 
340  class Visitor; // visitor interface is defined below
341 
342  enum NodeType
343  {
350  ntCondition
351  };
352 
353  class CORE_EXPORT Node
354  {
355  public:
356  virtual ~Node() {}
357  virtual NodeType nodeType() const = 0;
358  // abstract virtual eval function
359  // errors are reported to the parent
360  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
361 
362  // abstract virtual preparation function
363  // errors are reported to the parent
364  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
365 
366  virtual QString dump() const = 0;
367 
368  virtual QStringList referencedColumns() const = 0;
369  virtual bool needsGeometry() const = 0;
370 
371  // support for visitor pattern
372  virtual void accept( Visitor& v ) const = 0;
373  };
374 
375  class CORE_EXPORT NodeList
376  {
377  public:
378  NodeList() {}
379  virtual ~NodeList() { qDeleteAll( mList ); }
380  void append( Node* node ) { mList.append( node ); }
381  int count() { return mList.count(); }
382  QList<Node*> list() { return mList; }
383 
384  virtual QString dump() const;
385 
386  protected:
387  QList<Node*> mList;
388  };
389 
390  class CORE_EXPORT Interval
391  {
392  // YEAR const value taken from postgres query
393  // SELECT EXTRACT(EPOCH FROM interval '1 year')
394  static const int YEARS = 31557600;
395  static const int MONTHS = 60 * 60 * 24 * 30;
396  static const int WEEKS = 60 * 60 * 24 * 7;
397  static const int DAY = 60 * 60 * 24;
398  static const int HOUR = 60 * 60;
399  static const int MINUTE = 60;
400  public:
401  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
402  ~Interval();
403  double years() { return mSeconds / YEARS;}
404  double months() { return mSeconds / MONTHS; }
405  double weeks() { return mSeconds / WEEKS;}
406  double days() { return mSeconds / DAY;}
407  double hours() { return mSeconds / HOUR;}
408  double minutes() { return mSeconds / MINUTE;}
409  double seconds() { return mSeconds; }
410  bool isValid() { return mValid; }
411  void setValid( bool valid ) { mValid = valid; }
412  bool operator==( const QgsExpression::Interval& other ) const;
413  static QgsExpression::Interval invalidInterVal();
414  static QgsExpression::Interval fromString( QString string );
415  private:
416  double mSeconds;
417  bool mValid;
418  };
419 
420  class CORE_EXPORT NodeUnaryOperator : public Node
421  {
422  public:
423  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
424  ~NodeUnaryOperator() { delete mOperand; }
425 
426  UnaryOperator op() const { return mOp; }
427  Node* operand() const { return mOperand; }
428 
429  virtual NodeType nodeType() const { return ntUnaryOperator; }
430  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
431  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
432  virtual QString dump() const;
433 
434  virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
435  virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
436  virtual void accept( Visitor& v ) const { v.visit( *this ); }
437 
438  protected:
441  };
442 
443  class CORE_EXPORT NodeBinaryOperator : public Node
444  {
445  public:
446  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
447  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
448 
449  BinaryOperator op() const { return mOp; }
450  Node* opLeft() const { return mOpLeft; }
451  Node* opRight() const { return mOpRight; }
452 
453  virtual NodeType nodeType() const { return ntBinaryOperator; }
454  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
455  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
456  virtual QString dump() const;
457 
458  virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
459  virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
460  virtual void accept( Visitor& v ) const { v.visit( *this ); }
461 
462  int precedence() const;
463 
464  protected:
465  bool compare( double diff );
466  int computeInt( int x, int y );
467  double computeDouble( double x, double y );
468  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
469 
473  };
474 
475  class CORE_EXPORT NodeInOperator : public Node
476  {
477  public:
478  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
479  virtual ~NodeInOperator() { delete mNode; delete mList; }
480 
481  Node* node() const { return mNode; }
482  bool isNotIn() const { return mNotIn; }
483  NodeList* list() const { return mList; }
484 
485  virtual NodeType nodeType() const { return ntInOperator; }
486  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
487  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
488  virtual QString dump() const;
489 
490  virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
491  virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
492  virtual void accept( Visitor& v ) const { v.visit( *this ); }
493 
494  protected:
497  bool mNotIn;
498  };
499 
500  class CORE_EXPORT NodeFunction : public Node
501  {
502  public:
503  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
504  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
505  virtual ~NodeFunction() { delete mArgs; }
506 
507  int fnIndex() const { return mFnIndex; }
508  NodeList* args() const { return mArgs; }
509 
510  virtual NodeType nodeType() const { return ntFunction; }
511  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
512  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
513  virtual QString dump() const;
514 
515  virtual QStringList referencedColumns() const;
516  virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
517  virtual void accept( Visitor& v ) const { v.visit( *this ); }
518 
519  protected:
520  //QString mName;
521  int mFnIndex;
523  };
524 
525  class CORE_EXPORT NodeLiteral : public Node
526  {
527  public:
528  NodeLiteral( QVariant value ) : mValue( value ) {}
529 
530  QVariant value() const { return mValue; }
531 
532  virtual NodeType nodeType() const { return ntLiteral; }
533  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
534  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
535  virtual QString dump() const;
536 
537  virtual QStringList referencedColumns() const { return QStringList(); }
538  virtual bool needsGeometry() const { return false; }
539  virtual void accept( Visitor& v ) const { v.visit( *this ); }
540 
541  protected:
542  QVariant mValue;
543  };
544 
545  class CORE_EXPORT NodeColumnRef : public Node
546  {
547  public:
548  NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
549 
550  QString name() const { return mName; }
551 
552  virtual NodeType nodeType() const { return ntColumnRef; }
553  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
554  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
555  virtual QString dump() const;
556 
557  virtual QStringList referencedColumns() const { return QStringList( mName ); }
558  virtual bool needsGeometry() const { return false; }
559 
560  virtual void accept( Visitor& v ) const { v.visit( *this ); }
561 
562  protected:
563  QString mName;
564  int mIndex;
565  };
566 
567  class CORE_EXPORT WhenThen
568  {
569  public:
570  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
571  ~WhenThen() { delete mWhenExp; delete mThenExp; }
572 
573  //protected:
576  };
577  typedef QList<WhenThen*> WhenThenList;
578 
579  class CORE_EXPORT NodeCondition : public Node
580  {
581  public:
582  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
583  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
584 
585  virtual NodeType nodeType() const { return ntCondition; }
586  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
587  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
588  virtual QString dump() const;
589 
590  virtual QStringList referencedColumns() const;
591  virtual bool needsGeometry() const;
592  virtual void accept( Visitor& v ) const { v.visit( *this ); }
593 
594  protected:
597  };
598 
600 
603  class CORE_EXPORT Visitor
604  {
605  public:
606  virtual ~Visitor() {}
607  virtual void visit( const NodeUnaryOperator& n ) = 0;
608  virtual void visit( const NodeBinaryOperator& n ) = 0;
609  virtual void visit( const NodeInOperator& n ) = 0;
610  virtual void visit( const NodeFunction& n ) = 0;
611  virtual void visit( const NodeLiteral& n ) = 0;
612  virtual void visit( const NodeColumnRef& n ) = 0;
613  virtual void visit( const NodeCondition& n ) = 0;
614  };
615 
617  void acceptVisitor( Visitor& v ) const;
618 
619  static QString helptext( QString name );
620  static QString group( QString group );
621 
622  protected:
623  // internally used to create an empty expression
624  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mCalc( 0 ) {}
625 
626  void initGeomCalculator();
627 
629 
632 
634  double mScale;
635  QString mExp;
636 
637  static QMap<QString, QVariant> gmSpecialColumns;
638  static QMap<QString, QString> gmSpecialColumnGroups;
639 
641 
642  friend class QgsOgcUtils;
643 
644  static void initFunctionHelp();
645  static QHash<QString, QString> gFunctionHelpTexts;
646  static QHash<QString, QString> gGroups;
647 
648  private:
649  Q_DISABLE_COPY( QgsExpression ) // for now - until we have proper copy constructor / implicit sharing
650 };
651 
653 
654 #endif // QGSEXPRESSION_H