angular-slickgrid 3.3.0 → 4.1.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 (55) hide show
  1. package/README.md +26 -28
  2. package/angular-slickgrid.d.ts +1 -3
  3. package/app/modules/angular-slickgrid/components/angular-slickgrid.component.d.ts +9 -6
  4. package/app/modules/angular-slickgrid/extensions/index.d.ts +1 -1
  5. package/app/modules/angular-slickgrid/extensions/{rowDetailViewExtension.d.ts → slickRowDetailView.d.ts} +40 -27
  6. package/app/modules/angular-slickgrid/index.d.ts +1 -1
  7. package/app/modules/angular-slickgrid/models/angularGridInstance.interface.d.ts +1 -1
  8. package/app/modules/angular-slickgrid/modules/angular-slickgrid.module.d.ts +7 -0
  9. package/app/modules/angular-slickgrid/services/angularUtil.service.d.ts +3 -0
  10. package/app/modules/angular-slickgrid/services/bsDropdown.service.d.ts +3 -0
  11. package/app/modules/angular-slickgrid/services/container.service.d.ts +3 -0
  12. package/app/modules/angular-slickgrid/services/translater.service.d.ts +3 -0
  13. package/docs/assets/lib/multiple-select/README.md +17 -0
  14. package/esm2020/angular-slickgrid.mjs +5 -0
  15. package/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +1167 -0
  16. package/{esm2015/app/modules/angular-slickgrid/constants.js → esm2020/app/modules/angular-slickgrid/constants.mjs} +0 -0
  17. package/{esm2015/app/modules/angular-slickgrid/extensions/index.js → esm2020/app/modules/angular-slickgrid/extensions/index.mjs} +2 -2
  18. package/esm2020/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +300 -0
  19. package/esm2020/app/modules/angular-slickgrid/global-grid-options.mjs +243 -0
  20. package/{esm2015/app/modules/angular-slickgrid/index.js → esm2020/app/modules/angular-slickgrid/index.mjs} +2 -2
  21. package/{esm2015/app/modules/angular-slickgrid/models/angularComponentOutput.interface.js → esm2020/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs} +0 -0
  22. package/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +2 -0
  23. package/{esm2015/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.js → esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs} +0 -0
  24. package/{esm2015/app/modules/angular-slickgrid/models/gridOption.interface.js → esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs} +0 -0
  25. package/{esm2015/app/modules/angular-slickgrid/models/index.js → esm2020/app/modules/angular-slickgrid/models/index.mjs} +0 -0
  26. package/{esm2015/app/modules/angular-slickgrid/models/rowDetailView.interface.js → esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs} +0 -0
  27. package/{esm2015/app/modules/angular-slickgrid/models/slickGrid.interface.js → esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs} +0 -0
  28. package/esm2020/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +46 -0
  29. package/esm2020/app/modules/angular-slickgrid/services/angularUtil.service.mjs +46 -0
  30. package/esm2020/app/modules/angular-slickgrid/services/bsDropdown.service.mjs +103 -0
  31. package/esm2020/app/modules/angular-slickgrid/services/container.service.mjs +26 -0
  32. package/{esm2015/app/modules/angular-slickgrid/services/index.js → esm2020/app/modules/angular-slickgrid/services/index.mjs} +0 -0
  33. package/esm2020/app/modules/angular-slickgrid/services/translater.service.mjs +43 -0
  34. package/{esm2015/app/modules/angular-slickgrid/services/utilities.js → esm2020/app/modules/angular-slickgrid/services/utilities.mjs} +0 -0
  35. package/{esm2015/app/modules/angular-slickgrid/slickgrid-config.js → esm2020/app/modules/angular-slickgrid/slickgrid-config.mjs} +0 -0
  36. package/{esm2015/public_api.js → esm2020/public_api.mjs} +0 -0
  37. package/fesm2015/{angular-slickgrid.js → angular-slickgrid.mjs} +248 -280
  38. package/fesm2015/angular-slickgrid.mjs.map +1 -0
  39. package/fesm2020/angular-slickgrid.mjs +2065 -0
  40. package/fesm2020/angular-slickgrid.mjs.map +1 -0
  41. package/package.json +40 -22
  42. package/angular-slickgrid.metadata.json +0 -1
  43. package/bundles/angular-slickgrid.umd.js +0 -2642
  44. package/bundles/angular-slickgrid.umd.js.map +0 -1
  45. package/esm2015/angular-slickgrid.js +0 -7
  46. package/esm2015/app/modules/angular-slickgrid/components/angular-slickgrid.component.js +0 -1202
  47. package/esm2015/app/modules/angular-slickgrid/extensions/rowDetailViewExtension.js +0 -342
  48. package/esm2015/app/modules/angular-slickgrid/global-grid-options.js +0 -243
  49. package/esm2015/app/modules/angular-slickgrid/models/angularGridInstance.interface.js +0 -2
  50. package/esm2015/app/modules/angular-slickgrid/modules/angular-slickgrid.module.js +0 -37
  51. package/esm2015/app/modules/angular-slickgrid/services/angularUtil.service.js +0 -48
  52. package/esm2015/app/modules/angular-slickgrid/services/bsDropdown.service.js +0 -103
  53. package/esm2015/app/modules/angular-slickgrid/services/container.service.js +0 -24
  54. package/esm2015/app/modules/angular-slickgrid/services/translater.service.js +0 -47
  55. package/fesm2015/angular-slickgrid.js.map +0 -1
