Merge pull request #3 from tschaub/bartvde-ogcfilter2
Suggestions for filter encoding
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 = '<ogc:UpperBoundary xmlns:ogc="' +
|
||||
'http://www.opengis.net/ogc">10</ogc:UpperBoundary>';
|
||||
@@ -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 = '<ogc:UpperBoundary xmlns:ogc="http://www.opengis.net/ogc">' +
|
||||
'foo<ogc:PropertyName>x</ogc:PropertyName>bar</ogc:UpperBoundary>';
|
||||
|
||||
@@ -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:
|
||||
'<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">' +
|
||||
@@ -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'];
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/filter/1.0.0/filter.xsd">
|
||||
<ogc:PropertyIsBetween>
|
||||
<ogc:PropertyName>when</ogc:PropertyName>
|
||||
<ogc:LowerBoundary>
|
||||
<ogc:Literal>2010-11-27T18:19:15.123Z</ogc:Literal>
|
||||
</ogc:LowerBoundary>
|
||||
<ogc:UpperBoundary>
|
||||
<ogc:Literal>2011-12-27T18:19:15.123Z</ogc:Literal>
|
||||
</ogc:UpperBoundary>
|
||||
</ogc:PropertyIsBetween>
|
||||
</ogc:Filter>
|
||||
@@ -1,11 +0,0 @@
|
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||
<ogc:PropertyIsBetween>
|
||||
<ogc:PropertyName>when</ogc:PropertyName>
|
||||
<ogc:LowerBoundary>
|
||||
<ogc:Literal>2010-11-27</ogc:Literal>
|
||||
</ogc:LowerBoundary>
|
||||
<ogc:UpperBoundary>
|
||||
<ogc:Literal>2011-12-27</ogc:Literal>
|
||||
</ogc:UpperBoundary>
|
||||
</ogc:PropertyIsBetween>
|
||||
</ogc:Filter>
|
||||
Reference in New Issue
Block a user