0
|
1 define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array",
|
|
2 "../safe", "dojo/when", "dojo/Deferred", "dojo/store/util/QueryResults" ], function(declare,
|
|
3 lang, array, safe, when, Deferred, QueryResults) {
|
|
4 /**
|
8
|
5 * @module implab/data/RestStore
|
0
|
6 *
|
|
7 * Реализует шаблон репозитария dojo/store над уже имеющимся хранилищем. При получении и
|
8
|
8 * отправке данных в нижележащие хранилище используется implab/data/MapSchema для преобразования
|
0
|
9 * данных.
|
|
10 */
|
|
11 return declare(null, {
|
|
12
|
|
13 itemsType : null,
|
|
14
|
|
15 _dataContext : null,
|
|
16
|
|
17 _store : null, // backing store
|
|
18 _cache : null,
|
|
19
|
|
20 constructor : function(options) {
|
|
21 options = options || {};
|
|
22
|
|
23 this._cache = {};
|
|
24 if (options.store)
|
|
25 this._store = options.store;
|
|
26 if (options.dataContext)
|
|
27 this._dataContext = options.dataContext;
|
|
28 },
|
|
29
|
|
30 setDataContext : function(v) {
|
|
31 this._dataContext = v;
|
|
32 },
|
|
33
|
|
34 getDataContext : function() {
|
|
35 return this._dataContext;
|
|
36 },
|
|
37
|
|
38 // READ
|
|
39 get : function(id) {
|
|
40 var me = this;
|
|
41 var cache = me.getCacheEntry(id);
|
|
42 if (cache)
|
|
43 return cache;
|
|
44 else
|
|
45 return when(me._store.get(id), function(data) {
|
|
46 return me._mapToObject(id, data);
|
|
47 });
|
|
48 },
|
|
49
|
|
50 query : function(query, options) {
|
|
51 var me = this;
|
|
52 var d = me._store.query(query, options);
|
|
53 var result = QueryResults(when(d, function(data) {
|
|
54 return array.map(data, function(item) {
|
|
55 return me._mapToObject(me._store.getIdentity(item), item);
|
|
56 });
|
|
57 }));
|
|
58 result.total = d.total;
|
|
59 return result;
|
|
60 },
|
|
61
|
|
62 getIdentity : function(object) {
|
|
63 return object.getId();
|
|
64 },
|
|
65
|
|
66 // UPDATE
|
|
67 put : function(object, directives) {
|
|
68 return this._store.put(this._mapFromObject(object), directives);
|
|
69 },
|
|
70
|
|
71 // INSERT
|
|
72 add : function(object, directives) {
|
|
73 var me = this;
|
|
74 // добавляем в хранилище данные, сохраняем в кеше объект с
|
|
75 // полученным идентификатором
|
|
76 return when(
|
|
77 me._store.add(this._mapFromObject(object), directives),
|
|
78 function(id) {
|
|
79 object.attach(id, me);
|
|
80 me.storeCacheEntry(id, object);
|
|
81 return id;
|
|
82 });
|
|
83 },
|
|
84
|
|
85 // DELETE
|
|
86 remove : function(id) {
|
|
87 var me = this;
|
|
88 return when(me._store.remove(id), function() {
|
|
89 me.removeCacheEntry(id);
|
|
90 });
|
|
91 },
|
|
92
|
|
93 _mapToObject : function(id, data) {
|
|
94 var instance = this.createInstance(id);
|
|
95 this.populateInstance(instance, data);
|
|
96 return instance;
|
|
97 },
|
|
98
|
|
99 _mapFromObject : function(object) {
|
|
100 return this.serializeInstance(object);
|
|
101 },
|
|
102
|
|
103 getCacheEntry : function(id) {
|
|
104 safe.argumentNotNull(id, "id");
|
|
105 id = id.toString();
|
|
106
|
|
107 return this._cache[id];
|
|
108 },
|
|
109
|
|
110 storeCacheEntry : function(id, object) {
|
|
111 safe.argumentNotNull(id, "id");
|
|
112 id = id.toString();
|
|
113
|
|
114 this._cache[id] = object;
|
|
115 },
|
|
116
|
|
117 removeCacheEntry : function(id) {
|
|
118 safe.argumentNotNull(id, "id");
|
|
119 id = id.toString();
|
|
120 delete this._cache[id];
|
|
121 },
|
|
122
|
|
123 /** Создает экземпляр сущности с указанным идентификатором, либо извлекает из кеша, если таковая уже имеется.
|
|
124 * @remarks
|
|
125 * Технически сюда можно было бы дополнительно передать данные для ининциализации объекта,
|
|
126 * но концептуально это не верно, поскольку процесс чтения объекта состоит из двух этапов:
|
|
127 * 1. Создание пустого объекта (createInstance)
|
|
128 * 2. Заполнение объекта при помощи схемы отображения (populateInstance)
|
|
129 * при этом первый этап может быть выполнен за долго до второго, например,
|
|
130 * при создании заглушек в процессе установления ссылок между объектами.
|
|
131 */
|
|
132 createInstance : function(id) {
|
|
133 var instance = this.getCacheEntry(id);
|
|
134 if (!instance) {
|
|
135 instance = this.createInstanceImpl(id);
|
|
136 this.storeCacheEntry(id, instance);
|
|
137 }
|
|
138 return instance;
|
|
139 },
|
|
140
|
|
141 /** Непосредственно создает экземпляр сущнсти, т.е. является фабричным методом.
|
|
142 * @param {String} id идентификатор создаваемого экземпляра.
|
|
143 */
|
|
144 createInstanceImpl : function(id) {
|
|
145 var opts = {
|
|
146 dataContext : this.getDataContext(),
|
|
147 id : id
|
|
148 };
|
|
149
|
|
150 return new this.itemsType(opts);
|
|
151 },
|
|
152
|
|
153 populateInstance : function(instance, data) {
|
|
154 this.itemsType.readData(instance, data,this.getDataContext());
|
|
155 if (instance.onPopulate)
|
|
156 instance.onPopulate();
|
|
157 },
|
|
158
|
|
159 serializeInstance : function(instance) {
|
|
160 var data = {};
|
|
161 this.itemsType.writeData(instance, data, this.getDataContext());
|
|
162 return data;
|
|
163 }
|
|
164
|
|
165 });
|
|
166 }); |