diff --git a/src/ol/parser/ogc/filter_v1.js b/src/ol/parser/ogc/filter_v1.js index b390e61db6..1deca301fa 100644 --- a/src/ol/parser/ogc/filter_v1.js +++ b/src/ol/parser/ogc/filter_v1.js @@ -12,6 +12,8 @@ goog.require('ol.expr.Identifier'); goog.require('ol.expr.Literal'); goog.require('ol.expr.Logical'); goog.require('ol.expr.LogicalOp'); +goog.require('ol.expr.Math'); +goog.require('ol.expr.MathOp'); goog.require('ol.expr.Not'); goog.require('ol.expr.functions'); goog.require('ol.parser.XML'); @@ -28,34 +30,49 @@ ol.parser.ogc.Filter_v1 = function() { this.readers = { 'http://www.opengis.net/ogc': { _expression: function(node) { - var obj, source = ''; + var expressions = []; + var obj, value, numValue, expr; for (var child = node.firstChild; child; child = child.nextSibling) { switch (child.nodeType) { case 1: obj = this.readNode(child); if (obj.property) { - var name = obj.property.getName(); - source += (source !== '') ? '+' + name : name; + expressions.push(obj.property); } else if (goog.isDef(obj.value)) { return obj.value; } break; case 3: // text node case 4: // cdata section - if (source !== '') { - source += '+'; - } - if (isNaN(goog.string.toNumber(child.nodeValue))) { - source += goog.string.quote(goog.string.trim(child.nodeValue)); - } else { - source += goog.string.trim(child.nodeValue); + value = goog.string.trim(child.nodeValue); + // no need to concatenate empty strings + if (value) { + // check for numeric values + numValue = goog.string.toNumber(value); + if (!isNaN(numValue)) { + value = numValue; + } + expressions.push(new ol.expr.Literal(value)); } break; default: break; } } - return ol.expr.parse(source); + // if we have more than one property or literal, we concatenate them + var num = expressions.length; + if (num === 1) { + expr = expressions[0]; + } else { + expr = new ol.expr.Literal(''); + if (num > 1) { + var add = ol.expr.MathOp.ADD; + for (var i = 0; i < num; ++i) { + expr = new ol.expr.Math(add, expr, expressions[i]); + } + } + } + return expr; }, 'Filter': function(node, obj) { var container = { @@ -217,7 +234,8 @@ ol.parser.ogc.Filter_v1 = function() { ol.expr.functions.DWITHIN); }, 'Distance': function(node, obj) { - obj.distance = new ol.expr.Literal(this.getChildValue(node)); + var value = goog.string.toNumber(this.getChildValue(node)); + obj.distance = new ol.expr.Literal(value); obj.distanceUnits = new ol.expr.Literal(node.getAttribute('units')); } } @@ -328,12 +346,8 @@ ol.parser.ogc.Filter_v1 = function() { }, 'Literal': function(expr) { goog.asserts.assert(expr instanceof ol.expr.Literal); - var value = expr.getValue(); - if (value instanceof Date) { - value = value.toISOString(); - } var node = this.createElementNS('ogc:Literal'); - node.appendChild(this.createTextNode(value)); + node.appendChild(this.createTextNode(expr.getValue())); return node; }, 'LowerBoundary': function(expr) { 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 87ec4afffa..be7de99cee 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 @@ -4,9 +4,9 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { var parser = new ol.parser.ogc.Filter_v1_0_0(); - describe('#readwrite', function() { + describe('reading and writing', function() { - it('intersects filter read / written correctly', function(done) { + it('handles intersects', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/intersects.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -23,7 +23,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('within filter read / written correctly', function(done) { + it('handles within', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/within.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -39,7 +39,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('contains filter read / written correctly', function(done) { + it('handles contains', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/contains.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -56,18 +56,18 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('between filter read / written correctly', function(done) { + it('handles between', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/between.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); - expect(filter instanceof ol.expr.Logical).to.be.ok(); + expect(filter).to.be.a(ol.expr.Logical); expect(filter.getOperator()).to.equal(ol.expr.LogicalOp.AND); - expect(filter.getLeft() instanceof ol.expr.Comparison).to.be.ok(); + expect(filter.getLeft()).to.be.a(ol.expr.Comparison); 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()).to.be.a(ol.expr.Comparison); expect(filter.getRight().getOperator()).to.equal( ol.expr.ComparisonOp.LTE); expect(filter.getRight().getLeft().getName()).to.equal('number'); @@ -78,18 +78,18 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('between filter read correctly without literals', function(done) { + it('handles between without literals', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/between2.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); - expect(filter instanceof ol.expr.Logical).to.be.ok(); + expect(filter).to.be.a(ol.expr.Logical); expect(filter.getOperator()).to.equal(ol.expr.LogicalOp.AND); - expect(filter.getLeft() instanceof ol.expr.Comparison).to.be.ok(); + expect(filter.getLeft()).to.be.a(ol.expr.Comparison); 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()).to.be.a(ol.expr.Comparison); expect(filter.getRight().getOperator()).to.equal( ol.expr.ComparisonOp.LTE); expect(filter.getRight().getLeft().getName()).to.equal('number'); @@ -98,11 +98,11 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('null filter read / written correctly', function(done) { + it('handles null', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/null.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); - expect(filter instanceof ol.expr.Comparison).to.be.ok(); + expect(filter).to.be.a(ol.expr.Comparison); expect(filter.getLeft().getName()).to.equal('prop'); expect(filter.getRight().getValue()).to.equal(null); var output = parser.write(filter); @@ -111,7 +111,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('BBOX written correctly', function(done) { + it('writes BBOX', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/bbox.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Call( @@ -126,7 +126,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('BBOX without geometry name written correctly', function(done) { + it('writes BBOX without geometry name', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/bbox_nogeom.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Call( @@ -140,7 +140,28 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('DWithin written correctly', function(done) { + it('reads DWithin', function(done) { + var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/dwithin.xml'; + afterLoadXml(url, function(xml) { + var filter = parser.read(xml); + expect(filter).to.be.a(ol.expr.Call); + var callee = filter.getCallee(); + expect(callee).to.be.a(ol.expr.Identifier); + var name = callee.getName(); + expect(name).to.equal(ol.expr.functions.DWITHIN); + var args = filter.getArgs(); + expect(args.length).to.equal(5); + var distance = args[1]; + expect(distance).to.be.a(ol.expr.Literal); + expect(distance.getValue()).to.equal(1000); + var units = args[2]; + expect(units).to.be.a(ol.expr.Literal); + expect(units.getValue()).to.equal('m'); + done(); + }); + }); + + it('writes DWithin', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/dwithin.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Call(new ol.expr.Identifier( @@ -161,9 +182,9 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { // the Filter Encoding spec doesn't allow for FID filters inside logical // filters however, to be liberal, we will write them without complaining - describe('#logicalfid', function() { + describe('logical fid', function() { - it('logical filter [OR] with fid filter written correctly', function(done) { + it('writes logical [OR] with fid', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/logicalfeatureid.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Logical(ol.expr.LogicalOp.OR, @@ -179,7 +200,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('logical filter [AND] with fid filter written correctly', + it('writes logical [AND] with fid', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/' + 'logicalfeatureidand.xml'; @@ -197,7 +218,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); }); - it('logical filter [NOT] with fid filter written correctly', + it('writes logical [NOT] with fid', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/' + 'logicalfeatureidnot.xml'; @@ -213,30 +234,8 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { }); - describe('#date', function() { - - it('date writing works as expected', function(done) { - var url = 'spec/ol/parser/ogc/xml/filter_v1_0_0/betweendates.xml'; - afterLoadXml(url, function(xml) { - // ISO 8601: 2010-11-27T18:19:15.123Z - var start = new Date(Date.UTC(2010, 10, 27, 18, 19, 15, 123)); - // 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, - 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(); - }); - }); - - }); - - describe('_expression reader works as expected', function() { - it('_expression reader handles combined propertyname and literal', + describe('_expression reader', function() { + it('handles combined propertyname and literal', function() { var xml = '10'; @@ -244,7 +243,7 @@ describe('ol.parser.ogc.Filter_v1_0_0', function() { '_expression']; var expr = reader.call(parser, goog.dom.xml.loadXml( xml).documentElement); - expect(expr instanceof ol.expr.Literal).to.be.ok(); + expect(expr).to.be.a(ol.expr.Literal); expect(expr.getValue()).to.equal(10); xml = '' + 'fooxbar'; 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 9d7d06bd3d..b39fc59a0f 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 @@ -4,9 +4,9 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { var parser = new ol.parser.ogc.Filter_v1_1_0(); - describe('#readwrite', function() { + describe('reading and writing', function() { - it('filter read correctly', function(done) { + it('reads filter', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/test.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -45,7 +45,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('matchCase read correctly', function() { + it('reads matchCase', function() { var cases = [{ str: '' + @@ -119,7 +119,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { } }); - it('BBOX filter written correctly', function(done) { + it('writes BBOX', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/bbox.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -129,7 +129,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('BBOX filter without property name written correctly', function(done) { + it('writes BBOX without property name', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/bbox_nogeomname.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -139,7 +139,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('Intersects filter read / written correctly', function(done) { + it('handles intersects', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/intersects.xml'; afterLoadXml(url, function(xml) { var filter = parser.read(xml); @@ -149,7 +149,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('Filter functions written correctly', function(done) { + it('handles functions', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/function.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Call(new ol.expr.Identifier( @@ -165,7 +165,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('Custom filter functions written correctly', function(done) { + it('writes custom functions', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/customfunction.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Logical(ol.expr.LogicalOp.AND, @@ -179,7 +179,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('Nested filter functions written correctly', function(done) { + it('writes nested functions', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/nestedfunction.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Call(new ol.expr.Identifier( @@ -197,7 +197,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('matchCase written correctly on Like filter', function(done) { + it('writes matchCase on like', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/likematchcase.xml'; afterLoadXml(url, function(xml) { var filter = new ol.expr.Call( @@ -211,7 +211,7 @@ describe('ol.parser.ogc.Filter_v1_1_0', function() { }); }); - it('sortBy written correctly on Like filter', function(done) { + it('writes sortBy on like', function(done) { var url = 'spec/ol/parser/ogc/xml/filter_v1_1_0/sortby.xml'; afterLoadXml(url, function(xml) { var writer = parser.writers['http://www.opengis.net/ogc']['SortBy']; diff --git a/test/spec/ol/parser/ogc/xml/filter_v1_0_0/betweendates.xml b/test/spec/ol/parser/ogc/xml/filter_v1_0_0/betweendates.xml deleted file mode 100644 index 3ad5b0131e..0000000000 --- a/test/spec/ol/parser/ogc/xml/filter_v1_0_0/betweendates.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - when - - 2010-11-27T18:19:15.123Z - - - 2011-12-27T18:19:15.123Z - - - diff --git a/test/spec/ol/parser/ogc/xml/filter_v1_0_0/custombetweendates.xml b/test/spec/ol/parser/ogc/xml/filter_v1_0_0/custombetweendates.xml deleted file mode 100644 index f12024a9dd..0000000000 --- a/test/spec/ol/parser/ogc/xml/filter_v1_0_0/custombetweendates.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - when - - 2010-11-27 - - - 2011-12-27 - - -