Making consistent the evaluate method of filters. The evaluate method accepts vector features, making possible logical filters that combine spatial and comparison filters. r=ahocevar (closes #2773)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@10596 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -42,7 +42,8 @@ OpenLayers.Filter = OpenLayers.Class({
|
|||||||
* subclasses.
|
* subclasses.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* context - {Object} Context to use in evaluating the filter.
|
* context - {Object} Context to use in evaluating the filter. If a vector
|
||||||
|
* feature is provided, the feature.attributes will be used as context.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* {Boolean} The filter applies.
|
* {Boolean} The filter applies.
|
||||||
|
|||||||
@@ -93,20 +93,23 @@ OpenLayers.Filter.Comparison = OpenLayers.Class(OpenLayers.Filter, {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* APIMethod: evaluate
|
* APIMethod: evaluate
|
||||||
* Evaluates this filter in a specific context. Should be implemented by
|
* Evaluates this filter in a specific context.
|
||||||
* subclasses.
|
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* context - {Object} Context to use in evaluating the filter.
|
* context - {Object} Context to use in evaluating the filter. If a vector
|
||||||
|
* feature is provided, the feature.attributes will be used as context.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* {Boolean} The filter applies.
|
* {Boolean} The filter applies.
|
||||||
*/
|
*/
|
||||||
evaluate: function(context) {
|
evaluate: function(context) {
|
||||||
|
if (context instanceof OpenLayers.Feature.Vector) {
|
||||||
|
context = context.attributes;
|
||||||
|
}
|
||||||
var result = false;
|
var result = false;
|
||||||
|
var got = context[this.property];
|
||||||
switch(this.type) {
|
switch(this.type) {
|
||||||
case OpenLayers.Filter.Comparison.EQUAL_TO:
|
case OpenLayers.Filter.Comparison.EQUAL_TO:
|
||||||
var got = context[this.property];
|
|
||||||
var exp = this.value;
|
var exp = this.value;
|
||||||
if(!this.matchCase &&
|
if(!this.matchCase &&
|
||||||
typeof got == "string" && typeof exp == "string") {
|
typeof got == "string" && typeof exp == "string") {
|
||||||
@@ -116,7 +119,6 @@ OpenLayers.Filter.Comparison = OpenLayers.Class(OpenLayers.Filter, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:
|
case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:
|
||||||
var got = context[this.property];
|
|
||||||
var exp = this.value;
|
var exp = this.value;
|
||||||
if(!this.matchCase &&
|
if(!this.matchCase &&
|
||||||
typeof got == "string" && typeof exp == "string") {
|
typeof got == "string" && typeof exp == "string") {
|
||||||
@@ -126,24 +128,24 @@ OpenLayers.Filter.Comparison = OpenLayers.Class(OpenLayers.Filter, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.LESS_THAN:
|
case OpenLayers.Filter.Comparison.LESS_THAN:
|
||||||
result = context[this.property] < this.value;
|
result = got < this.value;
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.GREATER_THAN:
|
case OpenLayers.Filter.Comparison.GREATER_THAN:
|
||||||
result = context[this.property] > this.value;
|
result = got > this.value;
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:
|
case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:
|
||||||
result = context[this.property] <= this.value;
|
result = got <= this.value;
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:
|
case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:
|
||||||
result = context[this.property] >= this.value;
|
result = got >= this.value;
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.BETWEEN:
|
case OpenLayers.Filter.Comparison.BETWEEN:
|
||||||
result = (context[this.property] >= this.lowerBoundary) &&
|
result = (got >= this.lowerBoundary) &&
|
||||||
(context[this.property] <= this.upperBoundary);
|
(got <= this.upperBoundary);
|
||||||
break;
|
break;
|
||||||
case OpenLayers.Filter.Comparison.LIKE:
|
case OpenLayers.Filter.Comparison.LIKE:
|
||||||
var regexp = new RegExp(this.value, "gi");
|
var regexp = new RegExp(this.value, "gi");
|
||||||
result = regexp.test(context[this.property]);
|
result = regexp.test(got);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -58,11 +58,12 @@ OpenLayers.Filter.Logical = OpenLayers.Class(OpenLayers.Filter, {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* APIMethod: evaluate
|
* APIMethod: evaluate
|
||||||
* Evaluates this filter in a specific context. Should be implemented by
|
* Evaluates this filter in a specific context.
|
||||||
* subclasses.
|
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* context - {Object} Context to use in evaluating the filter.
|
* context - {Object} Context to use in evaluating the filter. A vector
|
||||||
|
* feature may also be provided to evaluate feature attributes in
|
||||||
|
* comparison filters or geometries in spatial filters.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* {Boolean} The filter applies.
|
* {Boolean} The filter applies.
|
||||||
|
|||||||
@@ -175,7 +175,117 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_evaluate_feature(t) {
|
||||||
|
|
||||||
|
var cases = [{
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.BETWEEN,
|
||||||
|
property: "area",
|
||||||
|
lowerBoundary: 1000,
|
||||||
|
upperBoundary: 4999
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {area: 999}),
|
||||||
|
expect: false
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.BETWEEN,
|
||||||
|
property: "area",
|
||||||
|
lowerBoundary: 1000,
|
||||||
|
upperBoundary: 4999
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {area: 1000}),
|
||||||
|
expect: true
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.BETWEEN,
|
||||||
|
property: "area",
|
||||||
|
lowerBoundary: 1000,
|
||||||
|
upperBoundary: 4999
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {area: 4999}),
|
||||||
|
expect: true
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.BETWEEN,
|
||||||
|
property: "area",
|
||||||
|
lowerBoundary: 1000,
|
||||||
|
upperBoundary: 4999
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {area: 5000}),
|
||||||
|
expect: false
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.BETWEEN,
|
||||||
|
property: "area",
|
||||||
|
lowerBoundary: 1000,
|
||||||
|
upperBoundary: 4999
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {area: 999}),
|
||||||
|
expect: false
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.EQUAL_TO,
|
||||||
|
property: "prop",
|
||||||
|
value: "Foo"
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {prop: "Foo"}),
|
||||||
|
expect: true
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.EQUAL_TO,
|
||||||
|
property: "prop",
|
||||||
|
value: "Foo"
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {prop: "foo"}),
|
||||||
|
expect: false
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.EQUAL_TO,
|
||||||
|
matchCase: true,
|
||||||
|
property: "prop",
|
||||||
|
value: "Foo"
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {prop: "foo"}),
|
||||||
|
expect: false
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
|
||||||
|
property: "prop",
|
||||||
|
value: "foo"
|
||||||
|
}),
|
||||||
|
context: {prop: "FOO"},
|
||||||
|
expect: true
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
|
||||||
|
matchCase: true,
|
||||||
|
property: "prop",
|
||||||
|
value: "foo"
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {prop: "FOO"}),
|
||||||
|
expect: true
|
||||||
|
}, {
|
||||||
|
filter: new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
|
||||||
|
matchCase: false,
|
||||||
|
property: "prop",
|
||||||
|
value: "foo"
|
||||||
|
}),
|
||||||
|
context: new OpenLayers.Feature.Vector(null, {prop: "FOO"}),
|
||||||
|
expect: false
|
||||||
|
}];
|
||||||
|
|
||||||
|
t.plan(cases.length);
|
||||||
|
|
||||||
|
var c;
|
||||||
|
for(var i=0; i<cases.length; ++i) {
|
||||||
|
c = cases[i];
|
||||||
|
t.eq(c.filter.evaluate(c.context), c.expect, "case " + i + ": " + c.filter.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function test_clone(t) {
|
function test_clone(t) {
|
||||||
|
|
||||||
t.plan(3);
|
t.plan(3);
|
||||||
|
|||||||
@@ -35,6 +35,75 @@
|
|||||||
"feature evaluates to false correctly.");
|
"feature evaluates to false correctly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_evaluate_feature(t) {
|
||||||
|
t.plan(6);
|
||||||
|
|
||||||
|
var feature = new OpenLayers.Feature.Vector(null, {
|
||||||
|
pop: 200,
|
||||||
|
name: "foo"
|
||||||
|
});
|
||||||
|
|
||||||
|
var smallPop = new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.LESS_THAN,
|
||||||
|
property: "pop",
|
||||||
|
value: 120
|
||||||
|
});
|
||||||
|
|
||||||
|
var bigPop = new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.GREATER_THAN,
|
||||||
|
property: "pop",
|
||||||
|
value: 120
|
||||||
|
});
|
||||||
|
|
||||||
|
var namedFoo = new OpenLayers.Filter.Comparison({
|
||||||
|
type: OpenLayers.Filter.Comparison.EQUAL_TO,
|
||||||
|
property: "name",
|
||||||
|
value: "foo"
|
||||||
|
});
|
||||||
|
|
||||||
|
var filter;
|
||||||
|
|
||||||
|
// test simple not
|
||||||
|
filter = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.NOT,
|
||||||
|
filters: [smallPop]
|
||||||
|
});
|
||||||
|
t.eq(filter.evaluate(feature), true, "not smallPop");
|
||||||
|
|
||||||
|
filter = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.NOT,
|
||||||
|
filters: [bigPop]
|
||||||
|
});
|
||||||
|
t.eq(filter.evaluate(feature), false, "not bigPop");
|
||||||
|
|
||||||
|
// test or
|
||||||
|
filter = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.OR,
|
||||||
|
filters: [smallPop, namedFoo]
|
||||||
|
});
|
||||||
|
t.eq(filter.evaluate(feature), true, "smallPop or namedFoo");
|
||||||
|
|
||||||
|
filter = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.OR,
|
||||||
|
filters: [bigPop, namedFoo]
|
||||||
|
});
|
||||||
|
t.eq(filter.evaluate(feature), true, "bigPop or namedFoo");
|
||||||
|
|
||||||
|
// test and
|
||||||
|
filter = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.AND,
|
||||||
|
filters: [smallPop, namedFoo]
|
||||||
|
});
|
||||||
|
t.eq(filter.evaluate(feature), false, "smallPop and namedFoo");
|
||||||
|
|
||||||
|
filter = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.AND,
|
||||||
|
filters: [bigPop, namedFoo]
|
||||||
|
});
|
||||||
|
t.eq(filter.evaluate(feature), true, "bigPop and namedFoo");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function test_clone(t) {
|
function test_clone(t) {
|
||||||
|
|
||||||
t.plan(2);
|
t.plan(2);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function test_evaluate(t) {
|
function test_evaluate(t) {
|
||||||
t.plan(4);
|
t.plan(8);
|
||||||
|
|
||||||
var filer, feature, res, geom, bounds;
|
var filer, feature, res, geom, bounds;
|
||||||
|
|
||||||
@@ -33,21 +33,25 @@
|
|||||||
value: bounds
|
value: bounds
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1 test
|
var not = new OpenLayers.Filter.Logical({
|
||||||
|
type: OpenLayers.Filter.Logical.NOT,
|
||||||
|
filters: [filter]
|
||||||
|
});
|
||||||
|
|
||||||
feature = new OpenLayers.Feature.Vector(
|
feature = new OpenLayers.Feature.Vector(
|
||||||
new OpenLayers.Geometry.Point(2, 2));
|
new OpenLayers.Geometry.Point(2, 2));
|
||||||
res = filter.evaluate(feature);
|
res = filter.evaluate(feature);
|
||||||
t.eq(res, true,
|
t.eq(res, true,
|
||||||
"evaluates returns correct value when feature intersects bounds");
|
"evaluates returns correct value when feature intersects bounds");
|
||||||
|
t.eq(not.evaluate(feature), !res, "not bbox");
|
||||||
// 1 test
|
|
||||||
feature = new OpenLayers.Feature.Vector(
|
feature = new OpenLayers.Feature.Vector(
|
||||||
new OpenLayers.Geometry.Point(20, 20));
|
new OpenLayers.Geometry.Point(20, 20));
|
||||||
res = filter.evaluate(feature);
|
res = filter.evaluate(feature);
|
||||||
t.eq(res, false,
|
t.eq(res, false,
|
||||||
"evaluates returns correct value when feature does not intersect bounds");
|
"evaluates returns correct value when feature does not intersect bounds");
|
||||||
|
t.eq(not.evaluate(feature), !res, "not outside bbox");
|
||||||
|
|
||||||
// 1 test
|
|
||||||
geom = bounds.toGeometry();
|
geom = bounds.toGeometry();
|
||||||
feature = new OpenLayers.Feature.Vector(
|
feature = new OpenLayers.Feature.Vector(
|
||||||
new OpenLayers.Geometry.Point(2, 2));
|
new OpenLayers.Geometry.Point(2, 2));
|
||||||
@@ -58,8 +62,9 @@
|
|||||||
res = filter.evaluate(feature);
|
res = filter.evaluate(feature);
|
||||||
t.eq(res, true,
|
t.eq(res, true,
|
||||||
"evaluates returns correct value when feature intersects bounds");
|
"evaluates returns correct value when feature intersects bounds");
|
||||||
|
not.filters = [filter];
|
||||||
|
t.eq(not.evaluate(feature), !res, "not intersection");
|
||||||
|
|
||||||
// 1 test
|
|
||||||
geom = bounds.toGeometry();
|
geom = bounds.toGeometry();
|
||||||
feature = new OpenLayers.Feature.Vector(
|
feature = new OpenLayers.Feature.Vector(
|
||||||
new OpenLayers.Geometry.Point(20, 20));
|
new OpenLayers.Geometry.Point(20, 20));
|
||||||
@@ -67,9 +72,13 @@
|
|||||||
type: OpenLayers.Filter.Spatial.INTERSECTS,
|
type: OpenLayers.Filter.Spatial.INTERSECTS,
|
||||||
value: geom
|
value: geom
|
||||||
});
|
});
|
||||||
|
not.filters = [filter];
|
||||||
res = filter.evaluate(feature);
|
res = filter.evaluate(feature);
|
||||||
t.eq(res, false,
|
t.eq(res, false,
|
||||||
"evaluates returns correct value when feature does not intersect bounds");
|
"evaluates returns correct value when feature does not intersect bounds");
|
||||||
|
t.eq(not.evaluate(feature), !res, "not non-intersection");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_clone(t) {
|
function test_clone(t) {
|
||||||
|
|||||||
Reference in New Issue
Block a user