Compare commits

...

4 Commits

Author SHA1 Message Date
Tom MacWright
fb702f3807 Stashing defilter work 2011-12-06 14:36:53 -05:00
Tom MacWright
ce691c95cd Simplify filter handling 2011-12-05 18:43:44 -05:00
Tom MacWright
c0526392dc Adding field 2011-12-05 14:08:30 -05:00
Tom MacWright
8b5ea80e5d refilter mode for carto 2011-12-05 13:46:51 -05:00
8 changed files with 116 additions and 472 deletions

View File

@ -52,7 +52,7 @@ var carto = {
[ 'alpha', 'anonymous', 'call', 'color', 'comment', 'definition', 'dimension',
'directive', 'element', 'expression', 'filterset', 'filter',
'keyword', 'layer', 'mixin', 'operation', 'quoted',
'keyword', 'layer', 'mixin', 'operation', 'quoted', 'field',
'reference', 'rule', 'ruleset', 'selector', 'style', 'url', 'value',
'variable', 'zoom', 'invalid', 'fontset'
].forEach(function(n) {

View File

@ -444,6 +444,14 @@ carto.Parser = function Parser(env) {
}
},
field: function() {
var name;
if (input.charAt(i) !== '[') return;
if (name = $(/^\[([^\]]+)\]/)) {
return new tree.Field(name[1]);
}
},
comparison: function() {
var str;
if (str = $(/^=|!=|<=|>=|<|>/)) {
@ -461,7 +469,9 @@ carto.Parser = function Parser(env) {
//
keyword: function() {
var k;
if (k = $(/^[A-Za-z-]+[A-Za-z-0-9_]*/)) { return new tree.Keyword(k) }
if (k = $(/^[A-Za-z-]+[A-Za-z-0-9_]*/)) {
return new tree.Keyword(k);
}
},
//
@ -786,16 +796,14 @@ carto.Parser = function Parser(env) {
}
},
filter: function() {
save();
var key, op, val;
if (! $('[')) return;
if (key = $(/^[a-zA-Z0-9-_]+/) || $(this.entities.quoted) || $(this.entities.variable)) {
if ((op = $(this.entities.comparison)) &&
(val = $(this.entities.quoted) || $(this.entities.variable) || $(/^[\w-\.]+/))) {
if (! $(']')) return;
return new tree.Filter(key, op, val, memo, env.filename);
}
var val;
if (!$('[')) return;
if (val = $(/(\[[^\]]+\]|[^\]])+/)) {
if (! $(']')) return;
return new tree.Filter(val[0], memo, env.filename);
}
},

View File

@ -68,7 +68,7 @@ tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) {
var xml = ' <Rule>\n';
xml += tree.Zoom.toXML(zoom).join('');
xml += this.filters.toXML(env);
// Sort symbolizers by the index of their first property definition
var sym_order = [], indexes = [];
for (var key in symbolizers) {

13
lib/carto/tree/field.js Normal file
View File

@ -0,0 +1,13 @@
(function(tree) {
tree.Field = function Keyword(value) {
this.value = value;
this.is = 'field';
};
tree.Field.prototype = {
eval: function() { return this },
toString: function() { return '[' + this.value + ']' }
};
})(require('../tree'));

View File

@ -1,56 +1,17 @@
(function(tree) {
tree.Filter = function Filter(key, op, val, index, filename) {
if (key.is) {
this.key = key.value;
this._key = key;
} else {
this.key = key;
}
tree.Filter = function Filter(val, index, filename) {
this.val = val;
this.op = op;
this.index = index;
this.filename = filename;
if (val.is) {
this.val = val.value;
this._val = val;
} else {
this.val = val;
}
if (this.op !== '=' && this.op !== '!=') {
this.val = 1 * this.val;
}
this.id = this.key + this.op + this.val;
};
// XML-safe versions of comparators
var opXML = {
'<': '&lt;',
'>': '&gt;',
'=': '=',
'!=': '!=',
'<=': '&lt;=',
'>=': '&gt;='
this.id = this.val;
};
tree.Filter.prototype.toXML = function(env) {
if (this.op !== '=' && this.op !== '!=' && isNaN(this.val)) {
env.error({
message: 'Cannot use operator "' + this.op + '" with value ' + this.val,
index: this.index,
filename: this.filename
});
}
if (this.val.eval) this._val = this.val.eval(env);
if (this.key.eval) this._key = this.key.eval(env);
if (this._key) var key = this._key.toString(false);
if (this._val) var val = this._val.toString(this._val.is == 'string');
return '[' + (key || this.key) + '] ' + opXML[this.op] + ' ' + (val || this.val);
// Handle variables correctly
return this.val;
};
tree.Filter.prototype.toString = function() {

View File

@ -1,207 +1,74 @@
var tree = require('../tree');
tree.Filterset = function Filterset() {};
tree.Filterset = function Filterset() {
this.filters = [];
};
Object.defineProperty(tree.Filterset.prototype, 'toXML', {
enumerable: false,
value: function(env) {
var filters = [];
for (var id in this) {
filters.push('(' + this[id].toXML(env).trim() + ')');
}
tree.Filterset.prototype.toXML = function(env) {
var filterXML = [];
if (filters.length) {
return ' <Filter>' + filters.join(' and ') + '</Filter>\n';
} else {
return '';
}
for (var id in this.filters) {
filterXML.push('(' + this.filters[id].toXML(env).trim() + ')');
}
});
Object.defineProperty(tree.Filterset.prototype, 'toString', {
enumerable: false,
value: function() {
var arr = [];
for (var id in this) arr.push(this[id].id);
arr.sort();
return arr.join('\t');
if (filterXML.length) {
return ' <Filter>' + filterXML.join(' and ') + '</Filter>\n';
} else {
return '';
}
});
};
Object.defineProperty(tree.Filterset.prototype, 'clone', {
enumerable: false,
value: function() {
var clone = new tree.Filterset();
for (var id in this) {
clone[id] = this[id];
}
return clone;
tree.Filterset.prototype.toString = function() {
var arr = [];
for (var id in this.filters) {
arr.push(this.filters[id].id);
}
});
arr.sort();
return arr.join('\t');
};
tree.Filterset.prototype.clone = function() {
var clone = new tree.Filterset();
for (var id in this.filters) {
clone[id] = this.filters[id];
}
return clone;
};
// Note: other has to be a tree.Filterset.
Object.defineProperty(tree.Filterset.prototype, 'cloneWith', {
enumerable: false,
value: function(other) {
var additions;
for (var id in other) {
var status = this.addable(other[id]);
if (status === false) {
return false;
}
if (status === true) {
// Adding the filter will override another value.
if (!additions) additions = [];
additions.push(other[id]);
}
}
// Adding the other filters doesn't make this filterset invalid, but it
// doesn't add anything to it either.
if (!additions) return null;
// We can successfully add all filters. Now clone the filterset and add the
// new rules.
var clone = new tree.Filterset();
// We can add the rules that are already present without going through the
// add function as a Filterset is always in it's simplest canonical form.
for (var id in this)
clone[id] = this[id];
// Only add new filters that actually change the filter.
while (id = additions.shift())
clone.add(id);
return clone;
tree.Filterset.prototype.cloneWith = function(other) {
var additions = [];
for (var id in other.filters) {
// Adding the filter will override another value.
additions.push(other.filters[id]);
}
});
/**
* Returns true when the new filter can be added, false otherwise.
*/
Object.defineProperty(tree.Filterset.prototype, 'addable', {
enumerable: false,
value: function(filter) {
var key = filter.key, value = filter.val;
// Adding the other filters doesn't make this filterset invalid, but it
// doesn't add anything to it either.
if (!additions.length) return null;
switch (filter.op) {
case '=':
if (key + '=' in this) return (this[key + '='].val != value) ? false : null;
if (key + '!=' + value in this) return false;
if (key + '>' in this && this[key + '>'].val >= value) return false;
if (key + '<' in this && this[key + '<'].val <= value) return false;
if (key + '>=' in this && this[key + '>='].val > value) return false;
if (key + '<=' in this && this[key + '<='].val < value) return false;
return true;
// We can successfully add all filters. Now clone the filterset and add the
// new rules.
var clone = new tree.Filterset();
case '!=':
if (key + '=' in this) return (this[key + '='].val == value) ? false : null;
if (key + '!=' + value in this) return null;
if (key + '>' in this && this[key + '>'].val >= value) return null;
if (key + '<' in this && this[key + '<'].val <= value) return null;
if (key + '>=' in this && this[key + '>='].val > value) return null;
if (key + '<=' in this && this[key + '<='].val < value) return null;
return true;
case '>':
if (key + '=' in this) return (this[key + '='].val <= value) ? false : null;
if (key + '<' in this && this[key + '<'].val <= value) return false;
if (key + '<=' in this && this[key + '<='].val <= value) return false;
if (key + '>' in this && this[key + '>'].val >= value) return null;
if (key + '>=' in this && this[key + '>='].val > value) return null;
return true;
case '>=':
if (key + '=' in this) return (this[key + '='].val < value) ? false : null;
if (key + '<' in this && this[key + '<'].val <= value) return false;
if (key + '<=' in this && this[key + '<='].val < value) return false;
if (key + '>' in this && this[key + '>'].val >= value) return null;
if (key + '>=' in this && this[key + '>='].val >= value) return null;
return true;
case '<':
if (key + '=' in this) return (this[key + '='].val >= value) ? false : null;
if (key + '>' in this && this[key + '>'].val >= value) return false;
if (key + '>=' in this && this[key + '>='].val >= value) return false;
if (key + '<' in this && this[key + '<'].val <= value) return null;
if (key + '<=' in this && this[key + '<='].val < value) return null;
return true;
case '<=':
if (key + '=' in this) return (this[key + '='].val > value) ? false : null;
if (key + '>' in this && this[key + '>'].val >= value) return false;
if (key + '>=' in this && this[key + '>='].val > value) return false;
if (key + '<' in this && this[key + '<'].val <= value) return null;
if (key + '<=' in this && this[key + '<='].val <= value) return null;
return true;
}
// We can add the rules that are already present without going through the
// add function as a Filterset is always in it's simplest canonical form.
for (var id in this.filters) {
clone.filters[id] = this.filters[id];
}
});
// Only add new filters that actually change the filter.
while (id = additions.shift()) {
clone.add(id);
}
return clone;
};
/**
* Only call this function for filters that have been cleared by .addable().
*/
Object.defineProperty(tree.Filterset.prototype, 'add', {
enumerable: false,
value: function(filter) {
var key = filter.key;
switch (filter.op) {
case '=':
for (var id in this)
if (this[id].key == key)
delete this[id];
this[key + '='] = filter;
break;
case '!=':
this[key + '!=' + filter.val] = filter;
break;
case '>':
for (var id in this)
if (this[id].key == key && this[id].val <= filter.val)
delete this[id];
this[key + '>'] = filter;
break;
case '>=':
for (var id in this)
if (this[id].key == key && this[id].val < filter.val)
delete this[id];
if (key + '!=' + filter.val in this) {
delete this[key + '!=' + filter.val];
filter.op = '>';
this[key + '>'] = filter;
}
else {
this[key + '>='] = filter;
}
break;
case '<':
for (var id in this)
if (this[id].key == key && this[id].val >= filter.val)
delete this[id];
this[key + '<'] = filter;
break;
case '<=':
for (var id in this)
if (this[id].key == key && this[id].val > filter.val)
delete this[id];
if (key + '!=' + filter.val in this) {
delete this[key + '!=' + filter.val];
filter.op = '<';
this[key + '<'] = filter;
}
else {
this[key + '<='] = filter;
}
break;
}
}
});
tree.Filterset.prototype.add = function(filter) {
//var key = filter.key;
this.filters.push(filter);
};

View File

@ -1,229 +0,0 @@
var assert = require('assert');
var tree = require('../lib/carto/tree.js');
require('../lib/carto/tree/filterset');
exports['test filterset addable'] = function() {
var f = new tree.Filterset;
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '!=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '>9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '>=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '<90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '<=90');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '=', val: '11' });
assert.ok(null === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '=11 =11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '=11 !=90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '=11 >9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '=11 >=9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '=11 <90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '=11 <=90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '90' }), '=11 =90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '=11 !=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '=11 >90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '=11 >=90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '=11 <9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '=11 <=9');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '!=', val: '11' });
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '!=11 =11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '!=11 !=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '9' }), '!=11 !=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '!=11 !=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '!=11 >9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '!=11 >=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '!=11 >90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '!=11 >=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '!=11 <9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '!=11 <=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '!=11 <90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '!=11 <=90');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '>', val: 11 });
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '>11 =11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '>11 !=11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>', val: 11 }), '>11 >11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>=', val: 11 }), '>11 >=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<', val: 11 }), '>11 <11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<=', val: 11 }), '>11 <=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '90' }), '>11 =90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '>11 !=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '>11 >90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '>11 >=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '>11 <90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '>11 <=90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '9' }), '>11 =9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '9' }), '>11 !=9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '>11 >9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '>11 >=9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '>11 <9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '>11 <=9');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '>=', val: 11 });
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '>=11 =11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '>=11 !=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 11 }), '>=11 >11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>=', val: 11 }), '>=11 >=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<', val: 11 }), '>=11 <11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 11 }), '>=11 <=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '90' }), '>=11 =90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '>=11 !=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '>=11 >90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '>=11 >=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '>=11 <90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '>=11 <=90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '9' }), '>=11 =9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '9' }), '>=11 !=9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '>=11 >9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '>=11 >=9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '>=11 <9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '>=11 <=9');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '<', val: 11 });
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '<11 =11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '<11 !=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 11 }), '<11 >11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>=', val: 11 }), '<11 >=11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<', val: 11 }), '<11 <11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 11 }), '<11 <=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '90' }), '<11 =90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '<11 !=90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '<11 >90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '<11 >=90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '<11 <90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '<11 <=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '9' }), '<11 =9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '9' }), '<11 !=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '<11 >9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '<11 >=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '<11 <9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '<11 <=9');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '<=', val: 11 });
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '<=11 =11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '<=11 !=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 11 }), '<=11 >11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 11 }), '<=11 >=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 11 }), '<=11 <11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 11 }), '<=11 <=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '90' }), '<=11 =90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '90' }), '<=11 !=90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '<=11 >90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '<=11 >=90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '<=11 <90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '<=11 <=90');
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '9' }), '<=11 =9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '9' }), '<=11 !=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '<=11 >9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '<=11 >=9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '<=11 <9');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '<=11 <=9');
var f = new tree.Filterset;
f.add({ key: 'TOTAL', op: '<=', val: 11 });
f.add({ key: 'TOTAL', op: '>', val: 9 });
f.add({ key: 'TOTAL', op: '!=', val: '10' });
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '10' }), '<=11 >9 !=10 =10');
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '10.5' }), '<=11 >9 !=10 =10.5');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '9' }), '<=11 >9 !=10 =9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '=', val: '8' }), '<=11 >9 !=10 =8');
assert.ok(true === f.addable({ key: 'TOTAL', op: '=', val: '11' }), '<=11 >9 !=10 =11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '10' }), '<=11 >9 !=10 !=10');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '10.5' }), '<=11 >9 !=10 !=10.5');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '9' }), '<=11 >9 !=10 !=9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '!=', val: '8' }), '<=11 >9 !=10 !=8');
assert.ok(true === f.addable({ key: 'TOTAL', op: '!=', val: '11' }), '<=11 >9 !=10 !=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 11 }), '<=11 >9 !=10 >11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '>=', val: 11 }), '<=11 >9 !=10 >=11');
assert.ok(true === f.addable({ key: 'TOTAL', op: '<', val: 11 }), '<=11 >9 !=10 <11');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 11 }), '<=11 >9 !=10 <=11');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>', val: 90 }), '<=11 >9 !=10 >90');
assert.ok(false === f.addable({ key: 'TOTAL', op: '>=', val: 90 }), '<=11 >9 !=10 >=90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<', val: 90 }), '<=11 >9 !=10 <90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '<=', val: 90 }), '<=11 >9 !=10 <=90');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>', val: 9 }), '<=11 >9 !=10 >9');
assert.ok(null === f.addable({ key: 'TOTAL', op: '>=', val: 9 }), '<=11 >9 !=10 >=9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<', val: 9 }), '<=11 >9 !=10 <9');
assert.ok(false === f.addable({ key: 'TOTAL', op: '<=', val: 9 }), '<=11 >9 !=10 <=9');
};
exports['test filterset add'] = function() {
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '=', val: '11' });
assert.deepEqual(f, { 'TOTAL=': { key: 'TOTAL', op: '=', val: '11' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '4' });
assert.deepEqual(f, { 'TOTAL!=4': { key: 'TOTAL', op: '!=', val: '4' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '>', val: '4' });
assert.deepEqual(f, { 'TOTAL>': { key: 'TOTAL', op: '>', val: '4' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '>=', val: '4' });
assert.deepEqual(f, { 'TOTAL>=': { key: 'TOTAL', op: '>=', val: '4' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '<', val: '4' });
assert.deepEqual(f, { 'TOTAL<': { key: 'TOTAL', op: '<', val: '4' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '<=', val: '4' });
assert.deepEqual(f, { 'TOTAL<=': { key: 'TOTAL', op: '<=', val: '4' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '!=', val: '9' });
assert.deepEqual(f, { 'TOTAL!=9': { key: 'TOTAL', op: '!=', val: '9' }, 'TOTAL!=11': { key: 'TOTAL', op: '!=', val: '11' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '>', val: 9 });
assert.deepEqual(f, { 'TOTAL>': { key: 'TOTAL', op: '>', val: 9 }, 'TOTAL!=11': { key: 'TOTAL', op: '!=', val: '11' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '>', val: 11 });
assert.deepEqual(f, { 'TOTAL>': { key: 'TOTAL', op: '>', val: 11 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '>', val: 90 });
assert.deepEqual(f, { 'TOTAL>': { key: 'TOTAL', op: '>', val: 90 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '>=', val: 9 });
assert.deepEqual(f, { 'TOTAL>=': { key: 'TOTAL', op: '>=', val: 9 }, 'TOTAL!=11': { key: 'TOTAL', op: '!=', val: '11' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '>=', val: 11 });
assert.deepEqual(f, { 'TOTAL>': { key: 'TOTAL', op: '>', val: 11 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '>=', val: 90 });
assert.deepEqual(f, { 'TOTAL>=': { key: 'TOTAL', op: '>=', val: 90 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '<', val: 9 });
assert.deepEqual(f, { 'TOTAL<': { key: 'TOTAL', op: '<', val: 9 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '<', val: 11 });
assert.deepEqual(f, { 'TOTAL<': { key: 'TOTAL', op: '<', val: 11 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '<', val: 90 });
assert.deepEqual(f, { 'TOTAL<': { key: 'TOTAL', op: '<', val: 90 }, 'TOTAL!=11': { key: 'TOTAL', op: '!=', val: '11' }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '<=', val: 9 });
assert.deepEqual(f, { 'TOTAL<=': { key: 'TOTAL', op: '<=', val: 9 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '<=', val: 11 });
assert.deepEqual(f, { 'TOTAL<': { key: 'TOTAL', op: '<', val: 11 }});
var f = new tree.Filterset; f.add({ key: 'TOTAL', op: '!=', val: '11' });
f.add({ key: 'TOTAL', op: '<=', val: 90 });
assert.deepEqual(f, { 'TOTAL<=': { key: 'TOTAL', op: '<=', val: 90 }, 'TOTAL!=11': { key: 'TOTAL', op: '!=', val: '11' }});
// TODO: some more adding tests.
};

View File

@ -1,5 +1,29 @@
#world[POP2005 > 100.1] {
#world[[POP2005] > 100.1] {
polygon-fill: #FFF;
line-color:#F00;
line-width: 0.5;
}
#world[5 > 100.1] {
polygon-fill: #FFF;
}
#world[[POP2005] > [POP2004]] {
polygon-fill: #FFF;
line-color:#F00;
line-width: 0.5;
}
#world[[POP2005] = "hello"] {
polygon-fill: #FFF;
line-color:#F00;
line-width: 0.5;
}
/*
#world[POP2004 = "test"] {
polygon-fill: #FFF;
line-color:#F00;
line-width: 0.5;
}
*/