Skip to content

Commit 06e3c72

Browse files
committed
Expressions: support for visitor pattern, expresion->OGCFilter now a visitor
1 parent 9509999 commit 06e3c72

File tree

8 files changed

+413
-111
lines changed

8 files changed

+413
-111
lines changed

python/core/qgsexpression.sip

Lines changed: 224 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,231 @@ public:
5151
//! (used by internal functions)
5252
QgsDistanceArea* geomCalculator();
5353

54-
//
54+
//
5555

56-
// tells whether the identifier is a name of existing function
57-
static bool isFunctionName( QString name );
56+
enum UnaryOperator
57+
{
58+
uoNot,
59+
uoMinus,
60+
};
61+
enum BinaryOperator
62+
{
63+
// logical
64+
boOr,
65+
boAnd,
5866

59-
// return index of the function in BuiltinFunctions array
60-
static int functionIndex( QString name );
67+
// comparison
68+
boEQ, // =
69+
boNE, // <>
70+
boLE, // <=
71+
boGE, // >=
72+
boLT, // <
73+
boGT, // >
74+
boRegexp,
75+
boLike,
76+
boILike,
77+
boIs,
78+
boIsNot,
79+
80+
// math
81+
boPlus,
82+
boMinus,
83+
boMul,
84+
boDiv,
85+
boMod,
86+
boPow,
87+
88+
// strings
89+
boConcat,
90+
};
91+
92+
93+
struct FunctionDef /NoDefaultCtors/
94+
{
95+
//FunctionDef( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false );
96+
/** The name of the function. */
97+
QString mName;
98+
/** The number of parameters this function takes. */
99+
int mParams;
100+
/** Pointer to fucntion. */
101+
//FcnEval mFcn;
102+
/** Does this function use a geometry object. */
103+
bool mUsesGeometry;
104+
/** The group the function belongs to. */
105+
QString mGroup;
106+
/** The help text for the function. */
107+
QString mHelpText;
108+
};
109+
110+
static const QList<QgsExpression::FunctionDef> &BuiltinFunctions();
111+
112+
// tells whether the identifier is a name of existing function
113+
static bool isFunctionName( QString name );
114+
115+
// return index of the function in BuiltinFunctions array
116+
static int functionIndex( QString name );
117+
118+
/** Returns the number of functions defined in the parser
119+
* @return The number of function defined in the parser.
120+
*/
121+
static int functionCount();
122+
123+
//! return quoted column reference (in double quotes)
124+
static QString quotedColumnRef( QString name );
125+
126+
//////
127+
128+
class Node
129+
{
130+
public:
131+
virtual ~Node();
132+
// abstract virtual eval function
133+
// errors are reported to the parent
134+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f ) = 0;
135+
136+
// abstract virtual preparation function
137+
// errors are reported to the parent
138+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields ) = 0;
139+
140+
virtual QString dump() const = 0;
141+
142+
virtual QStringList referencedColumns() const = 0;
143+
virtual bool needsGeometry() const = 0;
144+
145+
// support for visitor pattern
146+
virtual void accept( QgsExpression::Visitor& v ) = 0;
147+
};
148+
149+
class NodeList
150+
{
151+
public:
152+
NodeList();
153+
~NodeList();
154+
void append( QgsExpression::Node* node );
155+
int count();
156+
QList<QgsExpression::Node*> list();
157+
158+
virtual QString dump() const;
159+
};
160+
161+
class NodeUnaryOperator : QgsExpression::Node
162+
{
163+
public:
164+
NodeUnaryOperator( QgsExpression::UnaryOperator op, QgsExpression::Node* operand );
165+
~NodeUnaryOperator();
166+
167+
QgsExpression::UnaryOperator op();
168+
QgsExpression::Node* operand();
169+
170+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
171+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
172+
virtual QString dump() const;
173+
virtual QStringList referencedColumns() const;
174+
virtual bool needsGeometry() const;
175+
virtual void accept( QgsExpression::Visitor& v );
176+
};
177+
178+
class NodeBinaryOperator : QgsExpression::Node
179+
{
180+
public:
181+
NodeBinaryOperator( QgsExpression::BinaryOperator op, QgsExpression::Node* opLeft, QgsExpression::Node* opRight );
182+
~NodeBinaryOperator();
183+
184+
QgsExpression::BinaryOperator op();
185+
QgsExpression::Node* opLeft();
186+
QgsExpression::Node* opRight();
187+
188+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
189+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
190+
virtual QString dump() const;
191+
virtual QStringList referencedColumns() const;
192+
virtual bool needsGeometry() const;
193+
virtual void accept( QgsExpression::Visitor& v );
194+
};
195+
196+
class NodeInOperator : QgsExpression::Node
197+
{
198+
public:
199+
NodeInOperator( QgsExpression::Node* node, QgsExpression::NodeList* list, bool notin = false );
200+
~NodeInOperator();
201+
202+
QgsExpression::Node* node();
203+
bool isNotIn();
204+
QgsExpression::NodeList* list();
205+
206+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
207+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
208+
virtual QString dump() const;
209+
virtual QStringList referencedColumns() const;
210+
virtual bool needsGeometry() const;
211+
virtual void accept( QgsExpression::Visitor& v );
212+
};
213+
214+
class NodeFunction : QgsExpression::Node
215+
{
216+
public:
217+
NodeFunction( int fnIndex, QgsExpression::NodeList* args );
218+
//NodeFunction( QString name, QgsExpression::NodeList* args );
219+
~NodeFunction();
220+
221+
int fnIndex();
222+
QgsExpression::NodeList* args();
223+
224+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
225+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
226+
virtual QString dump() const;
227+
virtual QStringList referencedColumns() const;
228+
virtual bool needsGeometry() const;
229+
virtual void accept( QgsExpression::Visitor& v );
230+
};
231+
232+
class NodeLiteral : QgsExpression::Node
233+
{
234+
public:
235+
NodeLiteral( QVariant value );
236+
237+
QVariant value();
238+
239+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
240+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
241+
virtual QString dump() const;
242+
virtual QStringList referencedColumns() const;
243+
virtual bool needsGeometry() const;
244+
virtual void accept( QgsExpression::Visitor& v );
245+
};
246+
247+
class NodeColumnRef : QgsExpression::Node
248+
{
249+
public:
250+
NodeColumnRef( QString name );
251+
252+
QString name();
253+
254+
virtual bool prepare( QgsExpression* parent, const QgsFieldMap& fields );
255+
virtual QVariant eval( QgsExpression* parent, QgsFeature* f );
256+
virtual QString dump() const;
257+
virtual QStringList referencedColumns() const;
258+
virtual bool needsGeometry() const;
259+
virtual void accept( QgsExpression::Visitor& v );
260+
};
261+
262+
//////
263+
264+
/** support for visitor pattern - algorithms dealing with the expressions
265+
may be implemented without modifying the Node classes */
266+
class Visitor
267+
{
268+
public:
269+
virtual ~Visitor();
270+
virtual void visit( QgsExpression::NodeUnaryOperator* n ) = 0;
271+
virtual void visit( QgsExpression::NodeBinaryOperator* n ) = 0;
272+
virtual void visit( QgsExpression::NodeInOperator* n ) = 0;
273+
virtual void visit( QgsExpression::NodeFunction* n ) = 0;
274+
virtual void visit( QgsExpression::NodeLiteral* n ) = 0;
275+
virtual void visit( QgsExpression::NodeColumnRef* n ) = 0;
276+
};
277+
278+
/** entry function for the visitor pattern */
279+
void acceptVisitor( QgsExpression::Visitor& v );
61280

