@rentman/rm-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +23 -0
- package/package.json +33 -0
- package/src/classes/ApiFormatter.ts +338 -0
- package/src/classes/BatchStatus.ts +86 -0
- package/src/classes/ChangesCompiler.ts +161 -0
- package/src/classes/ChangesProcessor.ts +475 -0
- package/src/classes/CollectionCache.ts +234 -0
- package/src/classes/CollectionEntryService.ts +83 -0
- package/src/classes/CollectionHandler.ts +619 -0
- package/src/classes/CollectionResourceService.ts +38 -0
- package/src/classes/ColumnCache.ts +114 -0
- package/src/classes/ColumnExpansion.ts +74 -0
- package/src/classes/ColumnHandler.ts +90 -0
- package/src/classes/ColumnSet.ts +181 -0
- package/src/classes/ColumnUtil.ts +589 -0
- package/src/classes/CreateRequest.ts +158 -0
- package/src/classes/ItemAdministrator.ts +571 -0
- package/src/classes/ItemCache.ts +158 -0
- package/src/classes/ItemEntryService.ts +488 -0
- package/src/classes/ItemHandler.ts +592 -0
- package/src/classes/ItemRequestService.ts +229 -0
- package/src/classes/ItemResourceService.ts +36 -0
- package/src/classes/KeyService.ts +76 -0
- package/src/classes/LockService.ts +184 -0
- package/src/classes/ModuleChangesCompiler.ts +123 -0
- package/src/classes/PromiseService.ts +19 -0
- package/src/classes/QueryMatcher.ts +135 -0
- package/src/classes/QueryParser.ts +209 -0
- package/src/classes/QueryService.ts +35 -0
- package/src/classes/RequestColumnExpansion.ts +31 -0
- package/src/classes/ResourceCache.ts +289 -0
- package/src/classes/Util.ts +422 -0
- package/src/constants.ts +11 -0
- package/src/factories/BatchStatusFactory.ts +18 -0
- package/src/factories/ChangesCompilerFactory.ts +20 -0
- package/src/factories/ChangesProcessorFactory.ts +53 -0
- package/src/factories/CollectionCacheFactory.ts +15 -0
- package/src/factories/CollectionEntryFactory.ts +35 -0
- package/src/factories/CollectionResourceFactory.ts +36 -0
- package/src/factories/ColumnExpansionFactory.ts +25 -0
- package/src/factories/ColumnSetFactory.ts +24 -0
- package/src/factories/CreateRequestFactory.ts +28 -0
- package/src/factories/ItemCacheFactory.ts +18 -0
- package/src/factories/ItemEntryFactory.ts +18 -0
- package/src/factories/ItemResourceFactory.ts +28 -0
- package/src/factories/ModuleChangesCompilerFactory.ts +21 -0
- package/src/factories/QueryMatcherFactory.ts +20 -0
- package/src/factories/QueryParserFactory.ts +10 -0
- package/src/factories/RequestColumnExpansionFactory.ts +15 -0
- package/src/factories/ResourceCacheFactory.ts +55 -0
- package/src/index.ts +188 -0
- package/src/interfaces/ApiRequestServiceInterface.ts +17 -0
- package/src/interfaces/AuthInterface.ts +5 -0
- package/src/interfaces/ErrorHandlerInterface.ts +3 -0
- package/src/interfaces/ResourceCacheInterface.ts +9 -0
- package/src/models/CollectionEditResource.ts +139 -0
- package/src/models/CollectionEntry.ts +448 -0
- package/src/models/CollectionResource.ts +223 -0
- package/src/models/CollectionViewResource.ts +23 -0
- package/src/models/EditResource.ts +15 -0
- package/src/models/ItemEntry.ts +24 -0
- package/src/models/ItemResource.ts +35 -0
- package/src/models/ViewResource.ts +14 -0
- package/tsconfig.json +12 -0
- package/tslint.json +63 -0
- package/webpack.common.js +35 -0
- package/webpack.dev.js +10 -0
- package/webpack.prod.js +17 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import ChangesCompilerFactory from "../factories/ChangesCompilerFactory";
|
|
2
|
+
import ColumnExpansionFactory from "../factories/ColumnExpansionFactory";
|
|
3
|
+
import CreateRequestFactory from "../factories/CreateRequestFactory";
|
|
4
|
+
import RequestColumnExpansionFactory from "../factories/RequestColumnExpansionFactory";
|
|
5
|
+
import ApiRequestServiceInterface from '../interfaces/ApiRequestServiceInterface';
|
|
6
|
+
import ErrorHandlerInterface from '../interfaces/ErrorHandlerInterface';
|
|
7
|
+
import CollectionEntry from "../models/CollectionEntry";
|
|
8
|
+
import ItemEntry from "../models/ItemEntry";
|
|
9
|
+
import ApiFormatter from "./ApiFormatter";
|
|
10
|
+
import ChangesCompiler from "./ChangesCompiler";
|
|
11
|
+
import CollectionEntryService from "./CollectionEntryService";
|
|
12
|
+
import CollectionHandler from "./CollectionHandler";
|
|
13
|
+
import ColumnHandler from "./ColumnHandler";
|
|
14
|
+
import ItemEntryService from "./ItemEntryService";
|
|
15
|
+
import ItemHandler from "./ItemHandler";
|
|
16
|
+
import PromiseService from "./PromiseService";
|
|
17
|
+
import { createPath, getPath, hasProperties, inArray, isFunction } from "./Util";
|
|
18
|
+
|
|
19
|
+
export default class ChangesProcessor {
|
|
20
|
+
constructor (
|
|
21
|
+
private apiRequestService: ApiRequestServiceInterface,
|
|
22
|
+
private itemHandler: ItemHandler,
|
|
23
|
+
private errorHandler: ErrorHandlerInterface,
|
|
24
|
+
private collectionHandler: CollectionHandler,
|
|
25
|
+
private columnHandler: ColumnHandler,
|
|
26
|
+
private changesCompilerFactory: ChangesCompilerFactory,
|
|
27
|
+
private createRequestFactory: CreateRequestFactory,
|
|
28
|
+
private columnExpansionFactory: ColumnExpansionFactory,
|
|
29
|
+
private requestColumnExpansionFactory: RequestColumnExpansionFactory,
|
|
30
|
+
private collectionEntryService: CollectionEntryService,
|
|
31
|
+
private itemEntryService: ItemEntryService,
|
|
32
|
+
private apiFormatter: ApiFormatter,
|
|
33
|
+
private promiseService: PromiseService
|
|
34
|
+
) {
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// TODO: we can remove this once the document creation has been updated
|
|
38
|
+
getItemTypeUpdatePriority (itemType) {
|
|
39
|
+
switch (itemType) {
|
|
40
|
+
case 'Factuurregelbedrag':
|
|
41
|
+
return 0;
|
|
42
|
+
case 'Factuurregel':
|
|
43
|
+
case 'Minfactuur':
|
|
44
|
+
return 1;
|
|
45
|
+
default:
|
|
46
|
+
return 2;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
buildMoveRequest (compilationEntries) {
|
|
51
|
+
const result = {};
|
|
52
|
+
|
|
53
|
+
for (const compilationEntry of compilationEntries) {
|
|
54
|
+
const itemEntry = compilationEntry.item;
|
|
55
|
+
const itemType = itemEntry.itemType;
|
|
56
|
+
|
|
57
|
+
if (result[itemType] === undefined)
|
|
58
|
+
result[itemType] = [];
|
|
59
|
+
|
|
60
|
+
result[itemType].push(itemEntry.itemId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getMapValue (itemType, itemId, map) {
|
|
67
|
+
if (map === undefined)
|
|
68
|
+
return undefined;
|
|
69
|
+
|
|
70
|
+
if (map[itemType] === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
|
|
73
|
+
return map[itemType][itemId];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
execute (singleItems, collections, breakupByParent = false, parameters?, collectionOptions?, onAfterCreateCallback?) {
|
|
77
|
+
return this.executeRequests(
|
|
78
|
+
this.changesCompilerFactory.construct(singleItems, collections, collectionOptions),
|
|
79
|
+
parameters,
|
|
80
|
+
breakupByParent,
|
|
81
|
+
onAfterCreateCallback
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private executeCreateRequests (compilation, parameters, conversionMap, breakupByParent, onAfterCreateCallback) {
|
|
86
|
+
const requests = this.createRequestFactory.construct(compilation, parameters, breakupByParent).run();
|
|
87
|
+
const responses = [];
|
|
88
|
+
|
|
89
|
+
for (const request of requests)
|
|
90
|
+
responses.push(this.executeCreateRequest(request, conversionMap).then(notify));
|
|
91
|
+
|
|
92
|
+
return this.promiseService.all(responses).then(
|
|
93
|
+
() => {
|
|
94
|
+
return conversionMap;
|
|
95
|
+
},
|
|
96
|
+
this.errorHandler.reject
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
function notify (result) {
|
|
100
|
+
if (isFunction(onAfterCreateCallback))
|
|
101
|
+
onAfterCreateCallback(conversionMap);
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private executeCreateRequest (requestResource, conversionMap) {
|
|
108
|
+
return this.apiRequestService.requestSkeleton(requestResource.request).then(
|
|
109
|
+
response => {
|
|
110
|
+
const responseMap = response.map;
|
|
111
|
+
const responseColumns = response.fetchColumnsObject();
|
|
112
|
+
const itemEntries = requestResource.items;
|
|
113
|
+
|
|
114
|
+
for (const itemType in itemEntries) {
|
|
115
|
+
const columnExpansion = this.columnExpansionFactory.construct(
|
|
116
|
+
itemType,
|
|
117
|
+
requestResource.request.columns[itemType],
|
|
118
|
+
responseColumns
|
|
119
|
+
).run;
|
|
120
|
+
|
|
121
|
+
for (const itemId in itemEntries[itemType]) {
|
|
122
|
+
const itemEntry = itemEntries[itemType][itemId];
|
|
123
|
+
const newItemId = this.getMapValue(itemType, itemId, responseMap);
|
|
124
|
+
|
|
125
|
+
if (newItemId === undefined) {
|
|
126
|
+
console.warn('Create failed!', itemEntry);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.itemHandler.updateItemId(itemEntry, newItemId);
|
|
131
|
+
|
|
132
|
+
const fields = response.fetchObject(itemType, newItemId);
|
|
133
|
+
const expandResource = columnExpansion(itemEntry.columns, true);
|
|
134
|
+
|
|
135
|
+
this.itemEntryService.updateFields(itemEntry, fields);
|
|
136
|
+
|
|
137
|
+
if (expandResource === null)
|
|
138
|
+
continue;
|
|
139
|
+
|
|
140
|
+
this.itemEntryService.expand(
|
|
141
|
+
itemEntry,
|
|
142
|
+
fields,
|
|
143
|
+
response.fetchDerivedObject(itemType, newItemId, expandResource.difference.root),
|
|
144
|
+
expandResource
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.collectionHandler.addToCollections(requestResource.collections, true);
|
|
150
|
+
|
|
151
|
+
// extend conversion map
|
|
152
|
+
for (const itemType in responseMap) {
|
|
153
|
+
if (conversionMap[itemType] === undefined)
|
|
154
|
+
conversionMap[itemType] = {};
|
|
155
|
+
|
|
156
|
+
for (const itemId in responseMap[itemType])
|
|
157
|
+
conversionMap[itemType][itemId] = responseMap[itemType][itemId];
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
this.errorHandler.reject
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private prioritizeUpdateRequests (compilation, parameters) {
|
|
165
|
+
const prioritizedItemTypes = [[], [], []];
|
|
166
|
+
let requestChain = this.promiseService.when();
|
|
167
|
+
|
|
168
|
+
for (const itemType in compilation)
|
|
169
|
+
prioritizedItemTypes[this.getItemTypeUpdatePriority(itemType)].push(itemType);
|
|
170
|
+
|
|
171
|
+
for (const itemTypes of prioritizedItemTypes) {
|
|
172
|
+
if (itemTypes.length === 0)
|
|
173
|
+
continue;
|
|
174
|
+
|
|
175
|
+
requestChain = requestChain.then(
|
|
176
|
+
this.executeUpdateRequests(itemTypes, compilation, parameters),
|
|
177
|
+
this.errorHandler.reject
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return requestChain;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// construct a callback function
|
|
185
|
+
private executeUpdateRequests (itemTypes, compilation, parameters) {
|
|
186
|
+
return () => {
|
|
187
|
+
const requests = [];
|
|
188
|
+
|
|
189
|
+
for (const itemType of itemTypes) {
|
|
190
|
+
requests.push(this.executeUpdateRequest(itemType, compilation[itemType], parameters));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return this.promiseService.all(requests);
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private executeUpdateRequest (itemType, itemEntries, parameterMap) {
|
|
198
|
+
const request = {};
|
|
199
|
+
const requestColumns = this.requestColumnExpansionFactory.construct();
|
|
200
|
+
const collectionMap = {};
|
|
201
|
+
|
|
202
|
+
request[itemType] = {};
|
|
203
|
+
|
|
204
|
+
// we need to do the formatRequest call here (fields might have been updated)
|
|
205
|
+
for (const itemId in itemEntries) {
|
|
206
|
+
const itemEntry = itemEntries[itemId];
|
|
207
|
+
// RMCore todo: type
|
|
208
|
+
const itemRequest: any = request[itemType][itemId] = {};
|
|
209
|
+
const parameters = getPath(parameterMap, [itemType, itemId]);
|
|
210
|
+
|
|
211
|
+
itemRequest.values = this.itemEntryService.formatRequest(itemEntry);
|
|
212
|
+
|
|
213
|
+
if (parameters !== undefined)
|
|
214
|
+
itemRequest.parameters = parameters;
|
|
215
|
+
|
|
216
|
+
requestColumns.expand(itemEntry.columns);
|
|
217
|
+
this.collectionHandler.expandCollectionMap(itemEntry, collectionMap);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
for (const collectionId in collectionMap) {
|
|
221
|
+
const entry = collectionMap[collectionId];
|
|
222
|
+
|
|
223
|
+
if (entry.fitting.length > 0)
|
|
224
|
+
requestColumns.expand(entry.collection.columns);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return this.apiRequestService.updateItems(itemType, request, requestColumns.get()).then(
|
|
228
|
+
response => {
|
|
229
|
+
const columnExpansion = this.columnExpansionFactory.construct(
|
|
230
|
+
itemType,
|
|
231
|
+
requestColumns.get(),
|
|
232
|
+
response.fetchColumnsObject()
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
for (const itemId in itemEntries) {
|
|
236
|
+
const itemEntry = itemEntries[itemId];
|
|
237
|
+
const fields = response.fetchObject(itemType, itemId);
|
|
238
|
+
|
|
239
|
+
if (fields === undefined) {
|
|
240
|
+
console.warn('Update failed!', itemEntry);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const previous = this.apiFormatter.copyFields(itemEntry.initial, {}, itemEntry.columns.main);
|
|
245
|
+
|
|
246
|
+
this.itemEntryService.setDerived(
|
|
247
|
+
itemEntry,
|
|
248
|
+
response.fetchDerivedObject(itemType, itemId, itemEntry.columns.root)
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
this.itemEntryService.updateFields(itemEntry, fields);
|
|
252
|
+
this.itemEntryService.callOnChange(itemEntry, previous);
|
|
253
|
+
|
|
254
|
+
const expandResource = columnExpansion.run(itemEntry.columns, true);
|
|
255
|
+
|
|
256
|
+
if (expandResource === null)
|
|
257
|
+
continue;
|
|
258
|
+
|
|
259
|
+
this.itemEntryService.expand(
|
|
260
|
+
itemEntry,
|
|
261
|
+
fields,
|
|
262
|
+
response.fetchDerivedObject(itemType, itemId, expandResource.difference.root),
|
|
263
|
+
expandResource
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
this.collectionHandler.removeFromAndAddToCollections(collectionMap);
|
|
268
|
+
},
|
|
269
|
+
this.errorHandler.reject
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private executeDeleteRequests (compilation) {
|
|
274
|
+
const requests = [];
|
|
275
|
+
|
|
276
|
+
for (const itemType in compilation) // clearing not necessary
|
|
277
|
+
requests.push(this.executeDeleteRequest(itemType, compilation[itemType]));
|
|
278
|
+
|
|
279
|
+
return this.promiseService.all(requests);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private executeDeleteRequest (itemType, itemEntries: ItemEntry[]) {
|
|
283
|
+
const idArray = [];
|
|
284
|
+
|
|
285
|
+
for (const itemEntry of itemEntries)
|
|
286
|
+
idArray.push(itemEntry.itemId);
|
|
287
|
+
|
|
288
|
+
return this.apiRequestService.delete(
|
|
289
|
+
itemType,
|
|
290
|
+
idArray
|
|
291
|
+
).then(
|
|
292
|
+
response => {
|
|
293
|
+
const responseIdArray = response.items;
|
|
294
|
+
const collectionMap = {};
|
|
295
|
+
|
|
296
|
+
for (const itemEntry of itemEntries) {
|
|
297
|
+
if (!inArray(itemEntry.itemId, responseIdArray))
|
|
298
|
+
console.warn('Delete failed!', itemEntry);
|
|
299
|
+
|
|
300
|
+
this.collectionHandler.expandCollectionMap(itemEntry, collectionMap);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
this.collectionHandler.removeFromCollections(collectionMap, true);
|
|
304
|
+
},
|
|
305
|
+
this.errorHandler.reject
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private executeMoveRequests (compilation, conversionMap) {
|
|
310
|
+
const self = this;
|
|
311
|
+
const requests = [];
|
|
312
|
+
|
|
313
|
+
for (const parentType in compilation) {
|
|
314
|
+
for (const parentId in compilation[parentType])
|
|
315
|
+
executeMoveRequest(parentType, parentId);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return this.promiseService.all(requests);
|
|
319
|
+
|
|
320
|
+
function executeMoveRequest (parentType, parentId) {
|
|
321
|
+
// only the parent id could have been updated
|
|
322
|
+
const compilationEntries = compilation[parentType][parentId];
|
|
323
|
+
const newParentId = this.getMapValue(parentType, parentId, conversionMap);
|
|
324
|
+
|
|
325
|
+
requests.push(
|
|
326
|
+
self.apiRequestService.moveItems(
|
|
327
|
+
parentType,
|
|
328
|
+
newParentId !== undefined ? newParentId : parentId,
|
|
329
|
+
this.buildMoveRequest(compilationEntries)
|
|
330
|
+
).then(
|
|
331
|
+
response => {
|
|
332
|
+
self.processMoveResponse(response, compilationEntries);
|
|
333
|
+
},
|
|
334
|
+
self.errorHandler.reject
|
|
335
|
+
)
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private processMoveResponse (response, compilationEntries) {
|
|
341
|
+
// TODO: process response
|
|
342
|
+
|
|
343
|
+
const itemEntries = [];
|
|
344
|
+
const removeCollectionMap = {};
|
|
345
|
+
const addCollectionMap = {};
|
|
346
|
+
|
|
347
|
+
for (const compilationEntry of compilationEntries) {
|
|
348
|
+
const itemEntry: ItemEntry = compilationEntry.item;
|
|
349
|
+
|
|
350
|
+
this.addCollectionMapEntry(
|
|
351
|
+
removeCollectionMap,
|
|
352
|
+
compilationEntry.parentId,
|
|
353
|
+
itemEntry,
|
|
354
|
+
itemEntry.itemId
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
this.addCollectionMapEntry(
|
|
358
|
+
addCollectionMap,
|
|
359
|
+
itemEntry.parent.itemId,
|
|
360
|
+
itemEntry,
|
|
361
|
+
itemEntry
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
itemEntries.push(itemEntry);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
this.forEachCollection(removeCollectionMap, 'removeItems');
|
|
368
|
+
this.forEachCollection(addCollectionMap, 'addItems');
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private addCollectionMapEntry (collectionMap, parentId, itemEntry, value) {
|
|
372
|
+
const collectionMapEntry = createPath(
|
|
373
|
+
collectionMap,
|
|
374
|
+
[itemEntry.parent.itemType, parentId, itemEntry.itemType],
|
|
375
|
+
[{}, {}, []]
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
collectionMapEntry.push(value);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
private forEachCollection (collectionMap, method) {
|
|
382
|
+
for (const parentType in collectionMap) {
|
|
383
|
+
for (const parentId in collectionMap[parentType]) {
|
|
384
|
+
for (const itemType in collectionMap[parentType][parentId]) {
|
|
385
|
+
this.collectionHandler.entries.getByParent(parentType, parentId, itemType)[method](
|
|
386
|
+
collectionMap[parentType][parentId][itemType],
|
|
387
|
+
null,
|
|
388
|
+
true
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private onItemsCreated (conversionMap, singleItems: ItemEntry[], collections: CollectionEntry[]) {
|
|
396
|
+
if (!hasProperties(conversionMap))
|
|
397
|
+
return;
|
|
398
|
+
|
|
399
|
+
for (const collectionEntry of collections) {
|
|
400
|
+
const parent = collectionEntry.parent;
|
|
401
|
+
const updatedColumns: any = collectionEntry.getUpdatedItemColumns(conversionMap);
|
|
402
|
+
|
|
403
|
+
if (parent !== null) {
|
|
404
|
+
const newParentId = this.getMapValue(parent.itemType, parent.itemId, conversionMap);
|
|
405
|
+
|
|
406
|
+
if (newParentId !== undefined)
|
|
407
|
+
parent.itemId = newParentId;
|
|
408
|
+
|
|
409
|
+
collectionEntry.query = this.collectionEntryService.createQuery(collectionEntry.options);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (!hasProperties(updatedColumns))
|
|
413
|
+
continue;
|
|
414
|
+
|
|
415
|
+
if (updatedColumns.id !== undefined)
|
|
416
|
+
collectionEntry.onItemsCreated(conversionMap[collectionEntry.itemType]);
|
|
417
|
+
|
|
418
|
+
// there might be item columns (like subproject) which should be updated
|
|
419
|
+
collectionEntry.forEach(
|
|
420
|
+
itemEntry => {
|
|
421
|
+
this.itemEntryService.updateItemFields(itemEntry, conversionMap);
|
|
422
|
+
}
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
for (const itemEntry of singleItems) {
|
|
427
|
+
const parent = itemEntry.parent;
|
|
428
|
+
|
|
429
|
+
this.itemEntryService.updateItemFields(itemEntry, conversionMap);
|
|
430
|
+
|
|
431
|
+
if (parent !== undefined) {
|
|
432
|
+
const newParentId = this.getMapValue(parent.itemType, parent.itemId, conversionMap);
|
|
433
|
+
|
|
434
|
+
if (newParentId !== undefined)
|
|
435
|
+
parent.itemId = newParentId;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// proper order: create - move - delete - update
|
|
441
|
+
private executeRequests (changes: ChangesCompiler, parameters, breakupByParent, onAfterCreateCallback) {
|
|
442
|
+
const compilation = changes.compilation;
|
|
443
|
+
const singleItems = changes.singleItems;
|
|
444
|
+
const collections = changes.collections;
|
|
445
|
+
const conversionMap = {};
|
|
446
|
+
|
|
447
|
+
return this.executeCreateRequests(compilation.create, parameters, conversionMap, breakupByParent, onAfterCreateCallback).then(
|
|
448
|
+
() => {
|
|
449
|
+
this.onItemsCreated(conversionMap, singleItems, collections);
|
|
450
|
+
|
|
451
|
+
return this.executeMoveRequests(compilation.move, conversionMap);
|
|
452
|
+
},
|
|
453
|
+
error => {
|
|
454
|
+
this.onItemsCreated(conversionMap, singleItems, collections);
|
|
455
|
+
|
|
456
|
+
return this.errorHandler.reject(error);
|
|
457
|
+
}
|
|
458
|
+
).then(
|
|
459
|
+
() => {
|
|
460
|
+
return this.executeDeleteRequests(compilation.delete);
|
|
461
|
+
},
|
|
462
|
+
this.errorHandler.reject
|
|
463
|
+
).then(
|
|
464
|
+
() => {
|
|
465
|
+
return this.prioritizeUpdateRequests(compilation.update, parameters);
|
|
466
|
+
},
|
|
467
|
+
this.errorHandler.reject
|
|
468
|
+
).then(
|
|
469
|
+
() => {
|
|
470
|
+
return conversionMap;
|
|
471
|
+
}, // item id conversion map
|
|
472
|
+
this.errorHandler.reject
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import QueryMatcherFactory from "../factories/QueryMatcherFactory";
|
|
2
|
+
import CollectionEntry from "../models/CollectionEntry";
|
|
3
|
+
|
|
4
|
+
enum CONSTANTS {
|
|
5
|
+
MAYBE = 'maybe'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default class CollectionCache {
|
|
9
|
+
entries = {};
|
|
10
|
+
|
|
11
|
+
constructor (
|
|
12
|
+
private queryMatcherFactory: QueryMatcherFactory
|
|
13
|
+
) {
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
contains (collectionEntry) {
|
|
18
|
+
for (const itemType in this.entries) {
|
|
19
|
+
for (const entry of this.entries[itemType]) {
|
|
20
|
+
if (collectionEntry === entry)
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
some (callback) {
|
|
29
|
+
for (const itemType in this.entries) {
|
|
30
|
+
for (const entry of this.entries[itemType]) {
|
|
31
|
+
if (callback(entry))
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// TODO: check if this is still in use
|
|
40
|
+
forEach (callback) {
|
|
41
|
+
for (const itemType in this.entries) {
|
|
42
|
+
for (const entry of this.entries[itemType])
|
|
43
|
+
callback(entry);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
toArray () {
|
|
48
|
+
const result = [];
|
|
49
|
+
|
|
50
|
+
for (const itemType in this.entries) {
|
|
51
|
+
for (const entry of this.entries[itemType])
|
|
52
|
+
result.push(entry);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
add (collectionEntry: CollectionEntry) {
|
|
59
|
+
const itemType = collectionEntry.itemType;
|
|
60
|
+
|
|
61
|
+
if (this.entries[itemType] === undefined)
|
|
62
|
+
this.entries[itemType] = [];
|
|
63
|
+
|
|
64
|
+
this.entries[itemType].push(collectionEntry);
|
|
65
|
+
return collectionEntry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
clear (collectionEntry?: CollectionEntry) {
|
|
69
|
+
if (collectionEntry === undefined) {
|
|
70
|
+
this.entries = {};
|
|
71
|
+
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const itemType = collectionEntry.itemType;
|
|
76
|
+
|
|
77
|
+
if (this.entries[itemType] === undefined)
|
|
78
|
+
return false;
|
|
79
|
+
|
|
80
|
+
const index = this.entries[itemType].indexOf(collectionEntry);
|
|
81
|
+
|
|
82
|
+
if (index === -1)
|
|
83
|
+
return false;
|
|
84
|
+
|
|
85
|
+
this.entries[itemType].splice(index, 1);
|
|
86
|
+
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getByItemType (itemType) {
|
|
91
|
+
if (this.entries[itemType] === undefined)
|
|
92
|
+
return [];
|
|
93
|
+
|
|
94
|
+
return this.entries[itemType].slice();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// TODO: think of better name
|
|
98
|
+
getByParent (parentType, parentId, itemType) {
|
|
99
|
+
if (this.entries[itemType] === undefined)
|
|
100
|
+
return null;
|
|
101
|
+
|
|
102
|
+
for (const collectionEntry of this.entries[itemType]) {
|
|
103
|
+
if (collectionEntry.matchParent(parentType, parentId))
|
|
104
|
+
return collectionEntry;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getResourceByParent (parentType, parentId, itemType) {
|
|
111
|
+
const collectionEntry = this.getByParent(parentType, parentId, itemType);
|
|
112
|
+
|
|
113
|
+
if (collectionEntry === null)
|
|
114
|
+
return null;
|
|
115
|
+
|
|
116
|
+
return collectionEntry.getCurrentResource();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getCollectionsByParent (parentType, parentId) {
|
|
120
|
+
const result = [];
|
|
121
|
+
|
|
122
|
+
for (const itemType in this.entries) {
|
|
123
|
+
for (const collectionEntry of this.entries[itemType]) {
|
|
124
|
+
if (collectionEntry.matchParent(parentType, parentId))
|
|
125
|
+
result.push(collectionEntry);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Only resources
|
|
134
|
+
* @param {String} itemType
|
|
135
|
+
* @param {String|Integer} itemId
|
|
136
|
+
* @returns {Object} Array of collections.
|
|
137
|
+
*/
|
|
138
|
+
getByContainingItem (itemType, itemId) {
|
|
139
|
+
const result = [];
|
|
140
|
+
|
|
141
|
+
if (this.entries[itemType] === undefined)
|
|
142
|
+
return result;
|
|
143
|
+
|
|
144
|
+
for (const collectionEntry of this.entries[itemType]) {
|
|
145
|
+
if (collectionEntry.getItemById(itemId) !== undefined)
|
|
146
|
+
result.push(collectionEntry);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Returns an array of collections the item 'belongs' in.
|
|
154
|
+
* @param {String} parentType
|
|
155
|
+
* @param {String} parentId
|
|
156
|
+
* @param {String} itemType
|
|
157
|
+
* @returns {Object}
|
|
158
|
+
*/
|
|
159
|
+
getByFittingItem (parentType, parentId, itemType, fields) {
|
|
160
|
+
const fittingResult = [];
|
|
161
|
+
const maybeResult = [];
|
|
162
|
+
const notFittingResult = [];
|
|
163
|
+
const result = {fitting: fittingResult, notfitting: notFittingResult, maybe: maybeResult};
|
|
164
|
+
|
|
165
|
+
if (this.entries[itemType] === undefined)
|
|
166
|
+
return result;
|
|
167
|
+
|
|
168
|
+
// console.time('getByFittingItem');
|
|
169
|
+
|
|
170
|
+
const queryMatcher = this.queryMatcherFactory.construct(parentType, parentId, fields, itemType);
|
|
171
|
+
|
|
172
|
+
for (const collectionEntry of this.entries[itemType]) {
|
|
173
|
+
const matchResult = queryMatcher.matchQuery(collectionEntry.query.object);
|
|
174
|
+
|
|
175
|
+
// TODO: maybe?
|
|
176
|
+
if (matchResult === true) // might also return 'maybe'
|
|
177
|
+
fittingResult.push(collectionEntry);
|
|
178
|
+
else if (matchResult === CONSTANTS.MAYBE)
|
|
179
|
+
maybeResult.push(collectionEntry);
|
|
180
|
+
else
|
|
181
|
+
notFittingResult.push(collectionEntry);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// console.timeEnd('getByFittingItem');
|
|
185
|
+
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
getByQuery (itemType, query) {
|
|
190
|
+
if (this.entries[itemType] === undefined)
|
|
191
|
+
return null;
|
|
192
|
+
|
|
193
|
+
for (const collectionEntry of this.entries[itemType]) {
|
|
194
|
+
if (collectionEntry.query.string === query.string)
|
|
195
|
+
return collectionEntry;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
getByKey (itemType, entryKey) {
|
|
202
|
+
const result = [];
|
|
203
|
+
|
|
204
|
+
if (this.entries[itemType] === undefined)
|
|
205
|
+
return result;
|
|
206
|
+
|
|
207
|
+
for (const entry of this.entries[itemType]) {
|
|
208
|
+
if (entry.options.entryKey === entryKey)
|
|
209
|
+
result.push(entry);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
getResourceByKey (itemType, resourceKey) {
|
|
216
|
+
const result = [];
|
|
217
|
+
|
|
218
|
+
if (this.entries[itemType] === undefined)
|
|
219
|
+
return result;
|
|
220
|
+
|
|
221
|
+
for (const entry of this.entries[itemType]) {
|
|
222
|
+
for (const resource of entry.resources) {
|
|
223
|
+
if (resource === null)
|
|
224
|
+
continue;
|
|
225
|
+
|
|
226
|
+
if (resource.options.resourceKey === resourceKey)
|
|
227
|
+
result.push(resource);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
}
|