in query, 'method' is now called 'subject'
[unfold.git] / manifold / js / manifold-query.js
1 function ManifoldQuery(action, subject, timestamp, filters, params, fields, unique, query_uuid, aq, sq) {  
2     // get, update, delete, create
3     var action;
4     // slice, user, network... 
5     var subject; 
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 subject WHERE filter;
27 UPDATE subject SET field=value WHERE filter; / returns SELECT 
28 DELETE FROM subject WHERE filter
29 INSERT INTO subject VALUES(field=value)
30 -------------------------------------------------------------*/
31     
32     this.__repr = function (q) {
33         res  = "ManyfoldQuery ";
34         res += " id=" + q.query_uuid;
35         res += " a=" + q.action;
36         res += " s=" + q.subject;
37         res += " ts=" + q.timestamp;
38         res += " flts=" + q.filters;
39         res += " flds=" + q.fields;
40         res += " prms=" + q.params;
41         return res;
42     }   
43
44     this.clone = function() {
45         q = new ManifoldQuery();
46         return jQuery.extend(true, q, this);
47     }
48     this.add_filter = function(key, op, value) {
49         this.filters.push(new Array(key, op, value));
50     }
51     this.update_filter = function(key, op, value) {
52         // Need to be improved...
53         // remove all occurrences of key if operation is not defined
54         if(!op){
55             this.filters = jQuery.grep(this.filters, function(val, i) {
56                 return val[0] != key; 
57             });
58         // Else remove the key+op filters
59         }else{
60             this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
61         }
62         this.filters.push(new Array(key, op, value));
63     }
64     this.remove_filter = function (key,op,value){
65         // if operator is null then remove all occurences of this key
66         if(!op){
67             this.filters = jQuery.grep(this.filters, function(val, i) { 
68                 return val[0] != key; 
69             });
70         }else{
71             this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
72         }
73     }
74     // FIXME These functions computing diff's between queries are meant to be shared
75     this.diff_fields = function (otherQuery)
76     {
77         var f1 = this.fields;
78         var f2 = otherQuery.fields;
79
80         /* added elements are the ones in f2 not in f1 */
81         var added   = jQuery.grep(f2, function (x) { return jQuery.inArray(x, f1) == -1 }); 
82         /* removed elements are the ones in f1 not in f2 */
83         var removed = jQuery.grep(f1, function (x) { return jQuery.inArray(x, f2) == -1 }); 
84         
85         return {'added':added, 'removed':removed};
86     }    
87     // FIXME Modify filter to filters
88     this.diff_filter = function (otherQuery)
89     {
90         var f1 = this.filters;
91         var f2 = otherQuery.filters;
92         
93         /* added elements are the ones in f2 not in f1 */
94         var added   = jQuery.grep(f2, function (x) { return !arrayInArray(x, f1)}); 
95         /* removed elements are the ones in f1 not in f2 */
96         var removed = jQuery.grep(f1, function (x) { return !arrayInArray(x, f2)}); 
97         
98         return {'added':added, 'removed':removed};
99     } 
100     this.to_hash = function() {
101         return {'action': this.action, 'subject': this.subject, 'timestamp': this.timestamp,
102                 'filters': this.filters, 'params': this.params, 'fields': this.fields};
103     }
104     this.analyze_subqueries = function() {
105         /* adapted from the PHP function in com_tophat/includes/query.php */
106         var q = new ManifoldQuery();
107         q.query_uuid = this.query_uuid;
108         q.action = this.action;
109         q.subject = this.subject;
110         q.timestamp = this.timestamp;
111
112         /* Filters */
113         jQuery.each(this.filters, function(i, filter) {
114             var k = filter[0];
115             var op = filter[1];
116             var v = filter[2];
117             var pos = k.indexOf('.');
118             if (pos != -1) {
119                 var subject = k.substr(0, pos);
120                 var field = k.substr(pos+1);
121                 if (jQuery.inArray(this.subject, q.subqueries) == -1) {
122                     q.subqueries[this.subject] = new ManifoldQuery();
123                     q.subqueries[this.subject].action = this.action;
124                     q.subqueries[this.subject].subject = this.subject;
125                     q.subqueries[this.subject].timestamp = this.timestamp;
126                 }
127                 q.subqueries[this.subject].filters.push(Array(field, op, v));
128             } else {
129                 q.filters.push(this.filter);
130             }
131         });
132
133         /* Params */
134         jQuery.each(this.params, function(param, value) {
135             var pos = param.indexOf('.');
136             if (pos != -1) {
137                 var subject = param.substr(0, pos);
138                 var field = param.substr(pos+1);
139                 if (jQuery.inArray(this.subject, q.subqueries) == -1) {
140                     q.subqueries[this.subject] = new ManifoldQuery();
141                     q.subqueries[this.subject].action = this.action;
142                     q.subqueries[this.subject].subject = this.subject;
143                     q.subqueries[this.subject].timestamp = this.timestamp;
144                 }
145                 q.subqueries[this.subject].params[field] = value;
146             } else {
147                 q.params[field] = value;
148             }
149         });
150
151         /* Fields */
152         jQuery.each(this.fields, function(i, v) {
153             var pos = v.indexOf('.');
154             if (pos != -1) {
155                 var subject = v.substr(0, pos);
156                 var field = v.substr(pos+1);
157                 if (jQuery.inArray(this.subject, q.subqueries) == -1) {
158                     q.subqueries[this.subject] = new ManifoldQuery();
159                     q.subqueries[this.subject].action = this.action;
160                     q.subqueries[this.subject].subject = this.subject;
161                     q.subqueries[this.subject].timestamp = this.timestamp;
162                 }
163                 q.subqueries[this.subject].fields.push(field);
164             } else {
165                 q.fields.push(v);
166             }
167         });
168         this.analyzed_query = q;
169     }
170  
171     /* constructor */
172     this.action = action;
173     this.subject = subject;
174     this.timestamp = timestamp;
175     this.filters = filters;
176     this.params = params;
177     this.fields = fields;
178     this.unique = unique;
179     this.query_uuid = query_uuid;
180     this.analyzed_query = aq;
181     this.subqueries = sq;
182 }