Skip to content

Commit

Permalink
almost finished query builder - tests still failing
Browse files Browse the repository at this point in the history
  • Loading branch information
atruskie committed Sep 4, 2014
1 parent 8a39953 commit 9480791
Show file tree
Hide file tree
Showing 2 changed files with 380 additions and 44 deletions.
131 changes: 102 additions & 29 deletions src/components/services/queryBuilder.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,147 @@
var qb = angular.module("bawApp.services.queryBuilder", ["bawApp.configuration"]);

function Query() {
function Query(currentFieldKey) {
var currentField = currentFieldKey;

this.filter = {};



this.combinator = function combinator(type, functions) {
if (!functions){
return this;
}

this.filter[type] = new Query();
// create a new level of nesting IFF there is already a root combinator
var that = this;
if((this instanceof RootQuery) && (Object.keys(this.filter).length >= 1)) {
that = new Query(this.getField());
}

that.filter[type] = {};

var that = this.filter[type];
functions.forEach(function(value, key) {
if (!(value instanceof Query)){
throw "A combinator only accepts Query objects";
}

that.filter[key] = value.filter;
Query.deepMergeFilter(that.filter[type], value.filter);
});

return this;
};

this.operator = function operator(operation, field, value) {
var that = this;
this.operator = function operator(operation, value, field) {
var that = this, operatorField = field;
if (this instanceof RootQuery) {
that = new Query();
that = new Query(this.getField());
}

if (operatorField) {
that.field(operatorField);
}
else {
operatorField = that.getField();
}

that.filter[field] = that.filter[field] || {};
if (!operatorField) {
throw "A field is not set - using an operator does not make sense";
}

that.filter[field][operation] = value;
that.filter[operatorField] = that.filter[operatorField] || {};
that.filter[operatorField][operation] = value;

return that;
};

this.field = function field(fieldKey) {
currentField = fieldKey;
return this;
};

this.getField = function getField() {
return currentField;
};
}

Query.mergeFilter = function mergeFilter(rootQuery, childQuery) {
if (rootQuery instanceof Query && childQuery instanceof Query) {
Query.deepMergeFilter = function mergeFilter(base, child) {
Object.keys(child).forEach(function (key, index) {
if (angular.isObject(base[key])) {
Query.deepMergeFilter(base[key], child[key]);
}
else {
base[key] = child[key];
}
});
};

}
else {
throw "Query objects not passed in";
}
var validCombinators = {
"and": undefined,
"or": undefined,
"not": function(args) {
if (args.length > 1) {
throw "Not combinator only accepts one argument (either combinator or operator)";
}
}};

var validOperators = {
"equal": undefined,
"eq": undefined,
"notEqual": undefined,
"notEq": undefined,
"lessThan": undefined,
"lt": undefined,
"lessThanOrEqual": undefined,
"lteq": undefined,
"greaterThan": undefined,
"gt": undefined,
"greaterThanOrEqual": undefined,
"gteq": undefined,
"range": undefined,
"in": function(field, value) {
if (!angular.isArray(value)) {
throw "The in function must be given as an array";
}
},
"contains": undefined,
"startsWith": undefined,
"endsWith": undefined
};


Query.prototype.eq = function eq(field, value) {
return this.operator("eq", field, value);
};
Object.keys(validCombinators).forEach(function (combinatorKey) {
Query.prototype[combinatorKey] = function() {
var args = Array.prototype.slice.call(arguments, 0);

Query.prototype.and = function and() {
var args = Array.prototype.slice.call(arguments, 0);
return this.combinator("and", args);
};
var validator = validCombinators[combinatorKey];
if (validator) {
validator(arguments);
}

Query.prototype.or = function or() {
var args = Array.prototype.slice.call(arguments, 0);
return this.combinator("or", args);
};
return this.combinator(combinatorKey, args);
};
});

Object.keys(validOperators).forEach(function(operatorKey) {
Query.prototype[operatorKey] = function(field, value) {
if (arguments.length == 1) {
value = field;
field = undefined;
}


var validator = validOperators[operatorKey];
if (validator) {
validator(field, value);
}

return this.operator(operatorKey, value, field);
};
});


function RootQuery() {
Query.call(this);

this.sort = {};
this.sorting = {};
this.paging = {};

this.toJSON = function toJSON(spaces) {
Expand Down
Loading

0 comments on commit 9480791

Please sign in to comment.