framework now supports displaying the results of queries
[myslice.git] / manifold / 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         q = new ManifoldQuery();
46         return jQuery.extend(true, q, this);
47     }
48
49     this.add_filter = function(key, op, value) {
50         this.filters.push(new Array(key, op, value));
51     }
52     this.update_filter = function(key, op, value) {
53         // Need to be improved...
54         // remove all occurrences of key if operation is not defined
55         if(!op){
56             this.filters = jQuery.grep(this.filters, function(val, i) {
57                 return val[0] != key; 
58             });
59         // Else remove the key+op filters
60         }else{
61             this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
62         }
63         this.filters.push(new Array(key, op, value));
64     }
65
66     this.remove_filter = function (key,op,value) {
67         // if operator is null then remove all occurences of this key
68         if(!op){
69             this.filters = jQuery.grep(this.filters, function(val, i) { 
70                 return val[0] != key; 
71             });
72         }else{
73             this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
74         }
75     }
76
77     // FIXME These functions computing diff's between queries are meant to be shared
78     this.diff_fields = function(otherQuery) {
79         var f1 = this.fields;
80         var f2 = otherQuery.fields;
81
82         /* added elements are the ones in f2 not in f1 */
83         var added   = jQuery.grep(f2, function (x) { return jQuery.inArray(x, f1) == -1 }); 
84         /* removed elements are the ones in f1 not in f2 */
85         var removed = jQuery.grep(f1, function (x) { return jQuery.inArray(x, f2) == -1 }); 
86         
87         return {'added':added, 'removed':removed};
88     }
89
90     // FIXME Modify filter to filters
91     this.diff_filter = function(otherQuery) {
92         var f1 = this.filters;
93         var f2 = otherQuery.filters;
94         
95         /* added elements are the ones in f2 not in f1 */
96         var added   = jQuery.grep(f2, function (x) { return !arrayInArray(x, f1)}); 
97         /* removed elements are the ones in f1 not in f2 */
98         var removed = jQuery.grep(f1, function (x) { return !arrayInArray(x, f2)}); 
99         
100         return {'added':added, 'removed':removed};
101     } 
102
103     // Callaback received 3 parameters: query, data, parent_query
104     this.iter_subqueries = function(callback, data)
105     {
106         rec = function(query, callback, data, parent_query) {
107             callback(query, data, parent_query);
108             jQuery.each(query.subqueries, function(object, subquery) {
109                 rec(subquery, callback, data, query);
110             });
111         };
112
113         if (this.analyzed_query !== undefined)
114             query = this.analyzed_query;
115         else
116             query = this;
117
118         rec(query, callback, data, null);
119     }
120
121     this.select = function(field)
122     {
123         this.fields.push(field);
124     }
125
126     this.unselect = function(field)
127     {   
128         this.fields = $.grep(this.fields, function(x) { return x != field; });
129     }
130
131 // we send queries as a json string now 
132 //    this.as_POST = function() {
133 //        return {'action': this.action, 'object': this.object, 'timestamp': this.timestamp,
134 //              'filters': this.filters, 'params': this.params, 'fields': this.fields};
135 //    }
136     this.analyze_subqueries = function() {
137         /* adapted from the PHP function in com_tophat/includes/query.php */
138         var q = new ManifoldQuery();
139         q.query_uuid = this.query_uuid;
140         q.action = this.action;
141         q.object = this.object;
142         q.timestamp = this.timestamp;
143
144         /* Filters */
145         jQuery.each(this.filters, function(i, filter) {
146             var k = filter[0];
147             var op = filter[1];
148             var v = filter[2];
149             var pos = k.indexOf('.');
150             if (pos != -1) {
151                 var object = k.substr(0, pos);
152                 var field = k.substr(pos+1);
153                 if (!q.subqueries[object]) {
154                     q.subqueries[object] = new ManifoldQuery();
155                     q.subqueries[object].action = q.action;
156                     q.subqueries[object].object = object;
157                     q.subqueries[object].timestamp = q.timestamp;
158                 }
159                 q.subqueries[object].filters.push(Array(field, op, v));
160             } else {
161                 q.filters.push(filter);
162             }
163         });
164
165         /* Params */
166         jQuery.each(this.params, function(param, value) {
167             var pos = param.indexOf('.');
168             if (pos != -1) {
169                 var object = param.substr(0, pos);
170                 var field = param.substr(pos+1);
171                 if (!q.subqueries[object]) {
172                     q.subqueries[object] = new ManifoldQuery();
173                     q.subqueries[object].action = q.action;
174                     q.subqueries[object].object = object;
175                     q.subqueries[object].timestamp = q.timestamp;
176                 }
177                 q.subqueries[object].params[field] = value;
178             } else {
179                 q.params[field] = value;
180             }
181         });
182
183         /* Fields */
184         jQuery.each(this.fields, function(i, v) {
185             var pos = v.indexOf('.');
186             if (pos != -1) {
187                 var object = v.substr(0, pos);
188                 var field = v.substr(pos+1);
189                 if (!q.subqueries[object]) {
190                     q.subqueries[object] = new ManifoldQuery();
191                     q.subqueries[object].action = q.action;
192                     q.subqueries[object].object = object;
193                     q.subqueries[object].timestamp = q.timestamp;
194                 }
195                 q.subqueries[object].fields.push(field);
196             } else {
197                 q.fields.push(v);
198             }
199         });
200         this.analyzed_query = q;
201     }
202  
203     /* constructor */
204     if (typeof action == "undefined")
205         this.action = "get";
206     else
207         this.action = action;
208     
209     if (typeof object == "undefined")
210         this.object = null;
211     else
212         this.object = object;
213
214     if (typeof timestamp == "undefined")
215         this.timestamp = "now";
216     else
217         this.timestamp = timestamp;
218
219     if (typeof filters == "undefined")
220         this.filters = [];
221     else
222         this.filters = filters;
223
224     if (typeof params == "undefined")
225         this.params = {};
226     else
227         this.params = params;
228
229     if (typeof fields == "undefined")
230         this.fields = [];
231     else
232         this.fields = fields;
233
234     if (typeof unique == "undefined")
235         this.unique = false;
236     else
237         this.unique = unique;
238
239     this.query_uuid = query_uuid;
240
241     if (typeof aq == "undefined")
242         this.analyzed_query = null;
243     else
244         this.analyzed_query = aq;
245
246     if (typeof sq == "undefined")
247         this.subqueries = {};
248     else
249         this.subqueries = sq;
250 }