diff --git a/src/ol/expression/expression.js b/src/ol/expression/expression.js index c8f008a0b7..5015345afc 100644 --- a/src/ol/expression/expression.js +++ b/src/ol/expression/expression.js @@ -1,3 +1,5 @@ +goog.provide('ol.expression.Comparison'); +goog.provide('ol.expression.ComparisonOp'); goog.provide('ol.expression.Expression'); goog.provide('ol.expression.Identifier'); goog.provide('ol.expression.Literal'); @@ -28,6 +30,95 @@ ol.expression.Expression = function() {}; ol.expression.Expression.prototype.evaluate = goog.abstractMethod; +/** + * @enum {string} + */ +ol.expression.ComparisonOp = { + EQ: '==', + NEQ: '!=', + STRICT_EQ: '===', + STRICT_NEQ: '!==', + GT: '>', + LT: '<', + GTE: '>=', + LTE: '<=' +}; + + + +/** + * A comparison expression (e.g. `foo >= 42`, `bar != "chicken"`). + * + * @constructor + * @extends {ol.expression.Expression} + * @param {ol.expression.ComparisonOp} operator Comparison operator. + * @param {ol.expression.Expression} left Left expression. + * @param {ol.expression.Expression} right Right expression. + */ +ol.expression.Comparison = function(operator, left, right) { + + /** + * @type {ol.expression.ComparisonOp} + * @private + */ + this.operator_ = operator; + + /** + * @type {ol.expression.Expression} + * @private + */ + this.left_ = left; + + /** + * @type {ol.expression.Expression} + * @private + */ + this.right_ = right; + +}; +goog.inherits(ol.expression.Comparison, ol.expression.Expression); + + +/** + * @inheritDoc + */ +ol.expression.Comparison.prototype.evaluate = function(scope) { + var result; + var rightVal = this.right_.evaluate(scope); + var leftVal = this.left_.evaluate(scope); + + switch (this.operator_) { + case ol.expression.ComparisonOp.EQ: + result = leftVal == rightVal; + break; + case ol.expression.ComparisonOp.NEQ: + result = leftVal != rightVal; + break; + case ol.expression.ComparisonOp.STRICT_EQ: + result = leftVal === rightVal; + break; + case ol.expression.ComparisonOp.STRICT_NEQ: + result = leftVal !== rightVal; + break; + case ol.expression.ComparisonOp.GT: + result = leftVal > rightVal; + break; + case ol.expression.ComparisonOp.LT: + result = leftVal < rightVal; + break; + case ol.expression.ComparisonOp.GTE: + result = leftVal >= rightVal; + break; + case ol.expression.ComparisonOp.LTE: + result = leftVal <= rightVal; + break; + default: + throw new Error('Unsupported comparison operator: ' + this.operator_); + } + return result; +}; + + /** * An identifier expression (e.g. `foo`). diff --git a/test/spec/ol/expression/expression.test.js b/test/spec/ol/expression/expression.test.js index 99fbc234f9..f9c579cc13 100644 --- a/test/spec/ol/expression/expression.test.js +++ b/test/spec/ol/expression/expression.test.js @@ -1,6 +1,115 @@ goog.provide('ol.test.expression.Expression'); +describe('ol.expression.Comparison', function() { + + describe('constructor', function() { + it('creates a new expression', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.EQ, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + expect(expr).to.be.a(ol.expression.Expression); + expect(expr).to.be.a(ol.expression.Comparison); + }); + }); + + describe('#evaluate()', function() { + it('compares with ==', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.EQ, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(true); + expect(expr.evaluate({foo: '42'})).to.be(true); + expect(expr.evaluate({foo: true})).to.be(false); + expect(expr.evaluate({bar: true})).to.be(false); + }); + + it('compares with !=', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.NEQ, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(false); + expect(expr.evaluate({foo: '42'})).to.be(false); + expect(expr.evaluate({foo: true})).to.be(true); + expect(expr.evaluate({bar: true})).to.be(true); + }); + + it('compares with ===', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.STRICT_EQ, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(true); + expect(expr.evaluate({foo: '42'})).to.be(false); + expect(expr.evaluate({foo: true})).to.be(false); + expect(expr.evaluate({bar: true})).to.be(false); + }); + + it('compares with !==', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.STRICT_NEQ, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(false); + expect(expr.evaluate({foo: '42'})).to.be(true); + expect(expr.evaluate({foo: true})).to.be(true); + expect(expr.evaluate({bar: true})).to.be(true); + }); + + it('compares with >', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.GT, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(false); + expect(expr.evaluate({foo: 41})).to.be(false); + expect(expr.evaluate({foo: 43})).to.be(true); + }); + + it('compares with <', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.LT, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(false); + expect(expr.evaluate({foo: 41})).to.be(true); + expect(expr.evaluate({foo: 43})).to.be(false); + }); + + it('compares with >=', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.GTE, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(true); + expect(expr.evaluate({foo: 41})).to.be(false); + expect(expr.evaluate({foo: 43})).to.be(true); + }); + + it('compares with <=', function() { + var expr = new ol.expression.Comparison( + ol.expression.ComparisonOp.LTE, + new ol.expression.Identifier('foo'), + new ol.expression.Literal(42)); + + expect(expr.evaluate({foo: 42})).to.be(true); + expect(expr.evaluate({foo: 41})).to.be(true); + expect(expr.evaluate({foo: 43})).to.be(false); + }); + }); + +}); + describe('ol.expression.Identifier', function() { describe('constructor', function() { @@ -119,6 +228,8 @@ describe('ol.expression.Not', function() { }); +goog.require('ol.expression.Comparison'); +goog.require('ol.expression.ComparisonOp'); goog.require('ol.expression.Expression'); goog.require('ol.expression.Identifier'); goog.require('ol.expression.Literal');