@limble/limble-tree 0.12.4 → 0.13.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 (45) hide show
  1. package/README.md +149 -149
  2. package/{esm2015/lib/classes/Branch.js → esm2020/lib/classes/Branch.mjs} +1 -1
  3. package/{esm2015/lib/classes/DropZone.js → esm2020/lib/classes/DropZone.mjs} +1 -1
  4. package/{esm2015/lib/classes/DropZoneLocation.js → esm2020/lib/classes/DropZoneLocation.mjs} +1 -1
  5. package/{esm2015/lib/custom-event-bindings/dragleave-no-change-detect.directive.js → esm2020/lib/custom-event-bindings/dragleave-no-change-detect.directive.mjs} +0 -0
  6. package/{esm2015/lib/custom-event-bindings/dragover-no-change-detect.directive.js → esm2020/lib/custom-event-bindings/dragover-no-change-detect.directive.mjs} +1 -1
  7. package/esm2020/lib/drop-zone/drop-zone.component.mjs +75 -0
  8. package/esm2020/lib/limble-tree-branch/limble-tree-branch.component.mjs +110 -0
  9. package/esm2020/lib/limble-tree-node/limble-tree-node.component.mjs +467 -0
  10. package/{esm2015/lib/limble-tree-placeholder/limble-tree-placeholder.component.js → esm2020/lib/limble-tree-placeholder/limble-tree-placeholder.component.mjs} +3 -8
  11. package/esm2020/lib/limble-tree-root/drop-zone.service.mjs +376 -0
  12. package/esm2020/lib/limble-tree-root/limble-tree-root.component.mjs +172 -0
  13. package/{esm2015/lib/limble-tree-root/tree-construction-status.service.js → esm2020/lib/limble-tree-root/tree-construction-status.service.mjs} +1 -1
  14. package/esm2020/lib/limble-tree-root/tree.service.mjs +297 -0
  15. package/{esm2015/lib/limble-tree.module.js → esm2020/lib/limble-tree.module.mjs} +5 -5
  16. package/{esm2015/lib/singletons/component-creator.service.js → esm2020/lib/singletons/component-creator.service.mjs} +1 -1
  17. package/esm2020/lib/singletons/drag-state.service.mjs +63 -0
  18. package/esm2020/lib/singletons/global-events.service.mjs +136 -0
  19. package/{esm2015/lib/util.js → esm2020/lib/util.mjs} +1 -1
  20. package/{esm2015/limble-limble-tree.js → esm2020/limble-limble-tree.mjs} +0 -0
  21. package/{esm2015/public-api.js → esm2020/public-api.mjs} +1 -1
  22. package/fesm2015/limble-limble-tree.mjs +2256 -0
  23. package/fesm2015/limble-limble-tree.mjs.map +1 -0
  24. package/{fesm2015/limble-limble-tree.js → fesm2020/limble-limble-tree.mjs} +89 -136
  25. package/fesm2020/limble-limble-tree.mjs.map +1 -0
  26. package/{limble-limble-tree.d.ts → index.d.ts} +0 -0
  27. package/lib/custom-event-bindings/dragleave-no-change-detect.directive.d.ts +1 -1
  28. package/lib/custom-event-bindings/dragover-no-change-detect.directive.d.ts +1 -1
  29. package/lib/drop-zone/drop-zone.component.d.ts +1 -1
  30. package/lib/limble-tree-branch/limble-tree-branch.component.d.ts +1 -1
  31. package/lib/limble-tree-node/limble-tree-node.component.d.ts +1 -1
  32. package/lib/limble-tree-placeholder/limble-tree-placeholder.component.d.ts +1 -1
  33. package/lib/limble-tree-root/limble-tree-root.component.d.ts +1 -1
  34. package/package.json +22 -9
  35. package/bundles/limble-limble-tree.umd.js +0 -2910
  36. package/bundles/limble-limble-tree.umd.js.map +0 -1
  37. package/esm2015/lib/drop-zone/drop-zone.component.js +0 -81
  38. package/esm2015/lib/limble-tree-branch/limble-tree-branch.component.js +0 -116
  39. package/esm2015/lib/limble-tree-node/limble-tree-node.component.js +0 -484
  40. package/esm2015/lib/limble-tree-root/drop-zone.service.js +0 -377
  41. package/esm2015/lib/limble-tree-root/limble-tree-root.component.js +0 -178
  42. package/esm2015/lib/limble-tree-root/tree.service.js +0 -301
  43. package/esm2015/lib/singletons/drag-state.service.js +0 -64
  44. package/esm2015/lib/singletons/global-events.service.js +0 -137
  45. package/fesm2015/limble-limble-tree.js.map +0 -1
