Merge branch 'master' of git://git.planet-lab.org/plstackapi
[plstackapi.git] / planetstack / core / xoslib / static / js / xoslib / xos-backbone.js
1 if (! window.XOSLIB_LOADED ) {
2     window.XOSLIB_LOADED=true;
3
4     SLIVER_API = "/plstackapi/slivers/";
5     SLICE_API = "/plstackapi/slices/";
6     SLICEDEPLOYMENT_API = "/plstackapi/slice_deployments/";
7     SLICEPRIVILEGE_API = "/plstackapi/slice_privileges/";
8     SLICEROLE_API = "/plstackapi/slice_roles/";
9     NODE_API = "/plstackapi/nodes/";
10     SITE_API = "/plstackapi/sites/";
11     USER_API = "/plstackapi/users/";
12     USERDEPLOYMENT_API = "/plstackapi/user_deployments/";
13     DEPLOYMENT_API = "/plstackapi/deployments/";
14     IMAGE_API = "/plstackapi/images/";
15     NETWORKTEMPLATE_API = "/plstackapi/networktemplates/";
16     NETWORKDEPLOYMENT_API = "/plstackapi/networkdeployments/";
17     NETWORK_API = "/plstackapi/networks/";
18     NETWORKSLIVER_API = "/plstackapi/networkslivers/";
19     SERVICE_API = "/plstackapi/services/";
20
21     SLICEPLUS_API = "/xoslib/slicesplus/";
22
23     XOSModel = Backbone.Model.extend({
24         /* from backbone-tastypie.js */
25         //idAttribute: 'resource_uri',
26
27         /* from backbone-tastypie.js */
28         url: function() {
29                     var url = this.attributes.resource_uri;
30
31                     if (!url) {
32                         if (this.id) {
33                             url = this.urlRoot + this.id;
34                         } else {
35                             // this happens when creating a new model.
36                             url = this.urlRoot;
37                         }
38                     }
39
40                     if (!url) {
41                         // XXX I'm not sure this does anything useful
42                         url = ( _.isFunction( this.collection.url ) ? this.collection.url() : this.collection.url );
43                         url = url || this.urlRoot;
44                     }
45
46                     // remove any existing query parameters
47                     url && ( url.indexOf("?") > -1 ) && ( url = url.split("?")[0] );
48
49                     url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' );
50
51                     url && ( url += "?no_hyperlinks=1" );
52
53                     return url;
54             },
55
56             listMethods: function() {
57                 var res = [];\r
58                 for(var m in this) {\r
59                     if(typeof this[m] == "function") {\r
60                         res.push(m)\r
61                     }\r
62                 }\r
63                 return res;\r
64             }
65     });
66
67     XOSCollection = Backbone.Collection.extend({
68         objects: function() {
69                     return this.models.map(function(element) { return element.attributes; });
70                  },
71
72         initialize: function(){
73           this.isLoaded = false;
74           this.sortVar = 'name';\r
75           this.sortOrder = 'asc';\r
76           this.on( "sort", this.sorted );\r
77         },\r
78 \r
79         relatedCollections: [],\r
80         foreignCollections: [],\r
81 \r
82         sorted: function() {\r
83             this.isLoaded = true;\r
84         },\r
85 \r
86         simpleComparator: function( model ){\r
87           parts=this.sortVar.split(".");\r
88           result = model.get(parts[0]);\r
89           for (index=1; index<parts.length; ++index) {\r
90               result=result[parts[index]];\r
91           }\r
92           return result;\r
93         },\r
94 \r
95         comparator: function (left, right) {\r
96             var l = this.simpleComparator(left);\r
97             var r = this.simpleComparator(right);\r
98 \r
99             if (l === void 0) return -1;\r
100             if (r === void 0) return 1;\r
101 \r
102             if (this.sortOrder=="desc") {\r
103                 return l < r ? 1 : l > r ? -1 : 0;\r
104             } else {\r
105                 return l < r ? -1 : l > r ? 1 : 0;\r
106             }\r
107         },\r
108 \r
109         startPolling: function() {\r
110             if (!this._polling) {\r
111                 var collection=this;
112                 setInterval(function() { collection.fetch(); }, 10000);
113                 this._polling=true;
114                 this.fetch();
115             }
116         },
117
118         maybeFetch: function(options){
119                 // Helper function to fetch only if this collection has not been fetched before.
120             if(this._fetched){
121                     // If this has already been fetched, call the success, if it exists
122                 options.success && options.success();
123                 console.log("alreadyFetched");
124                 return;
125             }
126
127                 // when the original success function completes mark this collection as fetched
128             var self = this,
129             successWrapper = function(success){
130                 return function(){
131                     self._fetched = true;
132                     success && success.apply(this, arguments);
133                 };
134             };
135             options.success = successWrapper(options.success);
136             console.log("call fetch");
137             this.fetch(options);
138         },
139
140         getOrFetch: function(id, options){
141                 // Helper function to use this collection as a cache for models on the server
142             var model = this.get(id);
143
144             if(model){
145                 options.success && options.success(model);
146                 return;
147             }
148
149             model = new this.model({
150                 resource_uri: id
151             });
152
153             model.fetch(options);
154         },
155
156         filterBy: function(fieldName, value) {
157              filtered = this.filter(function(obj) {
158                  return obj.get(fieldName) == value;
159                  });
160              return new this.constructor(filtered);
161         },
162
163         /* from backbone-tastypie.js */
164         url: function( models ) {
165                     var url = this.urlRoot || ( models && models.length && models[0].urlRoot );
166                     url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' );
167
168                     // Build a url to retrieve a set of models. This assume the last part of each model's idAttribute
169                     // (set to 'resource_uri') contains the model's id.
170                     if ( models && models.length ) {
171                             var ids = _.map( models, function( model ) {
172                                             var parts = _.compact( model.id.split('/') );
173                                             return parts[ parts.length - 1 ];
174                                     });
175                             url += 'set/' + ids.join(';') + '/';
176                     }
177
178                     url && ( url += "?no_hyperlinks=1" );
179
180                     return url;
181             },
182
183         listMethods: function() {
184                 var res = [];\r
185                 for(var m in this) {\r
186                     if(typeof this[m] == "function") {\r
187                         res.push(m)\r
188                     }\r
189                 }\r
190                 return res;\r
191             },
192     });
193
194     function xoslib() {
195         // basic REST
196         this.sliver = XOSModel.extend({ urlRoot: SLIVER_API, modelName: "sliver" });
197         this.sliverCollection = XOSCollection.extend({ urlRoot: SLIVER_API,
198                                                        relatedCollections: {"networkSlivers": "sliver"},
199                                                        foreignCollections: ["slices", "deployments", "images", "nodes", "users"],
200                                                        model: this.sliver,
201                                                        modelName: "sliver"});
202         this.slivers = new this.sliverCollection();
203
204         this.slice = XOSModel.extend({ urlRoot: SLICE_API, modelName: "slice" });
205         this.sliceCollection = XOSCollection.extend({ urlRoot: SLICE_API,
206                                                        relatedCollections: {"slivers": "slice", "sliceDeployments": "slice", "slicePrivileges": "slice", "networks": "owner"},
207                                                        foreignCollections: ["services", "sites"],
208                                                        model: this.slice,
209                                                        modelName: "slice"});
210         this.slices = new this.sliceCollection();
211
212         this.sliceDeployment = XOSModel.extend({ urlRoot: SLICEDEPLOYMENT_API, modelName: "sliceDeployment" });
213         this.sliceDeploymentCollection = XOSCollection.extend({ urlRoot: SLICEDEPLOYMENT_API,
214                                                        foreignCollections: ["slices", "deployments"],
215                                                        model: this.sliceDeployment,
216                                                        modelName: "sliceDeployment"});
217         this.sliceDeployments = new this.sliceDeploymentCollection();
218
219         this.slicePrivilege = XOSModel.extend({ urlRoot: SLICEPRIVILEGE_API, modelName: "slicePrivilege" });
220         this.slicePrivilegeCollection = XOSCollection.extend({ urlRoot: SLICEPRIVILEGE_API,
221                                                        foreignCollections: ["slices", "users", "sliceRoles"],
222                                                        model: this.slicePrivilege,
223                                                        modelName: "slicePrivilege"});
224         this.slicePrivileges = new this.slicePrivilegeCollection();
225
226         this.sliceRole = XOSModel.extend({ urlRoot: SLICEROLE_API, modelName: "sliceRole" });
227         this.sliceRoleCollection = XOSCollection.extend({ urlRoot: SLICEROLE_API,
228                                                        model: this.sliceRole,
229                                                        modelName: "sliceRole"});
230         this.sliceRoles = new this.sliceRoleCollection();
231
232         this.node = XOSModel.extend({ urlRoot: NODE_API, modelName: "node" });
233         this.nodeCollection = XOSCollection.extend({ urlRoot: NODE_API,
234                                                        foreignCollections: ["sites", "deployments"],
235                                                        model: this.node,
236                                                        modelName: "node"});
237         this.nodes = new this.nodeCollection();
238
239         this.site = XOSModel.extend({ urlRoot: SITE_API, modelName: "site" });
240         this.siteCollection = XOSCollection.extend({ urlRoot: SITE_API,
241                                                        relatedCollections: {"users": "site", "slices": "site", "nodes": "site"},
242                                                        model: this.site,
243                                                        modelName: "site"});
244         this.sites = new this.siteCollection();
245
246         this.user = XOSModel.extend({ urlRoot: USER_API, modelName: "user" });
247         this.userCollection = XOSCollection.extend({ urlRoot: USER_API,
248                                                        relatedCollections: {"slicePrivileges": "user", "slices": "owner", "userDeployments": "user"},
249                                                        foreignCollections: ["sites"],
250                                                        model: this.user,
251                                                        modelName: "user"});
252         this.users = new this.userCollection();
253
254         this.userDeployment = XOSModel.extend({ urlRoot: USERDEPLOYMENT_API, modelName: "userDeployment" });
255         this.userDeploymentCollection = XOSCollection.extend({ urlRoot: USERDEPLOYMENT_API,
256                                                        foreignCollections: ["users","deployments"],
257                                                        model: this.userDeployment,
258                                                        modelName: "userDeployment"});
259         this.userDeployments = new this.userDeploymentCollection();
260
261         this.deployment = XOSModel.extend({ urlRoot: DEPLOYMENT_API,
262                                             modelName: "deployment",
263                                             defaults: xosdefaults.deployment });
264         this.deploymentCollection = XOSCollection.extend({ urlRoot: DEPLOYMENT_API,
265                                                            relatedCollections: {"nodes": "deployment", "slivers": "deploymentNetwork", "networkDeployments": "deployment", "userDeployments": "deployment"},
266                                                            model: this.deployment,
267                                                            modelName: "deployment"});
268         this.deployments = new this.deploymentCollection();
269
270         this.image = XOSModel.extend({ urlRoot: IMAGE_API,
271                                        modelName: "image" });
272         this.imageCollection = XOSCollection.extend({ urlRoot: IMAGE_API,
273                                                            model: this.image,
274                                                            modelName: "image"});
275         this.images = new this.imageCollection();
276
277         this.networkTemplate = XOSModel.extend({ urlRoot: NETWORKTEMPLATE_API, modelName: "networkTemplate" });
278         this.networkTemplateCollection = XOSCollection.extend({ urlRoot: NETWORKTEMPLATE_API,
279                                                            model: this.networkTemplate,
280                                                            modelName: "networkTemplate"});
281         this.networkTemplates = new this.networkTemplateCollection();
282
283         this.network = XOSModel.extend({ urlRoot: NETWORK_API, modelName: "network" });
284         this.networkCollection = XOSCollection.extend({ urlRoot: NETWORK_API,
285                                                            relatedCollections: {"networkDeployments": "network", "networkSlivers": "network"},
286                                                            foreignCollections: ["slices", "networkTemplates"],
287                                                            model: this.network,
288                                                            modelName: "network"});
289         this.networks = new this.networkCollection();
290
291         this.networkSliver = XOSModel.extend({ urlRoot: NETWORKSLIVER_API, modelName: "networkSliver" });
292         this.networkSliverCollection = XOSCollection.extend({ urlRoot: NETWORKSLIVER_API,
293                                                            model: this.networkSliver,
294                                                            modelName: "networkSliver"});
295         this.networkSlivers = new this.networkSliverCollection();
296
297         this.networkDeployment = XOSModel.extend({ urlRoot: NETWORKDEPLOYMENT_API, modelName: "networkDeployment" });
298         this.networkDeploymentCollection = XOSCollection.extend({ urlRoot: NETWORKDEPLOYMENT_API,
299                                                            model: this.networkDeployment,
300                                                            modelName: "networkDeployment"});
301         this.networkDeployments = new this.networkDeploymentCollection();
302
303         this.service = XOSModel.extend({ urlRoot: SERVICE_API, modelName: "sliver" });
304         this.serviceCollection = XOSCollection.extend({ urlRoot: SERVICE_API,
305                                                        model: this.service,
306                                                        modelName: "service"});
307         this.services = new this.serviceCollection();
308
309         // enhanced REST
310         this.slicePlus = XOSModel.extend({ urlRoot: SLICEPLUS_API, modelName: "slicePlus" });
311         this.slicePlusCollection = XOSCollection.extend({ urlRoot: SLICEPLUS_API,
312                                                           relatedCollections: {'slivers': "slice"},
313                                                           model: this.slicePlus,
314                                                           modelName: "slicePlus"});
315         this.slicesPlus = new this.slicePlusCollection();
316
317         this.listObjects = function() { return ["slivers", "slices", "nodes", "sites", "users", "deployments"]; };
318     };
319
320     xos = new xoslib();
321
322     function getCookie(name) {
323         var cookieValue = null;\r
324         if (document.cookie && document.cookie != '') {\r
325             var cookies = document.cookie.split(';');\r
326             for (var i = 0; i < cookies.length; i++) {\r
327                 var cookie = jQuery.trim(cookies[i]);\r
328                 // Does this cookie string begin with the name we want?\r
329                 if (cookie.substring(0, name.length + 1) == (name + '=')) {\r
330                     cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\r
331                     break;\r
332                 }\r
333             }\r
334         }\r
335         return cookieValue;\r
336     }
337
338     (function() {
339       var _sync = Backbone.sync;\r
340       Backbone.sync = function(method, model, options){\r
341         options.beforeSend = function(xhr){\r
342           var token = getCookie("csrftoken");\r
343           xhr.setRequestHeader('X-CSRFToken', token);\r
344         };\r
345         return _sync(method, model, options);\r
346       };\r
347     })();
348 }