aboutsummaryrefslogtreecommitdiffstats
path: root/src/moveToAngularCom/DataStore.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/moveToAngularCom/DataStore.js')
-rw-r--r--src/moveToAngularCom/DataStore.js330
1 files changed, 330 insertions, 0 deletions
diff --git a/src/moveToAngularCom/DataStore.js b/src/moveToAngularCom/DataStore.js
new file mode 100644
index 00000000..70bcc623
--- /dev/null
+++ b/src/moveToAngularCom/DataStore.js
@@ -0,0 +1,330 @@
+function DataStore(post, users, anchor) {
+ this.post = post;
+ this.users = users;
+ this._cache_collections = [];
+ this._cache = {'$collections':this._cache_collections};
+ this.anchor = anchor;
+ this.bulkRequest = [];
+};
+
+DataStore.NullEntity = extend(function(){}, {
+ 'all': function(){return [];},
+ 'query': function(){return [];},
+ 'load': function(){return {};},
+ 'title': undefined
+});
+
+DataStore.prototype = {
+ cache: function(document) {
+ if (! document.datastore === this) {
+ throw "Parameter must be an instance of Entity! " + toJson(document);
+ }
+ var key = document['$entity'] + '/' + document['$id'];
+ var cachedDocument = this._cache[key];
+ if (cachedDocument) {
+ Model.copyDirectFields(document, cachedDocument);
+ } else {
+ this._cache[key] = document;
+ cachedDocument = document;
+ }
+ return cachedDocument;
+ },
+
+ load: function(instance, id, callback, failure) {
+ if (id && id !== '*') {
+ var self = this;
+ this._jsonRequest(["GET", instance['$entity'] + "/" + id], function(response) {
+ instance['$loadFrom'](response);
+ instance['$migrate']();
+ var clone = instance['$$entity'](instance);
+ self.cache(clone);
+ (callback||noop)(instance);
+ }, failure);
+ }
+ return instance;
+ },
+
+ loadMany: function(entity, ids, callback) {
+ var self=this;
+ var list = [];
+ var callbackCount = 0;
+ foreach(ids, function(id){
+ list.push(self.load(entity(), id, function(){
+ callbackCount++;
+ if (callbackCount == ids.length) {
+ (callback||noop)(list);
+ }
+ }));
+ });
+ return list;
+ },
+
+ loadOrCreate: function(instance, id, callback) {
+ var self=this;
+ return this.load(instance, id, callback, function(response){
+ if (response['$status_code'] == 404) {
+ instance['$id'] = id;
+ (callback||noop)(instance);
+ } else {
+ throw response;
+ }
+ });
+ },
+
+ loadAll: function(entity, callback) {
+ var self = this;
+ var list = [];
+ list['$$accept'] = function(doc){
+ return doc['$entity'] == entity['title'];
+ };
+ this._cache_collections.push(list);
+ this._jsonRequest(["GET", entity['title']], function(response) {
+ var rows = response;
+ for ( var i = 0; i < rows.length; i++) {
+ var document = entity();
+ document['$loadFrom'](rows[i]);
+ list.push(self.cache(document));
+ }
+ (callback||noop)(list);
+ });
+ return list;
+ },
+
+ save: function(document, callback) {
+ var self = this;
+ var data = {};
+ document['$saveTo'](data);
+ this._jsonRequest(["POST", "", data], function(response) {
+ document['$loadFrom'](response);
+ var cachedDoc = self.cache(document);
+ _.each(self._cache_collections, function(collection){
+ if (collection['$$accept'](document)) {
+ angularArray['includeIf'](collection, cachedDoc, true);
+ }
+ });
+ if (document['$$anchor']) {
+ self.anchor[document['$$anchor']] = document['$id'];
+ }
+ if (callback)
+ callback(document);
+ });
+ },
+
+ remove: function(document, callback) {
+ var self = this;
+ var data = {};
+ document['$saveTo'](data);
+ this._jsonRequest(["DELETE", "", data], function(response) {
+ delete self._cache[document['$entity'] + '/' + document['$id']];
+ _.each(self._cache_collections, function(collection){
+ for ( var i = 0; i < collection.length; i++) {
+ var item = collection[i];
+ if (item['$id'] == document['$id']) {
+ collection.splice(i, 1);
+ }
+ }
+ });
+ (callback||noop)(response);
+ });
+ },
+
+ _jsonRequest: function(request, callback, failure) {
+ request['$$callback'] = callback;
+ request['$$failure'] = failure||function(response){
+ throw response;
+ };
+ this.bulkRequest.push(request);
+ },
+
+ flush: function() {
+ if (this.bulkRequest.length === 0) return;
+ var self = this;
+ var bulkRequest = this.bulkRequest;
+ this.bulkRequest = [];
+ log('REQUEST:', bulkRequest);
+ function callback(code, bulkResponse){
+ log('RESPONSE[' + code + ']: ', bulkResponse);
+ if(bulkResponse['$status_code'] == 401) {
+ self.users['login'](function(){
+ self.post(bulkRequest, callback);
+ });
+ } else if(bulkResponse['$status_code']) {
+ alert(toJson(bulkResponse));
+ } else {
+ for ( var i = 0; i < bulkResponse.length; i++) {
+ var response = bulkResponse[i];
+ var request = bulkRequest[i];
+ var responseCode = response['$status_code'];
+ if(responseCode) {
+ if(responseCode == 403) {
+ self.users['notAuthorized']();
+ } else {
+ request['$$failure'](response);
+ }
+ } else {
+ request['$$callback'](response);
+ }
+ }
+ }
+ }
+ this.post(bulkRequest, callback);
+ },
+
+ saveScope: function(scope, callback) {
+ var saveCounter = 1;
+ function onSaveDone() {
+ saveCounter--;
+ if (saveCounter === 0 && callback)
+ callback();
+ }
+ for(var key in scope) {
+ var item = scope[key];
+ if (item && item['$save'] == Model.prototype['$save']) {
+ saveCounter++;
+ item['$save'](onSaveDone);
+ }
+ }
+ onSaveDone();
+ },
+
+ query: function(type, query, arg, callback){
+ var self = this;
+ var queryList = [];
+ queryList['$$accept'] = function(doc){
+ return false;
+ };
+ this._cache_collections.push(queryList);
+ var request = type['title'] + '/' + query + '=' + arg;
+ this._jsonRequest(["GET", request], function(response){
+ var list = response;
+ foreach(list, function(item){
+ var document = type()['$loadFrom'](item);
+ queryList.push(self.cache(document));
+ });
+ (callback||noop)(queryList);
+ });
+ return queryList;
+ },
+
+ entities: function(callback) {
+ var entities = [];
+ var self = this;
+ this._jsonRequest(["GET", "$entities"], function(response) {
+ foreach(response, function(value, entityName){
+ entities.push(self.entity(entityName));
+ });
+ entities.sort(function(a,b){return a.title > b.title ? 1 : -1;});
+ (callback||noop)(entities);
+ });
+ return entities;
+ },
+
+ documentCountsByUser: function(){
+ var counts = {};
+ var self = this;
+ self.post([["GET", "$users"]], function(code, response){
+ extend(counts, response[0]);
+ });
+ return counts;
+ },
+
+ userDocumentIdsByEntity: function(user){
+ var ids = {};
+ var self = this;
+ self.post([["GET", "$users/" + user]], function(code, response){
+ extend(ids, response[0]);
+ });
+ return ids;
+ },
+
+ entity: function(name, defaults){
+ if (!name) {
+ return DataStore.NullEntity;
+ }
+ var self = this;
+ var entity = extend(function(initialState){
+ return new Model(entity, initialState);
+ }, {
+ // entity.name does not work as name seems to be reserved for functions
+ 'title': name,
+ '$$factory': true,
+ datastore: this, //private, obfuscate
+ 'defaults': defaults || {},
+ 'load': function(id, callback){
+ return self.load(entity(), id, callback);
+ },
+ 'loadMany': function(ids, callback){
+ return self.loadMany(entity, ids, callback);
+ },
+ 'loadOrCreate': function(id, callback){
+ return self.loadOrCreate(entity(), id, callback);
+ },
+ 'all': function(callback){
+ return self.loadAll(entity, callback);
+ },
+ 'query': function(query, queryArgs, callback){
+ return self.query(entity, query, queryArgs, callback);
+ },
+ 'properties': function(callback) {
+ self._jsonRequest(["GET", name + "/$properties"], callback);
+ }
+ });
+ return entity;
+ },
+
+ join: function(join){
+ function fn(){
+ throw "Joined entities can not be instantiated into a document.";
+ };
+ function base(name){return name ? name.substring(0, name.indexOf('.')) : undefined;}
+ function next(name){return name.substring(name.indexOf('.') + 1);}
+ var joinOrder = _(join).chain().
+ map(function($, name){
+ return name;}).
+ sortBy(function(name){
+ var path = [];
+ do {
+ if (_(path).include(name)) throw "Infinite loop in join: " + path.join(" -> ");
+ path.push(name);
+ if (!join[name]) throw _("Named entity '<%=name%>' is undefined.").template({name:name});
+ name = base(join[name].on);
+ } while(name);
+ return path.length;
+ }).
+ value();
+ if (_(joinOrder).select(function($){return join[$].on;}).length != joinOrder.length - 1)
+ throw "Exactly one entity needs to be primary.";
+ fn['query'] = function(exp, value) {
+ var joinedResult = [];
+ var baseName = base(exp);
+ if (baseName != joinOrder[0]) throw _("Named entity '<%=name%>' is not a primary entity.").template({name:baseName});
+ var Entity = join[baseName].join;
+ var joinIndex = 1;
+ Entity['query'](next(exp), value, function(result){
+ var nextJoinName = joinOrder[joinIndex++];
+ var nextJoin = join[nextJoinName];
+ var nextJoinOn = nextJoin.on;
+ var joinIds = {};
+ _(result).each(function(doc){
+ var row = {};
+ joinedResult.push(row);
+ row[baseName] = doc;
+ var id = Scope.getter(row, nextJoinOn);
+ joinIds[id] = id;
+ });
+ nextJoin.join.loadMany(_.toArray(joinIds), function(result){
+ var byId = {};
+ _(result).each(function(doc){
+ byId[doc.$id] = doc;
+ });
+ _(joinedResult).each(function(row){
+ var id = Scope.getter(row, nextJoinOn);
+ row[nextJoinName] = byId[id];
+ });
+ });
+ });
+ return joinedResult;
+ };
+ return fn;
+ }
+};