QGIS API Documentation  2.2.0-Valmiera
 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 
89 class CORE_EXPORT QgsExpression
90 {
91  public:
92  QgsExpression( const QString& expr );
93  ~QgsExpression();
94 
96  bool hasParserError() const { return !mParserErrorString.isNull(); }
98  QString parserErrorString() const { return mParserErrorString; }
99 
100  class Node;
101 
103  const Node* rootNode() const { return mRootNode; }
104 
106  bool prepare( const QgsFields &fields );
107 
109  QStringList referencedColumns();
111  bool needsGeometry();
112 
113  // evaluation
114 
117  QVariant evaluate( const QgsFeature* f = NULL );
118 
122  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
123 
126  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
127 
130  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
131 
133  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
135  QString evalErrorString() const { return mEvalErrorString; }
137  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
138 
140  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
142  int currentRowNumber() { return mRowNumber; }
143 
145  static void setSpecialColumn( const QString& name, QVariant value );
147  static void unsetSpecialColumn( const QString& name );
149  static QVariant specialColumn( const QString& name );
152  static bool hasSpecialColumn( const QString& name );
153 
154  void setScale( double scale ) { mScale = scale; }
155 
156  int scale() {return mScale; }
157 
159  const QString expression() const { return dump(); }
160 
162  QString dump() const;
163 
166  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
167 
169  // instead of the default.
170  void setGeomCalculator( const QgsDistanceArea &calc );
171 
179  static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
180  QgsVectorLayer *layer,
181  const QMap<QString, QVariant> *substitutionMap = 0 );
183  {
186  };
188  {
189  // logical
192 
193  // comparison
194  boEQ, // =
195  boNE, // <>
196  boLE, // <=
197  boGE, // >=
198  boLT, // <
199  boGT, // >
207 
208  // math
215 
216  // strings
218  };
220  {
230  };
231 
232  static const char* BinaryOperatorText[];
233  static const char* UnaryOperatorText[];
234 
235  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
236 
237 
241  class CORE_EXPORT Function
242  {
243  public:
244  Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false )
245  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ) {}
247  QString name() { return mName; }
249  int params() { return mParams; }
251  bool usesgeometry() { return mUsesGeometry; }
253  QString group() { return mGroup; }
255  QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
256 
257  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
258 
259  bool operator==( const Function& other ) const
260  {
261  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
262  return true;
263 
264  return false;
265  }
266 
267  private:
268  QString mName;
269  int mParams;
271  QString mGroup;
272  QString mHelpText;
273  };
274 
275  class StaticFunction : public Function
276  {
277  public:
278  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false )
279  : Function( fnname, params, group, helpText, usesGeometry ), mFnc( fcn ) {}
280 
281  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent )
282  {
283  return mFnc( values, f, parent );
284  }
285 
286  private:
287  FcnEval mFnc;
288  };
289 
290  static const QList<Function*> &Functions();
291  static QList<Function*> gmFunctions;
292 
293  static QStringList gmBuiltinFunctions;
294  static const QStringList &BuiltinFunctions();
295 
296  static bool registerFunction( Function* function );
297  static bool unregisterFunction( QString name );
298 
299  // tells whether the identifier is a name of existing function
300  static bool isFunctionName( QString name );
301 
302  // return index of the function in Functions array
303  static int functionIndex( QString name );
304 
308  static int functionCount();
309 
313  static QList<Function*> specialColumns();
314 
316  static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); }
318  static QString quotedString( QString text ) { return QString( "'%1'" ).arg( text.replace( "'", "''" ) ); }
319 
321 
322  class Visitor; // visitor interface is defined below
323 
324  enum NodeType
325  {
332  ntCondition
333  };
334 
335  class CORE_EXPORT Node
336  {
337  public:
338  virtual ~Node() {}
339  virtual NodeType nodeType() const = 0;
340  // abstract virtual eval function
341  // errors are reported to the parent
342  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
343 
344  // abstract virtual preparation function
345  // errors are reported to the parent
346  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
347 
348  virtual QString dump() const = 0;
349 
350  virtual QStringList referencedColumns() const = 0;
351  virtual bool needsGeometry() const = 0;
352 
353  // support for visitor pattern
354  virtual void accept( Visitor& v ) const = 0;
355  };
356 
357  class CORE_EXPORT NodeList
358  {
359  public:
360  NodeList() {}
361  virtual ~NodeList() { qDeleteAll( mList ); }
362  void append( Node* node ) { mList.append( node ); }
363  int count() { return mList.count(); }
364  QList<Node*> list() { return mList; }
365 
366  virtual QString dump() const;
367 
368  protected:
369  QList<Node*> mList;
370  };
371 
372  class CORE_EXPORT Interval
373  {
374  // YEAR const value taken from postgres query
375  // SELECT EXTRACT(EPOCH FROM interval '1 year')
376  static const int YEARS = 31557600;
377  static const int MONTHS = 60 * 60 * 24 * 30;
378  static const int WEEKS = 60 * 60 * 24 * 7;
379  static const int DAY = 60 * 60 * 24;
380  static const int HOUR = 60 * 60;
381  static const int MINUTE = 60;
382  public:
383  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
384  ~Interval();
385  double years() { return mSeconds / YEARS;}
386  double months() { return mSeconds / MONTHS; }
387  double weeks() { return mSeconds / WEEKS;}
388  double days() { return mSeconds / DAY;}
389  double hours() { return mSeconds / HOUR;}
390  double minutes() { return mSeconds / MINUTE;}
391  double seconds() { return mSeconds; }
392  bool isValid() { return mValid; }
393  void setValid( bool valid ) { mValid = valid; }
394  bool operator==( const QgsExpression::Interval& other ) const;
395  static QgsExpression::Interval invalidInterVal();
396  static QgsExpression::Interval fromString( QString string );
397  private:
398  double mSeconds;
399  bool mValid;
400  };
401 
402  class CORE_EXPORT NodeUnaryOperator : public Node
403  {
404  public:
405  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
406  ~NodeUnaryOperator() { delete mOperand; }
407 
408  UnaryOperator op() const { return mOp; }
409  Node* operand() const { return mOperand; }
410 
411  virtual NodeType nodeType() const { return ntUnaryOperator; }
412  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
413  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
414  virtual QString dump() const;
415 
416  virtual QStringList referencedColumns() const { return mOperand->referencedColumns(); }
417  virtual bool needsGeometry() const { return mOperand->needsGeometry(); }
418  virtual void accept( Visitor& v ) const { v.visit( *this ); }
419 
420  protected:
423  };
424 
425  class CORE_EXPORT NodeBinaryOperator : public Node
426  {
427  public:
428  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
429  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
430 
431  BinaryOperator op() const { return mOp; }
432  Node* opLeft() const { return mOpLeft; }
433  Node* opRight() const { return mOpRight; }
434 
435  virtual NodeType nodeType() const { return ntBinaryOperator; }
436  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
437  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
438  virtual QString dump() const;
439 
440  virtual QStringList referencedColumns() const { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
441  virtual bool needsGeometry() const { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
442  virtual void accept( Visitor& v ) const { v.visit( *this ); }
443 
444  protected:
445  bool compare( double diff );
446  int computeInt( int x, int y );
447  double computeDouble( double x, double y );
448  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
449 
453  };
454 
455  class CORE_EXPORT NodeInOperator : public Node
456  {
457  public:
458  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
459  virtual ~NodeInOperator() { delete mNode; delete mList; }
460 
461  Node* node() const { return mNode; }
462  bool isNotIn() const { return mNotIn; }
463  NodeList* list() const { return mList; }
464 
465  virtual NodeType nodeType() const { return ntInOperator; }
466  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
467  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
468  virtual QString dump() const;
469 
470  virtual QStringList referencedColumns() const { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
471  virtual bool needsGeometry() const { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
472  virtual void accept( Visitor& v ) const { v.visit( *this ); }
473 
474  protected:
477  bool mNotIn;
478  };
479 
480  class CORE_EXPORT NodeFunction : public Node
481  {
482  public:
483  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
484  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
485  virtual ~NodeFunction() { delete mArgs; }
486 
487  int fnIndex() const { return mFnIndex; }
488  NodeList* args() const { return mArgs; }
489 
490  virtual NodeType nodeType() const { return ntFunction; }
491  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
492  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
493  virtual QString dump() const;
494 
495  virtual QStringList referencedColumns() const { QStringList lst; if ( !mArgs ) return lst; foreach ( Node* n, mArgs->list() ) lst.append( n->referencedColumns() ); return lst; }
496  virtual bool needsGeometry() const { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
497  virtual void accept( Visitor& v ) const { v.visit( *this ); }
498 
499  protected:
500  //QString mName;
501  int mFnIndex;
503  };
504 
505  class CORE_EXPORT NodeLiteral : public Node
506  {
507  public:
508  NodeLiteral( QVariant value ) : mValue( value ) {}
509 
510  QVariant value() const { return mValue; }
511 
512  virtual NodeType nodeType() const { return ntLiteral; }
513  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
514  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
515  virtual QString dump() const;
516 
517  virtual QStringList referencedColumns() const { return QStringList(); }
518  virtual bool needsGeometry() const { return false; }
519  virtual void accept( Visitor& v ) const { v.visit( *this ); }
520 
521  protected:
522  QVariant mValue;
523  };
524 
525  class CORE_EXPORT NodeColumnRef : public Node
526  {
527  public:
528  NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
529 
530  QString name() const { return mName; }
531 
532  virtual NodeType nodeType() const { return ntColumnRef; }
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( mName ); }
538  virtual bool needsGeometry() const { return false; }
539 
540  virtual void accept( Visitor& v ) const { v.visit( *this ); }
541 
542  protected:
543  QString mName;
544  int mIndex;
545  };
546 
547  class CORE_EXPORT WhenThen
548  {
549  public:
550  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
551  ~WhenThen() { delete mWhenExp; delete mThenExp; }
552 
553  //protected:
556  };
557  typedef QList<WhenThen*> WhenThenList;
558 
559  class CORE_EXPORT NodeCondition : public Node
560  {
561  public:
562  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
563  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
564 
565  virtual NodeType nodeType() const { return ntCondition; }
566  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
567  virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
568  virtual QString dump() const;
569 
570  virtual QStringList referencedColumns() const;
571  virtual bool needsGeometry() const;
572  virtual void accept( Visitor& v ) const { v.visit( *this ); }
573 
574  protected:
577  };
578 
580 
583  class CORE_EXPORT Visitor
584  {
585  public:
586  virtual ~Visitor() {}
587  virtual void visit( const NodeUnaryOperator& n ) = 0;
588  virtual void visit( const NodeBinaryOperator& n ) = 0;
589  virtual void visit( const NodeInOperator& n ) = 0;
590  virtual void visit( const NodeFunction& n ) = 0;
591  virtual void visit( const NodeLiteral& n ) = 0;
592  virtual void visit( const NodeColumnRef& n ) = 0;
593  virtual void visit( const NodeCondition& n ) = 0;
594  };
595 
597  void acceptVisitor( Visitor& v ) const;
598 
599  static QString helptext( QString name );
600  static QString group( QString group );
601 
602  protected:
603  // internally used to create an empty expression
604  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mCalc( 0 ) {}
605 
606  void initGeomCalculator();
607 
609 
612 
614  double mScale;
615  QString mExp;
616 
617  static QMap<QString, QVariant> gmSpecialColumns;
619 
620  friend class QgsOgcUtils;
621 
622  static void initFunctionHelp();
623  static QHash<QString, QString> gFunctionHelpTexts;
624  static QHash<QString, QString> gGroups;
625 };
626 
628 
629 #endif // QGSEXPRESSION_H