ffd7c1f1cbaf6cb9512f53745a3ad9be6be428dd
[unfold.git] / manifold / manifoldquery.py
1 import json
2 import uuid
3
4 def uniqid (): 
5     return uuid.uuid4().hex
6
7 class ManifoldQuery:
8
9     def __init__ (self, action=None, method=None, timestamp='now',
10                   filters=[], params=[], fields=[],
11                   sort=None, limit=None, offset=None,
12                   ):
13         self.query_uuid=uniqid()
14         # settable
15         self.action=action
16         self.method=method
17         self.timestamp=timestamp
18         self.filters=filters
19         self.params=params
20         self.fields=fields
21         # xxx this is unused for now
22         self.sort=sort
23         self.limit=limit
24         self.offset=offset
25         # internal data - likewise, this is unused as of yet, although we have
26         # (untested) code below in analyze_subqueries to compute these..
27         self.analyzed_query=None
28         self.subqueries = {}
29
30     def __repr__ (self):
31         result="Q: id=%(query_uuid)s - %(action)s on %(method)s "%self.__dict__
32         result += " with %d filters, %d fields"%(len(self.filters),len(self.params))
33         return result
34
35     def to_json (self):
36         query_uuid=self.query_uuid
37         a=self.action
38         m=self.method
39         t=self.timestamp
40         f=json.dumps (self.filters)
41         p=json.dumps (self.params)
42         c=json.dumps (self.fields)
43         # xxx unique can be removed, but for now we pad the js structure
44         unique=0
45
46         aq = self.analyzed_query.to_json() if self.analyzed_query else 'null'
47         # subqueries is a dictionary method:query
48         if not self.subqueries: 
49             sq="{}"
50         else:
51             sq=", ".join ( [ "'%s':%s" % (method, subquery.to_json())
52                       for (method, subquery) in self.subqueries.iteritems()])
53             sq="{%s}"%sq
54         
55         return """ new ManifoldQuery('%(a)s', '%(m)s', '%(t)s', %(f)s, %(p)s, %(c)s, %(unique)s, '%(query_uuid)s', %(aq)s, %(sq)s)"""%locals()
56     
57     # this builds a ManifoldQuery object from a dict as received from javascript through its ajax request 
58     # e.g. here's what I captured from the server's output
59     # incoming POST <QueryDict: {u'query[method]': [u'slice'], u'query[fields][]': [u'slice_hrn'], u'query[timestamp]': [u'latest'], u'query[action]': [u'get']}>
60     def fill_from_dict (self, d):
61         for key in d.keys():
62             for arg in ['action', 'method', 'filters', 'fields', 'timestamp', 'params']:
63                 if arg in key:
64                     # dirty hack around fields; fields must be a list
65                     if arg == 'fields': 
66                         setattr(self, arg, [d[key]])
67                     else: 
68                         setattr(self, arg, d[key])
69                     break
70
71     # not used yet ..
72     def analyze_subqueries(self):
73         analyzed_query = ManifoldQuery()
74         analyzed_query.query_uuid = self.query_uuid
75         analyzed_query.action = self.action
76         analyzed_query.method = self.method
77         analyzed_query.timestamp = self.timestamp
78
79         # analyse query filters
80         # filter syntax : ['key', 'oparation', 'value']
81         for filter in self.filters:
82             key = filter[0]
83             operation = filter[1]
84             value = filter[2]
85             if '.' in key:
86                 method = key.split('.')[0]
87                 field = key.split('.')[1]
88                 if not analyzed_query.subqueries[method]:
89                     subquery = ManifoldQuery()
90                     subquery.action = self.action
91                     subquery.method = method
92                     subquery.timestamp = self.timestamp
93                     analyzed_query.subqueries[method] = subquery
94
95                 analyzed_query.subqueries[method].filters.append([field, operation, value])
96             else:
97                 analyzed_query.filters.append(filter)
98
99         # analyse query params
100         # params syntax : params = {'param1': value1, 'param2': value2, ...}
101         for param in self.params.keys():
102             if '.' in param:
103                 method = param.split('.')[0]
104                 field = param.split('.')[1]
105                 if not analyzed_query.subqueries[method]:
106                     subquery = ManifoldQuery()
107                     subquery.action = self.action
108                     subquery.method = method
109                     subquery.timestamp = self.timestamp
110                     analyzed_query.subqueries[method] = subquery
111
112                 analyzed_query.subqueries[method].params[field] = self.params[param]
113             else:
114                 analyzed_query.params[param] = self.params[param]
115
116         # analyse query fields
117         # fields syntax: fields = [element1, element2, ....]
118         for element in self.fields:
119             if '.' in element:
120                 method = element.split('.')[0]
121                 field = element.split('.')[1]
122                 if not analyzed_query.subqueries[method]:
123                     subquery = ManifoldQuery()
124                     subquery.action = self.action
125                     subquery.method = method
126                     subquery.timestamp = self.timestamp
127                     analyzed_query.subqueries[method] = subquery
128
129                 analyzed_query.subqueries[method].fields.append(field)
130             else:
131                 analyzed_query.fields.append(element)        
132
133
134         # default subqueries 
135         if analyzed_query.method == 'slice':
136             if not analyzed_query.subqueries['resource']:
137                 subquery = ManifoldQuery()
138                 subquery.action = self.action
139                 subquery.method = method
140                 subquery.timestamp = self.timestamp
141                 analyzed_query.subqueries['resource'] = subquery
142
143             if not analyzed_query.subqueries['lease']:
144                 subquery = ManifoldQuery()
145                 subquery.action = self.action
146                 subquery.method = method
147                 subquery.timestamp = self.timestamp
148                 analyzed_query.subqueries['lease'] = subquery
149
150
151         self.analyzed_query = analyzed_query