parent
13bc8c3488
commit
4181df378f
@ -1,232 +1,213 @@
|
||||
var tree = require('../tree');
|
||||
|
||||
tree.Filterset = function Filterset() {};
|
||||
|
||||
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() + ')');
|
||||
}
|
||||
|
||||
if (filters.length) {
|
||||
return ' <Filter>' + filters.join(' and ') + '</Filter>\n';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
tree.Filterset = function Filterset() {
|
||||
this.filters = {};
|
||||
};
|
||||
|
||||
tree.Filterset.prototype.toXML = function(env) {
|
||||
var filters = [];
|
||||
for (var id in this.filters) {
|
||||
filters.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 (filters.length) {
|
||||
return ' <Filter>' + filters.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.filters[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]);
|
||||
// status is true, false or null. if it's null we don't fail this
|
||||
// clone nor do we add the filter.
|
||||
if (status === false) {
|
||||
return false;
|
||||
}
|
||||
if (status === true) {
|
||||
// Adding the filter will override another value.
|
||||
if (!additions) additions = [];
|
||||
additions.push(other[id]);
|
||||
}
|
||||
tree.Filterset.prototype.cloneWith = function(other) {
|
||||
var additions;
|
||||
for (var id in other.filters) {
|
||||
var status = this.addable(other.filters[id]);
|
||||
// status is true, false or null. if it's null we don't fail this
|
||||
// clone nor do we add the filter.
|
||||
if (status === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adding the other filters doesn't make this filterset invalid, but it
|
||||
// doesn't add anything to it either.
|
||||
if (!additions) {
|
||||
return null;
|
||||
if (status === true) {
|
||||
// Adding the filter will override another value.
|
||||
if (!additions) additions = [];
|
||||
additions.push(other.filters[id]);
|
||||
}
|
||||
}
|
||||
|
||||
// We can successfully add all filters. Now clone the filterset and add the
|
||||
// new rules.
|
||||
var clone = new tree.Filterset();
|
||||
// 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 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 (id in this) {
|
||||
clone[id] = this[id];
|
||||
}
|
||||
// We can successfully add all filters. Now clone the filterset and add the
|
||||
// new rules.
|
||||
var clone = new tree.Filterset();
|
||||
|
||||
// Only add new filters that actually change the filter.
|
||||
while (id = additions.shift()) {
|
||||
clone.add(id);
|
||||
}
|
||||
// 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 (id in this.filters) {
|
||||
clone[id] = this.filters[id];
|
||||
}
|
||||
|
||||
return clone;
|
||||
// Only add new filters that actually change the filter.
|
||||
while (id = additions.shift()) {
|
||||
clone.add(id);
|
||||
}
|
||||
});
|
||||
|
||||
return clone;
|
||||
};
|
||||
|
||||
// Returns true when the new filter can be added, false otherwise.
|
||||
// It can also return null, and on the other side we test for === true or
|
||||
// false
|
||||
Object.defineProperty(tree.Filterset.prototype, 'addable', {
|
||||
enumerable: false,
|
||||
value: function(filter) {
|
||||
var key = filter.key,
|
||||
value = filter.val;
|
||||
|
||||
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;
|
||||
|
||||
case '=~':
|
||||
return true;
|
||||
|
||||
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;
|
||||
}
|
||||
tree.Filterset.prototype.addable = function(filter) {
|
||||
var key = filter.key,
|
||||
value = filter.val;
|
||||
|
||||
switch (filter.op) {
|
||||
case '=':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val != value) ? false : null;
|
||||
if (key + '!=' + value in this.filters) return false;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return false;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return false;
|
||||
if (key + '>=' in this.filters && this.filters[key + '>='].val > value) return false;
|
||||
if (key + '<=' in this.filters && this.filters[key + '<='].val < value) return false;
|
||||
return true;
|
||||
|
||||
case '=~':
|
||||
return true;
|
||||
|
||||
case '!=':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val == value) ? false : null;
|
||||
if (key + '!=' + value in this.filters) return null;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return null;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return null;
|
||||
if (key + '>=' in this.filters && this.filters[key + '>='].val > value) return null;
|
||||
if (key + '<=' in this.filters && this.filters[key + '<='].val < value) return null;
|
||||
return true;
|
||||
|
||||
case '>':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val <= value) ? false : null;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return false;
|
||||
if (key + '<=' in this.filters && this.filters[key + '<='].val <= value) return false;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return null;
|
||||
if (key + '>=' in this.filters && this.filters[key + '>='].val > value) return null;
|
||||
return true;
|
||||
|
||||
case '>=':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val < value) ? false : null;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return false;
|
||||
if (key + '<=' in this.filters && this.filters[key + '<='].val < value) return false;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return null;
|
||||
if (key + '>=' in this.filters && this.filters[key + '>='].val >= value) return null;
|
||||
return true;
|
||||
|
||||
case '<':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val >= value) ? false : null;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return false;
|
||||
if (key + '>=' in this.filters && this.filters[key + '>='].val >= value) return false;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return null;
|
||||
if (key + '<=' in this.filters && this.filters[key + '<='].val < value) return null;
|
||||
return true;
|
||||
|
||||
case '<=':
|
||||
if (key + '=' in this.filters) return (this.filters[key + '='].val > value) ? false : null;
|
||||
if (key + '>' in this.filters && this.filters[key + '>'].val >= value) return false;
|
||||
if (key + '>=' in this.filters && this.filters[key + '>='].val > value) return false;
|
||||
if (key + '<' in this.filters && this.filters[key + '<'].val <= value) return null;
|
||||
if (key + '<=' in this.filters && this.filters[key + '<='].val <= value) return null;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 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, id;
|
||||
|
||||
switch (filter.op) {
|
||||
case '=':
|
||||
for (id in this) {
|
||||
if (this[id].key == key) {
|
||||
delete this[id];
|
||||
}
|
||||
}
|
||||
this[key + '='] = filter;
|
||||
break;
|
||||
|
||||
case '!=':
|
||||
this[key + '!=' + filter.val] = filter;
|
||||
break;
|
||||
|
||||
case '=~':
|
||||
this[key + '=~' + filter.val] = filter;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
// If there are other filters that are also >
|
||||
// but are less than this one, they don't matter, so
|
||||
// remove them.
|
||||
for (id in this) {
|
||||
if (this[id].key == key && this[id].val <= filter.val) {
|
||||
delete this[id];
|
||||
}
|
||||
}
|
||||
this[key + '>'] = filter;
|
||||
break;
|
||||
|
||||
case '>=':
|
||||
for (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;
|
||||
};
|
||||
|
||||
// Only call this function for filters that have been cleared by .addable().
|
||||
tree.Filterset.prototype.add = function(filter) {
|
||||
var key = filter.key, id;
|
||||
|
||||
switch (filter.op) {
|
||||
case '=':
|
||||
for (id in this.filters) {
|
||||
if (this.filters[id].key == key) {
|
||||
delete this.filters[id];
|
||||
}
|
||||
else {
|
||||
this[key + '>='] = filter;
|
||||
}
|
||||
this.filters[key + '='] = filter;
|
||||
break;
|
||||
|
||||
case '!=':
|
||||
this.filters[key + '!=' + filter.val] = filter;
|
||||
break;
|
||||
|
||||
case '=~':
|
||||
this.filters[key + '=~' + filter.val] = filter;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
// If there are other filters that are also >
|
||||
// but are less than this one, they don't matter, so
|
||||
// remove them.
|
||||
for (id in this.filters) {
|
||||
if (this.filters[id].key == key && this.filters[id].val <= filter.val) {
|
||||
delete this.filters[id];
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.filters[key + '>'] = filter;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
for (id in this) {
|
||||
if (this[id].key == key && this[id].val >= filter.val) {
|
||||
delete this[id];
|
||||
}
|
||||
}
|
||||
this[key + '<'] = filter;
|
||||
break;
|
||||
|
||||
case '<=':
|
||||
for (id in this) {
|
||||
if (this[id].key == key && this[id].val > filter.val) {
|
||||
delete this[id];
|
||||
}
|
||||
case '>=':
|
||||
for (id in this.filters) {
|
||||
if (this.filters[id].key == key && this.filters[id].val < filter.val) {
|
||||
delete this.filters[id];
|
||||
}
|
||||
if (key + '!=' + filter.val in this) {
|
||||
delete this[key + '!=' + filter.val];
|
||||
filter.op = '<';
|
||||
this[key + '<'] = filter;
|
||||
}
|
||||
if (key + '!=' + filter.val in this.filters) {
|
||||
delete this.filters[key + '!=' + filter.val];
|
||||
filter.op = '>';
|
||||
this.filters[key + '>'] = filter;
|
||||
}
|
||||
else {
|
||||
this.filters[key + '>='] = filter;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
for (id in this.filters) {
|
||||
if (this.filters[id].key == key && this.filters[id].val >= filter.val) {
|
||||
delete this.filters[id];
|
||||
}
|
||||
else {
|
||||
this[key + '<='] = filter;
|
||||
}
|
||||
this.filters[key + '<'] = filter;
|
||||
break;
|
||||
|
||||
case '<=':
|
||||
for (id in this.filters) {
|
||||
if (this.filters[id].key == key && this.filters[id].val > filter.val) {
|
||||
delete this.filters[id];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (key + '!=' + filter.val in this.filters) {
|
||||
delete this.filters[key + '!=' + filter.val];
|
||||
filter.op = '<';
|
||||
this.filters[key + '<'] = filter;
|
||||
}
|
||||
else {
|
||||
this.filters[key + '<='] = filter;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
Loading…
Reference in new issue