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