Mercurial > pub > ImplabJs
diff src/implab/data/RestStore.js @ 0:fc2517695ee1
Initial commit, draft import of existing work
author | cin |
---|---|
date | Thu, 01 Jun 2017 13:20:03 +0300 |
parents | |
children | f0035923ff3e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/implab/data/RestStore.js Thu Jun 01 13:20:03 2017 +0300 @@ -0,0 +1,166 @@ +define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", + "../safe", "dojo/when", "dojo/Deferred", "dojo/store/util/QueryResults" ], function(declare, + lang, array, safe, when, Deferred, QueryResults) { + /** + * @module core/data/RestStore + * + * Реализует шаблон репозитария dojo/store над уже имеющимся хранилищем. При получении и + * отправке данных в нижележащие хранилище используется core/data/MapSchema для преобразования + * данных. + */ + return declare(null, { + + itemsType : null, + + _dataContext : null, + + _store : null, // backing store + _cache : null, + + constructor : function(options) { + options = options || {}; + + this._cache = {}; + if (options.store) + this._store = options.store; + if (options.dataContext) + this._dataContext = options.dataContext; + }, + + setDataContext : function(v) { + this._dataContext = v; + }, + + getDataContext : function() { + return this._dataContext; + }, + + // READ + get : function(id) { + var me = this; + var cache = me.getCacheEntry(id); + if (cache) + return cache; + else + return when(me._store.get(id), function(data) { + return me._mapToObject(id, data); + }); + }, + + query : function(query, options) { + var me = this; + var d = me._store.query(query, options); + var result = QueryResults(when(d, function(data) { + return array.map(data, function(item) { + return me._mapToObject(me._store.getIdentity(item), item); + }); + })); + result.total = d.total; + return result; + }, + + getIdentity : function(object) { + return object.getId(); + }, + + // UPDATE + put : function(object, directives) { + return this._store.put(this._mapFromObject(object), directives); + }, + + // INSERT + add : function(object, directives) { + var me = this; + // добавляем в хранилище данные, сохраняем в кеше объект с + // полученным идентификатором + return when( + me._store.add(this._mapFromObject(object), directives), + function(id) { + object.attach(id, me); + me.storeCacheEntry(id, object); + return id; + }); + }, + + // DELETE + remove : function(id) { + var me = this; + return when(me._store.remove(id), function() { + me.removeCacheEntry(id); + }); + }, + + _mapToObject : function(id, data) { + var instance = this.createInstance(id); + this.populateInstance(instance, data); + return instance; + }, + + _mapFromObject : function(object) { + return this.serializeInstance(object); + }, + + getCacheEntry : function(id) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + + return this._cache[id]; + }, + + storeCacheEntry : function(id, object) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + + this._cache[id] = object; + }, + + removeCacheEntry : function(id) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + delete this._cache[id]; + }, + + /** Создает экземпляр сущности с указанным идентификатором, либо извлекает из кеша, если таковая уже имеется. + * @remarks + * Технически сюда можно было бы дополнительно передать данные для ининциализации объекта, + * но концептуально это не верно, поскольку процесс чтения объекта состоит из двух этапов: + * 1. Создание пустого объекта (createInstance) + * 2. Заполнение объекта при помощи схемы отображения (populateInstance) + * при этом первый этап может быть выполнен за долго до второго, например, + * при создании заглушек в процессе установления ссылок между объектами. + */ + createInstance : function(id) { + var instance = this.getCacheEntry(id); + if (!instance) { + instance = this.createInstanceImpl(id); + this.storeCacheEntry(id, instance); + } + return instance; + }, + + /** Непосредственно создает экземпляр сущнсти, т.е. является фабричным методом. + * @param {String} id идентификатор создаваемого экземпляра. + */ + createInstanceImpl : function(id) { + var opts = { + dataContext : this.getDataContext(), + id : id + }; + + return new this.itemsType(opts); + }, + + populateInstance : function(instance, data) { + this.itemsType.readData(instance, data,this.getDataContext()); + if (instance.onPopulate) + instance.onPopulate(); + }, + + serializeInstance : function(instance) { + var data = {}; + this.itemsType.writeData(instance, data, this.getDataContext()); + return data; + } + + }); +}); \ No newline at end of file