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