mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 15:40:22 +00:00
334 lines
No EOL
9.6 KiB
JavaScript
334 lines
No EOL
9.6 KiB
JavaScript
function DataStore(post, users, anchor) {
|
|
this.post = post;
|
|
this.users = users;
|
|
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 instanceof Model) {
|
|
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)) {
|
|
angular['Array']['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;
|
|
for(var i = 0; i < list.length; i++) {
|
|
var document = new type().$loadFrom(list[i]);
|
|
queryList.push(self.cache(document));
|
|
}
|
|
if (callback)
|
|
callback(queryList);
|
|
});
|
|
return queryList;
|
|
},
|
|
|
|
entities: function(callback) {
|
|
var entities = [];
|
|
var self = this;
|
|
this._jsonRequest(["GET", "$entities"], function(response) {
|
|
for (var entityName in response) {
|
|
entities.push(self.entity(entityName));
|
|
}
|
|
entities.sort(function(a,b){return a.title > b.title ? 1 : -1;});
|
|
if (callback) callback(entities);
|
|
});
|
|
return entities;
|
|
},
|
|
|
|
documentCountsByUser: function(){
|
|
var counts = {};
|
|
var self = this;
|
|
self.post([["GET", "$users"]], function(code, response){
|
|
foreach(response[0], function(value, key){
|
|
counts[key] = value;
|
|
});
|
|
});
|
|
return counts;
|
|
},
|
|
|
|
userDocumentIdsByEntity: function(user){
|
|
var ids = {};
|
|
var self = this;
|
|
self.post([["GET", "$users/" + user]], function(code, response){
|
|
foreach(response[0], function(value, key){
|
|
ids[key] = value;
|
|
});
|
|
});
|
|
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,
|
|
'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;
|
|
}
|
|
}; |