@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.
Files changed (68) hide show
  1. package/.editorconfig +23 -0
  2. package/package.json +33 -0
  3. package/src/classes/ApiFormatter.ts +338 -0
  4. package/src/classes/BatchStatus.ts +86 -0
  5. package/src/classes/ChangesCompiler.ts +161 -0
  6. package/src/classes/ChangesProcessor.ts +475 -0
  7. package/src/classes/CollectionCache.ts +234 -0
  8. package/src/classes/CollectionEntryService.ts +83 -0
  9. package/src/classes/CollectionHandler.ts +619 -0
  10. package/src/classes/CollectionResourceService.ts +38 -0
  11. package/src/classes/ColumnCache.ts +114 -0
  12. package/src/classes/ColumnExpansion.ts +74 -0
  13. package/src/classes/ColumnHandler.ts +90 -0
  14. package/src/classes/ColumnSet.ts +181 -0
  15. package/src/classes/ColumnUtil.ts +589 -0
  16. package/src/classes/CreateRequest.ts +158 -0
  17. package/src/classes/ItemAdministrator.ts +571 -0
  18. package/src/classes/ItemCache.ts +158 -0
  19. package/src/classes/ItemEntryService.ts +488 -0
  20. package/src/classes/ItemHandler.ts +592 -0
  21. package/src/classes/ItemRequestService.ts +229 -0
  22. package/src/classes/ItemResourceService.ts +36 -0
  23. package/src/classes/KeyService.ts +76 -0
  24. package/src/classes/LockService.ts +184 -0
  25. package/src/classes/ModuleChangesCompiler.ts +123 -0
  26. package/src/classes/PromiseService.ts +19 -0
  27. package/src/classes/QueryMatcher.ts +135 -0
  28. package/src/classes/QueryParser.ts +209 -0
  29. package/src/classes/QueryService.ts +35 -0
  30. package/src/classes/RequestColumnExpansion.ts +31 -0
  31. package/src/classes/ResourceCache.ts +289 -0
  32. package/src/classes/Util.ts +422 -0
  33. package/src/constants.ts +11 -0
  34. package/src/factories/BatchStatusFactory.ts +18 -0
  35. package/src/factories/ChangesCompilerFactory.ts +20 -0
  36. package/src/factories/ChangesProcessorFactory.ts +53 -0
  37. package/src/factories/CollectionCacheFactory.ts +15 -0
  38. package/src/factories/CollectionEntryFactory.ts +35 -0
  39. package/src/factories/CollectionResourceFactory.ts +36 -0
  40. package/src/factories/ColumnExpansionFactory.ts +25 -0
  41. package/src/factories/ColumnSetFactory.ts +24 -0
  42. package/src/factories/CreateRequestFactory.ts +28 -0
  43. package/src/factories/ItemCacheFactory.ts +18 -0
  44. package/src/factories/ItemEntryFactory.ts +18 -0
  45. package/src/factories/ItemResourceFactory.ts +28 -0
  46. package/src/factories/ModuleChangesCompilerFactory.ts +21 -0
  47. package/src/factories/QueryMatcherFactory.ts +20 -0
  48. package/src/factories/QueryParserFactory.ts +10 -0
  49. package/src/factories/RequestColumnExpansionFactory.ts +15 -0
  50. package/src/factories/ResourceCacheFactory.ts +55 -0
  51. package/src/index.ts +188 -0
  52. package/src/interfaces/ApiRequestServiceInterface.ts +17 -0
  53. package/src/interfaces/AuthInterface.ts +5 -0
  54. package/src/interfaces/ErrorHandlerInterface.ts +3 -0
  55. package/src/interfaces/ResourceCacheInterface.ts +9 -0
  56. package/src/models/CollectionEditResource.ts +139 -0
  57. package/src/models/CollectionEntry.ts +448 -0
  58. package/src/models/CollectionResource.ts +223 -0
  59. package/src/models/CollectionViewResource.ts +23 -0
  60. package/src/models/EditResource.ts +15 -0
  61. package/src/models/ItemEntry.ts +24 -0
  62. package/src/models/ItemResource.ts +35 -0
  63. package/src/models/ViewResource.ts +14 -0
  64. package/tsconfig.json +12 -0
  65. package/tslint.json +63 -0
  66. package/webpack.common.js +35 -0
  67. package/webpack.dev.js +10 -0
  68. package/webpack.prod.js +17 -0