@@ -1,1202 +0,0 @@
1
- // import 3rd party vendor libs
2
- // only import the necessary core lib, each will be imported on demand when enabled (via require)
3
- import 'jquery-ui/ui/widgets/draggable';
4
- import 'jquery-ui/ui/widgets/droppable';
5
- import 'jquery-ui/ui/widgets/sortable';
6
- import 'slickgrid/lib/jquery.event.drag-2.3.0';
7
- import 'slickgrid/lib/jquery.mousewheel';
8
- import 'slickgrid/slick.core';
9
- import 'slickgrid/slick.grid';
10
- import 'slickgrid/slick.dataview';
11
- import 'slickgrid/slick.groupitemmetadataprovider';
12
- // ...then everything else...
13
- import { ApplicationRef, ChangeDetectorRef, Component, ElementRef, Inject, Input, Optional, } from '@angular/core';
14
- import { TranslateService } from '@ngx-translate/core';
15
- import { Observable } from 'rxjs';
16
- import {
17
- // services
18
- BackendUtilityService, CollectionService, EventNamingStyle, ExtensionService, FilterFactory, FilterService, GridEventService, GridService, GridStateService, GroupingAndColspanService, PaginationService, ResizerService, SharedService, SlickgridConfig, SortService, TreeDataService,
19
- // extensions
20
- AutoTooltipExtension, CheckboxSelectorExtension, CellExternalCopyManagerExtension, CellMenuExtension, ColumnPickerExtension, ContextMenuExtension, DraggableGroupingExtension, ExtensionUtility, GridMenuExtension, GroupItemMetaProviderExtension, HeaderMenuExtension, HeaderButtonExtension, RowSelectionExtension, RowMoveManagerExtension,
21
- // utilities
22
- autoAddEditorFormatterToColumnsWithEditor, emptyElement, GridStateType, } from '@slickgrid-universal/common';
23
- import { EventPubSubService } from '@slickgrid-universal/event-pub-sub';
24
- import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component';
25
- import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component';
26
- import { SlickPaginationComponent } from '@slickgrid-universal/pagination-component';
27
- import { RxJsResource } from '@slickgrid-universal/rxjs-observable';
28
- import { dequal } from 'dequal/lite';
29
- import { Constants } from '../constants';
30
- import { GlobalGridOptions } from './../global-grid-options';
31
- import { TranslaterService } from '../services/translater.service';
32
- import { unsubscribeAllObservables } from './../services/utilities';
33
- // Services
34
- import { AngularUtilService } from '../services/angularUtil.service';
35
- import { RowDetailViewExtension } from '../extensions/rowDetailViewExtension';
36
- import { ContainerService } from '../services/container.service';
37
- export class AngularSlickgridComponent {
38
- constructor(angularUtilService, appRef, cd, containerService, elm, translate, translaterService, forRootConfig, externalServices) {
39
- var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
40
- this.angularUtilService = angularUtilService;
41
- this.appRef = appRef;
42
- this.cd = cd;
43
- this.containerService = containerService;
44
- this.elm = elm;
45
- this.translate = translate;
46
- this.translaterService = translaterService;
47
- this.forRootConfig = forRootConfig;
48
- this._currentDatasetLength = 0;
49
- this._eventHandler = new Slick.EventHandler();
50
- this._hideHeaderRowAfterPageLoad = false;
51
- this._isGridInitialized = false;
52
- this._isDatasetInitialized = false;
53
- this._isDatasetHierarchicalInitialized = false;
54
- this._isPaginationInitialized = false;
55
- this._isLocalGrid = true;
56
- this._registeredResources = [];
57
- this.groupingDefinition = {};
58
- this.showPagination = false;
59
- this.serviceList = [];
60
- this.totalItems = 0;
61
- this.subscriptions = [];
62
- this.gridId = '';
63
- const slickgridConfig = new SlickgridConfig();
64
- // initialize and assign all Service Dependencies
65
- this._eventPubSubService = (_a = externalServices === null || externalServices === void 0 ? void 0 : externalServices.eventPubSubService) !== null && _a !== void 0 ? _a : new EventPubSubService(this.elm.nativeElement);
66
- this._eventPubSubService.eventNamingStyle = EventNamingStyle.camelCase;
67
- this.backendUtilityService = (_b = externalServices === null || externalServices === void 0 ? void 0 : externalServices.backendUtilityService) !== null && _b !== void 0 ? _b : new BackendUtilityService();
68
- this.gridEventService = (_c = externalServices === null || externalServices === void 0 ? void 0 : externalServices.gridEventService) !== null && _c !== void 0 ? _c : new GridEventService();
69
- this.sharedService = (_d = externalServices === null || externalServices === void 0 ? void 0 : externalServices.sharedService) !== null && _d !== void 0 ? _d : new SharedService();
70
- this.collectionService = (_f = externalServices === null || externalServices === void 0 ? void 0 : externalServices.collectionService) !== null && _f !== void 0 ? _f : new CollectionService(this.translaterService);
71
- this.extensionUtility = (_g = externalServices === null || externalServices === void 0 ? void 0 : externalServices.extensionUtility) !== null && _g !== void 0 ? _g : new ExtensionUtility(this.sharedService, this.translaterService);
72
- this.filterFactory = new FilterFactory(slickgridConfig, this.translaterService, this.collectionService);
73
- this.filterService = (_h = externalServices === null || externalServices === void 0 ? void 0 : externalServices.filterService) !== null && _h !== void 0 ? _h : new FilterService(this.filterFactory, this._eventPubSubService, this.sharedService, this.backendUtilityService);
74
- this.resizerService = (_j = externalServices === null || externalServices === void 0 ? void 0 : externalServices.resizerService) !== null && _j !== void 0 ? _j : new ResizerService(this._eventPubSubService);
75
- this.sortService = (_k = externalServices === null || externalServices === void 0 ? void 0 : externalServices.sortService) !== null && _k !== void 0 ? _k : new SortService(this.sharedService, this._eventPubSubService, this.backendUtilityService);
76
- this.treeDataService = (_l = externalServices === null || externalServices === void 0 ? void 0 : externalServices.treeDataService) !== null && _l !== void 0 ? _l : new TreeDataService(this._eventPubSubService, this.sharedService, this.sortService);
77
- this.paginationService = (_m = externalServices === null || externalServices === void 0 ? void 0 : externalServices.paginationService) !== null && _m !== void 0 ? _m : new PaginationService(this._eventPubSubService, this.sharedService, this.backendUtilityService);
78
- // extensions
79
- const autoTooltipExtension = new AutoTooltipExtension(this.sharedService);
80
- const cellExternalCopyManagerExtension = new CellExternalCopyManagerExtension(this.extensionUtility, this.sharedService);
81
- const cellMenuExtension = new CellMenuExtension(this.extensionUtility, this.sharedService, this.translaterService);
82
- const contextMenuExtension = new ContextMenuExtension(this.extensionUtility, this._eventPubSubService, this.sharedService, this.treeDataService, this.translaterService);
83
- const columnPickerExtension = new ColumnPickerExtension(this.extensionUtility, this.sharedService);
84
- const checkboxExtension = new CheckboxSelectorExtension(this.sharedService);
85
- const draggableGroupingExtension = new DraggableGroupingExtension(this.extensionUtility, this._eventPubSubService, this.sharedService);
86
- const gridMenuExtension = new GridMenuExtension(this.extensionUtility, this.filterService, this.sharedService, this.sortService, this.backendUtilityService, this.translaterService);
87
- const groupItemMetaProviderExtension = new GroupItemMetaProviderExtension(this.sharedService);
88
- const headerButtonExtension = new HeaderButtonExtension(this.extensionUtility, this.sharedService);
89
- const headerMenuExtension = new HeaderMenuExtension(this.extensionUtility, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.translaterService);
90
- const rowDetailViewExtension = new RowDetailViewExtension(this.angularUtilService, this.appRef, this._eventPubSubService, this.sharedService, this.rxjs);
91
- const rowMoveManagerExtension = new RowMoveManagerExtension(this.sharedService);
92
- const rowSelectionExtension = new RowSelectionExtension(this.sharedService);
93
- this.extensionService = (_o = externalServices === null || externalServices === void 0 ? void 0 : externalServices.extensionService) !== null && _o !== void 0 ? _o : new ExtensionService(autoTooltipExtension, cellExternalCopyManagerExtension, cellMenuExtension, checkboxExtension, columnPickerExtension, contextMenuExtension, draggableGroupingExtension, gridMenuExtension, groupItemMetaProviderExtension, headerButtonExtension, headerMenuExtension, rowDetailViewExtension, rowMoveManagerExtension, rowSelectionExtension, this.sharedService, this.translaterService);
94
- this.gridStateService = (_p = externalServices === null || externalServices === void 0 ? void 0 : externalServices.gridStateService) !== null && _p !== void 0 ? _p : new GridStateService(this.extensionService, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService);
95
- this.gridService = (_q = externalServices === null || externalServices === void 0 ? void 0 : externalServices.gridService) !== null && _q !== void 0 ? _q : new GridService(this.gridStateService, this.filterService, this._eventPubSubService, this.paginationService, this.sharedService, this.sortService, this.treeDataService);
96
- this.groupingService = (_r = externalServices === null || externalServices === void 0 ? void 0 : externalServices.groupingAndColspanService) !== null && _r !== void 0 ? _r : new GroupingAndColspanService(this.extensionUtility, this.extensionService, this._eventPubSubService);
97
- this.serviceList = [
98
- this.extensionService,
99
- this.filterService,
100
- this.gridEventService,
101
- this.gridService,
102
- this.gridStateService,
103
- this.groupingService,
104
- this.paginationService,
105
- this.resizerService,
106
- this.sortService,
107
- this.treeDataService,
108
- ];
109
- // register all Service instances in the container
110
- this.containerService.registerInstance('ExtensionUtility', this.extensionUtility);
111
- this.containerService.registerInstance('FilterService', this.filterService);
112
- this.containerService.registerInstance('CollectionService', this.collectionService);
113
- this.containerService.registerInstance('ExtensionService', this.extensionService);
114
- this.containerService.registerInstance('GridEventService', this.gridEventService);
115
- this.containerService.registerInstance('GridService', this.gridService);
116
- this.containerService.registerInstance('GridStateService', this.gridStateService);
117
- this.containerService.registerInstance('GroupingAndColspanService', this.groupingService);
118
- this.containerService.registerInstance('PaginationService', this.paginationService);
119
- this.containerService.registerInstance('ResizerService', this.resizerService);
120
- this.containerService.registerInstance('SharedService', this.sharedService);
121
- this.containerService.registerInstance('SortService', this.sortService);
122
- this.containerService.registerInstance('EventPubSubService', this._eventPubSubService);
123
- this.containerService.registerInstance('PubSubService', this._eventPubSubService);
124
- this.containerService.registerInstance('TranslaterService', this.translaterService);
125
- this.containerService.registerInstance('TreeDataService', this.treeDataService);
126
- }
127
- get paginationOptions() {
128
- return this._paginationOptions;
129
- }
130
- set paginationOptions(newPaginationOptions) {
131
- var _a, _b, _c;
132
- if (newPaginationOptions && this._paginationOptions) {
133
- this._paginationOptions = Object.assign(Object.assign(Object.assign({}, this.gridOptions.pagination), this._paginationOptions), newPaginationOptions);
134
- }
135
- else {
136
- this._paginationOptions = newPaginationOptions;
137
- }
138
- this.gridOptions.pagination = (_a = this._paginationOptions) !== null && _a !== void 0 ? _a : this.gridOptions.pagination;
139
- this.paginationService.updateTotalItems((_c = (_b = this.gridOptions.pagination) === null || _b === void 0 ? void 0 : _b.totalItems) !== null && _c !== void 0 ? _c : 0, true);
140
- }
141
- set columnDefinitions(columnDefinitions) {
142
- this._columnDefinitions = columnDefinitions;
143
- if (this._isGridInitialized) {
144
- this.updateColumnDefinitionsList(columnDefinitions);
145
- }
146
- if (columnDefinitions.length > 0) {
147
- this.copyColumnWidthsReference(columnDefinitions);
148
- }
149
- }
150
- get columnDefinitions() {
151
- return this._columnDefinitions;
152
- }
153
- get dataset() {
154
- var _a, _b, _c, _d;
155
- return (this.customDataView ? (_b = (_a = this.slickGrid) === null || _a === void 0 ? void 0 : _a.getData) === null || _b === void 0 ? void 0 : _b.call(_a) : (_d = (_c = this.dataView) === null || _c === void 0 ? void 0 : _c.getItems) === null || _d === void 0 ? void 0 : _d.call(_c)) || [];
156
- }
157
- set dataset(newDataset) {
158
- var _a, _b;
159
- const prevDatasetLn = this._currentDatasetLength;
160
- const isDatasetEqual = dequal(newDataset, this._dataset || []);
161
- let data = newDataset;
162
- // when Tree Data is enabled and we don't yet have the hierarchical dataset filled, we can force a convert+sort of the array
163
- if (this.slickGrid && ((_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.enableTreeData) && Array.isArray(newDataset) && (newDataset.length > 0 || newDataset.length !== prevDatasetLn || !isDatasetEqual)) {
164
- this._isDatasetHierarchicalInitialized = false;
165
- data = this.sortTreeDataset(newDataset, !isDatasetEqual); // if dataset changed, then force a refresh anyway
166
- }
167
- this._dataset = data;
168
- this.refreshGridData(data || []);
169
- this._currentDatasetLength = (newDataset || []).length;
170
- // expand/autofit columns on first page load
171
- // we can assume that if the prevDataset was empty then we are on first load
172
- if (((_b = this.gridOptions) === null || _b === void 0 ? void 0 : _b.autoFitColumnsOnFirstLoad) && prevDatasetLn === 0) {
173
- this.slickGrid.autosizeColumns();
174
- }
175
- }
176
- get datasetHierarchical() {
177
- return this.sharedService.hierarchicalDataset;
178
- }
179
- set datasetHierarchical(newHierarchicalDataset) {
180
- var _a, _b, _c, _d, _f;
181
- const isDatasetEqual = dequal(newHierarchicalDataset, (_b = (_a = this.sharedService) === null || _a === void 0 ? void 0 : _a.hierarchicalDataset) !== null && _b !== void 0 ? _b : []);
182
- const prevFlatDatasetLn = this._currentDatasetLength;
183
- this.sharedService.hierarchicalDataset = newHierarchicalDataset;
184
- if (newHierarchicalDataset && this.columnDefinitions && ((_c = this.filterService) === null || _c === void 0 ? void 0 : _c.clearFilters)) {
185
- this.filterService.clearFilters();
186
- }
187
- // when a hierarchical dataset is set afterward, we can reset the flat dataset and call a tree data sort that will overwrite the flat dataset
188
- if (newHierarchicalDataset && this.slickGrid && ((_d = this.sortService) === null || _d === void 0 ? void 0 : _d.processTreeDataInitialSort)) {
189
- this.dataView.setItems([], (_f = this.gridOptions.datasetIdPropertyName) !== null && _f !== void 0 ? _f : 'id');
190
- this.sortService.processTreeDataInitialSort();
191
- // we also need to reset/refresh the Tree Data filters because if we inserted new item(s) then it might not show up without doing this refresh
192
- // however we need 1 cpu cycle before having the DataView refreshed, so we need to wrap this check in a setTimeout
193
- setTimeout(() => {
194
- const flatDatasetLn = this.dataView.getItemCount();
195
- if (flatDatasetLn > 0 && (flatDatasetLn !== prevFlatDatasetLn || !isDatasetEqual)) {
196
- this.filterService.refreshTreeDataFilters();
197
- }
198
- });
199
- this._isDatasetHierarchicalInitialized = true;
200
- }
201
- }
202
- get elementRef() {
203
- return this.elm;
204
- }
205
- get eventHandler() {
206
- return this._eventHandler;
207
- }
208
- get gridContainerElement() {
209
- return document.querySelector(`#${this.gridOptions.gridContainerId || ''}`);
210
- }
211
- /** GETTER to know if dataset was initialized or not */
212
- get isDatasetInitialized() {
213
- return this._isDatasetInitialized;
214
- }
215
- /** SETTER to change if dataset was initialized or not (stringly used for unit testing purposes) */
216
- set isDatasetInitialized(isInitialized) {
217
- this._isDatasetInitialized = isInitialized;
218
- }
219
- set isDatasetHierarchicalInitialized(isInitialized) {
220
- this._isDatasetHierarchicalInitialized = isInitialized;
221
- }
222
- get registeredResources() {
223
- return this._registeredResources;
224
- }
225
- ngAfterViewInit() {
226
- this.initialization(this._eventHandler);
227
- this._isGridInitialized = true;
228
- // recheck the empty warning message after grid is shown so that it works in every use case
229
- if (this.gridOptions && this.gridOptions.enableEmptyDataWarningMessage && Array.isArray(this.dataset)) {
230
- const finalTotalCount = this.dataset.length;
231
- this.displayEmptyDataWarning(finalTotalCount < 1);
232
- }
233
- }
234
- ngOnDestroy() {
235
- this._eventPubSubService.publish('onBeforeGridDestroy', this.slickGrid);
236
- this.destroy();
237
- this._eventPubSubService.publish('onAfterGridDestroyed', true);
238
- }
239
- destroy(shouldEmptyDomElementContainer = false) {
240
- var _a, _b, _c, _d, _f, _g, _h;
241
- // dispose of all Services
242
- this.serviceList.forEach((service) => {
243
- if (service && service.dispose) {
244
- service.dispose();
245
- }
246
- });
247
- this.serviceList = [];
248
- // dispose all registered external resources
249
- if (Array.isArray(this._registeredResources)) {
250
- while (this._registeredResources.length > 0) {
251
- const resource = this._registeredResources.pop();
252
- if (resource === null || resource === void 0 ? void 0 : resource.dispose) {
253
- resource.dispose();
254
- }
255
- }
256
- this._registeredResources = [];
257
- }
258
- // dispose the Components
259
- (_a = this.slickEmptyWarning) === null || _a === void 0 ? void 0 : _a.dispose();
260
- (_b = this.slickFooter) === null || _b === void 0 ? void 0 : _b.dispose();
261
- (_c = this.slickPagination) === null || _c === void 0 ? void 0 : _c.dispose();
262
- if ((_d = this._eventHandler) === null || _d === void 0 ? void 0 : _d.unsubscribeAll) {
263
- this._eventHandler.unsubscribeAll();
264
- }
265
- (_f = this._eventPubSubService) === null || _f === void 0 ? void 0 : _f.unsubscribeAll();
266
- if (this.dataView) {
267
- if ((_g = this.dataView) === null || _g === void 0 ? void 0 : _g.setItems) {
268
- this.dataView.setItems([]);
269
- }
270
- if (this.dataView.destroy) {
271
- this.dataView.destroy();
272
- }
273
- }
274
- if ((_h = this.slickGrid) === null || _h === void 0 ? void 0 : _h.destroy) {
275
- this.slickGrid.destroy(shouldEmptyDomElementContainer);
276
- }
277
- if (this.backendServiceApi) {
278
- for (const prop of Object.keys(this.backendServiceApi)) {
279
- delete this.backendServiceApi[prop];
280
- }
281
- this.backendServiceApi = undefined;
282
- }
283
- for (const prop of Object.keys(this.columnDefinitions)) {
284
- this.columnDefinitions[prop] = null;
285
- }
286
- for (const prop of Object.keys(this.sharedService)) {
287
- this.sharedService[prop] = null;
288
- }
289
- // we could optionally also empty the content of the grid container DOM element
290
- if (shouldEmptyDomElementContainer) {
291
- this.emptyGridContainerElm();
292
- }
293
- // also unsubscribe all RxJS subscriptions
294
- this.subscriptions = unsubscribeAllObservables(this.subscriptions);
295
- this._dataset = null;
296
- this.datasetHierarchical = undefined;
297
- this._columnDefinitions = [];
298
- this._angularGridInstances = undefined;
299
- }
300
- emptyGridContainerElm() {
301
- var _a, _b;
302
- const gridContainerId = (_b = (_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.gridContainerId) !== null && _b !== void 0 ? _b : 'grid1';
303
- const gridContainerElm = document.querySelector(`#${gridContainerId}`);
304
- emptyElement(gridContainerElm);
305
- }
306
- /**
307
- * Define our internal Post Process callback, it will execute internally after we get back result from the Process backend call
308
- * For now, this is GraphQL Service ONLY feature and it will basically refresh the Dataset & Pagination without having the user to create his own PostProcess every time
309
- */
310
- createBackendApiInternalPostProcessCallback(gridOptions) {
311
- const backendApi = gridOptions && gridOptions.backendServiceApi;
312
- if (backendApi && backendApi.service) {
313
- const backendApiService = backendApi.service;
314
- // internalPostProcess only works (for now) with a GraphQL Service, so make sure it is of that type
315
- if (typeof backendApiService.getDatasetName === 'function') {
316
- backendApi.internalPostProcess = (processResult) => {
317
- const datasetName = (backendApi && backendApiService && typeof backendApiService.getDatasetName === 'function') ? backendApiService.getDatasetName() : '';
318
- if (processResult === null || processResult === void 0 ? void 0 : processResult.data[datasetName]) {
319
- const data = processResult.data[datasetName].hasOwnProperty('nodes') ? processResult.data[datasetName].nodes : processResult.data[datasetName];
320
- const totalCount = processResult.data[datasetName].hasOwnProperty('totalCount') ? processResult.data[datasetName].totalCount : processResult.data[datasetName].length;
321
- this.refreshGridData(data, totalCount || 0);
322
- }
323
- };
324
- }
325
- }
326
- }
327
- initialization(eventHandler) {
328
- var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
329
- this.gridOptions.translater = this.translaterService;
330
- this._eventHandler = eventHandler;
331
- // when detecting a frozen grid, we'll automatically enable the mousewheel scroll handler so that we can scroll from both left/right frozen containers
332
- if (this.gridOptions && ((this.gridOptions.frozenRow !== undefined && this.gridOptions.frozenRow >= 0) || this.gridOptions.frozenColumn !== undefined && this.gridOptions.frozenColumn >= 0) && this.gridOptions.enableMouseWheelScrollHandler === undefined) {
333
- this.gridOptions.enableMouseWheelScrollHandler = true;
334
- }
335
- this._eventPubSubService.eventNamingStyle = (_b = (_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.eventNamingStyle) !== null && _b !== void 0 ? _b : EventNamingStyle.camelCase;
336
- this._eventPubSubService.publish('onBeforeGridCreate', true);
337
- // make sure the dataset is initialized (if not it will throw an error that it cannot getLength of null)
338
- this._dataset = this._dataset || [];
339
- this.gridOptions = this.mergeGridOptions(this.gridOptions);
340
- this._paginationOptions = (_c = this.gridOptions) === null || _c === void 0 ? void 0 : _c.pagination;
341
- this.locales = (_f = (_d = this.gridOptions) === null || _d === void 0 ? void 0 : _d.locales) !== null && _f !== void 0 ? _f : Constants.locales;
342
- this.backendServiceApi = (_g = this.gridOptions) === null || _g === void 0 ? void 0 : _g.backendServiceApi;
343
- this._isLocalGrid = !this.backendServiceApi; // considered a local grid if it doesn't have a backend service set
344
- this.createBackendApiInternalPostProcessCallback(this.gridOptions);
345
- if (!this.customDataView) {
346
- const dataviewInlineFilters = this.gridOptions.dataView && this.gridOptions.dataView.inlineFilters || false;
347
- let dataViewOptions = { inlineFilters: dataviewInlineFilters };
348
- if (this.gridOptions.draggableGrouping || this.gridOptions.enableGrouping) {
349
- this.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
350
- this.sharedService.groupItemMetadataProvider = this.groupItemMetadataProvider;
351
- dataViewOptions = Object.assign(Object.assign({}, dataViewOptions), { groupItemMetadataProvider: this.groupItemMetadataProvider });
352
- }
353
- this.dataView = new Slick.Data.DataView(dataViewOptions);
354
- this._eventPubSubService.publish('onDataviewCreated', this.dataView);
355
- }
356
- // get any possible Services that user want to register which don't require SlickGrid to be instantiated
357
- // RxJS Resource is in this lot because it has to be registered before anything else and doesn't require SlickGrid to be initialized
358
- this.preRegisterResources();
359
- // for convenience to the user, we provide the property "editor" as an Angular-Slickgrid editor complex object
360
- // however "editor" is used internally by SlickGrid for it's own Editor Factory
361
- // so in our lib we will swap "editor" and copy it into a new property called "internalColumnEditor"
362
- // then take back "editor.model" and make it the new "editor" so that SlickGrid Editor Factory still works
363
- this._columnDefinitions = this.swapInternalEditorToSlickGridFactoryEditor(this._columnDefinitions);
364
- // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again
365
- if (this.gridOptions.autoAddCustomEditorFormatter) {
366
- autoAddEditorFormatterToColumnsWithEditor(this._columnDefinitions, this.gridOptions.autoAddCustomEditorFormatter);
367
- }
368
- // save reference for all columns before they optionally become hidden/visible
369
- this.sharedService.allColumns = this._columnDefinitions;
370
- this.sharedService.visibleColumns = this._columnDefinitions;
371
- this.extensionService.createExtensionsBeforeGridCreation(this._columnDefinitions, this.gridOptions);
372
- // if user entered some Pinning/Frozen "presets", we need to apply them in the grid options
373
- if ((_h = this.gridOptions.presets) === null || _h === void 0 ? void 0 : _h.pinning) {
374
- this.gridOptions = Object.assign(Object.assign({}, this.gridOptions), this.gridOptions.presets.pinning);
375
- }
376
- // build SlickGrid Grid, also user might optionally pass a custom dataview (e.g. remote model)
377
- this.slickGrid = new Slick.Grid(`#${this.gridId}`, this.customDataView || this.dataView, this._columnDefinitions, this.gridOptions);
378
- this.sharedService.dataView = this.dataView;
379
- this.sharedService.slickGrid = this.slickGrid;
380
- this.extensionService.bindDifferentExtensions();
381
- this.bindDifferentHooks(this.slickGrid, this.gridOptions, this.dataView);
382
- // when it's a frozen grid, we need to keep the frozen column id for reference if we ever show/hide column from ColumnPicker/GridMenu afterward
383
- const frozenColumnIndex = this.gridOptions.frozenColumn !== undefined ? this.gridOptions.frozenColumn : -1;
384
- if (frozenColumnIndex >= 0 && frozenColumnIndex <= this._columnDefinitions.length) {
385
- this.sharedService.frozenVisibleColumnId = this._columnDefinitions[frozenColumnIndex].id || '';
386
- }
387
- // get any possible Services that user want to register
388
- this.registerResources();
389
- // initialize the SlickGrid grid
390
- this.slickGrid.init();
391
- // initialized the resizer service only after SlickGrid is initialized
392
- // if we don't we end up binding our resize to a grid element that doesn't yet exist in the DOM and the resizer service will fail silently (because it has a try/catch that unbinds the resize without throwing back)
393
- if (this.gridContainerElement) {
394
- this.resizerService.init(this.slickGrid, this.gridContainerElement);
395
- }
396
- // user could show a custom footer with the data metrics (dataset length and last updated timestamp)
397
- if (!this.gridOptions.enablePagination && this.gridOptions.showCustomFooter && this.gridOptions.customFooterOptions && this.gridContainerElement) {
398
- this.slickFooter = new SlickFooterComponent(this.slickGrid, this.gridOptions.customFooterOptions, this._eventPubSubService, this.translaterService);
399
- this.slickFooter.renderFooter(this.gridContainerElement);
400
- }
401
- if (!this.customDataView && this.dataView) {
402
- // load the data in the DataView (unless it's a hierarchical dataset, if so it will be loaded after the initial tree sort)
403
- const initialDataset = ((_j = this.gridOptions) === null || _j === void 0 ? void 0 : _j.enableTreeData) ? this.sortTreeDataset(this._dataset) : this._dataset;
404
- this.dataView.beginUpdate();
405
- this.dataView.setItems(initialDataset || [], (_k = this.gridOptions.datasetIdPropertyName) !== null && _k !== void 0 ? _k : 'id');
406
- this.dataView.endUpdate();
407
- // if you don't want the items that are not visible (due to being filtered out or being on a different page)
408
- // to stay selected, pass 'false' to the second arg
409
- const selectionModel = this.slickGrid && this.slickGrid.getSelectionModel();
410
- if (selectionModel && this.gridOptions && this.gridOptions.dataView && this.gridOptions.dataView.hasOwnProperty('syncGridSelection')) {
411
- // if we are using a Backend Service, we will do an extra flag check, the reason is because it might have some unintended behaviors
412
- // with the BackendServiceApi because technically the data in the page changes the DataView on every page change.
413
- let preservedRowSelectionWithBackend = false;
414
- if (this.gridOptions.backendServiceApi && this.gridOptions.dataView.hasOwnProperty('syncGridSelectionWithBackendService')) {
415
- preservedRowSelectionWithBackend = this.gridOptions.dataView.syncGridSelectionWithBackendService;
416
- }
417
- const syncGridSelection = this.gridOptions.dataView.syncGridSelection;
418
- if (typeof syncGridSelection === 'boolean') {
419
- let preservedRowSelection = syncGridSelection;
420
- if (!this._isLocalGrid) {
421
- // when using BackendServiceApi, we'll be using the "syncGridSelectionWithBackendService" flag BUT "syncGridSelection" must also be set to True
422
- preservedRowSelection = syncGridSelection && preservedRowSelectionWithBackend;
423
- }
424
- this.dataView.syncGridSelection(this.slickGrid, preservedRowSelection);
425
- }
426
- else if (typeof syncGridSelection === 'object') {
427
- this.dataView.syncGridSelection(this.slickGrid, syncGridSelection.preserveHidden, syncGridSelection.preserveHiddenOnSelectionChange);
428
- }
429
- }
430
- const datasetLn = this.dataView.getLength() || this._dataset && this._dataset.length || 0;
431
- if (datasetLn > 0) {
432
- if (!this._isDatasetInitialized && (this.gridOptions.enableCheckboxSelector || this.gridOptions.enableRowSelection)) {
433
- this.loadRowSelectionPresetWhenExists();
434
- }
435
- this.loadFilterPresetsWhenDatasetInitialized();
436
- this._isDatasetInitialized = true;
437
- }
438
- }
439
- // user might want to hide the header row on page load but still have `enableFiltering: true`
440
- // if that is the case, we need to hide the headerRow ONLY AFTER all filters got created & dataView exist
441
- if (this._hideHeaderRowAfterPageLoad) {
442
- this.showHeaderRow(false);
443
- this.sharedService.hideHeaderRowAfterPageLoad = this._hideHeaderRowAfterPageLoad;
444
- }
445
- // publish & dispatch certain events
446
- this._eventPubSubService.publish('onGridCreated', this.slickGrid);
447
- // after the DataView is created & updated execute some processes
448
- if (!this.customDataView) {
449
- this.executeAfterDataviewCreated(this.slickGrid, this.gridOptions);
450
- }
451
- // bind resize ONLY after the dataView is ready
452
- this.bindResizeHook(this.slickGrid, this.gridOptions);
453
- // bind the Backend Service API callback functions only after the grid is initialized
454
- // because the preProcess() and onInit() might get triggered
455
- if ((_l = this.gridOptions) === null || _l === void 0 ? void 0 : _l.backendServiceApi) {
456
- this.bindBackendCallbackFunctions(this.gridOptions);
457
- }
458
- // local grid, check if we need to show the Pagination
459
- // if so then also check if there's any presets and finally initialize the PaginationService
460
- // a local grid with Pagination presets will potentially have a different total of items, we'll need to get it from the DataView and update our total
461
- if (((_m = this.gridOptions) === null || _m === void 0 ? void 0 : _m.enablePagination) && this._isLocalGrid) {
462
- this.showPagination = true;
463
- this.loadLocalGridPagination(this.dataset);
464
- }
465
- this._angularGridInstances = {
466
- // Slick Grid & DataView objects
467
- dataView: this.dataView,
468
- slickGrid: this.slickGrid,
469
- extensions: (_o = this.extensionService) === null || _o === void 0 ? void 0 : _o.extensionList,
470
- // public methods
471
- destroy: this.destroy.bind(this),
472
- // return all available Services (non-singleton)
473
- backendService: (_q = (_p = this.gridOptions) === null || _p === void 0 ? void 0 : _p.backendServiceApi) === null || _q === void 0 ? void 0 : _q.service,
474
- filterService: this.filterService,
475
- gridEventService: this.gridEventService,
476
- gridStateService: this.gridStateService,
477
- gridService: this.gridService,
478
- groupingService: this.groupingService,
479
- extensionService: this.extensionService,
480
- paginationService: this.paginationService,
481
- resizerService: this.resizerService,
482
- sortService: this.sortService,
483
- treeDataService: this.treeDataService,
484
- };
485
- // all instances (SlickGrid, DataView & all Services)
486
- this._eventPubSubService.publish('onAngularGridCreated', this._angularGridInstances);
487
- }
488
- /**
489
- * On a Pagination changed, we will trigger a Grid State changed with the new pagination info
490
- * Also if we use Row Selection or the Checkbox Selector, we need to reset any selection
491
- */
492
- paginationChanged(pagination) {
493
- var _a, _b;
494
- const isSyncGridSelectionEnabled = (_b = (_a = this.gridStateService) === null || _a === void 0 ? void 0 : _a.needToPreserveRowSelection()) !== null && _b !== void 0 ? _b : false;
495
- if (!isSyncGridSelectionEnabled && (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector)) {
496
- this.slickGrid.setSelectedRows([]);
497
- }
498
- const { pageNumber, pageSize } = pagination;
499
- if (this.sharedService) {
500
- if (pageSize !== undefined && pageNumber !== undefined) {
501
- this.sharedService.currentPagination = { pageNumber, pageSize };
502
- }
503
- }
504
- this._eventPubSubService.publish('onGridStateChanged', {
505
- change: { newValues: { pageNumber, pageSize }, type: GridStateType.pagination },
506
- gridState: this.gridStateService.getCurrentGridState()
507
- });
508
- this.cd.markForCheck();
509
- }
510
- /**
511
- * When dataset changes, we need to refresh the entire grid UI & possibly resize it as well
512
- * @param dataset
513
- */
514
- refreshGridData(dataset, totalCount) {
515
- var _a, _b, _c, _d, _f, _g;
516
- if (this.gridOptions && this.gridOptions.enableEmptyDataWarningMessage && Array.isArray(dataset)) {
517
- const finalTotalCount = totalCount || dataset.length;
518
- this.displayEmptyDataWarning(finalTotalCount < 1);
519
- }
520
- if (Array.isArray(dataset) && this.slickGrid && ((_a = this.dataView) === null || _a === void 0 ? void 0 : _a.setItems)) {
521
- this.dataView.setItems(dataset, (_b = this.gridOptions.datasetIdPropertyName) !== null && _b !== void 0 ? _b : 'id');
522
- if (!this.gridOptions.backendServiceApi && !this.gridOptions.enableTreeData) {
523
- this.dataView.reSort();
524
- }
525
- if (dataset.length > 0) {
526
- if (!this._isDatasetInitialized) {
527
- this.loadFilterPresetsWhenDatasetInitialized();
528
- if (this.gridOptions.enableCheckboxSelector) {
529
- this.loadRowSelectionPresetWhenExists();
530
- }
531
- }
532
- this._isDatasetInitialized = true;
533
- }
534
- if (dataset) {
535
- this.slickGrid.invalidate();
536
- }
537
- // display the Pagination component only after calling this refresh data first, we call it here so that if we preset pagination page number it will be shown correctly
538
- this.showPagination = (this.gridOptions && (this.gridOptions.enablePagination || (this.gridOptions.backendServiceApi && this.gridOptions.enablePagination === undefined))) ? true : false;
539
- if (this._paginationOptions && ((_c = this.gridOptions) === null || _c === void 0 ? void 0 : _c.pagination) && ((_d = this.gridOptions) === null || _d === void 0 ? void 0 : _d.backendServiceApi)) {
540
- const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this._paginationOptions);
541
- // when we have a totalCount use it, else we'll take it from the pagination object
542
- // only update the total items if it's different to avoid refreshing the UI
543
- const totalRecords = (totalCount !== undefined) ? totalCount : ((_g = (_f = this.gridOptions) === null || _f === void 0 ? void 0 : _f.pagination) === null || _g === void 0 ? void 0 : _g.totalItems);
544
- if (totalRecords !== undefined && totalRecords !== this.totalItems) {
545
- this.totalItems = +totalRecords;
546
- }
547
- // initialize the Pagination Service with new pagination options (which might have presets)
548
- if (!this._isPaginationInitialized) {
549
- this.initializePaginationService(paginationOptions);
550
- }
551
- else {
552
- // update the pagination service with the new total
553
- this.paginationService.updateTotalItems(this.totalItems);
554
- }
555
- }
556
- // resize the grid inside a slight timeout, in case other DOM element changed prior to the resize (like a filter/pagination changed)
557
- if (this.slickGrid && this.gridOptions.enableAutoResize) {
558
- const delay = this.gridOptions.autoResize && this.gridOptions.autoResize.delay;
559
- this.resizerService.resizeGrid(delay || 10);
560
- }
561
- }
562
- }
563
- /**
564
- * Check if there's any Pagination Presets defined in the Grid Options,
565
- * if there are then load them in the paginationOptions object
566
- */
567
- setPaginationOptionsWhenPresetDefined(gridOptions, paginationOptions) {
568
- var _a;
569
- if (((_a = gridOptions.presets) === null || _a === void 0 ? void 0 : _a.pagination) && paginationOptions && !this._isPaginationInitialized) {
570
- paginationOptions.pageSize = gridOptions.presets.pagination.pageSize;
571
- paginationOptions.pageNumber = gridOptions.presets.pagination.pageNumber;
572
- }
573
- return paginationOptions;
574
- }
575
- /**
576
- * Dynamically change or update the column definitions list.
577
- * We will re-render the grid so that the new header and data shows up correctly.
578
- * If using i18n, we also need to trigger a re-translate of the column headers
579
- */
580
- updateColumnDefinitionsList(newColumnDefinitions) {
581
- var _a, _b, _c;
582
- // map/swap the internal library Editor to the SlickGrid Editor factory
583
- newColumnDefinitions = this.swapInternalEditorToSlickGridFactoryEditor(newColumnDefinitions);
584
- if (this.gridOptions.enableTranslate) {
585
- this.extensionService.translateColumnHeaders(false, newColumnDefinitions);
586
- }
587
- else {
588
- this.extensionService.renderColumnHeaders(newColumnDefinitions, true);
589
- }
590
- if ((_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.enableAutoSizeColumns) {
591
- this.slickGrid.autosizeColumns();
592
- }
593
- else if (((_b = this.gridOptions) === null || _b === void 0 ? void 0 : _b.enableAutoResizeColumnsByCellContent) && ((_c = this.resizerService) === null || _c === void 0 ? void 0 : _c.resizeColumnsByCellContent)) {
594
- this.resizerService.resizeColumnsByCellContent();
595
- }
596
- }
597
- /**
598
- * Show the filter row displayed on first row, we can optionally pass false to hide it.
599
- * @param showing
600
- */
601
- showHeaderRow(showing = true) {
602
- this.slickGrid.setHeaderRowVisibility(showing, false);
603
- if (showing === true && this._isGridInitialized) {
604
- this.slickGrid.setColumns(this.columnDefinitions);
605
- }
606
- return showing;
607
- }
608
- //
609
- // private functions
610
- // ------------------
611
- /**
612
- * Loop through all column definitions and copy the original optional `width` properties optionally provided by the user.
613
- * We will use this when doing a resize by cell content, if user provided a `width` it won't override it.
614
- */
615
- copyColumnWidthsReference(columnDefinitions) {
616
- columnDefinitions.forEach(col => col.originalWidth = col.width);
617
- }
618
- displayEmptyDataWarning(showWarning = true) {
619
- var _a;
620
- (_a = this.slickEmptyWarning) === null || _a === void 0 ? void 0 : _a.showEmptyDataMessage(showWarning);
621
- }
622
- bindDifferentHooks(grid, gridOptions, dataView) {
623
- var _a, _b, _c, _d;
624
- // on locale change, we have to manually translate the Headers, GridMenu
625
- if ((_a = this.translate) === null || _a === void 0 ? void 0 : _a.onLangChange) {
626
- // translate some of them on first load, then on each language change
627
- if (gridOptions.enableTranslate) {
628
- this.translateColumnHeaderTitleKeys();
629
- this.translateColumnGroupKeys();
630
- }
631
- this.subscriptions.push(this.translate.onLangChange.subscribe(() => {
632
- // publish event of the same name that Slickgrid-Universal uses on a language change event
633
- this._eventPubSubService.publish('onLanguageChange');
634
- if (gridOptions.enableTranslate) {
635
- this.extensionService.translateCellMenu();
636
- this.extensionService.translateColumnHeaders();
637
- this.extensionService.translateColumnPicker();
638
- this.extensionService.translateContextMenu();
639
- this.extensionService.translateGridMenu();
640
- this.extensionService.translateHeaderMenu();
641
- this.translateColumnHeaderTitleKeys();
642
- this.translateColumnGroupKeys();
643
- if (gridOptions.createPreHeaderPanel && !gridOptions.enableDraggableGrouping) {
644
- this.groupingService.translateGroupingAndColSpan();
645
- }
646
- }
647
- }));
648
- }
649
- // if user set an onInit Backend, we'll run it right away (and if so, we also need to run preProcess, internalPostProcess & postProcess)
650
- if (gridOptions.backendServiceApi) {
651
- const backendApi = gridOptions.backendServiceApi;
652
- if ((_b = backendApi === null || backendApi === void 0 ? void 0 : backendApi.service) === null || _b === void 0 ? void 0 : _b.init) {
653
- backendApi.service.init(backendApi.options, gridOptions.pagination, this.slickGrid, this.sharedService);
654
- }
655
- }
656
- if (dataView && grid) {
657
- const slickgridEventPrefix = (_d = (_c = this.gridOptions) === null || _c === void 0 ? void 0 : _c.defaultSlickgridEventPrefix) !== null && _d !== void 0 ? _d : '';
658
- // expose all Slick Grid Events through dispatch
659
- for (const prop in grid) {
660
- if (grid.hasOwnProperty(prop) && prop.startsWith('on')) {
661
- const gridEventHandler = grid[prop];
662
- const gridEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, slickgridEventPrefix);
663
- this._eventHandler.subscribe(gridEventHandler, (event, args) => {
664
- return this._eventPubSubService.dispatchCustomEvent(gridEventName, { eventData: event, args });
665
- });
666
- }
667
- }
668
- // expose all Slick DataView Events through dispatch
669
- for (const prop in dataView) {
670
- if (dataView.hasOwnProperty(prop) && prop.startsWith('on')) {
671
- const dataViewEventHandler = dataView[prop];
672
- this._eventHandler.subscribe(dataViewEventHandler, (event, args) => {
673
- const dataViewEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, slickgridEventPrefix);
674
- return this._eventPubSubService.dispatchCustomEvent(dataViewEventName, { eventData: event, args });
675
- });
676
- }
677
- }
678
- // on cell click, mainly used with the columnDef.action callback
679
- this.gridEventService.bindOnCellChange(grid);
680
- this.gridEventService.bindOnClick(grid);
681
- if (dataView && grid) {
682
- // bind external sorting (backend) when available or default onSort (dataView)
683
- if (gridOptions.enableSorting) {
684
- // bind external sorting (backend) unless specified to use the local one
685
- if (gridOptions.backendServiceApi && !gridOptions.backendServiceApi.useLocalSorting) {
686
- this.sortService.bindBackendOnSort(grid);
687
- }
688
- else {
689
- this.sortService.bindLocalOnSort(grid);
690
- }
691
- }
692
- // bind external filter (backend) when available or default onFilter (dataView)
693
- if (gridOptions.enableFiltering) {
694
- this.filterService.init(grid);
695
- // bind external filter (backend) unless specified to use the local one
696
- if (gridOptions.backendServiceApi && !gridOptions.backendServiceApi.useLocalFiltering) {
697
- this.filterService.bindBackendOnFilter(grid);
698
- }
699
- else {
700
- this.filterService.bindLocalOnFilter(grid);
701
- }
702
- }
703
- // load any presets if any (after dataset is initialized)
704
- this.loadColumnPresetsWhenDatasetInitialized();
705
- this.loadFilterPresetsWhenDatasetInitialized();
706
- // When data changes in the DataView, we need to refresh the metrics and/or display a warning if the dataset is empty
707
- const onRowCountChangedHandler = dataView.onRowCountChanged;
708
- this._eventHandler.subscribe(onRowCountChangedHandler, (_e, args) => {
709
- grid.invalidate();
710
- this.handleOnItemCountChanged(this.dataView.getFilteredItemCount() || 0, dataView.getItemCount());
711
- });
712
- const onSetItemsCalledHandler = dataView.onSetItemsCalled;
713
- this._eventHandler.subscribe(onSetItemsCalledHandler, (_e, args) => {
714
- var _a;
715
- grid.invalidate();
716
- this.handleOnItemCountChanged(this.dataView.getFilteredItemCount(), args.itemCount);
717
- // when user has resize by content enabled, we'll force a full width calculation since we change our entire dataset
718
- if (args.itemCount > 0 && (this.gridOptions.autosizeColumnsByCellContentOnFirstLoad || this.gridOptions.enableAutoResizeColumnsByCellContent)) {
719
- this.resizerService.resizeColumnsByCellContent(!((_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.resizeByContentOnlyOnFirstLoad));
720
- }
721
- });
722
- const onRowsChangedHandler = dataView.onRowsChanged;
723
- this._eventHandler.subscribe(onRowsChangedHandler, (_e, args) => {
724
- // filtering data with local dataset will not always show correctly unless we call this updateRow/render
725
- // also don't use "invalidateRows" since it destroys the entire row and as bad user experience when updating a row
726
- // see commit: https://github.com/ghiscoding/aurelia-slickgrid/commit/8c503a4d45fba11cbd8d8cc467fae8d177cc4f60
727
- if (gridOptions && gridOptions.enableFiltering && !gridOptions.enableRowDetailView) {
728
- if ((args === null || args === void 0 ? void 0 : args.rows) && Array.isArray(args.rows)) {
729
- args.rows.forEach((row) => grid.updateRow(row));
730
- grid.render();
731
- }
732
- }
733
- });
734
- }
735
- }
736
- // did the user add a colspan callback? If so, hook it into the DataView getItemMetadata
737
- if (gridOptions && gridOptions.colspanCallback && dataView && dataView.getItem && dataView.getItemMetadata) {
738
- dataView.getItemMetadata = (rowNumber) => {
739
- let callbackResult = null;
740
- if (gridOptions.colspanCallback && gridOptions.colspanCallback) {
741
- callbackResult = gridOptions.colspanCallback(dataView.getItem(rowNumber));
742
- }
743
- return callbackResult;
744
- };
745
- }
746
- }
747
- bindBackendCallbackFunctions(gridOptions) {
748
- var _a;
749
- const backendApi = gridOptions.backendServiceApi;
750
- const backendApiService = backendApi && backendApi.service;
751
- const serviceOptions = (_a = backendApiService === null || backendApiService === void 0 ? void 0 : backendApiService.options) !== null && _a !== void 0 ? _a : {};
752
- const isExecuteCommandOnInit = (!serviceOptions) ? false : ((serviceOptions && serviceOptions.hasOwnProperty('executeProcessCommandOnInit')) ? serviceOptions['executeProcessCommandOnInit'] : true);
753
- if (backendApiService) {
754
- // update backend filters (if need be) BEFORE the query runs (via the onInit command a few lines below)
755
- // if user entered some any "presets", we need to reflect them all in the grid
756
- if (gridOptions && gridOptions.presets) {
757
- // Filters "presets"
758
- if (backendApiService.updateFilters && Array.isArray(gridOptions.presets.filters) && gridOptions.presets.filters.length > 0) {
759
- backendApiService.updateFilters(gridOptions.presets.filters, true);
760
- }
761
- // Sorters "presets"
762
- if (backendApiService.updateSorters && Array.isArray(gridOptions.presets.sorters) && gridOptions.presets.sorters.length > 0) {
763
- // when using multi-column sort, we can have multiple but on single sort then only grab the first sort provided
764
- const sortColumns = this.gridOptions.multiColumnSort ? gridOptions.presets.sorters : gridOptions.presets.sorters.slice(0, 1);
765
- backendApiService.updateSorters(undefined, sortColumns);
766
- }
767
- // Pagination "presets"
768
- if (backendApiService.updatePagination && gridOptions.presets.pagination) {
769
- const { pageNumber, pageSize } = gridOptions.presets.pagination;
770
- backendApiService.updatePagination(pageNumber, pageSize);
771
- }
772
- }
773
- else {
774
- const columnFilters = this.filterService.getColumnFilters();
775
- if (columnFilters && backendApiService.updateFilters) {
776
- backendApiService.updateFilters(columnFilters, false);
777
- }
778
- }
779
- // execute onInit command when necessary
780
- if (backendApi && backendApiService && (backendApi.onInit || isExecuteCommandOnInit)) {
781
- const query = (typeof backendApiService.buildQuery === 'function') ? backendApiService.buildQuery() : '';
782
- const process = (isExecuteCommandOnInit) ? (backendApi.process && backendApi.process(query) || null) : (backendApi.onInit && backendApi.onInit(query) || null);
783
- // wrap this inside a setTimeout to avoid timing issue since the gridOptions needs to be ready before running this onInit
784
- setTimeout(() => {
785
- var _a, _b, _c, _d;
786
- const backendUtilityService = this.backendUtilityService;
787
- // keep start time & end timestamps & return it after process execution
788
- const startTime = new Date();
789
- // run any pre-process, if defined, for example a spinner
790
- if (backendApi.preProcess) {
791
- backendApi.preProcess();
792
- }
793
- // the processes can be a Promise (like Http)
794
- const totalItems = (_c = (_b = (_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.totalItems) !== null && _c !== void 0 ? _c : 0;
795
- if (process instanceof Promise) {
796
- process
797
- .then((processResult) => backendUtilityService.executeBackendProcessesCallback(startTime, processResult, backendApi, totalItems))
798
- .catch((error) => backendUtilityService.onBackendError(error, backendApi));
799
- }
800
- else if (process && ((_d = this.rxjs) === null || _d === void 0 ? void 0 : _d.isObservable(process))) {
801
- this.subscriptions.push(process.subscribe({
802
- next: (processResult) => backendUtilityService.executeBackendProcessesCallback(startTime, processResult, backendApi, totalItems),
803
- error: (error) => backendUtilityService.onBackendError(error, backendApi)
804
- }));
805
- }
806
- });
807
- }
808
- }
809
- }
810
- bindResizeHook(grid, options) {
811
- if ((options.autoFitColumnsOnFirstLoad && options.autosizeColumnsByCellContentOnFirstLoad) || (options.enableAutoSizeColumns && options.enableAutoResizeColumnsByCellContent)) {
812
- throw new Error(`[Angular-Slickgrid] You cannot enable both autosize/fit viewport & resize by content, you must choose which resize technique to use. You can enable these 2 options ("autoFitColumnsOnFirstLoad" and "enableAutoSizeColumns") OR these other 2 options ("autosizeColumnsByCellContentOnFirstLoad" and "enableAutoResizeColumnsByCellContent").`);
813
- }
814
- // expand/autofit columns on first page load
815
- if (grid && options.autoFitColumnsOnFirstLoad && options.enableAutoSizeColumns) {
816
- grid.autosizeColumns();
817
- }
818
- // auto-resize grid on browser resize
819
- if (options.gridHeight || options.gridWidth) {
820
- this.resizerService.resizeGrid(0, { height: options.gridHeight, width: options.gridWidth });
821
- }
822
- else {
823
- this.resizerService.resizeGrid();
824
- }
825
- if (options.enableAutoResize) {
826
- if (grid && options.autoFitColumnsOnFirstLoad && options.enableAutoSizeColumns) {
827
- grid.autosizeColumns();
828
- }
829
- }
830
- }
831
- executeAfterDataviewCreated(_grid, gridOptions) {
832
- // if user entered some Sort "presets", we need to reflect them all in the DOM
833
- if (gridOptions.enableSorting) {
834
- if (gridOptions.presets && Array.isArray(gridOptions.presets.sorters)) {
835
- // when using multi-column sort, we can have multiple but on single sort then only grab the first sort provided
836
- const sortColumns = this.gridOptions.multiColumnSort ? gridOptions.presets.sorters : gridOptions.presets.sorters.slice(0, 1);
837
- this.sortService.loadGridSorters(sortColumns);
838
- }
839
- }
840
- }
841
- /** When data changes in the DataView, we'll refresh the metrics and/or display a warning if the dataset is empty */
842
- handleOnItemCountChanged(currentPageRowItemCount, totalItemCount) {
843
- var _a;
844
- this._currentDatasetLength = totalItemCount;
845
- this.metrics = {
846
- startTime: new Date(),
847
- endTime: new Date(),
848
- itemCount: currentPageRowItemCount,
849
- totalItemCount
850
- };
851
- // if custom footer is enabled, then we'll update its metrics
852
- if (this.slickFooter) {
853
- this.slickFooter.metrics = this.metrics;
854
- }
855
- // when using local (in-memory) dataset, we'll display a warning message when filtered data is empty
856
- if (this._isLocalGrid && ((_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.enableEmptyDataWarningMessage)) {
857
- this.displayEmptyDataWarning(currentPageRowItemCount === 0);
858
- }
859
- }
860
- initializePaginationService(paginationOptions) {
861
- if (this.gridOptions) {
862
- this.paginationData = {
863
- gridOptions: this.gridOptions,
864
- paginationService: this.paginationService,
865
- };
866
- this.paginationService.totalItems = this.totalItems;
867
- this.paginationService.init(this.slickGrid, paginationOptions, this.backendServiceApi);
868
- this.subscriptions.push(this._eventPubSubService.subscribe('onPaginationChanged', (paginationChanges) => {
869
- this.paginationChanged(paginationChanges);
870
- }), this._eventPubSubService.subscribe('onPaginationVisibilityChanged', (visibility) => {
871
- var _a, _b, _c;
872
- this.showPagination = (_a = visibility === null || visibility === void 0 ? void 0 : visibility.visible) !== null && _a !== void 0 ? _a : false;
873
- if ((_b = this.gridOptions) === null || _b === void 0 ? void 0 : _b.backendServiceApi) {
874
- (_c = this.backendUtilityService) === null || _c === void 0 ? void 0 : _c.refreshBackendDataset(this.gridOptions);
875
- }
876
- this.renderPagination(this.showPagination);
877
- }));
878
- // also initialize (render) the pagination component
879
- this.renderPagination();
880
- this._isPaginationInitialized = true;
881
- }
882
- this.cd.detectChanges();
883
- }
884
- /** Load the Editor Collection asynchronously and replace the "collection" property when Observable resolves */
885
- loadEditorCollectionAsync(column) {
886
- const collectionAsync = column && column.editor && column.editor.collectionAsync;
887
- if (collectionAsync instanceof Observable) {
888
- this.subscriptions.push(collectionAsync.subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection)));
889
- }
890
- else if (collectionAsync instanceof Promise) {
891
- // wait for the "collectionAsync", once resolved we will save it into the "collection"
892
- // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise
893
- collectionAsync.then((response) => {
894
- if (Array.isArray(response)) {
895
- this.updateEditorCollection(column, response); // from Promise
896
- }
897
- });
898
- }
899
- }
900
- /** Load any possible Columns Grid Presets */
901
- loadColumnPresetsWhenDatasetInitialized() {
902
- // if user entered some Columns "presets", we need to reflect them all in the grid
903
- if (this.gridOptions.presets && Array.isArray(this.gridOptions.presets.columns) && this.gridOptions.presets.columns.length > 0) {
904
- const gridColumns = this.gridStateService.getAssociatedGridColumns(this.slickGrid, this.gridOptions.presets.columns);
905
- if (gridColumns && Array.isArray(gridColumns) && gridColumns.length > 0) {
906
- // make sure that the checkbox selector is also visible if it is enabled
907
- if (this.gridOptions.enableCheckboxSelector) {
908
- const checkboxColumn = (Array.isArray(this._columnDefinitions) && this._columnDefinitions.length > 0) ? this._columnDefinitions[0] : null;
909
- if (checkboxColumn && checkboxColumn.id === '_checkbox_selector' && gridColumns[0].id !== '_checkbox_selector') {
910
- gridColumns.unshift(checkboxColumn);
911
- }
912
- }
913
- // keep copy the original optional `width` properties optionally provided by the user.
914
- // We will use this when doing a resize by cell content, if user provided a `width` it won't override it.
915
- gridColumns.forEach(col => col.originalWidth = col.width);
916
- // finally set the new presets columns (including checkbox selector if need be)
917
- this.slickGrid.setColumns(gridColumns);
918
- this.sharedService.visibleColumns = gridColumns;
919
- }
920
- }
921
- }
922
- /** Load any possible Filters Grid Presets */
923
- loadFilterPresetsWhenDatasetInitialized() {
924
- var _a, _b, _c;
925
- if (this.gridOptions && !this.customDataView) {
926
- // if user entered some Filter "presets", we need to reflect them all in the DOM
927
- // also note that a presets of Tree Data Toggling will also call this method because Tree Data toggling does work with data filtering
928
- // (collapsing a parent will basically use Filter for hidding (aka collapsing) away the child underneat it)
929
- if (this.gridOptions.presets && (Array.isArray(this.gridOptions.presets.filters) || Array.isArray((_b = (_a = this.gridOptions.presets) === null || _a === void 0 ? void 0 : _a.treeData) === null || _b === void 0 ? void 0 : _b.toggledItems))) {
930
- this.filterService.populateColumnFilterSearchTermPresets(((_c = this.gridOptions.presets) === null || _c === void 0 ? void 0 : _c.filters) || []);
931
- }
932
- }
933
- }
934
- /**
935
- * local grid, check if we need to show the Pagination
936
- * if so then also check if there's any presets and finally initialize the PaginationService
937
- * a local grid with Pagination presets will potentially have a different total of items, we'll need to get it from the DataView and update our total
938
- */
939
- loadLocalGridPagination(dataset) {
940
- var _a;
941
- if (this.gridOptions && this._paginationOptions) {
942
- this.totalItems = Array.isArray(dataset) ? dataset.length : 0;
943
- if (this._paginationOptions && ((_a = this.dataView) === null || _a === void 0 ? void 0 : _a.getPagingInfo)) {
944
- const slickPagingInfo = this.dataView.getPagingInfo();
945
- if ((slickPagingInfo === null || slickPagingInfo === void 0 ? void 0 : slickPagingInfo.hasOwnProperty('totalRows')) && this._paginationOptions.totalItems !== slickPagingInfo.totalRows) {
946
- this.totalItems = slickPagingInfo.totalRows || 0;
947
- }
948
- }
949
- this._paginationOptions.totalItems = this.totalItems;
950
- const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this._paginationOptions);
951
- this.initializePaginationService(paginationOptions);
952
- }
953
- }
954
- /** Load any Row Selections into the DataView that were presets by the user */
955
- loadRowSelectionPresetWhenExists() {
956
- var _a, _b, _c;
957
- // if user entered some Row Selections "presets"
958
- const presets = (_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.presets;
959
- const selectionModel = (_c = (_b = this.slickGrid) === null || _b === void 0 ? void 0 : _b.getSelectionModel) === null || _c === void 0 ? void 0 : _c.call(_b);
960
- const enableRowSelection = this.gridOptions && (this.gridOptions.enableCheckboxSelector || this.gridOptions.enableRowSelection);
961
- if (enableRowSelection && selectionModel && presets && presets.rowSelection && (Array.isArray(presets.rowSelection.gridRowIndexes) || Array.isArray(presets.rowSelection.dataContextIds))) {
962
- let dataContextIds = presets.rowSelection.dataContextIds;
963
- let gridRowIndexes = presets.rowSelection.gridRowIndexes;
964
- // maps the IDs to the Grid Rows and vice versa, the "dataContextIds" has precedence over the other
965
- if (Array.isArray(dataContextIds) && dataContextIds.length > 0) {
966
- gridRowIndexes = this.dataView.mapIdsToRows(dataContextIds) || [];
967
- }
968
- else if (Array.isArray(gridRowIndexes) && gridRowIndexes.length > 0) {
969
- dataContextIds = this.dataView.mapRowsToIds(gridRowIndexes) || [];
970
- }
971
- this.gridStateService.selectedRowDataContextIds = dataContextIds;
972
- // change the selected rows except UNLESS it's a Local Grid with Pagination
973
- // local Pagination uses the DataView and that also trigger a change/refresh
974
- // and we don't want to trigger 2 Grid State changes just 1
975
- if ((this._isLocalGrid && !this.gridOptions.enablePagination) || !this._isLocalGrid) {
976
- setTimeout(() => {
977
- if (this.slickGrid && Array.isArray(gridRowIndexes)) {
978
- this.slickGrid.setSelectedRows(gridRowIndexes);
979
- }
980
- });
981
- }
982
- }
983
- }
984
- mergeGridOptions(gridOptions) {
985
- gridOptions.gridId = this.gridId;
986
- gridOptions.gridContainerId = `slickGridContainer-${this.gridId}`;
987
- // if we have a backendServiceApi and the enablePagination is undefined, we'll assume that we do want to see it, else get that defined value
988
- gridOptions.enablePagination = ((gridOptions.backendServiceApi && gridOptions.enablePagination === undefined) ? true : gridOptions.enablePagination) || false;
989
- // use jquery extend to deep merge & copy to avoid immutable properties being changed in GlobalGridOptions after a route change
990
- const options = $.extend(true, {}, GlobalGridOptions, this.forRootConfig, gridOptions);
991
- // using jQuery extend to do a deep clone has an unwanted side on objects and pageSizes but ES6 spread has other worst side effects
992
- // so we will just overwrite the pageSizes when needed, this is the only one causing issues so far.
993
- // jQuery wrote this on their docs:: On a deep extend, Object and Array are extended, but object wrappers on primitive types such as String, Boolean, and Number are not.
994
- if ((options === null || options === void 0 ? void 0 : options.pagination) && (gridOptions.enablePagination || gridOptions.backendServiceApi) && gridOptions.pagination && Array.isArray(gridOptions.pagination.pageSizes)) {
995
- options.pagination.pageSizes = gridOptions.pagination.pageSizes;
996
- }
997
- // also make sure to show the header row if user have enabled filtering
998
- this._hideHeaderRowAfterPageLoad = (options.showHeaderRow === false);
999
- if (options.enableFiltering && !options.showHeaderRow) {
1000
- options.showHeaderRow = options.enableFiltering;
1001
- }
1002
- // when we use Pagination on Local Grid, it doesn't seem to work without enableFiltering
1003
- // so we'll enable the filtering but we'll keep the header row hidden
1004
- if (options && !options.enableFiltering && options.enablePagination && this._isLocalGrid) {
1005
- options.enableFiltering = true;
1006
- options.showHeaderRow = false;
1007
- this._hideHeaderRowAfterPageLoad = true;
1008
- if (this.sharedService) {
1009
- this.sharedService.hideHeaderRowAfterPageLoad = true;
1010
- }
1011
- }
1012
- return options;
1013
- }
1014
- /** Pre-Register any Resource that don't require SlickGrid to be instantiated (for example RxJS Resource) */
1015
- preRegisterResources() {
1016
- this._registeredResources = this.gridOptions.registerExternalResources || [];
1017
- // Angular-Slickgrid requires RxJS, so we'll register it as the first resource
1018
- this.registerRxJsResource(new RxJsResource());
1019
- }
1020
- registerResources() {
1021
- // at this point, we consider all the registered services as external services, anything else registered afterward aren't external
1022
- if (Array.isArray(this._registeredResources)) {
1023
- this.sharedService.externalRegisteredResources = this._registeredResources;
1024
- }
1025
- // push all other Services that we want to be registered
1026
- this._registeredResources.push(this.gridService, this.gridStateService);
1027
- // when using Grouping/DraggableGrouping/Colspan register its Service
1028
- if (this.gridOptions.createPreHeaderPanel && !this.gridOptions.enableDraggableGrouping) {
1029
- this._registeredResources.push(this.groupingService);
1030
- }
1031
- // when using Tree Data View, register its Service
1032
- if (this.gridOptions.enableTreeData) {
1033
- this._registeredResources.push(this.treeDataService);
1034
- }
1035
- // when user enables translation, we need to translate Headers on first pass & subsequently in the bindDifferentHooks
1036
- if (this.gridOptions.enableTranslate) {
1037
- this.extensionService.translateColumnHeaders();
1038
- }
1039
- // also initialize (render) the empty warning component
1040
- this.slickEmptyWarning = new SlickEmptyWarningComponent();
1041
- this._registeredResources.push(this.slickEmptyWarning);
1042
- // bind & initialize all Components/Services that were tagged as enabled
1043
- // register all services by executing their init method and providing them with the Grid object
1044
- if (Array.isArray(this._registeredResources)) {
1045
- for (const resource of this._registeredResources) {
1046
- if (typeof resource.init === 'function') {
1047
- resource.init(this.slickGrid, this.containerService);
1048
- }
1049
- }
1050
- }
1051
- }
1052
- /** Register the RxJS Resource in all necessary services which uses */
1053
- registerRxJsResource(resource) {
1054
- this.rxjs = resource;
1055
- this.backendUtilityService.addRxJsResource(this.rxjs);
1056
- this.filterFactory.addRxJsResource(this.rxjs);
1057
- this.filterService.addRxJsResource(this.rxjs);
1058
- this.sortService.addRxJsResource(this.rxjs);
1059
- this.paginationService.addRxJsResource(this.rxjs);
1060
- this.containerService.registerInstance('RxJsResource', this.rxjs);
1061
- }
1062
- /**
1063
- * Render (or dispose) the Pagination Component, user can optionally provide False (to not show it) which will in term dispose of the Pagination,
1064
- * also while disposing we can choose to omit the disposable of the Pagination Service (if we are simply toggling the Pagination, we want to keep the Service alive)
1065
- * @param {Boolean} showPagination - show (new render) or not (dispose) the Pagination
1066
- * @param {Boolean} shouldDisposePaginationService - when disposing the Pagination, do we also want to dispose of the Pagination Service? (defaults to True)
1067
- */
1068
- renderPagination(showPagination = true) {
1069
- var _a;
1070
- if (((_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.enablePagination) && !this._isPaginationInitialized && showPagination) {
1071
- this.slickPagination = new SlickPaginationComponent(this.paginationService, this._eventPubSubService, this.sharedService, this.translaterService);
1072
- this.slickPagination.renderPagination(this.gridContainerElement);
1073
- this._isPaginationInitialized = true;
1074
- }
1075
- else if (!showPagination) {
1076
- if (this.slickPagination) {
1077
- this.slickPagination.dispose();
1078
- }
1079
- this._isPaginationInitialized = false;
1080
- }
1081
- }
1082
- /**
1083
- * Takes a flat dataset with parent/child relationship, sort it (via its tree structure) and return the sorted flat array
1084
- * @param {Array<Object>} flatDatasetInput - flat dataset input
1085
- * @param {Boolean} forceGridRefresh - optionally force a full grid refresh
1086
- * @returns {Array<Object>} sort flat parent/child dataset
1087
- */
1088
- sortTreeDataset(flatDatasetInput, forceGridRefresh = false) {
1089
- var _a, _b;
1090
- const prevDatasetLn = this._currentDatasetLength;
1091
- let sortedDatasetResult;
1092
- let flatDatasetOutput = [];
1093
- // if the hierarchical dataset was already initialized then no need to re-convert it, we can use it directly from the shared service ref
1094
- if (this._isDatasetHierarchicalInitialized && this.datasetHierarchical) {
1095
- sortedDatasetResult = this.treeDataService.sortHierarchicalDataset(this.datasetHierarchical);
1096
- flatDatasetOutput = sortedDatasetResult.flat;
1097
- }
1098
- else if (Array.isArray(flatDatasetInput) && flatDatasetInput.length > 0) {
1099
- if ((_b = (_a = this.gridOptions) === null || _a === void 0 ? void 0 : _a.treeDataOptions) === null || _b === void 0 ? void 0 : _b.initialSort) {
1100
- // else we need to first convert the flat dataset to a hierarchical dataset and then sort
1101
- sortedDatasetResult = this.treeDataService.convertFlatParentChildToTreeDatasetAndSort(flatDatasetInput, this._columnDefinitions, this.gridOptions);
1102
- this.sharedService.hierarchicalDataset = sortedDatasetResult.hierarchical;
1103
- flatDatasetOutput = sortedDatasetResult.flat;
1104
- }
1105
- else {
1106
- // else we assume that the user provided an array that is already sorted (user's responsability)
1107
- // and so we can simply convert the array to a tree structure and we're done, no need to sort
1108
- this.sharedService.hierarchicalDataset = this.treeDataService.convertFlatParentChildToTreeDataset(flatDatasetInput, this.gridOptions);
1109
- flatDatasetOutput = flatDatasetInput || [];
1110
- }
1111
- }
1112
- // if we add/remove item(s) from the dataset, we need to also refresh our tree data filters
1113
- if (flatDatasetInput.length > 0 && (forceGridRefresh || flatDatasetInput.length !== prevDatasetLn)) {
1114
- this.filterService.refreshTreeDataFilters(flatDatasetOutput);
1115
- }
1116
- return flatDatasetOutput;
1117
- }
1118
- /**
1119
- * For convenience to the user, we provide the property "editor" as an Angular-Slickgrid editor complex object
1120
- * however "editor" is used internally by SlickGrid for it's own Editor Factory
1121
- * so in our lib we will swap "editor" and copy it into a new property called "internalColumnEditor"
1122
- * then take back "editor.model" and make it the new "editor" so that SlickGrid Editor Factory still works
1123
- */
1124
- swapInternalEditorToSlickGridFactoryEditor(columnDefinitions) {
1125
- if (columnDefinitions.some(col => `${col.id}`.includes('.'))) {
1126
- console.error('[Angular-Slickgrid] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".');
1127
- }
1128
- return columnDefinitions.map((column) => {
1129
- // on every Editor that have a "collectionAsync", resolve the data and assign it to the "collection" property
1130
- if (column && column.editor && column.editor.collectionAsync) {
1131
- this.loadEditorCollectionAsync(column);
1132
- }
1133
- return Object.assign(Object.assign({}, column), { editor: column.editor && column.editor.model, internalColumnEditor: Object.assign({}, column.editor) });
1134
- });
1135
- }
1136
- translateColumnHeaderTitleKeys() {
1137
- // translate all columns (including hidden columns)
1138
- this.extensionUtility.translateItems(this.sharedService.allColumns, 'nameKey', 'name');
1139
- }
1140
- translateColumnGroupKeys() {
1141
- // translate all column groups (including hidden columns)
1142
- this.extensionUtility.translateItems(this.sharedService.allColumns, 'columnGroupKey', 'columnGroup');
1143
- }
1144
- /**
1145
- * Update the "internalColumnEditor.collection" property.
1146
- * Since this is called after the async call resolves, the pointer will not be the same as the "column" argument passed.
1147
- * Once we found the new pointer, we will reassign the "editor" and "collection" to the "internalColumnEditor" so it has newest collection
1148
- */
1149
- updateEditorCollection(column, newCollection) {
1150
- column.editor.collection = newCollection;
1151
- column.editor.disabled = false;
1152
- // find the new column reference pointer & re-assign the new editor to the internalColumnEditor
1153
- const columns = this.slickGrid.getColumns();
1154
- if (Array.isArray(columns)) {
1155
- const columnRef = columns.find((col) => col.id === column.id);
1156
- if (columnRef) {
1157
- columnRef.internalColumnEditor = column.editor;
1158
- }
1159
- }
1160
- // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection.
1161
- const currentEditor = this.slickGrid.getCellEditor();
1162
- if ((currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.disable) && (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.renderDomElement)) {
1163
- currentEditor.destroy();
1164
- currentEditor.disable(false);
1165
- currentEditor.renderDomElement(newCollection);
1166
- }
1167
- }
1168
- }
1169
- AngularSlickgridComponent.decorators = [
1170
- { type: Component, args: [{
1171
- selector: 'angular-slickgrid',
1172
- template: "<div id=\"slickGridContainer-{{gridId}}\" class=\"gridPane\">\r\n <div attr.id='{{gridId}}' class=\"slickgrid-container\" style=\"width: 100%\">\r\n </div>\r\n</div>",
1173
- providers: [
1174
- // make everything transient (non-singleton)
1175
- AngularUtilService,
1176
- ApplicationRef,
1177
- RowDetailViewExtension,
1178
- TranslaterService,
1179
- ]
1180
- },] }
1181
- ];
1182
- AngularSlickgridComponent.ctorParameters = () => [
1183
- { type: AngularUtilService },
1184
- { type: ApplicationRef },
1185
- { type: ChangeDetectorRef },
1186
- { type: ContainerService },
1187
- { type: ElementRef },
1188
- { type: TranslateService, decorators: [{ type: Optional }] },
1189
- { type: TranslaterService, decorators: [{ type: Optional }] },
1190
- { type: undefined, decorators: [{ type: Inject, args: ['config',] }] },
1191
- { type: undefined, decorators: [{ type: Inject, args: ['externalService',] }] }
1192
- ];
1193
- AngularSlickgridComponent.propDecorators = {
1194
- customDataView: [{ type: Input }],
1195
- gridId: [{ type: Input }],
1196
- gridOptions: [{ type: Input }],
1197
- paginationOptions: [{ type: Input }],
1198
- columnDefinitions: [{ type: Input }],
1199
- dataset: [{ type: Input }],
1200
- datasetHierarchical: [{ type: Input }]
1201
- };
1202
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1zbGlja2dyaWQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9tb2R1bGVzL2FuZ3VsYXItc2xpY2tncmlkL2NvbXBvbmVudHMvYW5ndWxhci1zbGlja2dyaWQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtCQUErQjtBQUMvQixpR0FBaUc7QUFDakcsT0FBTyxnQ0FBZ0MsQ0FBQztBQUN4QyxPQUFPLGdDQUFnQyxDQUFDO0FBQ3hDLE9BQU8sK0JBQStCLENBQUM7QUFDdkMsT0FBTyx1Q0FBdUMsQ0FBQztBQUMvQyxPQUFPLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sMkNBQTJDLENBQUM7QUFFbkQsNkJBQTZCO0FBQzdCLE9BQU8sRUFBaUIsY0FBYyxFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBYSxRQUFRLEdBQUcsTUFBTSxlQUFlLENBQUM7QUFDN0ksT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFVBQVUsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFFaEQsT0FBTztBQW1CTCxXQUFXO0FBQ1gscUJBQXFCLEVBQ3JCLGlCQUFpQixFQUNqQixnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFDYixhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLFdBQVcsRUFDWCxnQkFBZ0IsRUFDaEIseUJBQXlCLEVBQ3pCLGlCQUFpQixFQUNqQixjQUFjLEVBRWQsYUFBYSxFQUNiLGVBQWUsRUFDZixXQUFXLEVBQ1gsZUFBZTtBQUVmLGFBQWE7QUFDYixvQkFBb0IsRUFDcEIseUJBQXlCLEVBQ3pCLGdDQUFnQyxFQUNoQyxpQkFB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TUFBSSxhQUFhLGFBQWIsYUFBYSx1QkFBYixhQUFhLENBQUUsZ0JBQWdCLENBQUEsRUFBRTtZQUM3RCxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEIsYUFBYSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QixhQUFhLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDL0M7SUFDSCxDQUFDOzs7WUFyekNGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsbUJBQW1CO2dCQUM3QixtTEFBaUQ7Z0JBQ2pELFNBQVMsRUFBRTtvQkFDVCw0Q0FBNEM7b0JBQzVDLGtCQUFrQjtvQkFDbEIsY0FBYztvQkFDZCxzQkFBc0I7b0JBQ3RCLGlCQUFpQjtpQkFDbEI7YUFDRjs7O1lBakJRLGtCQUFrQjtZQTlFSCxjQUFjO1lBQUUsaUJBQWlCO1lBZ0ZoRCxnQkFBZ0I7WUFoRjZDLFVBQVU7WUFDdkUsZ0JBQWdCLHVCQWdScEIsUUFBUTtZQXZNSixpQkFBaUIsdUJBd01yQixRQUFROzRDQUNSLE1BQU0sU0FBQyxRQUFROzRDQUNmLE1BQU0sU0FBQyxpQkFBaUI7Ozs2QkE1SDFCLEtBQUs7cUJBQ0wsS0FBSzswQkFDTCxLQUFLO2dDQUVMLEtBQUs7Z0NBY0wsS0FBSztzQkFjTCxLQUFLO2tDQXlCTCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLy8gaW1wb3J0IDNyZCBwYXJ0eSB2ZW5kb3IgbGlic1xyXG4vLyBvbmx5IGltcG9ydCB0aGUgbmVjZXNzYXJ5IGNvcmUgbGliLCBlYWNoIHdpbGwgYmUgaW1wb3J0ZWQgb24gZGVtYW5kIHdoZW4gZW5hYmxlZCAodmlhIHJlcXVpcmUpXHJcbmltcG9ydCAnanF1ZXJ5LXVpL3VpL3dpZGdldHMvZHJhZ2dhYmxlJztcclxuaW1wb3J0ICdqcXVlcnktdWkvdWkvd2lkZ2V0cy9kcm9wcGFibGUnO1xyXG5pbXBvcnQgJ2pxdWVyeS11aS91aS93aWRnZXRzL3NvcnRhYmxlJztcclxuaW1wb3J0ICdzbGlja2dyaWQvbGliL2pxdWVyeS5ldmVudC5kcmFnLTIuMy4wJztcclxuaW1wb3J0ICdzbGlja2dyaWQvbGliL2pxdWVyeS5tb3VzZXdoZWVsJztcclxuaW1wb3J0ICdzbGlja2dyaWQvc2xpY2suY29yZSc7XHJcbmltcG9ydCAnc2xpY2tncmlkL3NsaWNrLmdyaWQnO1xyXG5pbXBvcnQgJ3NsaWNrZ3JpZC9zbGljay5kYXRhdmlldyc7XHJcbmltcG9ydCAnc2xpY2tncmlkL3NsaWNrLmdyb3VwaXRlbW1ldGFkYXRhcHJvdmlkZXInO1xyXG5cclxuLy8gLi4udGhlbiBldmVyeXRoaW5nIGVsc2UuLi5cclxuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQXBwbGljYXRpb25SZWYsIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEluamVjdCwgSW5wdXQsIE9uRGVzdHJveSwgT3B0aW9uYWwsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcblxyXG5pbXBvcnQge1xyXG4gIC8vIGludGVyZmFjZXMvdHlwZXNcclxuICBBdXRvQ29tcGxldGVFZGl0b3IsXHJcbiAgQmFja2VuZFNlcnZpY2VBcGksXHJcbiAgQmFja2VuZFNlcnZpY2VPcHRpb24sXHJcbiAgQ29sdW1uLFxyXG4gIENvbHVtbkVkaXRvcixcclxuICBEYXRhVmlld09wdGlvbixcclxuICBFeHRlcm5hbFJlc291cmNlLFxyXG4gIExvY2FsZSxcclxuICBNZXRyaWNzLFxyXG4gIFBhZ2luYXRpb24sXHJcbiAgU2VsZWN0RWRpdG9yLFxyXG4gIFNlcnZpY2VQYWdpbmF0aW9uLFxyXG4gIFNsaWNrRGF0YVZpZXcsXHJcbiAgU2xpY2tFdmVudEhhbmRsZXIsXHJcbiAgU2xpY2tHcmlkLFxyXG4gIFNsaWNrTmFtZXNwYWNlLFxyXG5cclxuICAvLyBzZXJ2aWNlc1xyXG4gIEJhY2tlbmRVdGlsaXR5U2VydmljZSxcclxuICBDb2xsZWN0aW9uU2VydmljZSxcclxuICBFdmVudE5hbWluZ1N0eWxlLFxyXG4gIEV4dGVuc2lvblNlcnZpY2UsXHJcbiAgRmlsdGVyRmFjdG9yeSxcclxuICBGaWx0ZXJTZXJ2aWNlLFxyXG4gIEdyaWRFdmVudFNlcnZpY2UsXHJcbiAgR3JpZFNlcnZpY2UsXHJcbiAgR3JpZFN0YXRlU2VydmljZSxcclxuICBHcm91cGluZ0FuZENvbHNwYW5TZXJ2aWNlLFxyXG4gIFBhZ2luYXRpb25TZXJ2aWNlLFxyXG4gIFJlc2l6ZXJTZXJ2aWNlLFxyXG4gIFJ4SnNGYWNhZGUsXHJcbiAgU2hhcmVkU2VydmljZSxcclxuICBTbGlja2dyaWRDb25maWcsXHJcbiAgU29ydFNlcnZpY2UsXHJcbiAgVHJlZURhdGFTZXJ2aWNlLFxyXG5cclxuICAvLyBleHRlbnNpb25zXHJcbiAgQXV0b1Rvb2x0aXBFeHRlbnNpb24sXHJcbiAgQ2hlY2tib3hTZWxlY3RvckV4dGVuc2lvbixcclxuICBDZWxsRXh0ZXJuYWxDb3B5TWFuYWdlckV4dGVuc2lvbixcclxuICBDZWxsTWVudUV4dGVuc2lvbixcclxuICBDb2x1bW5QaWNrZXJFeHRlbnNpb24sXHJcbiAgQ29udGV4dE1lbnVFeHRlbnNpb24sXHJcbiAgRHJhZ2dhYmxlR3JvdXBpbmdFeHRlbnNpb24sXHJcbiAgRXh0ZW5zaW9uVXRpbGl0eSxcclxuICBHcmlkTWVudUV4dGVuc2lvbixcclxuICBHcm91cEl0ZW1NZXRhUHJvdmlkZXJFeHRlbnNpb24sXHJcbiAgSGVhZGVyTWVudUV4dGVuc2lvbixcclxuICBIZWFkZXJCdXR0b25FeHRlbnNpb24sXHJcbiAgUm93U2VsZWN0aW9uRXh0ZW5zaW9uLFxyXG4gIFJvd01vdmVNYW5hZ2VyRXh0ZW5zaW9uLFxyXG5cclxuICAvLyB1dGlsaXRpZXNcclxuICBhdXRvQWRkRWRpdG9yRm9ybWF0dGVyVG9Db2x1bW5zV2l0aEVkaXRvcixcclxuICBlbXB0eUVsZW1lbnQsXHJcbiAgR2V0U2xpY2tFdmVudFR5cGUsXHJcbiAgR3JpZFN0YXRlVHlwZSxcclxufSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9jb21tb24nO1xyXG5pbXBvcnQgeyBFdmVudFB1YlN1YlNlcnZpY2UgfSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9ldmVudC1wdWItc3ViJztcclxuaW1wb3J0IHsgU2xpY2tFbXB0eVdhcm5pbmdDb21wb25lbnQgfSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9lbXB0eS13YXJuaW5nLWNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFNsaWNrRm9vdGVyQ29tcG9uZW50IH0gZnJvbSAnQHNsaWNrZ3JpZC11bml2ZXJzYWwvY3VzdG9tLWZvb3Rlci1jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBTbGlja1BhZ2luYXRpb25Db21wb25lbnQgfSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9wYWdpbmF0aW9uLWNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFJ4SnNSZXNvdXJjZSB9IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL3J4anMtb2JzZXJ2YWJsZSc7XHJcbmltcG9ydCB7IGRlcXVhbCB9IGZyb20gJ2RlcXVhbC9saXRlJztcclxuXHJcbmltcG9ydCB7IENvbnN0YW50cyB9IGZyb20gJy4uL2NvbnN0YW50cyc7XHJcbmltcG9ydCB7IEFuZ3VsYXJHcmlkSW5zdGFuY2UsIEV4dGVybmFsVGVzdGluZ0RlcGVuZGVuY2llcywgR3JpZE9wdGlvbiwgfSBmcm9tICcuLy4uL21vZGVscy9pbmRleCc7XHJcbmltcG9ydCB7IEdsb2JhbEdyaWRPcHRpb25zIH0gZnJvbSAnLi8uLi9nbG9iYWwtZ3JpZC1vcHRpb25zJztcclxuaW1wb3J0IHsgVHJhbnNsYXRlclNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy90cmFuc2xhdGVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyB1bnN1YnNjcmliZUFsbE9ic2VydmFibGVzIH0gZnJvbSAnLi8uLi9zZXJ2aWNlcy91dGlsaXRpZXMnO1xyXG5cclxuLy8gU2VydmljZXNcclxuaW1wb3J0IHsgQW5ndWxhclV0aWxTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvYW5ndWxhclV0aWwuc2VydmljZSc7XHJcbmltcG9ydCB7IFJvd0RldGFpbFZpZXdFeHRlbnNpb24gfSBmcm9tICcuLi9leHRlbnNpb25zL3Jvd0RldGFpbFZpZXdFeHRlbnNpb24nO1xyXG5pbXBvcnQgeyBDb250YWluZXJTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvY29udGFpbmVyLnNlcnZpY2UnO1xyXG5cclxuLy8gdXNpbmcgZXh0ZXJuYWwgbm9uLXR5cGVkIGpzIGxpYnJhcmllc1xyXG5kZWNsYXJlIGNvbnN0IFNsaWNrOiBTbGlja05hbWVzcGFjZTtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYW5ndWxhci1zbGlja2dyaWQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9hbmd1bGFyLXNsaWNrZ3JpZC5jb21wb25lbnQuaHRtbCcsXHJcbiAgcHJvdmlkZXJzOiBbXHJcbiAgICAvLyBtYWtlIGV2ZXJ5dGhpbmcgdHJhbnNpZW50IChub24tc2luZ2xldG9uKVxyXG4gICAgQW5ndWxhclV0aWxTZXJ2aWNlLFxyXG4gICAgQXBwbGljYXRpb25SZWYsXHJcbiAgICBSb3dEZXRhaWxWaWV3RXh0ZW5zaW9uLFxyXG4gICAgVHJhbnNsYXRlclNlcnZpY2UsXHJcbiAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgQW5ndWxhclNsaWNrZ3JpZENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgcHJpdmF0ZSBfZGF0YXNldD86IGFueVtdIHwgbnVsbDtcclxuICBwcml2YXRlIF9jb2x1bW5EZWZpbml0aW9ucyE6IENvbHVtbltdO1xyXG4gIHByaXZhdGUgX2N1cnJlbnREYXRhc2V0TGVuZ3RoID0gMDtcclxuICBwcml2YXRlIF9ldmVudEhhbmRsZXI6IFNsaWNrRXZlbnRIYW5kbGVyID0gbmV3IFNsaWNrLkV2ZW50SGFuZGxlcigpO1xyXG4gIHByaXZhdGUgX2V2ZW50UHViU3ViU2VydmljZSE6IEV2ZW50UHViU3ViU2VydmljZTtcclxuICBwcml2YXRlIF9hbmd1bGFyR3JpZEluc3RhbmNlczogQW5ndWxhckdyaWRJbnN0YW5jZSB8IHVuZGVmaW5lZDtcclxuICBwcml2YXRlIF9oaWRlSGVhZGVyUm93QWZ0ZXJQYWdlTG9hZCA9IGZhbHNlO1xyXG4gIHByaXZhdGUgX2lzR3JpZEluaXRpYWxpemVkID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBfaXNEYXRhc2V0SW5pdGlhbGl6ZWQgPSBmYWxzZTtcclxuICBwcml2YXRlIF9pc0RhdGFzZXRIaWVyYXJjaGljYWxJbml0aWFsaXplZCA9IGZhbHNlO1xyXG4gIHByaXZhdGUgX2lzUGFnaW5hdGlvbkluaXRpYWxpemVkID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBfaXNMb2NhbEdyaWQgPSB0cnVlO1xyXG4gIHByaXZhdGUgX3BhZ2luYXRpb25PcHRpb25zOiBQYWdpbmF0aW9uIHwgdW5kZWZpbmVkO1xyXG4gIHByaXZhdGUgX3JlZ2lzdGVyZWRSZXNvdXJjZXM6IEV4dGVybmFsUmVzb3VyY2VbXSA9IFtdO1xyXG4gIGRhdGFWaWV3ITogU2xpY2tEYXRhVmlldztcclxuICBzbGlja0dyaWQhOiBTbGlja0dyaWQ7XHJcbiAgZ3JvdXBpbmdEZWZpbml0aW9uOiBhbnkgPSB7fTtcclxuICBncm91cEl0ZW1NZXRhZGF0YVByb3ZpZGVyOiBhbnk7XHJcbiAgYmFja2VuZFNlcnZpY2VBcGk/OiBCYWNrZW5kU2VydmljZUFwaTtcclxuICBsb2NhbGVzITogTG9jYWxlO1xyXG4gIG1ldHJpY3M/OiBNZXRyaWNzO1xyXG4gIHNob3dQYWdpbmF0aW9uID0gZmFsc2U7XHJcbiAgc2VydmljZUxpc3Q6IGFueVtdID0gW107XHJcbiAgdG90YWxJdGVtcyA9IDA7XHJcbiAgcGFnaW5hdGlvbkRhdGE/OiB7XHJcbiAgICBncmlkT3B0aW9uczogR3JpZE9wdGlvbjtcclxuICAgIHBhZ2luYXRpb25TZXJ2aWNlOiBQYWdpbmF0aW9uU2VydmljZTtcclxuICB9O1xyXG4gIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XHJcblxyXG4gIC8vIGNvbXBvbmVudHNcclxuICBzbGlja0VtcHR5V2FybmluZz86IFNsaWNrRW1wdHlXYXJuaW5nQ29tcG9uZW50O1xyXG4gIHNsaWNrRm9vdGVyPzogU2xpY2tGb290ZXJDb21wb25lbnQ7XHJcbiAgc2xpY2tQYWdpbmF0aW9uPzogU2xpY2tQYWdpbmF0aW9uQ29tcG9uZW50O1xyXG5cclxuICAvLyBleHRlbnNpb25zXHJcbiAgZXh0ZW5zaW9uVXRpbGl0eTogRXh0ZW5zaW9uVXRpbGl0eTtcclxuXHJcbiAgLy8gc2VydmljZXNcclxuICBiYWNrZW5kVXRpbGl0eVNlcnZpY2UhOiBCYWNrZW5kVXRpbGl0eVNlcnZpY2U7XHJcbiAgY29sbGVjdGlvblNlcnZpY2U6IENvbGxlY3Rpb25TZXJ2aWNlO1xyXG4gIGV4dGVuc2lvblNlcnZpY2U6IEV4dGVuc2lvblNlcnZpY2U7XHJcbiAgZmlsdGVyRmFjdG9yeSE6IEZpbHRlckZhY3Rvcnk7XHJcbiAgZmlsdGVyU2VydmljZTogRmlsdGVyU2VydmljZTtcclxuICBncmlkRXZlbnRTZXJ2aWNlOiBHcmlkRXZlbnRTZXJ2aWNlO1xyXG4gIGdyaWRTZXJ2aWNlOiBHcmlkU2VydmljZTtcclxuICBncmlkU3RhdGVTZXJ2aWNlOiBHcmlkU3RhdGVTZXJ2aWNlO1xyXG4gIGdyb3VwaW5nU2VydmljZTogR3JvdXBpbmdBbmRDb2xzcGFuU2VydmljZTtcclxuICBwYWdpbmF0aW9uU2VydmljZTogUGFnaW5hdGlvblNlcnZpY2U7XHJcbiAgcmVzaXplclNlcnZpY2UhOiBSZXNpemVyU2VydmljZTtcclxuICByeGpzPzogUnhKc0ZhY2FkZTtcclxuICBzaGFyZWRTZXJ2aWNlOiBTaGFyZWRTZXJ2aWNlO1xyXG4gIHNvcnRTZXJ2aWNlOiBTb3J0U2VydmljZTtcclxuICB0cmVlRGF0YVNlcnZpY2U6IFRyZWVEYXRhU2VydmljZTtcclxuXHJcbiAgQElucHV0KCkgY3VzdG9tRGF0YVZpZXc6IGFueTtcclxuICBASW5wdXQoKSBncmlkSWQ6IHN0cmluZyA9ICcnO1xyXG4gIEBJbnB1dCgpIGdyaWRPcHRpb25zITogR3JpZE9wdGlvbjtcclxuXHJcbiAgQElucHV0KClcclxuICBnZXQgcGFnaW5hdGlvbk9wdGlvbnMoKTogUGFnaW5hdGlvbiB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5fcGFnaW5hdGlvbk9wdGlvbnM7XHJcbiAgfVxyXG4gIHNldCBwYWdpbmF0aW9uT3B0aW9ucyhuZXdQYWdpbmF0aW9uT3B0aW9uczogUGFnaW5hdGlvbiB8IHVuZGVmaW5lZCkge1xyXG4gICAgaWYgKG5ld1BhZ2luYXRpb25PcHRpb25zICYmIHRoaXMuX3BhZ2luYXRpb25PcHRpb25zKSB7XHJcbiAgICAgIHRoaXMuX3BhZ2luYXRpb25PcHRpb25zID0geyAuLi50aGlzLmdyaWRPcHRpb25zLnBhZ2luYXRpb24sIC4uLnRoaXMuX3BhZ2luYXRpb25PcHRpb25zLCAuLi5uZXdQYWdpbmF0aW9uT3B0aW9ucyB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5fcGFnaW5hdGlvbk9wdGlvbnMgPSBuZXdQYWdpbmF0aW9uT3B0aW9ucztcclxuICAgIH1cclxuICAgIHRoaXMuZ3JpZE9wdGlvbnMucGFnaW5hdGlvbiA9IHRoaXMuX3BhZ2luYXRpb25PcHRpb25zID8/IHRoaXMuZ3JpZE9wdGlvbnMucGFnaW5hdGlvbjtcclxuICAgIHRoaXMucGFnaW5hdGlvblNlcnZpY2UudXBkYXRlVG90YWxJdGVtcyh0aGlzLmdyaWRPcHRpb25zLnBhZ2luYXRpb24/LnRvdGFsSXRlbXMgPz8gMCwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBASW5wdXQoKVxyXG4gIHNldCBjb2x1bW5EZWZpbml0aW9ucyhjb2x1bW5EZWZpbml0aW9uczogQ29sdW1uW10pIHtcclxuICAgIHRoaXMuX2NvbHVtbkRlZmluaXRpb25zID0gY29sdW1uRGVmaW5pdGlvbnM7XHJcbiAgICBpZiAodGhpcy5faXNHcmlkSW5pdGlhbGl6ZWQpIHtcclxuICAgICAgdGhpcy51cGRhdGVDb2x1bW5EZWZpbml0aW9uc0xpc3QoY29sdW1uRGVmaW5pdGlvbnMpO1xyXG4gICAgfVxyXG4gICAgaWYgKGNvbHVtbkRlZmluaXRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgdGhpcy5jb3B5Q29sdW1uV2lkdGhzUmVmZXJlbmNlKGNvbHVtbkRlZmluaXRpb25zKTtcclxuICAgIH1cclxuICB9XHJcbiAgZ2V0IGNvbHVtbkRlZmluaXRpb25zKCk6IENvbHVtbltdIHtcclxuICAgIHJldHVybiB0aGlzLl9jb2x1bW5EZWZpbml0aW9ucztcclxuICB9XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZ2V0IGRhdGFzZXQoKTogYW55W10ge1xyXG4gICAgcmV0dXJuICh0aGlzLmN1c3RvbURhdGFWaWV3ID8gdGhpcy5zbGlja0dyaWQ/LmdldERhdGE/LigpIDogdGhpcy5kYXRhVmlldz8uZ2V0SXRlbXM/LigpKSB8fCBbXTtcclxuICB9XHJcbiAgc2V0IGRhdGFzZXQobmV3RGF0YXNldDogYW55W10pIHtcclxuICAgIGNvbnN0IHByZXZEYXRhc2V0TG4gPSB0aGlzLl9jdXJyZW50RGF0YXNldExlbmd0aDtcclxuICAgIGNvbnN0IGlzRGF0YXNldEVxdWFsID0gZGVxdWFsKG5ld0RhdGFzZXQsIHRoaXMuX2RhdGFzZXQgfHwgW10pO1xyXG4gICAgbGV0IGRhdGEgPSBuZXdEYXRhc2V0O1xyXG5cclxuICAgIC8vIHdoZW4gVHJlZSBEYXRhIGlzIGVuYWJsZWQgYW5kIHdlIGRvbid0IHlldCBoYXZlIHRoZSBoaWVyYXJjaGljYWwgZGF0YXNldCBmaWxsZWQsIHdlIGNhbiBmb3JjZSBhIGNvbnZlcnQrc29ydCBvZiB0aGUgYXJyYXlcclxuICAgIGlmICh0aGlzLnNsaWNrR3JpZCAmJiB0aGlzLmdyaWRPcHRpb25zPy5lbmFibGVUcmVlRGF0YSAmJiBBcnJheS5pc0FycmF5KG5ld0RhdGFzZXQpICYmIChuZXdEYXRhc2V0Lmxlbmd0aCA+IDAgfHwgbmV3RGF0YXNldC5sZW5ndGggIT09IHByZXZEYXRhc2V0TG4gfHwgIWlzRGF0YXNldEVxdWFsKSkge1xyXG4gICAgICB0aGlzLl9pc0RhdGFzZXRIaWVyYXJjaGljYWxJbml0aWFsaXplZCA9IGZhbHNlO1xyXG4gICAgICBkYXRhID0gdGhpcy5zb3J0VHJlZURhdGFzZXQobmV3RGF0YXNldCwgIWlzRGF0YXNldEVxdWFsKTsgLy8gaWYgZGF0YXNldCBjaGFuZ2VkLCB0aGVuIGZvcmNlIGEgcmVmcmVzaCBhbnl3YXlcclxuICAgIH1cclxuICAgIHRoaXMuX2RhdGFzZXQgPSBkYXRhO1xyXG4gICAgdGhpcy5yZWZyZXNoR3JpZERhdGEoZGF0YSB8fCBbXSk7XHJcbiAgICB0aGlzLl9jdXJyZW50RGF0YXNldExlbmd0aCA9IChuZXdEYXRhc2V0IHx8IFtdKS5sZW5ndGg7XHJcblxyXG4gICAgLy8gZXhwYW5kL2F1dG9maXQgY29sdW1ucyBvbiBmaXJzdCBwYWdlIGxvYWRcclxuICAgIC8vIHdlIGNhbiBhc3N1bWUgdGhhdCBpZiB0aGUgcHJldkRhdGFzZXQgd2FzIGVtcHR5IHRoZW4gd2UgYXJlIG9uIGZpcnN0IGxvYWRcclxuICAgIGlmICh0aGlzLmdyaWRPcHRpb25zPy5hdXRvRml0Q29sdW1uc09uRmlyc3RMb2FkICYmIHByZXZEYXRhc2V0TG4gPT09IDApIHtcclxuICAgICAgdGhpcy5zbGlja0dyaWQuYXV0b3NpemVDb2x1bW5zKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASW5wdXQoKVxyXG4gIGdldCBkYXRhc2V0SGllcmFyY2hpY2FsKCk6IGFueVtdIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLnNoYXJlZFNlcnZpY2UuaGllcmFyY2hpY2FsRGF0YXNldDtcclxuICB9XHJcbiAgc2V0IGRhdGFzZXRIaWVyYXJjaGljYWwobmV3SGllcmFyY2hpY2FsRGF0YXNldDogYW55W10gfCB1bmRlZmluZWQpIHtcclxuICAgIGNvbnN0IGlzRGF0YXNldEVxdWFsID0gZGVxdWFsKG5ld0hpZXJhcmNoaWNhbERhdGFzZXQsIHRoaXMuc2hhcmVkU2VydmljZT8uaGllcmFyY2hpY2FsRGF0YXNldCA/PyBbXSk7XHJcbiAgICBjb25zdCBwcmV2RmxhdERhdGFzZXRMbiA9IHRoaXMuX2N1cnJlbnREYXRhc2V0TGVuZ3RoO1xyXG4gICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmhpZXJhcmNoaWNhbERhdGFzZXQgPSBuZXdIaWVyYXJjaGljYWxEYXRhc2V0O1xyXG5cclxuICAgIGlmIChuZXdIaWVyYXJjaGljYWxEYXRhc2V0ICYmIHRoaXMuY29sdW1uRGVmaW5pdGlvbnMgJiYgdGhpcy5maWx0ZXJTZXJ2aWNlPy5jbGVhckZpbHRlcnMpIHtcclxuICAgICAgdGhpcy5maWx0ZXJTZXJ2aWNlLmNsZWFyRmlsdGVycygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHdoZW4gYSBoaWVyYXJjaGljYWwgZGF0YXNldCBpcyBzZXQgYWZ0ZXJ3YXJkLCB3ZSBjYW4gcmVzZXQgdGhlIGZsYXQgZGF0YXNldCBhbmQgY2FsbCBhIHRyZWUgZGF0YSBzb3J0IHRoYXQgd2lsbCBvdmVyd3JpdGUgdGhlIGZsYXQgZGF0YXNldFxyXG4gICAgaWYgKG5ld0hpZXJhcmNoaWNhbERhdGFzZXQgJiYgdGhpcy5zbGlja0dyaWQgJiYgdGhpcy5zb3J0U2VydmljZT8ucHJvY2Vzc1RyZWVEYXRhSW5pdGlhbFNvcnQpIHtcclxuICAgICAgdGhpcy5kYXRhVmlldy5zZXRJdGVtcyhbXSwgdGhpcy5ncmlkT3B0aW9ucy5kYXRhc2V0SWRQcm9wZXJ0eU5hbWUgPz8gJ2lkJyk7XHJcbiAgICAgIHRoaXMuc29ydFNlcnZpY2UucHJvY2Vzc1RyZWVEYXRhSW5pdGlhbFNvcnQoKTtcclxuXHJcbiAgICAgIC8vIHdlIGFsc28gbmVlZCB0byByZXNldC9yZWZyZXNoIHRoZSBUcmVlIERhdGEgZmlsdGVycyBiZWNhdXNlIGlmIHdlIGluc2VydGVkIG5ldyBpdGVtKHMpIHRoZW4gaXQgbWlnaHQgbm90IHNob3cgdXAgd2l0aG91dCBkb2luZyB0aGlzIHJlZnJlc2hcclxuICAgICAgLy8gaG93ZXZlciB3ZSBuZWVkIDEgY3B1IGN5Y2xlIGJlZm9yZSBoYXZpbmcgdGhlIERhdGFWaWV3IHJlZnJlc2hlZCwgc28gd2UgbmVlZCB0byB3cmFwIHRoaXMgY2hlY2sgaW4gYSBzZXRUaW1lb3V0XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGZsYXREYXRhc2V0TG4gPSB0aGlzLmRhdGFWaWV3LmdldEl0ZW1Db3VudCgpO1xyXG4gICAgICAgIGlmIChmbGF0RGF0YXNldExuID4gMCAmJiAoZmxhdERhdGFzZXRMbiAhPT0gcHJldkZsYXREYXRhc2V0TG4gfHwgIWlzRGF0YXNldEVxdWFsKSkge1xyXG4gICAgICAgICAgdGhpcy5maWx0ZXJTZXJ2aWNlLnJlZnJlc2hUcmVlRGF0YUZpbHRlcnMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLl9pc0RhdGFzZXRIaWVyYXJjaGljYWxJbml0aWFsaXplZCA9IHRydWU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXQgZWxlbWVudFJlZigpOiBFbGVtZW50UmVmIHtcclxuICAgIHJldHVybiB0aGlzLmVsbTtcclxuICB9XHJcblxyXG4gIGdldCBldmVudEhhbmRsZXIoKTogU2xpY2tFdmVudEhhbmRsZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2V2ZW50SGFuZGxlcjtcclxuICB9XHJcblxyXG4gIGdldCBncmlkQ29udGFpbmVyRWxlbWVudCgpOiBIVE1MRWxlbWVudCB8IG51bGwge1xyXG4gICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYCMke3RoaXMuZ3JpZE9wdGlvbnMuZ3JpZENvbnRhaW5lcklkIHx8ICcnfWApO1xyXG4gIH1cclxuXHJcbiAgLyoqIEdFVFRFUiB0byBrbm93IGlmIGRhdGFzZXQgd2FzIGluaXRpYWxpemVkIG9yIG5vdCAqL1xyXG4gIGdldCBpc0RhdGFzZXRJbml0aWFsaXplZCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9pc0RhdGFzZXRJbml0aWFsaXplZDtcclxuICB9XHJcbiAgLyoqIFNFVFRFUiB0byBjaGFuZ2UgaWYgZGF0YXNldCB3YXMgaW5pdGlhbGl6ZWQgb3Igbm90IChzdHJpbmdseSB1c2VkIGZvciB1bml0IHRlc3RpbmcgcHVycG9zZXMpICovXHJcbiAgc2V0IGlzRGF0YXNldEluaXRpYWxpemVkKGlzSW5pdGlhbGl6ZWQ6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuX2lzRGF0YXNldEluaXRpYWxpemVkID0gaXNJbml0aWFsaXplZDtcclxuICB9XHJcbiAgc2V0IGlzRGF0YXNldEhpZXJhcmNoaWNhbEluaXRpYWxpemVkKGlzSW5pdGlhbGl6ZWQ6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuX2lzRGF0YXNldEhpZXJhcmNoaWNhbEluaXRpYWxpemVkID0gaXNJbml0aWFsaXplZDtcclxuICB9XHJcblxyXG4gIGdldCByZWdpc3RlcmVkUmVzb3VyY2VzKCk6IEV4dGVybmFsUmVzb3VyY2VbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcztcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBhbmd1bGFyVXRpbFNlcnZpY2U6IEFuZ3VsYXJVdGlsU2VydmljZSxcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXBwUmVmOiBBcHBsaWNhdGlvblJlZixcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2Q6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXJTZXJ2aWNlOiBDb250YWluZXJTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBlbG06IEVsZW1lbnRSZWYsXHJcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIHJlYWRvbmx5IHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcclxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNsYXRlclNlcnZpY2U6IFRyYW5zbGF0ZXJTZXJ2aWNlLFxyXG4gICAgQEluamVjdCgnY29uZmlnJykgcHJpdmF0ZSBmb3JSb290Q29uZmlnOiBHcmlkT3B0aW9uLFxyXG4gICAgQEluamVjdCgnZXh0ZXJuYWxTZXJ2aWNlJykgZXh0ZXJuYWxTZXJ2aWNlczogRXh0ZXJuYWxUZXN0aW5nRGVwZW5kZW5jaWVzXHJcbiAgKSB7XHJcbiAgICBjb25zdCBzbGlja2dyaWRDb25maWcgPSBuZXcgU2xpY2tncmlkQ29uZmlnKCk7XHJcblxyXG4gICAgLy8gaW5pdGlhbGl6ZSBhbmQgYXNzaWduIGFsbCBTZXJ2aWNlIERlcGVuZGVuY2llc1xyXG4gICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlID0gZXh0ZXJuYWxTZXJ2aWNlcz8uZXZlbnRQdWJTdWJTZXJ2aWNlID8/IG5ldyBFdmVudFB1YlN1YlNlcnZpY2UodGhpcy5lbG0ubmF0aXZlRWxlbWVudCk7XHJcbiAgICB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UuZXZlbnROYW1pbmdTdHlsZSA9IEV2ZW50TmFtaW5nU3R5bGUuY2FtZWxDYXNlO1xyXG5cclxuICAgIHRoaXMuYmFja2VuZFV0aWxpdHlTZXJ2aWNlID0gZXh0ZXJuYWxTZXJ2aWNlcz8uYmFja2VuZFV0aWxpdHlTZXJ2aWNlID8/IG5ldyBCYWNrZW5kVXRpbGl0eVNlcnZpY2UoKTtcclxuICAgIHRoaXMuZ3JpZEV2ZW50U2VydmljZSA9IGV4dGVybmFsU2VydmljZXM/LmdyaWRFdmVudFNlcnZpY2UgPz8gbmV3IEdyaWRFdmVudFNlcnZpY2UoKTtcclxuICAgIHRoaXMuc2hhcmVkU2VydmljZSA9IGV4dGVybmFsU2VydmljZXM/LnNoYXJlZFNlcnZpY2UgPz8gbmV3IFNoYXJlZFNlcnZpY2UoKTtcclxuICAgIHRoaXMuY29sbGVjdGlvblNlcnZpY2UgPSBleHRlcm5hbFNlcnZpY2VzPy5jb2xsZWN0aW9uU2VydmljZSA/PyBuZXcgQ29sbGVjdGlvblNlcnZpY2UodGhpcy50cmFuc2xhdGVyU2VydmljZSk7XHJcbiAgICB0aGlzLmV4dGVuc2lvblV0aWxpdHkgPSBleHRlcm5hbFNlcnZpY2VzPy5leHRlbnNpb25VdGlsaXR5ID8/IG5ldyBFeHRlbnNpb25VdGlsaXR5KHRoaXMuc2hhcmVkU2VydmljZSwgdGhpcy50cmFuc2xhdGVyU2VydmljZSk7XHJcbiAgICB0aGlzLmZpbHRlckZhY3RvcnkgPSBuZXcgRmlsdGVyRmFjdG9yeShzbGlja2dyaWRDb25maWcsIHRoaXMudHJhbnNsYXRlclNlcnZpY2UsIHRoaXMuY29sbGVjdGlvblNlcnZpY2UpO1xyXG4gICAgdGhpcy5maWx0ZXJTZXJ2aWNlID0gZXh0ZXJuYWxTZXJ2aWNlcz8uZmlsdGVyU2VydmljZSA/PyBuZXcgRmlsdGVyU2VydmljZSh0aGlzLmZpbHRlckZhY3RvcnkgYXMgYW55LCB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UsIHRoaXMuc2hhcmVkU2VydmljZSwgdGhpcy5iYWNrZW5kVXRpbGl0eVNlcnZpY2UpO1xyXG4gICAgdGhpcy5yZXNpemVyU2VydmljZSA9IGV4dGVybmFsU2VydmljZXM/LnJlc2l6ZXJTZXJ2aWNlID8/IG5ldyBSZXNpemVyU2VydmljZSh0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UpO1xyXG4gICAgdGhpcy5zb3J0U2VydmljZSA9IGV4dGVybmFsU2VydmljZXM/LnNvcnRTZXJ2aWNlID8/IG5ldyBTb3J0U2VydmljZSh0aGlzLnNoYXJlZFNlcnZpY2UsIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZSwgdGhpcy5iYWNrZW5kVXRpbGl0eVNlcnZpY2UpO1xyXG4gICAgdGhpcy50cmVlRGF0YVNlcnZpY2UgPSBleHRlcm5hbFNlcnZpY2VzPy50cmVlRGF0YVNlcnZpY2UgPz8gbmV3IFRyZWVEYXRhU2VydmljZSh0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UsIHRoaXMuc2hhcmVkU2VydmljZSwgdGhpcy5zb3J0U2VydmljZSk7XHJcbiAgICB0aGlzLnBhZ2luYXRpb25TZXJ2aWNlID0gZXh0ZXJuYWxTZXJ2aWNlcz8ucGFnaW5hdGlvblNlcnZpY2UgPz8gbmV3IFBhZ2luYXRpb25TZXJ2aWNlKHRoaXMuX2V2ZW50UHViU3ViU2VydmljZSwgdGhpcy5zaGFyZWRTZXJ2aWNlLCB0aGlzLmJhY2tlbmRVdGlsaXR5U2VydmljZSk7XHJcblxyXG4gICAgLy8gZXh0ZW5zaW9uc1xyXG4gICAgY29uc3QgYXV0b1Rvb2x0aXBFeHRlbnNpb24gPSBuZXcgQXV0b1Rvb2x0aXBFeHRlbnNpb24odGhpcy5zaGFyZWRTZXJ2aWNlKTtcclxuICAgIGNvbnN0IGNlbGxFeHRlcm5hbENvcHlNYW5hZ2VyRXh0ZW5zaW9uID0gbmV3IENlbGxFeHRlcm5hbENvcHlNYW5hZ2VyRXh0ZW5zaW9uKHRoaXMuZXh0ZW5zaW9uVXRpbGl0eSwgdGhpcy5zaGFyZWRTZXJ2aWNlKTtcclxuICAgIGNvbnN0IGNlbGxNZW51RXh0ZW5zaW9uID0gbmV3IENlbGxNZW51RXh0ZW5zaW9uKHRoaXMuZXh0ZW5zaW9uVXRpbGl0eSwgdGhpcy5zaGFyZWRTZXJ2aWNlLCB0aGlzLnRyYW5zbGF0ZXJTZXJ2aWNlKTtcclxuICAgIGNvbnN0IGNvbnRleHRNZW51RXh0ZW5zaW9uID0gbmV3IENvbnRleHRNZW51RXh0ZW5zaW9uKHRoaXMuZXh0ZW5zaW9uVXRpbGl0eSwgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLCB0aGlzLnNoYXJlZFNlcnZpY2UsIHRoaXMudHJlZURhdGFTZXJ2aWNlLCB0aGlzLnRyYW5zbGF0ZXJTZXJ2aWNlKTtcclxuICAgIGNvbnN0IGNvbHVtblBpY2tlckV4dGVuc2lvbiA9IG5ldyBDb2x1bW5QaWNrZXJFeHRlbnNpb24odGhpcy5leHRlbnNpb25VdGlsaXR5LCB0aGlzLnNoYXJlZFNlcnZpY2UpO1xyXG4gICAgY29uc3QgY2hlY2tib3hFeHRlbnNpb24gPSBuZXcgQ2hlY2tib3hTZWxlY3RvckV4dGVuc2lvbih0aGlzLnNoYXJlZFNlcnZpY2UpO1xyXG4gICAgY29uc3QgZHJhZ2dhYmxlR3JvdXBpbmdFeHRlbnNpb24gPSBuZXcgRHJhZ2dhYmxlR3JvdXBpbmdFeHRlbnNpb24odGhpcy5leHRlbnNpb25VdGlsaXR5LCB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UsIHRoaXMuc2hhcmVkU2VydmljZSk7XHJcbiAgICBjb25zdCBncmlkTWVudUV4dGVuc2lvbiA9IG5ldyBHcmlkTWVudUV4dGVuc2lvbih0aGlzLmV4dGVuc2lvblV0aWxpdHksIHRoaXMuZmlsdGVyU2VydmljZSwgdGhpcy5zaGFyZWRTZXJ2aWNlLCB0aGlzLnNvcnRTZXJ2aWNlLCB0aGlzLmJhY2tlbmRVdGlsaXR5U2VydmljZSwgdGhpcy50cmFuc2xhdGVyU2VydmljZSk7XHJcbiAgICBjb25zdCBncm91cEl0ZW1NZXRhUHJvdmlkZXJFeHRlbnNpb24gPSBuZXcgR3JvdXBJdGVtTWV0YVByb3ZpZGVyRXh0ZW5zaW9uKHRoaXMuc2hhcmVkU2VydmljZSk7XHJcbiAgICBjb25zdCBoZWFkZXJCdXR0b25FeHRlbnNpb24gPSBuZXcgSGVhZGVyQnV0dG9uRXh0ZW5zaW9uKHRoaXMuZXh0ZW5zaW9uVXRpbGl0eSwgdGhpcy5zaGFyZWRTZXJ2aWNlKTtcclxuICAgIGNvbnN0IGhlYWRlck1lbnVFeHRlbnNpb24gPSBuZXcgSGVhZGVyTWVudUV4dGVuc2lvbih0aGlzLmV4dGVuc2lvblV0aWxpdHksIHRoaXMuZmlsdGVyU2VydmljZSwgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLCB0aGlzLnNoYXJlZFNlcnZpY2UsIHRoaXMuc29ydFNlcnZpY2UsIHRoaXMudHJhbnNsYXRlclNlcnZpY2UpO1xyXG4gICAgY29uc3Qgcm93RGV0YWlsVmlld0V4dGVuc2lvbiA9IG5ldyBSb3dEZXRhaWxWaWV3RXh0ZW5zaW9uKHRoaXMuYW5ndWxhclV0aWxTZXJ2aWNlLCB0aGlzLmFwcFJlZiwgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLCB0aGlzLnNoYXJlZFNlcnZpY2UsIHRoaXMucnhqcyk7XHJcbiAgICBjb25zdCByb3dNb3ZlTWFuYWdlckV4dGVuc2lvbiA9IG5ldyBSb3dNb3ZlTWFuYWdlckV4dGVuc2lvbih0aGlzLnNoYXJlZFNlcnZpY2UpO1xyXG4gICAgY29uc3Qgcm93U2VsZWN0aW9uRXh0ZW5zaW9uID0gbmV3IFJvd1NlbGVjdGlvbkV4dGVuc2lvbih0aGlzLnNoYXJlZFNlcnZpY2UpO1xyXG5cclxuICAgIHRoaXMuZXh0ZW5zaW9uU2VydmljZSA9IGV4dGVybmFsU2VydmljZXM/LmV4dGVuc2lvblNlcnZpY2UgPz8gbmV3IEV4dGVuc2lvblNlcnZpY2UoXHJcbiAgICAgIGF1dG9Ub29sdGlwRXh0ZW5zaW9uLFxyXG4gICAgICBjZWxsRXh0ZXJuYWxDb3B5TWFuYWdlckV4dGVuc2lvbixcclxuICAgICAgY2VsbE1lbnVFeHRlbnNpb24sXHJcbiAgICAgIGNoZWNrYm94RXh0ZW5zaW9uLFxyXG4gICAgICBjb2x1bW5QaWNrZXJFeHRlbnNpb24sXHJcbiAgICAgIGNvbnRleHRNZW51RXh0ZW5zaW9uLFxyXG4gICAgICBkcmFnZ2FibGVHcm91cGluZ0V4dGVuc2lvbixcclxuICAgICAgZ3JpZE1lbnVFeHRlbnNpb24sXHJcbiAgICAgIGdyb3VwSXRlbU1ldGFQcm92aWRlckV4dGVuc2lvbixcclxuICAgICAgaGVhZGVyQnV0dG9uRXh0ZW5zaW9uLFxyXG4gICAgICBoZWFkZXJNZW51RXh0ZW5zaW9uLFxyXG4gICAgICByb3dEZXRhaWxWaWV3RXh0ZW5zaW9uLFxyXG4gICAgICByb3dNb3ZlTWFuYWdlckV4dGVuc2lvbixcclxuICAgICAgcm93U2VsZWN0aW9uRXh0ZW5zaW9uLFxyXG4gICAgICB0aGlzLnNoYXJlZFNlcnZpY2UsXHJcbiAgICAgIHRoaXMudHJhbnNsYXRlclNlcnZpY2UsXHJcbiAgICApO1xyXG5cclxuICAgIHRoaXMuZ3JpZFN0YXRlU2VydmljZSA9IGV4dGVybmFsU2VydmljZXM/LmdyaWRTdGF0ZVNlcnZpY2UgPz8gbmV3IEdyaWRTdGF0ZVNlcnZpY2UodGhpcy5leHRlbnNpb25TZXJ2aWNlLCB0aGlzLmZpbHRlclNlcnZpY2UsIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZSwgdGhpcy5zaGFyZWRTZXJ2aWNlLCB0aGlzLnNvcnRTZXJ2aWNlLCB0aGlzLnRyZWVEYXRhU2VydmljZSk7XHJcbiAgICB0aGlzLmdyaWRTZXJ2aWNlID0gZXh0ZXJuYWxTZXJ2aWNlcz8uZ3JpZFNlcnZpY2UgPz8gbmV3IEdyaWRTZXJ2aWNlKHRoaXMuZ3JpZFN0YXRlU2VydmljZSwgdGhpcy5maWx0ZXJTZXJ2aWNlLCB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UsIHRoaXMucGFnaW5hdGlvblNlcnZpY2UsIHRoaXMuc2hhcmVkU2VydmljZSwgdGhpcy5zb3J0U2VydmljZSwgdGhpcy50cmVlRGF0YVNlcnZpY2UpO1xyXG4gICAgdGhpcy5ncm91cGluZ1NlcnZpY2UgPSBleHRlcm5hbFNlcnZpY2VzPy5ncm91cGluZ0FuZENvbHNwYW5TZXJ2aWNlID8/IG5ldyBHcm91cGluZ0FuZENvbHNwYW5TZXJ2aWNlKHRoaXMuZXh0ZW5zaW9uVXRpbGl0eSwgdGhpcy5leHRlbnNpb25TZXJ2aWNlLCB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UpO1xyXG5cclxuICAgIHRoaXMuc2VydmljZUxpc3QgPSBbXHJcbiAgICAgIHRoaXMuZXh0ZW5zaW9uU2VydmljZSxcclxuICAgICAgdGhpcy5maWx0ZXJTZXJ2aWNlLFxyXG4gICAgICB0aGlzLmdyaWRFdmVudFNlcnZpY2UsXHJcbiAgICAgIHRoaXMuZ3JpZFNlcnZpY2UsXHJcbiAgICAgIHRoaXMuZ3JpZFN0YXRlU2VydmljZSxcclxuICAgICAgdGhpcy5ncm91cGluZ1NlcnZpY2UsXHJcbiAgICAgIHRoaXMucGFnaW5hdGlvblNlcnZpY2UsXHJcbiAgICAgIHRoaXMucmVzaXplclNlcnZpY2UsXHJcbiAgICAgIHRoaXMuc29ydFNlcnZpY2UsXHJcbiAgICAgIHRoaXMudHJlZURhdGFTZXJ2aWNlLFxyXG4gICAgXTtcclxuXHJcbiAgICAvLyByZWdpc3RlciBhbGwgU2VydmljZSBpbnN0YW5jZXMgaW4gdGhlIGNvbnRhaW5lclxyXG4gICAgdGhpcy5jb250YWluZXJTZXJ2aWNlLnJlZ2lzdGVySW5zdGFuY2UoJ0V4dGVuc2lvblV0aWxpdHknLCB0aGlzLmV4dGVuc2lvblV0aWxpdHkpO1xyXG4gICAgdGhpcy5jb250YWluZXJTZXJ2aWNlLnJlZ2lzdGVySW5zdGFuY2UoJ0ZpbHRlclNlcnZpY2UnLCB0aGlzLmZpbHRlclNlcnZpY2UpO1xyXG4gICAgdGhpcy5jb250YWluZXJTZXJ2aWNlLnJlZ2lzdGVySW5zdGFuY2UoJ0NvbGxlY3Rpb25TZXJ2aWNlJywgdGhpcy5jb2xsZWN0aW9uU2VydmljZSk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnRXh0ZW5zaW9uU2VydmljZScsIHRoaXMuZXh0ZW5zaW9uU2VydmljZSk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnR3JpZEV2ZW50U2VydmljZScsIHRoaXMuZ3JpZEV2ZW50U2VydmljZSk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnR3JpZFNlcnZpY2UnLCB0aGlzLmdyaWRTZXJ2aWNlKTtcclxuICAgIHRoaXMuY29udGFpbmVyU2VydmljZS5yZWdpc3Rlckluc3RhbmNlKCdHcmlkU3RhdGVTZXJ2aWNlJywgdGhpcy5ncmlkU3RhdGVTZXJ2aWNlKTtcclxuICAgIHRoaXMuY29udGFpbmVyU2VydmljZS5yZWdpc3Rlckluc3RhbmNlKCdHcm91cGluZ0FuZENvbHNwYW5TZXJ2aWNlJywgdGhpcy5ncm91cGluZ1NlcnZpY2UpO1xyXG4gICAgdGhpcy5jb250YWluZXJTZXJ2aWNlLnJlZ2lzdGVySW5zdGFuY2UoJ1BhZ2luYXRpb25TZXJ2aWNlJywgdGhpcy5wYWdpbmF0aW9uU2VydmljZSk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnUmVzaXplclNlcnZpY2UnLCB0aGlzLnJlc2l6ZXJTZXJ2aWNlKTtcclxuICAgIHRoaXMuY29udGFpbmVyU2VydmljZS5yZWdpc3Rlckluc3RhbmNlKCdTaGFyZWRTZXJ2aWNlJywgdGhpcy5zaGFyZWRTZXJ2aWNlKTtcclxuICAgIHRoaXMuY29udGFpbmVyU2VydmljZS5yZWdpc3Rlckluc3RhbmNlKCdTb3J0U2VydmljZScsIHRoaXMuc29ydFNlcnZpY2UpO1xyXG4gICAgdGhpcy5jb250YWluZXJTZXJ2aWNlLnJlZ2lzdGVySW5zdGFuY2UoJ0V2ZW50UHViU3ViU2VydmljZScsIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZSk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnUHViU3ViU2VydmljZScsIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZSk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnVHJhbnNsYXRlclNlcnZpY2UnLCB0aGlzLnRyYW5zbGF0ZXJTZXJ2aWNlKTtcclxuICAgIHRoaXMuY29udGFpbmVyU2VydmljZS5yZWdpc3Rlckluc3RhbmNlKCdUcmVlRGF0YVNlcnZpY2UnLCB0aGlzLnRyZWVEYXRhU2VydmljZSk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLmluaXRpYWxpemF0aW9uKHRoaXMuX2V2ZW50SGFuZGxlcik7XHJcbiAgICB0aGlzLl9pc0dyaWRJbml0aWFsaXplZCA9IHRydWU7XHJcblxyXG4gICAgLy8gcmVjaGVjayB0aGUgZW1wdHkgd2FybmluZyBtZXNzYWdlIGFmdGVyIGdyaWQgaXMgc2hvd24gc28gdGhhdCBpdCB3b3JrcyBpbiBldmVyeSB1c2UgY2FzZVxyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMgJiYgdGhpcy5ncmlkT3B0aW9ucy5lbmFibGVFbXB0eURhdGFXYXJuaW5nTWVzc2FnZSAmJiBBcnJheS5pc0FycmF5KHRoaXMuZGF0YXNldCkpIHtcclxuICAgICAgY29uc3QgZmluYWxUb3RhbENvdW50ID0gdGhpcy5kYXRhc2V0Lmxlbmd0aDtcclxuICAgICAgdGhpcy5kaXNwbGF5RW1wdHlEYXRhV2FybmluZyhmaW5hbFRvdGFsQ291bnQgPCAxKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnB1Ymxpc2goJ29uQmVmb3JlR3JpZERlc3Ryb3knLCB0aGlzLnNsaWNrR3JpZCk7XHJcbiAgICB0aGlzLmRlc3Ryb3koKTtcclxuICAgIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZS5wdWJsaXNoKCdvbkFmdGVyR3JpZERlc3Ryb3llZCcsIHRydWUpO1xyXG4gIH1cclxuXHJcbiAgZGVzdHJveShzaG91bGRFbXB0eURvbUVsZW1lbnRDb250YWluZXIgPSBmYWxzZSkge1xyXG4gICAgLy8gZGlzcG9zZSBvZiBhbGwgU2VydmljZXNcclxuICAgIHRoaXMuc2VydmljZUxpc3QuZm9yRWFjaCgoc2VydmljZTogYW55KSA9PiB7XHJcbiAgICAgIGlmIChzZXJ2aWNlICYmIHNlcnZpY2UuZGlzcG9zZSkge1xyXG4gICAgICAgIHNlcnZpY2UuZGlzcG9zZSgpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHRoaXMuc2VydmljZUxpc3QgPSBbXTtcclxuXHJcbiAgICAvLyBkaXNwb3NlIGFsbCByZWdpc3RlcmVkIGV4dGVybmFsIHJlc291cmNlc1xyXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcykpIHtcclxuICAgICAgd2hpbGUgKHRoaXMuX3JlZ2lzdGVyZWRSZXNvdXJjZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGNvbnN0IHJlc291cmNlID0gdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcy5wb3AoKTtcclxuICAgICAgICBpZiAocmVzb3VyY2U/LmRpc3Bvc2UpIHtcclxuICAgICAgICAgIHJlc291cmNlLmRpc3Bvc2UoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcyA9IFtdO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGRpc3Bvc2UgdGhlIENvbXBvbmVudHNcclxuICAgIHRoaXMuc2xpY2tFbXB0eVdhcm5pbmc/LmRpc3Bvc2UoKTtcclxuICAgIHRoaXMuc2xpY2tGb290ZXI/LmRpc3Bvc2UoKTtcclxuICAgIHRoaXMuc2xpY2tQYWdpbmF0aW9uPy5kaXNwb3NlKCk7XHJcblxyXG4gICAgaWYgKHRoaXMuX2V2ZW50SGFuZGxlcj8udW5zdWJzY3JpYmVBbGwpIHtcclxuICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnVuc3Vic2NyaWJlQWxsKCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2U/LnVuc3Vic2NyaWJlQWxsKCk7XHJcbiAgICBpZiAodGhpcy5kYXRhVmlldykge1xyXG4gICAgICBpZiAodGhpcy5kYXRhVmlldz8uc2V0SXRlbXMpIHtcclxuICAgICAgICB0aGlzLmRhdGFWaWV3LnNldEl0ZW1zKFtdKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy5kYXRhVmlldy5kZXN0cm95KSB7XHJcbiAgICAgICAgdGhpcy5kYXRhVmlldy5kZXN0cm95KCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICh0aGlzLnNsaWNrR3JpZD8uZGVzdHJveSkge1xyXG4gICAgICB0aGlzLnNsaWNrR3JpZC5kZXN0cm95KHNob3VsZEVtcHR5RG9tRWxlbWVudENvbnRhaW5lcik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuYmFja2VuZFNlcnZpY2VBcGkpIHtcclxuICAgICAgZm9yIChjb25zdCBwcm9wIG9mIE9iamVjdC5rZXlzKHRoaXMuYmFja2VuZFNlcnZpY2VBcGkpKSB7XHJcbiAgICAgICAgZGVsZXRlIHRoaXMuYmFja2VuZFNlcnZpY2VBcGlbcHJvcCBhcyBrZXlvZiBCYWNrZW5kU2VydmljZUFwaV07XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5iYWNrZW5kU2VydmljZUFwaSA9IHVuZGVmaW5lZDtcclxuICAgIH1cclxuICAgIGZvciAoY29uc3QgcHJvcCBvZiBPYmplY3Qua2V5cyh0aGlzLmNvbHVtbkRlZmluaXRpb25zKSkge1xyXG4gICAgICAodGhpcy5jb2x1bW5EZWZpbml0aW9ucyBhcyBhbnkpW3Byb3BdID0gbnVsbDtcclxuICAgIH1cclxuICAgIGZvciAoY29uc3QgcHJvcCBvZiBPYmplY3Qua2V5cyh0aGlzLnNoYXJlZFNlcnZpY2UpKSB7XHJcbiAgICAgICh0aGlzLnNoYXJlZFNlcnZpY2UgYXMgYW55KVtwcm9wXSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gd2UgY291bGQgb3B0aW9uYWxseSBhbHNvIGVtcHR5IHRoZSBjb250ZW50IG9mIHRoZSBncmlkIGNvbnRhaW5lciBET00gZWxlbWVudFxyXG4gICAgaWYgKHNob3VsZEVtcHR5RG9tRWxlbWVudENvbnRhaW5lcikge1xyXG4gICAgICB0aGlzLmVtcHR5R3JpZENvbnRhaW5lckVsbSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGFsc28gdW5zdWJzY3JpYmUgYWxsIFJ4SlMgc3Vic2NyaXB0aW9uc1xyXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zID0gdW5zdWJzY3JpYmVBbGxPYnNlcnZhYmxlcyh0aGlzLnN1YnNjcmlwdGlvbnMpO1xyXG5cclxuICAgIHRoaXMuX2RhdGFzZXQgPSBudWxsO1xyXG4gICAgdGhpcy5kYXRhc2V0SGllcmFyY2hpY2FsID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5fY29sdW1uRGVmaW5pdGlvbnMgPSBbXTtcclxuICAgIHRoaXMuX2FuZ3VsYXJHcmlkSW5zdGFuY2VzID0gdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgZW1wdHlHcmlkQ29udGFpbmVyRWxtKCkge1xyXG4gICAgY29uc3QgZ3JpZENvbnRhaW5lcklkID0gdGhpcy5ncmlkT3B0aW9ucz8uZ3JpZENvbnRhaW5lcklkID8/ICdncmlkMSc7XHJcbiAgICBjb25zdCBncmlkQ29udGFpbmVyRWxtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgIyR7Z3JpZENvbnRhaW5lcklkfWApO1xyXG4gICAgZW1wdHlFbGVtZW50KGdyaWRDb250YWluZXJFbG0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGVmaW5lIG91ciBpbnRlcm5hbCBQb3N0IFByb2Nlc3MgY2FsbGJhY2ssIGl0IHdpbGwgZXhlY3V0ZSBpbnRlcm5hbGx5IGFmdGVyIHdlIGdldCBiYWNrIHJlc3VsdCBmcm9tIHRoZSBQcm9jZXNzIGJhY2tlbmQgY2FsbFxyXG4gICAqIEZvciBub3csIHRoaXMgaXMgR3JhcGhRTCBTZXJ2aWNlIE9OTFkgZmVhdHVyZSBhbmQgaXQgd2lsbCBiYXNpY2FsbHkgcmVmcmVzaCB0aGUgRGF0YXNldCAmIFBhZ2luYXRpb24gd2l0aG91dCBoYXZpbmcgdGhlIHVzZXIgdG8gY3JlYXRlIGhpcyBvd24gUG9zdFByb2Nlc3MgZXZlcnkgdGltZVxyXG4gICAqL1xyXG4gIGNyZWF0ZUJhY2tlbmRBcGlJbnRlcm5hbFBvc3RQcm9jZXNzQ2FsbGJhY2soZ3JpZE9wdGlvbnM6IEdyaWRPcHRpb24pIHtcclxuICAgIGNvbnN0IGJhY2tlbmRBcGkgPSBncmlkT3B0aW9ucyAmJiBncmlkT3B0aW9ucy5iYWNrZW5kU2VydmljZUFwaTtcclxuICAgIGlmIChiYWNrZW5kQXBpICYmIGJhY2tlbmRBcGkuc2VydmljZSkge1xyXG4gICAgICBjb25zdCBiYWNrZW5kQXBpU2VydmljZSA9IGJhY2tlbmRBcGkuc2VydmljZTtcclxuXHJcbiAgICAgIC8vIGludGVybmFsUG9zdFByb2Nlc3Mgb25seSB3b3JrcyAoZm9yIG5vdykgd2l0aCBhIEdyYXBoUUwgU2VydmljZSwgc28gbWFrZSBzdXJlIGl0IGlzIG9mIHRoYXQgdHlwZVxyXG4gICAgICBpZiAodHlwZW9mIGJhY2tlbmRBcGlTZXJ2aWNlLmdldERhdGFzZXROYW1lID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgYmFja2VuZEFwaS5pbnRlcm5hbFBvc3RQcm9jZXNzID0gKHByb2Nlc3NSZXN1bHQ6IGFueSkgPT4ge1xyXG4gICAgICAgICAgY29uc3QgZGF0YXNldE5hbWUgPSAoYmFja2VuZEFwaSAmJiBiYWNrZW5kQXBpU2VydmljZSAmJiB0eXBlb2YgYmFja2VuZEFwaVNlcnZpY2UuZ2V0RGF0YXNldE5hbWUgPT09ICdmdW5jdGlvbicpID8gYmFja2VuZEFwaVNlcnZpY2UuZ2V0RGF0YXNldE5hbWUoKSA6ICcnO1xyXG4gICAgICAgICAgaWYgKHByb2Nlc3NSZXN1bHQ/LmRhdGFbZGF0YXNldE5hbWVdKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBwcm9jZXNzUmVzdWx0LmRhdGFbZGF0YXNldE5hbWVdLmhhc093blByb3BlcnR5KCdub2RlcycpID8gKHByb2Nlc3NSZXN1bHQgYXMgYW55KS5kYXRhW2RhdGFzZXROYW1lXS5ub2RlcyA6IChwcm9jZXNzUmVzdWx0IGFzIGFueSkuZGF0YVtkYXRhc2V0TmFtZV07XHJcbiAgICAgICAgICAgIGNvbnN0IHRvdGFsQ291bnQgPSBwcm9jZXNzUmVzdWx0LmRhdGFbZGF0YXNldE5hbWVdLmhhc093blByb3BlcnR5KCd0b3RhbENvdW50JykgPyAocHJvY2Vzc1Jlc3VsdCBhcyBhbnkpLmRhdGFbZGF0YXNldE5hbWVdLnRvdGFsQ291bnQgOiAocHJvY2Vzc1Jlc3VsdCBhcyBhbnkpLmRhdGFbZGF0YXNldE5hbWVdLmxlbmd0aDtcclxuICAgICAgICAgICAgdGhpcy5yZWZyZXNoR3JpZERhdGEoZGF0YSwgdG90YWxDb3VudCB8fCAwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbml0aWFsaXphdGlvbihldmVudEhhbmRsZXI6IFNsaWNrRXZlbnRIYW5kbGVyKSB7XHJcbiAgICB0aGlzLmdyaWRPcHRpb25zLnRyYW5zbGF0ZXIgPSB0aGlzLnRyYW5zbGF0ZXJTZXJ2aWNlO1xyXG4gICAgdGhpcy5fZXZlbnRIYW5kbGVyID0gZXZlbnRIYW5kbGVyO1xyXG5cclxuICAgIC8vIHdoZW4gZGV0ZWN0aW5nIGEgZnJvemVuIGdyaWQsIHdlJ2xsIGF1dG9tYXRpY2FsbHkgZW5hYmxlIHRoZSBtb3VzZXdoZWVsIHNjcm9sbCBoYW5kbGVyIHNvIHRoYXQgd2UgY2FuIHNjcm9sbCBmcm9tIGJvdGggbGVmdC9yaWdodCBmcm96ZW4gY29udGFpbmVyc1xyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMgJiYgKCh0aGlzLmdyaWRPcHRpb25zLmZyb3plblJvdyAhPT0gdW5kZWZpbmVkICYmIHRoaXMuZ3JpZE9wdGlvbnMuZnJvemVuUm93ID49IDApIHx8IHRoaXMuZ3JpZE9wdGlvbnMuZnJvemVuQ29sdW1uICE9PSB1bmRlZmluZWQgJiYgdGhpcy5ncmlkT3B0aW9ucy5mcm96ZW5Db2x1bW4gPj0gMCkgJiYgdGhpcy5ncmlkT3B0aW9ucy5lbmFibGVNb3VzZVdoZWVsU2Nyb2xsSGFuZGxlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlTW91c2VXaGVlbFNjcm9sbEhhbmRsZXIgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZS5ldmVudE5hbWluZ1N0eWxlID0gdGhpcy5ncmlkT3B0aW9ucz8uZXZlbnROYW1pbmdTdHlsZSA/PyBFdmVudE5hbWluZ1N0eWxlLmNhbWVsQ2FzZTtcclxuICAgIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZS5wdWJsaXNoKCdvbkJlZm9yZUdyaWRDcmVhdGUnLCB0cnVlKTtcclxuXHJcbiAgICAvLyBtYWtlIHN1cmUgdGhlIGRhdGFzZXQgaXMgaW5pdGlhbGl6ZWQgKGlmIG5vdCBpdCB3aWxsIHRocm93IGFuIGVycm9yIHRoYXQgaXQgY2Fubm90IGdldExlbmd0aCBvZiBudWxsKVxyXG4gICAgdGhpcy5fZGF0YXNldCA9IHRoaXMuX2RhdGFzZXQgfHwgW107XHJcbiAgICB0aGlzLmdyaWRPcHRpb25zID0gdGhpcy5tZXJnZUdyaWRPcHRpb25zKHRoaXMuZ3JpZE9wdGlvbnMpO1xyXG4gICAgdGhpcy5fcGFnaW5hdGlvbk9wdGlvbnMgPSB0aGlzLmdyaWRPcHRpb25zPy5wYWdpbmF0aW9uO1xyXG4gICAgdGhpcy5sb2NhbGVzID0gdGhpcy5ncmlkT3B0aW9ucz8ubG9jYWxlcyA/PyBDb25zdGFudHMubG9jYWxlcztcclxuICAgIHRoaXMuYmFja2VuZFNlcnZpY2VBcGkgPSB0aGlzLmdyaWRPcHRpb25zPy5iYWNrZW5kU2VydmljZUFwaTtcclxuICAgIHRoaXMuX2lzTG9jYWxHcmlkID0gIXRoaXMuYmFja2VuZFNlcnZpY2VBcGk7IC8vIGNvbnNpZGVyZWQgYSBsb2NhbCBncmlkIGlmIGl0IGRvZXNuJ3QgaGF2ZSBhIGJhY2tlbmQgc2VydmljZSBzZXRcclxuXHJcbiAgICB0aGlzLmNyZWF0ZUJhY2tlbmRBcGlJbnRlcm5hbFBvc3RQcm9jZXNzQ2FsbGJhY2sodGhpcy5ncmlkT3B0aW9ucyk7XHJcblxyXG4gICAgaWYgKCF0aGlzLmN1c3RvbURhdGFWaWV3KSB7XHJcbiAgICAgIGNvbnN0IGRhdGF2aWV3SW5saW5lRmlsdGVycyA9IHRoaXMuZ3JpZE9wdGlvbnMuZGF0YVZpZXcgJiYgdGhpcy5ncmlkT3B0aW9ucy5kYXRhVmlldy5pbmxpbmVGaWx0ZXJzIHx8IGZhbHNlO1xyXG4gICAgICBsZXQgZGF0YVZpZXdPcHRpb25zOiBEYXRhVmlld09wdGlvbiA9IHsgaW5saW5lRmlsdGVyczogZGF0YXZpZXdJbmxpbmVGaWx0ZXJzIH07XHJcblxyXG4gICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5kcmFnZ2FibGVHcm91cGluZyB8fCB0aGlzLmdyaWRPcHRpb25zLmVuYWJsZUdyb3VwaW5nKSB7XHJcbiAgICAgICAgdGhpcy5ncm91cEl0ZW1NZXRhZGF0YVByb3ZpZGVyID0gbmV3IFNsaWNrLkRhdGEuR3JvdXBJdGVtTWV0YWRhdGFQcm92aWRlcigpO1xyXG4gICAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5ncm91cEl0ZW1NZXRhZGF0YVByb3ZpZGVyID0gdGhpcy5ncm91cEl0ZW1NZXRhZGF0YVByb3ZpZGVyO1xyXG4gICAgICAgIGRhdGFWaWV3T3B0aW9ucyA9IHsgLi4uZGF0YVZpZXdPcHRpb25zLCBncm91cEl0ZW1NZXRhZGF0YVByb3ZpZGVyOiB0aGlzLmdyb3VwSXRlbU1ldGFkYXRhUHJvdmlkZXIgfTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmRhdGFWaWV3ID0gbmV3IFNsaWNrLkRhdGEuRGF0YVZpZXcoZGF0YVZpZXdPcHRpb25zKTtcclxuICAgICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnB1Ymxpc2goJ29uRGF0YXZpZXdDcmVhdGVkJywgdGhpcy5kYXRhVmlldyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZ2V0IGFueSBwb3NzaWJsZSBTZXJ2aWNlcyB0aGF0IHVzZXIgd2FudCB0byByZWdpc3RlciB3aGljaCBkb24ndCByZXF1aXJlIFNsaWNrR3JpZCB0byBiZSBpbnN0YW50aWF0ZWRcclxuICAgIC8vIFJ4SlMgUmVzb3VyY2UgaXMgaW4gdGhpcyBsb3QgYmVjYXVzZSBpdCBoYXMgdG8gYmUgcmVnaXN0ZXJlZCBiZWZvcmUgYW55dGhpbmcgZWxzZSBhbmQgZG9lc24ndCByZXF1aXJlIFNsaWNrR3JpZCB0byBiZSBpbml0aWFsaXplZFxyXG4gICAgdGhpcy5wcmVSZWdpc3RlclJlc291cmNlcygpO1xyXG5cclxuICAgIC8vIGZvciBjb252ZW5pZW5jZSB0byB0aGUgdXNlciwgd2UgcHJvdmlkZSB0aGUgcHJvcGVydHkgXCJlZGl0b3JcIiBhcyBhbiBBbmd1bGFyLVNsaWNrZ3JpZCBlZGl0b3IgY29tcGxleCBvYmplY3RcclxuICAgIC8vIGhvd2V2ZXIgXCJlZGl0b3JcIiBpcyB1c2VkIGludGVybmFsbHkgYnkgU2xpY2tHcmlkIGZvciBpdCdzIG93biBFZGl0b3IgRmFjdG9yeVxyXG4gICAgLy8gc28gaW4gb3VyIGxpYiB3ZSB3aWxsIHN3YXAgXCJlZGl0b3JcIiBhbmQgY29weSBpdCBpbnRvIGEgbmV3IHByb3BlcnR5IGNhbGxlZCBcImludGVybmFsQ29sdW1uRWRpdG9yXCJcclxuICAgIC8vIHRoZW4gdGFrZSBiYWNrIFwiZWRpdG9yLm1vZGVsXCIgYW5kIG1ha2UgaXQgdGhlIG5ldyBcImVkaXRvclwiIHNvIHRoYXQgU2xpY2tHcmlkIEVkaXRvciBGYWN0b3J5IHN0aWxsIHdvcmtzXHJcbiAgICB0aGlzLl9jb2x1bW5EZWZpbml0aW9ucyA9IHRoaXMuc3dhcEludGVybmFsRWRpdG9yVG9TbGlja0dyaWRGYWN0b3J5RWRpdG9yKHRoaXMuX2NvbHVtbkRlZmluaXRpb25zKTtcclxuXHJcbiAgICAvLyBpZiB0aGUgdXNlciB3YW50cyB0byBhdXRvbWF0aWNhbGx5IGFkZCBhIEN1c3RvbSBFZGl0b3IgRm9ybWF0dGVyLCB3ZSBuZWVkIHRvIGNhbGwgdGhlIGF1dG8gYWRkIGZ1bmN0aW9uIGFnYWluXHJcbiAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5hdXRvQWRkQ3VzdG9tRWRpdG9yRm9ybWF0dGVyKSB7XHJcbiAgICAgIGF1dG9BZGRFZGl0b3JGb3JtYXR0ZXJUb0NvbHVtbnNXaXRoRWRpdG9yKHRoaXMuX2NvbHVtbkRlZmluaXRpb25zLCB0aGlzLmdyaWRPcHRpb25zLmF1dG9BZGRDdXN0b21FZGl0b3JGb3JtYXR0ZXIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHNhdmUgcmVmZXJlbmNlIGZvciBhbGwgY29sdW1ucyBiZWZvcmUgdGhleSBvcHRpb25hbGx5IGJlY29tZSBoaWRkZW4vdmlzaWJsZVxyXG4gICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmFsbENvbHVtbnMgPSB0aGlzLl9jb2x1bW5EZWZpbml0aW9ucztcclxuICAgIHRoaXMuc2hhcmVkU2VydmljZS52aXNpYmxlQ29sdW1ucyA9IHRoaXMuX2NvbHVtbkRlZmluaXRpb25zO1xyXG4gICAgdGhpcy5leHRlbnNpb25TZXJ2aWNlLmNyZWF0ZUV4dGVuc2lvbnNCZWZvcmVHcmlkQ3JlYXRpb24odGhpcy5fY29sdW1uRGVmaW5pdGlvbnMsIHRoaXMuZ3JpZE9wdGlvbnMpO1xyXG5cclxuICAgIC8vIGlmIHVzZXIgZW50ZXJlZCBzb21lIFBpbm5pbmcvRnJvemVuIFwicHJlc2V0c1wiLCB3ZSBuZWVkIHRvIGFwcGx5IHRoZW0gaW4gdGhlIGdyaWQgb3B0aW9uc1xyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMucHJlc2V0cz8ucGlubmluZykge1xyXG4gICAgICB0aGlzLmdyaWRPcHRpb25zID0geyAuLi50aGlzLmdyaWRPcHRpb25zLCAuLi50aGlzLmdyaWRPcHRpb25zLnByZXNldHMucGlubmluZyB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGJ1aWxkIFNsaWNrR3JpZCBHcmlkLCBhbHNvIHVzZXIgbWlnaHQgb3B0aW9uYWxseSBwYXNzIGEgY3VzdG9tIGRhdGF2aWV3IChlLmcuIHJlbW90ZSBtb2RlbClcclxuICAgIHRoaXMuc2xpY2tHcmlkID0gbmV3IFNsaWNrLkdyaWQoYCMke3RoaXMuZ3JpZElkfWAsIHRoaXMuY3VzdG9tRGF0YVZpZXcgfHwgdGhpcy5kYXRhVmlldywgdGhpcy5fY29sdW1uRGVmaW5pdGlvbnMsIHRoaXMuZ3JpZE9wdGlvbnMpO1xyXG4gICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmRhdGFWaWV3ID0gdGhpcy5kYXRhVmlldztcclxuICAgIHRoaXMuc2hhcmVkU2VydmljZS5zbGlja0dyaWQgPSB0aGlzLnNsaWNrR3JpZDtcclxuXHJcbiAgICB0aGlzLmV4dGVuc2lvblNlcnZpY2UuYmluZERpZmZlcmVudEV4dGVuc2lvbnMoKTtcclxuICAgIHRoaXMuYmluZERpZmZlcmVudEhvb2tzKHRoaXMuc2xpY2tHcmlkLCB0aGlzLmdyaWRPcHRpb25zLCB0aGlzLmRhdGFWaWV3KTtcclxuXHJcbiAgICAvLyB3aGVuIGl0J3MgYSBmcm96ZW4gZ3JpZCwgd2UgbmVlZCB0byBrZWVwIHRoZSBmcm96ZW4gY29sdW1uIGlkIGZvciByZWZlcmVuY2UgaWYgd2UgZXZlciBzaG93L2hpZGUgY29sdW1uIGZyb20gQ29sdW1uUGlja2VyL0dyaWRNZW51IGFmdGVyd2FyZFxyXG4gICAgY29uc3QgZnJvemVuQ29sdW1uSW5kZXggPSB0aGlzLmdyaWRPcHRpb25zLmZyb3plbkNvbHVtbiAhPT0gdW5kZWZpbmVkID8gdGhpcy5ncmlkT3B0aW9ucy5mcm96ZW5Db2x1bW4gOiAtMTtcclxuICAgIGlmIChmcm96ZW5Db2x1bW5JbmRleCA+PSAwICYmIGZyb3plbkNvbHVtbkluZGV4IDw9IHRoaXMuX2NvbHVtbkRlZmluaXRpb25zLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnNoYXJlZFNlcnZpY2UuZnJvemVuVmlzaWJsZUNvbHVtbklkID0gdGhpcy5fY29sdW1uRGVmaW5pdGlvbnNbZnJvemVuQ29sdW1uSW5kZXhdLmlkIHx8ICcnO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGdldCBhbnkgcG9zc2libGUgU2VydmljZXMgdGhhdCB1c2VyIHdhbnQgdG8gcmVnaXN0ZXJcclxuICAgIHRoaXMucmVnaXN0ZXJSZXNvdXJjZXMoKTtcclxuXHJcbiAgICAvLyBpbml0aWFsaXplIHRoZSBTbGlja0dyaWQgZ3JpZFxyXG4gICAgdGhpcy5zbGlja0dyaWQuaW5pdCgpO1xyXG5cclxuICAgIC8vIGluaXRpYWxpemVkIHRoZSByZXNpemVyIHNlcnZpY2Ugb25seSBhZnRlciBTbGlja0dyaWQgaXMgaW5pdGlhbGl6ZWRcclxuICAgIC8vIGlmIHdlIGRvbid0IHdlIGVuZCB1cCBiaW5kaW5nIG91ciByZXNpemUgdG8gYSBncmlkIGVsZW1lbnQgdGhhdCBkb2Vzbid0IHlldCBleGlzdCBpbiB0aGUgRE9NIGFuZCB0aGUgcmVzaXplciBzZXJ2aWNlIHdpbGwgZmFpbCBzaWxlbnRseSAoYmVjYXVzZSBpdCBoYXMgYSB0cnkvY2F0Y2ggdGhhdCB1bmJpbmRzIHRoZSByZXNpemUgd2l0aG91dCB0aHJvd2luZyBiYWNrKVxyXG4gICAgaWYgKHRoaXMuZ3JpZENvbnRhaW5lckVsZW1lbnQpIHtcclxuICAgICAgdGhpcy5yZXNpemVyU2VydmljZS5pbml0KHRoaXMuc2xpY2tHcmlkLCB0aGlzLmdyaWRDb250YWluZXJFbGVtZW50IGFzIEhUTUxEaXZFbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyB1c2VyIGNvdWxkIHNob3cgYSBjdXN0b20gZm9vdGVyIHdpdGggdGhlIGRhdGEgbWV0cmljcyAoZGF0YXNldCBsZW5ndGggYW5kIGxhc3QgdXBkYXRlZCB0aW1lc3RhbXApXHJcbiAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUGFnaW5hdGlvbiAmJiB0aGlzLmdyaWRPcHRpb25zLnNob3dDdXN0b21Gb290ZXIgJiYgdGhpcy5ncmlkT3B0aW9ucy5jdXN0b21Gb290ZXJPcHRpb25zICYmIHRoaXMuZ3JpZENvbnRhaW5lckVsZW1lbnQpIHtcclxuICAgICAgdGhpcy5zbGlja0Zvb3RlciA9IG5ldyBTbGlja0Zvb3RlckNvbXBvbmVudCh0aGlzLnNsaWNrR3JpZCwgdGhpcy5ncmlkT3B0aW9ucy5jdXN0b21Gb290ZXJPcHRpb25zLCB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UsIHRoaXMudHJhbnNsYXRlclNlcnZpY2UpO1xyXG4gICAgICB0aGlzLnNsaWNrRm9vdGVyLnJlbmRlckZvb3Rlcih0aGlzLmdyaWRDb250YWluZXJFbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRoaXMuY3VzdG9tRGF0YVZpZXcgJiYgdGhpcy5kYXRhVmlldykge1xyXG4gICAgICAvLyBsb2FkIHRoZSBkYXRhIGluIHRoZSBEYXRhVmlldyAodW5sZXNzIGl0J3MgYSBoaWVyYXJjaGljYWwgZGF0YXNldCwgaWYgc28gaXQgd2lsbCBiZSBsb2FkZWQgYWZ0ZXIgdGhlIGluaXRpYWwgdHJlZSBzb3J0KVxyXG4gICAgICBjb25zdCBpbml0aWFsRGF0YXNldCA9IHRoaXMuZ3JpZE9wdGlvbnM/LmVuYWJsZVRyZWVEYXRhID8gdGhpcy5zb3J0VHJlZURhdGFzZXQodGhpcy5fZGF0YXNldCkgOiB0aGlzLl9kYXRhc2V0O1xyXG4gICAgICB0aGlzLmRhdGFWaWV3LmJlZ2luVXBkYXRlKCk7XHJcbiAgICAgIHRoaXMuZGF0YVZpZXcuc2V0SXRlbXMoaW5pdGlhbERhdGFzZXQgfHwgW10sIHRoaXMuZ3JpZE9wdGlvbnMuZGF0YXNldElkUHJvcGVydHlOYW1lID8/ICdpZCcpO1xyXG4gICAgICB0aGlzLmRhdGFWaWV3LmVuZFVwZGF0ZSgpO1xyXG5cclxuICAgICAgLy8gaWYgeW91IGRvbid0IHdhbnQgdGhlIGl0ZW1zIHRoYXQgYXJlIG5vdCB2aXNpYmxlIChkdWUgdG8gYmVpbmcgZmlsdGVyZWQgb3V0IG9yIGJlaW5nIG9uIGEgZGlmZmVyZW50IHBhZ2UpXHJcbiAgICAgIC8vIHRvIHN0YXkgc2VsZWN0ZWQsIHBhc3MgJ2ZhbHNlJyB0byB0aGUgc2Vjb25kIGFyZ1xyXG4gICAgICBjb25zdCBzZWxlY3Rpb25Nb2RlbCA9IHRoaXMuc2xpY2tHcmlkICYmIHRoaXMuc2xpY2tHcmlkLmdldFNlbGVjdGlvbk1vZGVsKCk7XHJcbiAgICAgIGlmIChzZWxlY3Rpb25Nb2RlbCAmJiB0aGlzLmdyaWRPcHRpb25zICYmIHRoaXMuZ3JpZE9wdGlvbnMuZGF0YVZpZXcgJiYgdGhpcy5ncmlkT3B0aW9ucy5kYXRhVmlldy5oYXNPd25Qcm9wZXJ0eSgnc3luY0dyaWRTZWxlY3Rpb24nKSkge1xyXG4gICAgICAgIC8vIGlmIHdlIGFyZSB1c2luZyBhIEJhY2tlbmQgU2VydmljZSwgd2Ugd2lsbCBkbyBhbiBleHRyYSBmbGFnIGNoZWNrLCB0aGUgcmVhc29uIGlzIGJlY2F1c2UgaXQgbWlnaHQgaGF2ZSBzb21lIHVuaW50ZW5kZWQgYmVoYXZpb3JzXHJcbiAgICAgICAgLy8gd2l0aCB0aGUgQmFja2VuZFNlcnZpY2VBcGkgYmVjYXVzZSB0ZWNobmljYWxseSB0aGUgZGF0YSBpbiB0aGUgcGFnZSBjaGFuZ2VzIHRoZSBEYXRhVmlldyBvbiBldmVyeSBwYWdlIGNoYW5nZS5cclxuICAgICAgICBsZXQgcHJlc2VydmVkUm93U2VsZWN0aW9uV2l0aEJhY2tlbmQgPSBmYWxzZTtcclxuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5iYWNrZW5kU2VydmljZUFwaSAmJiB0aGlzLmdyaWRPcHRpb25zLmRhdGFWaWV3Lmhhc093blByb3BlcnR5KCdzeW5jR3JpZFNlbGVjdGlvbldpdGhCYWNrZW5kU2VydmljZScpKSB7XHJcbiAgICAgICAgICBwcmVzZXJ2ZWRSb3dTZWxlY3Rpb25XaXRoQmFja2VuZCA9IHRoaXMuZ3JpZE9wdGlvbnMuZGF0YVZpZXcuc3luY0dyaWRTZWxlY3Rpb25XaXRoQmFja2VuZFNlcnZpY2UgYXMgYm9vbGVhbjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHN5bmNHcmlkU2VsZWN0aW9uID0gdGhpcy5ncmlkT3B0aW9ucy5kYXRhVmlldy5zeW5jR3JpZFNlbGVjdGlvbjtcclxuICAgICAgICBpZiAodHlwZW9mIHN5bmNHcmlkU2VsZWN0aW9uID09PSAnYm9vbGVhbicpIHtcclxuICAgICAgICAgIGxldCBwcmVzZXJ2ZWRSb3dTZWxlY3Rpb24gPSBzeW5jR3JpZFNlbGVjdGlvbjtcclxuICAgICAgICAgIGlmICghdGhpcy5faXNMb2NhbEdyaWQpIHtcclxuICAgICAgICAgICAgLy8gd2hlbiB1c2luZyBCYWNrZW5kU2VydmljZUFwaSwgd2UnbGwgYmUgdXNpbmcgdGhlIFwic3luY0dyaWRTZWxlY3Rpb25XaXRoQmFja2VuZFNlcnZpY2VcIiBmbGFnIEJVVCBcInN5bmNHcmlkU2VsZWN0aW9uXCIgbXVzdCBhbHNvIGJlIHNldCB0byBUcnVlXHJcbiAgICAgICAgICAgIHByZXNlcnZlZFJvd1NlbGVjdGlvbiA9IHN5bmNHcmlkU2VsZWN0aW9uICYmIHByZXNlcnZlZFJvd1NlbGVjdGlvbldpdGhCYWNrZW5kO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5kYXRhVmlldy5zeW5jR3JpZFNlbGVjdGlvbih0aGlzLnNsaWNrR3JpZCwgcHJlc2VydmVkUm93U2VsZWN0aW9uKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBzeW5jR3JpZFNlbGVjdGlvbiA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICAgIHRoaXMuZGF0YVZpZXcuc3luY0dyaWRTZWxlY3Rpb24odGhpcy5zbGlja0dyaWQsIHN5bmNHcmlkU2VsZWN0aW9uLnByZXNlcnZlSGlkZGVuLCBzeW5jR3JpZFNlbGVjdGlvbi5wcmVzZXJ2ZUhpZGRlbk9uU2VsZWN0aW9uQ2hhbmdlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGRhdGFzZXRMbiA9IHRoaXMuZGF0YVZpZXcuZ2V0TGVuZ3RoKCkgfHwgdGhpcy5fZGF0YXNldCAmJiB0aGlzLl9kYXRhc2V0Lmxlbmd0aCB8fCAwO1xyXG4gICAgICBpZiAoZGF0YXNldExuID4gMCkge1xyXG4gICAgICAgIGlmICghdGhpcy5faXNEYXRhc2V0SW5pdGlhbGl6ZWQgJiYgKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2hlY2tib3hTZWxlY3RvciB8fCB0aGlzLmdyaWRPcHRpb25zLmVuYWJsZVJvd1NlbGVjdGlvbikpIHtcclxuICAgICAgICAgIHRoaXMubG9hZFJvd1NlbGVjdGlvblByZXNldFdoZW5FeGlzdHMoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5sb2FkRmlsdGVyUHJlc2V0c1doZW5EYXRhc2V0SW5pdGlhbGl6ZWQoKTtcclxuICAgICAgICB0aGlzLl9pc0RhdGFzZXRJbml0aWFsaXplZCA9IHRydWU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyB1c2VyIG1pZ2h0IHdhbnQgdG8gaGlkZSB0aGUgaGVhZGVyIHJvdyBvbiBwYWdlIGxvYWQgYnV0IHN0aWxsIGhhdmUgYGVuYWJsZUZpbHRlcmluZzogdHJ1ZWBcclxuICAgIC8vIGlmIHRoYXQgaXMgdGhlIGNhc2UsIHdlIG5lZWQgdG8gaGlkZSB0aGUgaGVhZGVyUm93IE9OTFkgQUZURVIgYWxsIGZpbHRlcnMgZ290IGNyZWF0ZWQgJiBkYXRhVmlldyBleGlzdFxyXG4gICAgaWYgKHRoaXMuX2hpZGVIZWFkZXJSb3dBZnRlclBhZ2VMb2FkKSB7XHJcbiAgICAgIHRoaXMuc2hvd0hlYWRlclJvdyhmYWxzZSk7XHJcbiAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5oaWRlSGVhZGVyUm93QWZ0ZXJQYWdlTG9hZCA9IHRoaXMuX2hpZGVIZWFkZXJSb3dBZnRlclBhZ2VMb2FkO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHB1Ymxpc2ggJiBkaXNwYXRjaCBjZXJ0YWluIGV2ZW50c1xyXG4gICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnB1Ymxpc2goJ29uR3JpZENyZWF0ZWQnLCB0aGlzLnNsaWNrR3JpZCk7XHJcblxyXG4gICAgLy8gYWZ0ZXIgdGhlIERhdGFWaWV3IGlzIGNyZWF0ZWQgJiB1cGRhdGVkIGV4ZWN1dGUgc29tZSBwcm9jZXNzZXNcclxuICAgIGlmICghdGhpcy5jdXN0b21EYXRhVmlldykge1xyXG4gICAgICB0aGlzLmV4ZWN1dGVBZnRlckRhdGF2aWV3Q3JlYXRlZCh0aGlzLnNsaWNrR3JpZCwgdGhpcy5ncmlkT3B0aW9ucyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gYmluZCByZXNpemUgT05MWSBhZnRlciB0aGUgZGF0YVZpZXcgaXMgcmVhZHlcclxuICAgIHRoaXMuYmluZFJlc2l6ZUhvb2sodGhpcy5zbGlja0dyaWQsIHRoaXMuZ3JpZE9wdGlvbnMpO1xyXG5cclxuICAgIC8vIGJpbmQgdGhlIEJhY2tlbmQgU2VydmljZSBBUEkgY2FsbGJhY2sgZnVuY3Rpb25zIG9ubHkgYWZ0ZXIgdGhlIGdyaWQgaXMgaW5pdGlhbGl6ZWRcclxuICAgIC8vIGJlY2F1c2UgdGhlIHByZVByb2Nlc3MoKSBhbmQgb25Jbml0KCkgbWlnaHQgZ2V0IHRyaWdnZXJlZFxyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnM/LmJhY2tlbmRTZXJ2aWNlQXBpKSB7XHJcbiAgICAgIHRoaXMuYmluZEJhY2tlbmRDYWxsYmFja0Z1bmN0aW9ucyh0aGlzLmdyaWRPcHRpb25zKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBsb2NhbCBncmlkLCBjaGVjayBpZiB3ZSBuZWVkIHRvIHNob3cgdGhlIFBhZ2luYXRpb25cclxuICAgIC8vIGlmIHNvIHRoZW4gYWxzbyBjaGVjayBpZiB0aGVyZSdzIGFueSBwcmVzZXRzIGFuZCBmaW5hbGx5IGluaXRpYWxpemUgdGhlIFBhZ2luYXRpb25TZXJ2aWNlXHJcbiAgICAvLyBhIGxvY2FsIGdyaWQgd2l0aCBQYWdpbmF0aW9uIHByZXNldHMgd2lsbCBwb3RlbnRpYWxseSBoYXZlIGEgZGlmZmVyZW50IHRvdGFsIG9mIGl0ZW1zLCB3ZSdsbCBuZWVkIHRvIGdldCBpdCBmcm9tIHRoZSBEYXRhVmlldyBhbmQgdXBkYXRlIG91ciB0b3RhbFxyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnM/LmVuYWJsZVBhZ2luYXRpb24gJiYgdGhpcy5faXNMb2NhbEdyaWQpIHtcclxuICAgICAgdGhpcy5zaG93UGFnaW5hdGlvbiA9IHRydWU7XHJcbiAgICAgIHRoaXMubG9hZExvY2FsR3JpZFBhZ2luYXRpb24odGhpcy5kYXRhc2V0KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl9hbmd1bGFyR3JpZEluc3RhbmNlcyA9IHtcclxuICAgICAgLy8gU2xpY2sgR3JpZCAmIERhdGFWaWV3IG9iamVjdHNcclxuICAgICAgZGF0YVZpZXc6IHRoaXMuZGF0YVZpZXcsXHJcbiAgICAgIHNsaWNrR3JpZDogdGhpcy5zbGlja0dyaWQsXHJcbiAgICAgIGV4dGVuc2lvbnM6IHRoaXMuZXh0ZW5zaW9uU2VydmljZT8uZXh0ZW5zaW9uTGlzdCxcclxuXHJcbiAgICAgIC8vIHB1YmxpYyBtZXRob2RzXHJcbiAgICAgIGRlc3Ryb3k6IHRoaXMuZGVzdHJveS5iaW5kKHRoaXMpLFxyXG5cclxuICAgICAgLy8gcmV0dXJuIGFsbCBhdmFpbGFibGUgU2VydmljZXMgKG5vbi1zaW5nbGV0b24pXHJcbiAgICAgIGJhY2tlbmRTZXJ2aWNlOiB0aGlzLmdyaWRPcHRpb25zPy5iYWNrZW5kU2VydmljZUFwaT8uc2VydmljZSxcclxuICAgICAgZmlsdGVyU2VydmljZTogdGhpcy5maWx0ZXJTZXJ2aWNlLFxyXG4gICAgICBncmlkRXZlbnRTZXJ2aWNlOiB0aGlzLmdyaWRFdmVudFNlcnZpY2UsXHJcbiAgICAgIGdyaWRTdGF0ZVNlcnZpY2U6IHRoaXMuZ3JpZFN0YXRlU2VydmljZSxcclxuICAgICAgZ3JpZFNlcnZpY2U6IHRoaXMuZ3JpZFNlcnZpY2UsXHJcbiAgICAgIGdyb3VwaW5nU2VydmljZTogdGhpcy5ncm91cGluZ1NlcnZpY2UsXHJcbiAgICAgIGV4dGVuc2lvblNlcnZpY2U6IHRoaXMuZXh0ZW5zaW9uU2VydmljZSxcclxuICAgICAgcGFnaW5hdGlvblNlcnZpY2U6IHRoaXMucGFnaW5hdGlvblNlcnZpY2UsXHJcbiAgICAgIHJlc2l6ZXJTZXJ2aWNlOiB0aGlzLnJlc2l6ZXJTZXJ2aWNlLFxyXG4gICAgICBzb3J0U2VydmljZTogdGhpcy5zb3J0U2VydmljZSxcclxuICAgICAgdHJlZURhdGFTZXJ2aWNlOiB0aGlzLnRyZWVEYXRhU2VydmljZSxcclxuICAgIH1cclxuXHJcbiAgICAvLyBhbGwgaW5zdGFuY2VzIChTbGlja0dyaWQsIERhdGFWaWV3ICYgYWxsIFNlcnZpY2VzKVxyXG4gICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnB1Ymxpc2goJ29uQW5ndWxhckdyaWRDcmVhdGVkJywgdGhpcy5fYW5ndWxhckdyaWRJbnN0YW5jZXMpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogT24gYSBQYWdpbmF0aW9uIGNoYW5nZWQsIHdlIHdpbGwgdHJpZ2dlciBhIEdyaWQgU3RhdGUgY2hhbmdlZCB3aXRoIHRoZSBuZXcgcGFnaW5hdGlvbiBpbmZvXHJcbiAgICogQWxzbyBpZiB3ZSB1c2UgUm93IFNlbGVjdGlvbiBvciB0aGUgQ2hlY2tib3ggU2VsZWN0b3IsIHdlIG5lZWQgdG8gcmVzZXQgYW55IHNlbGVjdGlvblxyXG4gICAqL1xyXG4gIHBhZ2luYXRpb25DaGFuZ2VkKHBhZ2luYXRpb246IFNlcnZpY2VQYWdpbmF0aW9uKSB7XHJcbiAgICBjb25zdCBpc1N5bmNHcmlkU2VsZWN0aW9uRW5hYmxlZCA9IHRoaXMuZ3JpZFN0YXRlU2VydmljZT8ubmVlZFRvUHJlc2VydmVSb3dTZWxlY3Rpb24oKSA/PyBmYWxzZTtcclxuICAgIGlmICghaXNTeW5jR3JpZFNlbGVjdGlvbkVuYWJsZWQgJiYgKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUm93U2VsZWN0aW9uIHx8IHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2hlY2tib3hTZWxlY3RvcikpIHtcclxuICAgICAgdGhpcy5zbGlja0dyaWQuc2V0U2VsZWN0ZWRSb3dzKFtdKTtcclxuICAgIH1cclxuICAgIGNvbnN0IHsgcGFnZU51bWJlciwgcGFnZVNpemUgfSA9IHBhZ2luYXRpb247XHJcbiAgICBpZiAodGhpcy5zaGFyZWRTZXJ2aWNlKSB7XHJcbiAgICAgIGlmIChwYWdlU2l6ZSAhPT0gdW5kZWZpbmVkICYmIHBhZ2VOdW1iZXIgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5jdXJyZW50UGFnaW5hdGlvbiA9IHsgcGFnZU51bWJlciwgcGFnZVNpemUgfTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnB1Ymxpc2goJ29uR3JpZFN0YXRlQ2hhbmdlZCcsIHtcclxuICAgICAgY2hhbmdlOiB7IG5ld1ZhbHVlczogeyBwYWdlTnVtYmVyLCBwYWdlU2l6ZSB9LCB0eXBlOiBHcmlkU3RhdGVUeXBlLnBhZ2luYXRpb24gfSxcclxuICAgICAgZ3JpZFN0YXRlOiB0aGlzLmdyaWRTdGF0ZVNlcnZpY2UuZ2V0Q3VycmVudEdyaWRTdGF0ZSgpXHJcbiAgICB9KTtcclxuICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBXaGVuIGRhdGFzZXQgY2hhbmdlcywgd2UgbmVlZCB0byByZWZyZXNoIHRoZSBlbnRpcmUgZ3JpZCBVSSAmIHBvc3NpYmx5IHJlc2l6ZSBpdCBhcyB3ZWxsXHJcbiAgICogQHBhcmFtIGRhdGFzZXRcclxuICAgKi9cclxuICByZWZyZXNoR3JpZERhdGEoZGF0YXNldDogYW55W10sIHRvdGFsQ291bnQ/OiBudW1iZXIpIHtcclxuICAgIGlmICh0aGlzLmdyaWRPcHRpb25zICYmIHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlRW1wdHlEYXRhV2FybmluZ01lc3NhZ2UgJiYgQXJyYXkuaXNBcnJheShkYXRhc2V0KSkge1xyXG4gICAgICBjb25zdCBmaW5hbFRvdGFsQ291bnQgPSB0b3RhbENvdW50IHx8IGRhdGFzZXQubGVuZ3RoO1xyXG4gICAgICB0aGlzLmRpc3BsYXlFbXB0eURhdGFXYXJuaW5nKGZpbmFsVG90YWxDb3VudCA8IDEpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGFzZXQpICYmIHRoaXMuc2xpY2tHcmlkICYmIHRoaXMuZGF0YVZpZXc/LnNldEl0ZW1zKSB7XHJcbiAgICAgIHRoaXMuZGF0YVZpZXcuc2V0SXRlbXMoZGF0YXNldCwgdGhpcy5ncmlkT3B0aW9ucy5kYXRhc2V0SWRQcm9wZXJ0eU5hbWUgPz8gJ2lkJyk7XHJcbiAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9ucy5iYWNrZW5kU2VydmljZUFwaSAmJiAhdGhpcy5ncmlkT3B0aW9ucy5lbmFibGVUcmVlRGF0YSkge1xyXG4gICAgICAgIHRoaXMuZGF0YVZpZXcucmVTb3J0KCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChkYXRhc2V0Lmxlbmd0aCA+IDApIHtcclxuICAgICAgICBpZiAoIXRoaXMuX2lzRGF0YXNldEluaXRpYWxpemVkKSB7XHJcbiAgICAgICAgICB0aGlzLmxvYWRGaWx0ZXJQcmVzZXRzV2hlbkRhdGFzZXRJbml0aWFsaXplZCgpO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLmVuYWJsZUNoZWNrYm94U2VsZWN0b3IpIHtcclxuICAgICAgICAgICAgdGhpcy5sb2FkUm93U2VsZWN0aW9uUHJlc2V0V2hlbkV4aXN0cygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9pc0RhdGFzZXRJbml0aWFsaXplZCA9IHRydWU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChkYXRhc2V0KSB7XHJcbiAgICAgICAgdGhpcy5zbGlja0dyaWQuaW52YWxpZGF0ZSgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBkaXNwbGF5IHRoZSBQYWdpbmF0aW9uIGNvbXBvbmVudCBvbmx5IGFmdGVyIGNhbGxpbmcgdGhpcyByZWZyZXNoIGRhdGEgZmlyc3QsIHdlIGNhbGwgaXQgaGVyZSBzbyB0aGF0IGlmIHdlIHByZXNldCBwYWdpbmF0aW9uIHBhZ2UgbnVtYmVyIGl0IHdpbGwgYmUgc2hvd24gY29ycmVjdGx5XHJcbiAgICAgIHRoaXMuc2hvd1BhZ2luYXRpb24gPSAodGhpcy5ncmlkT3B0aW9ucyAmJiAodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVQYWdpbmF0aW9uIHx8ICh0aGlzLmdyaWRPcHRpb25zLmJhY2tlbmRTZXJ2aWNlQXBpICYmIHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUGFnaW5hdGlvbiA9PT0gdW5kZWZpbmVkKSkpID8gdHJ1ZSA6IGZhbHNlO1xyXG5cclxuICAgICAgaWYgKHRoaXMuX3BhZ2luYXRpb25PcHRpb25zICYmIHRoaXMuZ3JpZE9wdGlvbnM/LnBhZ2luYXRpb24gJiYgdGhpcy5ncmlkT3B0aW9ucz8uYmFja2VuZFNlcnZpY2VBcGkpIHtcclxuICAgICAgICBjb25zdCBwYWdpbmF0aW9uT3B0aW9ucyA9IHRoaXMuc2V0UGFnaW5hdGlvbk9wdGlvbnNXaGVuUHJlc2V0RGVmaW5lZCh0aGlzLmdyaWRPcHRpb25zLCB0aGlzLl9wYWdpbmF0aW9uT3B0aW9ucyBhcyBQYWdpbmF0aW9uKTtcclxuICAgICAgICAvLyB3aGVuIHdlIGhhdmUgYSB0b3RhbENvdW50IHVzZSBpdCwgZWxzZSB3ZSdsbCB0YWtlIGl0IGZyb20gdGhlIHBhZ2luYXRpb24gb2JqZWN0XHJcbiAgICAgICAgLy8gb25seSB1cGRhdGUgdGhlIHRvdGFsIGl0ZW1zIGlmIGl0J3MgZGlmZmVyZW50IHRvIGF2b2lkIHJlZnJlc2hpbmcgdGhlIFVJXHJcbiAgICAgICAgY29uc3QgdG90YWxSZWNvcmRzID0gKHRvdGFsQ291bnQgIT09IHVuZGVmaW5lZCkgPyB0b3RhbENvdW50IDogKHRoaXMuZ3JpZE9wdGlvbnM/LnBhZ2luYXRpb24/LnRvdGFsSXRlbXMpO1xyXG4gICAgICAgIGlmICh0b3RhbFJlY29yZHMgIT09IHVuZGVmaW5lZCAmJiB0b3RhbFJlY29yZHMgIT09IHRoaXMudG90YWxJdGVtcykge1xyXG4gICAgICAgICAgdGhpcy50b3RhbEl0ZW1zID0gK3RvdGFsUmVjb3JkcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGluaXRpYWxpemUgdGhlIFBhZ2luYXRpb24gU2VydmljZSB3aXRoIG5ldyBwYWdpbmF0aW9uIG9wdGlvbnMgKHdoaWNoIG1pZ2h0IGhhdmUgcHJlc2V0cylcclxuICAgICAgICBpZiAoIXRoaXMuX2lzUGFnaW5hdGlvbkluaXRpYWxpemVkKSB7XHJcbiAgICAgICAgICB0aGlzLmluaXRpYWxpemVQYWdpbmF0aW9uU2VydmljZShwYWdpbmF0aW9uT3B0aW9ucyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgcGFnaW5hdGlvbiBzZXJ2aWNlIHdpdGggdGhlIG5ldyB0b3RhbFxyXG4gICAgICAgICAgdGhpcy5wYWdpbmF0aW9uU2VydmljZS51cGRhdGVUb3RhbEl0ZW1zKHRoaXMudG90YWxJdGVtcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyByZXNpemUgdGhlIGdyaWQgaW5zaWRlIGEgc2xpZ2h0IHRpbWVvdXQsIGluIGNhc2Ugb3RoZXIgRE9NIGVsZW1lbnQgY2hhbmdlZCBwcmlvciB0byB0aGUgcmVzaXplIChsaWtlIGEgZmlsdGVyL3BhZ2luYXRpb24gY2hhbmdlZClcclxuICAgICAgaWYgKHRoaXMuc2xpY2tHcmlkICYmIHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQXV0b1Jlc2l6ZSkge1xyXG4gICAgICAgIGNvbnN0IGRlbGF5ID0gdGhpcy5ncmlkT3B0aW9ucy5hdXRvUmVzaXplICYmIHRoaXMuZ3JpZE9wdGlvbnMuYXV0b1Jlc2l6ZS5kZWxheTtcclxuICAgICAgICB0aGlzLnJlc2l6ZXJTZXJ2aWNlLnJlc2l6ZUdyaWQoZGVsYXkgfHwgMTApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDaGVjayBpZiB0aGVyZSdzIGFueSBQYWdpbmF0aW9uIFByZXNldHMgZGVmaW5lZCBpbiB0aGUgR3JpZCBPcHRpb25zLFxyXG4gICAqIGlmIHRoZXJlIGFyZSB0aGVuIGxvYWQgdGhlbSBpbiB0aGUgcGFnaW5hdGlvbk9wdGlvbnMgb2JqZWN0XHJcbiAgICovXHJcbiAgc2V0UGFnaW5hdGlvbk9wdGlvbnNXaGVuUHJlc2V0RGVmaW5lZChncmlkT3B0aW9uczogR3JpZE9wdGlvbiwgcGFnaW5hdGlvbk9wdGlvbnM6IFBhZ2luYXRpb24pOiBQYWdpbmF0aW9uIHtcclxuICAgIGlmIChncmlkT3B0aW9ucy5wcmVzZXRzPy5wYWdpbmF0aW9uICYmIHBhZ2luYXRpb25PcHRpb25zICYmICF0aGlzLl9pc1BhZ2luYXRpb25Jbml0aWFsaXplZCkge1xyXG4gICAgICBwYWdpbmF0aW9uT3B0aW9ucy5wYWdlU2l6ZSA9IGdyaWRPcHRpb25zLnByZXNldHMucGFnaW5hdGlvbi5wYWdlU2l6ZTtcclxuICAgICAgcGFnaW5hdGlvbk9wdGlvbnMucGFnZU51bWJlciA9IGdyaWRPcHRpb25zLnByZXNldHMucGFnaW5hdGlvbi5wYWdlTnVtYmVyO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHBhZ2luYXRpb25PcHRpb25zO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRHluYW1pY2FsbHkgY2hhbmdlIG9yIHVwZGF0ZSB0aGUgY29sdW1uIGRlZmluaXRpb25zIGxpc3QuXHJcbiAgICogV2Ugd2lsbCByZS1yZW5kZXIgdGhlIGdyaWQgc28gdGhhdCB0aGUgbmV3IGhlYWRlciBhbmQgZGF0YSBzaG93cyB1cCBjb3JyZWN0bHkuXHJcbiAgICogSWYgdXNpbmcgaTE4biwgd2UgYWxzbyBuZWVkIHRvIHRyaWdnZXIgYSByZS10cmFuc2xhdGUgb2YgdGhlIGNvbHVtbiBoZWFkZXJzXHJcbiAgICovXHJcbiAgdXBkYXRlQ29sdW1uRGVmaW5pdGlvbnNMaXN0KG5ld0NvbHVtbkRlZmluaXRpb25zOiBDb2x1bW5bXSkge1xyXG4gICAgLy8gbWFwL3N3YXAgdGhlIGludGVybmFsIGxpYnJhcnkgRWRpdG9yIHRvIHRoZSBTbGlja0dyaWQgRWRpdG9yIGZhY3RvcnlcclxuICAgIG5ld0NvbHVtbkRlZmluaXRpb25zID0gdGhpcy5zd2FwSW50ZXJuYWxFZGl0b3JUb1NsaWNrR3JpZEZhY3RvcnlFZGl0b3IobmV3Q29sdW1uRGVmaW5pdGlvbnMpO1xyXG5cclxuICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLmVuYWJsZVRyYW5zbGF0ZSkge1xyXG4gICAgICB0aGlzLmV4dGVuc2lvblNlcnZpY2UudHJhbnNsYXRlQ29sdW1uSGVhZGVycyhmYWxzZSwgbmV3Q29sdW1uRGVmaW5pdGlvbnMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5leHRlbnNpb25TZXJ2aWNlLnJlbmRlckNvbHVtbkhlYWRlcnMobmV3Q29sdW1uRGVmaW5pdGlvbnMsIHRydWUpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmdyaWRPcHRpb25zPy5lbmFibGVBdXRvU2l6ZUNvbHVtbnMpIHtcclxuICAgICAgdGhpcy5zbGlja0dyaWQuYXV0b3NpemVDb2x1bW5zKCk7XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMuZ3JpZE9wdGlvbnM/LmVuYWJsZUF1dG9SZXNpemVDb2x1bW5zQnlDZWxsQ29udGVudCAmJiB0aGlzLnJlc2l6ZXJTZXJ2aWNlPy5yZXNpemVDb2x1bW5zQnlDZWxsQ29udGVudCkge1xyXG4gICAgICB0aGlzLnJlc2l6ZXJTZXJ2aWNlLnJlc2l6ZUNvbHVtbnNCeUNlbGxDb250ZW50KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaG93IHRoZSBmaWx0ZXIgcm93IGRpc3BsYXllZCBvbiBmaXJzdCByb3csIHdlIGNhbiBvcHRpb25hbGx5IHBhc3MgZmFsc2UgdG8gaGlkZSBpdC5cclxuICAgKiBAcGFyYW0gc2hvd2luZ1xyXG4gICAqL1xyXG4gIHNob3dIZWFkZXJSb3coc2hvd2luZyA9IHRydWUpIHtcclxuICAgIHRoaXMuc2xpY2tHcmlkLnNldEhlYWRlclJvd1Zpc2liaWxpdHkoc2hvd2luZywgZmFsc2UpO1xyXG4gICAgaWYgKHNob3dpbmcgPT09IHRydWUgJiYgdGhpcy5faXNHcmlkSW5pdGlhbGl6ZWQpIHtcclxuICAgICAgdGhpcy5zbGlja0dyaWQuc2V0Q29sdW1ucyh0aGlzLmNvbHVtbkRlZmluaXRpb25zKTtcclxuICAgIH1cclxuICAgIHJldHVybiBzaG93aW5nO1xyXG4gIH1cclxuXHJcbiAgLy9cclxuICAvLyBwcml2YXRlIGZ1bmN0aW9uc1xyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICAvKipcclxuICAgKiBMb29wIHRocm91Z2ggYWxsIGNvbHVtbiBkZWZpbml0aW9ucyBhbmQgY29weSB0aGUgb3JpZ2luYWwgb3B0aW9uYWwgYHdpZHRoYCBwcm9wZXJ0aWVzIG9wdGlvbmFsbHkgcHJvdmlkZWQgYnkgdGhlIHVzZXIuXHJcbiAgICogV2Ugd2lsbCB1c2UgdGhpcyB3aGVuIGRvaW5nIGEgcmVzaXplIGJ5IGNlbGwgY29udGVudCwgaWYgdXNlciBwcm92aWRlZCBhIGB3aWR0aGAgaXQgd29uJ3Qgb3ZlcnJpZGUgaXQuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjb3B5Q29sdW1uV2lkdGhzUmVmZXJlbmNlKGNvbHVtbkRlZmluaXRpb25zOiBDb2x1bW5bXSkge1xyXG4gICAgY29sdW1uRGVmaW5pdGlvbnMuZm9yRWFjaChjb2wgPT4gY29sLm9yaWdpbmFsV2lkdGggPSBjb2wud2lkdGgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkaXNwbGF5RW1wdHlEYXRhV2FybmluZyhzaG93V2FybmluZyA9IHRydWUpIHtcclxuICAgIHRoaXMuc2xpY2tFbXB0eVdhcm5pbmc/LnNob3dFbXB0eURhdGFNZXNzYWdlKHNob3dXYXJuaW5nKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYmluZERpZmZlcmVudEhvb2tzKGdyaWQ6IFNsaWNrR3JpZCwgZ3JpZE9wdGlvbnM6IEdyaWRPcHRpb24sIGRhdGFWaWV3OiBTbGlja0RhdGFWaWV3KSB7XHJcbiAgICAvLyBvbiBsb2NhbGUgY2hhbmdlLCB3ZSBoYXZlIHRvIG1hbnVhbGx5IHRyYW5zbGF0ZSB0aGUgSGVhZGVycywgR3JpZE1lbnVcclxuICAgIGlmICh0aGlzLnRyYW5zbGF0ZT8ub25MYW5nQ2hhbmdlKSB7XHJcbiAgICAgIC8vIHRyYW5zbGF0ZSBzb21lIG9mIHRoZW0gb24gZmlyc3QgbG9hZCwgdGhlbiBvbiBlYWNoIGxhbmd1YWdlIGNoYW5nZVxyXG4gICAgICBpZiAoZ3JpZE9wdGlvbnMuZW5hYmxlVHJhbnNsYXRlKSB7XHJcbiAgICAgICAgdGhpcy50cmFuc2xhdGVDb2x1bW5IZWFkZXJUaXRsZUtleXMoKTtcclxuICAgICAgICB0aGlzLnRyYW5zbGF0ZUNvbHVtbkdyb3VwS2V5cygpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcclxuICAgICAgICB0aGlzLnRyYW5zbGF0ZS5vbkxhbmdDaGFuZ2Uuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgICAgIC8vIHB1Ymxpc2ggZXZlbnQgb2YgdGhlIHNhbWUgbmFtZSB0aGF0IFNsaWNrZ3JpZC1Vbml2ZXJzYWwgdXNlcyBvbiBhIGxhbmd1YWdlIGNoYW5nZSBldmVudFxyXG4gICAgICAgICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnB1Ymxpc2goJ29uTGFuZ3VhZ2VDaGFuZ2UnKTtcclxuXHJcbiAgICAgICAgICBpZiAoZ3JpZE9wdGlvbnMuZW5hYmxlVHJhbnNsYXRlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZXh0ZW5zaW9uU2VydmljZS50cmFuc2xhdGVDZWxsTWVudSgpO1xyXG4gICAgICAgICAgICB0aGlzLmV4dGVuc2lvblNlcnZpY2UudHJhbnNsYXRlQ29sdW1uSGVhZGVycygpO1xyXG4gICAgICAgICAgICB0aGlzLmV4dGVuc2lvblNlcnZpY2UudHJhbnNsYXRlQ29sdW1uUGlja2VyKCk7XHJcbiAgICAgICAgICAgIHRoaXMuZXh0ZW5zaW9uU2VydmljZS50cmFuc2xhdGVDb250ZXh0TWVudSgpO1xyXG4gICAgICAgICAgICB0aGlzLmV4dGVuc2lvblNlcnZpY2UudHJhbnNsYXRlR3JpZE1lbnUoKTtcclxuICAgICAgICAgICAgdGhpcy5leHRlbnNpb25TZXJ2aWNlLnRyYW5zbGF0ZUhlYWRlck1lbnUoKTtcclxuICAgICAgICAgICAgdGhpcy50cmFuc2xhdGVDb2x1bW5IZWFkZXJUaXRsZUtleXMoKTtcclxuICAgICAgICAgICAgdGhpcy50cmFuc2xhdGVDb2x1bW5Hcm91cEtleXMoKTtcclxuICAgICAgICAgICAgaWYgKGdyaWRPcHRpb25zLmNyZWF0ZVByZUhlYWRlclBhbmVsICYmICFncmlkT3B0aW9ucy5lbmFibGVEcmFnZ2FibGVHcm91cGluZykge1xyXG4gICAgICAgICAgICAgIHRoaXMuZ3JvdXBpbmdTZXJ2aWNlLnRyYW5zbGF0ZUdyb3VwaW5nQW5kQ29sU3BhbigpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBpZiB1c2VyIHNldCBhbiBvbkluaXQgQmFja2VuZCwgd2UnbGwgcnVuIGl0IHJpZ2h0IGF3YXkgKGFuZCBpZiBzbywgd2UgYWxzbyBuZWVkIHRvIHJ1biBwcmVQcm9jZXNzLCBpbnRlcm5hbFBvc3RQcm9jZXNzICYgcG9zdFByb2Nlc3MpXHJcbiAgICBpZiAoZ3JpZE9wdGlvbnMuYmFja2VuZFNlcnZpY2VBcGkpIHtcclxuICAgICAgY29uc3QgYmFja2VuZEFwaSA9IGdyaWRPcHRpb25zLmJhY2tlbmRTZXJ2aWNlQXBpO1xyXG5cclxuICAgICAgaWYgKGJhY2tlbmRBcGk/LnNlcnZpY2U/LmluaXQpIHtcclxuICAgICAgICBiYWNrZW5kQXBpLnNlcnZpY2UuaW5pdChiYWNrZW5kQXBpLm9wdGlvbnMsIGdyaWRPcHRpb25zLnBhZ2luYXRpb24sIHRoaXMuc2xpY2tHcmlkLCB0aGlzLnNoYXJlZFNlcnZpY2UpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGRhdGFWaWV3ICYmIGdyaWQpIHtcclxuICAgICAgY29uc3Qgc2xpY2tncmlkRXZlbnRQcmVmaXggPSB0aGlzLmdyaWRPcHRpb25zPy5kZWZhdWx0U2xpY2tncmlkRXZlbnRQcmVmaXggPz8gJyc7XHJcblxyXG4gICAgICAvLyBleHBvc2UgYWxsIFNsaWNrIEdyaWQgRXZlbnRzIHRocm91Z2ggZGlzcGF0Y2hcclxuICAgICAgZm9yIChjb25zdCBwcm9wIGluIGdyaWQpIHtcclxuICAgICAgICBpZiAoZ3JpZC5oYXNPd25Qcm9wZXJ0eShwcm9wKSAmJiBwcm9wLnN0YXJ0c1dpdGgoJ29uJykpIHtcclxuICAgICAgICAgIGNvbnN0IGdyaWRFdmVudEhhbmRsZXIgPSAoZ3JpZCBhcyBhbnkpW3Byb3BdO1xyXG4gICAgICAgICAgY29uc3QgZ3JpZEV2ZW50TmFtZSA9IHRoaXMuX2V2ZW50UHViU3ViU2VydmljZS5nZXRFdmVudE5hbWVCeU5hbWluZ0NvbnZlbnRpb24ocHJvcCwgc2xpY2tncmlkRXZlbnRQcmVmaXgpO1xyXG4gICAgICAgICAgKHRoaXMuX2V2ZW50SGFuZGxlciBhcyBTbGlja0V2ZW50SGFuZGxlcjxHZXRTbGlja0V2ZW50VHlwZTx0eXBlb2YgZ3JpZEV2ZW50SGFuZGxlcj4+KS5zdWJzY3JpYmUoZ3JpZEV2ZW50SGFuZGxlciwgKGV2ZW50LCBhcmdzKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UuZGlzcGF0Y2hDdXN0b21FdmVudChncmlkRXZlbnROYW1lLCB7IGV2ZW50RGF0YTogZXZlbnQsIGFyZ3MgfSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGV4cG9zZSBhbGwgU2xpY2sgRGF0YVZpZXcgRXZlbnRzIHRocm91Z2ggZGlzcGF0Y2hcclxuICAgICAgZm9yIChjb25zdCBwcm9wIGluIGRhdGFWaWV3KSB7XHJcbiAgICAgICAgaWYgKGRhdGFWaWV3Lmhhc093blByb3BlcnR5KHByb3ApICYmIHByb3Auc3RhcnRzV2l0aCgnb24nKSkge1xyXG4gICAgICAgICAgY29uc3QgZGF0YVZpZXdFdmVudEhhbmRsZXIgPSAoZGF0YVZpZXcgYXMgYW55KVtwcm9wXTtcclxuICAgICAgICAgICh0aGlzLl9ldmVudEhhbmRsZXIgYXMgU2xpY2tFdmVudEhhbmRsZXI8R2V0U2xpY2tFdmVudFR5cGU8dHlwZW9mIGRhdGFWaWV3RXZlbnRIYW5kbGVyPj4pLnN1YnNjcmliZShkYXRhVmlld0V2ZW50SGFuZGxlciwgKGV2ZW50LCBhcmdzKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGRhdGFWaWV3RXZlbnROYW1lID0gdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLmdldEV2ZW50TmFtZUJ5TmFtaW5nQ29udmVudGlvbihwcm9wLCBzbGlja2dyaWRFdmVudFByZWZpeCk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UuZGlzcGF0Y2hDdXN0b21FdmVudChkYXRhVmlld0V2ZW50TmFtZSwgeyBldmVudERhdGE6IGV2ZW50LCBhcmdzIH0pO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBvbiBjZWxsIGNsaWNrLCBtYWlubHkgdXNlZCB3aXRoIHRoZSBjb2x1bW5EZWYuYWN0aW9uIGNhbGxiYWNrXHJcbiAgICAgIHRoaXMuZ3JpZEV2ZW50U2VydmljZS5iaW5kT25DZWxsQ2hhbmdlKGdyaWQpO1xyXG4gICAgICB0aGlzLmdyaWRFdmVudFNlcnZpY2UuYmluZE9uQ2xpY2soZ3JpZCk7XHJcblxyXG4gICAgICBpZiAoZGF0YVZpZXcgJiYgZ3JpZCkge1xyXG4gICAgICAgIC8vIGJpbmQgZXh0ZXJuYWwgc29ydGluZyAoYmFja2VuZCkgd2hlbiBhdmFpbGFibGUgb3IgZGVmYXVsdCBvblNvcnQgKGRhdGFWaWV3KVxyXG4gICAgICAgIGlmIChncmlkT3B0aW9ucy5lbmFibGVTb3J0aW5nKSB7XHJcbiAgICAgICAgICAvLyBiaW5kIGV4dGVybmFsIHNvcnRpbmcgKGJhY2tlbmQpIHVubGVzcyBzcGVjaWZpZWQgdG8gdXNlIHRoZSBsb2NhbCBvbmVcclxuICAgICAgICAgIGlmIChncmlkT3B0aW9ucy5iYWNrZW5kU2VydmljZUFwaSAmJiAhZ3JpZE9wdGlvbnMuYmFja2VuZFNlcnZpY2VBcGkudXNlTG9jYWxTb3J0aW5nKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc29ydFNlcnZpY2UuYmluZEJhY2tlbmRPblNvcnQoZ3JpZCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLnNvcnRTZXJ2aWNlLmJpbmRMb2NhbE9uU29ydChncmlkKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGJpbmQgZXh0ZXJuYWwgZmlsdGVyIChiYWNrZW5kKSB3aGVuIGF2YWlsYWJsZSBvciBkZWZhdWx0IG9uRmlsdGVyIChkYXRhVmlldylcclxuICAgICAgICBpZiAoZ3JpZE9wdGlvbnMuZW5hYmxlRmlsdGVyaW5nKSB7XHJcbiAgICAgICAgICB0aGlzLmZpbHRlclNlcnZpY2UuaW5pdChncmlkKTtcclxuXHJcbiAgICAgICAgICAvLyBiaW5kIGV4dGVybmFsIGZpbHRlciAoYmFja2VuZCkgdW5sZXNzIHNwZWNpZmllZCB0byB1c2UgdGhlIGxvY2FsIG9uZVxyXG4gICAgICAgICAgaWYgKGdyaWRPcHRpb25zLmJhY2tlbmRTZXJ2aWNlQXBpICYmICFncmlkT3B0aW9ucy5iYWNrZW5kU2VydmljZUFwaS51c2VMb2NhbEZpbHRlcmluZykge1xyXG4gICAgICAgICAgICB0aGlzLmZpbHRlclNlcnZpY2UuYmluZEJhY2tlbmRPbkZpbHRlcihncmlkKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuZmlsdGVyU2VydmljZS5iaW5kTG9jYWxPbkZpbHRlcihncmlkKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGxvYWQgYW55IHByZXNldHMgaWYgYW55IChhZnRlciBkYXRhc2V0IGlzIGluaXRpYWxpemVkKVxyXG4gICAgICAgIHRoaXMubG9hZENvbHVtblByZXNldHNXaGVuRGF0YXNldEluaXRpYWxpemVkKCk7XHJcbiAgICAgICAgdGhpcy5sb2FkRmlsdGVyUHJlc2V0c1doZW5EYXRhc2V0SW5pdGlhbGl6ZWQoKTtcclxuXHJcbiAgICAgICAgLy8gV2hlbiBkYXRhIGNoYW5nZXMgaW4gdGhlIERhdGFWaWV3LCB3ZSBuZWVkIHRvIHJlZnJlc2ggdGhlIG1ldHJpY3MgYW5kL29yIGRpc3BsYXkgYSB3YXJuaW5nIGlmIHRoZSBkYXRhc2V0IGlzIGVtcHR5XHJcbiAgICAgICAgY29uc3Qgb25Sb3dDb3VudENoYW5nZWRIYW5kbGVyID0gZGF0YVZpZXcub25Sb3dDb3VudENoYW5nZWQ7XHJcbiAgICAgICAgKHRoaXMuX2V2ZW50SGFuZGxlciBhcyBTbGlja0V2ZW50SGFuZGxlcjxHZXRTbGlja0V2ZW50VHlwZTx0eXBlb2Ygb25Sb3dDb3VudENoYW5nZWRIYW5kbGVyPj4pLnN1YnNjcmliZShvblJvd0NvdW50Q2hhbmdlZEhhbmRsZXIsIChfZSwgYXJncykgPT4ge1xyXG4gICAgICAgICAgZ3JpZC5pbnZhbGlkYXRlKCk7XHJcbiAgICAgICAgICB0aGlzLmhhbmRsZU9uSXRlbUNvdW50Q2hhbmdlZCh0aGlzLmRhdGFWaWV3LmdldEZpbHRlcmVkSXRlbUNvdW50KCkgfHwgMCwgZGF0YVZpZXcuZ2V0SXRlbUNvdW50KCkpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnN0IG9uU2V0SXRlbXNDYWxsZWRIYW5kbGVyID0gZGF0YVZpZXcub25TZXRJdGVtc0NhbGxlZDtcclxuICAgICAgICAodGhpcy5fZXZlbnRIYW5kbGVyIGFzIFNsaWNrRXZlbnRIYW5kbGVyPEdldFNsaWNrRXZlbnRUeXBlPHR5cGVvZiBvblNldEl0ZW1zQ2FsbGVkSGFuZGxlcj4+KS5zdWJzY3JpYmUob25TZXRJdGVtc0NhbGxlZEhhbmRsZXIsIChfZSwgYXJncykgPT4ge1xyXG4gICAgICAgICAgZ3JpZC5pbnZhbGlkYXRlKCk7XHJcbiAgICAgICAgICB0aGlzLmhhbmRsZU9uSXRlbUNvdW50Q2hhbmdlZCh0aGlzLmRhdGFWaWV3LmdldEZpbHRlcmVkSXRlbUNvdW50KCksIGFyZ3MuaXRlbUNvdW50KTtcclxuXHJcbiAgICAgICAgICAvLyB3aGVuIHVzZXIgaGFzIHJlc2l6ZSBieSBjb250ZW50IGVuYWJsZWQsIHdlJ2xsIGZvcmNlIGEgZnVsbCB3aWR0aCBjYWxjdWxhdGlvbiBzaW5jZSB3ZSBjaGFuZ2Ugb3VyIGVudGlyZSBkYXRhc2V0XHJcbiAgICAgICAgICBpZiAoYXJncy5pdGVtQ291bnQgPiAwICYmICh0aGlzLmdyaWRPcHRpb25zLmF1dG9zaXplQ29sdW1uc0J5Q2VsbENvbnRlbnRPbkZpcnN0TG9hZCB8fCB0aGlzLmdyaWRPcHRpb25zLmVuYWJsZUF1dG9SZXNpemVDb2x1bW5zQnlDZWxsQ29udGVudCkpIHtcclxuICAgICAgICAgICAgdGhpcy5yZXNpemVyU2VydmljZS5yZXNpemVDb2x1bW5zQnlDZWxsQ29udGVudCghdGhpcy5ncmlkT3B0aW9ucz8ucmVzaXplQnlDb250ZW50T25seU9uRmlyc3RMb2FkKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgY29uc3Qgb25Sb3dzQ2hhbmdlZEhhbmRsZXIgPSBkYXRhVmlldy5vblJvd3NDaGFuZ2VkO1xyXG4gICAgICAgICh0aGlzLl9ldmVudEhhbmRsZXIgYXMgU2xpY2tFdmVudEhhbmRsZXI8R2V0U2xpY2tFdmVudFR5cGU8dHlwZW9mIG9uUm93c0NoYW5nZWRIYW5kbGVyPj4pLnN1YnNjcmliZShvblJvd3NDaGFuZ2VkSGFuZGxlciwgKF9lLCBhcmdzKSA9PiB7XHJcbiAgICAgICAgICAvLyBmaWx0ZXJpbmcgZGF0YSB3aXRoIGxvY2FsIGRhdGFzZXQgd2lsbCBub3QgYWx3YXlzIHNob3cgY29ycmVjdGx5IHVubGVzcyB3ZSBjYWxsIHRoaXMgdXBkYXRlUm93L3JlbmRlclxyXG4gICAgICAgICAgLy8gYWxzbyBkb24ndCB1c2UgXCJpbnZhbGlkYXRlUm93c1wiIHNpbmNlIGl0IGRlc3Ryb3lzIHRoZSBlbnRpcmUgcm93IGFuZCBhcyBiYWQgdXNlciBleHBlcmllbmNlIHdoZW4gdXBkYXRpbmcgYSByb3dcclxuICAgICAgICAgIC8vIHNlZSBjb21taXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9naGlzY29kaW5nL2F1cmVsaWEtc2xpY2tncmlkL2NvbW1pdC84YzUwM2E0ZDQ1ZmJhMTFjYmQ4ZDhjYzQ2N2ZhZThkMTc3Y2M0ZjYwXHJcbiAgICAgICAgICBpZiAoZ3JpZE9wdGlvbnMgJiYgZ3JpZE9wdGlvbnMuZW5hYmxlRmlsdGVyaW5nICYmICFncmlkT3B0aW9ucy5lbmFibGVSb3dEZXRhaWxWaWV3KSB7XHJcbiAgICAgICAgICAgIGlmIChhcmdzPy5yb3dzICYmIEFycmF5LmlzQXJyYXkoYXJncy5yb3dzKSkge1xyXG4gICAgICAgICAgICAgIGFyZ3Mucm93cy5mb3JFYWNoKChyb3c6IG51bWJlcikgPT4gZ3JpZC51cGRhdGVSb3cocm93KSk7XHJcbiAgICAgICAgICAgICAgZ3JpZC5yZW5kZXIoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZGlkIHRoZSB1c2VyIGFkZCBhIGNvbHNwYW4gY2FsbGJhY2s/IElmIHNvLCBob29rIGl0IGludG8gdGhlIERhdGFWaWV3IGdldEl0ZW1NZXRhZGF0YVxyXG4gICAgaWYgKGdyaWRPcHRpb25zICYmIGdyaWRPcHRpb25zLmNvbHNwYW5DYWxsYmFjayAmJiBkYXRhVmlldyAmJiBkYXRhVmlldy5nZXRJdGVtICYmIGRhdGFWaWV3LmdldEl0ZW1NZXRhZGF0YSkge1xyXG4gICAgICBkYXRhVmlldy5nZXRJdGVtTWV0YWRhdGEgPSAocm93TnVtYmVyOiBudW1iZXIpID0+IHtcclxuICAgICAgICBsZXQgY2FsbGJhY2tSZXN1bHQgPSBudWxsO1xyXG4gICAgICAgIGlmIChncmlkT3B0aW9ucy5jb2xzcGFuQ2FsbGJhY2sgJiYgZ3JpZE9wdGlvbnMuY29sc3BhbkNhbGxiYWNrKSB7XHJcbiAgICAgICAgICBjYWxsYmFja1Jlc3VsdCA9IGdyaWRPcHRpb25zLmNvbHNwYW5DYWxsYmFjayhkYXRhVmlldy5nZXRJdGVtKHJvd051bWJlcikpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gY2FsbGJhY2tSZXN1bHQ7XHJcbiAgICAgIH07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJpbmRCYWNrZW5kQ2FsbGJhY2tGdW5jdGlvbnMoZ3JpZE9wdGlvbnM6IEdyaWRPcHRpb24pIHtcclxuICAgIGNvbnN0IGJhY2tlbmRBcGkgPSBncmlkT3B0aW9ucy5iYWNrZW5kU2VydmljZUFwaTtcclxuICAgIGNvbnN0IGJhY2tlbmRBcGlTZXJ2aWNlID0gYmFja2VuZEFwaSAmJiBiYWNrZW5kQXBpLnNlcnZpY2U7XHJcbiAgICBjb25zdCBzZXJ2aWNlT3B0aW9uczogQmFja2VuZFNlcnZpY2VPcHRpb24gPSBiYWNrZW5kQXBpU2VydmljZT8ub3B0aW9ucyA/PyB7fTtcclxuICAgIGNvbnN0IGlzRXhlY3V0ZUNvbW1hbmRPbkluaXQgPSAoIXNlcnZpY2VPcHRpb25zKSA/IGZhbHNlIDogKChzZXJ2aWNlT3B0aW9ucyAmJiBzZXJ2aWNlT3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnZXhlY3V0ZVByb2Nlc3NDb21tYW5kT25Jbml0JykpID8gc2VydmljZU9wdGlvbnNbJ2V4ZWN1dGVQcm9jZXNzQ29tbWFuZE9uSW5pdCddIDogdHJ1ZSk7XHJcblxyXG4gICAgaWYgKGJhY2tlbmRBcGlTZXJ2aWNlKSB7XHJcbiAgICAgIC8vIHVwZGF0ZSBiYWNrZW5kIGZpbHRlcnMgKGlmIG5lZWQgYmUpIEJFRk9SRSB0aGUgcXVlcnkgcnVucyAodmlhIHRoZSBvbkluaXQgY29tbWFuZCBhIGZldyBsaW5lcyBiZWxvdylcclxuICAgICAgLy8gaWYgdXNlciBlbnRlcmVkIHNvbWUgYW55IFwicHJlc2V0c1wiLCB3ZSBuZWVkIHRvIHJlZmxlY3QgdGhlbSBhbGwgaW4gdGhlIGdyaWRcclxuICAgICAgaWYgKGdyaWRPcHRpb25zICYmIGdyaWRPcHRpb25zLnByZXNldHMpIHtcclxuICAgICAgICAvLyBGaWx0ZXJzIFwicHJlc2V0c1wiXHJcbiAgICAgICAgaWYgKGJhY2tlbmRBcGlTZXJ2aWNlLnVwZGF0ZUZpbHRlcnMgJiYgQXJyYXkuaXNBcnJheShncmlkT3B0aW9ucy5wcmVzZXRzLmZpbHRlcnMpICYmIGdyaWRPcHRpb25zLnByZXNldHMuZmlsdGVycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICBiYWNrZW5kQXBpU2VydmljZS51cGRhdGVGaWx0ZXJzKGdyaWRPcHRpb25zLnByZXNldHMuZmlsdGVycywgdHJ1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIFNvcnRlcnMgXCJwcmVzZXRzXCJcclxuICAgICAgICBpZiAoYmFja2VuZEFwaVNlcnZpY2UudXBkYXRlU29ydGVycyAmJiBBcnJheS5pc0FycmF5KGdyaWRPcHRpb25zLnByZXNldHMuc29ydGVycykgJiYgZ3JpZE9wdGlvbnMucHJlc2V0cy5zb3J0ZXJzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIC8vIHdoZW4gdXNpbmcgbXVsdGktY29sdW1uIHNvcnQsIHdlIGNhbiBoYXZlIG11bHRpcGxlIGJ1dCBvbiBzaW5nbGUgc29ydCB0aGVuIG9ubHkgZ3JhYiB0aGUgZmlyc3Qgc29ydCBwcm92aWRlZFxyXG4gICAgICAgICAgY29uc3Qgc29ydENvbHVtbnMgPSB0aGlzLmdyaWRPcHRpb25zLm11bHRpQ29sdW1uU29ydCA/IGdyaWRPcHRpb25zLnByZXNldHMuc29ydGVycyA6IGdyaWRPcHRpb25zLnByZXNldHMuc29ydGVycy5zbGljZSgwLCAxKTtcclxuICAgICAgICAgIGJhY2tlbmRBcGlTZXJ2aWNlLnVwZGF0ZVNvcnRlcnModW5kZWZpbmVkLCBzb3J0Q29sdW1ucyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIFBhZ2luYXRpb24gXCJwcmVzZXRzXCJcclxuICAgICAgICBpZiAoYmFja2VuZEFwaVNlcnZpY2UudXBkYXRlUGFnaW5hdGlvbiAmJiBncmlkT3B0aW9ucy5wcmVzZXRzLnBhZ2luYXRpb24pIHtcclxuICAgICAgICAgIGNvbnN0IHsgcGFnZU51bWJlciwgcGFnZVNpemUgfSA9IGdyaWRPcHRpb25zLnByZXNldHMucGFnaW5hdGlvbjtcclxuICAgICAgICAgIGJhY2tlbmRBcGlTZXJ2aWNlLnVwZGF0ZVBhZ2luYXRpb24ocGFnZU51bWJlciwgcGFnZVNpemUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCBjb2x1bW5GaWx0ZXJzID0gdGhpcy5maWx0ZXJTZXJ2aWNlLmdldENvbHVtbkZpbHRlcnMoKTtcclxuICAgICAgICBpZiAoY29sdW1uRmlsdGVycyAmJiBiYWNrZW5kQXBpU2VydmljZS51cGRhdGVGaWx0ZXJzKSB7XHJcbiAgICAgICAgICBiYWNrZW5kQXBpU2VydmljZS51cGRhdGVGaWx0ZXJzKGNvbHVtbkZpbHRlcnMsIGZhbHNlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGV4ZWN1dGUgb25Jbml0IGNvbW1hbmQgd2hlbiBuZWNlc3NhcnlcclxuICAgICAgaWYgKGJhY2tlbmRBcGkgJiYgYmFja2VuZEFwaVNlcnZpY2UgJiYgKGJhY2tlbmRBcGkub25Jbml0IHx8IGlzRXhlY3V0ZUNvbW1hbmRPbkluaXQpKSB7XHJcbiAgICAgICAgY29uc3QgcXVlcnkgPSAodHlwZW9mIGJhY2tlbmRBcGlTZXJ2aWNlLmJ1aWxkUXVlcnkgPT09ICdmdW5jdGlvbicpID8gYmFja2VuZEFwaVNlcnZpY2UuYnVpbGRRdWVyeSgpIDogJyc7XHJcbiAgICAgICAgY29uc3QgcHJvY2VzcyA9IChpc0V4ZWN1dGVDb21tYW5kT25Jbml0KSA/IChiYWNrZW5kQXBpLnByb2Nlc3MgJiYgYmFja2VuZEFwaS5wcm9jZXNzKHF1ZXJ5KSB8fCBudWxsKSA6IChiYWNrZW5kQXBpLm9uSW5pdCAmJiBiYWNrZW5kQXBpLm9uSW5pdChxdWVyeSkgfHwgbnVsbCk7XHJcblxyXG4gICAgICAgIC8vIHdyYXAgdGhpcyBpbnNpZGUgYSBzZXRUaW1lb3V0IHRvIGF2b2lkIHRpbWluZyBpc3N1ZSBzaW5jZSB0aGUgZ3JpZE9wdGlvbnMgbmVlZHMgdG8gYmUgcmVhZHkgYmVmb3JlIHJ1bm5pbmcgdGhpcyBvbkluaXRcclxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgIGNvbnN0IGJhY2tlbmRVdGlsaXR5U2VydmljZSA9IHRoaXMuYmFja2VuZFV0aWxpdHlTZXJ2aWNlIGFzIEJhY2tlbmRVdGlsaXR5U2VydmljZTtcclxuXHJcbiAgICAgICAgICAvLyBrZWVwIHN0YXJ0IHRpbWUgJiBlbmQgdGltZXN0YW1wcyAmIHJldHVybiBpdCBhZnRlciBwcm9jZXNzIGV4ZWN1dGlvblxyXG4gICAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gbmV3IERhdGUoKTtcclxuXHJcbiAgICAgICAgICAvLyBydW4gYW55IHByZS1wcm9jZXNzLCBpZiBkZWZpbmVkLCBmb3IgZXhhbXBsZSBhIHNwaW5uZXJcclxuICAgICAgICAgIGlmIChiYWNrZW5kQXBpLnByZVByb2Nlc3MpIHtcclxuICAgICAgICAgICAgYmFja2VuZEFwaS5wcmVQcm9jZXNzKCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gdGhlIHByb2Nlc3NlcyBjYW4gYmUgYSBQcm9taXNlIChsaWtlIEh0dHApXHJcbiAgICAgICAgICBjb25zdCB0b3RhbEl0ZW1zID0gdGhpcy5ncmlkT3B0aW9ucz8ucGFnaW5hdGlvbj8udG90YWxJdGVtcyA/PyAwO1xyXG4gICAgICAgICAgaWYgKHByb2Nlc3MgaW5zdGFuY2VvZiBQcm9taXNlKSB7XHJcbiAgICAgICAgICAgIHByb2Nlc3NcclxuICAgICAgICAgICAgICAudGhlbigocHJvY2Vzc1Jlc3VsdDogYW55KSA9PiBiYWNrZW5kVXRpbGl0eVNlcnZpY2UuZXhlY3V0ZUJhY2tlbmRQcm9jZXNzZXNDYWxsYmFjayhzdGFydFRpbWUsIHByb2Nlc3NSZXN1bHQsIGJhY2tlbmRBcGksIHRvdGFsSXRlbXMpKVxyXG4gICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IGJhY2tlbmRVdGlsaXR5U2VydmljZS5vbkJhY2tlbmRFcnJvcihlcnJvciwgYmFja2VuZEFwaSkpO1xyXG4gICAgICAgICAgfSBlbHNlIGlmIChwcm9jZXNzICYmIHRoaXMucnhqcz8uaXNPYnNlcnZhYmxlKHByb2Nlc3MpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxyXG4gICAgICAgICAgICAgIChwcm9jZXNzIGFzIE9ic2VydmFibGU8YW55Pikuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgICAgIG5leHQ6IChwcm9jZXNzUmVzdWx0OiBhbnkpID0+IGJhY2tlbmRVdGlsaXR5U2VydmljZS5leGVjdXRlQmFja2VuZFByb2Nlc3Nlc0NhbGxiYWNrKHN0YXJ0VGltZSwgcHJvY2Vzc1Jlc3VsdCwgYmFja2VuZEFwaSwgdG90YWxJdGVtcyksXHJcbiAgICAgICAgICAgICAgICBlcnJvcjogKGVycm9yOiBhbnkpID0+IGJhY2tlbmRVdGlsaXR5U2VydmljZS5vbkJhY2tlbmRFcnJvcihlcnJvciwgYmFja2VuZEFwaSlcclxuICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJpbmRSZXNpemVIb29rKGdyaWQ6IFNsaWNrR3JpZCwgb3B0aW9uczogR3JpZE9wdGlvbikge1xyXG4gICAgaWYgKChvcHRpb25zLmF1dG9GaXRDb2x1bW5zT25GaXJzdExvYWQgJiYgb3B0aW9ucy5hdXRvc2l6ZUNvbHVtbnNCeUNlbGxDb250ZW50T25GaXJzdExvYWQpIHx8IChvcHRpb25zLmVuYWJsZUF1dG9TaXplQ29sdW1ucyAmJiBvcHRpb25zLmVuYWJsZUF1dG9SZXNpemVDb2x1bW5zQnlDZWxsQ29udGVudCkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBbQW5ndWxhci1TbGlja2dyaWRdIFlvdSBjYW5ub3QgZW5hYmxlIGJvdGggYXV0b3NpemUvZml0IHZpZXdwb3J0ICYgcmVzaXplIGJ5IGNvbnRlbnQsIHlvdSBtdXN0IGNob29zZSB3aGljaCByZXNpemUgdGVjaG5pcXVlIHRvIHVzZS4gWW91IGNhbiBlbmFibGUgdGhlc2UgMiBvcHRpb25zIChcImF1dG9GaXRDb2x1bW5zT25GaXJzdExvYWRcIiBhbmQgXCJlbmFibGVBdXRvU2l6ZUNvbHVtbnNcIikgT1IgdGhlc2Ugb3RoZXIgMiBvcHRpb25zIChcImF1dG9zaXplQ29sdW1uc0J5Q2VsbENvbnRlbnRPbkZpcnN0TG9hZFwiIGFuZCBcImVuYWJsZUF1dG9SZXNpemVDb2x1bW5zQnlDZWxsQ29udGVudFwiKS5gKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBleHBhbmQvYXV0b2ZpdCBjb2x1bW5zIG9uIGZpcnN0IHBhZ2UgbG9hZFxyXG4gICAgaWYgKGdyaWQgJiYgb3B0aW9ucy5hdXRvRml0Q29sdW1uc09uRmlyc3RMb2FkICYmIG9wdGlvbnMuZW5hYmxlQXV0b1NpemVDb2x1bW5zKSB7XHJcbiAgICAgIGdyaWQuYXV0b3NpemVDb2x1bW5zKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gYXV0by1yZXNpemUgZ3JpZCBvbiBicm93c2VyIHJlc2l6ZVxyXG4gICAgaWYgKG9wdGlvbnMuZ3JpZEhlaWdodCB8fCBvcHRpb25zLmdyaWRXaWR0aCkge1xyXG4gICAgICB0aGlzLnJlc2l6ZXJTZXJ2aWNlLnJlc2l6ZUdyaWQoMCwgeyBoZWlnaHQ6IG9wdGlvbnMuZ3JpZEhlaWdodCwgd2lkdGg6IG9wdGlvbnMuZ3JpZFdpZHRoIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5yZXNpemVyU2VydmljZS5yZXNpemVHcmlkKCk7XHJcbiAgICB9XHJcbiAgICBpZiAob3B0aW9ucy5lbmFibGVBdXRvUmVzaXplKSB7XHJcbiAgICAgIGlmIChncmlkICYmIG9wdGlvbnMuYXV0b0ZpdENvbHVtbnNPbkZpcnN0TG9hZCAmJiBvcHRpb25zLmVuYWJsZUF1dG9TaXplQ29sdW1ucykge1xyXG4gICAgICAgIGdyaWQuYXV0b3NpemVDb2x1bW5zKCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXhlY3V0ZUFmdGVyRGF0YXZpZXdDcmVhdGVkKF9ncmlkOiBTbGlja0dyaWQsIGdyaWRPcHRpb25zOiBHcmlkT3B0aW9uKSB7XHJcbiAgICAvLyBpZiB1c2VyIGVudGVyZWQgc29tZSBTb3J0IFwicHJlc2V0c1wiLCB3ZSBuZWVkIHRvIHJlZmxlY3QgdGhlbSBhbGwgaW4gdGhlIERPTVxyXG4gICAgaWYgKGdyaWRPcHRpb25zLmVuYWJsZVNvcnRpbmcpIHtcclxuICAgICAgaWYgKGdyaWRPcHRpb25zLnByZXNldHMgJiYgQXJyYXkuaXNBcnJheShncmlkT3B0aW9ucy5wcmVzZXRzLnNvcnRlcnMpKSB7XHJcbiAgICAgICAgLy8gd2hlbiB1c2luZyBtdWx0aS1jb2x1bW4gc29ydCwgd2UgY2FuIGhhdmUgbXVsdGlwbGUgYnV0IG9uIHNpbmdsZSBzb3J0IHRoZW4gb25seSBncmFiIHRoZSBmaXJzdCBzb3J0IHByb3ZpZGVkXHJcbiAgICAgICAgY29uc3Qgc29ydENvbHVtbnMgPSB0aGlzLmdyaWRPcHRpb25zLm11bHRpQ29sdW1uU29ydCA/IGdyaWRPcHRpb25zLnByZXNldHMuc29ydGVycyA6IGdyaWRPcHRpb25zLnByZXNldHMuc29ydGVycy5zbGljZSgwLCAxKTtcclxuICAgICAgICB0aGlzLnNvcnRTZXJ2aWNlLmxvYWRHcmlkU29ydGVycyhzb3J0Q29sdW1ucyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBXaGVuIGRhdGEgY2hhbmdlcyBpbiB0aGUgRGF0YVZpZXcsIHdlJ2xsIHJlZnJlc2ggdGhlIG1ldHJpY3MgYW5kL29yIGRpc3BsYXkgYSB3YXJuaW5nIGlmIHRoZSBkYXRhc2V0IGlzIGVtcHR5ICovXHJcbiAgcHJpdmF0ZSBoYW5kbGVPbkl0ZW1Db3VudENoYW5nZWQoY3VycmVudFBhZ2VSb3dJdGVtQ291bnQ6IG51bWJlciwgdG90YWxJdGVtQ291bnQ6IG51bWJlcikge1xyXG4gICAgdGhpcy5fY3VycmVudERhdGFzZXRMZW5ndGggPSB0b3RhbEl0ZW1Db3VudDtcclxuICAgIHRoaXMubWV0cmljcyA9IHtcclxuICAgICAgc3RhcnRUaW1lOiBuZXcgRGF0ZSgpLFxyXG4gICAgICBlbmRUaW1lOiBuZXcgRGF0ZSgpLFxyXG4gICAgICBpdGVtQ291bnQ6IGN1cnJlbnRQYWdlUm93SXRlbUNvdW50LFxyXG4gICAgICB0b3RhbEl0ZW1Db3VudFxyXG4gICAgfTtcclxuICAgIC8vIGlmIGN1c3RvbSBmb290ZXIgaXMgZW5hYmxlZCwgdGhlbiB3ZSdsbCB1cGRhdGUgaXRzIG1ldHJpY3NcclxuICAgIGlmICh0aGlzLnNsaWNrRm9vdGVyKSB7XHJcbiAgICAgIHRoaXMuc2xpY2tGb290ZXIubWV0cmljcyA9IHRoaXMubWV0cmljcztcclxuICAgIH1cclxuXHJcbiAgICAvLyB3aGVuIHVzaW5nIGxvY2FsIChpbi1tZW1vcnkpIGRhdGFzZXQsIHdlJ2xsIGRpc3BsYXkgYSB3YXJuaW5nIG1lc3NhZ2Ugd2hlbiBmaWx0ZXJlZCBkYXRhIGlzIGVtcHR5XHJcbiAgICBpZiAodGhpcy5faXNMb2NhbEdyaWQgJiYgdGhpcy5ncmlkT3B0aW9ucz8uZW5hYmxlRW1wdHlEYXRhV2FybmluZ01lc3NhZ2UpIHtcclxuICAgICAgdGhpcy5kaXNwbGF5RW1wdHlEYXRhV2FybmluZyhjdXJyZW50UGFnZVJvd0l0ZW1Db3VudCA9PT0gMCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluaXRpYWxpemVQYWdpbmF0aW9uU2VydmljZShwYWdpbmF0aW9uT3B0aW9uczogUGFnaW5hdGlvbikge1xyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMpIHtcclxuICAgICAgdGhpcy5wYWdpbmF0aW9uRGF0YSA9IHtcclxuICAgICAgICBncmlkT3B0aW9uczogdGhpcy5ncmlkT3B0aW9ucyxcclxuICAgICAgICBwYWdpbmF0aW9uU2VydmljZTogdGhpcy5wYWdpbmF0aW9uU2VydmljZSxcclxuICAgICAgfTtcclxuICAgICAgdGhpcy5wYWdpbmF0aW9uU2VydmljZS50b3RhbEl0ZW1zID0gdGhpcy50b3RhbEl0ZW1zO1xyXG4gICAgICB0aGlzLnBhZ2luYXRpb25TZXJ2aWNlLmluaXQodGhpcy5zbGlja0dyaWQsIHBhZ2luYXRpb25PcHRpb25zLCB0aGlzLmJhY2tlbmRTZXJ2aWNlQXBpKTtcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXHJcbiAgICAgICAgdGhpcy5fZXZlbnRQdWJTdWJTZXJ2aWNlLnN1YnNjcmliZSgnb25QYWdpbmF0aW9uQ2hhbmdlZCcsIChwYWdpbmF0aW9uQ2hhbmdlczogU2VydmljZVBhZ2luYXRpb24pID0+IHtcclxuICAgICAgICAgIHRoaXMucGFnaW5hdGlvbkNoYW5nZWQocGFnaW5hdGlvbkNoYW5nZXMpO1xyXG4gICAgICAgIH0pLFxyXG4gICAgICAgIHRoaXMuX2V2ZW50UHViU3ViU2VydmljZS5zdWJzY3JpYmUoJ29uUGFnaW5hdGlvblZpc2liaWxpdHlDaGFuZ2VkJywgKHZpc2liaWxpdHk6IHsgdmlzaWJsZTogYm9vbGVhbiB9KSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnNob3dQYWdpbmF0aW9uID0gdmlzaWJpbGl0eT8udmlzaWJsZSA/PyBmYWxzZTtcclxuICAgICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zPy5iYWNrZW5kU2VydmljZUFwaSkge1xyXG4gICAgICAgICAgICB0aGlzLmJhY2tlbmRVdGlsaXR5U2VydmljZT8ucmVmcmVzaEJhY2tlbmREYXRhc2V0KHRoaXMuZ3JpZE9wdGlvbnMpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5yZW5kZXJQYWdpbmF0aW9uKHRoaXMuc2hvd1BhZ2luYXRpb24pO1xyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgICAgIC8vIGFsc28gaW5pdGlhbGl6ZSAocmVuZGVyKSB0aGUgcGFnaW5hdGlvbiBjb21wb25lbnRcclxuICAgICAgdGhpcy5yZW5kZXJQYWdpbmF0aW9uKCk7XHJcbiAgICAgIHRoaXMuX2lzUGFnaW5hdGlvbkluaXRpYWxpemVkID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gIH1cclxuXHJcbiAgLyoqIExvYWQgdGhlIEVkaXRvciBDb2xsZWN0aW9uIGFzeW5jaHJvbm91c2x5IGFuZCByZXBsYWNlIHRoZSBcImNvbGxlY3Rpb25cIiBwcm9wZXJ0eSB3aGVuIE9ic2VydmFibGUgcmVzb2x2ZXMgKi9cclxuICBwcml2YXRlIGxvYWRFZGl0b3JDb2xsZWN0aW9uQXN5bmMoY29sdW1uOiBDb2x1bW4pIHtcclxuICAgIGNvbnN0IGNvbGxlY3Rpb25Bc3luYyA9IGNvbHVtbiAmJiBjb2x1bW4uZWRpdG9yICYmIChjb2x1bW4uZWRpdG9yIGFzIENvbHVtbkVkaXRvcikuY29sbGVjdGlvbkFzeW5jO1xyXG4gICAgaWYgKGNvbGxlY3Rpb25Bc3luYyBpbnN0YW5jZW9mIE9ic2VydmFibGUpIHtcclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXHJcbiAgICAgICAgY29sbGVjdGlvbkFzeW5jLnN1YnNjcmliZSgocmVzb2x2ZWRDb2xsZWN0aW9uKSA9PiB0aGlzLnVwZGF0ZUVkaXRvckNvbGxlY3Rpb24oY29sdW1uLCByZXNvbHZlZENvbGxlY3Rpb24pKVxyXG4gICAgICApO1xyXG4gICAgfSBlbHNlIGlmIChjb2xsZWN0aW9uQXN5bmMgaW5zdGFuY2VvZiBQcm9taXNlKSB7XHJcbiAgICAgIC8vIHdhaXQgZm9yIHRoZSBcImNvbGxlY3Rpb25Bc3luY1wiLCBvbmNlIHJlc29sdmVkIHdlIHdpbGwgc2F2ZSBpdCBpbnRvIHRoZSBcImNvbGxlY3Rpb25cIlxyXG4gICAgICAvLyB0aGUgY29sbGVjdGlvbkFzeW5jIGNhbiBiZSBvZiAzIHR5cGVzIEh0dHBDbGllbnQsIEh0dHBGZXRjaCBvciBhIFByb21pc2VcclxuICAgICAgY29sbGVjdGlvbkFzeW5jLnRoZW4oKHJlc3BvbnNlOiBhbnkgfCBhbnlbXSkgPT4ge1xyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3BvbnNlKSkge1xyXG4gICAgICAgICAgdGhpcy51cGRhdGVFZGl0b3JDb2xsZWN0aW9uKGNvbHVtbiwgcmVzcG9uc2UpOyAvLyBmcm9tIFByb21pc2VcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIExvYWQgYW55IHBvc3NpYmxlIENvbHVtbnMgR3JpZCBQcmVzZXRzICovXHJcbiAgcHJpdmF0ZSBsb2FkQ29sdW1uUHJlc2V0c1doZW5EYXRhc2V0SW5pdGlhbGl6ZWQoKSB7XHJcbiAgICAvLyBpZiB1c2VyIGVudGVyZWQgc29tZSBDb2x1bW5zIFwicHJlc2V0c1wiLCB3ZSBuZWVkIHRvIHJlZmxlY3QgdGhlbSBhbGwgaW4gdGhlIGdyaWRcclxuICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLnByZXNldHMgJiYgQXJyYXkuaXNBcnJheSh0aGlzLmdyaWRPcHRpb25zLnByZXNldHMuY29sdW1ucykgJiYgdGhpcy5ncmlkT3B0aW9ucy5wcmVzZXRzLmNvbHVtbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICBjb25zdCBncmlkQ29sdW1uczogQ29sdW1uW10gPSB0aGlzLmdyaWRTdGF0ZVNlcnZpY2UuZ2V0QXNzb2NpYXRlZEdyaWRDb2x1bW5zKHRoaXMuc2xpY2tHcmlkLCB0aGlzLmdyaWRPcHRpb25zLnByZXNldHMuY29sdW1ucyk7XHJcbiAgICAgIGlmIChncmlkQ29sdW1ucyAmJiBBcnJheS5pc0FycmF5KGdyaWRDb2x1bW5zKSAmJiBncmlkQ29sdW1ucy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgdGhlIGNoZWNrYm94IHNlbGVjdG9yIGlzIGFsc28gdmlzaWJsZSBpZiBpdCBpcyBlbmFibGVkXHJcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2hlY2tib3hTZWxlY3Rvcikge1xyXG4gICAgICAgICAgY29uc3QgY2hlY2tib3hDb2x1bW4gPSAoQXJyYXkuaXNBcnJheSh0aGlzLl9jb2x1bW5EZWZpbml0aW9ucykgJiYgdGhpcy5fY29sdW1uRGVmaW5pdGlvbnMubGVuZ3RoID4gMCkgPyB0aGlzLl9jb2x1bW5EZWZpbml0aW9uc1swXSA6IG51bGw7XHJcbiAgICAgICAgICBpZiAoY2hlY2tib3hDb2x1bW4gJiYgY2hlY2tib3hDb2x1bW4uaWQgPT09ICdfY2hlY2tib3hfc2VsZWN0b3InICYmIGdyaWRDb2x1bW5zWzBdLmlkICE9PSAnX2NoZWNrYm94X3NlbGVjdG9yJykge1xyXG4gICAgICAgICAgICBncmlkQ29sdW1ucy51bnNoaWZ0KGNoZWNrYm94Q29sdW1uKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGtlZXAgY29weSB0aGUgb3JpZ2luYWwgb3B0aW9uYWwgYHdpZHRoYCBwcm9wZXJ0aWVzIG9wdGlvbmFsbHkgcHJvdmlkZWQgYnkgdGhlIHVzZXIuXHJcbiAgICAgICAgLy8gV2Ugd2lsbCB1c2UgdGhpcyB3aGVuIGRvaW5nIGEgcmVzaXplIGJ5IGNlbGwgY29udGVudCwgaWYgdXNlciBwcm92aWRlZCBhIGB3aWR0aGAgaXQgd29uJ3Qgb3ZlcnJpZGUgaXQuXHJcbiAgICAgICAgZ3JpZENvbHVtbnMuZm9yRWFjaChjb2wgPT4gY29sLm9yaWdpbmFsV2lkdGggPSBjb2wud2lkdGgpO1xyXG5cclxuICAgICAgICAvLyBmaW5hbGx5IHNldCB0aGUgbmV3IHByZXNldHMgY29sdW1ucyAoaW5jbHVkaW5nIGNoZWNrYm94IHNlbGVjdG9yIGlmIG5lZWQgYmUpXHJcbiAgICAgICAgdGhpcy5zbGlja0dyaWQuc2V0Q29sdW1ucyhncmlkQ29sdW1ucyk7XHJcbiAgICAgICAgdGhpcy5zaGFyZWRTZXJ2aWNlLnZpc2libGVDb2x1bW5zID0gZ3JpZENvbHVtbnM7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBMb2FkIGFueSBwb3NzaWJsZSBGaWx0ZXJzIEdyaWQgUHJlc2V0cyAqL1xyXG4gIHByaXZhdGUgbG9hZEZpbHRlclByZXNldHNXaGVuRGF0YXNldEluaXRpYWxpemVkKCkge1xyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMgJiYgIXRoaXMuY3VzdG9tRGF0YVZpZXcpIHtcclxuICAgICAgLy8gaWYgdXNlciBlbnRlcmVkIHNvbWUgRmlsdGVyIFwicHJlc2V0c1wiLCB3ZSBuZWVkIHRvIHJlZmxlY3QgdGhlbSBhbGwgaW4gdGhlIERPTVxyXG4gICAgICAvLyBhbHNvIG5vdGUgdGhhdCBhIHByZXNldHMgb2YgVHJlZSBEYXRhIFRvZ2dsaW5nIHdpbGwgYWxzbyBjYWxsIHRoaXMgbWV0aG9kIGJlY2F1c2UgVHJlZSBEYXRhIHRvZ2dsaW5nIGRvZXMgd29yayB3aXRoIGRhdGEgZmlsdGVyaW5nXHJcbiAgICAgIC8vIChjb2xsYXBzaW5nIGEgcGFyZW50IHdpbGwgYmFzaWNhbGx5IHVzZSBGaWx0ZXIgZm9yIGhpZGRpbmcgKGFrYSBjb2xsYXBzaW5nKSBhd2F5IHRoZSBjaGlsZCB1bmRlcm5lYXQgaXQpXHJcbiAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLnByZXNldHMgJiYgKEFycmF5LmlzQXJyYXkodGhpcy5ncmlkT3B0aW9ucy5wcmVzZXRzLmZpbHRlcnMpIHx8IEFycmF5LmlzQXJyYXkodGhpcy5ncmlkT3B0aW9ucy5wcmVzZXRzPy50cmVlRGF0YT8udG9nZ2xlZEl0ZW1zKSkpIHtcclxuICAgICAgICB0aGlzLmZpbHRlclNlcnZpY2UucG9wdWxhdGVDb2x1bW5GaWx0ZXJTZWFyY2hUZXJtUHJlc2V0cyh0aGlzLmdyaWRPcHRpb25zLnByZXNldHM/LmZpbHRlcnMgfHwgW10pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBsb2NhbCBncmlkLCBjaGVjayBpZiB3ZSBuZWVkIHRvIHNob3cgdGhlIFBhZ2luYXRpb25cclxuICAgKiBpZiBzbyB0aGVuIGFsc28gY2hlY2sgaWYgdGhlcmUncyBhbnkgcHJlc2V0cyBhbmQgZmluYWxseSBpbml0aWFsaXplIHRoZSBQYWdpbmF0aW9uU2VydmljZVxyXG4gICAqIGEgbG9jYWwgZ3JpZCB3aXRoIFBhZ2luYXRpb24gcHJlc2V0cyB3aWxsIHBvdGVudGlhbGx5IGhhdmUgYSBkaWZmZXJlbnQgdG90YWwgb2YgaXRlbXMsIHdlJ2xsIG5lZWQgdG8gZ2V0IGl0IGZyb20gdGhlIERhdGFWaWV3IGFuZCB1cGRhdGUgb3VyIHRvdGFsXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBsb2FkTG9jYWxHcmlkUGFnaW5hdGlvbihkYXRhc2V0PzogYW55W10pIHtcclxuICAgIGlmICh0aGlzLmdyaWRPcHRpb25zICYmIHRoaXMuX3BhZ2luYXRpb25PcHRpb25zKSB7XHJcbiAgICAgIHRoaXMudG90YWxJdGVtcyA9IEFycmF5LmlzQXJyYXkoZGF0YXNldCkgPyBkYXRhc2V0Lmxlbmd0aCA6IDA7XHJcbiAgICAgIGlmICh0aGlzLl9wYWdpbmF0aW9uT3B0aW9ucyAmJiB0aGlzLmRhdGFWaWV3Py5nZXRQYWdpbmdJbmZvKSB7XHJcbiAgICAgICAgY29uc3Qgc2xpY2tQYWdpbmdJbmZvID0gdGhpcy5kYXRhVmlldy5nZXRQYWdpbmdJbmZvKCk7XHJcbiAgICAgICAgaWYgKHNsaWNrUGFnaW5nSW5mbz8uaGFzT3duUHJvcGVydHkoJ3RvdGFsUm93cycpICYmIHRoaXMuX3BhZ2luYXRpb25PcHRpb25zLnRvdGFsSXRlbXMgIT09IHNsaWNrUGFnaW5nSW5mby50b3RhbFJvd3MpIHtcclxuICAgICAgICAgIHRoaXMudG90YWxJdGVtcyA9IHNsaWNrUGFnaW5nSW5mby50b3RhbFJvd3MgfHwgMDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5fcGFnaW5hdGlvbk9wdGlvbnMudG90YWxJdGVtcyA9IHRoaXMudG90YWxJdGVtcztcclxuICAgICAgY29uc3QgcGFnaW5hdGlvbk9wdGlvbnMgPSB0aGlzLnNldFBhZ2luYXRpb25PcHRpb25zV2hlblByZXNldERlZmluZWQodGhpcy5ncmlkT3B0aW9ucywgdGhpcy5fcGFnaW5hdGlvbk9wdGlvbnMpO1xyXG4gICAgICB0aGlzLmluaXRpYWxpemVQYWdpbmF0aW9uU2VydmljZShwYWdpbmF0aW9uT3B0aW9ucyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogTG9hZCBhbnkgUm93IFNlbGVjdGlvbnMgaW50byB0aGUgRGF0YVZpZXcgdGhhdCB3ZXJlIHByZXNldHMgYnkgdGhlIHVzZXIgKi9cclxuICBwcml2YXRlIGxvYWRSb3dTZWxlY3Rpb25QcmVzZXRXaGVuRXhpc3RzKCkge1xyXG4gICAgLy8gaWYgdXNlciBlbnRlcmVkIHNvbWUgUm93IFNlbGVjdGlvbnMgXCJwcmVzZXRzXCJcclxuICAgIGNvbnN0IHByZXNldHMgPSB0aGlzLmdyaWRPcHRpb25zPy5wcmVzZXRzO1xyXG4gICAgY29uc3Qgc2VsZWN0aW9uTW9kZWwgPSB0aGlzLnNsaWNrR3JpZD8uZ2V0U2VsZWN0aW9uTW9kZWw/LigpO1xyXG4gICAgY29uc3QgZW5hYmxlUm93U2VsZWN0aW9uID0gdGhpcy5ncmlkT3B0aW9ucyAmJiAodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVDaGVja2JveFNlbGVjdG9yIHx8IHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUm93U2VsZWN0aW9uKTtcclxuICAgIGlmIChlbmFibGVSb3dTZWxlY3Rpb24gJiYgc2VsZWN0aW9uTW9kZWwgJiYgcHJlc2V0cyAmJiBwcmVzZXRzLnJvd1NlbGVjdGlvbiAmJiAoQXJyYXkuaXNBcnJheShwcmVzZXRzLnJvd1NlbGVjdGlvbi5ncmlkUm93SW5kZXhlcykgfHwgQXJyYXkuaXNBcnJheShwcmVzZXRzLnJvd1NlbGVjdGlvbi5kYXRhQ29udGV4dElkcykpKSB7XHJcbiAgICAgIGxldCBkYXRhQ29udGV4dElkcyA9IHByZXNldHMucm93U2VsZWN0aW9uLmRhdGFDb250ZXh0SWRzO1xyXG4gICAgICBsZXQgZ3JpZFJvd0luZGV4ZXMgPSBwcmVzZXRzLnJvd1NlbGVjdGlvbi5ncmlkUm93SW5kZXhlcztcclxuXHJcbiAgICAgIC8vIG1hcHMgdGhlIElEcyB0byB0aGUgR3JpZCBSb3dzIGFuZCB2aWNlIHZlcnNhLCB0aGUgXCJkYXRhQ29udGV4dElkc1wiIGhhcyBwcmVjZWRlbmNlIG92ZXIgdGhlIG90aGVyXHJcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGFDb250ZXh0SWRzKSAmJiBkYXRhQ29udGV4dElkcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgZ3JpZFJvd0luZGV4ZXMgPSB0aGlzLmRhdGFWaWV3Lm1hcElkc1RvUm93cyhkYXRhQ29udGV4dElkcykgfHwgW107XHJcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShncmlkUm93SW5kZXhlcykgJiYgZ3JpZFJvd0luZGV4ZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGRhdGFDb250ZXh0SWRzID0gdGhpcy5kYXRhVmlldy5tYXBSb3dzVG9JZHMoZ3JpZFJvd0luZGV4ZXMpIHx8IFtdO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuZ3JpZFN0YXRlU2VydmljZS5zZWxlY3RlZFJvd0RhdGFDb250ZXh0SWRzID0gZGF0YUNvbnRleHRJZHM7XHJcblxyXG4gICAgICAvLyBjaGFuZ2UgdGhlIHNlbGVjdGVkIHJvd3MgZXhjZXB0IFVOTEVTUyBpdCdzIGEgTG9jYWwgR3JpZCB3aXRoIFBhZ2luYXRpb25cclxuICAgICAgLy8gbG9jYWwgUGFnaW5hdGlvbiB1c2VzIHRoZSBEYXRhVmlldyBhbmQgdGhhdCBhbHNvIHRyaWdnZXIgYSBjaGFuZ2UvcmVmcmVzaFxyXG4gICAgICAvLyBhbmQgd2UgZG9uJ3Qgd2FudCB0byB0cmlnZ2VyIDIgR3JpZCBTdGF0ZSBjaGFuZ2VzIGp1c3QgMVxyXG4gICAgICBpZiAoKHRoaXMuX2lzTG9jYWxHcmlkICYmICF0aGlzLmdyaWRPcHRpb25zLmVuYWJsZVBhZ2luYXRpb24pIHx8ICF0aGlzLl9pc0xvY2FsR3JpZCkge1xyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgaWYgKHRoaXMuc2xpY2tHcmlkICYmIEFycmF5LmlzQXJyYXkoZ3JpZFJvd0luZGV4ZXMpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2xpY2tHcmlkLnNldFNlbGVjdGVkUm93cyhncmlkUm93SW5kZXhlcyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgbWVyZ2VHcmlkT3B0aW9ucyhncmlkT3B0aW9uczogR3JpZE9wdGlvbik6IEdyaWRPcHRpb24ge1xyXG4gICAgZ3JpZE9wdGlvbnMuZ3JpZElkID0gdGhpcy5ncmlkSWQ7XHJcbiAgICBncmlkT3B0aW9ucy5ncmlkQ29udGFpbmVySWQgPSBgc2xpY2tHcmlkQ29udGFpbmVyLSR7dGhpcy5ncmlkSWR9YDtcclxuXHJcbiAgICAvLyBpZiB3ZSBoYXZlIGEgYmFja2VuZFNlcnZpY2VBcGkgYW5kIHRoZSBlbmFibGVQYWdpbmF0aW9uIGlzIHVuZGVmaW5lZCwgd2UnbGwgYXNzdW1lIHRoYXQgd2UgZG8gd2FudCB0byBzZWUgaXQsIGVsc2UgZ2V0IHRoYXQgZGVmaW5lZCB2YWx1ZVxyXG4gICAgZ3JpZE9wdGlvbnMuZW5hYmxlUGFnaW5hdGlvbiA9ICgoZ3JpZE9wdGlvbnMuYmFja2VuZFNlcnZpY2VBcGkgJiYgZ3JpZE9wdGlvbnMuZW5hYmxlUGFnaW5hdGlvbiA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBncmlkT3B0aW9ucy5lbmFibGVQYWdpbmF0aW9uKSB8fCBmYWxzZTtcclxuXHJcbiAgICAvLyB1c2UganF1ZXJ5IGV4dGVuZCB0byBkZWVwIG1lcmdlICYgY29weSB0byBhdm9pZCBpbW11dGFibGUgcHJvcGVydGllcyBiZWluZyBjaGFuZ2VkIGluIEdsb2JhbEdyaWRPcHRpb25zIGFmdGVyIGEgcm91dGUgY2hhbmdlXHJcbiAgICBjb25zdCBvcHRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIEdsb2JhbEdyaWRPcHRpb25zLCB0aGlzLmZvclJvb3RDb25maWcsIGdyaWRPcHRpb25zKSBhcyBHcmlkT3B0aW9uO1xyXG5cclxuICAgIC8vIHVzaW5nIGpRdWVyeSBleHRlbmQgdG8gZG8gYSBkZWVwIGNsb25lIGhhcyBhbiB1bndhbnRlZCBzaWRlIG9uIG9iamVjdHMgYW5kIHBhZ2VTaXplcyBidXQgRVM2IHNwcmVhZCBoYXMgb3RoZXIgd29yc3Qgc2lkZSBlZmZlY3RzXHJcbiAgICAvLyBzbyB3ZSB3aWxsIGp1c3Qgb3ZlcndyaXRlIHRoZSBwYWdlU2l6ZXMgd2hlbiBuZWVkZWQsIHRoaXMgaXMgdGhlIG9ubHkgb25lIGNhdXNpbmcgaXNzdWVzIHNvIGZhci5cclxuICAgIC8vIGpRdWVyeSB3cm90ZSB0aGlzIG9uIHRoZWlyIGRvY3M6OiBPbiBhIGRlZXAgZXh0ZW5kLCBPYmplY3QgYW5kIEFycmF5IGFyZSBleHRlbmRlZCwgYnV0IG9iamVjdCB3cmFwcGVycyBvbiBwcmltaXRpdmUgdHlwZXMgc3VjaCBhcyBTdHJpbmcsIEJvb2xlYW4sIGFuZCBOdW1iZXIgYXJlIG5vdC5cclxuICAgIGlmIChvcHRpb25zPy5wYWdpbmF0aW9uICYmIChncmlkT3B0aW9ucy5lbmFibGVQYWdpbmF0aW9uIHx8IGdyaWRPcHRpb25zLmJhY2tlbmRTZXJ2aWNlQXBpKSAmJiBncmlkT3B0aW9ucy5wYWdpbmF0aW9uICYmIEFycmF5LmlzQXJyYXkoZ3JpZE9wdGlvbnMucGFnaW5hdGlvbi5wYWdlU2l6ZXMpKSB7XHJcbiAgICAgIG9wdGlvbnMucGFnaW5hdGlvbi5wYWdlU2l6ZXMgPSBncmlkT3B0aW9ucy5wYWdpbmF0aW9uLnBhZ2VTaXplcztcclxuICAgIH1cclxuXHJcbiAgICAvLyBhbHNvIG1ha2Ugc3VyZSB0byBzaG93IHRoZSBoZWFkZXIgcm93IGlmIHVzZXIgaGF2ZSBlbmFibGVkIGZpbHRlcmluZ1xyXG4gICAgdGhpcy5faGlkZUhlYWRlclJvd0FmdGVyUGFnZUxvYWQgPSAob3B0aW9ucy5zaG93SGVhZGVyUm93ID09PSBmYWxzZSk7XHJcbiAgICBpZiAob3B0aW9ucy5lbmFibGVGaWx0ZXJpbmcgJiYgIW9wdGlvbnMuc2hvd0hlYWRlclJvdykge1xyXG4gICAgICBvcHRpb25zLnNob3dIZWFkZXJSb3cgPSBvcHRpb25zLmVuYWJsZUZpbHRlcmluZztcclxuICAgIH1cclxuXHJcbiAgICAvLyB3aGVuIHdlIHVzZSBQYWdpbmF0aW9uIG9uIExvY2FsIEdyaWQsIGl0IGRvZXNuJ3Qgc2VlbSB0byB3b3JrIHdpdGhvdXQgZW5hYmxlRmlsdGVyaW5nXHJcbiAgICAvLyBzbyB3ZSdsbCBlbmFibGUgdGhlIGZpbHRlcmluZyBidXQgd2UnbGwga2VlcCB0aGUgaGVhZGVyIHJvdyBoaWRkZW5cclxuICAgIGlmIChvcHRpb25zICYmICFvcHRpb25zLmVuYWJsZUZpbHRlcmluZyAmJiBvcHRpb25zLmVuYWJsZVBhZ2luYXRpb24gJiYgdGhpcy5faXNMb2NhbEdyaWQpIHtcclxuICAgICAgb3B0aW9ucy5lbmFibGVGaWx0ZXJpbmcgPSB0cnVlO1xyXG4gICAgICBvcHRpb25zLnNob3dIZWFkZXJSb3cgPSBmYWxzZTtcclxuICAgICAgdGhpcy5faGlkZUhlYWRlclJvd0FmdGVyUGFnZUxvYWQgPSB0cnVlO1xyXG4gICAgICBpZiAodGhpcy5zaGFyZWRTZXJ2aWNlKSB7XHJcbiAgICAgICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmhpZGVIZWFkZXJSb3dBZnRlclBhZ2VMb2FkID0gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBvcHRpb25zO1xyXG4gIH1cclxuXHJcbiAgLyoqIFByZS1SZWdpc3RlciBhbnkgUmVzb3VyY2UgdGhhdCBkb24ndCByZXF1aXJlIFNsaWNrR3JpZCB0byBiZSBpbnN0YW50aWF0ZWQgKGZvciBleGFtcGxlIFJ4SlMgUmVzb3VyY2UpICovXHJcbiAgcHJpdmF0ZSBwcmVSZWdpc3RlclJlc291cmNlcygpIHtcclxuICAgIHRoaXMuX3JlZ2lzdGVyZWRSZXNvdXJjZXMgPSB0aGlzLmdyaWRPcHRpb25zLnJlZ2lzdGVyRXh0ZXJuYWxSZXNvdXJjZXMgfHwgW107XHJcblxyXG4gICAgLy8gQW5ndWxhci1TbGlja2dyaWQgcmVxdWlyZXMgUnhKUywgc28gd2UnbGwgcmVnaXN0ZXIgaXQgYXMgdGhlIGZpcnN0IHJlc291cmNlXHJcbiAgICB0aGlzLnJlZ2lzdGVyUnhKc1Jlc291cmNlKG5ldyBSeEpzUmVzb3VyY2UoKSBhcyBSeEpzRmFjYWRlKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVnaXN0ZXJSZXNvdXJjZXMoKSB7XHJcbiAgICAvLyBhdCB0aGlzIHBvaW50LCB3ZSBjb25zaWRlciBhbGwgdGhlIHJlZ2lzdGVyZWQgc2VydmljZXMgYXMgZXh0ZXJuYWwgc2VydmljZXMsIGFueXRoaW5nIGVsc2UgcmVnaXN0ZXJlZCBhZnRlcndhcmQgYXJlbid0IGV4dGVybmFsXHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLl9yZWdpc3RlcmVkUmVzb3VyY2VzKSkge1xyXG4gICAgICB0aGlzLnNoYXJlZFNlcnZpY2UuZXh0ZXJuYWxSZWdpc3RlcmVkUmVzb3VyY2VzID0gdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcztcclxuICAgIH1cclxuXHJcbiAgICAvLyBwdXNoIGFsbCBvdGhlciBTZXJ2aWNlcyB0aGF0IHdlIHdhbnQgdG8gYmUgcmVnaXN0ZXJlZFxyXG4gICAgdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcy5wdXNoKHRoaXMuZ3JpZFNlcnZpY2UsIHRoaXMuZ3JpZFN0YXRlU2VydmljZSk7XHJcblxyXG4gICAgLy8gd2hlbiB1c2luZyBHcm91cGluZy9EcmFnZ2FibGVHcm91cGluZy9Db2xzcGFuIHJlZ2lzdGVyIGl0cyBTZXJ2aWNlXHJcbiAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5jcmVhdGVQcmVIZWFkZXJQYW5lbCAmJiAhdGhpcy5ncmlkT3B0aW9ucy5lbmFibGVEcmFnZ2FibGVHcm91cGluZykge1xyXG4gICAgICB0aGlzLl9yZWdpc3RlcmVkUmVzb3VyY2VzLnB1c2godGhpcy5ncm91cGluZ1NlcnZpY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHdoZW4gdXNpbmcgVHJlZSBEYXRhIFZpZXcsIHJlZ2lzdGVyIGl0cyBTZXJ2aWNlXHJcbiAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVUcmVlRGF0YSkge1xyXG4gICAgICB0aGlzLl9yZWdpc3RlcmVkUmVzb3VyY2VzLnB1c2godGhpcy50cmVlRGF0YVNlcnZpY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHdoZW4gdXNlciBlbmFibGVzIHRyYW5zbGF0aW9uLCB3ZSBuZWVkIHRvIHRyYW5zbGF0ZSBIZWFkZXJzIG9uIGZpcnN0IHBhc3MgJiBzdWJzZXF1ZW50bHkgaW4gdGhlIGJpbmREaWZmZXJlbnRIb29rc1xyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlVHJhbnNsYXRlKSB7XHJcbiAgICAgIHRoaXMuZXh0ZW5zaW9uU2VydmljZS50cmFuc2xhdGVDb2x1bW5IZWFkZXJzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gYWxzbyBpbml0aWFsaXplIChyZW5kZXIpIHRoZSBlbXB0eSB3YXJuaW5nIGNvbXBvbmVudFxyXG4gICAgdGhpcy5zbGlja0VtcHR5V2FybmluZyA9IG5ldyBTbGlja0VtcHR5V2FybmluZ0NvbXBvbmVudCgpO1xyXG4gICAgdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcy5wdXNoKHRoaXMuc2xpY2tFbXB0eVdhcm5pbmcpO1xyXG5cclxuICAgIC8vIGJpbmQgJiBpbml0aWFsaXplIGFsbCBDb21wb25lbnRzL1NlcnZpY2VzIHRoYXQgd2VyZSB0YWdnZWQgYXMgZW5hYmxlZFxyXG4gICAgLy8gcmVnaXN0ZXIgYWxsIHNlcnZpY2VzIGJ5IGV4ZWN1dGluZyB0aGVpciBpbml0IG1ldGhvZCBhbmQgcHJvdmlkaW5nIHRoZW0gd2l0aCB0aGUgR3JpZCBvYmplY3RcclxuICAgIGlmIChBcnJheS5pc0FycmF5KHRoaXMuX3JlZ2lzdGVyZWRSZXNvdXJjZXMpKSB7XHJcbiAgICAgIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgdGhpcy5fcmVnaXN0ZXJlZFJlc291cmNlcykge1xyXG4gICAgICAgIGlmICh0eXBlb2YgcmVzb3VyY2UuaW5pdCA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgcmVzb3VyY2UuaW5pdCh0aGlzLnNsaWNrR3JpZCwgdGhpcy5jb250YWluZXJTZXJ2aWNlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBSZWdpc3RlciB0aGUgUnhKUyBSZXNvdXJjZSBpbiBhbGwgbmVjZXNzYXJ5IHNlcnZpY2VzIHdoaWNoIHVzZXMgKi9cclxuICBwcml2YXRlIHJlZ2lzdGVyUnhKc1Jlc291cmNlKHJlc291cmNlOiBSeEpzRmFjYWRlKSB7XHJcbiAgICB0aGlzLnJ4anMgPSByZXNvdXJjZTtcclxuICAgIHRoaXMuYmFja2VuZFV0aWxpdHlTZXJ2aWNlLmFkZFJ4SnNSZXNvdXJjZSh0aGlzLnJ4anMpO1xyXG4gICAgdGhpcy5maWx0ZXJGYWN0b3J5LmFkZFJ4SnNSZXNvdXJjZSh0aGlzLnJ4anMpO1xyXG4gICAgdGhpcy5maWx0ZXJTZXJ2aWNlLmFkZFJ4SnNSZXNvdXJjZSh0aGlzLnJ4anMpO1xyXG4gICAgdGhpcy5zb3J0U2VydmljZS5hZGRSeEpzUmVzb3VyY2UodGhpcy5yeGpzKTtcclxuICAgIHRoaXMucGFnaW5hdGlvblNlcnZpY2UuYWRkUnhKc1Jlc291cmNlKHRoaXMucnhqcyk7XHJcbiAgICB0aGlzLmNvbnRhaW5lclNlcnZpY2UucmVnaXN0ZXJJbnN0YW5jZSgnUnhKc1Jlc291cmNlJywgdGhpcy5yeGpzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbmRlciAob3IgZGlzcG9zZSkgdGhlIFBhZ2luYXRpb24gQ29tcG9uZW50LCB1c2VyIGNhbiBvcHRpb25hbGx5IHByb3ZpZGUgRmFsc2UgKHRvIG5vdCBzaG93IGl0KSB3aGljaCB3aWxsIGluIHRlcm0gZGlzcG9zZSBvZiB0aGUgUGFnaW5hdGlvbixcclxuICAgKiBhbHNvIHdoaWxlIGRpc3Bvc2luZyB3ZSBjYW4gY2hvb3NlIHRvIG9taXQgdGhlIGRpc3Bvc2FibGUgb2YgdGhlIFBhZ2luYXRpb24gU2VydmljZSAoaWYgd2UgYXJlIHNpbXBseSB0b2dnbGluZyB0aGUgUGFnaW5hdGlvbiwgd2Ugd2FudCB0byBrZWVwIHRoZSBTZXJ2aWNlIGFsaXZlKVxyXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gc2hvd1BhZ2luYXRpb24gLSBzaG93IChuZXcgcmVuZGVyKSBvciBub3QgKGRpc3Bvc2UpIHRoZSBQYWdpbmF0aW9uXHJcbiAgICogQHBhcmFtIHtCb29sZWFufSBzaG91bGREaXNwb3NlUGFnaW5hdGlvblNlcnZpY2UgLSB3aGVuIGRpc3Bvc2luZyB0aGUgUGFnaW5hdGlvbiwgZG8gd2UgYWxzbyB3YW50IHRvIGRpc3Bvc2Ugb2YgdGhlIFBhZ2luYXRpb24gU2VydmljZT8gKGRlZmF1bHRzIHRvIFRydWUpXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZW5kZXJQYWdpbmF0aW9uKHNob3dQYWdpbmF0aW9uID0gdHJ1ZSkge1xyXG4gICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnM/LmVuYWJsZVBhZ2luYXRpb24gJiYgIXRoaXMuX2lzUGFnaW5hdGlvbkluaXRpYWxpemVkICYmIHNob3dQYWdpbmF0aW9uKSB7XHJcbiAgICAgIHRoaXMuc2xpY2tQYWdpbmF0aW9uID0gbmV3IFNsaWNrUGFnaW5hdGlvbkNvbXBvbmVudCh0aGlzLnBhZ2luYXRpb25TZXJ2aWNlLCB0aGlzLl9ldmVudFB1YlN1YlNlcnZpY2UsIHRoaXMuc2hhcmVkU2VydmljZSwgdGhpcy50cmFuc2xhdGVyU2VydmljZSk7XHJcbiAgICAgIHRoaXMuc2xpY2tQYWdpbmF0aW9uLnJlbmRlclBhZ2luYXRpb24odGhpcy5ncmlkQ29udGFpbmVyRWxlbWVudCBhcyBIVE1MRWxlbWVudCk7XHJcbiAgICAgIHRoaXMuX2lzUGFnaW5hdGlvbkluaXRpYWxpemVkID0gdHJ1ZTtcclxuICAgIH0gZWxzZSBpZiAoIXNob3dQYWdpbmF0aW9uKSB7XHJcbiAgICAgIGlmICh0aGlzLnNsaWNrUGFnaW5hdGlvbikge1xyXG4gICAgICAgIHRoaXMuc2xpY2tQYWdpbmF0aW9uLmRpc3Bvc2UoKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLl9pc1BhZ2luYXRpb25Jbml0aWFsaXplZCA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGFrZXMgYSBmbGF0IGRhdGFzZXQgd2l0aCBwYXJlbnQvY2hpbGQgcmVsYXRpb25zaGlwLCBzb3J0IGl0ICh2aWEgaXRzIHRyZWUgc3RydWN0dXJlKSBhbmQgcmV0dXJuIHRoZSBzb3J0ZWQgZmxhdCBhcnJheVxyXG4gICAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gZmxhdERhdGFzZXRJbnB1dCAtIGZsYXQgZGF0YXNldCBpbnB1dFxyXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2VHcmlkUmVmcmVzaCAtIG9wdGlvbmFsbHkgZm9yY2UgYSBmdWxsIGdyaWQgcmVmcmVzaFxyXG4gICAqIEByZXR1cm5zIHtBcnJheTxPYmplY3Q+fSBzb3J0IGZsYXQgcGFyZW50L2NoaWxkIGRhdGFzZXRcclxuICAgKi9cclxuICBwcml2YXRlIHNvcnRUcmVlRGF0YXNldDxUPihmbGF0RGF0YXNldElucHV0OiBUW10sIGZvcmNlR3JpZFJlZnJlc2ggPSBmYWxzZSk6IFRbXSB7XHJcbiAgICBjb25zdCBwcmV2RGF0YXNldExuID0gdGhpcy5fY3VycmVudERhdGFzZXRMZW5ndGg7XHJcbiAgICBsZXQgc29ydGVkRGF0YXNldFJlc3VsdDtcclxuICAgIGxldCBmbGF0RGF0YXNldE91dHB1dDogYW55W10gPSBbXTtcclxuXHJcbiAgICAvLyBpZiB0aGUgaGllcmFyY2hpY2FsIGRhdGFzZXQgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQgdGhlbiBubyBuZWVkIHRvIHJlLWNvbnZlcnQgaXQsIHdlIGNhbiB1c2UgaXQgZGlyZWN0bHkgZnJvbSB0aGUgc2hhcmVkIHNlcnZpY2UgcmVmXHJcbiAgICBpZiAodGhpcy5faXNEYXRhc2V0SGllcmFyY2hpY2FsSW5pdGlhbGl6ZWQgJiYgdGhpcy5kYXRhc2V0SGllcmFyY2hpY2FsKSB7XHJcbiAgICAgIHNvcnRlZERhdGFzZXRSZXN1bHQgPSB0aGlzLnRyZWVEYXRhU2VydmljZS5zb3J0SGllcmFyY2hpY2FsRGF0YXNldCh0aGlzLmRhdGFzZXRIaWVyYXJjaGljYWwpO1xyXG4gICAgICBmbGF0RGF0YXNldE91dHB1dCA9IHNvcnRlZERhdGFzZXRSZXN1bHQuZmxhdDtcclxuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShmbGF0RGF0YXNldElucHV0KSAmJiBmbGF0RGF0YXNldElucHV0Lmxlbmd0aCA+IDApIHtcclxuICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnM/LnRyZWVEYXRhT3B0aW9ucz8uaW5pdGlhbFNvcnQpIHtcclxuICAgICAgICAvLyBlbHNlIHdlIG5lZWQgdG8gZmlyc3QgY29udmVydCB0aGUgZmxhdCBkYXRhc2V0IHRvIGEgaGllcmFyY2hpY2FsIGRhdGFzZXQgYW5kIHRoZW4gc29ydFxyXG4gICAgICAgIHNvcnRlZERhdGFzZXRSZXN1bHQgPSB0aGlzLnRyZWVEYXRhU2VydmljZS5jb252ZXJ0RmxhdFBhcmVudENoaWxkVG9UcmVlRGF0YXNldEFuZFNvcnQoZmxhdERhdGFzZXRJbnB1dCwgdGhpcy5fY29sdW1uRGVmaW5pdGlvbnMsIHRoaXMuZ3JpZE9wdGlvbnMpO1xyXG4gICAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5oaWVyYXJjaGljYWxEYXRhc2V0ID0gc29ydGVkRGF0YXNldFJlc3VsdC5oaWVyYXJjaGljYWw7XHJcbiAgICAgICAgZmxhdERhdGFzZXRPdXRwdXQgPSBzb3J0ZWREYXRhc2V0UmVzdWx0LmZsYXQ7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gZWxzZSB3ZSBhc3N1bWUgdGhhdCB0aGUgdXNlciBwcm92aWRlZCBhbiBhcnJheSB0aGF0IGlzIGFscmVhZHkgc29ydGVkICh1c2VyJ3MgcmVzcG9uc2FiaWxpdHkpXHJcbiAgICAgICAgLy8gYW5kIHNvIHdlIGNhbiBzaW1wbHkgY29udmVydCB0aGUgYXJyYXkgdG8gYSB0cmVlIHN0cnVjdHVyZSBhbmQgd2UncmUgZG9uZSwgbm8gbmVlZCB0byBzb3J0XHJcbiAgICAgICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmhpZXJhcmNoaWNhbERhdGFzZXQgPSB0aGlzLnRyZWVEYXRhU2VydmljZS5jb252ZXJ0RmxhdFBhcmVudENoaWxkVG9UcmVlRGF0YXNldChmbGF0RGF0YXNldElucHV0LCB0aGlzLmdyaWRPcHRpb25zKTtcclxuICAgICAgICBmbGF0RGF0YXNldE91dHB1dCA9IGZsYXREYXRhc2V0SW5wdXQgfHwgW107XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBpZiB3ZSBhZGQvcmVtb3ZlIGl0ZW0ocykgZnJvbSB0aGUgZGF0YXNldCwgd2UgbmVlZCB0byBhbHNvIHJlZnJlc2ggb3VyIHRyZWUgZGF0YSBmaWx0ZXJzXHJcbiAgICBpZiAoZmxhdERhdGFzZXRJbnB1dC5sZW5ndGggPiAwICYmIChmb3JjZUdyaWRSZWZyZXNoIHx8IGZsYXREYXRhc2V0SW5wdXQubGVuZ3RoICE9PSBwcmV2RGF0YXNldExuKSkge1xyXG4gICAgICB0aGlzLmZpbHRlclNlcnZpY2UucmVmcmVzaFRyZWVEYXRhRmlsdGVycyhmbGF0RGF0YXNldE91dHB1dCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGZsYXREYXRhc2V0T3V0cHV0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRm9yIGNvbnZlbmllbmNlIHRvIHRoZSB1c2VyLCB3ZSBwcm92aWRlIHRoZSBwcm9wZXJ0eSBcImVkaXRvclwiIGFzIGFuIEFuZ3VsYXItU2xpY2tncmlkIGVkaXRvciBjb21wbGV4IG9iamVjdFxyXG4gICAqIGhvd2V2ZXIgXCJlZGl0b3JcIiBpcyB1c2VkIGludGVybmFsbHkgYnkgU2xpY2tHcmlkIGZvciBpdCdzIG93biBFZGl0b3IgRmFjdG9yeVxyXG4gICAqIHNvIGluIG91ciBsaWIgd2Ugd2lsbCBzd2FwIFwiZWRpdG9yXCIgYW5kIGNvcHkgaXQgaW50byBhIG5ldyBwcm9wZXJ0eSBjYWxsZWQgXCJpbnRlcm5hbENvbHVtbkVkaXRvclwiXHJcbiAgICogdGhlbiB0YWtlIGJhY2sgXCJlZGl0b3IubW9kZWxcIiBhbmQgbWFrZSBpdCB0aGUgbmV3IFwiZWRpdG9yXCIgc28gdGhhdCBTbGlja0dyaWQgRWRpdG9yIEZhY3Rvcnkgc3RpbGwgd29ya3NcclxuICAgKi9cclxuICBwcml2YXRlIHN3YXBJbnRlcm5hbEVkaXRvclRvU2xpY2tHcmlkRmFjdG9yeUVkaXRvcihjb2x1bW5EZWZpbml0aW9uczogQ29sdW1uW10pIHtcclxuICAgIGlmIChjb2x1bW5EZWZpbml0aW9ucy5zb21lKGNvbCA9PiBgJHtjb2wuaWR9YC5pbmNsdWRlcygnLicpKSkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdbQW5ndWxhci1TbGlja2dyaWRdIE1ha2Ugc3VyZSB0aGF0IG5vbmUgb2YgeW91ciBDb2x1bW4gRGVmaW5pdGlvbiBcImlkXCIgcHJvcGVydHkgaW5jbHVkZXMgYSBkb3QgaW4gaXRzIG5hbWUgYmVjYXVzZSB0aGF0IHdpbGwgY2F1c2Ugc29tZSBwcm9ibGVtcyB3aXRoIHRoZSBFZGl0b3JzLiBGb3IgZXhhbXBsZSBpZiB5b3VyIGNvbHVtbiBkZWZpbml0aW9uIFwiZmllbGRcIiBwcm9wZXJ0eSBpcyBcInVzZXIuZmlyc3ROYW1lXCIgdGhlbiB1c2UgXCJmaXJzdE5hbWVcIiBhcyB0aGUgY29sdW1uIFwiaWRcIi4nKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gY29sdW1uRGVmaW5pdGlvbnMubWFwKChjb2x1bW46IENvbHVtbiB8IGFueSkgPT4ge1xyXG4gICAgICAvLyBvbiBldmVyeSBFZGl0b3IgdGhhdCBoYXZlIGEgXCJjb2xsZWN0aW9uQXN5bmNcIiwgcmVzb2x2ZSB0aGUgZGF0YSBhbmQgYXNzaWduIGl0IHRvIHRoZSBcImNvbGxlY3Rpb25cIiBwcm9wZXJ0eVxyXG4gICAgICBpZiAoY29sdW1uICYmIGNvbHVtbi5lZGl0b3IgJiYgY29sdW1uLmVkaXRvci5jb2xsZWN0aW9uQXN5bmMpIHtcclxuICAgICAgICB0aGlzLmxvYWRFZGl0b3JDb2xsZWN0aW9uQXN5bmMoY29sdW1uKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4geyAuLi5jb2x1bW4sIGVkaXRvcjogY29sdW1uLmVkaXRvciAmJiBjb2x1bW4uZWRpdG9yLm1vZGVsLCBpbnRlcm5hbENvbHVtbkVkaXRvcjogeyAuLi5jb2x1bW4uZWRpdG9yIH0gfTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB0cmFuc2xhdGVDb2x1bW5IZWFkZXJUaXRsZUtleXMoKSB7XHJcbiAgICAvLyB0cmFuc2xhdGUgYWxsIGNvbHVtbnMgKGluY2x1ZGluZyBoaWRkZW4gY29sdW1ucylcclxuICAgIHRoaXMuZXh0ZW5zaW9uVXRpbGl0eS50cmFuc2xhdGVJdGVtcyh0aGlzLnNoYXJlZFNlcnZpY2UuYWxsQ29sdW1ucywgJ25hbWVLZXknLCAnbmFtZScpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB0cmFuc2xhdGVDb2x1bW5Hcm91cEtleXMoKSB7XHJcbiAgICAvLyB0cmFuc2xhdGUgYWxsIGNvbHVtbiBncm91cHMgKGluY2x1ZGluZyBoaWRkZW4gY29sdW1ucylcclxuICAgIHRoaXMuZXh0ZW5zaW9uVXRpbGl0eS50cmFuc2xhdGVJdGVtcyh0aGlzLnNoYXJlZFNlcnZpY2UuYWxsQ29sdW1ucywgJ2NvbHVtbkdyb3VwS2V5JywgJ2NvbHVtbkdyb3VwJyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGUgdGhlIFwiaW50ZXJuYWxDb2x1bW5FZGl0b3IuY29sbGVjdGlvblwiIHByb3BlcnR5LlxyXG4gICAqIFNpbmNlIHRoaXMgaXMgY2FsbGVkIGFmdGVyIHRoZSBhc3luYyBjYWxsIHJlc29sdmVzLCB0aGUgcG9pbnRlciB3aWxsIG5vdCBiZSB0aGUgc2FtZSBhcyB0aGUgXCJjb2x1bW5cIiBhcmd1bWVudCBwYXNzZWQuXHJcbiAgICogT25jZSB3ZSBmb3VuZCB0aGUgbmV3IHBvaW50ZXIsIHdlIHdpbGwgcmVhc3NpZ24gdGhlIFwiZWRpdG9yXCIgYW5kIFwiY29sbGVjdGlvblwiIHRvIHRoZSBcImludGVybmFsQ29sdW1uRWRpdG9yXCIgc28gaXQgaGFzIG5ld2VzdCBjb2xsZWN0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSB1cGRhdGVFZGl0b3JDb2xsZWN0aW9uPFQgPSBhbnk+KGNvbHVtbjogQ29sdW1uPFQ+LCBuZXdDb2xsZWN0aW9uOiBUW10pIHtcclxuICAgIChjb2x1bW4uZWRpdG9yIGFzIENvbHVtbkVkaXRvcikuY29sbGVjdGlvbiA9IG5ld0NvbGxlY3Rpb247XHJcbiAgICAoY29sdW1uLmVkaXRvciBhcyBDb2x1bW5FZGl0b3IpLmRpc2FibGVkID0gZmFsc2U7XHJcblxyXG4gICAgLy8gZmluZCB0aGUgbmV3IGNvbHVtbiByZWZlcmVuY2UgcG9pbnRlciAmIHJlLWFzc2lnbiB0aGUgbmV3IGVkaXRvciB0byB0aGUgaW50ZXJuYWxDb2x1bW5FZGl0b3JcclxuICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLnNsaWNrR3JpZC5nZXRDb2x1bW5zKCk7XHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2x1bW5zKSkge1xyXG4gICAgICBjb25zdCBjb2x1bW5SZWYgPSBjb2x1bW5zLmZpbmQoKGNvbDogQ29sdW1uKSA9PiBjb2wuaWQgPT09IGNvbHVtbi5pZCk7XHJcbiAgICAgIGlmIChjb2x1bW5SZWYpIHtcclxuICAgICAgICBjb2x1bW5SZWYuaW50ZXJuYWxDb2x1bW5FZGl0b3IgPSBjb2x1bW4uZWRpdG9yIGFzIENvbHVtbkVkaXRvcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIGdldCBjdXJyZW50IEVkaXRvciwgcmVtb3ZlIGl0IGZyb20gdGhlIERPTSB0aGVuIHJlLWVuYWJsZSBpdCBhbmQgcmUtcmVuZGVyIGl0IHdpdGggdGhlIG5ldyBjb2xsZWN0aW9uLlxyXG4gICAgY29uc3QgY3VycmVudEVkaXRvciA9IHRoaXMuc2xpY2tHcmlkLmdldENlbGxFZGl0b3IoKSBhcyBBdXRvQ29tcGxldGVFZGl0b3IgfCBTZWxlY3RFZGl0b3I7XHJcbiAgICBpZiAoY3VycmVudEVkaXRvcj8uZGlzYWJsZSAmJiBjdXJyZW50RWRpdG9yPy5yZW5kZXJEb21FbGVtZW50KSB7XHJcbiAgICAgIGN1cnJlbnRFZGl0b3IuZGVzdHJveSgpO1xyXG4gICAgICBjdXJyZW50RWRpdG9yLmRpc2FibGUoZmFsc2UpO1xyXG4gICAgICBjdXJyZW50RWRpdG9yLnJlbmRlckRvbUVsZW1lbnQobmV3Q29sbGVjdGlvbik7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ==