diff options
| author | Misko Hevery | 2010-01-25 20:02:24 -0800 |
|---|---|---|
| committer | Misko Hevery | 2010-01-25 20:02:24 -0800 |
| commit | 0b630972b15676b1c1b6c59edd564e4ee331ec70 (patch) | |
| tree | bd31ca5b69b6ea03d906a3107dfe38a8c1adcb8e /src/DataStore.js | |
| parent | 19bbee030ba012b8fc4835c1d17e039804b2b94b (diff) | |
| parent | 473e57e22532f9b85fc9dcc1bcc53e12a10154c2 (diff) | |
| download | angular.js-0b630972b15676b1c1b6c59edd564e4ee331ec70.tar.bz2 | |
merge
Diffstat (limited to 'src/DataStore.js')
| -rw-r--r-- | src/DataStore.js | 604 |
1 files changed, 301 insertions, 303 deletions
diff --git a/src/DataStore.js b/src/DataStore.js index 97ab92ff..789b8f71 100644 --- a/src/DataStore.js +++ b/src/DataStore.js @@ -1,332 +1,330 @@ -// Copyright (C) 2009 BRAT Tech LLC - -nglr.DataStore = function(post, users, anchor) { +function DataStore(post, users, anchor) { this.post = post; this.users = users; - this._cache = {$collections:[]}; + this._cache_collections = []; + this._cache = {'$collections':this._cache_collections}; this.anchor = anchor; this.bulkRequest = []; }; -nglr.DataStore.prototype.cache = function(document) { - if (document.constructor != nglr.Model) { - throw "Parameter must be an instance of Entity! " + nglr.toJson(document); - } - var key = document.$entity + '/' + document.$id; - var cachedDocument = this._cache[key]; - if (cachedDocument) { - nglr.Model.copyDirectFields(document, cachedDocument); - } else { - this._cache[key] = document; - cachedDocument = document; - } - return cachedDocument; -}; - -nglr.DataStore.prototype.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||nglr.noop)(instance); - }, failure); - } - return instance; -}; - -nglr.DataStore.prototype.loadMany = function(entity, ids, callback) { - var self=this; - var list = []; - var callbackCount = 0; - jQuery.each(ids, function(i, id){ - list.push(self.load(entity(), id, function(){ - callbackCount++; - if (callbackCount == ids.length) { - (callback||nglr.noop)(list); - } - })); - }); - return list; -} +DataStore.NullEntity = extend(function(){}, { + 'all': function(){return [];}, + 'query': function(){return [];}, + 'load': function(){return {};}, + 'title': undefined +}); -nglr.DataStore.prototype.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||nglr.noop)(instance); +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 { - throw response; + this._cache[key] = document; + cachedDocument = document; } - }); -}; - -nglr.DataStore.prototype.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)); + 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); } - (callback||nglr.noop)(list); - }); - return list; -}; - -nglr.DataStore.prototype.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)) { - angular.Array.includeIf(collection, cachedDoc, true); + 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; } }); - if (document.$$anchor) { - self.anchor[document.$$anchor] = document.$id; - } - if (callback) - callback(document); - }); -}; - -nglr.DataStore.prototype.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); + }, + + 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); }); - (callback||nglr.noop)(response); - }); -}; - -nglr.DataStore.prototype._jsonRequest = function(request, callback, failure) { - request.$$callback = callback; - request.$$failure = failure||function(response){ - throw response; - }; - this.bulkRequest.push(request); -}; - -nglr.DataStore.prototype.flush = function() { - if (this.bulkRequest.length === 0) return; - var self = this; - var bulkRequest = this.bulkRequest; - this.bulkRequest = []; - console.log('REQUEST:', bulkRequest); - function callback(code, bulkResponse){ - console.log('RESPONSE[' + code + ']: ', bulkResponse); - if(bulkResponse.$status_code == 401) { - self.users.login(function(){ - self.post(bulkRequest, callback); + }, + + 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); + } + } }); - } else if(bulkResponse.$status_code) { - nglr.alert(nglr.toJson(bulkResponse)); - } else { - for ( var i = 0; i < bulkResponse.length; i++) { - var response = bulkResponse[i]; - var request = bulkRequest[i]; - var code = response.$status_code; - if(code) { - if(code == 403) { - self.users.notAuthorized(); + (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.$$failure(response); + request['$$callback'](response); } - } else { - request.$$callback(response); } } } - } - this.post(bulkRequest, callback); -}; - -nglr.DataStore.prototype.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 == nglr.Model.prototype.$save) { - saveCounter++; - item.$save(onSaveDone); - } - } - onSaveDone(); -}; - -nglr.DataStore.prototype.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; - for(var i = 0; i < list.length; i++) { - var document = new type().$loadFrom(list[i]); - queryList.push(self.cache(document)); + this.post(bulkRequest, callback); + }, + + saveScope: function(scope, callback) { + var saveCounter = 1; + function onSaveDone() { + saveCounter--; + if (saveCounter === 0 && callback) + callback(); } - if (callback) - callback(queryList); - }); - return queryList; -}; - -nglr.DataStore.prototype.entities = function(callback) { - var entities = []; - var self = this; - this._jsonRequest(["GET", "$entities"], function(response) { - for (var entityName in response) { - entities.push(self.entity(entityName)); + for(var key in scope) { + var item = scope[key]; + if (item && item['$save'] == Model.prototype['$save']) { + saveCounter++; + item['$save'](onSaveDone); + } } - entities.sort(function(a,b){return a.title > b.title ? 1 : -1;}); - if (callback) callback(entities); - }); - return entities; -}; - -nglr.DataStore.prototype.documentCountsByUser = function(){ - var counts = {}; - var self = this; - self.post([["GET", "$users"]], function(code, response){ - jQuery.each(response[0], function(key, value){ - counts[key] = value; - }); - }); - return counts; -}; - -nglr.DataStore.prototype.userDocumentIdsByEntity = function(user){ - var ids = {}; - var self = this; - self.post([["GET", "$users/" + user]], function(code, response){ - jQuery.each(response[0], function(key, value){ - ids[key] = value; + 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 ids; -}; - -nglr.DataStore.NullEntity = function(){}; -nglr.DataStore.NullEntity.all = function(){return [];}; -nglr.DataStore.NullEntity.query = function(){return [];}; -nglr.DataStore.NullEntity.load = function(){return {};}; -nglr.DataStore.NullEntity.title = undefined; - -nglr.DataStore.prototype.entity = function(name, defaults){ - if (!name) { - return nglr.DataStore.NullEntity; - } - var self = this; - var entity = function(initialState){ - return new nglr.Model(entity, initialState); - }; - // entity.name does not work as name seems to be reserved for functions - entity.title = name; - entity.$$factory = true; - entity.datastore = this; - entity.defaults = defaults || {}; - entity.load = function(id, callback){ - return self.load(entity(), id, callback); - }; - entity.loadMany = function(ids, callback){ - return self.loadMany(entity, ids, callback); - }; - entity.loadOrCreate = function(id, callback){ - return self.loadOrCreate(entity(), id, callback); - }; - entity.all = function(callback){ - return self.loadAll(entity, callback); - }; - entity.query = function(query, queryArgs, callback){ - return self.query(entity, query, queryArgs, callback); - }; - entity.properties = function(callback) { - self._jsonRequest(["GET", name + "/$properties"], callback); - }; - return entity; -}; - -nglr.DataStore.prototype.join = function(join){ - var fn = function(){ - 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 = nglr.Scope.getter(row, nextJoinOn); - joinIds[id] = id; + 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)); }); - nextJoin.join.loadMany(_.toArray(joinIds), function(result){ - var byId = {}; + 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){ - byId[doc.$id] = doc; + var row = {}; + joinedResult.push(row); + row[baseName] = doc; + var id = Scope.getter(row, nextJoinOn); + joinIds[id] = id; }); - _(joinedResult).each(function(row){ - var id = nglr.Scope.getter(row, nextJoinOn); - row[nextJoinName] = byId[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; -}; + return joinedResult; + }; + return fn; + } +};
\ No newline at end of file |