@@ -0,0 +1,83 @@
1
+ import QueryParserFactory from "../factories/QueryParserFactory";
2
+ import ItemEntry from "../models/ItemEntry";
3
+ import QueryService from './QueryService';
4
+ import { shallowMerge } from "./Util";
5
+
6
+ export default class CollectionEntryService {
7
+ constructor (
8
+ private queryParserFactory: QueryParserFactory,
9
+ private queryService: QueryService
10
+ ) {
11
+
12
+ }
13
+
14
+ processOptions (options) {
15
+ return shallowMerge(
16
+ options,
17
+ {
18
+ columns: [],
19
+ query: null,
20
+ queryItemType: null,
21
+ queryParams: {},
22
+ parent: null,
23
+ deferRequest: false,
24
+ limit: null,
25
+ entryKey: '',
26
+ addLocalItems: false
27
+ }
28
+ );
29
+ }
30
+
31
+ createQuery (options) {
32
+ const parent = options.parent;
33
+
34
+ let query;
35
+
36
+ if (parent === null)
37
+ query = options.query;
38
+ else {
39
+ const linkedToQuery = {linkedTo: parent.itemType, query: {id: '&parentId'}};
40
+ options.queryParams.parentId = parent.itemId;
41
+
42
+ query = options.query === null ?
43
+ linkedToQuery :
44
+ this.queryService.addAndCondition(options.query, linkedToQuery);
45
+ }
46
+
47
+ const parsedQuery = this.queryParserFactory.construct(query, options.queryParams).parse();
48
+
49
+ return {object: parsedQuery[0], string: parsedQuery[1]};
50
+ }
51
+
52
+ getIdArray (itemEntries: ItemEntry[], accumulator) {
53
+ if (accumulator === undefined)
54
+ accumulator = [];
55
+
56
+ for (const itemEntry of itemEntries)
57
+ accumulator.push(itemEntry.itemId);
58
+
59
+ return accumulator;
60
+ }
61
+
62
+ filterArray (itemEntries: ItemEntry[], callback) {
63
+ const filteredEntries = [];
64
+ const removedEntries = [];
65
+
66
+ for (const itemEntry of itemEntries) {
67
+ if (callback(itemEntry))
68
+ filteredEntries.push(itemEntry);
69
+ else
70
+ removedEntries.push(itemEntry);
71
+ }
72
+
73
+ if (removedEntries.length === 0)
74
+ return removedEntries;
75
+
76
+ itemEntries.length = filteredEntries.length;
77
+
78
+ for (let i = 0; i < itemEntries.length; i++)
79
+ itemEntries[i] = filteredEntries[i];
80
+
81
+ return removedEntries;
82
+ }
83
+ }
@@ -0,0 +1,619 @@
1
+ import { ENTRY_STATUS } from "../constants";
2
+ import CollectionCacheFactory from "../factories/CollectionCacheFactory";
3
+ import CollectionEntryFactory from "../factories/CollectionEntryFactory";
4
+ import ColumnSetFactory from "../factories/ColumnSetFactory";
5
+ import QueryParserFactory from "../factories/QueryParserFactory";
6
+ import { identity } from "../index";
7
+ import ErrorHandlerInterface from '../interfaces/ErrorHandlerInterface';
8
+ import CollectionEntry from "../models/CollectionEntry";
9
+ import CollectionResource from "../models/CollectionResource";
10
+ import ItemEntry from "../models/ItemEntry";
11
+ import ItemResource from "../models/ItemResource";
12
+ import CollectionCache from "./CollectionCache";
13
+ import CollectionEntryService from "./CollectionEntryService";
14
+ import ColumnHandler from "./ColumnHandler";
15
+ import ColumnUtil from "./ColumnUtil";
16
+ import ItemCache from "./ItemCache";
17
+ import ItemEntryService from "./ItemEntryService";
18
+ import ItemHandler from "./ItemHandler";
19
+ import ItemRequestService from "./ItemRequestService";
20
+ import KeyService from "./KeyService";
21
+ import PromiseService from "./PromiseService";
22
+ import QueryService from "./QueryService";
23
+ import { hasProperties } from "./Util";
24
+
25
+ export default class CollectionHandler {
26
+ entries: CollectionCache;
27
+
28
+ constructor (
29
+ private errorHandler: ErrorHandlerInterface,
30
+ private itemRequestService: ItemRequestService,
31
+ private itemHandler: ItemHandler,
32
+ private columnHandler: ColumnHandler,
33
+ private collectionEntryFactory: CollectionEntryFactory,
34
+ private collectionCacheFactory: CollectionCacheFactory,
35
+ private queryParserFactory: QueryParserFactory,
36
+ private collectionEntryService: CollectionEntryService,
37
+ private columnSetFactory: ColumnSetFactory,
38
+ private itemEntryService: ItemEntryService,
39
+ private keyService: KeyService,
40
+ private promiseService: PromiseService,
41
+ private queryService: QueryService,
42
+ private columnUtil: ColumnUtil
43
+ ) {
44
+ this.entries = this.collectionCacheFactory.construct();
45
+ }
46
+
47
+ getPromises (statusResource) {
48
+ const promised = statusResource[ENTRY_STATUS.PROMISED];
49
+ const promisedExpand = statusResource[ENTRY_STATUS.PROMISED_EXPAND];
50
+ const result = [];
51
+
52
+ for (const parentId in promised)
53
+ result.push(promised[parentId]);
54
+
55
+ for (const parentId in promisedExpand)
56
+ result.push(promisedExpand[parentId]);
57
+
58
+ return result;
59
+ }
60
+
61
+ getRequestIds (statusResource) {
62
+ const result = [];
63
+
64
+ for (const parentId in statusResource[ENTRY_STATUS.RESOLVE])
65
+ result.push(parentId);
66
+
67
+ for (const parentId in statusResource[ENTRY_STATUS.EXPAND])
68
+ result.push(parentId);
69
+
70
+ return result;
71
+ }
72
+
73
+ removeFromAndAddToCollections (collectionMap, updateInitial?) {
74
+ for (const collectionId in collectionMap) {
75
+ const entry = collectionMap[collectionId];
76
+ const collection: CollectionEntry = entry.collection;
77
+
78
+ collection.removeItems(entry.notfitting, null, true);
79
+ collection.addItems(entry.fitting, null, true); // doesn't do anything with initial
80
+
81
+ if (entry.maybe.length > 0)
82
+ collection.extend(identity, null, true, updateInitial);
83
+ }
84
+ }
85
+
86
+ removeFromCollections (collectionMap, updateInitial?, resultResource: CollectionResource | null = null) {
87
+ let result;
88
+
89
+ for (const collectionId in collectionMap) {
90
+ const mapEntry = collectionMap[collectionId];
91
+ const fitting = mapEntry.fitting;
92
+ const maybe = mapEntry.maybe;
93
+ const collectionEntry: CollectionEntry = mapEntry.collection;
94
+ const idArray = [];
95
+
96
+ for (const fittingItem of fitting)
97
+ idArray.push(fittingItem.itemId);
98
+
99
+ for (const maybeItem of maybe)
100
+ idArray.push(maybeItem);
101
+
102
+ if (resultResource !== null && collectionEntry === resultResource.entry)
103
+ result = collectionEntry.removeItems(idArray, resultResource, updateInitial);
104
+ else
105
+ collectionEntry.removeItems(idArray, null, updateInitial);
106
+ }
107
+
108
+ return result;
109
+ }
110
+
111
+ /**
112
+ * @deprecated
113
+ */
114
+ addItemsToCollections (itemEntries: ItemEntry[]) {
115
+ return this.addToCollections(this.createCollectionMap(itemEntries), false);
116
+ }
117
+
118
+ // TODO: maybe, boolean instead of message
119
+ addToCollections (collectionMap, updateInitial: boolean, resultResource: ItemResource | null = null) {
120
+ let result;
121
+
122
+ for (const collectionId in collectionMap) {
123
+ const mapEntry = collectionMap[collectionId];
124
+ const collectionEntry = mapEntry.collection;
125
+
126
+ if (collectionEntry.isDeferred())
127
+ continue;
128
+
129
+ if (resultResource !== null && collectionEntry === resultResource.entry)
130
+ result = collectionEntry.addItems(mapEntry.fitting, resultResource, updateInitial);
131
+ else
132
+ collectionEntry.addItems(mapEntry.fitting, null, updateInitial);
133
+
134
+ if (updateInitial && mapEntry.maybe.length > 0)
135
+ collectionEntry.extend(identity, null, true, updateInitial);
136
+ }
137
+
138
+ return result;
139
+ }
140
+
141
+ batchExpand (parentType: string, itemType: string, collections: CollectionResource[], newColumns) {
142
+ if (newColumns.length === 0)
143
+ return this.promiseService.when(collections);
144
+
145
+ const parentIdArray = [];
146
+ let itemEntries = [];
147
+
148
+ // TODO: filter local items?
149
+
150
+ for (const parentId in collections) {
151
+ parentIdArray.push(parentId);
152
+
153
+ itemEntries = itemEntries.concat(collections[parentId].entry.items);
154
+ }
155
+
156
+ return this.itemRequestService.requestLinkItems(
157
+ parentType,
158
+ parentIdArray,
159
+ itemType,
160
+ null,
161
+ newColumns
162
+ ).then(
163
+ response => {
164
+ const columnExpansion = this.itemRequestService.processExpansion(
165
+ newColumns,
166
+ response,
167
+ itemType,
168
+ itemEntries
169
+ );
170
+
171
+ for (const parentId of parentIdArray)
172
+ collections[parentId].entry.updateColumns(columnExpansion);
173
+ }
174
+ );
175
+ }
176
+
177
+ batchExtend (parentType: string, itemType: string, options, queryCallback, collections: CollectionResource[], returnAllItems = false) {
178
+ if (!hasProperties(collections))
179
+ return {};
180
+
181
+ const parentIdArray = [];
182
+ let itemIdArray = [];
183
+
184
+ options.queryParams = queryCallback(options.queryParams);
185
+
186
+ for (const parentId in collections) {
187
+ const collectionEntry = collections[parentId].entry;
188
+
189
+ collectionEntry.extendQuery(queryCallback);
190
+ parentIdArray.push(parentId);
191
+
192
+ itemIdArray = itemIdArray.concat(collectionEntry.getIdArray());
193
+ }
194
+
195
+ return this.itemRequestService.requestLinkItems(
196
+ parentType,
197
+ parentIdArray,
198
+ itemType,
199
+ this.queryService.addAndCondition(
200
+ this.collectionEntryService.createQuery(options).object,
201
+ this.queryService.createNotIn(itemIdArray)
202
+ ),
203
+ options.columns
204
+ ).then(
205
+ response => {
206
+ return this.itemRequestService.processLinkResponse(
207
+ response,
208
+ parentType,
209
+ parentIdArray,
210
+ itemType,
211
+ options
212
+ );
213
+ },
214
+ this.errorHandler.reject
215
+ ).then(
216
+ itemEntryResource => {
217
+ const result = {};
218
+
219
+ for (const parentId of parentIdArray) {
220
+ const collectionResource = collections[parentId];
221
+ const itemResources = collectionResource.entry.addItems( // should go first
222
+ itemEntryResource.items[parentId],
223
+ collectionResource
224
+ );
225
+
226
+ result[parentId] = returnAllItems ? collectionResource.items : itemResources;
227
+ }
228
+
229
+ return result;
230
+ },
231
+ this.errorHandler.reject
232
+ );
233
+ }
234
+
235
+ batchFetch (
236
+ parentType: string,
237
+ parentIdArray: number[],
238
+ itemType: string,
239
+ options,
240
+ deferredCollectionCache: CollectionCache
241
+ ) {
242
+ const resource = this.createStatusResource(parentType, parentIdArray, itemType, options, deferredCollectionCache);
243
+
244
+ return this.promiseService.all(this.getPromises(resource)).then(
245
+ () => {
246
+ const requestIds = this.getRequestIds(resource);
247
+
248
+ if (requestIds.length > 0) {
249
+ return this.itemRequestService.requestLinkItems(
250
+ parentType,
251
+ requestIds,
252
+ itemType,
253
+ options.query === null ?
254
+ null :
255
+ this.queryParserFactory.construct(options.query, options.queryParams).parse()[0],
256
+ options.columns
257
+ ).then(
258
+ response => {
259
+ return this.itemRequestService.processLinkResponse(
260
+ response,
261
+ parentType,
262
+ requestIds,
263
+ itemType,
264
+ options
265
+ );
266
+ },
267
+ this.errorHandler.reject
268
+ ).then(
269
+ itemEntryResource => {
270
+ return this.handleBatchResponse(resource, itemEntryResource);
271
+ },
272
+ this.errorHandler.reject
273
+ );
274
+ }
275
+
276
+ if (hasProperties(resource[ENTRY_STATUS.LOCAL])) {
277
+ return this.columnHandler.fetch(itemType, options.columns).then(
278
+ responseColumns => {
279
+ return this.handleBatchResponse(
280
+ resource,
281
+ {
282
+ columns: this.columnSetFactory.construct(
283
+ itemType,
284
+ options.columns,
285
+ responseColumns,
286
+ false
287
+ )
288
+ }
289
+ );
290
+ },
291
+ this.errorHandler.reject
292
+ );
293
+ }
294
+
295
+ return resource[ENTRY_STATUS.CACHED];
296
+
297
+ },
298
+ this.errorHandler.reject
299
+ );
300
+ }
301
+
302
+ clone (collectionEntry: CollectionEntry, options, conversionMap = {}) {
303
+ const itemType = collectionEntry.itemType;
304
+ const items = collectionEntry.items;
305
+ const clonedItems = [];
306
+
307
+ if (conversionMap[itemType] === undefined)
308
+ conversionMap[itemType] = {};
309
+
310
+ const conversionMapEntry = conversionMap[itemType];
311
+
312
+ // update the conversion map first (dependencies)
313
+ for (const item of items)
314
+ conversionMapEntry[item.itemId] = this.keyService.getLocalId();
315
+
316
+ for (const itemEntry of items) {
317
+ const clonedEntry = this.itemHandler.cloneItem(
318
+ conversionMapEntry[itemEntry.itemId],
319
+ itemEntry,
320
+ conversionMap
321
+ );
322
+
323
+ if (options.parent !== null)
324
+ clonedEntry.parent = options.parent;
325
+
326
+ clonedItems.push(clonedEntry);
327
+ }
328
+
329
+ return this.create(itemType, options, collectionEntry.columns, clonedItems);
330
+ }
331
+
332
+ create (itemType: string, options, columns, items: ItemEntry[]) {
333
+ return this.entries.add(
334
+ this.collectionEntryFactory.construct(
335
+ itemType,
336
+ options
337
+ )
338
+ ).resolve(
339
+ {
340
+ columns: columns,
341
+ items: items
342
+ }
343
+ );
344
+ }
345
+
346
+ createCollectionMap (itemEntries: ItemEntry[]) {
347
+ const result = {};
348
+
349
+ for (const itemEntry of itemEntries)
350
+ this.expandCollectionMap(itemEntry, result);
351
+
352
+ return result;
353
+ }
354
+
355
+ createStatusResource (
356
+ parentType: string,
357
+ parentIdArray: number[],
358
+ itemType: string, options,
359
+ deferredCollectionCache: CollectionCache
360
+ ) {
361
+ const result = {};
362
+
363
+ for (const statusId in ENTRY_STATUS)
364
+ result[ENTRY_STATUS[statusId]] = {};
365
+
366
+ for (const parentId of parentIdArray) {
367
+ const entryOptions = this.collectionEntryService.processOptions(options); // use processEntryOptions to clone
368
+
369
+ let statusResource;
370
+
371
+ entryOptions.parent = {itemType: parentType, itemId: parentId};
372
+
373
+ statusResource = this.getEntryStatus(itemType, entryOptions, deferredCollectionCache);
374
+
375
+ result[statusResource.status][parentId] = statusResource.entry;
376
+ }
377
+
378
+ return result;
379
+ }
380
+
381
+ expandCollectionMap (
382
+ itemEntry: ItemEntry,
383
+ accumulator,
384
+ collectionCache: CollectionCache = this.entries
385
+ ) {
386
+ // todo: parent type
387
+ const parent: any = itemEntry.parent !== undefined ? itemEntry.parent : {};
388
+
389
+ const collections = collectionCache.getByFittingItem(
390
+ parent.itemType,
391
+ parent.itemId,
392
+ itemEntry.itemType,
393
+ this.itemEntryService.getFields(itemEntry)
394
+ );
395
+
396
+ for (const status in collections) {
397
+ for (const collection of collections[status]) {
398
+ const collectionId = collection.id;
399
+
400
+ if (accumulator[collectionId] === undefined)
401
+ accumulator[collectionId] = {collection: collection, fitting: [], notfitting: [], maybe: []};
402
+
403
+ accumulator[collectionId][status].push(status === 'fitting' ? itemEntry : itemEntry.itemId);
404
+ }
405
+ }
406
+ }
407
+
408
+ fetch (itemType: string, options, itemCache: ItemCache, deferredCollectionCache: CollectionCache) {
409
+ const statusResource = this.getEntryStatus(itemType, options, deferredCollectionCache);
410
+ const entry = statusResource.entry;
411
+
412
+ switch (statusResource.status) {
413
+ case ENTRY_STATUS.CACHED:
414
+ return this.promiseService.when(entry);
415
+ case ENTRY_STATUS.PROMISED:
416
+ return entry.promise;
417
+ case ENTRY_STATUS.EXPAND:
418
+ return entry.expand(options.columns);
419
+ case ENTRY_STATUS.PROMISED_EXPAND:
420
+ return entry.promise.then(
421
+ () => {
422
+ return entry.expand(options.columns);
423
+ },
424
+ this.errorHandler.reject
425
+ );
426
+ case ENTRY_STATUS.RESOLVE:
427
+ return this.resolveRemote(entry, itemCache);
428
+ case ENTRY_STATUS.LOCAL:
429
+ return this.resolveLocal(entry, itemCache);
430
+ }
431
+ }
432
+
433
+ getDeferredEntryStatus (collectionEntry: CollectionEntry, options) {
434
+ // because the collection entry is not fully loaded yet, we'll have to rely on the options
435
+ const entryOptions = collectionEntry.options;
436
+ const entryColumns = entryOptions.columns;
437
+
438
+ let isColumnSubset = false;
439
+
440
+ if (collectionEntry.reloadQueued) {
441
+ collectionEntry.reloadQueued = false;
442
+ entryOptions.columns = this.columnUtil.mergeRequestColumns(options.columns, entryColumns).merged;
443
+
444
+ return {
445
+ entry: collectionEntry,
446
+ status: collectionEntry.isLocal() ? ENTRY_STATUS.LOCAL : ENTRY_STATUS.RESOLVE
447
+ };
448
+ }
449
+
450
+ if (entryColumns === true) {
451
+ console.warn('Columns: true for collections is deprecated!');
452
+ isColumnSubset = true;
453
+ } else
454
+ isColumnSubset = this.columnUtil.isColumnSubset(options.columns, entryColumns, false);
455
+
456
+ return {
457
+ entry: collectionEntry,
458
+ status: isColumnSubset ? ENTRY_STATUS.PROMISED : ENTRY_STATUS.PROMISED_EXPAND
459
+ };
460
+ }
461
+
462
+ getEntryStatus (itemType: string, options, deferredEntries: CollectionCache) {
463
+ const query = this.collectionEntryService.createQuery(options);
464
+ const cachedEntry = this.entries.getByQuery(itemType, query);
465
+
466
+ if (cachedEntry === null)
467
+ return this.getNewEntryStatus(itemType, query, options, deferredEntries);
468
+
469
+ if (cachedEntry.isDeferred())
470
+ return this.getDeferredEntryStatus(cachedEntry, options);
471
+
472
+ return {
473
+ entry: cachedEntry,
474
+ status: this.columnUtil.isColumnSubset(options.columns, cachedEntry.columns.request, cachedEntry.columns.true) ?
475
+ ENTRY_STATUS.CACHED : ENTRY_STATUS.EXPAND
476
+ };
477
+ }
478
+
479
+ getNewEntryStatus (itemType: string, query, options, deferredEntries: CollectionCache) {
480
+ let collectionEntry;
481
+ let deferredOptions;
482
+
483
+ if (options.deferRequest) {
484
+ collectionEntry = deferredEntries.getByQuery(itemType, query);
485
+
486
+ if (collectionEntry === null) {
487
+ return {
488
+ entry: deferredEntries.add(this.collectionEntryFactory.construct(itemType, options)),
489
+ status: ENTRY_STATUS.PROMISED
490
+ };
491
+ }
492
+
493
+ deferredOptions = collectionEntry.options;
494
+ deferredOptions.columns = this.columnUtil.mergeRequestColumns(deferredOptions.columns, options.columns).merged;
495
+ } else {
496
+ collectionEntry = this.collectionEntryFactory.construct(itemType, options);
497
+ }
498
+
499
+ this.entries.add(collectionEntry); // will also add the deferred entry
500
+
501
+ return {
502
+ entry: collectionEntry,
503
+ status: collectionEntry.isLocal() ? ENTRY_STATUS.LOCAL : ENTRY_STATUS.RESOLVE
504
+ };
505
+ }
506
+
507
+ handleBatchResponse (statusResource, itemEntryResource) {
508
+ const result = {};
509
+
510
+ for (const parentId in statusResource.cached)
511
+ result[parentId] = statusResource.cached[parentId];
512
+
513
+ for (const parentId in statusResource.resolve) {
514
+ result[parentId] = statusResource.resolve[parentId].resolve(
515
+ {
516
+ items: itemEntryResource.items[parentId],
517
+ columns: itemEntryResource.columns
518
+ }
519
+ );
520
+ }
521
+
522
+ for (const parentId in statusResource.expand) {
523
+ const collectionEntry: CollectionEntry = statusResource.expand[parentId];
524
+
525
+ collectionEntry.updateColumns(itemEntryResource.columnExpansion);
526
+
527
+ result[parentId] = collectionEntry;
528
+ }
529
+
530
+ for (const parentId in statusResource.local) {
531
+ const collectionEntry: CollectionEntry = statusResource.local[parentId];
532
+
533
+ result[parentId] = collectionEntry.resolve(
534
+ {
535
+ items: this.itemHandler.entries.getByParent( // TODO: use tab cache?
536
+ collectionEntry.parent.itemType,
537
+ parentId,
538
+ collectionEntry.itemType
539
+ ),
540
+ columns: itemEntryResource.columns
541
+ }
542
+ );
543
+ }
544
+
545
+ return result;
546
+ }
547
+
548
+ /**
549
+ * @deprecated
550
+ */
551
+ removeItemsFromAndAddItemsToCollections (itemEntries: ItemEntry[]) {
552
+ return this.removeFromAndAddToCollections(
553
+ this.createCollectionMap(itemEntries),
554
+ false
555
+ );
556
+ }
557
+
558
+ /**
559
+ * @deprecated
560
+ */
561
+ // TODO: maybe
562
+ removeItemsFromCollections (itemEntries: ItemEntry[]) {
563
+ return this.removeFromCollections(
564
+ this.createCollectionMap(itemEntries),
565
+ false
566
+ );
567
+ }
568
+
569
+ resolveLocal (collectionEntry: CollectionEntry, itemCache) {
570
+ const itemType = collectionEntry.itemType;
571
+ const requestColumns = collectionEntry.options.columns;
572
+
573
+ return this.columnHandler.fetch(itemType, requestColumns).then(
574
+ responseColumns => {
575
+ return collectionEntry.resolve(
576
+ {
577
+ items: itemCache.getByQuery(itemType, collectionEntry.query),
578
+ columns: this.columnSetFactory.construct(itemType, requestColumns, responseColumns, false)
579
+ }
580
+ );
581
+ },
582
+ this.errorHandler.reject
583
+ );
584
+ }
585
+
586
+ resolveRemote (collectionEntry, itemCache) {
587
+ const itemType = collectionEntry.itemType;
588
+ const options = collectionEntry.options;
589
+
590
+ let columnInfo;
591
+
592
+ return this.itemRequestService.requestItems(collectionEntry).then(
593
+ response => {
594
+ columnInfo = this.columnSetFactory.construct(itemType, options.columns, response.fetchColumnsObject());
595
+
596
+ return this.itemRequestService.processResponse(
597
+ response,
598
+ response.links[itemType],
599
+ collectionEntry.parent,
600
+ columnInfo
601
+ );
602
+ },
603
+ this.errorHandler.reject
604
+ ).then(itemEntries => {
605
+ return collectionEntry.resolve(
606
+ {
607
+ items: itemEntries.concat(
608
+ options.addLocalItems ?
609
+ itemCache.getLocalByQuery(itemType, collectionEntry.query) :
610
+ []
611
+ ),
612
+ columns: columnInfo
613
+ }
614
+ );
615
+ },
616
+ this.errorHandler.reject
617
+ );
618
+ }
619
+ }