00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "qgsexpression.h"
00017
00018 #include <QtDebug>
00019 #include <QDomDocument>
00020 #include <QSettings>
00021
00022 #include <math.h>
00023 #include <limits>
00024
00025 #include "qgsdistancearea.h"
00026 #include "qgsfeature.h"
00027 #include "qgsgeometry.h"
00028 #include "qgslogger.h"
00029
00030
00031 extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
00032
00033
00035
00036
00037 enum TVL
00038 {
00039 False,
00040 True,
00041 Unknown
00042 };
00043
00044 static TVL AND[3][3] =
00045 {
00046
00047 { False, False, False },
00048 { False, True, Unknown },
00049 { False, Unknown, Unknown }
00050 };
00051
00052 static TVL OR[3][3] =
00053 {
00054 { False, True, Unknown },
00055 { True, True, True },
00056 { Unknown, True, Unknown }
00057 };
00058
00059 static TVL NOT[3] = { True, False, Unknown };
00060
00061 static QVariant tvl2variant( TVL v )
00062 {
00063 switch ( v )
00064 {
00065 case False: return 0;
00066 case True: return 1;
00067 case Unknown:
00068 default:
00069 return QVariant();
00070 }
00071 }
00072
00073 #define TVL_True QVariant(1)
00074 #define TVL_False QVariant(0)
00075 #define TVL_Unknown QVariant()
00076
00078
00079
00080 inline bool isIntSafe( const QVariant& v )
00081 {
00082 if ( v.type() == QVariant::Int ) return true;
00083 if ( v.type() == QVariant::Double ) return false;
00084 if ( v.type() == QVariant::String ) { bool ok; v.toString().toInt( &ok ); return ok; }
00085 return false;
00086 }
00087 inline bool isDoubleSafe( const QVariant& v )
00088 {
00089 if ( v.type() == QVariant::Double || v.type() == QVariant::Int ) return true;
00090 if ( v.type() == QVariant::String ) { bool ok; v.toString().toDouble( &ok ); return ok; }
00091 return false;
00092 }
00093
00094 inline bool isNull( const QVariant& v ) { return v.isNull(); }
00095
00097
00098
00099 #define ENSURE_NO_EVAL_ERROR { if (parent->hasEvalError()) return QVariant(); }
00100 #define SET_EVAL_ERROR(x) { parent->setEvalErrorString(x); return QVariant(); }
00101
00103
00104
00105 const char* QgsExpression::BinaryOperatorText[] =
00106 {
00107 "OR", "AND",
00108 "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
00109 "+", "-", "*", "/", "%", "^",
00110 "||"
00111 };
00112
00113 const char* QgsExpression::BinaryOgcOperatorText[] =
00114 {
00115 "Or", "And",
00116 "PropertyIsEqualTo", "PropertyIsNotEqualTo",
00117 "PropertyIsGreaterThanOrEqualTo", "PropertyIsLessThanOrEqualTo",
00118 "PropertyIsLessThan", "PropertyIsGreaterThan",
00119 "", "PropertyIsLike", "", "", "",
00120 "Add", "Sub", "Mul", "Div", "", "",
00121 ""
00122 };
00123
00124 const char* QgsExpression::UnaryOperatorText[] =
00125 {
00126 "NOT", "-"
00127 };
00128
00129 const char* QgsExpression::UnaryOgcOperatorText[] =
00130 {
00131 "Not", ""
00132 };
00133
00135
00136
00137
00138 static QString getStringValue( const QVariant& value, QgsExpression* )
00139 {
00140 return value.toString();
00141 }
00142
00143 static double getDoubleValue( const QVariant& value, QgsExpression* parent )
00144 {
00145 bool ok;
00146 double x = value.toDouble( &ok );
00147 if ( !ok )
00148 {
00149 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to double" ).arg( value.toString() ) );
00150 return 0;
00151 }
00152 return x;
00153 }
00154
00155 static int getIntValue( const QVariant& value, QgsExpression* parent )
00156 {
00157 bool ok;
00158 qint64 x = value.toLongLong( &ok );
00159 if ( ok && x >= std::numeric_limits<int>::min() && x <= std::numeric_limits<int>::max() )
00160 {
00161 return x;
00162 }
00163 else
00164 {
00165 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to int" ).arg( value.toString() ) );
00166 return 0;
00167 }
00168 }
00169
00170
00171
00172 static TVL getTVLValue( const QVariant& value, QgsExpression* parent )
00173 {
00174
00175 if ( value.isNull() )
00176 return Unknown;
00177
00178 if ( value.type() == QVariant::Int )
00179 return value.toInt() != 0 ? True : False;
00180
00181 bool ok;
00182 double x = value.toDouble( &ok );
00183 if ( !ok )
00184 {
00185 parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to boolean" ).arg( value.toString() ) );
00186 return Unknown;
00187 }
00188 return x != 0 ? True : False;
00189 }
00190
00192
00193 static QVariant fcnSqrt( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00194 {
00195 double x = getDoubleValue( values.at( 0 ), parent );
00196 return QVariant( sqrt( x ) );
00197 }
00198 static QVariant fcnSin( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00199 {
00200 double x = getDoubleValue( values.at( 0 ), parent );
00201 return QVariant( sin( x ) );
00202 }
00203 static QVariant fcnCos( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00204 {
00205 double x = getDoubleValue( values.at( 0 ), parent );
00206 return QVariant( cos( x ) );
00207 }
00208 static QVariant fcnTan( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00209 {
00210 double x = getDoubleValue( values.at( 0 ), parent );
00211 return QVariant( tan( x ) );
00212 }
00213 static QVariant fcnAsin( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00214 {
00215 double x = getDoubleValue( values.at( 0 ), parent );
00216 return QVariant( asin( x ) );
00217 }
00218 static QVariant fcnAcos( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00219 {
00220 double x = getDoubleValue( values.at( 0 ), parent );
00221 return QVariant( acos( x ) );
00222 }
00223 static QVariant fcnAtan( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00224 {
00225 double x = getDoubleValue( values.at( 0 ), parent );
00226 return QVariant( atan( x ) );
00227 }
00228 static QVariant fcnAtan2( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00229 {
00230 double y = getDoubleValue( values.at( 0 ), parent );
00231 double x = getDoubleValue( values.at( 1 ), parent );
00232 return QVariant( atan2( y, x ) );
00233 }
00234 static QVariant fcnExp( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00235 {
00236 double x = getDoubleValue( values.at( 0 ), parent );
00237 return QVariant( exp( x ) );
00238 }
00239 static QVariant fcnLn( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00240 {
00241 double x = getDoubleValue( values.at( 0 ), parent );
00242 if ( x <= 0 )
00243 return QVariant();
00244 return QVariant( log( x ) );
00245 }
00246 static QVariant fcnLog10( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00247 {
00248 double x = getDoubleValue( values.at( 0 ), parent );
00249 if ( x <= 0 )
00250 return QVariant();
00251 return QVariant( log10( x ) );
00252 }
00253 static QVariant fcnLog( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00254 {
00255 double b = getDoubleValue( values.at( 0 ), parent );
00256 double x = getDoubleValue( values.at( 1 ), parent );
00257 if ( x <= 0 || b <= 0 )
00258 return QVariant();
00259 return QVariant( log( x ) / log( b ) );
00260 }
00261 static QVariant fcnToInt( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00262 {
00263 return QVariant( getIntValue( values.at( 0 ), parent ) );
00264 }
00265 static QVariant fcnToReal( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00266 {
00267 return QVariant( getDoubleValue( values.at( 0 ), parent ) );
00268 }
00269 static QVariant fcnToString( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00270 {
00271 return QVariant( getStringValue( values.at( 0 ), parent ) );
00272 }
00273 static QVariant fcnLower( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00274 {
00275 QString str = getStringValue( values.at( 0 ), parent );
00276 return QVariant( str.toLower() );
00277 }
00278 static QVariant fcnUpper( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00279 {
00280 QString str = getStringValue( values.at( 0 ), parent );
00281 return QVariant( str.toUpper() );
00282 }
00283 static QVariant fcnLength( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00284 {
00285 QString str = getStringValue( values.at( 0 ), parent );
00286 return QVariant( str.length() );
00287 }
00288 static QVariant fcnReplace( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00289 {
00290 QString str = getStringValue( values.at( 0 ), parent );
00291 QString before = getStringValue( values.at( 1 ), parent );
00292 QString after = getStringValue( values.at( 2 ), parent );
00293 return QVariant( str.replace( before, after ) );
00294 }
00295 static QVariant fcnRegexpReplace( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00296 {
00297 QString str = getStringValue( values.at( 0 ), parent );
00298 QString regexp = getStringValue( values.at( 1 ), parent );
00299 QString after = getStringValue( values.at( 2 ), parent );
00300
00301 QRegExp re( regexp );
00302 if ( !re.isValid() )
00303 {
00304 parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp ).arg( re.errorString() ) );
00305 return QVariant();
00306 }
00307 return QVariant( str.replace( re, after ) );
00308 }
00309 static QVariant fcnSubstr( const QVariantList& values, QgsFeature* , QgsExpression* parent )
00310 {
00311 QString str = getStringValue( values.at( 0 ), parent );
00312 int from = getIntValue( values.at( 1 ), parent );
00313 int len = getIntValue( values.at( 2 ), parent );
00314 return QVariant( str.mid( from -1, len ) );
00315 }
00316
00317 static QVariant fcnRowNumber( const QVariantList& , QgsFeature* , QgsExpression* parent )
00318 {
00319 return QVariant( parent->currentRowNumber() );
00320 }
00321
00322 static QVariant fcnFeatureId( const QVariantList& , QgsFeature* f, QgsExpression* )
00323 {
00324
00325 return f ? QVariant(( int )f->id() ) : QVariant();
00326 }
00327
00328 #define ENSURE_GEOM_TYPE(f, g, geomtype) if (!f) return QVariant(); \
00329 QgsGeometry* g = f->geometry(); \
00330 if (!g || g->type() != geomtype) return QVariant();
00331
00332
00333 static QVariant fcnX( const QVariantList& , QgsFeature* f, QgsExpression* )
00334 {
00335 ENSURE_GEOM_TYPE( f, g, QGis::Point );
00336 if ( g->isMultipart() )
00337 {
00338 return g->asMultiPoint()[ 0 ].x();
00339 }
00340 else
00341 {
00342 return g->asPoint().x();
00343 }
00344 }
00345 static QVariant fcnY( const QVariantList& , QgsFeature* f, QgsExpression* )
00346 {
00347 ENSURE_GEOM_TYPE( f, g, QGis::Point );
00348 if ( g->isMultipart() )
00349 {
00350 return g->asMultiPoint()[ 0 ].y();
00351 }
00352 else
00353 {
00354 return g->asPoint().y();
00355 }
00356 }
00357
00358 static QVariant pointAt( const QVariantList& values, QgsFeature* f, QgsExpression* parent )
00359 {
00360 int idx = getIntValue( values.at( 0 ), parent );
00361 ENSURE_GEOM_TYPE( f, g, QGis::Line );
00362 QgsPolyline polyline = g->asPolyline();
00363 if ( idx < 0 )
00364 idx += polyline.count();
00365
00366 if ( idx < 0 || idx >= polyline.count() )
00367 {
00368 parent->setEvalErrorString( QObject::tr( "Index is out of range" ) );
00369 return QVariant();
00370 }
00371 return QVariant( QPointF( polyline[idx].x(), polyline[idx].y() ) );
00372 }
00373
00374 static QVariant fcnXat( const QVariantList& values, QgsFeature* f, QgsExpression* parent )
00375 {
00376 QVariant v = pointAt( values, f, parent );
00377 if ( v.type() == QVariant::PointF )
00378 return QVariant( v.toPointF().x() );
00379 else
00380 return QVariant();
00381 }
00382 static QVariant fcnYat( const QVariantList& values, QgsFeature* f, QgsExpression* parent )
00383 {
00384 QVariant v = pointAt( values, f, parent );
00385 if ( v.type() == QVariant::PointF )
00386 return QVariant( v.toPointF().y() );
00387 else
00388 return QVariant();
00389 }
00390
00391 static QVariant fcnGeomArea( const QVariantList& , QgsFeature* f, QgsExpression* parent )
00392 {
00393 ENSURE_GEOM_TYPE( f, g, QGis::Polygon );
00394 QgsDistanceArea* calc = parent->geomCalculator();
00395 return QVariant( calc->measure( f->geometry() ) );
00396 }
00397 static QVariant fcnGeomLength( const QVariantList& , QgsFeature* f, QgsExpression* parent )
00398 {
00399 ENSURE_GEOM_TYPE( f, g, QGis::Line );
00400 QgsDistanceArea* calc = parent->geomCalculator();
00401 return QVariant( calc->measure( f->geometry() ) );
00402 }
00403 static QVariant fcnGeomPerimeter( const QVariantList& , QgsFeature* f, QgsExpression* parent )
00404 {
00405 ENSURE_GEOM_TYPE( f, g, QGis::Polygon );
00406 QgsDistanceArea* calc = parent->geomCalculator();
00407 return QVariant( calc->measurePerimeter( f->geometry() ) );
00408 }
00409
00410 QList<QgsExpression::FunctionDef> QgsExpression::gmBuiltinFunctions;
00411
00412 const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
00413 {
00414 if ( gmBuiltinFunctions.isEmpty() )
00415 {
00416
00417 gmBuiltinFunctions
00418 << FunctionDef( "sqrt", 1, fcnSqrt, QObject::tr( "Math" ) )
00419 << FunctionDef( "sin", 1, fcnSin, QObject::tr( "Math" ) )
00420 << FunctionDef( "cos", 1, fcnCos, QObject::tr( "Math" ) )
00421 << FunctionDef( "tan", 1, fcnTan, QObject::tr( "Math" ) )
00422 << FunctionDef( "asin", 1, fcnAsin, QObject::tr( "Math" ) )
00423 << FunctionDef( "acos", 1, fcnAcos, QObject::tr( "Math" ) )
00424 << FunctionDef( "atan", 1, fcnAtan, QObject::tr( "Math" ) )
00425 << FunctionDef( "atan2", 2, fcnAtan2, QObject::tr( "Math" ) )
00426 << FunctionDef( "exp", 1, fcnExp, QObject::tr( "Math" ) )
00427 << FunctionDef( "ln", 1, fcnLn, QObject::tr( "Math" ) )
00428 << FunctionDef( "log10", 1, fcnLog10, QObject::tr( "Math" ) )
00429 << FunctionDef( "log", 2, fcnLog, QObject::tr( "Math" ) )
00430
00431 << FunctionDef( "toint", 1, fcnToInt, QObject::tr( "Conversions" ) )
00432 << FunctionDef( "toreal", 1, fcnToReal, QObject::tr( "Conversions" ) )
00433 << FunctionDef( "tostring", 1, fcnToString, QObject::tr( "Conversions" ) )
00434
00435 << FunctionDef( "lower", 1, fcnLower, QObject::tr( "String" ) )
00436 << FunctionDef( "upper", 1, fcnUpper, QObject::tr( "String" ) )
00437 << FunctionDef( "length", 1, fcnLength, QObject::tr( "String" ) )
00438 << FunctionDef( "replace", 3, fcnReplace, QObject::tr( "String" ) )
00439 << FunctionDef( "regexp_replace", 3, fcnRegexpReplace, QObject::tr( "String" ) )
00440 << FunctionDef( "substr", 3, fcnSubstr, QObject::tr( "String" ) )
00441
00442 << FunctionDef( "xat", 1, fcnXat, QObject::tr( "Geometry" ), "", true )
00443 << FunctionDef( "yat", 1, fcnYat, QObject::tr( "Geometry" ), "", true )
00444 << FunctionDef( "$area", 0, fcnGeomArea, QObject::tr( "Geometry" ), "", true )
00445 << FunctionDef( "$length", 0, fcnGeomLength, QObject::tr( "Geometry" ), "", true )
00446 << FunctionDef( "$perimeter", 0, fcnGeomPerimeter, QObject::tr( "Geometry" ), "", true )
00447 << FunctionDef( "$x", 0, fcnX, QObject::tr( "Geometry" ), "", true )
00448 << FunctionDef( "$y", 0, fcnY, QObject::tr( "Geometry" ), "" , true )
00449
00450 << FunctionDef( "$rownum", 0, fcnRowNumber, QObject::tr( "Record" ) )
00451 << FunctionDef( "$id", 0, fcnFeatureId, QObject::tr( "Record" ) )
00452 ;
00453 }
00454
00455 return gmBuiltinFunctions;
00456 }
00457
00458
00459 bool QgsExpression::isFunctionName( QString name )
00460 {
00461 return functionIndex( name ) != -1;
00462 }
00463
00464 int QgsExpression::functionIndex( QString name )
00465 {
00466 int count = functionCount();
00467 for ( int i = 0; i < count; i++ )
00468 {
00469 if ( QString::compare( name, BuiltinFunctions()[i].mName, Qt::CaseInsensitive ) == 0 )
00470 return i;
00471 }
00472 return -1;
00473 }
00474
00475 int QgsExpression::functionCount()
00476 {
00477 return BuiltinFunctions().size();
00478 }
00479
00480
00481 QgsExpression::QgsExpression( const QString& expr )
00482 : mExpression( expr ), mRowNumber( 0 ), mCalc( NULL )
00483 {
00484 mRootNode = ::parseExpression( mExpression, mParserErrorString );
00485
00486 if ( mParserErrorString.isNull() )
00487 {
00488 Q_ASSERT( mRootNode != NULL );
00489 }
00490 }
00491
00492 QgsExpression::~QgsExpression()
00493 {
00494 delete mRootNode;
00495 delete mCalc;
00496 }
00497
00498 QStringList QgsExpression::referencedColumns()
00499 {
00500 if ( !mRootNode )
00501 return QStringList();
00502 QStringList columns = mRootNode->referencedColumns();
00503
00504
00505 for ( int i = 0; i < columns.count(); i++ )
00506 {
00507 QString col = columns.at( i );
00508 for ( int j = i + 1; j < columns.count(); j++ )
00509 {
00510 if ( QString::compare( col, columns[j], Qt::CaseInsensitive ) == 0 )
00511 {
00512
00513 columns.removeAt( j-- );
00514 }
00515 }
00516 }
00517
00518 return columns;
00519 }
00520
00521 bool QgsExpression::needsGeometry()
00522 {
00523 if ( !mRootNode )
00524 return false;
00525 return mRootNode->needsGeometry();
00526 }
00527
00528 void QgsExpression::initGeomCalculator()
00529 {
00530 mCalc = new QgsDistanceArea;
00531 mCalc->setProjectionsEnabled( false );
00532 QSettings settings;
00533 QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString();
00534 mCalc->setEllipsoid( ellipsoid );
00535 }
00536
00537 bool QgsExpression::prepare( const QgsFieldMap& fields )
00538 {
00539 mEvalErrorString = QString();
00540 if ( !mRootNode )
00541 {
00542 mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
00543 return false;
00544 }
00545
00546 return mRootNode->prepare( this, fields );
00547 }
00548
00549 QVariant QgsExpression::evaluate( QgsFeature* f )
00550 {
00551 mEvalErrorString = QString();
00552 if ( !mRootNode )
00553 {
00554 mEvalErrorString = QObject::tr( "No root node! Parsing failed?" );
00555 return QVariant();
00556 }
00557
00558 return mRootNode->eval( this, f );
00559 }
00560
00561 QVariant QgsExpression::evaluate( QgsFeature* f, const QgsFieldMap& fields )
00562 {
00563
00564 bool res = prepare( fields );
00565 if ( !res )
00566 return QVariant();
00567
00568
00569 return evaluate( f );
00570 }
00571
00572 QString QgsExpression::dump() const
00573 {
00574 if ( !mRootNode )
00575 return QObject::tr( "(no root)" );
00576
00577 return mRootNode->dump();
00578 }
00579
00580 void QgsExpression::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
00581 {
00582 if ( !mRootNode )
00583 return;
00584
00585 mRootNode->toOgcFilter( doc, element );
00586 }
00587
00588 QgsExpression* QgsExpression::createFromOgcFilter( QDomElement &element )
00589 {
00590 if ( element.isNull() || !element.hasChildNodes() )
00591 return NULL;
00592
00593 QgsExpression *expr = new QgsExpression();
00594
00595 QDomElement childElem = element.firstChildElement();
00596 while ( !childElem.isNull() )
00597 {
00598 QString errorMsg;
00599 QgsExpression::Node *node = QgsExpression::Node::createFromOgcFilter( childElem, errorMsg );
00600 if ( !node )
00601 {
00602
00603 expr->mParserErrorString = errorMsg;
00604 return expr;
00605 }
00606
00607
00608 if ( !expr->mRootNode )
00609 {
00610 expr->mRootNode = node;
00611 }
00612 else
00613 {
00614 expr->mRootNode = new QgsExpression::NodeBinaryOperator( boConcat, expr->mRootNode, node );
00615 }
00616
00617 childElem = childElem.nextSiblingElement();
00618 }
00619
00620 return expr;
00621 }
00622
00623 void QgsExpression::acceptVisitor( QgsExpression::Visitor& v )
00624 {
00625 if ( mRootNode )
00626 mRootNode->accept( v );
00627 }
00628
00629
00630 QgsExpression::Node* QgsExpression::Node::createFromOgcFilter( QDomElement &element, QString &errorMessage )
00631 {
00632 if ( element.isNull() )
00633 return NULL;
00634
00635
00636 int unaryOpCount = sizeof( UnaryOgcOperatorText ) / sizeof( UnaryOgcOperatorText[0] );
00637 for ( int i = 0; i < unaryOpCount; i++ )
00638 {
00639 QString ogcOperatorName = UnaryOgcOperatorText[ i ];
00640 if ( ogcOperatorName.isEmpty() )
00641 continue;
00642
00643 if ( element.localName() == ogcOperatorName )
00644 {
00645 QgsExpression::Node *node = QgsExpression::NodeUnaryOperator::createFromOgcFilter( element, errorMessage );
00646 if ( node )
00647 return node;
00648
00649 return NULL;
00650 }
00651 }
00652
00653
00654 int binaryOpCount = sizeof( BinaryOgcOperatorText ) / sizeof( BinaryOgcOperatorText[0] );
00655 for ( int i = 0; i < binaryOpCount; i++ )
00656 {
00657 QString ogcOperatorName = BinaryOgcOperatorText[ i ];
00658 if ( ogcOperatorName.isEmpty() )
00659 continue;
00660
00661 if ( element.localName() == ogcOperatorName )
00662 {
00663 QgsExpression::Node *node = QgsExpression::NodeBinaryOperator::createFromOgcFilter( element, errorMessage );
00664 if ( node )
00665 return node;
00666
00667 return NULL;
00668 }
00669 }
00670
00671
00672
00673 if ( element.localName() == "PropertyIsNull" )
00674 {
00675 return QgsExpression::NodeBinaryOperator::createFromOgcFilter( element, errorMessage );
00676 }
00677 else if ( element.localName() == "Literal" )
00678 {
00679 return QgsExpression::NodeLiteral::createFromOgcFilter( element, errorMessage );
00680 }
00681 else if ( element.localName() == "Function" )
00682 {
00683 return QgsExpression::NodeFunction::createFromOgcFilter( element, errorMessage );
00684 }
00685 else if ( element.localName() == "PropertyName" )
00686 {
00687 return QgsExpression::NodeColumnRef::createFromOgcFilter( element, errorMessage );
00688 }
00689 else if ( element.localName() == "PropertyIsBetween" )
00690 {
00691
00692 QgsExpression::Node *operand = 0, *lowerBound = 0, *upperBound = 0;
00693
00694 QDomElement operandElem = element.firstChildElement( "LowerBoundary" );
00695 if ( !operandElem.isNull() )
00696 lowerBound = createFromOgcFilter( operandElem, errorMessage );
00697
00698 operandElem = element.firstChildElement( "UpperBoundary" );
00699 if ( !operandElem.isNull() )
00700 upperBound = createFromOgcFilter( operandElem, errorMessage );
00701
00702
00703 operandElem = element.firstChildElement();
00704 while ( !operandElem.isNull() )
00705 {
00706 if ( operandElem.localName() != "LowerBoundary" &&
00707 operandElem.localName() != "UpperBoundary" )
00708 {
00709 operand = createFromOgcFilter( operandElem, errorMessage );
00710 break;
00711 }
00712
00713 operandElem = operandElem.nextSiblingElement();
00714 }
00715
00716 if ( !operand || !lowerBound || !upperBound )
00717 {
00718 if ( operand )
00719 delete operand;
00720
00721 if ( lowerBound )
00722 delete lowerBound;
00723
00724 if ( upperBound )
00725 delete upperBound;
00726
00727 errorMessage = "missing some required sub-elements in ogc:PropertyIsBetween";
00728 return NULL;
00729 }
00730
00731 QgsExpression::Node *geOperator = new QgsExpression::NodeBinaryOperator( boGE, operand, lowerBound );
00732 QgsExpression::Node *leOperator = new QgsExpression::NodeBinaryOperator( boLE, operand, upperBound );
00733 return new QgsExpression::NodeBinaryOperator( boAnd, geOperator, leOperator );
00734 }
00735
00736 errorMessage += QString( "unable to convert '%1' element to a valid expression: it is not supported yet or it has invalid arguments" ).arg( element.tagName() );
00737 return NULL;
00738 }
00739
00741
00742
00743 QString QgsExpression::NodeList::dump() const
00744 {
00745 QString msg; bool first = true;
00746 foreach( Node* n, mList )
00747 {
00748 if ( !first ) msg += ", "; else first = false;
00749 msg += n->dump();
00750 }
00751 return msg;
00752 }
00753
00754 void QgsExpression::NodeList::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
00755 {
00756 foreach( Node* n, mList )
00757 {
00758 n->toOgcFilter( doc, element );
00759 }
00760 }
00761
00762
00763
00764 QVariant QgsExpression::NodeUnaryOperator::eval( QgsExpression* parent, QgsFeature* f )
00765 {
00766 QVariant val = mOperand->eval( parent, f );
00767 ENSURE_NO_EVAL_ERROR;
00768
00769 switch ( mOp )
00770 {
00771 case uoNot:
00772 {
00773 TVL tvl = getTVLValue( val, parent );
00774 ENSURE_NO_EVAL_ERROR;
00775 return tvl2variant( NOT[tvl] );
00776 }
00777
00778 case uoMinus:
00779 if ( isIntSafe( val ) )
00780 return QVariant( - getIntValue( val, parent ) );
00781 else if ( isDoubleSafe( val ) )
00782 return QVariant( - getDoubleValue( val, parent ) );
00783 else
00784 SET_EVAL_ERROR( QObject::tr( "Unary minus only for numeric values." ) );
00785 break;
00786 default:
00787 Q_ASSERT( 0 && "unknown unary operation" );
00788 }
00789 return QVariant();
00790 }
00791
00792 bool QgsExpression::NodeUnaryOperator::prepare( QgsExpression* parent, const QgsFieldMap& fields )
00793 {
00794 return mOperand->prepare( parent, fields );
00795 }
00796
00797 QString QgsExpression::NodeUnaryOperator::dump() const
00798 {
00799 return QString( "%1 %2" ).arg( UnaryOperatorText[mOp] ).arg( mOperand->dump() );
00800 }
00801
00802 void QgsExpression::NodeUnaryOperator::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
00803 {
00804 QDomElement uoElem;
00805 switch ( mOp )
00806 {
00807 case uoMinus:
00808 uoElem = doc.createElement( "ogc:Literal" );
00809 uoElem.appendChild( doc.createTextNode( "-" ) );
00810 break;
00811 case uoNot:
00812 uoElem = doc.createElement( "ogc:Not" );
00813 break;
00814
00815 default:
00816 element.appendChild( doc.createComment( QString( "Unary operator %1 not implemented yet" ).arg( UnaryOperatorText[mOp] ) ) );
00817 return;
00818 }
00819 mOperand->toOgcFilter( doc, uoElem );
00820 element.appendChild( uoElem );
00821 }
00822
00823 QgsExpression::Node* QgsExpression::NodeUnaryOperator::createFromOgcFilter( QDomElement &element, QString &errorMessage )
00824 {
00825 if ( element.isNull() )
00826 return NULL;
00827
00828 int unaryOpCount = sizeof( UnaryOgcOperatorText ) / sizeof( UnaryOgcOperatorText[0] );
00829 for ( int i = 0; i < unaryOpCount; i++ )
00830 {
00831 QString ogcOperatorName = UnaryOgcOperatorText[ i ];
00832 if ( ogcOperatorName.isEmpty() )
00833 continue;
00834
00835 if ( element.localName() != ogcOperatorName )
00836 continue;
00837
00838 QDomElement operandElem = element.firstChildElement();
00839 QgsExpression::Node* operand = QgsExpression::Node::createFromOgcFilter( operandElem, errorMessage );
00840 if ( !operand )
00841 {
00842 if ( errorMessage.isEmpty() )
00843 errorMessage = QString( "invalid operand for '%1' unary operator" ).arg( ogcOperatorName );
00844 return NULL;
00845 }
00846
00847 return new QgsExpression::NodeUnaryOperator(( UnaryOperator ) i, operand );
00848 }
00849
00850 errorMessage = QString( "%1 unary operator not supported." ).arg( element.tagName() );
00851 return NULL;
00852 }
00853
00854
00855
00856 QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression* parent, QgsFeature* f )
00857 {
00858 QVariant vL = mOpLeft->eval( parent, f );
00859 ENSURE_NO_EVAL_ERROR;
00860 QVariant vR = mOpRight->eval( parent, f );
00861 ENSURE_NO_EVAL_ERROR;
00862
00863 switch ( mOp )
00864 {
00865 case boPlus:
00866 case boMinus:
00867 case boMul:
00868 case boDiv:
00869 case boMod:
00870 if ( isNull( vL ) || isNull( vR ) )
00871 return QVariant();
00872 else if ( isIntSafe( vL ) && isIntSafe( vR ) )
00873 {
00874
00875 int iL = getIntValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00876 int iR = getIntValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00877 if ( mOp == boDiv && iR == 0 ) return QVariant();
00878 return QVariant( computeInt( iL, iR ) );
00879 }
00880 else
00881 {
00882
00883 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00884 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00885 if ( mOp == boDiv && fR == 0 )
00886 return QVariant();
00887 return QVariant( computeDouble( fL, fR ) );
00888 }
00889
00890 case boPow:
00891 if ( isNull( vL ) || isNull( vR ) )
00892 return QVariant();
00893 else
00894 {
00895 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00896 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00897 return QVariant( pow( fL, fR ) );
00898 }
00899
00900 case boAnd:
00901 {
00902 TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
00903 ENSURE_NO_EVAL_ERROR;
00904 return tvl2variant( AND[tvlL][tvlR] );
00905 }
00906
00907 case boOr:
00908 {
00909 TVL tvlL = getTVLValue( vL, parent ), tvlR = getTVLValue( vR, parent );
00910 ENSURE_NO_EVAL_ERROR;
00911 return tvl2variant( OR[tvlL][tvlR] );
00912 }
00913
00914 case boEQ:
00915 case boNE:
00916 case boLT:
00917 case boGT:
00918 case boLE:
00919 case boGE:
00920 if ( isNull( vL ) || isNull( vR ) )
00921 {
00922 return TVL_Unknown;
00923 }
00924 else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
00925 {
00926
00927 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00928 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00929 return compare( fL - fR ) ? TVL_True : TVL_False;
00930 }
00931 else
00932 {
00933
00934 QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00935 QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00936 int diff = QString::compare( sL, sR );
00937 return compare( diff ) ? TVL_True : TVL_False;
00938 }
00939
00940 case boIs:
00941 case boIsNot:
00942 if ( isNull( vL ) && isNull( vR ) )
00943 return ( mOp == boIs ? TVL_True : TVL_False );
00944 else if ( isNull( vL ) || isNull( vR ) )
00945 return ( mOp == boIs ? TVL_False : TVL_True );
00946 else
00947 {
00948 bool equal = false;
00949 if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) )
00950 {
00951 double fL = getDoubleValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00952 double fR = getDoubleValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00953 equal = fL == fR;
00954 }
00955 else
00956 {
00957 QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00958 QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00959 equal = QString::compare( sL, sR ) == 0;
00960 }
00961 if ( equal )
00962 return mOp == boIs ? TVL_True : TVL_False;
00963 else
00964 return mOp == boIs ? TVL_False : TVL_True;
00965 }
00966
00967 case boRegexp:
00968 case boLike:
00969 case boNotLike:
00970 case boILike:
00971 case boNotILike:
00972 if ( isNull( vL ) || isNull( vR ) )
00973 return TVL_Unknown;
00974 else
00975 {
00976 QString str = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
00977 QString regexp = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
00978
00979 bool matches;
00980 if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike )
00981 {
00982
00983 regexp.replace( "%", ".*" );
00984 regexp.replace( "_", "." );
00985 matches = QRegExp( regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
00986 }
00987 else
00988 {
00989 matches = QRegExp( regexp ).indexIn( str ) != -1;
00990 }
00991
00992 if ( mOp == boNotLike || mOp == boNotILike )
00993 {
00994 matches = !matches;
00995 }
00996
00997 return matches ? TVL_True : TVL_False;
00998 }
00999
01000 case boConcat:
01001 if ( isNull( vL ) || isNull( vR ) )
01002 return QVariant();
01003 else
01004 {
01005 QString sL = getStringValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
01006 QString sR = getStringValue( vR, parent ); ENSURE_NO_EVAL_ERROR;
01007 return QVariant( sL + sR );
01008 }
01009
01010 default: break;
01011 }
01012 Q_ASSERT( false );
01013 return QVariant();
01014 }
01015
01016 bool QgsExpression::NodeBinaryOperator::compare( double diff )
01017 {
01018 switch ( mOp )
01019 {
01020 case boEQ: return diff == 0;
01021 case boNE: return diff != 0;
01022 case boLT: return diff < 0;
01023 case boGT: return diff > 0;
01024 case boLE: return diff <= 0;
01025 case boGE: return diff >= 0;
01026 default: Q_ASSERT( false ); return false;
01027 }
01028 }
01029
01030 int QgsExpression::NodeBinaryOperator::computeInt( int x, int y )
01031 {
01032 switch ( mOp )
01033 {
01034 case boPlus: return x+y;
01035 case boMinus: return x-y;
01036 case boMul: return x*y;
01037 case boDiv: return x/y;
01038 case boMod: return x%y;
01039 default: Q_ASSERT( false ); return 0;
01040 }
01041 }
01042
01043 double QgsExpression::NodeBinaryOperator::computeDouble( double x, double y )
01044 {
01045 switch ( mOp )
01046 {
01047 case boPlus: return x+y;
01048 case boMinus: return x-y;
01049 case boMul: return x*y;
01050 case boDiv: return x/y;
01051 case boMod: return fmod( x,y );
01052 default: Q_ASSERT( false ); return 0;
01053 }
01054 }
01055
01056
01057 bool QgsExpression::NodeBinaryOperator::prepare( QgsExpression* parent, const QgsFieldMap& fields )
01058 {
01059 bool resL = mOpLeft->prepare( parent, fields );
01060 bool resR = mOpRight->prepare( parent, fields );
01061 return resL && resR;
01062 }
01063
01064 QString QgsExpression::NodeBinaryOperator::dump() const
01065 {
01066 return QString( "%1 %2 %3" ).arg( mOpLeft->dump() ).arg( BinaryOperatorText[mOp] ).arg( mOpRight->dump() );
01067 }
01068
01069 void QgsExpression::NodeBinaryOperator::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
01070 {
01071 if ( mOp == boConcat )
01072 {
01073
01074 mOpLeft->toOgcFilter( doc, element );
01075 mOpRight->toOgcFilter( doc, element );
01076 return;
01077 }
01078
01079 if ( mOp == boIs || mOp == boIsNot )
01080 {
01081
01082 QgsExpression::NodeLiteral *opLeftLiteral = dynamic_cast<QgsExpression::NodeLiteral *>( mOpLeft );
01083 QgsExpression::NodeLiteral *opRightLiteral = dynamic_cast<QgsExpression::NodeLiteral *>( mOpRight );
01084
01085 if ( opLeftLiteral && opLeftLiteral->value().isNull() &&
01086 opRightLiteral && opRightLiteral->value().isNull() )
01087 {
01088
01089
01090 QDomElement eqElem = doc.createElement( "ogc:PropertyIsEqual" );
01091
01092 QDomElement literalElem = doc.createElement( "ogc:Literal" );
01093 literalElem.appendChild( doc.createTextNode( "1" ) );
01094 eqElem.appendChild( literalElem );
01095
01096 literalElem = doc.createElement( "ogc:Literal" );
01097 literalElem.appendChild( doc.createTextNode( "1" ) );
01098 eqElem.appendChild( literalElem );
01099
01100 element.appendChild( eqElem );
01101 }
01102 else if (( opLeftLiteral && opLeftLiteral->value().isNull() ) ||
01103 ( opRightLiteral && opRightLiteral->value().isNull() ) )
01104 {
01105
01106 QDomElement isNullElem = doc.createElement( "ogc:PropertyIsNull" );
01107 QgsExpression::Node *operand = opLeftLiteral->value().isNull() ? mOpRight : mOpLeft;
01108 operand->toOgcFilter( doc, isNullElem );
01109
01110 if ( mOp == boIsNot )
01111 {
01112
01113 QDomElement notOpElem = doc.createElement( "ogc:Not" );
01114 notOpElem.appendChild( isNullElem );
01115 element.appendChild( notOpElem );
01116 }
01117 else
01118 {
01119 element.appendChild( isNullElem );
01120 }
01121 }
01122 else
01123 {
01124
01125 QDomElement eqElem = doc.createElement( "ogc:PropertyIsEqual" );
01126 mOpLeft->toOgcFilter( doc, eqElem );
01127 mOpRight->toOgcFilter( doc, eqElem );
01128 element.appendChild( eqElem );
01129 }
01130 return;
01131 }
01132
01133 if ( mOp == boILike )
01134 {
01135
01136
01137
01138
01139 QgsExpression ilikeExpr( QString( "upper( %1 ) LIKE upper( %2 )" ).arg( mOpLeft->dump() ).arg( mOpRight->dump() ) );
01140 ilikeExpr.toOgcFilter( doc, element );
01141 return;
01142 }
01143
01144 QString opText = BinaryOgcOperatorText[mOp];
01145 if ( opText.isEmpty() )
01146 {
01147
01148
01149 element.appendChild( doc.createComment( QString( "Binary operator %1 not implemented yet" ).arg( BinaryOperatorText[mOp] ) ) );
01150 return;
01151 }
01152
01153 QDomElement boElem = doc.createElement( "ogc:" + opText );
01154 if ( mOp == boLike )
01155 {
01156
01157 boElem.setAttribute( "wildCard", "%" );
01158 boElem.setAttribute( "singleChar", "?" );
01159 boElem.setAttribute( "escapeChar", "!" );
01160 }
01161
01162 mOpLeft->toOgcFilter( doc, boElem );
01163 mOpRight->toOgcFilter( doc, boElem );
01164 element.appendChild( boElem );
01165 }
01166
01167 QgsExpression::Node* QgsExpression::NodeBinaryOperator::createFromOgcFilter( QDomElement &element, QString &errorMessage )
01168 {
01169 if ( element.isNull() )
01170 return NULL;
01171
01172 QgsExpression::Node* opLeft = 0;
01173 QgsExpression::Node* opRight = 0;
01174
01175
01176 if ( element.localName() == "PropertyIsNull" )
01177 {
01178 QDomElement operandElem = element.firstChildElement();
01179 opLeft = QgsExpression::Node::createFromOgcFilter( operandElem, errorMessage );
01180 if ( !opLeft )
01181 return NULL;
01182
01183 opRight = new QgsExpression::NodeLiteral( QVariant() );
01184 return new QgsExpression::NodeBinaryOperator( boIs, opLeft, opRight );
01185 }
01186
01187
01188 int binaryOpCount = sizeof( BinaryOgcOperatorText ) / sizeof( BinaryOgcOperatorText[0] );
01189 for ( int i = 0; i < binaryOpCount; i++ )
01190 {
01191 QString ogcOperatorName = BinaryOgcOperatorText[ i ];
01192 if ( ogcOperatorName.isEmpty() )
01193 continue;
01194
01195 if ( element.localName() != ogcOperatorName )
01196 continue;
01197
01198 QDomElement operandElem = element.firstChildElement();
01199 opLeft = QgsExpression::Node::createFromOgcFilter( operandElem, errorMessage );
01200 if ( !opLeft )
01201 {
01202 if ( errorMessage.isEmpty() )
01203 errorMessage = QString( "invalid left operand for '%1' binary operator" ).arg( ogcOperatorName );
01204 break;
01205 }
01206
01207 operandElem = operandElem.nextSiblingElement();
01208 opRight = QgsExpression::Node::createFromOgcFilter( operandElem, errorMessage );
01209 if ( !opRight )
01210 {
01211 if ( errorMessage.isEmpty() )
01212 errorMessage = QString( "invalid right operand for '%1' binary operator" ).arg( ogcOperatorName );
01213 break;
01214 }
01215
01216 return new QgsExpression::NodeBinaryOperator(( BinaryOperator ) i, opLeft, opRight );
01217 }
01218
01219 if ( !opLeft && !opRight )
01220 {
01221 errorMessage = QString( "'%1' binary operator not supported." ).arg( element.tagName() );
01222 return NULL;
01223 }
01224
01225 if ( opLeft )
01226 delete opLeft;
01227
01228 if ( opRight )
01229 delete opRight;
01230
01231 return NULL;
01232 }
01233
01234
01235
01236 QVariant QgsExpression::NodeInOperator::eval( QgsExpression* parent, QgsFeature* f )
01237 {
01238 if ( mList->count() == 0 )
01239 return mNotIn ? TVL_True : TVL_False;
01240 QVariant v1 = mNode->eval( parent, f );
01241 ENSURE_NO_EVAL_ERROR;
01242 if ( isNull( v1 ) )
01243 return TVL_Unknown;
01244
01245 bool listHasNull = false;
01246
01247 foreach( Node* n, mList->list() )
01248 {
01249 QVariant v2 = n->eval( parent, f );
01250 ENSURE_NO_EVAL_ERROR;
01251 if ( isNull( v2 ) )
01252 listHasNull = true;
01253 else
01254 {
01255 bool equal = false;
01256
01257 if ( isDoubleSafe( v1 ) && isDoubleSafe( v2 ) )
01258 {
01259 double f1 = getDoubleValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
01260 double f2 = getDoubleValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
01261 equal = f1 == f2;
01262 }
01263 else
01264 {
01265 QString s1 = getStringValue( v1, parent ); ENSURE_NO_EVAL_ERROR;
01266 QString s2 = getStringValue( v2, parent ); ENSURE_NO_EVAL_ERROR;
01267 equal = QString::compare( s1, s2 ) == 0;
01268 }
01269
01270 if ( equal )
01271 return mNotIn ? TVL_False : TVL_True;
01272 }
01273 }
01274
01275
01276 if ( listHasNull )
01277 return TVL_Unknown;
01278 else
01279 return mNotIn ? TVL_True : TVL_False;
01280 }
01281
01282 bool QgsExpression::NodeInOperator::prepare( QgsExpression* parent, const QgsFieldMap& fields )
01283 {
01284 bool res = mNode->prepare( parent, fields );
01285 foreach( Node* n, mList->list() )
01286 {
01287 res = res && n->prepare( parent, fields );
01288 }
01289 return res;
01290 }
01291
01292 QString QgsExpression::NodeInOperator::dump() const
01293 {
01294 return QString( "%1 IN (%2)" ).arg( mNode->dump() ).arg( mList->dump() );
01295 }
01296
01297 void QgsExpression::NodeInOperator::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
01298 {
01299
01300
01301 QDomElement *parent = &element;
01302
01303 QDomElement orElem;
01304 if ( mList->list().size() > 1 )
01305 {
01306 orElem = doc.createElement( "ogc:Or" );
01307 element.appendChild( orElem );
01308
01309 parent = &orElem;
01310 }
01311
01312 foreach( Node* n, mList->list() )
01313 {
01314 QDomElement eqElem = doc.createElement( "ogc:PropertyIsEqualTo" );
01315 mNode->toOgcFilter( doc, eqElem );
01316 n->toOgcFilter( doc, eqElem );
01317
01318 parent->appendChild( eqElem );
01319 }
01320 }
01321
01322
01323
01324 QVariant QgsExpression::NodeFunction::eval( QgsExpression* parent, QgsFeature* f )
01325 {
01326 const FunctionDef& fd = BuiltinFunctions()[mFnIndex];
01327
01328
01329 QVariantList argValues;
01330 if ( mArgs )
01331 {
01332 foreach( Node* n, mArgs->list() )
01333 {
01334 QVariant v = n->eval( parent, f );
01335 ENSURE_NO_EVAL_ERROR;
01336 if ( isNull( v ) )
01337 return QVariant();
01338 argValues.append( v );
01339 }
01340 }
01341
01342
01343 QVariant res = fd.mFcn( argValues, f, parent );
01344 ENSURE_NO_EVAL_ERROR;
01345
01346
01347 return res;
01348 }
01349
01350 bool QgsExpression::NodeFunction::prepare( QgsExpression* parent, const QgsFieldMap& fields )
01351 {
01352 bool res = true;
01353 if ( mArgs )
01354 {
01355 foreach( Node* n, mArgs->list() )
01356 {
01357 res = res && n->prepare( parent, fields );
01358 }
01359 }
01360 return res;
01361 }
01362
01363 QString QgsExpression::NodeFunction::dump() const
01364 {
01365 const FunctionDef& fd = BuiltinFunctions()[mFnIndex];
01366 if ( fd.mParams == 0 )
01367 return fd.mName;
01368 else
01369 return QString( "%1(%2)" ).arg( fd.mName ).arg( mArgs ? mArgs->dump() : QString() );
01370 }
01371
01372 void QgsExpression::NodeFunction::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
01373 {
01374 const FunctionDef& fd = BuiltinFunctions()[mFnIndex];
01375 if ( fd.mParams == 0 )
01376 return;
01377
01378 QDomElement funcElem = doc.createElement( "ogc:Function" );
01379 funcElem.setAttribute( "name", fd.mName );
01380 mArgs->toOgcFilter( doc, funcElem );
01381 element.appendChild( funcElem );
01382 }
01383
01384 QgsExpression::Node* QgsExpression::NodeFunction::createFromOgcFilter( QDomElement &element, QString &errorMessage )
01385 {
01386 if ( element.isNull() )
01387 return NULL;
01388
01389 if ( element.localName() != "Function" )
01390 {
01391 errorMessage = QString( "ogc:Function expected, got %1" ).arg( element.tagName() );
01392 return NULL;
01393 }
01394
01395 for ( int i = 0; i < BuiltinFunctions().size(); i++ )
01396 {
01397 QgsExpression::FunctionDef funcDef = BuiltinFunctions()[i];
01398
01399 if ( element.attribute( "name" ) != funcDef.mName )
01400 continue;
01401
01402 QgsExpression::NodeList *args = new QgsExpression::NodeList();
01403
01404 QDomElement operandElem = element.firstChildElement();
01405 while ( !operandElem.isNull() )
01406 {
01407 QgsExpression::Node* op = QgsExpression::Node::createFromOgcFilter( operandElem, errorMessage );
01408 if ( !op )
01409 {
01410 delete args;
01411 return NULL;
01412 }
01413 args->append( op );
01414
01415 operandElem = operandElem.nextSiblingElement();
01416 }
01417
01418 return new QgsExpression::NodeFunction( i, args );
01419 }
01420
01421 return NULL;
01422 }
01423
01424
01425
01426 QVariant QgsExpression::NodeLiteral::eval( QgsExpression* , QgsFeature* )
01427 {
01428 return mValue;
01429 }
01430
01431 bool QgsExpression::NodeLiteral::prepare( QgsExpression* , const QgsFieldMap& )
01432 {
01433 return true;
01434 }
01435
01436
01437 QString QgsExpression::NodeLiteral::dump() const
01438 {
01439 if ( mValue.isNull() )
01440 return "NULL";
01441
01442 switch ( mValue.type() )
01443 {
01444 case QVariant::Int: return QString::number( mValue.toInt() );
01445 case QVariant::Double: return QString::number( mValue.toDouble() );
01446 case QVariant::String: return QString( "'%1'" ).arg( mValue.toString() );
01447 default: return QObject::tr( "[unsupported type;%1; value:%2]" ).arg( mValue.typeName() ).arg( mValue.toString() );
01448 }
01449 }
01450
01451 void QgsExpression::NodeLiteral::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
01452 {
01453 QString value;
01454 if ( !mValue.isNull() )
01455 {
01456 switch ( mValue.type() )
01457 {
01458 case QVariant::Int:
01459 value = QString::number( mValue.toInt() );
01460 break;
01461 case QVariant::Double:
01462 value = QString::number( mValue.toDouble() );
01463 break;
01464 case QVariant::String:
01465 value = mValue.toString();
01466 break;
01467 default:
01468 break;
01469 }
01470 }
01471 QDomElement litElem = doc.createElement( "ogc:Literal" );
01472 litElem.appendChild( doc.createTextNode( value ) );
01473 element.appendChild( litElem );
01474 }
01475
01476 QgsExpression::Node* QgsExpression::NodeLiteral::createFromOgcFilter( QDomElement &element, QString &errorMessage )
01477 {
01478 if ( element.isNull() )
01479 return NULL;
01480
01481 if ( element.localName() != "Literal" )
01482 {
01483 errorMessage = QString( "ogc:Literal expected, got %1" ).arg( element.tagName() );
01484 return NULL;
01485 }
01486
01487 QgsExpression::Node *root = 0;
01488
01489
01490 QDomNode childNode = element.firstChild();
01491 while ( !childNode.isNull() )
01492 {
01493 QgsExpression::Node* operand = 0;
01494
01495 if ( childNode.nodeType() == QDomNode::ElementNode )
01496 {
01497
01498 QDomElement operandElem = childNode.toElement();
01499 operand = QgsExpression::Node::createFromOgcFilter( operandElem, errorMessage );
01500 if ( !operand )
01501 {
01502 if ( root )
01503 delete root;
01504
01505 errorMessage = QString( "'%1' is an invalid or not supported content for ogc:Literal" ).arg( operandElem.tagName() );
01506 return NULL;
01507 }
01508 }
01509 else
01510 {
01511
01512 operand = new QgsExpression::NodeLiteral( childNode.nodeValue() );
01513 }
01514
01515 if ( !operand )
01516 continue;
01517
01518
01519 if ( !root )
01520 {
01521 root = operand;
01522 }
01523 else
01524 {
01525 root = new QgsExpression::NodeBinaryOperator( boConcat, root, operand );
01526 }
01527
01528 childNode = childNode.nextSibling();
01529 }
01530
01531 if ( root )
01532 return root;
01533
01534 return NULL;
01535 }
01536
01537
01538
01539 QVariant QgsExpression::NodeColumnRef::eval( QgsExpression* , QgsFeature* f )
01540 {
01541 return f->attributeMap()[mIndex];
01542 }
01543
01544 bool QgsExpression::NodeColumnRef::prepare( QgsExpression* parent, const QgsFieldMap& fields )
01545 {
01546 foreach( int i, fields.keys() )
01547 {
01548 if ( QString::compare( fields[i].name(), mName, Qt::CaseInsensitive ) == 0 )
01549 {
01550 mIndex = i;
01551 return true;
01552 }
01553 }
01554 parent->mEvalErrorString = QObject::tr( "Column '%1'' not found" ).arg( mName );
01555 mIndex = -1;
01556 return false;
01557 }
01558
01559 QString QgsExpression::NodeColumnRef::dump() const
01560 {
01561 return mName;
01562 }
01563
01564 void QgsExpression::NodeColumnRef::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
01565 {
01566 QDomElement propElem = doc.createElement( "ogc:PropertyName" );
01567 propElem.appendChild( doc.createTextNode( mName ) );
01568 element.appendChild( propElem );
01569 }
01570
01571 QgsExpression::Node* QgsExpression::NodeColumnRef::createFromOgcFilter( QDomElement &element, QString &errorMessage )
01572 {
01573 if ( element.isNull() )
01574 return NULL;
01575
01576 if ( element.localName() != "PropertyName" )
01577 {
01578 errorMessage = QString( "ogc:PropertyName expected, got %1" ).arg( element.tagName() );
01579 return NULL;
01580 }
01581
01582 return new QgsExpression::NodeColumnRef( element.firstChild().nodeValue() );
01583 }
01584
01585
01586
01587 QVariant QgsExpression::NodeCondition::eval( QgsExpression* parent, QgsFeature* f )
01588 {
01589 foreach( WhenThen* cond, mConditions )
01590 {
01591 QVariant vWhen = cond->mWhenExp->eval( parent, f );
01592 TVL tvl = getTVLValue( vWhen, parent );
01593 ENSURE_NO_EVAL_ERROR;
01594 if ( tvl == True )
01595 {
01596 QVariant vRes = cond->mThenExp->eval( parent, f );
01597 ENSURE_NO_EVAL_ERROR;
01598 return vRes;
01599 }
01600 }
01601
01602 if ( mElseExp )
01603 {
01604 QVariant vElse = mElseExp->eval( parent, f );
01605 ENSURE_NO_EVAL_ERROR;
01606 return vElse;
01607 }
01608
01609
01610 return QVariant();
01611 }
01612
01613 bool QgsExpression::NodeCondition::prepare( QgsExpression* parent, const QgsFieldMap& fields )
01614 {
01615 bool res;
01616 foreach( WhenThen* cond, mConditions )
01617 {
01618 res = cond->mWhenExp->prepare( parent, fields )
01619 & cond->mThenExp->prepare( parent, fields );
01620 if ( !res ) return false;
01621 }
01622
01623 if ( mElseExp )
01624 return mElseExp->prepare( parent, fields );
01625
01626 return true;
01627 }
01628
01629 QString QgsExpression::NodeCondition::dump() const
01630 {
01631 QString msg = "CONDITION:\n";
01632 foreach( WhenThen* cond, mConditions )
01633 {
01634 msg += QString( "- WHEN %1 THEN %2\n" ).arg( cond->mWhenExp->dump() ).arg( cond->mThenExp->dump() );
01635 }
01636 if ( mElseExp )
01637 msg += QString( "- ELSE %1" ).arg( mElseExp->dump() );
01638 return msg;
01639 }
01640
01641 void QgsExpression::NodeCondition::toOgcFilter( QDomDocument &doc, QDomElement &element ) const
01642 {
01643
01644 element.appendChild( doc.createComment( "CASE operator not implemented yet" ) );
01645 }
01646
01647 QStringList QgsExpression::NodeCondition::referencedColumns() const
01648 {
01649 QStringList lst;
01650 foreach( WhenThen* cond, mConditions )
01651 {
01652 lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
01653 }
01654
01655 if ( mElseExp )
01656 lst += mElseExp->referencedColumns();
01657
01658 return lst;
01659 }
01660
01661 bool QgsExpression::NodeCondition::needsGeometry() const
01662 {
01663 foreach( WhenThen* cond, mConditions )
01664 {
01665 if ( cond->mWhenExp->needsGeometry() ||
01666 cond->mThenExp->needsGeometry() )
01667 return true;
01668 }
01669
01670 if ( mElseExp && mElseExp->needsGeometry() )
01671 return true;
01672
01673 return false;
01674 }