diff --git a/src/ol/expr/expression.js b/src/ol/expr/expression.js index 277364d750..bc732e825f 100644 --- a/src/ol/expr/expression.js +++ b/src/ol/expr/expression.js @@ -123,7 +123,7 @@ ol.expr.lib[ol.expr.functions.EXTENT] = function(minX, maxX, minY, maxY, opt_projection, opt_attribute) { var intersects = false; var geometry = goog.isDef(opt_attribute) ? - this.getAttributes()[opt_attribute] : this.getGeometry(); + this.get(opt_attribute) : this.getGeometry(); if (geometry) { intersects = ol.extent.intersects(geometry.getBounds(), [minX, maxX, minY, maxY]); @@ -167,7 +167,7 @@ ol.expr.lib[ol.expr.functions.LIKE] = function(attribute, value, wildCard, singleChar, escapeChar, matchCase) { if (wildCard == '.') { throw new Error('"." is an unsupported wildCard character for ' + - 'ol.filter.Comparison'); + 'the "like" function'); } // set UMN MapServer defaults for unspecified parameters wildCard = goog.isDef(wildCard) ? wildCard : '*'; @@ -184,9 +184,8 @@ ol.expr.lib[ol.expr.functions.LIKE] = function(attribute, value, wildCard, new RegExp('\\\\.\\*', 'g'), '\\' + wildCard); val = value.replace( new RegExp('\\\\\\.', 'g'), '\\' + singleChar); - var attributes = this.getAttributes(); var modifiers = (matchCase === false) ? 'gi' : 'g'; - return new RegExp(val, modifiers).test(attributes[attribute]); + return new RegExp(val, modifiers).test(this.get(attribute)); }; @@ -197,11 +196,11 @@ ol.expr.lib[ol.expr.functions.LIKE] = function(attribute, value, wildCard, * @this {ol.Feature} */ ol.expr.lib[ol.expr.functions.IEQ] = function(attribute, value) { - var attributes = this.getAttributes(); - if (goog.isString(value) && goog.isString(attributes[attribute])) { - return value.toUpperCase() == attributes[attribute].toUpperCase(); + var attributeValue = this.get(attribute); + if (goog.isString(value) && goog.isString(attributeValue)) { + return value.toUpperCase() == attributeValue.toUpperCase(); } else { - return value == attributes[attribute]; + return value == attributeValue; } }; @@ -213,11 +212,11 @@ ol.expr.lib[ol.expr.functions.IEQ] = function(attribute, value) { * @this {ol.Feature} */ ol.expr.lib[ol.expr.functions.INEQ] = function(attribute, value) { - var attributes = this.getAttributes(); - if (goog.isString(value) && goog.isString(attributes[attribute])) { - return value.toUpperCase() == attributes[attribute].toUpperCase(); + var attributeValue = this.get(attribute); + if (goog.isString(value) && goog.isString(attributeValue)) { + return value.toUpperCase() == attributeValue.toUpperCase(); } else { - return value != attributes[attribute]; + return value != attributeValue; } }; diff --git a/src/ol/expr/expressions.js b/src/ol/expr/expressions.js index bd827885ea..1f16e7ff9c 100644 --- a/src/ol/expr/expressions.js +++ b/src/ol/expr/expressions.js @@ -277,12 +277,12 @@ ol.expr.Identifier.prototype.getName = function() { * * @constructor * @extends {ol.expr.Expression} - * @param {string|number|boolean|null} value A literal value. + * @param {string|number|boolean|Date|null} value A literal value. */ ol.expr.Literal = function(value) { /** - * @type {string|number|boolean|null} + * @type {string|number|boolean|Date|null} * @private */ this.value_ = value; @@ -301,7 +301,7 @@ ol.expr.Literal.prototype.evaluate = function() { /** * Get the literal value. - * @return {string|number|boolean|null} The literal value. + * @return {string|number|boolean|Date|null} The literal value. */ ol.expr.Literal.prototype.getValue = function() { return this.value_; diff --git a/src/ol/parser/ogc/filter_v1.js b/src/ol/parser/ogc/filter_v1.js index 4b7f1063ec..3085e1397d 100644 --- a/src/ol/parser/ogc/filter_v1.js +++ b/src/ol/parser/ogc/filter_v1.js @@ -1,12 +1,15 @@ goog.provide('ol.parser.ogc.Filter_v1'); goog.require('goog.array'); +goog.require('goog.asserts'); goog.require('goog.dom.xml'); +goog.require('goog.object'); goog.require('goog.string'); goog.require('ol.expr'); goog.require('ol.expr.Call'); goog.require('ol.expr.Comparison'); goog.require('ol.expr.ComparisonOp'); goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); goog.require('ol.expr.Logical'); goog.require('ol.expr.LogicalOp'); goog.require('ol.expr.Not'); @@ -24,18 +27,18 @@ ol.parser.ogc.Filter_v1 = function() { this.errorProperty = 'filter'; this.readers = { 'http://www.opengis.net/ogc': { - '_expression': function(node) { - // only the simplest of ogc:expression handled - // "some text and an attribute" + _expression: function(node) { var obj, value = ''; for (var child = node.firstChild; child; child = child.nextSibling) { switch (child.nodeType) { case 1: obj = this.readNode(child); if (obj['property']) { - value += obj['property']; + value += obj['property'].getName(); } else if (goog.isDef(obj['value'])) { - value += obj['value']; + // TODO adding this to value and then parsing causes + // ol.expr.UnexpectedToken on e.g. 10 + return obj['value']; } break; case 3: // text node @@ -46,17 +49,17 @@ ol.parser.ogc.Filter_v1 = function() { break; } } - return value; + return ol.expr.parse(value); }, 'Filter': function(node, obj) { var container = { 'filters': [] }; this.readChildNodes(node, container); - if (goog.isDef(container['fids'])) { + if (goog.isDef(container.fids)) { obj['filter'] = new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.FID), - container['fids']); + goog.object.getValues(container.fids)); } else if (container['filters'].length > 0) { obj['filter'] = container['filters'][0]; } @@ -64,10 +67,12 @@ ol.parser.ogc.Filter_v1 = function() { 'FeatureId': function(node, obj) { var fid = node.getAttribute('fid'); if (fid) { - if (!goog.isDef(obj['fids'])) { - obj['fids'] = {}; + if (!goog.isDef(obj.fids)) { + obj.fids = {}; + } + if (!obj.fids.hasOwnProperty(fid)) { + obj.fids[fid] = new ol.expr.Literal(fid); } - obj['fids'][fid] = true; } }, 'And': function(node, obj) { @@ -97,7 +102,7 @@ ol.parser.ogc.Filter_v1 = function() { obj['filters'].push(new ol.expr.Comparison( ol.expr.ComparisonOp.EQ, container['property'], - null)); + new ol.expr.Literal(null))); }, 'PropertyIsLessThan': function(node, obj) { var container = {}; @@ -143,28 +148,29 @@ ol.parser.ogc.Filter_v1 = function() { 'Literal': function(node, obj) { var nodeValue = this.getChildValue(node); var value = goog.string.toNumber(nodeValue); - obj['value'] = isNaN(value) ? nodeValue : value; + obj['value'] = new ol.expr.Literal(isNaN(value) ? nodeValue : value); }, 'PropertyName': function(node, obj) { - obj['property'] = this.getChildValue(node); + obj['property'] = new ol.expr.Identifier(this.getChildValue(node)); }, 'LowerBoundary': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - obj['lowerBoundary'] = goog.string.toNumber( - readers['_expression'].call(this, node)); + obj['lowerBoundary'] = readers._expression.call(this, node); }, 'UpperBoundary': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - obj['upperBoundary'] = goog.string.toNumber( - readers['_expression'].call(this, node)); + obj['upperBoundary'] = readers._expression.call(this, node); }, - '_spatial': function(node, obj, identifier) { + _spatial: function(node, obj, identifier) { var args = [], container = {}; this.readChildNodes(node, container); if (goog.isDef(container.geometry)) { - args.push(this.gml_.createGeometry(container)); + args.push(new ol.expr.Literal(this.gml_.createGeometry(container))); } else { - args = container['bounds']; + args = [new ol.expr.Literal(container.bounds[0]), + new ol.expr.Literal(container.bounds[1]), + new ol.expr.Literal(container.bounds[2]), + new ol.expr.Literal(container.bounds[3])]; } if (goog.isDef(container['distance'])) { args.push(container['distance']); @@ -172,7 +178,7 @@ ol.parser.ogc.Filter_v1 = function() { if (goog.isDef(container['distanceUnits'])) { args.push(container['distanceUnits']); } - args.push(container['projection']); + args.push(new ol.expr.Literal(container.projection)); if (goog.isDef(container['property'])) { args.push(container['property']); } @@ -181,32 +187,32 @@ ol.parser.ogc.Filter_v1 = function() { }, 'BBOX': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - readers['_spatial'].call(this, node, obj, + readers._spatial.call(this, node, obj, ol.expr.functions.EXTENT); }, 'Intersects': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - readers['_spatial'].call(this, node, obj, + readers._spatial.call(this, node, obj, ol.expr.functions.INTERSECTS); }, 'Within': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - readers['_spatial'].call(this, node, obj, + readers._spatial.call(this, node, obj, ol.expr.functions.WITHIN); }, 'Contains': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - readers['_spatial'].call(this, node, obj, + readers._spatial.call(this, node, obj, ol.expr.functions.CONTAINS); }, 'DWithin': function(node, obj) { var readers = this.readers[this.defaultNamespaceURI]; - readers['_spatial'].call(this, node, obj, + readers._spatial.call(this, node, obj, ol.expr.functions.DWITHIN); }, 'Distance': function(node, obj) { - obj['distance'] = parseInt(this.getChildValue(node), 10); - obj['distanceUnits'] = node.getAttribute('units'); + obj['distance'] = new ol.expr.Literal(this.getChildValue(node)); + obj['distanceUnits'] = new ol.expr.Literal(node.getAttribute('units')); } } }; @@ -219,9 +225,10 @@ ol.parser.ogc.Filter_v1 = function() { }, '_featureIds': function(filter) { var node = this.createDocumentFragment(); - var fids = filter.getArgs(); - for (var i = 0, ii = fids.length; i < ii; i++) { - this.writeNode('FeatureId', fids[i], null, node); + var args = filter.getArgs(); + for (var i = 0, ii = args.length; i < ii; i++) { + goog.asserts.assert(args[i] instanceof ol.expr.Literal); + this.writeNode('FeatureId', args[i].getValue(), null, node); } return node; }, @@ -296,23 +303,26 @@ ol.parser.ogc.Filter_v1 = function() { filters[0] = filter.getLeft(); filters[1] = filter.getRight(); for (var i = 0; i < 2; ++i) { - var value = filters[i].getRight(); + var expr = filters[i].getRight(); if (filters[i].getOperator() === ol.expr.ComparisonOp.GTE) { - lower = value; + lower = expr; } else if (filters[i].getOperator() === ol.expr.ComparisonOp.LTE) { - upper = value; + upper = expr; } } this.writeNode('LowerBoundary', lower, null, node); this.writeNode('UpperBoundary', upper, null, node); return node; }, - 'PropertyName': function(name) { + 'PropertyName': function(expr) { + goog.asserts.assert(expr instanceof ol.expr.Identifier); var node = this.createElementNS('ogc:PropertyName'); - node.appendChild(this.createTextNode(name)); + node.appendChild(this.createTextNode(expr.getName())); return node; }, - 'Literal': function(value) { + 'Literal': function(expr) { + goog.asserts.assert(expr instanceof ol.expr.Literal); + var value = expr.getValue(); if (value instanceof Date) { value = value.toISOString(); } @@ -320,14 +330,14 @@ ol.parser.ogc.Filter_v1 = function() { node.appendChild(this.createTextNode(value)); return node; }, - 'LowerBoundary': function(value) { + 'LowerBoundary': function(expr) { var node = this.createElementNS('ogc:LowerBoundary'); - this.writeOgcExpression(value, node); + this.writeOgcExpression(expr, node); return node; }, - 'UpperBoundary': function(value) { + 'UpperBoundary': function(expr) { var node = this.createElementNS('ogc:UpperBoundary'); - this.writeOgcExpression(value, node); + this.writeOgcExpression(expr, node); return node; }, 'INTERSECTS': function(filter) { @@ -347,8 +357,10 @@ ol.parser.ogc.Filter_v1 = function() { 'Distance': function(filter) { var node = this.createElementNS('ogc:Distance'); var args = filter.getArgs(); - node.setAttribute('units', args[2]); - node.appendChild(this.createTextNode(args[1])); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + node.setAttribute('units', args[2].getValue()); + goog.asserts.assert(args[1] instanceof ol.expr.Literal); + node.appendChild(this.createTextNode(args[1].getValue())); return node; }, 'Function': function(filter) { @@ -378,14 +390,16 @@ ol.parser.ogc.Filter_v1 = function() { '<=': 'PropertyIsLessThanOrEqualTo', '>=': 'PropertyIsGreaterThanOrEqualTo', '..': 'PropertyIsBetween', - '~': 'PropertyIsLike', - 'NULL': 'PropertyIsNull', - 'BBOX': 'BBOX', - 'DWITHIN': 'DWITHIN', - 'WITHIN': 'WITHIN', - 'CONTAINS': 'CONTAINS', - 'INTERSECTS': 'INTERSECTS', - 'FID': '_featureIds' + 'like': 'PropertyIsLike', + 'null': 'PropertyIsNull', + 'extent': 'BBOX', + 'dwithin': 'DWITHIN', + 'within': 'WITHIN', + 'contains': 'CONTAINS', + 'intersects': 'INTERSECTS', + 'fid': '_featureIds', + 'ieq': 'PropertyIsEqualTo', + 'ineq': 'PropertyIsNotEqualTo' }; goog.base(this); }; @@ -402,46 +416,30 @@ ol.parser.ogc.Filter_v1.prototype.getFilterType_ = function(filter) { if (filter instanceof ol.expr.Logical || filter instanceof ol.expr.Comparison) { type = filter.getOperator(); + var left = filter.getLeft(); + var right = filter.getRight(); var isNull = (type === ol.expr.ComparisonOp.EQ && - filter.getRight() === null); + right instanceof ol.expr.Literal && right.getValue() === null); if (isNull) { - type = 'NULL'; + type = 'null'; } var isBetween = (type === ol.expr.LogicalOp.AND && - filter.getLeft() instanceof ol.expr.Comparison && - filter.getRight() instanceof ol.expr.Comparison && - filter.getLeft().getLeft() === filter.getRight().getLeft() && - (filter.getLeft().getOperator() === ol.expr.ComparisonOp.LTE || - filter.getLeft().getOperator() === ol.expr.ComparisonOp.GTE) && - (filter.getRight().getOperator() === ol.expr.ComparisonOp.LTE || - filter.getRight().getOperator() === ol.expr.ComparisonOp.GTE)); + left instanceof ol.expr.Comparison && + right instanceof ol.expr.Comparison && + left.getLeft() instanceof ol.expr.Identifier && + right.getLeft() instanceof ol.expr.Identifier && + left.getLeft().getName() === right.getLeft().getName() && + (left.getOperator() === ol.expr.ComparisonOp.LTE || + left.getOperator() === ol.expr.ComparisonOp.GTE) && + (right.getOperator() === ol.expr.ComparisonOp.LTE || + right.getOperator() === ol.expr.ComparisonOp.GTE)); if (isBetween) { type = '..'; } } else if (filter instanceof ol.expr.Call) { - var callee = filter.getCallee().getName(); - if (callee === ol.expr.functions.FID) { - type = 'FID'; - } - else if (callee === ol.expr.functions.IEQ) { - type = '=='; - } else if (callee === ol.expr.functions.INEQ) { - type = '!='; - } - else if (callee === ol.expr.functions.LIKE) { - type = '~'; - } - else if (callee === ol.expr.functions.CONTAINS) { - type = 'CONTAINS'; - } else if (callee === ol.expr.functions.WITHIN) { - type = 'WITHIN'; - } else if (callee === ol.expr.functions.DWITHIN) { - type = 'DWITHIN'; - } else if (callee === ol.expr.functions.EXTENT) { - type = 'BBOX'; - } else if (callee === ol.expr.functions.INTERSECTS) { - type = 'INTERSECTS'; - } + var callee = filter.getCallee(); + goog.asserts.assert(callee instanceof ol.expr.Identifier); + type = callee.getName(); } else if (filter instanceof ol.expr.Not) { type = '!'; } @@ -484,16 +482,18 @@ ol.parser.ogc.Filter_v1.prototype.write = function(filter) { /** - * @param {ol.expr.Call|string|number} value The value write out. + * @param {ol.expr.Expression} expr The value write out. * @param {Element} node The node to append to. * @return {Element} The node to which was appended. * @protected */ -ol.parser.ogc.Filter_v1.prototype.writeOgcExpression = function(value, node) { - if (value instanceof ol.expr.Call) { - this.writeNode('Function', value, null, node); - } else { - this.writeNode('Literal', value, null, node); +ol.parser.ogc.Filter_v1.prototype.writeOgcExpression = function(expr, node) { + if (expr instanceof ol.expr.Call) { + this.writeNode('Function', expr, null, node); + } else if (expr instanceof ol.expr.Literal) { + this.writeNode('Literal', expr, null, node); + } else if (expr instanceof ol.expr.Identifier) { + this.writeNode('PropertyName', expr, null, node); } return node; }; @@ -540,7 +540,7 @@ ol.parser.ogc.Filter_v1.prototype.aggregateLogical_ = function(filters, if (subFilters.length === 2) { newFilters.push(new ol.expr.Logical(operator, subFilters[0], subFilters[1])); - goog.array.clear(subFilters); + subFilters.length = 0; } } // there could be a single item left now diff --git a/src/ol/parser/ogc/filter_v1_0_0.js b/src/ol/parser/ogc/filter_v1_0_0.js index 7bbc07f568..bcf2874935 100644 --- a/src/ol/parser/ogc/filter_v1_0_0.js +++ b/src/ol/parser/ogc/filter_v1_0_0.js @@ -1,11 +1,13 @@ goog.provide('ol.parser.ogc.Filter_v1_0_0'); +goog.require('goog.asserts'); goog.require('goog.object'); goog.require('ol.expr'); goog.require('ol.expr.Call'); goog.require('ol.expr.Comparison'); goog.require('ol.expr.ComparisonOp'); goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); goog.require('ol.expr.functions'); goog.require('ol.geom.Geometry'); goog.require('ol.parser.ogc.Filter_v1'); @@ -44,10 +46,9 @@ ol.parser.ogc.Filter_v1_0_0 = function() { this.readChildNodes(node, container); var args = []; args.push(container['property'], container['value'], - node.getAttribute('wildCard'), - node.getAttribute('singleChar'), - node.getAttribute('escape') - ); + new ol.expr.Literal(node.getAttribute('wildCard')), + new ol.expr.Literal(node.getAttribute('singleChar')), + new ol.expr.Literal(node.getAttribute('escape'))); obj['filters'].push(new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.LIKE), args)); } @@ -56,27 +57,26 @@ ol.parser.ogc.Filter_v1_0_0 = function() { 'PropertyIsEqualTo': function(filter) { var node = this.createElementNS('ogc:PropertyIsEqualTo'); var property = filter.getLeft(); - if (goog.isDef(property)) { - this.writeNode('PropertyName', property, null, node); - } + this.writeNode('PropertyName', property, null, node); this.writeOgcExpression(filter.getRight(), node); return node; }, 'PropertyIsNotEqualTo': function(filter) { var node = this.createElementNS('ogc:PropertyIsNotEqualTo'); var property = filter.getLeft(); - if (goog.isDef(property)) { - this.writeNode('PropertyName', property, null, node); - } + this.writeNode('PropertyName', property, null, node); this.writeOgcExpression(filter.getRight(), node); return node; }, 'PropertyIsLike': function(filter) { var node = this.createElementNS('ogc:PropertyIsLike'); var args = filter.getArgs(); - node.setAttribute('wildCard', args[2]); - node.setAttribute('singleChar', args[3]); - node.setAttribute('escape', args[4]); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + node.setAttribute('wildCard', args[2].getValue()); + goog.asserts.assert(args[3] instanceof ol.expr.Literal); + node.setAttribute('singleChar', args[3].getValue()); + goog.asserts.assert(args[4] instanceof ol.expr.Literal); + node.setAttribute('escape', args[4].getValue()); var property = args[0]; if (goog.isDef(property)) { this.writeNode('PropertyName', property, null, node); @@ -87,8 +87,14 @@ ol.parser.ogc.Filter_v1_0_0 = function() { 'BBOX': function(filter) { var node = this.createElementNS('ogc:BBOX'); var args = filter.getArgs(); - var property = args[5], bbox = [args[0], args[1], args[2], args[3]], - projection = args[4]; + goog.asserts.assert(args[0] instanceof ol.expr.Literal); + goog.asserts.assert(args[1] instanceof ol.expr.Literal); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + goog.asserts.assert(args[3] instanceof ol.expr.Literal); + goog.asserts.assert(args[4] instanceof ol.expr.Literal); + var property = args[5], bbox = [args[0].getValue(), args[1].getValue(), + args[2].getValue(), args[3].getValue()], + projection = args[4].getValue(); // PropertyName is mandatory in 1.0.0, but e.g. GeoServer also // accepts filters without it. if (goog.isDefAndNotNull(property)) { @@ -119,12 +125,17 @@ ol.parser.ogc.Filter_v1_0_0.prototype.writeSpatial_ = function(filter, name) { var node = this.createElementNS('ogc:' + name); var args = filter.getArgs(); var property, geom = null, bbox, call, projection; - if (goog.isNumber(args[0])) { - bbox = [args[0], args[1], args[2], args[3]]; + if (args[0] instanceof ol.expr.Literal && goog.isNumber(args[0].getValue())) { + goog.asserts.assert(args[1] instanceof ol.expr.Literal); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + goog.asserts.assert(args[3] instanceof ol.expr.Literal); + bbox = [args[0].getValue(), args[1].getValue(), args[2].getValue(), + args[3].getValue()]; projection = args[4]; property = args[5]; - } else if (args[0] instanceof ol.geom.Geometry) { - geom = args[0]; + } else if (args[0] instanceof ol.expr.Literal && + args[0].getValue() instanceof ol.geom.Geometry) { + geom = args[0].getValue(); if (name === 'DWithin') { projection = args[3]; property = args[4]; @@ -157,8 +168,9 @@ ol.parser.ogc.Filter_v1_0_0.prototype.writeSpatial_ = function(filter, name) { 'http://www.opengis.net/gml'); } if (goog.isDef(child)) { - if (goog.isDef(projection)) { - child.setAttribute('srsName', projection); + goog.asserts.assert(projection instanceof ol.expr.Literal); + if (goog.isDefAndNotNull(projection.getValue())) { + child.setAttribute('srsName', projection.getValue()); } node.appendChild(child); } diff --git a/src/ol/parser/ogc/filter_v1_1_0.js b/src/ol/parser/ogc/filter_v1_1_0.js index 6cfa18ed44..a54813efb7 100644 --- a/src/ol/parser/ogc/filter_v1_1_0.js +++ b/src/ol/parser/ogc/filter_v1_1_0.js @@ -1,11 +1,13 @@ goog.provide('ol.parser.ogc.Filter_v1_1_0'); +goog.require('goog.asserts'); goog.require('goog.object'); goog.require('ol.expr'); goog.require('ol.expr.Call'); goog.require('ol.expr.Comparison'); goog.require('ol.expr.ComparisonOp'); goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); goog.require('ol.expr.functions'); goog.require('ol.geom.Geometry'); goog.require('ol.parser.ogc.Filter_v1'); @@ -59,10 +61,10 @@ ol.parser.ogc.Filter_v1_1_0 = function() { this.readChildNodes(node, container); var args = []; args.push(container['property'], container['value'], - node.getAttribute('wildCard'), - node.getAttribute('singleChar'), - node.getAttribute('escapeChar'), - node.getAttribute('matchCase')); + new ol.expr.Literal(node.getAttribute('wildCard')), + new ol.expr.Literal(node.getAttribute('singleChar')), + new ol.expr.Literal(node.getAttribute('escapeChar')), + new ol.expr.Literal(node.getAttribute('matchCase'))); obj['filters'].push(new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.LIKE), args)); } @@ -103,11 +105,15 @@ ol.parser.ogc.Filter_v1_1_0 = function() { 'PropertyIsLike': function(filter) { var node = this.createElementNS('ogc:PropertyIsLike'); var args = filter.getArgs(); - node.setAttribute('wildCard', args[2]); - node.setAttribute('singleChar', args[3]); - node.setAttribute('escapeChar', args[4]); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + goog.asserts.assert(args[3] instanceof ol.expr.Literal); + goog.asserts.assert(args[4] instanceof ol.expr.Literal); + node.setAttribute('wildCard', args[2].getValue()); + node.setAttribute('singleChar', args[3].getValue()); + node.setAttribute('escapeChar', args[4].getValue()); if (goog.isDefAndNotNull(args[5])) { - node.setAttribute('matchCase', args[5]); + goog.asserts.assert(args[5] instanceof ol.expr.Literal); + node.setAttribute('matchCase', args[5].getValue()); } var property = args[0]; if (goog.isDef(property)) { @@ -119,8 +125,14 @@ ol.parser.ogc.Filter_v1_1_0 = function() { 'BBOX': function(filter) { var node = this.createElementNS('ogc:BBOX'); var args = filter.getArgs(); - var property = args[5], bbox = [args[0], args[1], args[2], args[3]], - projection = args[4]; + goog.asserts.assert(args[0] instanceof ol.expr.Literal); + goog.asserts.assert(args[1] instanceof ol.expr.Literal); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + goog.asserts.assert(args[3] instanceof ol.expr.Literal); + goog.asserts.assert(args[4] instanceof ol.expr.Literal); + var property = args[5], bbox = [args[0].getValue(), args[1].getValue(), + args[2].getValue(), args[3].getValue()], + projection = args[4].getValue(); // PropertyName is optional in 1.1.0 if (goog.isDefAndNotNull(property)) { this.writeNode('PropertyName', property, null, node); @@ -143,8 +155,10 @@ ol.parser.ogc.Filter_v1_1_0 = function() { 'SortProperty': function(sortProperty) { var node = this.createElementNS('ogc:SortProperty'); this.writeNode('PropertyName', sortProperty['property'], null, node); + goog.asserts.assert(sortProperty['order'] instanceof ol.expr.Literal); this.writeNode('SortOrder', - (sortProperty['order'] == 'DESC') ? 'DESC' : 'ASC', null, node); + (sortProperty['order'].getValue() == 'DESC') ? 'DESC' : 'ASC', null, + node); return node; }, 'SortOrder': function(value) { @@ -169,12 +183,17 @@ ol.parser.ogc.Filter_v1_1_0.prototype.writeSpatial_ = function(filter, name) { var node = this.createElementNS('ogc:' + name); var args = filter.getArgs(); var property, geom = null, bbox, call, projection; - if (goog.isNumber(args[0])) { - bbox = [args[0], args[1], args[2], args[3]]; + if (args[0] instanceof ol.expr.Literal && goog.isNumber(args[0].getValue())) { + goog.asserts.assert(args[1] instanceof ol.expr.Literal); + goog.asserts.assert(args[2] instanceof ol.expr.Literal); + goog.asserts.assert(args[3] instanceof ol.expr.Literal); + bbox = [args[0].getValue(), args[1].getValue(), args[2].getValue(), + args[3].getValue()]; projection = args[4]; property = args[5]; - } else if (args[0] instanceof ol.geom.Geometry) { - geom = args[0]; + } else if (args[0] instanceof ol.expr.Literal && + args[0].getValue() instanceof ol.geom.Geometry) { + geom = args[0].getValue(); if (name === 'DWithin') { projection = args[3]; property = args[4]; @@ -207,8 +226,9 @@ ol.parser.ogc.Filter_v1_1_0.prototype.writeSpatial_ = function(filter, name) { 'http://www.opengis.net/gml'); } if (goog.isDef(child)) { - if (goog.isDef(projection)) { - child.setAttribute('srsName', projection); + goog.asserts.assert(projection instanceof ol.expr.Literal); + if (goog.isDefAndNotNull(projection.getValue())) { + child.setAttribute('srsName', projection.getValue()); } node.appendChild(child); } diff --git a/test/spec/ol/parser/ogc/filter_v1_0_0.test.js b/test/spec/ol/parser/ogc/filter_v1_0_0.test.js index 3c413c75ca..43aaa54201 100644 --- a/test/spec/ol/parser/ogc/filter_v1_0_0.test.js +++ b/test/spec/ol/parser/ogc/filter_v1_0_0.test.js @@ -11,12 +11,12 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Call).to.be(true); - expect(filter.getCallee().getName()).to.eql( + expect(filter.getCallee().getName()).to.equal( ol.expr.functions.INTERSECTS); var args = filter.getArgs(); var geom = args[0]; - expect(geom instanceof ol.geom.Polygon).to.be(true); - expect(args[2]).to.eql('Geometry'); + expect(geom.getValue() instanceof ol.geom.Polygon).to.be(true); + expect(args[2].getName()).to.equal('Geometry'); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -28,11 +28,11 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Call).to.be(true); - expect(filter.getCallee().getName()).to.eql(ol.expr.functions.WITHIN); + expect(filter.getCallee().getName()).to.equal(ol.expr.functions.WITHIN); var args = filter.getArgs(); var geom = args[0]; - expect(geom instanceof ol.geom.Polygon).to.be(true); - expect(args[2]).to.eql('Geometry'); + expect(geom.getValue() instanceof ol.geom.Polygon).to.be(true); + expect(args[2].getName()).to.equal('Geometry'); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -44,12 +44,12 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Call).to.be(true); - expect(filter.getCallee().getName()).to.eql( + expect(filter.getCallee().getName()).to.equal( ol.expr.functions.CONTAINS); var args = filter.getArgs(); var geom = args[0]; - expect(geom instanceof ol.geom.Polygon).to.be(true); - expect(args[2]).to.eql('Geometry'); + expect(geom.getValue() instanceof ol.geom.Polygon).to.be(true); + expect(args[2].getName()).to.equal('Geometry'); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -61,16 +61,17 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Logical).to.be.ok(); - expect(filter.getOperator()).to.eql(ol.expr.LogicalOp.AND); + expect(filter.getOperator()).to.equal(ol.expr.LogicalOp.AND); expect(filter.getLeft() instanceof ol.expr.Comparison).to.be.ok(); - expect(filter.getLeft().getOperator()).to.eql(ol.expr.ComparisonOp.GTE); - expect(filter.getLeft().getLeft()).to.eql('number'); - expect(filter.getLeft().getRight()).to.eql(0); + expect(filter.getLeft().getOperator()).to.equal( + ol.expr.ComparisonOp.GTE); + expect(filter.getLeft().getLeft().getName()).to.equal('number'); + expect(filter.getLeft().getRight().getValue()).to.equal(0); expect(filter.getRight() instanceof ol.expr.Comparison).to.be.ok(); - expect(filter.getRight().getOperator()).to.eql( + expect(filter.getRight().getOperator()).to.equal( ol.expr.ComparisonOp.LTE); - expect(filter.getRight().getLeft()).to.eql('number'); - expect(filter.getRight().getRight()).to.eql(100); + expect(filter.getRight().getLeft().getName()).to.equal('number'); + expect(filter.getRight().getRight().getValue()).to.equal(100); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -82,16 +83,17 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Logical).to.be.ok(); - expect(filter.getOperator()).to.eql(ol.expr.LogicalOp.AND); + expect(filter.getOperator()).to.equal(ol.expr.LogicalOp.AND); expect(filter.getLeft() instanceof ol.expr.Comparison).to.be.ok(); - expect(filter.getLeft().getOperator()).to.eql(ol.expr.ComparisonOp.GTE); - expect(filter.getLeft().getLeft()).to.eql('number'); - expect(filter.getLeft().getRight()).to.eql(0); + expect(filter.getLeft().getOperator()).to.equal( + ol.expr.ComparisonOp.GTE); + expect(filter.getLeft().getLeft().getName()).to.equal('number'); + expect(filter.getLeft().getRight().getValue()).to.equal(0); expect(filter.getRight() instanceof ol.expr.Comparison).to.be.ok(); - expect(filter.getRight().getOperator()).to.eql( + expect(filter.getRight().getOperator()).to.equal( ol.expr.ComparisonOp.LTE); - expect(filter.getRight().getLeft()).to.eql('number'); - expect(filter.getRight().getRight()).to.eql(100); + expect(filter.getRight().getLeft().getName()).to.equal('number'); + expect(filter.getRight().getRight().getValue()).to.equal(100); done(); }); }); @@ -101,8 +103,8 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Comparison).to.be.ok(); - expect(filter.getLeft()).to.eql('prop'); - expect(filter.getRight()).to.eql(null); + expect(filter.getLeft().getName()).to.equal('prop'); + expect(filter.getRight().getValue()).to.equal(null); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -114,7 +116,10 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.EXTENT), - [-180, -90, 180, 90, 'EPSG:4326', 'the_geom']); + [new ol.expr.Literal(-180), new ol.expr.Literal(-90), + new ol.expr.Literal(180), new ol.expr.Literal(90), + new ol.expr.Literal('EPSG:4326'), + new ol.expr.Identifier('the_geom')]); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -126,7 +131,9 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.EXTENT), - [-180, -90, 180, 90, 'EPSG:4326']); + [new ol.expr.Literal(-180), new ol.expr.Literal(-90), + new ol.expr.Literal(180), new ol.expr.Literal(90), + new ol.expr.Literal('EPSG:4326')]); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -138,8 +145,9 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Call(new ol.expr.Identifier( ol.expr.functions.DWITHIN), - [new ol.geom.Point([2488789, 289552]), 1000, 'm', undefined, - 'Geometry']); + [new ol.expr.Literal(new ol.geom.Point([2488789, 289552])), + new ol.expr.Literal(1000), new ol.expr.Literal('m'), + new ol.expr.Literal(null), new ol.expr.Identifier('Geometry')]); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); filter = parser.read(xml); @@ -160,9 +168,11 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Logical(ol.expr.LogicalOp.OR, new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.LIKE), - ['person', 'me', '*', '.', '!']), + [new ol.expr.Identifier('person'), new ol.expr.Literal('me'), + new ol.expr.Literal('*'), new ol.expr.Literal('.'), + new ol.expr.Literal('!')]), new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.FID), - ['foo.1', 'foo.2'])); + [new ol.expr.Literal('foo.1'), new ol.expr.Literal('foo.2')])); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -176,9 +186,11 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND, new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.LIKE), - ['person', 'me', '*', '.', '!']), + [new ol.expr.Identifier('person'), new ol.expr.Literal('me'), + new ol.expr.Literal('*'), new ol.expr.Literal('.'), + new ol.expr.Literal('!')]), new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.FID), - ['foo.1', 'foo.2'])); + [new ol.expr.Literal('foo.1'), new ol.expr.Literal('foo.2')])); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -192,7 +204,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Not( new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.FID), - ['foo.2'])); + [new ol.expr.Literal('foo.2')])); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -211,8 +223,10 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { // ISO 8601: 2011-12-27T18:19:15.123Z var end = new Date(Date.UTC(2011, 11, 27, 18, 19, 15, 123)); var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND, - new ol.expr.Comparison(ol.expr.ComparisonOp.GTE, 'when', start), - new ol.expr.Comparison(ol.expr.ComparisonOp.LTE, 'when', end)); + new ol.expr.Comparison(ol.expr.ComparisonOp.GTE, + new ol.expr.Identifier('when'), new ol.expr.Literal(start)), + new ol.expr.Comparison(ol.expr.ComparisonOp.LTE, + new ol.expr.Identifier('when'), new ol.expr.Literal(end))); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -229,6 +243,7 @@ goog.require('ol.expr.Call'); goog.require('ol.expr.Comparison'); goog.require('ol.expr.ComparisonOp'); goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); goog.require('ol.expr.Logical'); goog.require('ol.expr.LogicalOp'); goog.require('ol.expr.Not'); diff --git a/test/spec/ol/parser/ogc/filter_v1_1_0.test.js b/test/spec/ol/parser/ogc/filter_v1_1_0.test.js index 695a848d65..9d7d06bd3d 100644 --- a/test/spec/ol/parser/ogc/filter_v1_1_0.test.js +++ b/test/spec/ol/parser/ogc/filter_v1_1_0.test.js @@ -11,30 +11,36 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { afterLoadXml(url, function(xml) { var filter = parser.read(xml); expect(filter instanceof ol.expr.Logical).to.be(true); - expect(filter.getOperator()).to.eql(ol.expr.LogicalOp.OR); + expect(filter.getOperator()).to.equal(ol.expr.LogicalOp.OR); var filters = []; parser.getSubfiltersForLogical_(filter, filters); - expect(filters.length).to.eql(5); + expect(filters.length).to.equal(5); expect(filters[0]).to.eql(new ol.expr.Logical(ol.expr.LogicalOp.AND, new ol.expr.Comparison( - ol.expr.ComparisonOp.GTE, 'number', 1064866676), + ol.expr.ComparisonOp.GTE, new ol.expr.Identifier('number'), + new ol.expr.Literal(1064866676)), new ol.expr.Comparison( - ol.expr.ComparisonOp.LTE, 'number', 1065512599))); + ol.expr.ComparisonOp.LTE, new ol.expr.Identifier('number'), + new ol.expr.Literal(1065512599)))); expect(filters[1]).to.eql(new ol.expr.Not(new ol.expr.Comparison( - ol.expr.ComparisonOp.LTE, 'FOO', 5000))); + ol.expr.ComparisonOp.LTE, new ol.expr.Identifier('FOO'), + new ol.expr.Literal(5000)))); expect(filters[2] instanceof ol.expr.Call).to.be(true); - expect(filters[2].getCallee().getName()).to.eql( + expect(filters[2].getCallee().getName()).to.equal( ol.expr.functions.LIKE); - expect(filters[2].getArgs()).to.eql(['cat', '*dog.food!*good', '*', - '.', '!', null]); + expect(filters[2].getArgs()).to.eql([new ol.expr.Identifier('cat'), + new ol.expr.Literal('*dog.food!*good'), new ol.expr.Literal('*'), + new ol.expr.Literal('.'), new ol.expr.Literal('!'), + new ol.expr.Literal(null)]); expect(filters[3] instanceof ol.expr.Call).to.be(true); - expect(filters[3].getCallee().getName()).to.eql( + expect(filters[3].getCallee().getName()).to.equal( ol.expr.functions.IEQ); - expect(filters[3].getArgs()).to.eql(['cat', 'dog']); + expect(filters[3].getArgs()).to.eql([new ol.expr.Identifier('cat'), + new ol.expr.Literal('dog')]); expect(filters[4] instanceof ol.expr.Comparison).to.be(true); - expect(filters[4].getOperator()).to.eql(ol.expr.ComparisonOp.EQ); - expect(filters[4].getLeft()).to.eql('cat'); - expect(filters[4].getRight()).to.eql('dog'); + expect(filters[4].getOperator()).to.equal(ol.expr.ComparisonOp.EQ); + expect(filters[4].getLeft().getName()).to.equal('cat'); + expect(filters[4].getRight().getValue()).to.equal('dog'); done(); }); }); @@ -109,7 +115,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { c = cases[i]; filter = parser.read(c.str); var matchCase = (filter instanceof ol.expr.Call) ? false : true; - expect(matchCase).to.eql(c.exp); + expect(matchCase).to.equal(c.exp); } }); @@ -149,8 +155,10 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { var filter = new ol.expr.Call(new ol.expr.Identifier( ol.expr.functions.INTERSECTS), [new ol.expr.Call(new ol.expr.Identifier('querySingle'), - ['sf:restricted', 'the_geom', - 'cat=3']), undefined, 'the_geom']); + [new ol.expr.Literal('sf:restricted'), + new ol.expr.Literal('the_geom'), + new ol.expr.Literal('cat=3')]), new ol.expr.Literal(null), + new ol.expr.Identifier('the_geom')]); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -162,8 +170,9 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND, new ol.expr.Call(new ol.expr.Identifier(ol.expr.functions.INEQ), - ['FOO', new ol.expr.Call(new ol.expr.Identifier('customFunction'), - ['param1', 'param2'])])); + [new ol.expr.Identifier('FOO'), new ol.expr.Call( + new ol.expr.Identifier('customFunction'), + [new ol.expr.Literal('param1'), new ol.expr.Literal('param2')])])); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -177,8 +186,11 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { ol.expr.functions.DWITHIN), [new ol.expr.Call(new ol.expr.Identifier('collectGeometries'), [new ol.expr.Call(new ol.expr.Identifier('queryCollection'), - ['sf:roads', 'the_geom', 'INCLUDE'])]), 200, 'meters', - undefined, 'the_geom']); + [new ol.expr.Literal('sf:roads'), + new ol.expr.Literal('the_geom'), + new ol.expr.Literal('INCLUDE')])]), new ol.expr.Literal(200), + new ol.expr.Literal('meters'), + new ol.expr.Literal(null), new ol.expr.Identifier('the_geom')]); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -190,7 +202,9 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { afterLoadXml(url, function(xml) { var filter = new ol.expr.Call( new ol.expr.Identifier(ol.expr.functions.LIKE), - ['person', '*me*', '*', '.', '!', false]); + [new ol.expr.Identifier('person'), new ol.expr.Literal('*me*'), + new ol.expr.Literal('*'), new ol.expr.Literal('.'), + new ol.expr.Literal('!'), new ol.expr.Literal(false)]); var output = parser.write(filter); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); done(); @@ -202,11 +216,11 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { afterLoadXml(url, function(xml) { var writer = parser.writers['http://www.opengis.net/ogc']['SortBy']; var output = writer.call(parser, [{ - 'property': 'Title', - 'order': 'ASC' + 'property': new ol.expr.Identifier('Title'), + 'order': new ol.expr.Literal('ASC') },{ - 'property': 'Relevance', - 'order': 'DESC' + 'property': new ol.expr.Identifier('Relevance'), + 'order': new ol.expr.Literal('DESC') }]); expect(output).to.xmleql(xml); done(); @@ -223,6 +237,7 @@ goog.require('ol.expr.Call'); goog.require('ol.expr.Comparison'); goog.require('ol.expr.ComparisonOp'); goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); goog.require('ol.expr.Logical'); goog.require('ol.expr.LogicalOp'); goog.require('ol.expr.Not');