Mercurial > pub > ImplabJs
comparison src/djol/VectorStore.js @ 10:8705103f074f
Слияние
author | cin |
---|---|
date | Mon, 21 Aug 2017 18:03:00 +0300 |
parents | f0035923ff3e |
children | 60f6493e2892 |
comparison
equal
deleted
inserted
replaced
9:37e9e6bbe87a | 10:8705103f074f |
---|---|
1 define( | |
2 [ | |
3 "dojo/_base/declare", | |
4 "dojo/_base/array", | |
5 "implab/safe", | |
6 "implab/Uuid", | |
7 "ol", | |
8 "ol3/listen", | |
9 "./VectorStoreQuery", | |
10 "dojo/store/util/QueryResults" | |
11 ], | |
12 function (declare, array, safe, UUID, ol, listen, VectorStoreQuery, QueryResults) { | |
13 function createPaginator(opts) { | |
14 return (opts.count || opts.start) && | |
15 function (results) { | |
16 var total = results.length; | |
17 results = results.slice(opts.start || 0, (opts.start || 0) + | |
18 (opts.count || Infinity)); | |
19 results.total = total; | |
20 | |
21 return results; | |
22 }; | |
23 } | |
24 | |
25 /** | |
26 * Обертка вокруг векторного источника данных ol.source.Vector, | |
27 * реализует dojo/store а также notify, что делает возможным наблюдение | |
28 * за хранилищем при помощи dojo/store/Observable. | |
29 * | |
30 * @disposable | |
31 */ | |
32 return declare( | |
33 null, { | |
34 _source: null, // ol3.source.Vector | |
35 | |
36 _subscriptions: null, | |
37 | |
38 constructor: function (opts) { | |
39 safe.argumentNotNull(opts, "opts"); | |
40 safe.argumentOfType( | |
41 opts.source, | |
42 ol.source.Vector, | |
43 "opts.source"); | |
44 | |
45 var me = this; | |
46 | |
47 me._source = opts.source; | |
48 }, | |
49 | |
50 getSource: function () { | |
51 return this._source; | |
52 }, | |
53 | |
54 get: function (id) { | |
55 return this._source.getFeatureById(id); | |
56 }, | |
57 | |
58 /** | |
59 * @param{Object|Function} q предикат для выбора объекта | |
60 * @param{Object} opts параметры выполнения (start,count,sort) | |
61 * @return{Function} filter(data) filter.matches | |
62 * filter.matches.predicate | |
63 * filter.matches.extent filter.sort | |
64 * filter.sort.compare | |
65 */ | |
66 queryEngine: function (q, opts) { | |
67 opts = opts || {}; | |
68 | |
69 // строим функцию для фильтрации | |
70 var filter; | |
71 if (q instanceof Function) { | |
72 // если передали уже готовую функцию, испольуем ее | |
73 filter = new VectorStoreQuery(q, q.extent); | |
74 } else { | |
75 // если передали объект | |
76 var extent; | |
77 // вытаскиваем из него extent | |
78 if (q && 'extent' in q) { | |
79 extent = q.extent; | |
80 delete q.extent; | |
81 } | |
82 | |
83 // строим новую функцию фильтрации | |
84 filter = new VectorStoreQuery(q, extent); | |
85 } | |
86 | |
87 // строим функцию сортировки | |
88 var sort = opts.sort && this.sortEngine(opts.sort); | |
89 | |
90 var paginate = createPaginator(opts); | |
91 | |
92 // строим функцию выполнения запроса | |
93 var execute = function (data) { | |
94 var results = array.filter(data, filter); | |
95 | |
96 if (sort) | |
97 sort(results); | |
98 | |
99 if (paginate) | |
100 results = paginate(results); | |
101 return results; | |
102 }; | |
103 | |
104 execute.matches = filter; | |
105 execute.sort = sort; | |
106 execute.paginate = paginate; | |
107 return execute; | |
108 }, | |
109 | |
110 sortEngine: function (options) { | |
111 var cmp = function (a, b) { | |
112 for (var sort, i = 0; | |
113 (sort = options[i]); i++) { | |
114 var aValue = a.get(sort.attribute); | |
115 var bValue = b.get(sort.attribute); | |
116 if (aValue != bValue) { | |
117 return Boolean(sort.descending) == aValue > bValue ? -1 : 1; | |
118 } | |
119 } | |
120 return 0; | |
121 }; | |
122 | |
123 var execute = function (data) { | |
124 return data.sort(cmp); | |
125 }; | |
126 | |
127 execute.compare = cmp; | |
128 return execute; | |
129 }, | |
130 | |
131 /** | |
132 * Запрашивает объекты со слоя | |
133 * | |
134 * @param{object|VectorStoreQuery|Function} query | |
135 * | |
136 * <pre> | |
137 * { | |
138 * extent : ol3.Extent, | |
139 * } | |
140 * </pre> | |
141 */ | |
142 query: function (q, options) { | |
143 var me = this; | |
144 var filter = this.queryEngine(q, options); | |
145 | |
146 if (this.notify && !this.hasOwnProperty("_subscriptions")) { | |
147 me._subscriptions = []; | |
148 | |
149 var sc = function (evt, handler) { | |
150 me._subscriptions.push(listen(me._source, evt, safe.delegate(me, handler))); | |
151 } | |
152 | |
153 sc("addfeature", "_onAdd"); | |
154 sc("changefeature", "_onUpdate"); | |
155 sc("removefeature", "_onRemove"); | |
156 } | |
157 | |
158 var predicate, data, extent = filter.matches && | |
159 filter.matches.extent; | |
160 // если это запрос с указанием области | |
161 if (extent) { | |
162 predicate = filter.matches.predicate; | |
163 | |
164 data = this._source.getFeaturesInExtent(extent); | |
165 | |
166 if (predicate) | |
167 data = array.filter(data, predicate); | |
168 | |
169 if (filter.sort) | |
170 filter.sort(data); | |
171 | |
172 if (filter.paginate) | |
173 data = filter.paginate(data); | |
174 } else { | |
175 // любой другой запрос | |
176 data = filter(this._source.getFeatures()); | |
177 } | |
178 | |
179 return new QueryResults(data); | |
180 }, | |
181 | |
182 put: function (obj, options) { | |
183 safe.argumentOfType(obj, ol.Feature, "obj"); | |
184 if (!options) | |
185 options = {}; | |
186 | |
187 if (options.id) | |
188 obj.setId(options.id); | |
189 | |
190 var id = obj.getId() || new UUID(); | |
191 | |
192 var prev = this.get(id); | |
193 | |
194 if ('overwrite' in options) { | |
195 // overwrite=true указан, но перезаписывать нечего | |
196 if (!prev && options.overwrite) | |
197 throw new Error("The specified feature with id '" + | |
198 id + "' doesn't exist in the store"); | |
199 | |
200 // overwrite=false указан, но объект уже существует | |
201 if (prev && !options.overwrite) | |
202 throw new Error("The specified feature with id '" + | |
203 id + "' already exists in the store"); | |
204 } | |
205 | |
206 // ok | |
207 if (prev) { | |
208 var data = obj.getProperties(); | |
209 prev.setProperties(data); | |
210 } else { | |
211 this._source.addFeature(obj); | |
212 } | |
213 | |
214 return id; | |
215 }, | |
216 | |
217 add: function (obj, options) { | |
218 safe.argumentOfType(obj, ol.Feature, "obj"); | |
219 | |
220 if (!options) | |
221 options = {}; | |
222 | |
223 if (options.id) | |
224 obj.setId(options.id); | |
225 | |
226 var id = obj.getId() || new UUID(); | |
227 | |
228 var prev = this.get(id); | |
229 | |
230 if (prev) | |
231 throw new Error("The specified feature with id '" + id + | |
232 "' already exists in the store"); | |
233 | |
234 this._source.addFeature(obj); | |
235 }, | |
236 | |
237 remove: function (id) { | |
238 var me = this; | |
239 | |
240 var ft = me.get(id); | |
241 if (ft) | |
242 me._source.removeFeature(ft); | |
243 }, | |
244 | |
245 getIdentity: function (obj) { | |
246 if (safe.isNull(obj)) | |
247 return undefined; | |
248 if (!(obj instanceof ol.Feature)) | |
249 throw new Error("A feature is expected"); | |
250 | |
251 return obj.getId(); | |
252 }, | |
253 | |
254 _onAdd: function (ev) { | |
255 this.notify(ev.feature); | |
256 }, | |
257 | |
258 _onRemove: function (ev) { | |
259 var id = ev.feature.getId(); | |
260 if (!safe.isNull(id)) | |
261 this.notify(undefined, id); | |
262 }, | |
263 | |
264 _onUpdate: function (ev) { | |
265 var id = ev.feature.getId(); | |
266 if (!safe.isNull(id)) | |
267 this.notify(ev.feature, id); | |
268 }, | |
269 | |
270 dispose: function () { | |
271 var me = this; | |
272 if (me._subscriptions) | |
273 me._subscriptions.forEach(function (sc) { | |
274 sc.remove(); | |
275 }); | |
276 | |
277 me._source = null; | |
278 me._subscriptions = null; | |
279 } | |
280 }); | |
281 }); |