angular
    .module('ngSharepoint.Lists')
    .factory('$query', $query);

function $query($spList) {
    var Query = function() {
        this.list = undefined;
        this.__columns = [];
        this.__type = undefined;
        this.__query = undefined;
        this.__limit = undefined;
        this.__serializer = undefined;
        this.__order = [];
        this.__data = {};
        this.read = function(cols) {
            if (angular.isUndefined(this.__type)) {
                this.__columns = cols;
                this.__type = 'read';
            }else {
                throw 'Cannot use read after another query type was selected';
            }
            return this;
        };
        this.create = function(data) {
            if (angular.isUndefined(this.__type)) {
                this.__type = 'create';
                if (angular.isDefined(data)) {
                    this.__data = data;
                }
            }else {
                throw 'Cannot use create after another query type was selected';
            }
            return this;
        };
        this.from = function(list) {
            this.list = list;
            return this;
        };
        this.in = function(list) {
            this.list = list;
            return this;
        };
        this.list = function(list) {
            this.list = list;
            return this;
        };
        this.update = function(data) {
            if (angular.isUndefined(this.__type)) {
                this.__type = 'update';
                if (angular.isDefined(data)) {
                    this.__data = data;
                }
            }else {
                throw 'Cannot use update after another query type was selected';
            }
            return this;
        };
        this.delete = function() {
            if (angular.isUndefined(this.__type)) {
                this.__type = 'delete';
            }else {
                throw 'Cannot use delete after another query type was selected';
            }
            return this;
        };
        this.where = function(col) {
            var Where = function(col, instance) {
                this.equals = function(value) {
                    instance.__query = {
                        comparator: 'equals',
                        column: col,
                        value: value
                    };
                    return instance;
                };
                this.greater = function(value) {
                    instance.__query = {
                        comparator: 'greater',
                        column: col,
                        value: value
                    };
                    return instance;
                };
                this.smaller = function(value) {
                    instance.__query = {
                        comparator: 'smaller',
                        column: col,
                        value: value
                    };
                    return instance;
                };
            };
            return new Where(col, this);
        };
        this.set = function(column, value) {
            this.__data[column] = value;
            return this;
        };
        this.value = function(column, value) {
            this.__data[column] = value;
            return this;
        };
        this.class = function(serializer) {
            this.__serializer = serializer;
            return this;
        };
        this.orderBy = function(field, asc) {
            if (angular.isUndefined(asc)) {
                asc = true;
            }
            this.__order.push({column: field, asc: asc});
            return this;
        };
        this.limit = function(limit) {
            this.__limit = limit;
            return this;
        };
        this.exec = function() {
            return $spList.getList(this.list).query({
                columns: this.__columns,
                type: this.__type,
                query: this.__query,
                limit: this.__limit,
                serializer: this.__serializer,
                order: this.__order,
                data: this.__data
            });
        };
        this.then = function(resolve, reject) {
            return this.exec().then(resolve, reject);
        };
    };
    return ({ //TODO: Reimplement this nested return mess
        'create': function(data) {
            return new Query().create(data);
        },
        'read': function(cols) {
            return new Query().read(cols);
        },
        'update': function(data) {
            return new Query().update(data);
        },
        'delete': function() {
            return new Query().delete();
        }
    });
}

@@ -3827,48 +3827,357 @@
     
-return $spList.getList(this.list).query(
+if (angular.isDefined(this.list) && angular.isString(this.list)) %7B%0A                var query = %7B%7D;%0A                if (angular.isDefined(this.__type)) %7B%0A                    query.type = this.__type;%0A                %7Delse %7B%0A                    throw 'No Query Type specified';%0A                %7D%0A                if (angular.isDefined(this.__columns)) 
 %7B%0A  
@@ -4194,16 +4194,27 @@
     
+    query.
 columns
-:
+ =
  thi
@@ -4228,44 +4228,82 @@
 umns
-,%0A                type: this.__type,
+;%0A                %7D%0A                if (angular.isDefined(this.__query)) %7B
 %0A   
@@ -4319,14 +4319,25 @@
     
+    query.
 query
-:
+ =
  thi
@@ -4349,74 +4349,247 @@
 uery
-,%0A                limit: this.__limit,%0A                serializer:
+;%0A                %7D%0A                if (angular.isDefined(this.__limit)) %7B%0A                    query.limit = this.__limit;%0A                %7D%0A                if (angular.isDefined(this.__serializer)) %7B%0A                    query.serializer =
  thi
@@ -4602,17 +4602,17 @@
 rializer
-,
+;
 %0A       
@@ -4624,28 +4624,411 @@
     
-order: this.__order,
+%7D%0A                if (angular.isDefined(this.__order) &&%0A                    angular.isArray(this.__order) &&%0A                    this.__order.length %3E 0) %7B%0A                    query.order = this.__order;%0A                %7D%0A                if (angular.isDefined(this.__data) &&%0A                    angular.isObject(this.__data) &&%0A                    Object.getOwnPropertyNames(this.__data).length %3E 0) %7B
 %0A   
@@ -5044,13 +5044,24 @@
     
+    query.
 data
-:
+ =
  thi
@@ -5068,17 +5068,19 @@
 s.__data
-%0A
+;%0A 
         
@@ -5083,19 +5083,161 @@
         
-%7D);
+   %7D%0A                return $spList.getList(this.list).query(query);%0A            %7Delse %7B%0A                throw 'No List specified';%0A            %7D
 %0A       

Check whether the query is valid before executing it