Setting tag myslice-0.2-3
[myslice.git] / manifold / static / js / manifold-query.js
1 function ManifoldQuery(action, object, timestamp, filters, params, fields, unique, query_uuid, aq, sq) {  
2     // get, update, delete, create
3     var action;
4     // slice, user, network... 
5     var object; 
6     // timestamp, now, latest(cache) : date of the results queried    
7     var timestamp;
8     // key(field),op(=<>),value
9     var filters;
10     // todo
11     var params;
12     // hostname, ip,... 
13     var fields;
14     // 0,1 : list of element of an object or single object  
15     var unique;
16     // query_uuid : unique identifier of a query
17     var query_uuid;
18     // Query : root query (no sub-Query)
19     var analyzed_query;
20     // {} : Assoc Table of sub-queries ["resources"->subQ1, "users"->subQ2]
21     var subqueries;
22
23 /*-------------------------------------------------------------
24               Query properties are SQL like : 
25 ---------------------------------------------------------------
26 SELECT fields FROM object WHERE filter;
27 UPDATE object SET field=value WHERE filter; / returns SELECT 
28 DELETE FROM object WHERE filter
29 INSERT INTO object VALUES(field=value)
30 -------------------------------------------------------------*/
31     
32     this.__repr = function () {
33         res  = "ManifoldQuery ";
34         res += " id=" + this.query_uuid;
35         res += " a=" + this.action;
36         res += " o=" + this.object;
37         res += " ts=" + this.timestamp;
38         res += " flts=" + this.filters;
39         res += " flds=" + this.fields;
40         res += " prms=" + this.params;
41         return res;
42     }   
43
44     this.clone = function() {
45         // 
46         var q = new ManifoldQuery();
47         q.action     = this.action;
48         q.object     = this.object;
49         q.timestamp  = this.timestamp;
50         q.filters    = this.filters.slice();
51         q.fields     = this.fields.slice();
52         q.query_uuid = this.query_uuid;
53
54         if (this.analyzed_query)
55             q.analyzed_query = this.analyzed_query.clone();
56         else
57             q.analyzed_query = null;
58
59         if (this.subqueries) {
60             q.subqueries = {}
61             for (method in this.subqueries)
62                 q.subqueries[method] = this.subqueries[method].clone();
63         }
64
65         // deep extend not working for custom objects
66         // $.extend(true, q, this);
67         return q;
68     }
69
70     this.add_filter = function(key, op, value) {
71         this.filters.push(new Array(key, op, value));
72     }
73     this.update_filter = function(key, op, value) {
74         // Need to be improved...
75         // remove all occurrences of key if operation is not defined
76         if(!op){
77             this.filters = jQuery.grep(this.filters, function(val, i) {
78                 return val[0] != key; 
79             });
80         // Else remove the key+op filters
81         }else{
82             this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
83         }
84         this.filters.push(new Array(key, op, value));
85     }
86
87     this.remove_filter = function (key,op,value) {
88         // if operator is null then remove all occurences of this key
89         if(!op){
90             this.filters = jQuery.grep(this.filters, function(val, i) { 
91                 return val[0] != key; 
92             });
93         }else{
94             this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
95         }
96     }
97
98     // FIXME These functions computing diff's between queries are meant to be shared
99     this.diff_fields = function(otherQuery) {
100         var f1 = this.fields;
101         var f2 = otherQuery.fields;
102
103         /* added elements are the ones in f2 not in f1 */
104         var added   = jQuery.grep(f2, function (x) { return jQuery.inArray(x, f1) == -1 }); 
105         /* removed elements are the ones in f1 not in f2 */
106         var removed = jQuery.grep(f1, function (x) { return jQuery.inArray(x, f2) == -1 }); 
107         
108         return {'added':added, 'removed':removed};
109     }
110
111     // FIXME Modify filter to filters
112     this.diff_filter = function(otherQuery) {
113         var f1 = this.filters;
114         var f2 = otherQuery.filters;
115         
116         /* added elements are the ones in f2 not in f1 */
117         var added   = jQuery.grep(f2, function (x) { return !arrayInArray(x, f1)}); 
118         /* removed elements are the ones in f1 not in f2 */
119         var removed = jQuery.grep(f1, function (x) { return !arrayInArray(x, f2)}); 
120         
121         return {'added':added, 'removed':removed};
122     } 
123
124     // Callaback received 3 parameters: query, data, parent_query
125     this.iter_subqueries = function(callback, data)
126     {
127         rec = function(query, callback, data, parent_query) {
128             callback(query, data, parent_query);
129             jQuery.each(query.subqueries, function(object, subquery) {
130                 rec(subquery, callback, data, query);
131             });
132         };
133
134         if (this.analyzed_query !== undefined)
135             query = this.analyzed_query;
136         else
137             query = this;
138
139         rec(query, callback, data, null);
140     }
141
142     this.select = function(field)
143     {
144         this.fields.push(field);
145     }
146
147     this.unselect = function(field)
148     {   
149         this.fields = $.grep(this.fields, function(x) { return x != field; });
150     }
151
152 // we send queries as a json string now 
153 //    this.as_POST = function() {
154 //        return {'action': this.action, 'object': this.object, 'timestamp': this.timestamp,
155 //              'filters': this.filters, 'params': this.params, 'fields': this.fields};
156 //    }
157     this.analyze_subqueries = function() {
158         /* adapted from the PHP function in com_tophat/includes/query.php */
159         var q = new ManifoldQuery();
160         q.query_uuid = this.query_uuid;
161         q.action = this.action;
162         q.object = this.object;
163         q.timestamp = this.timestamp;
164
165         /* Filters */
166         jQuery.each(this.filters, function(i, filter) {
167             var k = filter[0];
168             var op = filter[1];
169             var v = filter[2];
170             var pos = k.indexOf('.');
171             if (pos != -1) {
172                 var object = k.substr(0, pos);
173                 var field = k.substr(pos+1);
174                 if (!q.subqueries[object]) {
175                     q.subqueries[object] = new ManifoldQuery();
176                     q.subqueries[object].action = q.action;
177                     q.subqueries[object].object = object;
178                     q.subqueries[object].timestamp = q.timestamp;
179                 }
180                 q.subqueries[object].filters.push(Array(field, op, v));
181             } else {
182                 q.filters.push(filter);
183             }
184         });
185
186         /* Params */
187         jQuery.each(this.params, function(param, value) {
188             var pos = param.indexOf('.');
189             if (pos != -1) {
190                 var object = param.substr(0, pos);
191                 var field = param.substr(pos+1);
192                 if (!q.subqueries[object]) {
193                     q.subqueries[object] = new ManifoldQuery();
194                     q.subqueries[object].action = q.action;
195                     q.subqueries[object].object = object;
196                     q.subqueries[object].timestamp = q.timestamp;
197                 }
198                 q.subqueries[object].params[field] = value;
199             } else {
200                 q.params[field] = value;
201             }
202         });
203
204         /* Fields */
205         jQuery.each(this.fields, function(i, v) {
206             var pos = v.indexOf('.');
207             if (pos != -1) {
208                 var object = v.substr(0, pos);
209                 var field = v.substr(pos+1);
210                 if (!q.subqueries[object]) {
211                     q.subqueries[object] = new ManifoldQuery();
212                     q.subqueries[object].action = q.action;
213                     q.subqueries[object].object = object;
214                     q.subqueries[object].timestamp = q.timestamp;
215                 }
216                 q.subqueries[object].fields.push(field);
217             } else {
218                 q.fields.push(v);
219             }
220         });
221         this.analyzed_query = q;
222     }
223  
224     /* constructor */
225     if (typeof action == "undefined")
226         this.action = "get";
227     else
228         this.action = action;
229     
230     if (typeof object == "undefined")
231         this.object = null;
232     else
233         this.object = object;
234
235     if (typeof timestamp == "undefined")
236         this.timestamp = "now";
237     else
238         this.timestamp = timestamp;
239
240     if (typeof filters == "undefined")
241         this.filters = [];
242     else
243         this.filters = filters;
244
245     if (typeof params == "undefined")
246         this.params = {};
247     else
248         this.params = params;
249
250     if (typeof fields == "undefined")
251         this.fields = [];
252     else
253         this.fields = fields;
254
255     if (typeof unique == "undefined")
256         this.unique = false;
257     else
258         this.unique = unique;
259
260     this.query_uuid = query_uuid;
261
262     if (typeof aq == "undefined")
263         this.analyzed_query = null;
264     else
265         this.analyzed_query = aq;
266
267     if (typeof sq == "undefined")
268         this.subqueries = {};
269     else
270         this.subqueries = sq;
271 }