@@ -1,377 +0,0 @@
1
- import { Injectable } from "@angular/core";
2
- import { arraysAreEqual, isNestingAllowed } from "../util";
3
- import { DropZone } from "../classes/DropZone";
4
- import { DropZoneLocation } from "../classes/DropZoneLocation";
5
- import { Subject } from "rxjs";
6
- import { debounce, filter, tap } from "rxjs/operators";
7
- import * as i0 from "@angular/core";
8
- import * as i1 from "../singletons/drag-state.service";
9
- import * as i2 from "./tree-construction-status.service";
10
- function sortFamily(memberA, memberB) {
11
- const aCoordinates = memberA.getFullInsertCoordinates();
12
- const bCoordinates = memberB.getFullInsertCoordinates();
13
- if (aCoordinates.length > bCoordinates.length) {
14
- return -1;
15
- }
16
- if (aCoordinates.length < bCoordinates.length) {
17
- return 1;
18
- }
19
- return 0;
20
- }
21
- export class DropZoneService {
22
- constructor(dragStateService, treeConstructionStatus) {
23
- this.dragStateService = dragStateService;
24
- this.dropZoneArchive = new Set();
25
- this.dropZoneInventory = [];
26
- this.dropZoneFamilies = [];
27
- this.visibleFamily = null;
28
- this.activeDropZone = null;
29
- this.tempFamilies = [];
30
- this.setActiveDropZone(null);
31
- let treeIsStable = false;
32
- const treeIsStable$ = treeConstructionStatus.stable$.pipe(tap((value) => {
33
- treeIsStable = value;
34
- }), filter((value) => value === true));
35
- this.update$ = new Subject();
36
- this.update$
37
- .pipe(debounce(() => {
38
- if (treeIsStable === true) {
39
- //If tree is stable, continue right away
40
- return Promise.resolve();
41
- }
42
- //If tree is not stable, wait for it to become so.
43
- return treeIsStable$;
44
- }))
45
- .subscribe(() => {
46
- setTimeout(() => {
47
- this.updateDropZones();
48
- });
49
- });
50
- }
51
- addDropZone(newDropZone) {
52
- this.dropZoneArchive.add(newDropZone);
53
- }
54
- /** hides all drop zones */
55
- clearVisibleZones() {
56
- if (this.visibleFamily !== null) {
57
- for (const member of this.visibleFamily.members) {
58
- member.isVisible(false);
59
- }
60
- this.visibleFamily = null;
61
- }
62
- this.setActiveDropZone(null);
63
- }
64
- getActiveDropZone() {
65
- return this.activeDropZone;
66
- }
67
- getDropZone(coordinates) {
68
- const parent = [...coordinates];
69
- parent.pop();
70
- const index = coordinates[coordinates.length - 1];
71
- const location = new DropZoneLocation(parent, index);
72
- return this.dropZoneInventory.find((dropZone) => DropZone.dropZoneLocationsAreEqual(dropZone, location));
73
- }
74
- init(tree, treeOptions) {
75
- this.tree = tree;
76
- this.treeOptions = treeOptions;
77
- this.update();
78
- }
79
- removeDropZone(dropZone) {
80
- this.dropZoneArchive.delete(dropZone);
81
- }
82
- /** hides all drop zones, deletes all the family assignments,
83
- * and empties the dropZoneInventory
84
- */
85
- reset() {
86
- this.clearVisibleZones();
87
- this.dropZoneFamilies.length = 0;
88
- this.dropZoneInventory.length = 0;
89
- }
90
- /**
91
- * Restores the service to its initial state: hides all drop zones,
92
- * deletes all the family assignments, and empties the dropZoneInventory
93
- * and dropZoneArchive.
94
- */
95
- restart() {
96
- this.reset();
97
- this.dropZoneArchive.clear();
98
- }
99
- restoreFamilies() {
100
- if (this.tempFamilies.length === 2) {
101
- this.dropZoneFamilies.pop();
102
- this.dropZoneFamilies.push(this.tempFamilies[0]);
103
- for (const member of this.tempFamilies[0].members) {
104
- member.setFamily(this.tempFamilies[0]);
105
- }
106
- if (this.tempFamilies[1] !== null) {
107
- this.dropZoneFamilies.push(this.tempFamilies[1]);
108
- for (const member of this.tempFamilies[1].members) {
109
- member.setFamily(this.tempFamilies[1]);
110
- }
111
- }
112
- this.tempFamilies = [];
113
- }
114
- }
115
- /**
116
- * Shows the drop zone family of the drop zone indicated by `coordinates`.
117
- */
118
- showDropZoneFamily(
119
- /** Note: this drop zone may not exist in the dropZoneInventory; we have to search the inventory based on its location */
120
- dropZone, options = { joinFamilies: false, activateLowestInsteadOfFounder: false }) {
121
- if (this.activeDropZone !== null &&
122
- DropZone.dropZoneLocationsAreEqual(this.activeDropZone, dropZone)) {
123
- //Already showing the family with the appropriate active drop zone
124
- return;
125
- }
126
- if (this.visibleFamily !== null || this.activeDropZone !== null) {
127
- this.clearVisibleZones();
128
- }
129
- const target = this.dropZoneInventory.find((zone) => DropZone.dropZoneLocationsAreEqual(zone, dropZone));
130
- if (target === undefined) {
131
- throw new Error(`Could not find drop zone to show. location: ${JSON.stringify(dropZone.getLocation())}`);
132
- }
133
- const family = target.getFamily();
134
- if (options.joinFamilies === true) {
135
- const location1 = dropZone.getLocation();
136
- const location2 = new DropZoneLocation([...location1.parentCoordinates], location1.insertIndex + 1);
137
- const target2 = this.dropZoneInventory.find((zone) => DropZone.dropZoneLocationsAreEqual(zone, location2));
138
- if (target2 === undefined) {
139
- throw new Error("Could not find drop zone to show");
140
- }
141
- const family2 = target2.getFamily();
142
- if (family === undefined || family2 === undefined) {
143
- throw new Error("No family");
144
- }
145
- const newFamily = {
146
- founder: family.founder,
147
- members: [...family.members]
148
- };
149
- this.showDropZone(family.founder, true);
150
- for (const member of family.members.sort(sortFamily)) {
151
- member.setFamily(newFamily);
152
- if (member !== family.founder) {
153
- if (this.activeDropZone === null) {
154
- //Failed to activate a zone so far, so activate this one instead
155
- this.showDropZone(member, true);
156
- }
157
- else {
158
- this.showDropZone(member);
159
- }
160
- }
161
- }
162
- for (const member of family2.members) {
163
- member.setFamily(newFamily);
164
- if (member.getLocation().parentCoordinates.length <
165
- target2.getLocation().parentCoordinates.length) {
166
- newFamily.members.push(member);
167
- this.showDropZone(member);
168
- }
169
- }
170
- //Temporarily store the old families
171
- this.tempFamilies = [family, family2];
172
- //Remove the old families
173
- const familyIndex = this.dropZoneFamilies.indexOf(family);
174
- this.dropZoneFamilies.splice(familyIndex, 1);
175
- const family2Index = this.dropZoneFamilies.indexOf(family2);
176
- this.dropZoneFamilies.splice(family2Index, 1);
177
- //Add the new family
178
- this.dropZoneFamilies.push(newFamily);
179
- this.visibleFamily = newFamily;
180
- }
181
- else {
182
- if (family === undefined) {
183
- throw new Error("No family");
184
- }
185
- this.visibleFamily = family;
186
- this.showDropZone(family.founder, true);
187
- if (family.members.length > 1) {
188
- for (const member of family.members.sort(sortFamily)) {
189
- if (member !== family.founder) {
190
- if (this.activeDropZone === null) {
191
- //Failed to activate a zone so far, so activate this one instead
192
- this.showDropZone(member, true);
193
- }
194
- else {
195
- this.showDropZone(member);
196
- }
197
- }
198
- }
199
- }
200
- }
201
- if (options.activateLowestInsteadOfFounder === true &&
202
- this.visibleFamily.members.length > 1) {
203
- const lowestMember = [...this.visibleFamily.members]
204
- .sort(sortFamily)
205
- .pop();
206
- if (lowestMember === undefined) {
207
- throw new Error("Could not get lowest member");
208
- }
209
- this.swapActiveDropZone(lowestMember);
210
- }
211
- }
212
- swapActiveDropZone(newActiveDropZone) {
213
- if (this.visibleFamily === null) {
214
- throw new Error("No visible family available for swapping");
215
- }
216
- const index = this.visibleFamily.members.findIndex((dropZone) => dropZone === newActiveDropZone);
217
- if (index === -1) {
218
- throw new Error("failed to swap active drop zone");
219
- }
220
- this.setActiveDropZone(newActiveDropZone);
221
- }
222
- update() {
223
- this.update$.next(null);
224
- }
225
- assignFamilies() {
226
- const orphanZones = [...this.dropZoneInventory];
227
- const deepestMembers = orphanZones
228
- .filter((zone) => {
229
- const location = zone.getLocation();
230
- return (location.insertIndex === 0 &&
231
- location.parentCoordinates.length > 0);
232
- })
233
- .sort((valueA, valueB) => {
234
- var _a, _b, _c, _d;
235
- const aCoordinates = valueA.getFullInsertCoordinates();
236
- const bCoordinates = valueB.getFullInsertCoordinates();
237
- const length = Math.max(aCoordinates.length, bCoordinates.length);
238
- for (let index = 0; index < length; index++) {
239
- if (((_a = aCoordinates[index]) !== null && _a !== void 0 ? _a : -1) > ((_b = bCoordinates[index]) !== null && _b !== void 0 ? _b : -1)) {
240
- return -1;
241
- }
242
- else if (((_c = aCoordinates[index]) !== null && _c !== void 0 ? _c : -1) < ((_d = bCoordinates[index]) !== null && _d !== void 0 ? _d : -1)) {
243
- return 1;
244
- }
245
- }
246
- return 0;
247
- });
248
- for (const dropZone of deepestMembers) {
249
- if (!orphanZones.includes(dropZone)) {
250
- continue;
251
- }
252
- const family = {
253
- founder: dropZone,
254
- members: []
255
- };
256
- dropZone.setFamily(family);
257
- //See if there are any orphans that belong to this family and claim them.
258
- const cursor = [...dropZone.getFullInsertCoordinates()];
259
- while (cursor.length > 0) {
260
- const familyMemberIndex = orphanZones.findIndex((zone) => arraysAreEqual(zone.getFullInsertCoordinates(), cursor));
261
- if (familyMemberIndex !== -1) {
262
- const familyMember = orphanZones.splice(familyMemberIndex, 1)[0];
263
- family.members.push(familyMember);
264
- familyMember.setFamily(family);
265
- }
266
- cursor.pop();
267
- cursor[cursor.length - 1]++;
268
- }
269
- this.dropZoneFamilies.push(family);
270
- }
271
- for (const dropZone of orphanZones.filter((zone) => zone.getFullInsertCoordinates().length === 1)) {
272
- const family = {
273
- founder: dropZone,
274
- members: [dropZone]
275
- };
276
- dropZone.setFamily(family);
277
- this.dropZoneFamilies.push(family);
278
- orphanZones.splice(orphanZones.indexOf(dropZone), 1);
279
- }
280
- if (orphanZones.length !== 0) {
281
- let orphans = "";
282
- for (const zone of orphanZones) {
283
- orphans += `${JSON.stringify(zone.getLocation())}, `;
284
- }
285
- orphans = orphans.slice(0, orphans.length - 2);
286
- throw new Error(`Some zones were not assigned to a family. The orphan zones have the following locations: ${orphans}`);
287
- }
288
- }
289
- buildInventory() {
290
- //We do this funky string array because it is faster than doing direct array comparisons
291
- const inventoryCoordinates = [];
292
- for (const dropZone of this.dropZoneArchive) {
293
- const coordinates = dropZone.getFullInsertCoordinates().join(",");
294
- if (inventoryCoordinates.includes(coordinates)) {
295
- dropZone.isRendered(false);
296
- }
297
- else {
298
- this.dropZoneInventory.push(dropZone);
299
- inventoryCoordinates.push(coordinates);
300
- dropZone.isRendered(true);
301
- }
302
- }
303
- }
304
- setActiveDropZone(dropZone) {
305
- if (this.activeDropZone !== null) {
306
- this.activeDropZone.isActive(false);
307
- }
308
- this.activeDropZone = dropZone;
309
- if (this.activeDropZone !== null &&
310
- this.dragStateService.getState() !== "droppable") {
311
- this.dragStateService.droppable();
312
- }
313
- else if (this.activeDropZone === null &&
314
- this.dragStateService.getState() === "droppable") {
315
- this.dragStateService.notDroppable();
316
- }
317
- if (this.activeDropZone !== null) {
318
- this.activeDropZone.isActive(true);
319
- }
320
- }
321
- showDropZone(dropZone, active = false) {
322
- if (this.tree === undefined) {
323
- throw new Error("DropZoneService not initialized");
324
- }
325
- if (!this.zoneIsAllowed(dropZone)) {
326
- //User settings indicate to skip this drop zone
327
- return false;
328
- }
329
- const parent = this.tree.findByCoordinates(dropZone.getLocation().parentCoordinates);
330
- if (parent === undefined) {
331
- throw new Error("Bad family member");
332
- }
333
- dropZone.isVisible(true);
334
- if (active === true) {
335
- this.setActiveDropZone(dropZone);
336
- }
337
- return true;
338
- }
339
- updateDropZones() {
340
- this.reset();
341
- this.buildInventory();
342
- this.assignFamilies();
343
- }
344
- zoneIsAllowed(dropZone) {
345
- if (this.treeOptions === undefined || this.tree === undefined) {
346
- throw new Error("dropZoneService not initialized");
347
- }
348
- const data = this.dragStateService.getData();
349
- if (data === undefined) {
350
- throw new Error("Can't get dragged node");
351
- }
352
- const parentCoordinates = dropZone.getLocation().parentCoordinates;
353
- const dropZoneParent = this.tree.findByCoordinates(parentCoordinates);
354
- if (dropZoneParent === undefined) {
355
- throw new Error("Could not get drop zone parent");
356
- }
357
- if (parentCoordinates.length > 0 &&
358
- !isNestingAllowed(this.treeOptions, dropZoneParent.data)) {
359
- return false;
360
- }
361
- const dropZoneIndex = dropZone.getLocation().insertIndex;
362
- if (dropZoneIndex === undefined) {
363
- throw new Error("Could not get drop zone index");
364
- }
365
- const draggedNode = data.branch;
366
- if (!this.treeOptions.allowDrop(draggedNode.data, dropZoneParent.data, dropZoneIndex)) {
367
- return false;
368
- }
369
- return true;
370
- }
371
- }
372
- DropZoneService.ɵfac = function DropZoneService_Factory(t) { return new (t || DropZoneService)(i0.ɵɵinject(i1.DragStateService), i0.ɵɵinject(i2.TreeConstructionStatus)); };
373
- DropZoneService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DropZoneService, factory: DropZoneService.ɵfac });
374
- (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropZoneService, [{
375
- type: Injectable
376
- }], function () { return [{ type: i1.DragStateService }, { type: i2.TreeConstructionStatus }]; }, null); })();
377
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcC16b25lLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saW1ibGUtdHJlZS9zcmMvbGliL2xpbWJsZS10cmVlLXJvb3QvZHJvcC16b25lLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzNELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRS9CLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7O0FBU3ZELFNBQVMsVUFBVSxDQUFDLE9BQWlCLEVBQUUsT0FBaUI7SUFDckQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDeEQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDeEQsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUU7UUFDNUMsT0FBTyxDQUFDLENBQUMsQ0FBQztLQUNaO0lBQ0QsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUU7UUFDNUMsT0FBTyxDQUFDLENBQUM7S0FDWDtJQUNELE9BQU8sQ0FBQyxDQUFDO0FBQ1osQ0FBQztBQUdELE1BQU0sT0FBTyxlQUFlO0lBYXpCLFlBQ29CLGdCQUFrQyxFQUNuRCxzQkFBOEM7UUFEN0IscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUduRCxJQUFJLENBQUMsZUFBZSxHQUFHLElB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b3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IEJyYW5jaCwgQnJhbmNoQ29vcmRpbmF0ZXMgfSBmcm9tIFwiLi4vY2xhc3Nlcy9CcmFuY2hcIjtcclxuaW1wb3J0IHsgRHJhZ1N0YXRlU2VydmljZSB9IGZyb20gXCIuLi9zaW5nbGV0b25zL2RyYWctc3RhdGUuc2VydmljZVwiO1xyXG5pbXBvcnQgdHlwZSB7IExpbWJsZVRyZWVOb2RlLCBQcm9jZXNzZWRPcHRpb25zIH0gZnJvbSBcIi4vdHJlZS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IGFycmF5c0FyZUVxdWFsLCBpc05lc3RpbmdBbGxvd2VkIH0gZnJvbSBcIi4uL3V0aWxcIjtcclxuaW1wb3J0IHsgRHJvcFpvbmUgfSBmcm9tIFwiLi4vY2xhc3Nlcy9Ecm9wWm9uZVwiO1xyXG5pbXBvcnQgeyBEcm9wWm9uZUxvY2F0aW9uIH0gZnJvbSBcIi4uL2NsYXNzZXMvRHJvcFpvbmVMb2NhdGlvblwiO1xyXG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcclxuaW1wb3J0IHsgVHJlZUNvbnN0cnVjdGlvblN0YXR1cyB9IGZyb20gXCIuL3RyZWUtY29uc3RydWN0aW9uLXN0YXR1cy5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IGRlYm91bmNlLCBmaWx0ZXIsIHRhcCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBEcm9wWm9uZUZhbWlseSB7XHJcbiAgIC8qKiBUaGUgZGVlcGVzdCBtZW1iZXIgb2YgdGhlIGZhbWlseSAqL1xyXG4gICBmb3VuZGVyOiBEcm9wWm9uZTtcclxuICAgLyoqIEFsbCB0aGUgZHJvcCB6b25lcyB0aGF0IGJlbG9uZyB0byB0aGlzIGZhbWlseSAqL1xyXG4gICBtZW1iZXJzOiBBcnJheTxEcm9wWm9uZT47XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNvcnRGYW1pbHkobWVtYmVyQTogRHJvcFpvbmUsIG1lbWJlckI6IERyb3Bab25lKSB7XHJcbiAgIGNvbnN0IGFDb29yZGluYXRlcyA9IG1lbWJlckEuZ2V0RnVsbEluc2VydENvb3JkaW5hdGVzKCk7XHJcbiAgIGNvbnN0IGJDb29yZGluYXRlcyA9IG1lbWJlckIuZ2V0RnVsbEluc2VydENvb3JkaW5hdGVzKCk7XHJcbiAgIGlmIChhQ29vcmRpbmF0ZXMubGVuZ3RoID4gYkNvb3JkaW5hdGVzLmxlbmd0aCkge1xyXG4gICAgICByZXR1cm4gLTE7XHJcbiAgIH1cclxuICAgaWYgKGFDb29yZGluYXRlcy5sZW5ndGggPCBiQ29vcmRpbmF0ZXMubGVuZ3RoKSB7XHJcbiAgICAgIHJldHVybiAxO1xyXG4gICB9XHJcbiAgIHJldHVybiAwO1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBEcm9wWm9uZVNlcnZpY2Uge1xyXG4gICBwcml2YXRlIHJlYWRvbmx5IGRyb3Bab25lQXJjaGl2ZTogU2V0PERyb3Bab25lPjtcclxuICAgcHJpdmF0ZSByZWFkb25seSBkcm9wWm9uZUludmVudG9yeTogQXJyYXk8RHJvcFpvbmU+O1xyXG4gICBwcml2YXRlIHJlYWRvbmx5IGRyb3Bab25lRmFtaWxpZXM6IEFycmF5PERyb3Bab25lRmFtaWx5PjtcclxuICAgcHJpdmF0ZSB2aXNpYmxlRmFtaWx5OiBEcm9wWm9uZUZhbWlseSB8IG51bGw7XHJcbiAgIHByaXZhdGUgYWN0aXZlRHJvcFpvbmU6IERyb3Bab25lIHwgbnVsbDtcclxuICAgcHJpdmF0ZSB0cmVlOiBCcmFuY2g8YW55PiB8IHVuZGVmaW5lZDtcclxuICAgcHJpdmF0ZSB0cmVlT3B0aW9uczogUHJvY2Vzc2VkT3B0aW9ucyB8IHVuZGVmaW5lZDtcclxuICAgcHJpdmF0ZSB0ZW1wRmFtaWxpZXM6XHJcbiAgICAgIHwgcmVhZG9ubHkgW0Ryb3Bab25lRmFtaWx5LCBEcm9wWm9uZUZhbWlseSB8IG51bGxdXHJcbiAgICAgIHwgcmVhZG9ubHkgW107XHJcbiAgIHByaXZhdGUgcmVhZG9ubHkgdXBkYXRlJDogU3ViamVjdDxudWxsPjtcclxuXHJcbiAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IGRyYWdTdGF0ZVNlcnZpY2U6IERyYWdTdGF0ZVNlcnZpY2UsXHJcbiAgICAgIHRyZWVDb25zdHJ1Y3Rpb25TdGF0dXM6IFRyZWVDb25zdHJ1Y3Rpb25TdGF0dXNcclxuICAgKSB7XHJcbiAgICAgIHRoaXMuZHJvcFpvbmVBcmNoaXZlID0gbmV3IFNldCgpO1xyXG4gICAgICB0aGlzLmRyb3Bab25lSW52ZW50b3J5ID0gW107XHJcbiAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcyA9IFtdO1xyXG4gICAgICB0aGlzLnZpc2libGVGYW1pbHkgPSBudWxsO1xyXG4gICAgICB0aGlzLmFjdGl2ZURyb3Bab25lID0gbnVsbDtcclxuICAgICAgdGhpcy50ZW1wRmFtaWxpZXMgPSBbXTtcclxuICAgICAgdGhpcy5zZXRBY3RpdmVEcm9wWm9uZShudWxsKTtcclxuICAgICAgbGV0IHRyZWVJc1N0YWJsZSA9IGZhbHNlO1xyXG4gICAgICBjb25zdCB0cmVlSXNTdGFibGUkID0gdHJlZUNvbnN0cnVjdGlvblN0YXR1cy5zdGFibGUkLnBpcGUoXHJcbiAgICAgICAgIHRhcCgodmFsdWUpID0+IHtcclxuICAgICAgICAgICAgdHJlZUlzU3RhYmxlID0gdmFsdWU7XHJcbiAgICAgICAgIH0pLFxyXG4gICAgICAgICBmaWx0ZXIoKHZhbHVlKSA9PiB2YWx1ZSA9PT0gdHJ1ZSlcclxuICAgICAgKTtcclxuICAgICAgdGhpcy51cGRhdGUkID0gbmV3IFN1YmplY3QoKTtcclxuICAgICAgdGhpcy51cGRhdGUkXHJcbiAgICAgICAgIC5waXBlKFxyXG4gICAgICAgICAgICBkZWJvdW5jZSgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgIGlmICh0cmVlSXNTdGFibGUgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgICAgLy9JZiB0cmVlIGlzIHN0YWJsZSwgY29udGludWUgcmlnaHQgYXdheVxyXG4gICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgLy9JZiB0cmVlIGlzIG5vdCBzdGFibGUsIHdhaXQgZm9yIGl0IHRvIGJlY29tZSBzby5cclxuICAgICAgICAgICAgICAgcmV0dXJuIHRyZWVJc1N0YWJsZSQ7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgIClcclxuICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICB0aGlzLnVwZGF0ZURyb3Bab25lcygpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgfSk7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyBhZGREcm9wWm9uZShuZXdEcm9wWm9uZTogRHJvcFpvbmUpOiB2b2lkIHtcclxuICAgICAgdGhpcy5kcm9wWm9uZUFyY2hpdmUuYWRkKG5ld0Ryb3Bab25lKTtcclxuICAgfVxyXG5cclxuICAgLyoqIGhpZGVzIGFsbCBkcm9wIHpvbmVzICovXHJcbiAgIHB1YmxpYyBjbGVhclZpc2libGVab25lcygpOiB2b2lkIHtcclxuICAgICAgaWYgKHRoaXMudmlzaWJsZUZhbWlseSAhPT0gbnVsbCkge1xyXG4gICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiB0aGlzLnZpc2libGVGYW1pbHkubWVtYmVycykge1xyXG4gICAgICAgICAgICBtZW1iZXIuaXNWaXNpYmxlKGZhbHNlKTtcclxuICAgICAgICAgfVxyXG4gICAgICAgICB0aGlzLnZpc2libGVGYW1pbHkgPSBudWxsO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuc2V0QWN0aXZlRHJvcFpvbmUobnVsbCk7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyBnZXRBY3RpdmVEcm9wWm9uZSgpOiBEcm9wWm9uZVNlcnZpY2VbXCJhY3RpdmVEcm9wWm9uZVwiXSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmFjdGl2ZURyb3Bab25lO1xyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgZ2V0RHJvcFpvbmUoY29vcmRpbmF0ZXM6IEJyYW5jaENvb3JkaW5hdGVzKTogRHJvcFpvbmUgfCB1bmRlZmluZWQge1xyXG4gICAgICBjb25zdCBwYXJlbnQgPSBbLi4uY29vcmRpbmF0ZXNdO1xyXG4gICAgICBwYXJlbnQucG9wKCk7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gY29vcmRpbmF0ZXNbY29vcmRpbmF0ZXMubGVuZ3RoIC0gMV07XHJcbiAgICAgIGNvbnN0IGxvY2F0aW9uID0gbmV3IERyb3Bab25lTG9jYXRpb24ocGFyZW50LCBpbmRleCk7XHJcbiAgICAgIHJldHVybiB0aGlzLmRyb3Bab25lSW52ZW50b3J5LmZpbmQoKGRyb3Bab25lKSA9PlxyXG4gICAgICAgICBEcm9wWm9uZS5kcm9wWm9uZUxvY2F0aW9uc0FyZUVxdWFsKGRyb3Bab25lLCBsb2NhdGlvbilcclxuICAgICAgKTtcclxuICAgfVxyXG5cclxuICAgcHVibGljIGluaXQodHJlZTogQnJhbmNoPGFueT4sIHRyZWVPcHRpb25zOiBQcm9jZXNzZWRPcHRpb25zKTogdm9pZCB7XHJcbiAgICAgIHRoaXMudHJlZSA9IHRyZWU7XHJcbiAgICAgIHRoaXMudHJlZU9wdGlvbnMgPSB0cmVlT3B0aW9ucztcclxuICAgICAgdGhpcy51cGRhdGUoKTtcclxuICAgfVxyXG5cclxuICAgcHVibGljIHJlbW92ZURyb3Bab25lKGRyb3Bab25lOiBEcm9wWm9uZSkge1xyXG4gICAgICB0aGlzLmRyb3Bab25lQXJjaGl2ZS5kZWxldGUoZHJvcFpvbmUpO1xyXG4gICB9XHJcblxyXG4gICAvKiogaGlkZXMgYWxsIGRyb3Agem9uZXMsIGRlbGV0ZXMgYWxsIHRoZSBmYW1pbHkgYXNzaWdubWVudHMsXHJcbiAgICAqIGFuZCBlbXB0aWVzIHRoZSBkcm9wWm9uZUludmVudG9yeVxyXG4gICAgKi9cclxuICAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xyXG4gICAgICB0aGlzLmNsZWFyVmlzaWJsZVpvbmVzKCk7XHJcbiAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5sZW5ndGggPSAwO1xyXG4gICAgICB0aGlzLmRyb3Bab25lSW52ZW50b3J5Lmxlbmd0aCA9IDA7XHJcbiAgIH1cclxuXHJcbiAgIC8qKlxyXG4gICAgKiBSZXN0b3JlcyB0aGUgc2VydmljZSB0byBpdHMgaW5pdGlhbCBzdGF0ZTogaGlkZXMgYWxsIGRyb3Agem9uZXMsXHJcbiAgICAqIGRlbGV0ZXMgYWxsIHRoZSBmYW1pbHkgYXNzaWdubWVudHMsIGFuZCBlbXB0aWVzIHRoZSBkcm9wWm9uZUludmVudG9yeVxyXG4gICAgKiBhbmQgZHJvcFpvbmVBcmNoaXZlLlxyXG4gICAgKi9cclxuICAgcHVibGljIHJlc3RhcnQoKTogdm9pZCB7XHJcbiAgICAgIHRoaXMucmVzZXQoKTtcclxuICAgICAgdGhpcy5kcm9wWm9uZUFyY2hpdmUuY2xlYXIoKTtcclxuICAgfVxyXG5cclxuICAgcHVibGljIHJlc3RvcmVGYW1pbGllcygpOiB2b2lkIHtcclxuICAgICAgaWYgKHRoaXMudGVtcEZhbWlsaWVzLmxlbmd0aCA9PT0gMikge1xyXG4gICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMucG9wKCk7XHJcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKHRoaXMudGVtcEZhbWlsaWVzWzBdKTtcclxuICAgICAgICAgZm9yIChjb25zdCBtZW1iZXIgb2YgdGhpcy50ZW1wRmFtaWxpZXNbMF0ubWVtYmVycykge1xyXG4gICAgICAgICAgICBtZW1iZXIuc2V0RmFtaWx5KHRoaXMudGVtcEZhbWlsaWVzWzBdKTtcclxuICAgICAgICAgfVxyXG4gICAgICAgICBpZiAodGhpcy50ZW1wRmFtaWxpZXNbMV0gIT09IG51bGwpIHtcclxuICAgICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnB1c2godGhpcy50ZW1wRmFtaWxpZXNbMV0pO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiB0aGlzLnRlbXBGYW1pbGllc1sxXS5tZW1iZXJzKSB7XHJcbiAgICAgICAgICAgICAgIG1lbWJlci5zZXRGYW1pbHkodGhpcy50ZW1wRmFtaWxpZXNbMV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgdGhpcy50ZW1wRmFtaWxpZXMgPSBbXTtcclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICAvKipcclxuICAgICogU2hvd3MgdGhlIGRyb3Agem9uZSBmYW1pbHkgb2YgdGhlIGRyb3Agem9uZSBpbmRpY2F0ZWQgYnkgYGNvb3JkaW5hdGVzYC5cclxuICAgICovXHJcbiAgIHB1YmxpYyBzaG93RHJvcFpvbmVGYW1pbHkoXHJcbiAgICAgIC8qKiBOb3RlOiB0aGlzIGRyb3Agem9uZSBtYXkgbm90IGV4aXN0IGluIHRoZSBkcm9wWm9uZUludmVudG9yeTsgd2UgaGF2ZSB0byBzZWFyY2ggdGhlIGludmVudG9yeSBiYXNlZCBvbiBpdHMgbG9jYXRpb24gKi9cclxuICAgICAgZHJvcFpvbmU6IERyb3Bab25lLFxyXG4gICAgICBvcHRpb25zOiB7XHJcbiAgICAgICAgIGpvaW5GYW1pbGllcz86IGJvb2xlYW47XHJcbiAgICAgICAgIGFjdGl2YXRlTG93ZXN0SW5zdGVhZE9mRm91bmRlcj86IGJvb2xlYW47XHJcbiAgICAgIH0gPSB7IGpvaW5GYW1pbGllczogZmFsc2UsIGFjdGl2YXRlTG93ZXN0SW5zdGVhZE9mRm91bmRlcjogZmFsc2UgfVxyXG4gICApOiB2b2lkIHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgICB0aGlzLmFjdGl2ZURyb3Bab25lICE9PSBudWxsICYmXHJcbiAgICAgICAgIERyb3Bab25lLmRyb3Bab25lTG9jYXRpb25zQXJlRXF1YWwodGhpcy5hY3RpdmVEcm9wWm9uZSwgZHJvcFpvbmUpXHJcbiAgICAgICkge1xyXG4gICAgICAgICAvL0FscmVhZHkgc2hvd2luZyB0aGUgZmFtaWx5IHdpdGggdGhlIGFwcHJvcHJpYXRlIGFjdGl2ZSBkcm9wIHpvbmVcclxuICAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0aGlzLnZpc2libGVGYW1pbHkgIT09IG51bGwgfHwgdGhpcy5hY3RpdmVEcm9wWm9uZSAhPT0gbnVsbCkge1xyXG4gICAgICAgICB0aGlzLmNsZWFyVmlzaWJsZVpvbmVzKCk7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5kcm9wWm9uZUludmVudG9yeS5maW5kKCh6b25lKSA9PlxyXG4gICAgICAgICBEcm9wWm9uZS5kcm9wWm9uZUxvY2F0aW9uc0FyZUVxdWFsKHpvbmUsIGRyb3Bab25lKVxyXG4gICAgICApO1xyXG4gICAgICBpZiAodGFyZ2V0ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxyXG4gICAgICAgICAgICBgQ291bGQgbm90IGZpbmQgZHJvcCB6b25lIHRvIHNob3cuIGxvY2F0aW9uOiAke0pTT04uc3RyaW5naWZ5KFxyXG4gICAgICAgICAgICAgICBkcm9wWm9uZS5nZXRMb2NhdGlvbigpXHJcbiAgICAgICAgICAgICl9YFxyXG4gICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGZhbWlseSA9IHRhcmdldC5nZXRGYW1pbHkoKTtcclxuICAgICAgaWYgKG9wdGlvbnMuam9pbkZhbWlsaWVzID09PSB0cnVlKSB7XHJcbiAgICAgICAgIGNvbnN0IGxvY2F0aW9uMSA9IGRyb3Bab25lLmdldExvY2F0aW9uKCk7XHJcbiAgICAgICAgIGNvbnN0IGxvY2F0aW9uMiA9IG5ldyBEcm9wWm9uZUxvY2F0aW9uKFxyXG4gICAgICAgICAgICBbLi4ubG9jYXRpb24xLnBhcmVudENvb3JkaW5hdGVzXSxcclxuICAgICAgICAgICAgbG9jYXRpb24xLmluc2VydEluZGV4ICsgMVxyXG4gICAgICAgICApO1xyXG4gICAgICAgICBjb25zdCB0YXJnZXQyID0gdGhpcy5kcm9wWm9uZUludmVudG9yeS5maW5kKCh6b25lKSA9PlxyXG4gICAgICAgICAgICBEcm9wWm9uZS5kcm9wWm9uZUxvY2F0aW9uc0FyZUVxdWFsKHpvbmUsIGxvY2F0aW9uMilcclxuICAgICAgICAgKTtcclxuICAgICAgICAgaWYgKHRhcmdldDIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBkcm9wIHpvbmUgdG8gc2hvd1wiKTtcclxuICAgICAgICAgfVxyXG4gICAgICAgICBjb25zdCBmYW1pbHkyID0gdGFyZ2V0Mi5nZXRGYW1pbHkoKTtcclxuICAgICAgICAgaWYgKGZhbWlseSA9PT0gdW5kZWZpbmVkIHx8IGZhbWlseTIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBmYW1pbHlcIik7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgY29uc3QgbmV3RmFtaWx5ID0ge1xyXG4gICAgICAgICAgICBmb3VuZGVyOiBmYW1pbHkuZm91bmRlcixcclxuICAgICAgICAgICAgbWVtYmVyczogWy4uLmZhbWlseS5tZW1iZXJzXVxyXG4gICAgICAgICB9O1xyXG4gICAgICAgICB0aGlzLnNob3dEcm9wWm9uZShmYW1pbHkuZm91bmRlciwgdHJ1ZSk7XHJcbiAgICAgICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIGZhbWlseS5tZW1iZXJzLnNvcnQoc29ydEZhbWlseSkpIHtcclxuICAgICAgICAgICAgbWVtYmVyLnNldEZhbWlseShuZXdGYW1pbHkpO1xyXG4gICAgICAgICAgICBpZiAobWVtYmVyICE9PSBmYW1pbHkuZm91bmRlcikge1xyXG4gICAgICAgICAgICAgICBpZiAodGhpcy5hY3RpdmVEcm9wWm9uZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAvL0ZhaWxlZCB0byBhY3RpdmF0ZSBhIHpvbmUgc28gZmFyLCBzbyBhY3RpdmF0ZSB0aGlzIG9uZSBpbnN0ZWFkXHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKG1lbWJlciwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKG1lbWJlcik7XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICB9XHJcbiAgICAgICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIGZhbWlseTIubWVtYmVycykge1xyXG4gICAgICAgICAgICBtZW1iZXIuc2V0RmFtaWx5KG5ld0ZhbWlseSk7XHJcbiAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgbWVtYmVyLmdldExvY2F0aW9uKCkucGFyZW50Q29vcmRpbmF0ZXMubGVuZ3RoIDxcclxuICAgICAgICAgICAgICAgdGFyZ2V0Mi5nZXRMb2NhdGlvbigpLnBhcmVudENvb3JkaW5hdGVzLmxlbmd0aFxyXG4gICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgbmV3RmFtaWx5Lm1lbWJlcnMucHVzaChtZW1iZXIpO1xyXG4gICAgICAgICAgICAgICB0aGlzLnNob3dEcm9wWm9uZShtZW1iZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgLy9UZW1wb3JhcmlseSBzdG9yZSB0aGUgb2xkIGZhbWlsaWVzXHJcbiAgICAgICAgIHRoaXMudGVtcEZhbWlsaWVzID0gW2ZhbWlseSwgZmFtaWx5Ml07XHJcbiAgICAgICAgIC8vUmVtb3ZlIHRoZSBvbGQgZmFtaWxpZXNcclxuICAgICAgICAgY29uc3QgZmFtaWx5SW5kZXggPSB0aGlzLmRyb3Bab25lRmFtaWxpZXMuaW5kZXhPZihmYW1pbHkpO1xyXG4gICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMuc3BsaWNlKGZhbWlseUluZGV4LCAxKTtcclxuICAgICAgICAgY29uc3QgZmFtaWx5MkluZGV4ID0gdGhpcy5kcm9wWm9uZUZhbWlsaWVzLmluZGV4T2YoZmFtaWx5Mik7XHJcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5zcGxpY2UoZmFtaWx5MkluZGV4LCAxKTtcclxuICAgICAgICAgLy9BZGQgdGhlIG5ldyBmYW1pbHlcclxuICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnB1c2gobmV3RmFtaWx5KTtcclxuICAgICAgICAgdGhpcy52aXNpYmxlRmFtaWx5ID0gbmV3RmFtaWx5O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgICBpZiAoZmFtaWx5ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZmFtaWx5XCIpO1xyXG4gICAgICAgICB9XHJcbiAgICAgICAgIHRoaXMudmlzaWJsZUZhbWlseSA9IGZhbWlseTtcclxuICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUoZmFtaWx5LmZvdW5kZXIsIHRydWUpO1xyXG4gICAgICAgICBpZiAoZmFtaWx5Lm1lbWJlcnMubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiBmYW1pbHkubWVtYmVycy5zb3J0KHNvcnRGYW1pbHkpKSB7XHJcbiAgICAgICAgICAgICAgIGlmIChtZW1iZXIgIT09IGZhbWlseS5mb3VuZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmFjdGl2ZURyb3Bab25lID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgIC8vRmFpbGVkIHRvIGFjdGl2YXRlIGEgem9uZSBzbyBmYXIsIHNvIGFjdGl2YXRlIHRoaXMgb25lIGluc3RlYWRcclxuICAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUobWVtYmVyLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUobWVtYmVyKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGlmIChcclxuICAgICAgICAgb3B0aW9ucy5hY3RpdmF0ZUxvd2VzdEluc3RlYWRPZkZvdW5kZXIgPT09IHRydWUgJiZcclxuICAgICAgICAgdGhpcy52aXNpYmxlRmFtaWx5Lm1lbWJlcnMubGVuZ3RoID4gMVxyXG4gICAgICApIHtcclxuICAgICAgICAgY29uc3QgbG93ZXN0TWVtYmVyID0gWy4uLnRoaXMudmlzaWJsZUZhbWlseS5tZW1iZXJzXVxyXG4gICAgICAgICAgICAuc29ydChzb3J0RmFtaWx5KVxyXG4gICAgICAgICAgICAucG9wKCk7XHJcbiAgICAgICAgIGlmIChsb3dlc3RNZW1iZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZ2V0IGxvd2VzdCBtZW1iZXJcIik7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgdGhpcy5zd2FwQWN0aXZlRHJvcFpvbmUobG93ZXN0TWVtYmVyKTtcclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgc3dhcEFjdGl2ZURyb3Bab25lKG5ld0FjdGl2ZURyb3Bab25lOiBEcm9wWm9uZSk6IHZvaWQge1xyXG4gICAgICBpZiAodGhpcy52aXNpYmxlRmFtaWx5ID09PSBudWxsKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIHZpc2libGUgZmFtaWx5IGF2YWlsYWJsZSBmb3Igc3dhcHBpbmdcIik7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnZpc2libGVGYW1pbHkubWVtYmVycy5maW5kSW5kZXgoXHJcbiAgICAgICAgIChkcm9wWm9uZSkgPT4gZHJvcFpvbmUgPT09IG5ld0FjdGl2ZURyb3Bab25lXHJcbiAgICAgICk7XHJcbiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmFpbGVkIHRvIHN3YXAgYWN0aXZlIGRyb3Agem9uZVwiKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNldEFjdGl2ZURyb3Bab25lKG5ld0FjdGl2ZURyb3Bab25lKTtcclxuICAgfVxyXG5cclxuICAgcHVibGljIHVwZGF0ZSgpOiB2b2lkIHtcclxuICAgICAgdGhpcy51cGRhdGUkLm5leHQobnVsbCk7XHJcbiAgIH1cclxuXHJcbiAgIHByaXZhdGUgYXNzaWduRmFtaWxpZXMoKTogdm9pZCB7XHJcbiAgICAgIGNvbnN0IG9ycGhhblpvbmVzID0gWy4uLnRoaXMuZHJvcFpvbmVJbnZlbnRvcnldO1xyXG4gICAgICBjb25zdCBkZWVwZXN0TWVtYmVycyA9IG9ycGhhblpvbmVzXHJcbiAgICAgICAgIC5maWx0ZXIoKHpvbmUpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgbG9jYXRpb24gPSB6b25lLmdldExvY2F0aW9uKCk7XHJcbiAgICAgICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgICAgIGxvY2F0aW9uLmluc2VydEluZGV4ID09PSAwICYmXHJcbiAgICAgICAgICAgICAgIGxvY2F0aW9uLnBhcmVudENvb3JkaW5hdGVzLmxlbmd0aCA+IDBcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgfSlcclxuICAgICAgICAgLnNvcnQoKHZhbHVlQSwgdmFsdWVCKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGFDb29yZGluYXRlcyA9IHZhbHVlQS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKTtcclxuICAgICAgICAgICAgY29uc3QgYkNvb3JkaW5hdGVzID0gdmFsdWVCLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpO1xyXG4gICAgICAgICAgICBjb25zdCBsZW5ndGggPSBNYXRoLm1heChhQ29vcmRpbmF0ZXMubGVuZ3RoLCBiQ29vcmRpbmF0ZXMubGVuZ3RoKTtcclxuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgICAgICAgICBpZiAoKGFDb29yZGluYXRlc1tpbmRleF0gPz8gLTEpID4gKGJDb29yZGluYXRlc1tpbmRleF0gPz8gLTEpKSB7XHJcbiAgICAgICAgICAgICAgICAgIHJldHVybiAtMTtcclxuICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgICAgICAgICAgKGFDb29yZGluYXRlc1tpbmRleF0gPz8gLTEpIDwgKGJDb29yZGluYXRlc1tpbmRleF0gPz8gLTEpXHJcbiAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICByZXR1cm4gMTtcclxuICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgICB9KTtcclxuICAgICAgZm9yIChjb25zdCBkcm9wWm9uZSBvZiBkZWVwZXN0TWVtYmVycykge1xyXG4gICAgICAgICBpZiAoIW9ycGhhblpvbmVzLmluY2x1ZGVzKGRyb3Bab25lKSkge1xyXG4gICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgfVxyXG4gICAgICAgICBjb25zdCBmYW1pbHk6IERyb3Bab25lRmFtaWx5ID0ge1xyXG4gICAgICAgICAgICBmb3VuZGVyOiBkcm9wWm9uZSxcclxuICAgICAgICAgICAgbWVtYmVyczogW11cclxuICAgICAgICAgfTtcclxuICAgICAgICAgZHJvcFpvbmUuc2V0RmFtaWx5KGZhbWlseSk7XHJcbiAgICAgICAgIC8vU2VlIGlmIHRoZXJlIGFyZSBhbnkgb3JwaGFucyB0aGF0IGJlbG9uZyB0byB0aGlzIGZhbWlseSBhbmQgY2xhaW0gdGhlbS5cclxuICAgICAgICAgY29uc3QgY3Vyc29yID0gWy4uLmRyb3Bab25lLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpXTtcclxuICAgICAgICAgd2hpbGUgKGN1cnNvci5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZhbWlseU1lbWJlckluZGV4ID0gb3JwaGFuWm9uZXMuZmluZEluZGV4KCh6b25lKSA9PlxyXG4gICAgICAgICAgICAgICBhcnJheXNBcmVFcXVhbCh6b25lLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpLCBjdXJzb3IpXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGlmIChmYW1pbHlNZW1iZXJJbmRleCAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgY29uc3QgZmFtaWx5TWVtYmVyID0gb3JwaGFuWm9uZXMuc3BsaWNlKGZhbWlseU1lbWJlckluZGV4LCAxKVswXTtcclxuICAgICAgICAgICAgICAgZmFtaWx5Lm1lbWJlcnMucHVzaChmYW1pbHlNZW1iZXIpO1xyXG4gICAgICAgICAgICAgICBmYW1pbHlNZW1iZXIuc2V0RmFtaWx5KGZhbWlseSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY3Vyc29yLnBvcCgpO1xyXG4gICAgICAgICAgICBjdXJzb3JbY3Vyc29yLmxlbmd0aCAtIDFdKys7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnB1c2goZmFtaWx5KTtcclxuICAgICAgfVxyXG4gICAgICBmb3IgKGNvbnN0IGRyb3Bab25lIG9mIG9ycGhhblpvbmVzLmZpbHRlcihcclxuICAgICAgICAgKHpvbmUpID0+IHpvbmUuZ2V0RnVsbEluc2VydENvb3JkaW5hdGVzKCkubGVuZ3RoID09PSAxXHJcbiAgICAgICkpIHtcclxuICAgICAgICAgY29uc3QgZmFtaWx5OiBEcm9wWm9uZUZhbWlseSA9IHtcclxuICAgICAgICAgICAgZm91bmRlcjogZHJvcFpvbmUsXHJcbiAgICAgICAgICAgIG1lbWJlcnM6IFtkcm9wWm9uZV1cclxuICAgICAgICAgfTtcclxuICAgICAgICAgZHJvcFpvbmUuc2V0RmFtaWx5KGZhbWlseSk7XHJcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKGZhbWlseSk7XHJcbiAgICAgICAgIG9ycGhhblpvbmVzLnNwbGljZShvcnBoYW5ab25lcy5pbmRleE9mKGRyb3Bab25lKSwgMSk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKG9ycGhhblpvbmVzLmxlbmd0aCAhPT0gMCkge1xyXG4gICAgICAgICBsZXQgb3JwaGFucyA9IFwiXCI7XHJcbiAgICAgICAgIGZvciAoY29uc3Qgem9uZSBvZiBvcnBoYW5ab25lcykge1xyXG4gICAgICAgICAgICBvcnBoYW5zICs9IGAke0pTT04uc3RyaW5naWZ5KHpvbmUuZ2V0TG9jYXRpb24oKSl9LCBgO1xyXG4gICAgICAgICB9XHJcbiAgICAgICAgIG9ycGhhbnMgPSBvcnBoYW5zLnNsaWNlKDAsIG9ycGhhbnMubGVuZ3RoIC0gMik7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAgICAgYFNvbWUgem9uZXMgd2VyZSBub3QgYXNzaWduZWQgdG8gYSBmYW1pbHkuIFRoZSBvcnBoYW4gem9uZXMgaGF2ZSB0aGUgZm9sbG93aW5nIGxvY2F0aW9uczogJHtvcnBoYW5zfWBcclxuICAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICBwcml2YXRlIGJ1aWxkSW52ZW50b3J5KCkge1xyXG4gICAgICAvL1dlIGRvIHRoaXMgZnVua3kgc3RyaW5nIGFycmF5IGJlY2F1c2UgaXQgaXMgZmFzdGVyIHRoYW4gZG9pbmcgZGlyZWN0IGFycmF5IGNvbXBhcmlzb25zXHJcbiAgICAgIGNvbnN0IGludmVudG9yeUNvb3JkaW5hdGVzOiBBcnJheTxzdHJpbmc+ID0gW107XHJcbiAgICAgIGZvciAoY29uc3QgZHJvcFpvbmUgb2YgdGhpcy5kcm9wWm9uZUFyY2hpdmUpIHtcclxuICAgICAgICAgY29uc3QgY29vcmRpbmF0ZXMgPSBkcm9wWm9uZS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKS5qb2luKFwiLFwiKTtcclxuICAgICAgICAgaWYgKGludmVudG9yeUNvb3JkaW5hdGVzLmluY2x1ZGVzKGNvb3JkaW5hdGVzKSkge1xyXG4gICAgICAgICAgICBkcm9wWm9uZS5pc1JlbmRlcmVkKGZhbHNlKTtcclxuICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5kcm9wWm9uZUludmVudG9yeS5wdXNoKGRyb3Bab25lKTtcclxuICAgICAgICAgICAgaW52ZW50b3J5Q29vcmRpbmF0ZXMucHVzaChjb29yZGluYXRlcyk7XHJcbiAgICAgICAgICAgIGRyb3Bab25lLmlzUmVuZGVyZWQodHJ1ZSk7XHJcbiAgICAgICAgIH1cclxuICAgICAgfVxyXG4gICB9XHJcblxyXG4gICBwcml2YXRlIHNldEFjdGl2ZURyb3Bab25lKGRyb3Bab25lOiBEcm9wWm9uZSB8IG51bGwpOiB2b2lkIHtcclxuICAgICAgaWYgKHRoaXMuYWN0aXZlRHJvcFpvbmUgIT09IG51bGwpIHtcclxuICAgICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZS5pc0FjdGl2ZShmYWxzZSk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZSA9IGRyb3Bab25lO1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUgIT09IG51bGwgJiZcclxuICAgICAgICAgdGhpcy5kcmFnU3RhdGVTZXJ2aWNlLmdldFN0YXRlKCkgIT09IFwiZHJvcHBhYmxlXCJcclxuICAgICAgKSB7XHJcbiAgICAgICAgIHRoaXMuZHJhZ1N0YXRlU2VydmljZS5kcm9wcGFibGUoKTtcclxuICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZSA9PT0gbnVsbCAmJlxyXG4gICAgICAgICB0aGlzLmRyYWdTdGF0ZVNlcnZpY2UuZ2V0U3RhdGUoKSA9PT0gXCJkcm9wcGFibGVcIlxyXG4gICAgICApIHtcclxuICAgICAgICAgdGhpcy5kcmFnU3RhdGVTZXJ2aWNlLm5vdERyb3BwYWJsZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0aGlzLmFjdGl2ZURyb3Bab25lICE9PSBudWxsKSB7XHJcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUuaXNBY3RpdmUodHJ1ZSk7XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSBzaG93RHJvcFpvbmUoZHJvcFpvbmU6IERyb3Bab25lLCBhY3RpdmUgPSBmYWxzZSk6IGJvb2xlYW4ge1xyXG4gICAgICBpZiAodGhpcy50cmVlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRHJvcFpvbmVTZXJ2aWNlIG5vdCBpbml0aWFsaXplZFwiKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAoIXRoaXMuem9uZUlzQWxsb3dlZChkcm9wWm9uZSkpIHtcclxuICAgICAgICAgLy9Vc2VyIHNldHRpbmdzIGluZGljYXRlIHRvIHNraXAgdGhpcyBkcm9wIHpvbmVcclxuICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXMudHJlZS5maW5kQnlDb29yZGluYXRlcyhcclxuICAgICAgICAgZHJvcFpvbmUuZ2V0TG9jYXRpb24oKS5wYXJlbnRDb29yZGluYXRlc1xyXG4gICAgICApO1xyXG4gICAgICBpZiAocGFyZW50ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQmFkIGZhbWlseSBtZW1iZXJcIik7XHJcbiAgICAgIH1cclxuICAgICAgZHJvcFpvbmUuaXNWaXNpYmxlKHRydWUpO1xyXG4gICAgICBpZiAoYWN0aXZlID09PSB0cnVlKSB7XHJcbiAgICAgICAgIHRoaXMuc2V0QWN0aXZlRHJvcFpvbmUoZHJvcFpvbmUpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICB9XHJcblxyXG4gICBwcml2YXRlIHVwZGF0ZURyb3Bab25lcygpOiB2b2lkIHtcclxuICAgICAgdGhpcy5yZXNldCgpO1xyXG4gICAgICB0aGlzLmJ1aWxkSW52ZW50b3J5KCk7XHJcbiAgICAgIHRoaXMuYXNzaWduRmFtaWxpZXMoKTtcclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSB6b25lSXNBbGxvd2VkKGRyb3Bab25lOiBEcm9wWm9uZSk6IGJvb2xlYW4ge1xyXG4gICAgICBpZiAodGhpcy50cmVlT3B0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IHRoaXMudHJlZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImRyb3Bab25lU2VydmljZSBub3QgaW5pdGlhbGl6ZWRcIik7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZHJhZ1N0YXRlU2VydmljZS5nZXREYXRhKCk7XHJcbiAgICAgIGlmIChkYXRhID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgZ2V0IGRyYWdnZWQgbm9kZVwiKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBwYXJlbnRDb29yZGluYXRlcyA9IGRyb3Bab25lLmdldExvY2F0aW9uKCkucGFyZW50Q29vcmRpbmF0ZXM7XHJcbiAgICAgIGNvbnN0IGRyb3Bab25lUGFyZW50ID0gdGhpcy50cmVlLmZpbmRCeUNvb3JkaW5hdGVzKHBhcmVudENvb3JkaW5hdGVzKTtcclxuICAgICAgaWYgKGRyb3Bab25lUGFyZW50ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGdldCBkcm9wIHpvbmUgcGFyZW50XCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChcclxuICAgICAgICAgcGFyZW50Q29vcmRpbmF0ZXMubGVuZ3RoID4gMCAmJlxyXG4gICAgICAgICAhaXNOZXN0aW5nQWxsb3dlZChcclxuICAgICAgICAgICAgdGhpcy50cmVlT3B0aW9ucyxcclxuICAgICAgICAgICAgZHJvcFpvbmVQYXJlbnQuZGF0YSBhcyBMaW1ibGVUcmVlTm9kZVxyXG4gICAgICAgICApXHJcbiAgICAgICkge1xyXG4gICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgZHJvcFpvbmVJbmRleCA9IGRyb3Bab25lLmdldExvY2F0aW9uKCkuaW5zZXJ0SW5kZXg7XHJcbiAgICAgIGlmIChkcm9wWm9uZUluZGV4ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGdldCBkcm9wIHpvbmUgaW5kZXhcIik7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgZHJhZ2dlZE5vZGUgPSBkYXRhLmJyYW5jaDtcclxuICAgICAgaWYgKFxyXG4gICAgICAgICAhdGhpcy50cmVlT3B0aW9ucy5hbGxvd0Ryb3AoXHJcbiAgICAgICAgICAgIGRyYWdnZWROb2RlLmRhdGEsXHJcbiAgICAgICAgICAgIGRyb3Bab25lUGFyZW50LmRhdGEgYXMgTGltYmxlVHJlZU5vZGUsXHJcbiAgICAgICAgICAgIGRyb3Bab25lSW5kZXhcclxuICAgICAgICAgKVxyXG4gICAgICApIHtcclxuICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICB9XHJcbn1cclxuIl19