@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
@@ -0,0 +1,376 @@
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
+ const aCoordinates = valueA.getFullInsertCoordinates();
235
+ const bCoordinates = valueB.getFullInsertCoordinates();
236
+ const length = Math.max(aCoordinates.length, bCoordinates.length);
237
+ for (let index = 0; index < length; index++) {
238
+ if ((aCoordinates[index] ?? -1) > (bCoordinates[index] ?? -1)) {
239
+ return -1;
240
+ }
241
+ else if ((aCoordinates[index] ?? -1) < (bCoordinates[index] ?? -1)) {
242
+ return 1;
243
+ }
244
+ }
245
+ return 0;
246
+ });
247
+ for (const dropZone of deepestMembers) {
248
+ if (!orphanZones.includes(dropZone)) {
249
+ continue;
250
+ }
251
+ const family = {
252
+ founder: dropZone,
253
+ members: []
254
+ };
255
+ dropZone.setFamily(family);
256
+ //See if there are any orphans that belong to this family and claim them.
257
+ const cursor = [...dropZone.getFullInsertCoordinates()];
258
+ while (cursor.length > 0) {
259
+ const familyMemberIndex = orphanZones.findIndex((zone) => arraysAreEqual(zone.getFullInsertCoordinates(), cursor));
260
+ if (familyMemberIndex !== -1) {
261
+ const familyMember = orphanZones.splice(familyMemberIndex, 1)[0];
262
+ family.members.push(familyMember);
263
+ familyMember.setFamily(family);
264
+ }
265
+ cursor.pop();
266
+ cursor[cursor.length - 1]++;
267
+ }
268
+ this.dropZoneFamilies.push(family);
269
+ }
270
+ for (const dropZone of orphanZones.filter((zone) => zone.getFullInsertCoordinates().length === 1)) {
271
+ const family = {
272
+ founder: dropZone,
273
+ members: [dropZone]
274
+ };
275
+ dropZone.setFamily(family);
276
+ this.dropZoneFamilies.push(family);
277
+ orphanZones.splice(orphanZones.indexOf(dropZone), 1);
278
+ }
279
+ if (orphanZones.length !== 0) {
280
+ let orphans = "";
281
+ for (const zone of orphanZones) {
282
+ orphans += `${JSON.stringify(zone.getLocation())}, `;
283
+ }
284
+ orphans = orphans.slice(0, orphans.length - 2);
285
+ throw new Error(`Some zones were not assigned to a family. The orphan zones have the following locations: ${orphans}`);
286
+ }
287
+ }
288
+ buildInventory() {
289
+ //We do this funky string array because it is faster than doing direct array comparisons
290
+ const inventoryCoordinates = [];
291
+ for (const dropZone of this.dropZoneArchive) {
292
+ const coordinates = dropZone.getFullInsertCoordinates().join(",");
293
+ if (inventoryCoordinates.includes(coordinates)) {
294
+ dropZone.isRendered(false);
295
+ }
296
+ else {
297
+ this.dropZoneInventory.push(dropZone);
298
+ inventoryCoordinates.push(coordinates);
299
+ dropZone.isRendered(true);
300
+ }
301
+ }
302
+ }
303
+ setActiveDropZone(dropZone) {
304
+ if (this.activeDropZone !== null) {
305
+ this.activeDropZone.isActive(false);
306
+ }
307
+ this.activeDropZone = dropZone;
308
+ if (this.activeDropZone !== null &&
309
+ this.dragStateService.getState() !== "droppable") {
310
+ this.dragStateService.droppable();
311
+ }
312
+ else if (this.activeDropZone === null &&
313
+ this.dragStateService.getState() === "droppable") {
314
+ this.dragStateService.notDroppable();
315
+ }
316
+ if (this.activeDropZone !== null) {
317
+ this.activeDropZone.isActive(true);
318
+ }
319
+ }
320
+ showDropZone(dropZone, active = false) {
321
+ if (this.tree === undefined) {
322
+ throw new Error("DropZoneService not initialized");
323
+ }
324
+ if (!this.zoneIsAllowed(dropZone)) {
325
+ //User settings indicate to skip this drop zone
326
+ return false;
327
+ }
328
+ const parent = this.tree.findByCoordinates(dropZone.getLocation().parentCoordinates);
329
+ if (parent === undefined) {
330
+ throw new Error("Bad family member");
331
+ }
332
+ dropZone.isVisible(true);
333
+ if (active === true) {
334
+ this.setActiveDropZone(dropZone);
335
+ }
336
+ return true;
337
+ }
338
+ updateDropZones() {
339
+ this.reset();
340
+ this.buildInventory();
341
+ this.assignFamilies();
342
+ }
343
+ zoneIsAllowed(dropZone) {
344
+ if (this.treeOptions === undefined || this.tree === undefined) {
345
+ throw new Error("dropZoneService not initialized");
346
+ }
347
+ const data = this.dragStateService.getData();
348
+ if (data === undefined) {
349
+ throw new Error("Can't get dragged node");
350
+ }
351
+ const parentCoordinates = dropZone.getLocation().parentCoordinates;
352
+ const dropZoneParent = this.tree.findByCoordinates(parentCoordinates);
353
+ if (dropZoneParent === undefined) {
354
+ throw new Error("Could not get drop zone parent");
355
+ }
356
+ if (parentCoordinates.length > 0 &&
357
+ !isNestingAllowed(this.treeOptions, dropZoneParent.data)) {
358
+ return false;
359
+ }
360
+ const dropZoneIndex = dropZone.getLocation().insertIndex;
361
+ if (dropZoneIndex === undefined) {
362
+ throw new Error("Could not get drop zone index");
363
+ }
364
+ const draggedNode = data.branch;
365
+ if (!this.treeOptions.allowDrop(draggedNode.data, dropZoneParent.data, dropZoneIndex)) {
366
+ return false;
367
+ }
368
+ return true;
369
+ }
370
+ }
371
+ DropZoneService.ɵfac = function DropZoneService_Factory(t) { return new (t || DropZoneService)(i0.ɵɵinject(i1.DragStateService), i0.ɵɵinject(i2.TreeConstructionStatus)); };
372
+ DropZoneService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DropZoneService, factory: DropZoneService.ɵfac });
373
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropZoneService, [{
374
+ type: Injectable
375
+ }], function () { return [{ type: i1.DragStateService }, { type: i2.TreeConstructionStatus }]; }, null); })();
376
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcC16b25lLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saW1ibGUtdHJlZS9zcmMvbGliL2xpbWJsZS10cmVlLXJvb3QvZHJvcC16b25lLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzNELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRS9CLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7O0FBU3ZELFNBQVMsVUFBVSxDQUFDLE9BQWlCLEVBQUUsT0FBaUI7SUFDckQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDeEQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDeEQsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUU7UUFDNUMsT0FBTyxDQUFDLENBQUMsQ0FBQztLQUNaO0lBQ0QsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUU7UUFDNUMsT0FBTyxDQUFDLENBQUM7S0FDWDtJQUNELE9BQU8sQ0FBQyxDQUFDO0FBQ1osQ0FBQztBQUdELE1BQU0sT0FBTyxlQUFlO0lBYXpCLFlBQ29CLGdCQUFrQyxFQUNuRCxzQkFBOEM7UUFEN0IscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUduRCxJQUFJLENBQUMsZUFBZSxHQUFHLElB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IkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IEJyYW5jaCwgQnJhbmNoQ29vcmRpbmF0ZXMgfSBmcm9tIFwiLi4vY2xhc3Nlcy9CcmFuY2hcIjtcbmltcG9ydCB7IERyYWdTdGF0ZVNlcnZpY2UgfSBmcm9tIFwiLi4vc2luZ2xldG9ucy9kcmFnLXN0YXRlLnNlcnZpY2VcIjtcbmltcG9ydCB0eXBlIHsgTGltYmxlVHJlZU5vZGUsIFByb2Nlc3NlZE9wdGlvbnMgfSBmcm9tIFwiLi90cmVlLnNlcnZpY2VcIjtcbmltcG9ydCB7IGFycmF5c0FyZUVxdWFsLCBpc05lc3RpbmdBbGxvd2VkIH0gZnJvbSBcIi4uL3V0aWxcIjtcbmltcG9ydCB7IERyb3Bab25lIH0gZnJvbSBcIi4uL2NsYXNzZXMvRHJvcFpvbmVcIjtcbmltcG9ydCB7IERyb3Bab25lTG9jYXRpb24gfSBmcm9tIFwiLi4vY2xhc3Nlcy9Ecm9wWm9uZUxvY2F0aW9uXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IFRyZWVDb25zdHJ1Y3Rpb25TdGF0dXMgfSBmcm9tIFwiLi90cmVlLWNvbnN0cnVjdGlvbi1zdGF0dXMuc2VydmljZVwiO1xuaW1wb3J0IHsgZGVib3VuY2UsIGZpbHRlciwgdGFwIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHJvcFpvbmVGYW1pbHkge1xuICAgLyoqIFRoZSBkZWVwZXN0IG1lbWJlciBvZiB0aGUgZmFtaWx5ICovXG4gICBmb3VuZGVyOiBEcm9wWm9uZTtcbiAgIC8qKiBBbGwgdGhlIGRyb3Agem9uZXMgdGhhdCBiZWxvbmcgdG8gdGhpcyBmYW1pbHkgKi9cbiAgIG1lbWJlcnM6IEFycmF5PERyb3Bab25lPjtcbn1cblxuZnVuY3Rpb24gc29ydEZhbWlseShtZW1iZXJBOiBEcm9wWm9uZSwgbWVtYmVyQjogRHJvcFpvbmUpIHtcbiAgIGNvbnN0IGFDb29yZGluYXRlcyA9IG1lbWJlckEuZ2V0RnVsbEluc2VydENvb3JkaW5hdGVzKCk7XG4gICBjb25zdCBiQ29vcmRpbmF0ZXMgPSBtZW1iZXJCLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpO1xuICAgaWYgKGFDb29yZGluYXRlcy5sZW5ndGggPiBiQ29vcmRpbmF0ZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gLTE7XG4gICB9XG4gICBpZiAoYUNvb3JkaW5hdGVzLmxlbmd0aCA8IGJDb29yZGluYXRlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiAxO1xuICAgfVxuICAgcmV0dXJuIDA7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBEcm9wWm9uZVNlcnZpY2Uge1xuICAgcHJpdmF0ZSByZWFkb25seSBkcm9wWm9uZUFyY2hpdmU6IFNldDxEcm9wWm9uZT47XG4gICBwcml2YXRlIHJlYWRvbmx5IGRyb3Bab25lSW52ZW50b3J5OiBBcnJheTxEcm9wWm9uZT47XG4gICBwcml2YXRlIHJlYWRvbmx5IGRyb3Bab25lRmFtaWxpZXM6IEFycmF5PERyb3Bab25lRmFtaWx5PjtcbiAgIHByaXZhdGUgdmlzaWJsZUZhbWlseTogRHJvcFpvbmVGYW1pbHkgfCBudWxsO1xuICAgcHJpdmF0ZSBhY3RpdmVEcm9wWm9uZTogRHJvcFpvbmUgfCBudWxsO1xuICAgcHJpdmF0ZSB0cmVlOiBCcmFuY2g8YW55PiB8IHVuZGVmaW5lZDtcbiAgIHByaXZhdGUgdHJlZU9wdGlvbnM6IFByb2Nlc3NlZE9wdGlvbnMgfCB1bmRlZmluZWQ7XG4gICBwcml2YXRlIHRlbXBGYW1pbGllczpcbiAgICAgIHwgcmVhZG9ubHkgW0Ryb3Bab25lRmFtaWx5LCBEcm9wWm9uZUZhbWlseSB8IG51bGxdXG4gICAgICB8IHJlYWRvbmx5IFtdO1xuICAgcHJpdmF0ZSByZWFkb25seSB1cGRhdGUkOiBTdWJqZWN0PG51bGw+O1xuXG4gICBjb25zdHJ1Y3RvcihcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgZHJhZ1N0YXRlU2VydmljZTogRHJhZ1N0YXRlU2VydmljZSxcbiAgICAgIHRyZWVDb25zdHJ1Y3Rpb25TdGF0dXM6IFRyZWVDb25zdHJ1Y3Rpb25TdGF0dXNcbiAgICkge1xuICAgICAgdGhpcy5kcm9wWm9uZUFyY2hpdmUgPSBuZXcgU2V0KCk7XG4gICAgICB0aGlzLmRyb3Bab25lSW52ZW50b3J5ID0gW107XG4gICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMgPSBbXTtcbiAgICAgIHRoaXMudmlzaWJsZUZhbWlseSA9IG51bGw7XG4gICAgICB0aGlzLmFjdGl2ZURyb3Bab25lID0gbnVsbDtcbiAgICAgIHRoaXMudGVtcEZhbWlsaWVzID0gW107XG4gICAgICB0aGlzLnNldEFjdGl2ZURyb3Bab25lKG51bGwpO1xuICAgICAgbGV0IHRyZWVJc1N0YWJsZSA9IGZhbHNlO1xuICAgICAgY29uc3QgdHJlZUlzU3RhYmxlJCA9IHRyZWVDb25zdHJ1Y3Rpb25TdGF0dXMuc3RhYmxlJC5waXBlKFxuICAgICAgICAgdGFwKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgdHJlZUlzU3RhYmxlID0gdmFsdWU7XG4gICAgICAgICB9KSxcbiAgICAgICAgIGZpbHRlcigodmFsdWUpID0+IHZhbHVlID09PSB0cnVlKVxuICAgICAgKTtcbiAgICAgIHRoaXMudXBkYXRlJCA9IG5ldyBTdWJqZWN0KCk7XG4gICAgICB0aGlzLnVwZGF0ZSRcbiAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgZGVib3VuY2UoKCkgPT4ge1xuICAgICAgICAgICAgICAgaWYgKHRyZWVJc1N0YWJsZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgLy9JZiB0cmVlIGlzIHN0YWJsZSwgY29udGludWUgcmlnaHQgYXdheVxuICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgLy9JZiB0cmVlIGlzIG5vdCBzdGFibGUsIHdhaXQgZm9yIGl0IHRvIGJlY29tZSBzby5cbiAgICAgICAgICAgICAgIHJldHVybiB0cmVlSXNTdGFibGUkO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgIClcbiAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICB0aGlzLnVwZGF0ZURyb3Bab25lcygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICB9KTtcbiAgIH1cblxuICAgcHVibGljIGFkZERyb3Bab25lKG5ld0Ryb3Bab25lOiBEcm9wWm9uZSk6IHZvaWQge1xuICAgICAgdGhpcy5kcm9wWm9uZUFyY2hpdmUuYWRkKG5ld0Ryb3Bab25lKTtcbiAgIH1cblxuICAgLyoqIGhpZGVzIGFsbCBkcm9wIHpvbmVzICovXG4gICBwdWJsaWMgY2xlYXJWaXNpYmxlWm9uZXMoKTogdm9pZCB7XG4gICAgICBpZiAodGhpcy52aXNpYmxlRmFtaWx5ICE9PSBudWxsKSB7XG4gICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiB0aGlzLnZpc2libGVGYW1pbHkubWVtYmVycykge1xuICAgICAgICAgICAgbWVtYmVyLmlzVmlzaWJsZShmYWxzZSk7XG4gICAgICAgICB9XG4gICAgICAgICB0aGlzLnZpc2libGVGYW1pbHkgPSBudWxsO1xuICAgICAgfVxuICAgICAgdGhpcy5zZXRBY3RpdmVEcm9wWm9uZShudWxsKTtcbiAgIH1cblxuICAgcHVibGljIGdldEFjdGl2ZURyb3Bab25lKCk6IERyb3Bab25lU2VydmljZVtcImFjdGl2ZURyb3Bab25lXCJdIHtcbiAgICAgIHJldHVybiB0aGlzLmFjdGl2ZURyb3Bab25lO1xuICAgfVxuXG4gICBwdWJsaWMgZ2V0RHJvcFpvbmUoY29vcmRpbmF0ZXM6IEJyYW5jaENvb3JkaW5hdGVzKTogRHJvcFpvbmUgfCB1bmRlZmluZWQge1xuICAgICAgY29uc3QgcGFyZW50ID0gWy4uLmNvb3JkaW5hdGVzXTtcbiAgICAgIHBhcmVudC5wb3AoKTtcbiAgICAgIGNvbnN0IGluZGV4ID0gY29vcmRpbmF0ZXNbY29vcmRpbmF0ZXMubGVuZ3RoIC0gMV07XG4gICAgICBjb25zdCBsb2NhdGlvbiA9IG5ldyBEcm9wWm9uZUxvY2F0aW9uKHBhcmVudCwgaW5kZXgpO1xuICAgICAgcmV0dXJuIHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkuZmluZCgoZHJvcFpvbmUpID0+XG4gICAgICAgICBEcm9wWm9uZS5kcm9wWm9uZUxvY2F0aW9uc0FyZUVxdWFsKGRyb3Bab25lLCBsb2NhdGlvbilcbiAgICAgICk7XG4gICB9XG5cbiAgIHB1YmxpYyBpbml0KHRyZWU6IEJyYW5jaDxhbnk+LCB0cmVlT3B0aW9uczogUHJvY2Vzc2VkT3B0aW9ucyk6IHZvaWQge1xuICAgICAgdGhpcy50cmVlID0gdHJlZTtcbiAgICAgIHRoaXMudHJlZU9wdGlvbnMgPSB0cmVlT3B0aW9ucztcbiAgICAgIHRoaXMudXBkYXRlKCk7XG4gICB9XG5cbiAgIHB1YmxpYyByZW1vdmVEcm9wWm9uZShkcm9wWm9uZTogRHJvcFpvbmUpIHtcbiAgICAgIHRoaXMuZHJvcFpvbmVBcmNoaXZlLmRlbGV0ZShkcm9wWm9uZSk7XG4gICB9XG5cbiAgIC8qKiBoaWRlcyBhbGwgZHJvcCB6b25lcywgZGVsZXRlcyBhbGwgdGhlIGZhbWlseSBhc3NpZ25tZW50cyxcbiAgICAqIGFuZCBlbXB0aWVzIHRoZSBkcm9wWm9uZUludmVudG9yeVxuICAgICovXG4gICBwdWJsaWMgcmVzZXQoKTogdm9pZCB7XG4gICAgICB0aGlzLmNsZWFyVmlzaWJsZVpvbmVzKCk7XG4gICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMubGVuZ3RoID0gMDtcbiAgICAgIHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkubGVuZ3RoID0gMDtcbiAgIH1cblxuICAgLyoqXG4gICAgKiBSZXN0b3JlcyB0aGUgc2VydmljZSB0byBpdHMgaW5pdGlhbCBzdGF0ZTogaGlkZXMgYWxsIGRyb3Agem9uZXMsXG4gICAgKiBkZWxldGVzIGFsbCB0aGUgZmFtaWx5IGFzc2lnbm1lbnRzLCBhbmQgZW1wdGllcyB0aGUgZHJvcFpvbmVJbnZlbnRvcnlcbiAgICAqIGFuZCBkcm9wWm9uZUFyY2hpdmUuXG4gICAgKi9cbiAgIHB1YmxpYyByZXN0YXJ0KCk6IHZvaWQge1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgdGhpcy5kcm9wWm9uZUFyY2hpdmUuY2xlYXIoKTtcbiAgIH1cblxuICAgcHVibGljIHJlc3RvcmVGYW1pbGllcygpOiB2b2lkIHtcbiAgICAgIGlmICh0aGlzLnRlbXBGYW1pbGllcy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wb3AoKTtcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKHRoaXMudGVtcEZhbWlsaWVzWzBdKTtcbiAgICAgICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIHRoaXMudGVtcEZhbWlsaWVzWzBdLm1lbWJlcnMpIHtcbiAgICAgICAgICAgIG1lbWJlci5zZXRGYW1pbHkodGhpcy50ZW1wRmFtaWxpZXNbMF0pO1xuICAgICAgICAgfVxuICAgICAgICAgaWYgKHRoaXMudGVtcEZhbWlsaWVzWzFdICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMucHVzaCh0aGlzLnRlbXBGYW1pbGllc1sxXSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiB0aGlzLnRlbXBGYW1pbGllc1sxXS5tZW1iZXJzKSB7XG4gICAgICAgICAgICAgICBtZW1iZXIuc2V0RmFtaWx5KHRoaXMudGVtcEZhbWlsaWVzWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgIH1cbiAgICAgICAgIHRoaXMudGVtcEZhbWlsaWVzID0gW107XG4gICAgICB9XG4gICB9XG5cbiAgIC8qKlxuICAgICogU2hvd3MgdGhlIGRyb3Agem9uZSBmYW1pbHkgb2YgdGhlIGRyb3Agem9uZSBpbmRpY2F0ZWQgYnkgYGNvb3JkaW5hdGVzYC5cbiAgICAqL1xuICAgcHVibGljIHNob3dEcm9wWm9uZUZhbWlseShcbiAgICAgIC8qKiBOb3RlOiB0aGlzIGRyb3Agem9uZSBtYXkgbm90IGV4aXN0IGluIHRoZSBkcm9wWm9uZUludmVudG9yeTsgd2UgaGF2ZSB0byBzZWFyY2ggdGhlIGludmVudG9yeSBiYXNlZCBvbiBpdHMgbG9jYXRpb24gKi9cbiAgICAgIGRyb3Bab25lOiBEcm9wWm9uZSxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgIGpvaW5GYW1pbGllcz86IGJvb2xlYW47XG4gICAgICAgICBhY3RpdmF0ZUxvd2VzdEluc3RlYWRPZkZvdW5kZXI/OiBib29sZWFuO1xuICAgICAgfSA9IHsgam9pbkZhbWlsaWVzOiBmYWxzZSwgYWN0aXZhdGVMb3dlc3RJbnN0ZWFkT2ZGb3VuZGVyOiBmYWxzZSB9XG4gICApOiB2b2lkIHtcbiAgICAgIGlmIChcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUgIT09IG51bGwgJiZcbiAgICAgICAgIERyb3Bab25lLmRyb3Bab25lTG9jYXRpb25zQXJlRXF1YWwodGhpcy5hY3RpdmVEcm9wWm9uZSwgZHJvcFpvbmUpXG4gICAgICApIHtcbiAgICAgICAgIC8vQWxyZWFkeSBzaG93aW5nIHRoZSBmYW1pbHkgd2l0aCB0aGUgYXBwcm9wcmlhdGUgYWN0aXZlIGRyb3Agem9uZVxuICAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMudmlzaWJsZUZhbWlseSAhPT0gbnVsbCB8fCB0aGlzLmFjdGl2ZURyb3Bab25lICE9PSBudWxsKSB7XG4gICAgICAgICB0aGlzLmNsZWFyVmlzaWJsZVpvbmVzKCk7XG4gICAgICB9XG4gICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLmRyb3Bab25lSW52ZW50b3J5LmZpbmQoKHpvbmUpID0+XG4gICAgICAgICBEcm9wWm9uZS5kcm9wWm9uZUxvY2F0aW9uc0FyZUVxdWFsKHpvbmUsIGRyb3Bab25lKVxuICAgICAgKTtcbiAgICAgIGlmICh0YXJnZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYENvdWxkIG5vdCBmaW5kIGRyb3Agem9uZSB0byBzaG93LiBsb2NhdGlvbjogJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgIGRyb3Bab25lLmdldExvY2F0aW9uKClcbiAgICAgICAgICAgICl9YFxuICAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZhbWlseSA9IHRhcmdldC5nZXRGYW1pbHkoKTtcbiAgICAgIGlmIChvcHRpb25zLmpvaW5GYW1pbGllcyA9PT0gdHJ1ZSkge1xuICAgICAgICAgY29uc3QgbG9jYXRpb24xID0gZHJvcFpvbmUuZ2V0TG9jYXRpb24oKTtcbiAgICAgICAgIGNvbnN0IGxvY2F0aW9uMiA9IG5ldyBEcm9wWm9uZUxvY2F0aW9uKFxuICAgICAgICAgICAgWy4uLmxvY2F0aW9uMS5wYXJlbnRDb29yZGluYXRlc10sXG4gICAgICAgICAgICBsb2NhdGlvbjEuaW5zZXJ0SW5kZXggKyAxXG4gICAgICAgICApO1xuICAgICAgICAgY29uc3QgdGFyZ2V0MiA9IHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkuZmluZCgoem9uZSkgPT5cbiAgICAgICAgICAgIERyb3Bab25lLmRyb3Bab25lTG9jYXRpb25zQXJlRXF1YWwoem9uZSwgbG9jYXRpb24yKVxuICAgICAgICAgKTtcbiAgICAgICAgIGlmICh0YXJnZXQyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBmaW5kIGRyb3Agem9uZSB0byBzaG93XCIpO1xuICAgICAgICAgfVxuICAgICAgICAgY29uc3QgZmFtaWx5MiA9IHRhcmdldDIuZ2V0RmFtaWx5KCk7XG4gICAgICAgICBpZiAoZmFtaWx5ID09PSB1bmRlZmluZWQgfHwgZmFtaWx5MiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBmYW1pbHlcIik7XG4gICAgICAgICB9XG4gICAgICAgICBjb25zdCBuZXdGYW1pbHkgPSB7XG4gICAgICAgICAgICBmb3VuZGVyOiBmYW1pbHkuZm91bmRlcixcbiAgICAgICAgICAgIG1lbWJlcnM6IFsuLi5mYW1pbHkubWVtYmVyc11cbiAgICAgICAgIH07XG4gICAgICAgICB0aGlzLnNob3dEcm9wWm9uZShmYW1pbHkuZm91bmRlciwgdHJ1ZSk7XG4gICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiBmYW1pbHkubWVtYmVycy5zb3J0KHNvcnRGYW1pbHkpKSB7XG4gICAgICAgICAgICBtZW1iZXIuc2V0RmFtaWx5KG5ld0ZhbWlseSk7XG4gICAgICAgICAgICBpZiAobWVtYmVyICE9PSBmYW1pbHkuZm91bmRlcikge1xuICAgICAgICAgICAgICAgaWYgKHRoaXMuYWN0aXZlRHJvcFpvbmUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgIC8vRmFpbGVkIHRvIGFjdGl2YXRlIGEgem9uZSBzbyBmYXIsIHNvIGFjdGl2YXRlIHRoaXMgb25lIGluc3RlYWRcbiAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKG1lbWJlciwgdHJ1ZSk7XG4gICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUobWVtYmVyKTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgIH1cbiAgICAgICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIGZhbWlseTIubWVtYmVycykge1xuICAgICAgICAgICAgbWVtYmVyLnNldEZhbWlseShuZXdGYW1pbHkpO1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgbWVtYmVyLmdldExvY2F0aW9uKCkucGFyZW50Q29vcmRpbmF0ZXMubGVuZ3RoIDxcbiAgICAgICAgICAgICAgIHRhcmdldDIuZ2V0TG9jYXRpb24oKS5wYXJlbnRDb29yZGluYXRlcy5sZW5ndGhcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgbmV3RmFtaWx5Lm1lbWJlcnMucHVzaChtZW1iZXIpO1xuICAgICAgICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUobWVtYmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgIH1cbiAgICAgICAgIC8vVGVtcG9yYXJpbHkgc3RvcmUgdGhlIG9sZCBmYW1pbGllc1xuICAgICAgICAgdGhpcy50ZW1wRmFtaWxpZXMgPSBbZmFtaWx5LCBmYW1pbHkyXTtcbiAgICAgICAgIC8vUmVtb3ZlIHRoZSBvbGQgZmFtaWxpZXNcbiAgICAgICAgIGNvbnN0IGZhbWlseUluZGV4ID0gdGhpcy5kcm9wWm9uZUZhbWlsaWVzLmluZGV4T2YoZmFtaWx5KTtcbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5zcGxpY2UoZmFtaWx5SW5kZXgsIDEpO1xuICAgICAgICAgY29uc3QgZmFtaWx5MkluZGV4ID0gdGhpcy5kcm9wWm9uZUZhbWlsaWVzLmluZGV4T2YoZmFtaWx5Mik7XG4gICAgICAgICB0aGlzLmRyb3Bab25lRmFtaWxpZXMuc3BsaWNlKGZhbWlseTJJbmRleCwgMSk7XG4gICAgICAgICAvL0FkZCB0aGUgbmV3IGZhbWlseVxuICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnB1c2gobmV3RmFtaWx5KTtcbiAgICAgICAgIHRoaXMudmlzaWJsZUZhbWlseSA9IG5ld0ZhbWlseTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICBpZiAoZmFtaWx5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZhbWlseVwiKTtcbiAgICAgICAgIH1cbiAgICAgICAgIHRoaXMudmlzaWJsZUZhbWlseSA9IGZhbWlseTtcbiAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKGZhbWlseS5mb3VuZGVyLCB0cnVlKTtcbiAgICAgICAgIGlmIChmYW1pbHkubWVtYmVycy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiBmYW1pbHkubWVtYmVycy5zb3J0KHNvcnRGYW1pbHkpKSB7XG4gICAgICAgICAgICAgICBpZiAobWVtYmVyICE9PSBmYW1pbHkuZm91bmRlcikge1xuICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYWN0aXZlRHJvcFpvbmUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgIC8vRmFpbGVkIHRvIGFjdGl2YXRlIGEgem9uZSBzbyBmYXIsIHNvIGFjdGl2YXRlIHRoaXMgb25lIGluc3RlYWRcbiAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd0Ryb3Bab25lKG1lbWJlciwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93RHJvcFpvbmUobWVtYmVyKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgIG9wdGlvbnMuYWN0aXZhdGVMb3dlc3RJbnN0ZWFkT2ZGb3VuZGVyID09PSB0cnVlICYmXG4gICAgICAgICB0aGlzLnZpc2libGVGYW1pbHkubWVtYmVycy5sZW5ndGggPiAxXG4gICAgICApIHtcbiAgICAgICAgIGNvbnN0IGxvd2VzdE1lbWJlciA9IFsuLi50aGlzLnZpc2libGVGYW1pbHkubWVtYmVyc11cbiAgICAgICAgICAgIC5zb3J0KHNvcnRGYW1pbHkpXG4gICAgICAgICAgICAucG9wKCk7XG4gICAgICAgICBpZiAobG93ZXN0TWVtYmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBnZXQgbG93ZXN0IG1lbWJlclwiKTtcbiAgICAgICAgIH1cbiAgICAgICAgIHRoaXMuc3dhcEFjdGl2ZURyb3Bab25lKGxvd2VzdE1lbWJlcik7XG4gICAgICB9XG4gICB9XG5cbiAgIHB1YmxpYyBzd2FwQWN0aXZlRHJvcFpvbmUobmV3QWN0aXZlRHJvcFpvbmU6IERyb3Bab25lKTogdm9pZCB7XG4gICAgICBpZiAodGhpcy52aXNpYmxlRmFtaWx5ID09PSBudWxsKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyB2aXNpYmxlIGZhbWlseSBhdmFpbGFibGUgZm9yIHN3YXBwaW5nXCIpO1xuICAgICAgfVxuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnZpc2libGVGYW1pbHkubWVtYmVycy5maW5kSW5kZXgoXG4gICAgICAgICAoZHJvcFpvbmUpID0+IGRyb3Bab25lID09PSBuZXdBY3RpdmVEcm9wWm9uZVxuICAgICAgKTtcbiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImZhaWxlZCB0byBzd2FwIGFjdGl2ZSBkcm9wIHpvbmVcIik7XG4gICAgICB9XG4gICAgICB0aGlzLnNldEFjdGl2ZURyb3Bab25lKG5ld0FjdGl2ZURyb3Bab25lKTtcbiAgIH1cblxuICAgcHVibGljIHVwZGF0ZSgpOiB2b2lkIHtcbiAgICAgIHRoaXMudXBkYXRlJC5uZXh0KG51bGwpO1xuICAgfVxuXG4gICBwcml2YXRlIGFzc2lnbkZhbWlsaWVzKCk6IHZvaWQge1xuICAgICAgY29uc3Qgb3JwaGFuWm9uZXMgPSBbLi4udGhpcy5kcm9wWm9uZUludmVudG9yeV07XG4gICAgICBjb25zdCBkZWVwZXN0TWVtYmVycyA9IG9ycGhhblpvbmVzXG4gICAgICAgICAuZmlsdGVyKCh6b25lKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBsb2NhdGlvbiA9IHpvbmUuZ2V0TG9jYXRpb24oKTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICBsb2NhdGlvbi5pbnNlcnRJbmRleCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgbG9jYXRpb24ucGFyZW50Q29vcmRpbmF0ZXMubGVuZ3RoID4gMFxuICAgICAgICAgICAgKTtcbiAgICAgICAgIH0pXG4gICAgICAgICAuc29ydCgodmFsdWVBLCB2YWx1ZUIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFDb29yZGluYXRlcyA9IHZhbHVlQS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKTtcbiAgICAgICAgICAgIGNvbnN0IGJDb29yZGluYXRlcyA9IHZhbHVlQi5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKTtcbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IE1hdGgubWF4KGFDb29yZGluYXRlcy5sZW5ndGgsIGJDb29yZGluYXRlcy5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICAgICAgICAgaWYgKChhQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKSA+IChiQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICAgIChhQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKSA8IChiQ29vcmRpbmF0ZXNbaW5kZXhdID8/IC0xKVxuICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgfSk7XG4gICAgICBmb3IgKGNvbnN0IGRyb3Bab25lIG9mIGRlZXBlc3RNZW1iZXJzKSB7XG4gICAgICAgICBpZiAoIW9ycGhhblpvbmVzLmluY2x1ZGVzKGRyb3Bab25lKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICB9XG4gICAgICAgICBjb25zdCBmYW1pbHk6IERyb3Bab25lRmFtaWx5ID0ge1xuICAgICAgICAgICAgZm91bmRlcjogZHJvcFpvbmUsXG4gICAgICAgICAgICBtZW1iZXJzOiBbXVxuICAgICAgICAgfTtcbiAgICAgICAgIGRyb3Bab25lLnNldEZhbWlseShmYW1pbHkpO1xuICAgICAgICAgLy9TZWUgaWYgdGhlcmUgYXJlIGFueSBvcnBoYW5zIHRoYXQgYmVsb25nIHRvIHRoaXMgZmFtaWx5IGFuZCBjbGFpbSB0aGVtLlxuICAgICAgICAgY29uc3QgY3Vyc29yID0gWy4uLmRyb3Bab25lLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpXTtcbiAgICAgICAgIHdoaWxlIChjdXJzb3IubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgZmFtaWx5TWVtYmVySW5kZXggPSBvcnBoYW5ab25lcy5maW5kSW5kZXgoKHpvbmUpID0+XG4gICAgICAgICAgICAgICBhcnJheXNBcmVFcXVhbCh6b25lLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpLCBjdXJzb3IpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGZhbWlseU1lbWJlckluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgY29uc3QgZmFtaWx5TWVtYmVyID0gb3JwaGFuWm9uZXMuc3BsaWNlKGZhbWlseU1lbWJlckluZGV4LCAxKVswXTtcbiAgICAgICAgICAgICAgIGZhbWlseS5tZW1iZXJzLnB1c2goZmFtaWx5TWVtYmVyKTtcbiAgICAgICAgICAgICAgIGZhbWlseU1lbWJlci5zZXRGYW1pbHkoZmFtaWx5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnNvci5wb3AoKTtcbiAgICAgICAgICAgIGN1cnNvcltjdXJzb3IubGVuZ3RoIC0gMV0rKztcbiAgICAgICAgIH1cbiAgICAgICAgIHRoaXMuZHJvcFpvbmVGYW1pbGllcy5wdXNoKGZhbWlseSk7XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGRyb3Bab25lIG9mIG9ycGhhblpvbmVzLmZpbHRlcihcbiAgICAgICAgICh6b25lKSA9PiB6b25lLmdldEZ1bGxJbnNlcnRDb29yZGluYXRlcygpLmxlbmd0aCA9PT0gMVxuICAgICAgKSkge1xuICAgICAgICAgY29uc3QgZmFtaWx5OiBEcm9wWm9uZUZhbWlseSA9IHtcbiAgICAgICAgICAgIGZvdW5kZXI6IGRyb3Bab25lLFxuICAgICAgICAgICAgbWVtYmVyczogW2Ryb3Bab25lXVxuICAgICAgICAgfTtcbiAgICAgICAgIGRyb3Bab25lLnNldEZhbWlseShmYW1pbHkpO1xuICAgICAgICAgdGhpcy5kcm9wWm9uZUZhbWlsaWVzLnB1c2goZmFtaWx5KTtcbiAgICAgICAgIG9ycGhhblpvbmVzLnNwbGljZShvcnBoYW5ab25lcy5pbmRleE9mKGRyb3Bab25lKSwgMSk7XG4gICAgICB9XG4gICAgICBpZiAob3JwaGFuWm9uZXMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICBsZXQgb3JwaGFucyA9IFwiXCI7XG4gICAgICAgICBmb3IgKGNvbnN0IHpvbmUgb2Ygb3JwaGFuWm9uZXMpIHtcbiAgICAgICAgICAgIG9ycGhhbnMgKz0gYCR7SlNPTi5zdHJpbmdpZnkoem9uZS5nZXRMb2NhdGlvbigpKX0sIGA7XG4gICAgICAgICB9XG4gICAgICAgICBvcnBoYW5zID0gb3JwaGFucy5zbGljZSgwLCBvcnBoYW5zLmxlbmd0aCAtIDIpO1xuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFNvbWUgem9uZXMgd2VyZSBub3QgYXNzaWduZWQgdG8gYSBmYW1pbHkuIFRoZSBvcnBoYW4gem9uZXMgaGF2ZSB0aGUgZm9sbG93aW5nIGxvY2F0aW9uczogJHtvcnBoYW5zfWBcbiAgICAgICAgICk7XG4gICAgICB9XG4gICB9XG5cbiAgIHByaXZhdGUgYnVpbGRJbnZlbnRvcnkoKSB7XG4gICAgICAvL1dlIGRvIHRoaXMgZnVua3kgc3RyaW5nIGFycmF5IGJlY2F1c2UgaXQgaXMgZmFzdGVyIHRoYW4gZG9pbmcgZGlyZWN0IGFycmF5IGNvbXBhcmlzb25zXG4gICAgICBjb25zdCBpbnZlbnRvcnlDb29yZGluYXRlczogQXJyYXk8c3RyaW5nPiA9IFtdO1xuICAgICAgZm9yIChjb25zdCBkcm9wWm9uZSBvZiB0aGlzLmRyb3Bab25lQXJjaGl2ZSkge1xuICAgICAgICAgY29uc3QgY29vcmRpbmF0ZXMgPSBkcm9wWm9uZS5nZXRGdWxsSW5zZXJ0Q29vcmRpbmF0ZXMoKS5qb2luKFwiLFwiKTtcbiAgICAgICAgIGlmIChpbnZlbnRvcnlDb29yZGluYXRlcy5pbmNsdWRlcyhjb29yZGluYXRlcykpIHtcbiAgICAgICAgICAgIGRyb3Bab25lLmlzUmVuZGVyZWQoZmFsc2UpO1xuICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZHJvcFpvbmVJbnZlbnRvcnkucHVzaChkcm9wWm9uZSk7XG4gICAgICAgICAgICBpbnZlbnRvcnlDb29yZGluYXRlcy5wdXNoKGNvb3JkaW5hdGVzKTtcbiAgICAgICAgICAgIGRyb3Bab25lLmlzUmVuZGVyZWQodHJ1ZSk7XG4gICAgICAgICB9XG4gICAgICB9XG4gICB9XG5cbiAgIHByaXZhdGUgc2V0QWN0aXZlRHJvcFpvbmUoZHJvcFpvbmU6IERyb3Bab25lIHwgbnVsbCk6IHZvaWQge1xuICAgICAgaWYgKHRoaXMuYWN0aXZlRHJvcFpvbmUgIT09IG51bGwpIHtcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUuaXNBY3RpdmUoZmFsc2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZSA9IGRyb3Bab25lO1xuICAgICAgaWYgKFxuICAgICAgICAgdGhpcy5hY3RpdmVEcm9wWm9uZSAhPT0gbnVsbCAmJlxuICAgICAgICAgdGhpcy5kcmFnU3RhdGVTZXJ2aWNlLmdldFN0YXRlKCkgIT09IFwiZHJvcHBhYmxlXCJcbiAgICAgICkge1xuICAgICAgICAgdGhpcy5kcmFnU3RhdGVTZXJ2aWNlLmRyb3BwYWJsZSgpO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgIHRoaXMuYWN0aXZlRHJvcFpvbmUgPT09IG51bGwgJiZcbiAgICAgICAgIHRoaXMuZHJhZ1N0YXRlU2VydmljZS5nZXRTdGF0ZSgpID09PSBcImRyb3BwYWJsZVwiXG4gICAgICApIHtcbiAgICAgICAgIHRoaXMuZHJhZ1N0YXRlU2VydmljZS5ub3REcm9wcGFibGUoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmFjdGl2ZURyb3Bab25lICE9PSBudWxsKSB7XG4gICAgICAgICB0aGlzLmFjdGl2ZURyb3Bab25lLmlzQWN0aXZlKHRydWUpO1xuICAgICAgfVxuICAgfVxuXG4gICBwcml2YXRlIHNob3dEcm9wWm9uZShkcm9wWm9uZTogRHJvcFpvbmUsIGFjdGl2ZSA9IGZhbHNlKTogYm9vbGVhbiB7XG4gICAgICBpZiAodGhpcy50cmVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkRyb3Bab25lU2VydmljZSBub3QgaW5pdGlhbGl6ZWRcIik7XG4gICAgICB9XG4gICAgICBpZiAoIXRoaXMuem9uZUlzQWxsb3dlZChkcm9wWm9uZSkpIHtcbiAgICAgICAgIC8vVXNlciBzZXR0aW5ncyBpbmRpY2F0ZSB0byBza2lwIHRoaXMgZHJvcCB6b25lXG4gICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBwYXJlbnQgPSB0aGlzLnRyZWUuZmluZEJ5Q29vcmRpbmF0ZXMoXG4gICAgICAgICBkcm9wWm9uZS5nZXRMb2NhdGlvbigpLnBhcmVudENvb3JkaW5hdGVzXG4gICAgICApO1xuICAgICAgaWYgKHBhcmVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJCYWQgZmFtaWx5IG1lbWJlclwiKTtcbiAgICAgIH1cbiAgICAgIGRyb3Bab25lLmlzVmlzaWJsZSh0cnVlKTtcbiAgICAgIGlmIChhY3RpdmUgPT09IHRydWUpIHtcbiAgICAgICAgIHRoaXMuc2V0QWN0aXZlRHJvcFpvbmUoZHJvcFpvbmUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICB9XG5cbiAgIHByaXZhdGUgdXBkYXRlRHJvcFpvbmVzKCk6IHZvaWQge1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgdGhpcy5idWlsZEludmVudG9yeSgpO1xuICAgICAgdGhpcy5hc3NpZ25GYW1pbGllcygpO1xuICAgfVxuXG4gICBwcml2YXRlIHpvbmVJc0FsbG93ZWQoZHJvcFpvbmU6IERyb3Bab25lKTogYm9vbGVhbiB7XG4gICAgICBpZiAodGhpcy50cmVlT3B0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IHRoaXMudHJlZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkcm9wWm9uZVNlcnZpY2Ugbm90IGluaXRpYWxpemVkXCIpO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZHJhZ1N0YXRlU2VydmljZS5nZXREYXRhKCk7XG4gICAgICBpZiAoZGF0YSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCBnZXQgZHJhZ2dlZCBub2RlXCIpO1xuICAgICAgfVxuICAgICAgY29uc3QgcGFyZW50Q29vcmRpbmF0ZXMgPSBkcm9wWm9uZS5nZXRMb2NhdGlvbigpLnBhcmVudENvb3JkaW5hdGVzO1xuICAgICAgY29uc3QgZHJvcFpvbmVQYXJlbnQgPSB0aGlzLnRyZWUuZmluZEJ5Q29vcmRpbmF0ZXMocGFyZW50Q29vcmRpbmF0ZXMpO1xuICAgICAgaWYgKGRyb3Bab25lUGFyZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBnZXQgZHJvcCB6b25lIHBhcmVudFwiKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgIHBhcmVudENvb3JkaW5hdGVzLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICFpc05lc3RpbmdBbGxvd2VkKFxuICAgICAgICAgICAgdGhpcy50cmVlT3B0aW9ucyxcbiAgICAgICAgICAgIGRyb3Bab25lUGFyZW50LmRhdGEgYXMgTGltYmxlVHJlZU5vZGVcbiAgICAgICAgIClcbiAgICAgICkge1xuICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgZHJvcFpvbmVJbmRleCA9IGRyb3Bab25lLmdldExvY2F0aW9uKCkuaW5zZXJ0SW5kZXg7XG4gICAgICBpZiAoZHJvcFpvbmVJbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZ2V0IGRyb3Agem9uZSBpbmRleFwiKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRyYWdnZWROb2RlID0gZGF0YS5icmFuY2g7XG4gICAgICBpZiAoXG4gICAgICAgICAhdGhpcy50cmVlT3B0aW9ucy5hbGxvd0Ryb3AoXG4gICAgICAgICAgICBkcmFnZ2VkTm9kZS5kYXRhLFxuICAgICAgICAgICAgZHJvcFpvbmVQYXJlbnQuZGF0YSBhcyBMaW1ibGVUcmVlTm9kZSxcbiAgICAgICAgICAgIGRyb3Bab25lSW5kZXhcbiAgICAgICAgIClcbiAgICAgICkge1xuICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICB9XG59XG4iXX0=