diff --git a/src/ol/expression/expression.js b/src/ol/expression/expression.js index 12bb880a35..51e3aaab52 100644 --- a/src/ol/expression/expression.js +++ b/src/ol/expression/expression.js @@ -3,6 +3,8 @@ goog.provide('ol.expression.ComparisonOp'); goog.provide('ol.expression.Expression'); goog.provide('ol.expression.Identifier'); goog.provide('ol.expression.Literal'); +goog.provide('ol.expression.Logical'); +goog.provide('ol.expression.LogicalOp'); goog.provide('ol.expression.Math'); goog.provide('ol.expression.MathOp'); goog.provide('ol.expression.Not'); @@ -177,6 +179,68 @@ ol.expression.Literal.prototype.evaluate = function(scope) { }; +/** + * @enum {string} + */ +ol.expression.LogicalOp = { + AND: '&&', + OR: '||' +}; + + + +/** + * A binary logical expression (e.g. `foo && bar`, `bar || "chicken"`). + * + * @constructor + * @extends {ol.expression.Expression} + * @param {ol.expression.LogicalOp} operator Logical operator. + * @param {ol.expression.Expression} left Left expression. + * @param {ol.expression.Expression} right Right expression. + */ +ol.expression.Logical = function(operator, left, right) { + + /** + * @type {ol.expression.LogicalOp} + * @private + */ + this.operator_ = operator; + + /** + * @type {ol.expression.Expression} + * @private + */ + this.left_ = left; + + /** + * @type {ol.expression.Expression} + * @private + */ + this.right_ = right; + +}; +goog.inherits(ol.expression.Logical, ol.expression.Expression); + + +/** + * @inheritDoc + */ +ol.expression.Logical.prototype.evaluate = function(scope) { + var result; + var rightVal = this.right_.evaluate(scope); + var leftVal = this.left_.evaluate(scope); + + if (this.operator_ === ol.expression.LogicalOp.AND) { + result = leftVal && rightVal; + } else if (this.operator_ === ol.expression.LogicalOp.OR) { + result = leftVal || rightVal; + } else { + throw new Error('Unsupported logical operator: ' + this.operator_); + } + return result; +}; + + /** * @enum {string} */ diff --git a/test/spec/ol/expression/expression.test.js b/test/spec/ol/expression/expression.test.js index f9297b72a4..b88ea17f3c 100644 --- a/test/spec/ol/expression/expression.test.js +++ b/test/spec/ol/expression/expression.test.js @@ -184,6 +184,47 @@ describe('ol.expression.Literal', function() { }); +describe('ol.expression.Logical', function() { + + describe('constructor', function() { + it('creates a new expression', function() { + var expr = new ol.expression.Logical( + ol.expression.LogicalOp.OR, + new ol.expression.Identifier('foo'), + new ol.expression.Identifier('bar')); + expect(expr).to.be.a(ol.expression.Expression); + expect(expr).to.be.a(ol.expression.Logical); + }); + }); + + describe('#evaluate()', function() { + it('applies || to resolved identifiers', function() { + var expr = new ol.expression.Logical( + ol.expression.LogicalOp.OR, + new ol.expression.Identifier('foo'), + new ol.expression.Identifier('bar')); + + expect(expr.evaluate({foo: true, bar: true})).to.be(true); + expect(expr.evaluate({foo: true, bar: false})).to.be(true); + expect(expr.evaluate({foo: false, bar: true})).to.be(true); + expect(expr.evaluate({foo: false, bar: false})).to.be(false); + }); + + it('applies && to resolved identifiers', function() { + var expr = new ol.expression.Logical( + ol.expression.LogicalOp.AND, + new ol.expression.Identifier('foo'), + new ol.expression.Identifier('bar')); + + expect(expr.evaluate({foo: true, bar: true})).to.be(true); + expect(expr.evaluate({foo: true, bar: false})).to.be(false); + expect(expr.evaluate({foo: false, bar: true})).to.be(false); + expect(expr.evaluate({foo: false, bar: false})).to.be(false); + }); + }); + +}); + describe('ol.expression.Math', function() { describe('constructor', function() { @@ -331,6 +372,8 @@ goog.require('ol.expression.ComparisonOp'); goog.require('ol.expression.Expression'); goog.require('ol.expression.Identifier'); goog.require('ol.expression.Literal'); +goog.require('ol.expression.Logical'); +goog.require('ol.expression.LogicalOp'); goog.require('ol.expression.Math'); goog.require('ol.expression.MathOp'); goog.require('ol.expression.Not');