62-
//! return quoted column reference (in double quotes)
63-
static QString quotedColumnRef( QString name );
64281
};

src/core/qgsexpression.cpp

Lines changed: 6 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ QString QgsExpression::dump() const
541541
return mRootNode->dump();
542542
}
543543

544+
void QgsExpression::acceptVisitor( QgsExpression::Visitor& v )
545+
{
546+
if ( mRootNode )
547+
mRootNode->accept( v );
548+
}
549+
544550

545551
///////////////////////////////////////////////
546552
// nodes
@@ -969,97 +975,3 @@ QString QgsExpression::NodeColumnRef::dump() const
969975
{
970976
return mName;
971977
}
972-
973-
bool QgsExpression::toOGCFilter( QDomDocument& doc ) const
974-
{
975-
if ( !mRootNode )
976-
{
977-
return false;
978-
}
979-
980-
doc.clear();
981-
QDomElement filterElem = doc.createElement( "Filter" );
982-
doc.appendChild( filterElem );
983-
return mRootNode->toOGCFilter( doc, filterElem );
984-
}
985-
986-
bool QgsExpression::NodeBinaryOperator::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
987-
{
988-
QDomElement opElem;
989-
switch ( mOp )
990-
{
991-
case boEQ:
992-
opElem = doc.createElement( "PropertyIsEqualTo" );
993-
break;
994-
case boNE:
995-
opElem = doc.createElement( "PropertyIsNotEqualTo" );
996-
break;
997-
case boLE:
998-
opElem = doc.createElement( "PropertyIsLessThanOrEqualTo" );
999-
break;
1000-
case boGE:
1001-
opElem = doc.createElement( "PropertyIsLessThanOrEqualTo" );
1002-
break;
1003-
case boLT:
1004-
opElem = doc.createElement( "PropertyIsLessThan" );
1005-
break;
1006-
case boGT:
1007-
opElem = doc.createElement( "PropertyIsGreaterThan" );
1008-
break;
1009-
case boOr:
1010-
opElem = doc.createElement( "Or" );
1011-
break;
1012-
case boAnd:
1013-
opElem = doc.createElement( "And" );
1014-
break;
1015-
default:
1016-
return false;
1017-
}
1018-
1019-
if ( mOpLeft )
1020-
{
1021-
mOpLeft->toOGCFilter( doc, opElem );
1022-
}
1023-
if ( mOpRight )
1024-
{
1025-
mOpRight->toOGCFilter( doc, opElem );
1026-
}
1027-
1028-
parent.appendChild( opElem );
1029-
return true;
1030-
}
1031-
1032-
bool QgsExpression::NodeLiteral::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
1033-
{
1034-
QDomElement literalElem = doc.createElement( "Literal" );
1035-
QDomText literalText = doc.createTextNode( mValue.toString() );
1036-
literalElem.appendChild( literalText );
1037-
parent.appendChild( literalElem );
1038-
return true;
1039-
}
1040-
1041-
bool QgsExpression::NodeColumnRef::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
1042-
{
1043-
QDomElement propertyElem = doc.createElement( "PropertyName" );
1044-
QDomText propertyText = doc.createTextNode( mName );
1045-
propertyElem.appendChild( propertyText );
1046-
parent.appendChild( propertyElem );
1047-
return true;
1048-
}
1049-
1050-
bool QgsExpression::NodeUnaryOperator::toOGCFilter( QDomDocument& doc, QDomElement& parent ) const
1051-
{
1052-
if ( mOp == uoNot )
1053-
{
1054-
QDomElement notElem = doc.createElement( "Not" );
1055-
if ( mOperand )
1056-
{
1057-
if ( mOperand->toOGCFilter( doc, notElem ) )
1058-
{
1059-
parent.appendChild( notElem );
1060-
return true;
1061-
}
1062-
}
1063-
}
1064-
return false;
1065-
}

0 commit comments

Comments
 (0)