@limble/limble-tree 0.12.2 → 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} +105 -147
  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 +24 -10
  35. package/bundles/limble-limble-tree.umd.js +0 -2905
  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 -372
  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,372 +0,0 @@
1
- import { Injectable } from "@angular/core";
2
- import { arraysAreEqual } from "../util";
3
- import { DropZone } from "../classes/DropZone";
4
- import { DropZoneLocation } from "../classes/DropZoneLocation";
5
- import { EMPTY, 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 EMPTY;
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 dropZoneParent = this.tree.findByCoordinates(dropZone.getLocation().parentCoordinates);
353
- if (dropZoneParent === undefined) {
354
- throw new Error("Could not get drop zone parent");
355
- }
356
- const dropZoneIndex = dropZone.getLocation().insertIndex;
357
- if (dropZoneIndex === undefined) {
358
- throw new Error("Could not get drop zone index");
359
- }
360
- const draggedNode = data.branch;
361
- if (this.treeOptions.allowDrop(draggedNode.data, dropZoneParent.data, dropZoneIndex)) {
362
- return true;
363
- }
364
- return false;
365
- }
366
- }
367
- DropZoneService.ɵfac = function DropZoneService_Factory(t) { return new (t || DropZoneService)(i0.ɵɵinject(i1.DragStateService), i0.ɵɵinject(i2.TreeConstructionStatus)); };
368
- DropZoneService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DropZoneService, factory: DropZoneService.ɵfac });
369
- (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropZoneService, [{
370
- type: Injectable
371
- }], function () { return [{ type: i1.DragStateService }, { type: i2.TreeConstructionStatus }]; }, null); })();
372
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcC16b25lLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saW1ibGUtdHJlZS9zcmMvbGliL2xpbWJsZS10cmVlLXJvb3QvZHJvcC16b25lLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV0QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7OztBQVN2RCxTQUFTLFVBQVUsQ0FBQyxPQUFpQixFQUFFLE9BQWlCO0lBQ3JELE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQ3hELE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQ3hELElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxZQUFZLENBQUMsTUFBTSxFQUFFO1FBQzVDLE9BQU8sQ0FBQyxDQUFDLENBQUM7S0FDWjtJQUNELElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxZQUFZLENBQUMsTUFBTSxFQUFFO1FBQzVDLE9BQU8sQ0FBQyxDQUFDO0tBQ1g7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNaLENBQUM7QUFHRCxNQUFNLE9BQU8sZUFBZTtJQWF6QixZQUNvQixnQkFBa0MsRUFDbkQsc0JBQThDO1FBRDdCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFHbkQsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJ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QUFJLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzdDLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRTtZQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7U0FDNUM7UUFDRCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUMvQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsaUJBQWlCLENBQzFDLENBQUM7UUFDRixJQUFJLGNBQWMsS0FBSyxTQUFTLEVBQUU7WUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1NBQ3BEO1FBQ0QsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLFdBQVcsQ0FBQztRQUN6RCxJQUFJLGFBQWEsS0FBSyxTQUFTLEVBQUU7WUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1NBQ25EO1FBQ0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNoQyxJQUNHLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUN2QixXQUFXLENBQUMsSUFBSSxFQUNoQixjQUFjLENBQUMsSUFBc0IsRUFDckMsYUFBYSxDQUNmLEVBQ0Y7WUFDQyxPQUFPLElBQUksQ0FBQztTQUNkO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDaEIsQ0FBQzs7OEVBeGFTLGVBQWU7cUVBQWYsZUFBZSxXQUFmLGVBQWU7dUZBQWYsZUFBZTtjQUQzQixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IEJyYW5jaCwgQnJhbmNoQ29vcmRpbmF0ZXMgfSBmcm9tIFwiLi4vY2xhc3Nlcy9CcmFuY2hcIjtcclxuaW1wb3J0IHsgRHJhZ1N0YXRlU2VydmljZSB9IGZyb20gXCIuLi9zaW5nbGV0b25zL2RyYWctc3RhdGUuc2VydmljZVwiO1xyXG5pbXBvcnQgdHlwZSB7IExpbWJsZVRyZWVOb2RlLCBQcm9jZXNzZWRPcHRpb25zIH0gZnJvbSBcIi4vdHJlZS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IGFycmF5c0FyZUVxdWFsIH0gZnJvbSBcIi4uL3V0aWxcIjtcclxuaW1wb3J0IHsgRHJvcFpvbmUgfSBmcm9tIFwiLi4vY2xhc3Nlcy9Ecm9wWm9uZVwiO1xyXG5pbXBvcnQgeyBEcm9wWm9uZUxvY2F0aW9uIH0gZnJvbSBcIi4uL2NsYXNzZXMvRHJvcFpvbmVMb2NhdGlvblwiO1xyXG5pbXBvcnQgeyBFTVBUWSwgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XHJcbmltcG9ydCB7IFRyZWVDb25zdHJ1Y3Rpb25TdGF0dXMgfSBmcm9tIFwiLi90cmVlLWNvbnN0cnVjdGlvbi1zdGF0dXMuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBkZWJvdW5jZSwgZmlsdGVyLCB0YXAgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRHJvcFpvbmVGYW1pbHkge1xyXG4gICAvKiogVGhlIGRlZXBlc3QgbWVtYmVyIG9mIHRoZSBmYW1pbHkgKi9cclxuICAgZm91bmRlcjogRHJvcFpvbmU7XHJcbiAgIC8qKiBBbGwgdGhlIGRyb3Agem9uZXMgdGhhdCBiZWxvbmcgdG8gdGhpcyBmYW1pbHkgKi9cclxuICAgbWVtYmVyczogQXJyYXk8RHJvcFpvbmU+O1xyXG59XHJcblxyXG5mdW5jdGlvbiBzb3J0RmFtaWx5KG1lbWJlckE6IERyb3Bab25lLCBtZW1iZXJCOiBEcm9wWm9uZSkge1xyXG4gICBjb25zdCBhQ29vcmRpbmF0ZXMgPSBtZW1iZXJBLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpO1xyXG4gICBjb25zdCBiQ29vcmRpbmF0ZXMgPSBtZW1iZXJCLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpO1xyXG4gICBpZiAoYUNvb3JkaW5hdGVzLmxlbmd0aCA+IGJDb29yZGluYXRlcy5sZW5ndGgpIHtcclxuICAgICAgcmV0dXJuIC0xO1xyXG4gICB9XHJcbiAgIGlmIChhQ29vcmRpbmF0ZXMubGVuZ3RoIDwgYkNvb3JkaW5hdGVzLmxlbmd0aCkge1xyXG4gICAgICByZXR1cm4gMTtcclxuICAgfVxyXG4gICByZXR1cm4gMDtcclxufVxyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgRHJvcFpvbmVTZXJ2aWNlIHtcclxuICAgcHJpdmF0ZSByZWFkb25seSBkcm9wWm9uZUFyY2hpdmU6IFNldDxEcm9wWm9uZT47XHJcbiAgIHByaXZhdGUgcmVhZG9ubHkgZHJvcFpvbmVJbnZlbnRvcnk6IEFycmF5PERyb3Bab25lPjtcclxuICAgcHJpdmF0ZSByZWFkb25seSBkcm9wWm9uZUZhbWlsaWVzOiBBcnJheTxEcm9wWm9uZUZhbWlseT47XHJcbiAgIHByaXZhdGUgdmlzaWJsZUZhbWlseTogRHJvcFpvbmVGYW1pbHkgfCBudWxsO1xyXG4gICBwcml2YXRlIGFjdGl2ZURyb3Bab25lOiBEcm9wWm9uZSB8IG51bGw7XHJcbiAgIHByaXZhdGUgdHJlZTogQnJhbmNoPGFueT4gfCB1bmRlZmluZWQ7XHJcbiAgIHByaXZhdGUgdHJlZU9wdGlvbnM6IFByb2Nlc3NlZE9wdGlvbnMgfCB1bmRlZmluZWQ7XHJcbiAgIHByaXZhdGUgdGVtcEZhbWlsaWVzOlxyXG4gICAgICB8IHJlYWRvbmx5IFtEcm9wWm9uZUZhbWlseSwgRHJvcFpvbmVGYW1pbHkgfCBudWxsXVxyXG4gICAgICB8IHJlYWRvbmx5IFtdO1xyXG4gICBwcml2YXRlIHJlYWRvbmx5IHVwZGF0ZSQ6IFN1YmplY3Q8bnVsbD47XHJcblxyXG4gICBjb25zdHJ1Y3RvcihcclxuICAgICAgcHJpdmF0ZSByZWFkb25seSBkcmFnU3RhdGVTZXJ2aWNlOiBEcmFnU3RhdGVTZXJ2aWNlLFxyXG4gICAgICB0cmVlQ29uc3RydWN0aW9uU3RhdHVzOiBUcmVlQ29uc3RydWN0aW9uU3RhdHVzXHJcbiAgICkge1xyXG4gICAgICB0aGlzLmRyb3Bab25lQXJjaGl2ZSA9IG5ldyBTZXQoKTtcclxuICAgICAgdGhpcy5kcm9wWm9uZUludmVudG9yeSA9IFtdO1xyXG4gICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMgPSBbXTtcclxuICAgICAgdGhpcy52aXNpYmxlRmFtaWx5ID0gbnVsbDtcclxuICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZSA9IG51bGw7XHJcbiAgICAgIHRoaXMudGVtcEZhbWlsaWVzID0gW107XHJcbiAgICAgIHRoaXMuc2V0QWN0aXZlRHJvcFpvbmUobnVsbCk7XHJcbiAgICAgIGxldCB0cmVlSXNTdGFibGUgPSBmYWxzZTtcclxuICAgICAgY29uc3QgdHJlZUlzU3RhYmxlJCA9IHRyZWVDb25zdHJ1Y3Rpb25TdGF0dXMuc3RhYmxlJC5waXBlKFxyXG4gICAgICAgICB0YXAoKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICAgIHRyZWVJc1N0YWJsZSA9IHZhbHVlO1xyXG4gICAgICAgICB9KSxcclxuICAgICAgICAgZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWUgPT09IHRydWUpXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMudXBkYXRlJCA9IG5ldyBTdWJqZWN0KCk7XHJcbiAgICAgIHRoaXMudXBkYXRlJFxyXG4gICAgICAgICAucGlwZShcclxuICAgICAgICAgICAgZGVib3VuY2UoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICBpZiAodHJlZUlzU3RhYmxlID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vSWYgdHJlZSBpcyBzdGFibGUsIGNvbnRpbnVlIHJpZ2h0IGF3YXlcclxuICAgICAgICAgICAgICAgICAgcmV0dXJuIEVNUFRZO1xyXG4gICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgIC8vSWYgdHJlZSBpcyBub3Qgc3RhYmxlLCB3YWl0IGZvciBpdCB0byBiZWNvbWUgc28uXHJcbiAgICAgICAgICAgICAgIHJldHVybiB0cmVlSXNTdGFibGUkO1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICApXHJcbiAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgdGhpcy51cGRhdGVEcm9wWm9uZXMoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgIH0pO1xyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgYWRkRHJvcFpvbmUobmV3RHJvcFpvbmU6IERyb3Bab25lKTogdm9pZCB7XHJcbiAgICAgIHRoaXMuZHJvcFpvbmVBcmNoaXZlLmFkZChuZXdEcm9wWm9uZSk7XHJcbiAgIH1cclxuXHJcbiAgIC8qKiBoaWRlcyBhbGwgZHJvcCB6b25lcyAqL1xyXG4gICBwdWJsaWMgY2xlYXJWaXNpYmxlWm9uZXMoKTogdm9pZCB7XHJcbiAgICAgIGlmICh0aGlzLnZpc2libGVGYW1pbHkgIT09IG51bGwpIHtcclxuICAgICAgICAgZm9yIChjb25zdCBtZW1iZXIgb2YgdGhpcy52aXNpYmxlRmFtaWx5Lm1lbWJlcnMpIHtcclxuICAgICAgICAgICAgbWVtYmVyLmlzVmlzaWJsZShmYWxzZSk7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgdGhpcy52aXNpYmxlRmFtaWx5ID0gbnVsbDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNldEFjdGl2ZURyb3Bab25lKG51bGwpO1xyXG4gICB9XHJcblxyXG4gICBwdWJsaWMgZ2V0QWN0aXZlRHJvcFpvbmUoKTogRHJvcFpvbmVTZXJ2aWNlW1wiYWN0aXZlRHJvcFpvbmVcIl0ge1xyXG4gICAgICByZXR1cm4gdGhpcy5hY3RpdmVEcm9wWm9uZTtcclxuICAgfVxyXG5cclxuICAgcHVibGljIGdldERyb3Bab25lKGNvb3JkaW5hdGVzOiBCcmFuY2hDb29yZGluYXRlcyk6IERyb3Bab25lIHwgdW5kZWZpbmVkIHtcclxuICAgICAgY29uc3QgcGFyZW50ID0gWy4uLmNvb3JkaW5hdGVzXTtcclxuICAgICAgcGFyZW50LnBvcCgpO1xyXG4gICAgICBjb25zdCBpbmRleCA9IGNvb3JkaW5hdGVzW2Nvb3JkaW5hdGVzLmxlbmd0aCAtIDFdO1xyXG4gICAgICBjb25zdCBsb2NhdGlvbiA9IG5ldyBEcm9wWm9uZUxvY2F0aW9uKHBhcmVudCwgaW5kZXgpO1xyXG4gICAgICByZXR1cm4gdGhpcy5kcm9wWm9uZUludmVudG9yeS5maW5kKChkcm9wWm9uZSkgPT5cclxuICAgICAgICAgRHJvcFpvbmUuZHJvcFpvbmVMb2NhdGlvbnNBcmVFcXVhbChkcm9wWm9uZSwgbG9jYXRpb24pXHJcbiAgICAgICk7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyBpbml0KHRyZWU6IEJyYW5jaDxhbnk+LCB0cmVlT3B0aW9uczogUHJvY2Vzc2VkT3B0aW9ucyk6IHZvaWQge1xyXG4gICAgICB0aGlzLnRyZWUgPSB0cmVlO1xyXG4gICAgICB0aGlzLnRyZWVPcHRpb25zID0gdHJlZU9wdGlvbnM7XHJcbiAgICAgIHRoaXMudXBkYXRlKCk7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyByZW1vdmVEcm9wWm9uZShkcm9wWm9uZTogRHJvcFpvbmUpIHtcclxuICAgICAgdGhpcy5kcm9wWm9uZUFyY2hpdmUuZGVsZXRlKGRyb3Bab25lKTtcclxuICAgfVxyXG5cclxuICAgLyoqIGhpZGVzIGFsbCBkcm9wIHpvbmVzLCBkZWxldGVzIGFsbCB0aGUgZmFtaWx5IGFzc2lnbm1lbnRzLFxyXG4gICAgKiBhbmQgZW1wdGllcyB0aGUgZHJvcFpvbmVJbnZlbnRvcnlcclxuICAgICovXHJcbiAgIHB1YmxpYyByZXNldCgpOiB2b2lkIHtcclxuICAgICAgdGhpcy5jbGVhclZpc2libGVab25lcygpO1xyXG4gICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMubGVuZ3RoID0gMDtcclxuICAgICAgdGhpcy5kcm9wWm9uZUludmVudG9yeS5sZW5ndGggPSAwO1xyXG4gICB9XHJcblxyXG4gICAvKipcclxuICAgICogUmVzdG9yZXMgdGhlIHNlcnZpY2UgdG8gaXRzIGluaXRpYWwgc3RhdGU6IGhpZGVzIGFsbCBkcm9wIHpvbmVzLFxyXG4gICAgKiBkZWxldGVzIGFsbCB0aGUgZmFtaWx5IGFzc2lnbm1lbnRzLCBhbmQgZW1wdGllcyB0aGUgZHJvcFpvbmVJbnZlbnRvcnlcclxuICAgICogYW5kIGRyb3Bab25lQXJjaGl2ZS5cclxuICAgICovXHJcbiAgIHB1YmxpYyByZXN0YXJ0KCk6IHZvaWQge1xyXG4gICAgICB0aGlzLnJlc2V0KCk7XHJcbiAgICAgIHRoaXMuZHJvcFpvbmVBcmNoaXZlLmNsZWFyKCk7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyByZXN0b3JlRmFtaWxpZXMoKTogdm9pZCB7XHJcbiAgICAgIGlmICh0aGlzLnRlbXBGYW1pbGllcy5sZW5ndGggPT09IDIpIHtcclxuICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnBvcCgpO1xyXG4gICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMucHVzaCh0aGlzLnRlbXBGYW1pbGllc1swXSk7XHJcbiAgICAgICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIHRoaXMudGVtcEZhbWlsaWVzWzBdLm1lbWJlcnMpIHtcclxuICAgICAgICAgICAgbWVtYmVyLnNldEZhbWlseSh0aGlzLnRlbXBGYW1pbGllc1swXSk7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgaWYgKHRoaXMudGVtcEZhbWlsaWVzWzFdICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKHRoaXMudGVtcEZhbWlsaWVzWzFdKTtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBtZW1iZXIgb2YgdGhpcy50ZW1wRmFtaWxpZXNbMV0ubWVtYmVycykge1xyXG4gICAgICAgICAgICAgICBtZW1iZXIuc2V0RmFtaWx5KHRoaXMudGVtcEZhbWlsaWVzWzFdKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICB9XHJcbiAgICAgICAgIHRoaXMudGVtcEZhbWlsaWVzID0gW107XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgLyoqXHJcbiAgICAqIFNob3dzIHRoZSBkcm9wIHpvbmUgZmFtaWx5IG9mIHRoZSBkcm9wIHpvbmUgaW5kaWNhdGVkIGJ5IGBjb29yZGluYXRlc2AuXHJcbiAgICAqL1xyXG4gICBwdWJsaWMgc2hvd0Ryb3Bab25lRmFtaWx5KFxyXG4gICAgICAvKiogTm90ZTogdGhpcyBkcm9wIHpvbmUgbWF5IG5vdCBleGlzdCBpbiB0aGUgZHJvcFpvbmVJbnZlbnRvcnk7IHdlIGhhdmUgdG8gc2VhcmNoIHRoZSBpbnZlbnRvcnkgYmFzZWQgb24gaXRzIGxvY2F0aW9uICovXHJcbiAgICAgIGRyb3Bab25lOiBEcm9wWm9uZSxcclxuICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgICBqb2luRmFtaWxpZXM/OiBib29sZWFuO1xyXG4gICAgICAgICBhY3RpdmF0ZUxvd2VzdEluc3RlYWRPZkZvdW5kZXI/OiBib29sZWFuO1xyXG4gICAgICB9ID0geyBqb2luRmFtaWxpZXM6IGZhbHNlLCBhY3RpdmF0ZUxvd2VzdEluc3RlYWRPZkZvdW5kZXI6IGZhbHNlIH1cclxuICAgKTogdm9pZCB7XHJcbiAgICAgIGlmIChcclxuICAgICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZSAhPT0gbnVsbCAmJlxyXG4gICAgICAgICBEcm9wWm9uZS5kcm9wWm9uZUxvY2F0aW9uc0FyZUVxdWFsKHRoaXMuYWN0aXZlRHJvcFpvbmUsIGRyb3Bab25lKVxyXG4gICAgICApIHtcclxuICAgICAgICAgLy9BbHJlYWR5IHNob3dpbmcgdGhlIGZhbWlseSB3aXRoIHRoZSBhcHByb3ByaWF0ZSBhY3RpdmUgZHJvcCB6b25lXHJcbiAgICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy52aXNpYmxlRmFtaWx5ICE9PSBudWxsIHx8IHRoaXMuYWN0aXZlRHJvcFpvbmUgIT09IG51bGwpIHtcclxuICAgICAgICAgdGhpcy5jbGVhclZpc2libGVab25lcygpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IHRhcmdldCA9IHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkuZmluZCgoem9uZSkgPT5cclxuICAgICAgICAgRHJvcFpvbmUuZHJvcFpvbmVMb2NhdGlvbnNBcmVFcXVhbCh6b25lLCBkcm9wWm9uZSlcclxuICAgICAgKTtcclxuICAgICAgaWYgKHRhcmdldCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICAgICAgYENvdWxkIG5vdCBmaW5kIGRyb3Agem9uZSB0byBzaG93LiBsb2NhdGlvbjogJHtKU09OLnN0cmluZ2lmeShcclxuICAgICAgICAgICAgICAgZHJvcFpvbmUuZ2V0TG9jYXRpb24oKVxyXG4gICAgICAgICAgICApfWBcclxuICAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBmYW1pbHkgPSB0YXJnZXQuZ2V0RmFtaWx5KCk7XHJcbiAgICAgIGlmIChvcHRpb25zLmpvaW5GYW1pbGllcyA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICBjb25zdCBsb2NhdGlvbjEgPSBkcm9wWm9uZS5nZXRMb2NhdGlvbigpO1xyXG4gICAgICAgICBjb25zdCBsb2NhdGlvbjIgPSBuZXcgRHJvcFpvbmVMb2NhdGlvbihcclxuICAgICAgICAgICAgWy4uLmxvY2F0aW9uMS5wYXJlbnRDb29yZGluYXRlc10sXHJcbiAgICAgICAgICAgIGxvY2F0aW9uMS5pbnNlcnRJbmRleCArIDFcclxuICAgICAgICAgKTtcclxuICAgICAgICAgY29uc3QgdGFyZ2V0MiA9IHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkuZmluZCgoem9uZSkgPT5cclxuICAgICAgICAgICAgRHJvcFpvbmUuZHJvcFpvbmVMb2NhdGlvbnNBcmVFcXVhbCh6b25lLCBsb2NhdGlvbjIpXHJcbiAgICAgICAgICk7XHJcbiAgICAgICAgIGlmICh0YXJnZXQyID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgZHJvcCB6b25lIHRvIHNob3dcIik7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgY29uc3QgZmFtaWx5MiA9IHRhcmdldDIuZ2V0RmFtaWx5KCk7XHJcbiAgICAgICAgIGlmIChmYW1pbHkgPT09IHVuZGVmaW5lZCB8fCBmYW1pbHkyID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZmFtaWx5XCIpO1xyXG4gICAgICAgICB9XHJcbiAgICAgICAgIGNvbnN0IG5ld0ZhbWlseSA9IHtcclxuICAgICAgICAgICAgZm91bmRlcjogZmFtaWx5LmZvdW5kZXIsXHJcbiAgICAgICAgICAgIG1lbWJlcnM6IFsuLi5mYW1pbHkubWVtYmVyc11cclxuICAgICAgICAgfTtcclxuICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUoZmFtaWx5LmZvdW5kZXIsIHRydWUpO1xyXG4gICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiBmYW1pbHkubWVtYmVycy5zb3J0KHNvcnRGYW1pbHkpKSB7XHJcbiAgICAgICAgICAgIG1lbWJlci5zZXRGYW1pbHkobmV3RmFtaWx5KTtcclxuICAgICAgICAgICAgaWYgKG1lbWJlciAhPT0gZmFtaWx5LmZvdW5kZXIpIHtcclxuICAgICAgICAgICAgICAgaWYgKHRoaXMuYWN0aXZlRHJvcFpvbmUgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgLy9GYWlsZWQgdG8gYWN0aXZhdGUgYSB6b25lIHNvIGZhciwgc28gYWN0aXZhdGUgdGhpcyBvbmUgaW5zdGVhZFxyXG4gICAgICAgICAgICAgICAgICB0aGlzLnNob3dEcm9wWm9uZShtZW1iZXIsIHRydWUpO1xyXG4gICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLnNob3dEcm9wWm9uZShtZW1iZXIpO1xyXG4gICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgfVxyXG4gICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiBmYW1pbHkyLm1lbWJlcnMpIHtcclxuICAgICAgICAgICAgbWVtYmVyLnNldEZhbWlseShuZXdGYW1pbHkpO1xyXG4gICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgIG1lbWJlci5nZXRMb2NhdGlvbigpLnBhcmVudENvb3JkaW5hdGVzLmxlbmd0aCA8XHJcbiAgICAgICAgICAgICAgIHRhcmdldDIuZ2V0TG9jYXRpb24oKS5wYXJlbnRDb29yZGluYXRlcy5sZW5ndGhcclxuICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgIG5ld0ZhbWlseS5tZW1iZXJzLnB1c2gobWVtYmVyKTtcclxuICAgICAgICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUobWVtYmVyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICB9XHJcbiAgICAgICAgIC8vVGVtcG9yYXJpbHkgc3RvcmUgdGhlIG9sZCBmYW1pbGllc1xyXG4gICAgICAgICB0aGlzLnRlbXBGYW1pbGllcyA9IFtmYW1pbHksIGZhbWlseTJdO1xyXG4gICAgICAgICAvL1JlbW92ZSB0aGUgb2xkIGZhbWlsaWVzXHJcbiAgICAgICAgIGNvbnN0IGZhbWlseUluZGV4ID0gdGhpcy5kcm9wWm9uZUZhbWlsaWVzLmluZGV4T2YoZmFtaWx5KTtcclxuICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnNwbGljZShmYW1pbHlJbmRleCwgMSk7XHJcbiAgICAgICAgIGNvbnN0IGZhbWlseTJJbmRleCA9IHRoaXMuZHJvcFpvbmVGYW1pbGllcy5pbmRleE9mKGZhbWlseTIpO1xyXG4gICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMuc3BsaWNlKGZhbWlseTJJbmRleCwgMSk7XHJcbiAgICAgICAgIC8vQWRkIHRoZSBuZXcgZmFtaWx5XHJcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKG5ld0ZhbWlseSk7XHJcbiAgICAgICAgIHRoaXMudmlzaWJsZUZhbWlseSA9IG5ld0ZhbWlseTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgaWYgKGZhbWlseSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZhbWlseVwiKTtcclxuICAgICAgICAgfVxyXG4gICAgICAgICB0aGlzLnZpc2libGVGYW1pbHkgPSBmYW1pbHk7XHJcbiAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKGZhbWlseS5mb3VuZGVyLCB0cnVlKTtcclxuICAgICAgICAgaWYgKGZhbWlseS5tZW1iZXJzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBtZW1iZXIgb2YgZmFtaWx5Lm1lbWJlcnMuc29ydChzb3J0RmFtaWx5KSkge1xyXG4gICAgICAgICAgICAgICBpZiAobWVtYmVyICE9PSBmYW1pbHkuZm91bmRlcikge1xyXG4gICAgICAgICAgICAgICAgICBpZiAodGhpcy5hY3RpdmVEcm9wWm9uZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAvL0ZhaWxlZCB0byBhY3RpdmF0ZSBhIHpvbmUgc28gZmFyLCBzbyBhY3RpdmF0ZSB0aGlzIG9uZSBpbnN0ZWFkXHJcbiAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKG1lbWJlciwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKG1lbWJlcik7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIG9wdGlvbnMuYWN0aXZhdGVMb3dlc3RJbnN0ZWFkT2ZGb3VuZGVyID09PSB0cnVlICYmXHJcbiAgICAgICAgIHRoaXMudmlzaWJsZUZhbWlseS5tZW1iZXJzLmxlbmd0aCA+IDFcclxuICAgICAgKSB7XHJcbiAgICAgICAgIGNvbnN0IGxvd2VzdE1lbWJlciA9IFsuLi50aGlzLnZpc2libGVGYW1pbHkubWVtYmVyc11cclxuICAgICAgICAgICAgLnNvcnQoc29ydEZhbWlseSlcclxuICAgICAgICAgICAgLnBvcCgpO1xyXG4gICAgICAgICBpZiAobG93ZXN0TWVtYmVyID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGdldCBsb3dlc3QgbWVtYmVyXCIpO1xyXG4gICAgICAgICB9XHJcbiAgICAgICAgIHRoaXMuc3dhcEFjdGl2ZURyb3Bab25lKGxvd2VzdE1lbWJlcik7XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgcHVibGljIHN3YXBBY3RpdmVEcm9wWm9uZShuZXdBY3RpdmVEcm9wWm9uZTogRHJvcFpvbmUpOiB2b2lkIHtcclxuICAgICAgaWYgKHRoaXMudmlzaWJsZUZhbWlseSA9PT0gbnVsbCkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyB2aXNpYmxlIGZhbWlseSBhdmFpbGFibGUgZm9yIHN3YXBwaW5nXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy52aXNpYmxlRmFtaWx5Lm1lbWJlcnMuZmluZEluZGV4KFxyXG4gICAgICAgICAoZHJvcFpvbmUpID0+IGRyb3Bab25lID09PSBuZXdBY3RpdmVEcm9wWm9uZVxyXG4gICAgICApO1xyXG4gICAgICBpZiAoaW5kZXggPT09IC0xKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImZhaWxlZCB0byBzd2FwIGFjdGl2ZSBkcm9wIHpvbmVcIik7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5zZXRBY3RpdmVEcm9wWm9uZShuZXdBY3RpdmVEcm9wWm9uZSk7XHJcbiAgIH1cclxuXHJcbiAgIHB1YmxpYyB1cGRhdGUoKTogdm9pZCB7XHJcbiAgICAgIHRoaXMudXBkYXRlJC5uZXh0KG51bGwpO1xyXG4gICB9XHJcblxyXG4gICBwcml2YXRlIGFzc2lnbkZhbWlsaWVzKCk6IHZvaWQge1xyXG4gICAgICBjb25zdCBvcnBoYW5ab25lcyA9IFsuLi50aGlzLmRyb3Bab25lSW52ZW50b3J5XTtcclxuICAgICAgY29uc3QgZGVlcGVzdE1lbWJlcnMgPSBvcnBoYW5ab25lc1xyXG4gICAgICAgICAuZmlsdGVyKCh6b25lKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxvY2F0aW9uID0gem9uZS5nZXRMb2NhdGlvbigpO1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICBsb2NhdGlvbi5pbnNlcnRJbmRleCA9PT0gMCAmJlxyXG4gICAgICAgICAgICAgICBsb2NhdGlvbi5wYXJlbnRDb29yZGluYXRlcy5sZW5ndGggPiAwXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgIH0pXHJcbiAgICAgICAgIC5zb3J0KCh2YWx1ZUEsIHZhbHVlQikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBhQ29vcmRpbmF0ZXMgPSB2YWx1ZUEuZ2V0RnVsbEluc2VydENvb3JkaW5hdGVzKCk7XHJcbiAgICAgICAgICAgIGNvbnN0IGJDb29yZGluYXRlcyA9IHZhbHVlQi5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKTtcclxuICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gTWF0aC5tYXgoYUNvb3JkaW5hdGVzLmxlbmd0aCwgYkNvb3JkaW5hdGVzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcclxuICAgICAgICAgICAgICAgaWYgKChhQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKSA+IChiQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKSkge1xyXG4gICAgICAgICAgICAgICAgICByZXR1cm4gLTE7XHJcbiAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgICAgICAgICAgIChhQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKSA8IChiQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKVxyXG4gICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgcmV0dXJuIDE7XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gMDtcclxuICAgICAgICAgfSk7XHJcbiAgICAgIGZvciAoY29uc3QgZHJvcFpvbmUgb2YgZGVlcGVzdE1lbWJlcnMpIHtcclxuICAgICAgICAgaWYgKCFvcnBoYW5ab25lcy5pbmNsdWRlcyhkcm9wWm9uZSkpIHtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgIH1cclxuICAgICAgICAgY29uc3QgZmFtaWx5OiBEcm9wWm9uZUZhbWlseSA9IHtcclxuICAgICAgICAgICAgZm91bmRlcjogZHJvcFpvbmUsXHJcbiAgICAgICAgICAgIG1lbWJlcnM6IFtdXHJcbiAgICAgICAgIH07XHJcbiAgICAgICAgIGRyb3Bab25lLnNldEZhbWlseShmYW1pbHkpO1xyXG4gICAgICAgICAvL1NlZSBpZiB0aGVyZSBhcmUgYW55IG9ycGhhbnMgdGhhdCBiZWxvbmcgdG8gdGhpcyBmYW1pbHkgYW5kIGNsYWltIHRoZW0uXHJcbiAgICAgICAgIGNvbnN0IGN1cnNvciA9IFsuLi5kcm9wWm9uZS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKV07XHJcbiAgICAgICAgIHdoaWxlIChjdXJzb3IubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBjb25zdCBmYW1pbHlNZW1iZXJJbmRleCA9IG9ycGhhblpvbmVzLmZpbmRJbmRleCgoem9uZSkgPT5cclxuICAgICAgICAgICAgICAgYXJyYXlzQXJlRXF1YWwoem9uZS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKSwgY3Vyc29yKVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAoZmFtaWx5TWVtYmVySW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgIGNvbnN0IGZhbWlseU1lbWJlciA9IG9ycGhhblpvbmVzLnNwbGljZShmYW1pbHlNZW1iZXJJbmRleCwgMSlbMF07XHJcbiAgICAgICAgICAgICAgIGZhbWlseS5tZW1iZXJzLnB1c2goZmFtaWx5TWVtYmVyKTtcclxuICAgICAgICAgICAgICAgZmFtaWx5TWVtYmVyLnNldEZhbWlseShmYW1pbHkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGN1cnNvci5wb3AoKTtcclxuICAgICAgICAgICAgY3Vyc29yW2N1cnNvci5sZW5ndGggLSAxXSsrO1xyXG4gICAgICAgICB9XHJcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKGZhbWlseSk7XHJcbiAgICAgIH1cclxuICAgICAgZm9yIChjb25zdCBkcm9wWm9uZSBvZiBvcnBoYW5ab25lcy5maWx0ZXIoXHJcbiAgICAgICAgICh6b25lKSA9PiB6b25lLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpLmxlbmd0aCA9PT0gMVxyXG4gICAgICApKSB7XHJcbiAgICAgICAgIGNvbnN0IGZhbWlseTogRHJvcFpvbmVGYW1pbHkgPSB7XHJcbiAgICAgICAgICAgIGZvdW5kZXI6IGRyb3Bab25lLFxyXG4gICAgICAgICAgICBtZW1iZXJzOiBbZHJvcFpvbmVdXHJcbiAgICAgICAgIH07XHJcbiAgICAgICAgIGRyb3Bab25lLnNldEZhbWlseShmYW1pbHkpO1xyXG4gICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMucHVzaChmYW1pbHkpO1xyXG4gICAgICAgICBvcnBoYW5ab25lcy5zcGxpY2Uob3JwaGFuWm9uZXMuaW5kZXhPZihkcm9wWm9uZSksIDEpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChvcnBoYW5ab25lcy5sZW5ndGggIT09IDApIHtcclxuICAgICAgICAgbGV0IG9ycGhhbnMgPSBcIlwiO1xyXG4gICAgICAgICBmb3IgKGNvbnN0IHpvbmUgb2Ygb3JwaGFuWm9uZXMpIHtcclxuICAgICAgICAgICAgb3JwaGFucyArPSBgJHtKU09OLnN0cmluZ2lmeSh6b25lLmdldExvY2F0aW9uKCkpfSwgYDtcclxuICAgICAgICAgfVxyXG4gICAgICAgICBvcnBoYW5zID0gb3JwaGFucy5zbGljZSgwLCBvcnBoYW5zLmxlbmd0aCAtIDIpO1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgICAgICAgIGBTb21lIHpvbmVzIHdlcmUgbm90IGFzc2lnbmVkIHRvIGEgZmFtaWx5LiBUaGUgb3JwaGFuIHpvbmVzIGhhdmUgdGhlIGZvbGxvd2luZyBsb2NhdGlvbnM6ICR7b3JwaGFuc31gXHJcbiAgICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSBidWlsZEludmVudG9yeSgpIHtcclxuICAgICAgLy9XZSBkbyB0aGlzIGZ1bmt5IHN0cmluZyBhcnJheSBiZWNhdXNlIGl0IGlzIGZhc3RlciB0aGFuIGRvaW5nIGRpcmVjdCBhcnJheSBjb21wYXJpc29uc1xyXG4gICAgICBjb25zdCBpbnZlbnRvcnlDb29yZGluYXRlczogQXJyYXk8c3RyaW5nPiA9IFtdO1xyXG4gICAgICBmb3IgKGNvbnN0IGRyb3Bab25lIG9mIHRoaXMuZHJvcFpvbmVBcmNoaXZlKSB7XHJcbiAgICAgICAgIGNvbnN0IGNvb3JkaW5hdGVzID0gZHJvcFpvbmUuZ2V0RnVsbEluc2VydENvb3JkaW5hdGVzKCkuam9pbihcIixcIik7XHJcbiAgICAgICAgIGlmIChpbnZlbnRvcnlDb29yZGluYXRlcy5pbmNsdWRlcyhjb29yZGluYXRlcykpIHtcclxuICAgICAgICAgICAgZHJvcFpvbmUuaXNSZW5kZXJlZChmYWxzZSk7XHJcbiAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkucHVzaChkcm9wWm9uZSk7XHJcbiAgICAgICAgICAgIGludmVudG9yeUNvb3JkaW5hdGVzLnB1c2goY29vcmRpbmF0ZXMpO1xyXG4gICAgICAgICAgICBkcm9wWm9uZS5pc1JlbmRlcmVkKHRydWUpO1xyXG4gICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSBzZXRBY3RpdmVEcm9wWm9uZShkcm9wWm9uZTogRHJvcFpvbmUgfCBudWxsKTogdm9pZCB7XHJcbiAgICAgIGlmICh0aGlzLmFjdGl2ZURyb3Bab25lICE9PSBudWxsKSB7XHJcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUuaXNBY3RpdmUoZmFsc2UpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUgPSBkcm9wWm9uZTtcclxuICAgICAgaWYgKFxyXG4gICAgICAgICB0aGlzLmFjdGl2ZURyb3Bab25lICE9PSBudWxsICYmXHJcbiAgICAgICAgIHRoaXMuZHJhZ1N0YXRlU2VydmljZS5nZXRTdGF0ZSgpICE9PSBcImRyb3BwYWJsZVwiXHJcbiAgICAgICkge1xyXG4gICAgICAgICB0aGlzLmRyYWdTdGF0ZVNlcnZpY2UuZHJvcHBhYmxlKCk7XHJcbiAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUgPT09IG51bGwgJiZcclxuICAgICAgICAgdGhpcy5kcmFnU3RhdGVTZXJ2aWNlLmdldFN0YXRlKCkgPT09IFwiZHJvcHBhYmxlXCJcclxuICAgICAgKSB7XHJcbiAgICAgICAgIHRoaXMuZHJhZ1N0YXRlU2VydmljZS5ub3REcm9wcGFibGUoKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy5hY3RpdmVEcm9wWm9uZSAhPT0gbnVsbCkge1xyXG4gICAgICAgICB0aGlzLmFjdGl2ZURyb3Bab25lLmlzQWN0aXZlKHRydWUpO1xyXG4gICAgICB9XHJcbiAgIH1cclxuXHJcbiAgIHByaXZhdGUgc2hvd0Ryb3Bab25lKGRyb3Bab25lOiBEcm9wWm9uZSwgYWN0aXZlID0gZmFsc2UpOiBib29sZWFuIHtcclxuICAgICAgaWYgKHRoaXMudHJlZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkRyb3Bab25lU2VydmljZSBub3QgaW5pdGlhbGl6ZWRcIik7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKCF0aGlzLnpvbmVJc0FsbG93ZWQoZHJvcFpvbmUpKSB7XHJcbiAgICAgICAgIC8vVXNlciBzZXR0aW5ncyBpbmRpY2F0ZSB0byBza2lwIHRoaXMgZHJvcCB6b25lXHJcbiAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBwYXJlbnQgPSB0aGlzLnRyZWUuZmluZEJ5Q29vcmRpbmF0ZXMoXHJcbiAgICAgICAgIGRyb3Bab25lLmdldExvY2F0aW9uKCkucGFyZW50Q29vcmRpbmF0ZXNcclxuICAgICAgKTtcclxuICAgICAgaWYgKHBhcmVudCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkJhZCBmYW1pbHkgbWVtYmVyXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGRyb3Bab25lLmlzVmlzaWJsZSh0cnVlKTtcclxuICAgICAgaWYgKGFjdGl2ZSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICB0aGlzLnNldEFjdGl2ZURyb3Bab25lKGRyb3Bab25lKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgfVxyXG5cclxuICAgcHJpdmF0ZSB1cGRhdGVEcm9wWm9uZXMoKTogdm9pZCB7XHJcbiAgICAgIHRoaXMucmVzZXQoKTtcclxuICAgICAgdGhpcy5idWlsZEludmVudG9yeSgpO1xyXG4gICAgICB0aGlzLmFzc2lnbkZhbWlsaWVzKCk7XHJcbiAgIH1cclxuXHJcbiAgIHByaXZhdGUgem9uZUlzQWxsb3dlZChkcm9wWm9uZTogRHJvcFpvbmUpOiBib29sZWFuIHtcclxuICAgICAgaWYgKHRoaXMudHJlZU9wdGlvbnMgPT09IHVuZGVmaW5lZCB8fCB0aGlzLnRyZWUgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkcm9wWm9uZVNlcnZpY2Ugbm90IGluaXRpYWxpemVkXCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmRyYWdTdGF0ZVNlcnZpY2UuZ2V0RGF0YSgpO1xyXG4gICAgICBpZiAoZGF0YSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IGdldCBkcmFnZ2VkIG5vZGVcIik7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgZHJvcFpvbmVQYXJlbnQgPSB0aGlzLnRyZWUuZmluZEJ5Q29vcmRpbmF0ZXMoXHJcbiAgICAgICAgIGRyb3Bab25lLmdldExvY2F0aW9uKCkucGFyZW50Q29vcmRpbmF0ZXNcclxuICAgICAgKTtcclxuICAgICAgaWYgKGRyb3Bab25lUGFyZW50ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGdldCBkcm9wIHpvbmUgcGFyZW50XCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGRyb3Bab25lSW5kZXggPSBkcm9wWm9uZS5nZXRMb2NhdGlvbigpLmluc2VydEluZGV4O1xyXG4gICAgICBpZiAoZHJvcFpvbmVJbmRleCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBnZXQgZHJvcCB6b25lIGluZGV4XCIpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGRyYWdnZWROb2RlID0gZGF0YS5icmFuY2g7XHJcbiAgICAgIGlmIChcclxuICAgICAgICAgdGhpcy50cmVlT3B0aW9ucy5hbGxvd0Ryb3AoXHJcbiAgICAgICAgICAgIGRyYWdnZWROb2RlLmRhdGEsXHJcbiAgICAgICAgICAgIGRyb3Bab25lUGFyZW50LmRhdGEgYXMgTGltYmxlVHJlZU5vZGUsXHJcbiAgICAgICAgICAgIGRyb3Bab25lSW5kZXhcclxuICAgICAgICAgKVxyXG4gICAgICApIHtcclxuICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICB9XHJcbn1cclxuIl19