65ff7e6698473e8735e3ac80a6b2791b5f966beb
[unfold.git] / rest / __init__.py
1 import decimal
2 import datetime
3 import json
4
5 from django.http                    import HttpResponse
6
7 from manifold.core.query            import Query
8 from manifoldapi.manifoldapi        import execute_query
9
10 from portal.actions                 import is_pi
11
12 from myslice.settings               import logger
13
14 # handles serialization of datetime in json
15 DateEncoder = lambda obj: obj.strftime("%B %d, %Y %H:%M:%S") if isinstance(obj, datetime.datetime) else None
16
17 # support converting decimal in json
18 json.encoder.FLOAT_REPR = lambda o: format(o, '.2f')
19
20 # handles decimal numbers serialization in json
21 class DecimalEncoder(json.JSONEncoder):
22     def _iterencode(self, o, markers=None):
23         if isinstance(o, decimal.Decimal):
24             return (str(o) for o in [o])
25         return super(DecimalEncoder, self)._iterencode(o, markers)
26     
27 class ObjectRequest(object):
28     
29     def __init__(self, request, object_type, object_name):
30         self.type = object_type
31         self.name = object_name
32         self.fields = []
33         self.params = []
34         self.filters = {}
35         self.options = None
36
37         self.request = request
38         
39         if ((self.type == 'platform') or (self.type == 'testbed')) :
40             self.type = 'local:platform'
41             self.id = 'platform'
42             self.fields = ['platform', 'platform_longname', 'platform_url', 'platform_description','gateway_type'];
43             self.filters['disabled'] = '0'
44             self.filters['gateway_type'] = 'sfa'
45             self.filters['platform'] = '!myslice'
46         #elif(self.type.startswith('local:')):
47         elif ':' in self.type:
48             table = self.type.split(':')
49             prefix = table[0]
50             table = table[1]
51             if prefix == 'local':
52                 # XXX TODO: find a generic Query to get the fields like 
53                 # select column.name from local:object where table == local:user
54                 table = self.type.split(':')
55                 table = table[1]
56                 if table == "user":
57                     self.id = table + '_id'
58                     self.fields = ['user_id', 'email', 'password', 'config','status'];
59                 elif table == "account":
60                     # XXX TODO: Multiple key for account = (platform_id, user_id)
61                     self.id = "platform_id, user_id"
62                     self.fields = ['platform_id', 'user_id', 'auth_type', 'config'];
63                 elif table == "platform":
64                     self.id = 'platform'
65                     self.fields = ['platform', 'platform_longname', 'platform_url', 'platform_description','gateway_type'];
66             else:
67                 # If we use prefix, set the key without the prefix then add it again
68                 self.type = table
69                 self.setKey()
70                 self.setLocalFields()
71                 self.type = prefix + ':' + table
72         else :
73             self.setKey()
74             self.setLocalFields()
75     
76     def setKey(self):
77         # What about key formed of multiple fields???
78         query = Query.get('local:object').filter_by('table', '==', self.type).select('key')
79         results = execute_query(self.request, query)
80         logger.debug("key of object = {}".format(results))
81         if results :
82             for r in results[0]['key'] :
83                 self.id = r
84         else :
85             raise Exception, 'Manifold db error'
86     
87     def setLocalFields(self):
88         query = Query.get('local:object').filter_by('table', '==', self.type).select('column.name')
89         results = execute_query(self.request, query)
90         if results :
91             for r in results[0]['column'] :
92                 self.fields.append(r['name'])
93         else :
94             raise Exception, 'Manifold db error'
95     
96     def setFields(self, fields):
97 #         selected_fields = []
98 #         for p in fields :
99 #             if p in self.fields :
100 #                 selected_fields.append(p)
101         self.fields = fields
102         
103     
104     def applyFilters(self, query, force_filters = False):
105         if (force_filters and not self.filters) :
106             raise Exception, "Filters required"
107         if self.filters :
108             for k, f in self.filters.iteritems() :
109                 if (f[:1] == "!") :
110                     query.filter_by(k, '!=', f[1:])
111                 elif (f[:2] == ">=") :
112                     query.filter_by(k, '>=', f[2:])
113                 elif (f[:1] == ">") :
114                     query.filter_by(k, '>', f[1:])
115                 elif (f[:2] == "<=") :
116                     query.filter_by(k, '<=', f[2:])
117                 elif (f[:1] == "<") :
118                     query.filter_by(k, '<', f[1:])
119                 elif (f[:8] == "CONTAINS") :
120                     query.filter_by(k, 'CONTAINS', f[8:])
121                 else :
122                     query.filter_by(k, '==', f)
123         return query
124     
125     def get(self):
126         query = Query.get(self.type)
127         if (self.id is not None) and (self.id not in self.fields) :
128             query.select(self.fields + [self.id])
129         else :
130             query.select(self.fields)
131         
132         query = self.applyFilters(query)
133         return execute_query(self.request, query)
134
135     def create(self):
136         query = Query.create(self.type)
137         # No filters for create
138         if self.params :
139             for p in self.params :
140                 for k,v in p.iteritems() :
141                     logger.debug("param: {} : {}".format(k, v))
142                     query.set({k : v})
143             logger.debug("query = {}".format(query))
144         else:
145             raise Exception, "Params are required for create"
146         return execute_query(self.request, query)
147    
148     def update(self):
149         query = Query.update(self.type)
150         query = self.applyFilters(query, True)
151
152         if self.params :
153             for p in self.params :
154                 for k,v in p.iteritems() :
155                     logger.debug("param: {} : {}".format(k, v))
156                     query.set({k : v})
157             logger.debug("query = {}".format(query))
158         else:
159             raise Exception, "Params are required for update"
160
161         if self.id is not None:
162            query.select(self.id)
163        
164         return execute_query(self.request, query)
165     
166     def delete(self):
167         query = Query.delete(self.type)
168         query = self.applyFilters(query, True)
169         if self.filters :
170             query.set(self.filters)
171         else:
172             raise Exception, "Filters are required for delete"
173         return execute_query(self.request, query)
174     
175     def json(self):
176         return HttpResponse(json.dumps(self.get(), cls=DecimalEncoder, default=DateEncoder), content_type="application/json")
177     
178     def datatable(self):
179         response = self.get()
180         response_data = {}
181         response_data['fields'] = self.fields
182         response_data['labels'] = self.fields
183         response_data['data'] = []
184         response_data['total'] = len(response)
185         for r in response :
186             d = []
187             for p in self.fields :
188                 d.append(r[p])
189             response_data['data'].append(d)
190         
191         return HttpResponse(json.dumps(response_data, cls=DecimalEncoder, default=DateEncoder), content_type="application/json")
192
193 def error(msg):
194     return HttpResponse(json.dumps({'error' : msg}), content_type="application/json")
195
196 def success(msg):
197     return HttpResponse(json.dumps({'success' : msg}), content_type="application/json")