angular-slickgrid 3.3.2 → 4.1.2

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 +180 -188
  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 +1168 -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} +252 -282
  38. package/fesm2015/angular-slickgrid.mjs.map +1 -0
  39. package/fesm2020/angular-slickgrid.mjs +2066 -0
  40. package/fesm2020/angular-slickgrid.mjs.map +1 -0
  41. package/package.json +38 -23
  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,342 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import 'slickgrid/plugins/slick.rowdetailview';
3
- import 'slickgrid/plugins/slick.rowselectionmodel';
4
- import { ApplicationRef, Injectable } from '@angular/core';
5
- import { addToArrayWhenNotExists, castObservableToPromise, RxJsFacade, SharedService, } from '@slickgrid-universal/common';
6
- import { EventPubSubService } from '@slickgrid-universal/event-pub-sub';
7
- import { Observable } from 'rxjs';
8
- import * as DOMPurify_ from 'dompurify';
9
- const DOMPurify = DOMPurify_['default'] || DOMPurify_; // patch to fix rollup to work
10
- import { AngularUtilService } from '../services/angularUtil.service';
11
- import { unsubscribeAllObservables } from '../services/utilities';
12
- const ROW_DETAIL_CONTAINER_PREFIX = 'container_';
13
- const PRELOAD_CONTAINER_PREFIX = 'container_loading';
14
- export class RowDetailViewExtension {
15
- constructor(angularUtilService, appRef, eventPubSubService, sharedService, rxjs) {
16
- this.angularUtilService = angularUtilService;
17
- this.appRef = appRef;
18
- this.eventPubSubService = eventPubSubService;
19
- this.sharedService = sharedService;
20
- this.rxjs = rxjs;
21
- this._views = [];
22
- this._subscriptions = [];
23
- this._eventHandler = new Slick.EventHandler();
24
- }
25
- get datasetIdPropName() {
26
- return this.gridOptions.datasetIdPropertyName || 'id';
27
- }
28
- get eventHandler() {
29
- return this._eventHandler;
30
- }
31
- get gridOptions() {
32
- var _a, _b;
33
- return ((_b = (_a = this.sharedService) === null || _a === void 0 ? void 0 : _a.gridOptions) !== null && _b !== void 0 ? _b : {});
34
- }
35
- get rowDetailViewOptions() {
36
- return this.gridOptions.rowDetailView;
37
- }
38
- addRxJsResource(rxjs) {
39
- this.rxjs = rxjs;
40
- }
41
- /** Dispose of the RowDetailView Extension */
42
- dispose() {
43
- // unsubscribe all SlickGrid events
44
- this._eventHandler.unsubscribeAll();
45
- if (this._addon && this._addon.destroy) {
46
- this._addon.destroy();
47
- }
48
- this._addonOptions = null;
49
- // also unsubscribe all RxJS subscriptions
50
- this._subscriptions = unsubscribeAllObservables(this._subscriptions);
51
- this.disposeAllViewComponents();
52
- }
53
- /** Dispose of all the opened Row Detail Panels Angular View Components */
54
- disposeAllViewComponents() {
55
- this._views.forEach((compRef) => this.disposeViewComponent(compRef));
56
- this._views = [];
57
- }
58
- /**
59
- * Create the plugin before the Grid creation, else it will behave oddly.
60
- * Mostly because the column definitions might change after the grid creation
61
- */
62
- create(columnDefinitions, gridOptions) {
63
- var _a, _b;
64
- if (columnDefinitions && gridOptions) {
65
- if (!gridOptions.rowDetailView) {
66
- throw new Error('The Row Detail View requires options to be passed via the "rowDetailView" property of the Grid Options');
67
- }
68
- if (gridOptions === null || gridOptions === void 0 ? void 0 : gridOptions.rowDetailView) {
69
- if (!this._addon) {
70
- if (typeof gridOptions.rowDetailView.process === 'function') {
71
- // we need to keep the user "process" method and replace it with our own execution method
72
- // we do this because when we get the item detail, we need to call "onAsyncResponse.notify" for the plugin to work
73
- this._userProcessFn = gridOptions.rowDetailView.process; // keep user's process method
74
- gridOptions.rowDetailView.process = (item) => this.onProcessing(item); // replace process method & run our internal one
75
- }
76
- else {
77
- throw new Error('You need to provide a "process" function for the Row Detail Extension to work properly');
78
- }
79
- // load the Preload & RowDetail Templates (could be straight HTML or Angular View/ViewModel)
80
- // when those are Angular View/ViewModel, we need to create View Component & provide the html containers to the Plugin (preTemplate/postTemplate methods)
81
- if (!gridOptions.rowDetailView.preTemplate) {
82
- this._preloadComponent = (_a = gridOptions === null || gridOptions === void 0 ? void 0 : gridOptions.rowDetailView) === null || _a === void 0 ? void 0 : _a.preloadComponent;
83
- gridOptions.rowDetailView.preTemplate = () => DOMPurify.sanitize(`<div class="${PRELOAD_CONTAINER_PREFIX}"></div>`);
84
- }
85
- if (!gridOptions.rowDetailView.postTemplate) {
86
- this._viewComponent = (_b = gridOptions === null || gridOptions === void 0 ? void 0 : gridOptions.rowDetailView) === null || _b === void 0 ? void 0 : _b.viewComponent;
87
- gridOptions.rowDetailView.postTemplate = (itemDetail) => DOMPurify.sanitize(`<div class="${ROW_DETAIL_CONTAINER_PREFIX}${itemDetail[this.datasetIdPropName]}"></div>`);
88
- }
89
- // finally register the Row Detail View Plugin
90
- this._addonOptions = gridOptions.rowDetailView;
91
- this._addon = new Slick.Plugins.RowDetailView(this._addonOptions);
92
- }
93
- const iconColumn = this._addon.getColumnDefinition();
94
- if (typeof iconColumn === 'object') {
95
- iconColumn.excludeFromExport = true;
96
- iconColumn.excludeFromColumnPicker = true;
97
- iconColumn.excludeFromGridMenu = true;
98
- iconColumn.excludeFromQuery = true;
99
- iconColumn.excludeFromHeaderMenu = true;
100
- // column index position in the grid
101
- const columnPosition = gridOptions && gridOptions.rowDetailView && gridOptions.rowDetailView.columnIndexPosition || 0;
102
- if (columnPosition > 0) {
103
- columnDefinitions.splice(columnPosition, 0, iconColumn);
104
- }
105
- else {
106
- columnDefinitions.unshift(iconColumn);
107
- }
108
- }
109
- }
110
- return this._addon;
111
- }
112
- return null;
113
- }
114
- /** Get the instance of the SlickGrid addon (control or plugin). */
115
- getAddonInstance() {
116
- return this._addon;
117
- }
118
- register(rowSelectionPlugin) {
119
- var _a;
120
- if (((_a = this.sharedService) === null || _a === void 0 ? void 0 : _a.slickGrid) && this.sharedService.gridOptions) {
121
- // the plugin has to be created BEFORE the grid (else it behaves oddly), but we can only watch grid events AFTER the grid is created
122
- this.sharedService.slickGrid.registerPlugin(this._addon);
123
- // this also requires the Row Selection Model to be registered as well
124
- if (!rowSelectionPlugin || !this.sharedService.slickGrid.getSelectionModel()) {
125
- rowSelectionPlugin = new Slick.RowSelectionModel(this.sharedService.gridOptions.rowSelectionOptions || { selectActiveRow: true });
126
- this.sharedService.slickGrid.setSelectionModel(rowSelectionPlugin);
127
- }
128
- // hook all events
129
- if (this.sharedService.slickGrid && this.rowDetailViewOptions) {
130
- if (this.rowDetailViewOptions.onExtensionRegistered) {
131
- this.rowDetailViewOptions.onExtensionRegistered(this._addon);
132
- }
133
- this._eventHandler.subscribe(this._addon.onAsyncResponse, (e, args) => {
134
- if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncResponse === 'function') {
135
- this.rowDetailViewOptions.onAsyncResponse(e, args);
136
- }
137
- });
138
- this._eventHandler.subscribe(this._addon.onAsyncEndUpdate, (e, args) => {
139
- // triggers after backend called "onAsyncResponse.notify()"
140
- this.renderViewModel(args && args.item);
141
- if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncEndUpdate === 'function') {
142
- this.rowDetailViewOptions.onAsyncEndUpdate(e, args);
143
- }
144
- });
145
- this._eventHandler.subscribe(this._addon.onAfterRowDetailToggle, (e, args) => {
146
- // display preload template & re-render all the other Detail Views after toggling
147
- // the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event
148
- this.renderPreloadView();
149
- this.renderAllViewComponents();
150
- if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAfterRowDetailToggle === 'function') {
151
- this.rowDetailViewOptions.onAfterRowDetailToggle(e, args);
152
- }
153
- });
154
- this._eventHandler.subscribe(this._addon.onBeforeRowDetailToggle, (e, args) => {
155
- // before toggling row detail, we need to create View Component if it doesn't exist
156
- this.onBeforeRowDetailToggle(e, args);
157
- if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onBeforeRowDetailToggle === 'function') {
158
- this.rowDetailViewOptions.onBeforeRowDetailToggle(e, args);
159
- }
160
- });
161
- this._eventHandler.subscribe(this._addon.onRowBackToViewportRange, (e, args) => {
162
- // when row is back to viewport range, we will re-render the View Component(s)
163
- this.onRowBackToViewportRange(e, args);
164
- if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowBackToViewportRange === 'function') {
165
- this.rowDetailViewOptions.onRowBackToViewportRange(e, args);
166
- }
167
- });
168
- this._eventHandler.subscribe(this._addon.onRowOutOfViewportRange, (e, args) => {
169
- if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowOutOfViewportRange === 'function') {
170
- this.rowDetailViewOptions.onRowOutOfViewportRange(e, args);
171
- }
172
- });
173
- // --
174
- // hook some events needed by the Plugin itself
175
- // we need to redraw the open detail views if we change column position (column reorder)
176
- this._eventHandler.subscribe(this.sharedService.slickGrid.onColumnsReordered, this.redrawAllViewComponents.bind(this));
177
- // on row selection changed, we also need to redraw
178
- if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) {
179
- this._eventHandler.subscribe(this.sharedService.slickGrid.onSelectedRowsChanged, this.redrawAllViewComponents.bind(this));
180
- }
181
- // on sort, all row detail are collapsed so we can dispose of all the Views as well
182
- this._eventHandler.subscribe(this.sharedService.slickGrid.onSort, this.disposeAllViewComponents.bind(this));
183
- // on filter changed, we need to re-render all Views
184
- this._subscriptions.push(this.eventPubSubService.subscribe('onFilterChanged', this.redrawAllViewComponents.bind(this)));
185
- }
186
- return this._addon;
187
- }
188
- return null;
189
- }
190
- /** Redraw (re-render) all the expanded row detail View Components */
191
- redrawAllViewComponents() {
192
- this._views.forEach((compRef) => {
193
- this.redrawViewComponent(compRef);
194
- });
195
- }
196
- /** Render all the expanded row detail View Components */
197
- renderAllViewComponents() {
198
- this._views.forEach((view) => {
199
- if (view && view.dataContext) {
200
- this.renderViewModel(view.dataContext);
201
- }
202
- });
203
- }
204
- /** Redraw the necessary View Component */
205
- redrawViewComponent(createdView) {
206
- const containerElements = document.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${createdView.id}`);
207
- if (containerElements && containerElements.length >= 0) {
208
- this.renderViewModel(createdView.dataContext);
209
- }
210
- }
211
- /** Render (or re-render) the View Component (Row Detail) */
212
- renderPreloadView() {
213
- const containerElements = document.getElementsByClassName(`${PRELOAD_CONTAINER_PREFIX}`);
214
- if (containerElements && containerElements.length >= 0) {
215
- this.angularUtilService.createAngularComponentAppendToDom(this._preloadComponent, containerElements[containerElements.length - 1], true);
216
- }
217
- }
218
- /** Render (or re-render) the View Component (Row Detail) */
219
- renderViewModel(item) {
220
- const containerElements = document.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`);
221
- if (containerElements && containerElements.length > 0) {
222
- const componentOutput = this.angularUtilService.createAngularComponentAppendToDom(this._viewComponent, containerElements[containerElements.length - 1], true);
223
- if (componentOutput && componentOutput.componentRef && componentOutput.componentRef.instance) {
224
- // pass a few properties to the Row Detail template component
225
- Object.assign(componentOutput.componentRef.instance, {
226
- model: item,
227
- addon: this._addon,
228
- grid: this.sharedService.slickGrid,
229
- dataView: this.sharedService.dataView,
230
- parent: this.rowDetailViewOptions && this.rowDetailViewOptions.parent,
231
- });
232
- const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
233
- if (viewObj) {
234
- viewObj.componentRef = componentOutput.componentRef;
235
- }
236
- return viewObj;
237
- }
238
- }
239
- return undefined;
240
- }
241
- // --
242
- // private functions
243
- // ------------------
244
- disposeViewComponent(expandedView) {
245
- const compRef = expandedView === null || expandedView === void 0 ? void 0 : expandedView.componentRef;
246
- if (compRef) {
247
- this.appRef.detachView(compRef.hostView);
248
- if (compRef === null || compRef === void 0 ? void 0 : compRef.destroy) {
249
- compRef.destroy();
250
- }
251
- return expandedView;
252
- }
253
- return null;
254
- }
255
- /**
256
- * notify the onAsyncResponse with the "args.item" (required property)
257
- * the plugin will then use item to populate the row detail panel with the "postTemplate"
258
- * @param item
259
- */
260
- notifyTemplate(item) {
261
- if (this._addon) {
262
- this._addon.onAsyncResponse.notify({ item }, undefined, this);
263
- }
264
- }
265
- /**
266
- * On Processing, we will notify the plugin with the new item detail once backend server call completes
267
- * @param item
268
- */
269
- onProcessing(item) {
270
- return __awaiter(this, void 0, void 0, function* () {
271
- if (item && typeof this._userProcessFn === 'function') {
272
- let awaitedItemDetail;
273
- const userProcessFn = this._userProcessFn(item);
274
- // wait for the "userProcessFn", once resolved we will save it into the "collection"
275
- const response = yield userProcessFn;
276
- if (response.hasOwnProperty(this.datasetIdPropName)) {
277
- awaitedItemDetail = response; // from Promise
278
- }
279
- else if (response && response instanceof Observable || response instanceof Promise) {
280
- awaitedItemDetail = yield castObservableToPromise(this.rxjs, response); // from Angular-http-client
281
- }
282
- if (!awaitedItemDetail || !awaitedItemDetail.hasOwnProperty(this.datasetIdPropName)) {
283
- throw new Error(`[Angular-Slickgrid] could not process the Row Detail, you must make sure that your "process" callback
284
- (a Promise or an HttpClient call returning an Observable) returns an item object that has an "${this.datasetIdPropName}" property`);
285
- }
286
- // notify the plugin with the new item details
287
- this.notifyTemplate(awaitedItemDetail || {});
288
- }
289
- });
290
- }
291
- /**
292
- * Just before the row get expanded or collapsed we will do the following
293
- * First determine if the row is expanding or collapsing,
294
- * if it's expanding we will add it to our View Components reference array if we don't already have it
295
- * or if it's collapsing we will remove it from our View Components reference array
296
- */
297
- onBeforeRowDetailToggle(e, args) {
298
- // expanding
299
- if (args && args.item && args.item.__collapsed) {
300
- // expanding row detail
301
- const viewInfo = {
302
- id: args.item[this.datasetIdPropName],
303
- dataContext: args.item
304
- };
305
- const idPropName = this.gridOptions.datasetIdPropertyName || 'id';
306
- addToArrayWhenNotExists(this._views, viewInfo, idPropName);
307
- }
308
- else {
309
- // collapsing, so dispose of the View/Component
310
- const foundViewIndex = this._views.findIndex((view) => view.id === args.item[this.datasetIdPropName]);
311
- if (foundViewIndex >= 0 && this._views.hasOwnProperty(foundViewIndex)) {
312
- const compRef = this._views[foundViewIndex].componentRef;
313
- if (compRef) {
314
- this.appRef.detachView(compRef.hostView);
315
- compRef.destroy();
316
- }
317
- this._views.splice(foundViewIndex, 1);
318
- }
319
- }
320
- }
321
- /** When Row comes back to Viewport Range, we need to redraw the View */
322
- onRowBackToViewportRange(e, args) {
323
- if (args && args.item) {
324
- this._views.forEach((view) => {
325
- if (view.id === args.item[this.datasetIdPropName]) {
326
- this.redrawViewComponent(view);
327
- }
328
- });
329
- }
330
- }
331
- }
332
- RowDetailViewExtension.decorators = [
333
- { type: Injectable }
334
- ];
335
- RowDetailViewExtension.ctorParameters = () => [
336
- { type: AngularUtilService },
337
- { type: ApplicationRef },
338
- { type: EventPubSubService },
339
- { type: SharedService },
340
- { type: RxJsFacade }
341
- ];
342
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm93RGV0YWlsVmlld0V4dGVuc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvbW9kdWxlcy9hbmd1bGFyLXNsaWNrZ3JpZC9leHRlbnNpb25zL3Jvd0RldGFpbFZpZXdFeHRlbnNpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sdUNBQXVDLENBQUM7QUFDL0MsT0FBTywyQ0FBMkMsQ0FBQztBQUVuRCxPQUFPLEVBQUUsY0FBYyxFQUFnQixVQUFVLEVBQTBCLE1BQU0sZUFBZSxDQUFDO0FBQ2pHLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsdUJBQXVCLEVBR3ZCLFVBQVUsRUFDVixhQUFhLEdBS2QsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN4RSxPQUFPLEVBQUUsVUFBVSxFQUF5QixNQUFNLE1BQU0sQ0FBQztBQUN6RCxPQUFPLEtBQUssVUFBVSxNQUFNLFdBQVcsQ0FBQztBQUN4QyxNQUFNLFNBQVMsR0FBSSxVQUFrQixDQUFDLFNBQVMsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxDQUFDLDhCQUE4QjtBQUc5RixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNyRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUtsRSxNQUFNLDJCQUEyQixHQUFHLFlBQVksQ0FBQztBQUNqRCxNQUFNLHdCQUF3QixHQUFHLG1CQUFtQixDQUFDO0FBU3JELE1BQU0sT0FBTyxzQkFBc0I7SUFXakMsWUFDbUIsa0JBQXNDLEVBQ3RDLE1BQXNCLEVBQ3RCLGtCQUFzQyxFQUN0QyxhQUE0QixFQUNyQyxJQUFpQjtRQUpSLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDdEMsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFDdEIsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtR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WUFuQmxCLGNBQWM7WUFhZCxrQkFBa0I7WUFOekIsYUFBYTtZQURiLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgJ3NsaWNrZ3JpZC9wbHVnaW5zL3NsaWNrLnJvd2RldGFpbHZpZXcnO1xyXG5pbXBvcnQgJ3NsaWNrZ3JpZC9wbHVnaW5zL3NsaWNrLnJvd3NlbGVjdGlvbm1vZGVsJztcclxuXHJcbmltcG9ydCB7IEFwcGxpY2F0aW9uUmVmLCBDb21wb25lbnRSZWYsIEluamVjdGFibGUsIFR5cGUsIFZpZXdDb250YWluZXJSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtcclxuICBhZGRUb0FycmF5V2hlbk5vdEV4aXN0cyxcclxuICBjYXN0T2JzZXJ2YWJsZVRvUHJvbWlzZSxcclxuICBDb2x1bW4sXHJcbiAgUm93RGV0YWlsVmlld0V4dGVuc2lvbiBhcyBVbml2ZXJzYWxSb3dEZXRhaWxWaWV3RXh0ZW5zaW9uLFxyXG4gIFJ4SnNGYWNhZGUsXHJcbiAgU2hhcmVkU2VydmljZSxcclxuICBTbGlja0V2ZW50SGFuZGxlcixcclxuICBTbGlja0dyaWQsXHJcbiAgU2xpY2tOYW1lc3BhY2UsXHJcbiAgU2xpY2tSb3dEZXRhaWxWaWV3LFxyXG59IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL2NvbW1vbic7XHJcbmltcG9ydCB7IEV2ZW50UHViU3ViU2VydmljZSB9IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL2V2ZW50LXB1Yi1zdWInO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0ICogYXMgRE9NUHVyaWZ5XyBmcm9tICdkb21wdXJpZnknO1xyXG5jb25zdCBET01QdXJpZnkgPSAoRE9NUHVyaWZ5XyBhcyBhbnkpWydkZWZhdWx0J10gfHwgRE9NUHVyaWZ5XzsgLy8gcGF0Y2ggdG8gZml4IHJvbGx1cCB0byB3b3JrXHJcblxyXG5pbXBvcnQgeyBHcmlkT3B0aW9uLCBSb3dEZXRhaWxWaWV3IH0gZnJvbSAnLi4vbW9kZWxzL2luZGV4JztcclxuaW1wb3J0IHsgQW5ndWxhclV0aWxTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvYW5ndWxhclV0aWwuc2VydmljZSc7XHJcbmltcG9ydCB7IHVuc3Vic2NyaWJlQWxsT2JzZXJ2YWJsZXMgfSBmcm9tICcuLi9zZXJ2aWNlcy91dGlsaXRpZXMnO1xyXG5cclxuLy8gdXNpbmcgZXh0ZXJuYWwgbm9uLXR5cGVkIGpzIGxpYnJhcmllc1xyXG5kZWNsYXJlIGNvbnN0IFNsaWNrOiBTbGlja05hbWVzcGFjZTtcclxuXHJcbmNvbnN0IFJPV19ERVRBSUxfQ09OVEFJTkVSX1BSRUZJWCA9ICdjb250YWluZXJfJztcclxuY29uc3QgUFJFTE9BRF9DT05UQUlORVJfUFJFRklYID0gJ2NvbnRhaW5lcl9sb2FkaW5nJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlZFZpZXcge1xyXG4gIGlkOiBzdHJpbmcgfCBudW1iZXI7XHJcbiAgZGF0YUNvbnRleHQ6IGFueTtcclxuICBjb21wb25lbnRSZWY/OiBDb21wb25lbnRSZWY8YW55PjtcclxufVxyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgUm93RGV0YWlsVmlld0V4dGVuc2lvbiBpbXBsZW1lbnRzIFVuaXZlcnNhbFJvd0RldGFpbFZpZXdFeHRlbnNpb24ge1xyXG4gIHJvd0RldGFpbENvbnRhaW5lciE6IFZpZXdDb250YWluZXJSZWY7XHJcbiAgcHJpdmF0ZSBfYWRkb246IGFueTtcclxuICBwcml2YXRlIF9hZGRvbk9wdGlvbnMhOiBSb3dEZXRhaWxWaWV3IHwgbnVsbDtcclxuICBwcml2YXRlIF9ldmVudEhhbmRsZXI6IFNsaWNrRXZlbnRIYW5kbGVyO1xyXG4gIHByaXZhdGUgX3ByZWxvYWRDb21wb25lbnQ6IFR5cGU8b2JqZWN0PiB8IHVuZGVmaW5lZDtcclxuICBwcml2YXRlIF92aWV3czogQ3JlYXRlZFZpZXdbXSA9IFtdO1xyXG4gIHByaXZhdGUgX3ZpZXdDb21wb25lbnQhOiBUeXBlPG9iamVjdD47XHJcbiAgcHJpdmF0ZSBfc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcclxuICBwcml2YXRlIF91c2VyUHJvY2Vzc0ZuITogKGl0ZW06IGFueSkgPT4gUHJvbWlzZTxhbnk+IHwgT2JzZXJ2YWJsZTxhbnk+IHwgU3ViamVjdDxhbnk+O1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgYW5ndWxhclV0aWxTZXJ2aWNlOiBBbmd1bGFyVXRpbFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFwcFJlZjogQXBwbGljYXRpb25SZWYsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGV2ZW50UHViU3ViU2VydmljZTogRXZlbnRQdWJTdWJTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBzaGFyZWRTZXJ2aWNlOiBTaGFyZWRTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByeGpzPzogUnhKc0ZhY2FkZSxcclxuICApIHtcclxuICAgIHRoaXMuX2V2ZW50SGFuZGxlciA9IG5ldyBTbGljay5FdmVudEhhbmRsZXIoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0IGRhdGFzZXRJZFByb3BOYW1lKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5kYXRhc2V0SWRQcm9wZXJ0eU5hbWUgfHwgJ2lkJztcclxuICB9XHJcblxyXG4gIGdldCBldmVudEhhbmRsZXIoKTogU2xpY2tFdmVudEhhbmRsZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2V2ZW50SGFuZGxlcjtcclxuICB9XHJcblxyXG4gIGdldCBncmlkT3B0aW9ucygpOiBHcmlkT3B0aW9uIHtcclxuICAgIHJldHVybiAodGhpcy5zaGFyZWRTZXJ2aWNlPy5ncmlkT3B0aW9ucyA/PyB7fSkgYXMgR3JpZE9wdGlvbjtcclxuICB9XHJcblxyXG4gIGdldCByb3dEZXRhaWxWaWV3T3B0aW9ucygpOiBSb3dEZXRhaWxWaWV3IHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXc7XHJcbiAgfVxyXG5cclxuICBhZGRSeEpzUmVzb3VyY2UocnhqczogUnhKc0ZhY2FkZSkge1xyXG4gICAgdGhpcy5yeGpzID0gcnhqcztcclxuICB9XHJcblxyXG4gIC8qKiBEaXNwb3NlIG9mIHRoZSBSb3dEZXRhaWxWaWV3IEV4dGVuc2lvbiAqL1xyXG4gIGRpc3Bvc2UoKSB7XHJcbiAgICAvLyB1bnN1YnNjcmliZSBhbGwgU2xpY2tHcmlkIGV2ZW50c1xyXG4gICAgdGhpcy5fZXZlbnRIYW5kbGVyLnVuc3Vic2NyaWJlQWxsKCk7XHJcblxyXG4gICAgaWYgKHRoaXMuX2FkZG9uICYmIHRoaXMuX2FkZG9uLmRlc3Ryb3kpIHtcclxuICAgICAgdGhpcy5fYWRkb24uZGVzdHJveSgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fYWRkb25PcHRpb25zID0gbnVsbDtcclxuXHJcbiAgICAvLyBhbHNvIHVuc3Vic2NyaWJlIGFsbCBSeEpTIHN1YnNjcmlwdGlvbnNcclxuICAgIHRoaXMuX3N1YnNjcmlwdGlvbnMgPSB1bnN1YnNjcmliZUFsbE9ic2VydmFibGVzKHRoaXMuX3N1YnNjcmlwdGlvbnMpO1xyXG4gICAgdGhpcy5kaXNwb3NlQWxsVmlld0NvbXBvbmVudHMoKTtcclxuICB9XHJcblxyXG4gIC8qKiBEaXNwb3NlIG9mIGFsbCB0aGUgb3BlbmVkIFJvdyBEZXRhaWwgUGFuZWxzIEFuZ3VsYXIgVmlldyBDb21wb25lbnRzICovXHJcbiAgZGlzcG9zZUFsbFZpZXdDb21wb25lbnRzKCkge1xyXG4gICAgdGhpcy5fdmlld3MuZm9yRWFjaCgoY29tcFJlZikgPT4gdGhpcy5kaXNwb3NlVmlld0NvbXBvbmVudChjb21wUmVmKSk7XHJcbiAgICB0aGlzLl92aWV3cyA9IFtdO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIHRoZSBwbHVnaW4gYmVmb3JlIHRoZSBHcmlkIGNyZWF0aW9uLCBlbHNlIGl0IHdpbGwgYmVoYXZlIG9kZGx5LlxyXG4gICAqIE1vc3RseSBiZWNhdXNlIHRoZSBjb2x1bW4gZGVmaW5pdGlvbnMgbWlnaHQgY2hhbmdlIGFmdGVyIHRoZSBncmlkIGNyZWF0aW9uXHJcbiAgICovXHJcbiAgY3JlYXRlKGNvbHVtbkRlZmluaXRpb25zOiBDb2x1bW5bXSwgZ3JpZE9wdGlvbnM6IEdyaWRPcHRpb24pOiBTbGlja1Jvd0RldGFpbFZpZXcgfCBudWxsIHtcclxuICAgIGlmIChjb2x1bW5EZWZpbml0aW9ucyAmJiBncmlkT3B0aW9ucykge1xyXG4gICAgICBpZiAoIWdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBSb3cgRGV0YWlsIFZpZXcgcmVxdWlyZXMgb3B0aW9ucyB0byBiZSBwYXNzZWQgdmlhIHRoZSBcInJvd0RldGFpbFZpZXdcIiBwcm9wZXJ0eSBvZiB0aGUgR3JpZCBPcHRpb25zJyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChncmlkT3B0aW9ucz8ucm93RGV0YWlsVmlldykge1xyXG4gICAgICAgIGlmICghdGhpcy5fYWRkb24pIHtcclxuICAgICAgICAgIGlmICh0eXBlb2YgZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldy5wcm9jZXNzID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgIC8vIHdlIG5lZWQgdG8ga2VlcCB0aGUgdXNlciBcInByb2Nlc3NcIiBtZXRob2QgYW5kIHJlcGxhY2UgaXQgd2l0aCBvdXIgb3duIGV4ZWN1dGlvbiBtZXRob2RcclxuICAgICAgICAgICAgLy8gd2UgZG8gdGhpcyBiZWNhdXNlIHdoZW4gd2UgZ2V0IHRoZSBpdGVtIGRldGFpbCwgd2UgbmVlZCB0byBjYWxsIFwib25Bc3luY1Jlc3BvbnNlLm5vdGlmeVwiIGZvciB0aGUgcGx1Z2luIHRvIHdvcmtcclxuICAgICAgICAgICAgdGhpcy5fdXNlclByb2Nlc3NGbiA9IGdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcucHJvY2VzcyBhcyAoaXRlbTogYW55KSA9PiBPYnNlcnZhYmxlPGFueT47ICAgICAgICAgICAgICAgIC8vIGtlZXAgdXNlcidzIHByb2Nlc3MgbWV0aG9kXHJcbiAgICAgICAgICAgIGdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcucHJvY2VzcyA9IChpdGVtKSA9PiB0aGlzLm9uUHJvY2Vzc2luZyhpdGVtKTsgIC8vIHJlcGxhY2UgcHJvY2VzcyBtZXRob2QgJiBydW4gb3VyIGludGVybmFsIG9uZVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgbmVlZCB0byBwcm92aWRlIGEgXCJwcm9jZXNzXCIgZnVuY3Rpb24gZm9yIHRoZSBSb3cgRGV0YWlsIEV4dGVuc2lvbiB0byB3b3JrIHByb3Blcmx5Jyk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gbG9hZCB0aGUgUHJlbG9hZCAmIFJvd0RldGFpbCBUZW1wbGF0ZXMgKGNvdWxkIGJlIHN0cmFpZ2h0IEhUTUwgb3IgQW5ndWxhciBWaWV3L1ZpZXdNb2RlbClcclxuICAgICAgICAgIC8vIHdoZW4gdGhvc2UgYXJlIEFuZ3VsYXIgVmlldy9WaWV3TW9kZWwsIHdlIG5lZWQgdG8gY3JlYXRlIFZpZXcgQ29tcG9uZW50ICYgcHJvdmlkZSB0aGUgaHRtbCBjb250YWluZXJzIHRvIHRoZSBQbHVnaW4gKHByZVRlbXBsYXRlL3Bvc3RUZW1wbGF0ZSBtZXRob2RzKVxyXG4gICAgICAgICAgaWYgKCFncmlkT3B0aW9ucy5yb3dEZXRhaWxWaWV3LnByZVRlbXBsYXRlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3ByZWxvYWRDb21wb25lbnQgPSBncmlkT3B0aW9ucz8ucm93RGV0YWlsVmlldz8ucHJlbG9hZENvbXBvbmVudDtcclxuICAgICAgICAgICAgZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldy5wcmVUZW1wbGF0ZSA9ICgpID0+IERPTVB1cmlmeS5zYW5pdGl6ZShgPGRpdiBjbGFzcz1cIiR7UFJFTE9BRF9DT05UQUlORVJfUFJFRklYfVwiPjwvZGl2PmApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKCFncmlkT3B0aW9ucy5yb3dEZXRhaWxWaWV3LnBvc3RUZW1wbGF0ZSkge1xyXG4gICAgICAgICAgICB0aGlzLl92aWV3Q29tcG9uZW50ID0gZ3JpZE9wdGlvbnM/LnJvd0RldGFpbFZpZXc/LnZpZXdDb21wb25lbnQ7XHJcbiAgICAgICAgICAgIGdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcucG9zdFRlbXBsYXRlID0gKGl0ZW1EZXRhaWw6IGFueSkgPT4gRE9NUHVyaWZ5LnNhbml0aXplKGA8ZGl2IGNsYXNzPVwiJHtST1dfREVUQUlMX0NPTlRBSU5FUl9QUkVGSVh9JHtpdGVtRGV0YWlsW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdfVwiPjwvZGl2PmApO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIGZpbmFsbHkgcmVnaXN0ZXIgdGhlIFJvdyBEZXRhaWwgVmlldyBQbHVnaW5cclxuICAgICAgICAgIHRoaXMuX2FkZG9uT3B0aW9ucyA9IGdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXc7XHJcbiAgICAgICAgICB0aGlzLl9hZGRvbiA9IG5ldyBTbGljay5QbHVnaW5zLlJvd0RldGFpbFZpZXcodGhpcy5fYWRkb25PcHRpb25zKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgaWNvbkNvbHVtbjogQ29sdW1uID0gdGhpcy5fYWRkb24uZ2V0Q29sdW1uRGVmaW5pdGlvbigpO1xyXG4gICAgICAgIGlmICh0eXBlb2YgaWNvbkNvbHVtbiA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICAgIGljb25Db2x1bW4uZXhjbHVkZUZyb21FeHBvcnQgPSB0cnVlO1xyXG4gICAgICAgICAgaWNvbkNvbHVtbi5leGNsdWRlRnJvbUNvbHVtblBpY2tlciA9IHRydWU7XHJcbiAgICAgICAgICBpY29uQ29sdW1uLmV4Y2x1ZGVGcm9tR3JpZE1lbnUgPSB0cnVlO1xyXG4gICAgICAgICAgaWNvbkNvbHVtbi5leGNsdWRlRnJvbVF1ZXJ5ID0gdHJ1ZTtcclxuICAgICAgICAgIGljb25Db2x1bW4uZXhjbHVkZUZyb21IZWFkZXJNZW51ID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAvLyBjb2x1bW4gaW5kZXggcG9zaXRpb24gaW4gdGhlIGdyaWRcclxuICAgICAgICAgIGNvbnN0IGNvbHVtblBvc2l0aW9uID0gZ3JpZE9wdGlvbnMgJiYgZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldyAmJiBncmlkT3B0aW9ucy5yb3dEZXRhaWxWaWV3LmNvbHVtbkluZGV4UG9zaXRpb24gfHwgMDtcclxuICAgICAgICAgIGlmIChjb2x1bW5Qb3NpdGlvbiA+IDApIHtcclxuICAgICAgICAgICAgY29sdW1uRGVmaW5pdGlvbnMuc3BsaWNlKGNvbHVtblBvc2l0aW9uLCAwLCBpY29uQ29sdW1uKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbHVtbkRlZmluaXRpb25zLnVuc2hpZnQoaWNvbkNvbHVtbik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0aGlzLl9hZGRvbjtcclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqIEdldCB0aGUgaW5zdGFuY2Ugb2YgdGhlIFNsaWNrR3JpZCBhZGRvbiAoY29udHJvbCBvciBwbHVnaW4pLiAqL1xyXG4gIGdldEFkZG9uSW5zdGFuY2UoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fYWRkb247XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlcihyb3dTZWxlY3Rpb25QbHVnaW4/OiBhbnkpIHtcclxuICAgIGlmICh0aGlzLnNoYXJlZFNlcnZpY2U/LnNsaWNrR3JpZCAmJiB0aGlzLnNoYXJlZFNlcnZpY2UuZ3JpZE9wdGlvbnMpIHtcclxuICAgICAgLy8gdGhlIHBsdWdpbiBoYXMgdG8gYmUgY3JlYXRlZCBCRUZPUkUgdGhlIGdyaWQgKGVsc2UgaXQgYmVoYXZlcyBvZGRseSksIGJ1dCB3ZSBjYW4gb25seSB3YXRjaCBncmlkIGV2ZW50cyBBRlRFUiB0aGUgZ3JpZCBpcyBjcmVhdGVkXHJcbiAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5zbGlja0dyaWQucmVnaXN0ZXJQbHVnaW4odGhpcy5fYWRkb24pO1xyXG5cclxuICAgICAgLy8gdGhpcyBhbHNvIHJlcXVpcmVzIHRoZSBSb3cgU2VsZWN0aW9uIE1vZGVsIHRvIGJlIHJlZ2lzdGVyZWQgYXMgd2VsbFxyXG4gICAgICBpZiAoIXJvd1NlbGVjdGlvblBsdWdpbiB8fCAhdGhpcy5zaGFyZWRTZXJ2aWNlLnNsaWNrR3JpZC5nZXRTZWxlY3Rpb25Nb2RlbCgpKSB7XHJcbiAgICAgICAgcm93U2VsZWN0aW9uUGx1Z2luID0gbmV3IFNsaWNrLlJvd1NlbGVjdGlvbk1vZGVsKHRoaXMuc2hhcmVkU2VydmljZS5ncmlkT3B0aW9ucy5yb3dTZWxlY3Rpb25PcHRpb25zIHx8IHsgc2VsZWN0QWN0aXZlUm93OiB0cnVlIH0pO1xyXG4gICAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5zbGlja0dyaWQuc2V0U2VsZWN0aW9uTW9kZWwocm93U2VsZWN0aW9uUGx1Z2luKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gaG9vayBhbGwgZXZlbnRzXHJcbiAgICAgIGlmICh0aGlzLnNoYXJlZFNlcnZpY2Uuc2xpY2tHcmlkICYmIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMpIHtcclxuICAgICAgICBpZiAodGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkV4dGVuc2lvblJlZ2lzdGVyZWQpIHtcclxuICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25FeHRlbnNpb25SZWdpc3RlcmVkKHRoaXMuX2FkZG9uKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLl9hZGRvbi5vbkFzeW5jUmVzcG9uc2UsIChlOiBhbnksIGFyZ3M6IHsgaXRlbTogYW55OyBkZXRhaWxWaWV3OiBSb3dEZXRhaWxWaWV3IH0pID0+IHtcclxuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQXN5bmNSZXNwb25zZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQXN5bmNSZXNwb25zZShlLCBhcmdzKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLl9ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMuX2FkZG9uLm9uQXN5bmNFbmRVcGRhdGUsIChlOiBhbnksIGFyZ3M6IHsgZ3JpZDogU2xpY2tHcmlkOyBpdGVtOiBhbnk7IH0pID0+IHtcclxuICAgICAgICAgIC8vIHRyaWdnZXJzIGFmdGVyIGJhY2tlbmQgY2FsbGVkIFwib25Bc3luY1Jlc3BvbnNlLm5vdGlmeSgpXCJcclxuICAgICAgICAgIHRoaXMucmVuZGVyVmlld01vZGVsKGFyZ3MgJiYgYXJncy5pdGVtKTtcclxuXHJcbiAgICAgICAgICBpZiAodGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucyAmJiB0eXBlb2YgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFzeW5jRW5kVXBkYXRlID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25Bc3luY0VuZFVwZGF0ZShlLCBhcmdzKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLl9ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMuX2FkZG9uLm9uQWZ0ZXJSb3dEZXRhaWxUb2dnbGUsIChlOiBhbnksIGFyZ3M6IHsgZ3JpZDogU2xpY2tHcmlkOyBpdGVtOiBhbnk7IGV4cGFuZGVkUm93czogbnVtYmVyW107IH0pID0+IHtcclxuICAgICAgICAgIC8vIGRpc3BsYXkgcHJlbG9hZCB0ZW1wbGF0ZSAmIHJlLXJlbmRlciBhbGwgdGhlIG90aGVyIERldGFpbCBWaWV3cyBhZnRlciB0b2dnbGluZ1xyXG4gICAgICAgICAgLy8gdGhlIHByZWxvYWQgVmlldyB3aWxsIGV2ZW50dWFsbHkgZ28gYXdheSBvbmNlIHRoZSBkYXRhIGdldHMgbG9hZGVkIGFmdGVyIHRoZSBcIm9uQXN5bmNFbmRVcGRhdGVcIiBldmVudFxyXG4gICAgICAgICAgdGhpcy5yZW5kZXJQcmVsb2FkVmlldygpO1xyXG4gICAgICAgICAgdGhpcy5yZW5kZXJBbGxWaWV3Q29tcG9uZW50cygpO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQWZ0ZXJSb3dEZXRhaWxUb2dnbGUgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFmdGVyUm93RGV0YWlsVG9nZ2xlKGUsIGFyZ3MpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5fYWRkb24ub25CZWZvcmVSb3dEZXRhaWxUb2dnbGUsIChlOiBhbnksIGFyZ3M6IHsgZ3JpZDogU2xpY2tHcmlkOyBpdGVtOiBhbnk7IH0pID0+IHtcclxuICAgICAgICAgIC8vIGJlZm9yZSB0b2dnbGluZyByb3cgZGV0YWlsLCB3ZSBuZWVkIHRvIGNyZWF0ZSBWaWV3IENvbXBvbmVudCBpZiBpdCBkb2Vzbid0IGV4aXN0XHJcbiAgICAgICAgICB0aGlzLm9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlKGUsIGFyZ3MpO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25CZWZvcmVSb3dEZXRhaWxUb2dnbGUoZSwgYXJncyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLl9hZGRvbi5vblJvd0JhY2tUb1ZpZXdwb3J0UmFuZ2UsIChlOiBhbnksIGFyZ3M6IHsgZ3JpZDogU2xpY2tHcmlkOyBpdGVtOiBhbnk7IHJvd0lkOiBudW1iZXI7IHJvd0luZGV4OiBudW1iZXI7IGV4cGFuZGVkUm93czogYW55W107IHJvd0lkc091dE9mVmlld3BvcnQ6IG51bWJlcltdOyB9KSA9PiB7XHJcbiAgICAgICAgICAvLyB3aGVuIHJvdyBpcyBiYWNrIHRvIHZpZXdwb3J0IHJhbmdlLCB3ZSB3aWxsIHJlLXJlbmRlciB0aGUgVmlldyBDb21wb25lbnQocylcclxuICAgICAgICAgIHRoaXMub25Sb3dCYWNrVG9WaWV3cG9ydFJhbmdlKGUsIGFyZ3MpO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uUm93QmFja1RvVmlld3BvcnRSYW5nZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uUm93QmFja1RvVmlld3BvcnRSYW5nZShlLCBhcmdzKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLl9ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMuX2FkZG9uLm9uUm93T3V0T2ZWaWV3cG9ydFJhbmdlLCAoZTogYW55LCBhcmdzOiB7IGdyaWQ6IFNsaWNrR3JpZDsgaXRlbTogYW55OyByb3dJZDogbnVtYmVyOyByb3dJbmRleDogbnVtYmVyOyBleHBhbmRlZFJvd3M6IGFueVtdOyByb3dJZHNPdXRPZlZpZXdwb3J0OiBudW1iZXJbXTsgfSkgPT4ge1xyXG4gICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25Sb3dPdXRPZlZpZXdwb3J0UmFuZ2UgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vblJvd091dE9mVmlld3BvcnRSYW5nZShlLCBhcmdzKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgLy8gLS1cclxuICAgICAgICAvLyBob29rIHNvbWUgZXZlbnRzIG5lZWRlZCBieSB0aGUgUGx1Z2luIGl0c2VsZlxyXG5cclxuICAgICAgICAvLyB3ZSBuZWVkIHRvIHJlZHJhdyB0aGUgb3BlbiBkZXRhaWwgdmlld3MgaWYgd2UgY2hhbmdlIGNvbHVtbiBwb3NpdGlvbiAoY29sdW1uIHJlb3JkZXIpXHJcbiAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLnNoYXJlZFNlcnZpY2Uuc2xpY2tHcmlkLm9uQ29sdW1uc1Jlb3JkZXJlZCwgdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cy5iaW5kKHRoaXMpKTtcclxuXHJcbiAgICAgICAgLy8gb24gcm93IHNlbGVjdGlvbiBjaGFuZ2VkLCB3ZSBhbHNvIG5lZWQgdG8gcmVkcmF3XHJcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUm93U2VsZWN0aW9uIHx8IHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2hlY2tib3hTZWxlY3Rvcikge1xyXG4gICAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLnNoYXJlZFNlcnZpY2Uuc2xpY2tHcmlkLm9uU2VsZWN0ZWRSb3dzQ2hhbmdlZCwgdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cy5iaW5kKHRoaXMpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIG9uIHNvcnQsIGFsbCByb3cgZGV0YWlsIGFyZSBjb2xsYXBzZWQgc28gd2UgY2FuIGRpc3Bvc2Ugb2YgYWxsIHRoZSBWaWV3cyBhcyB3ZWxsXHJcbiAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLnNoYXJlZFNlcnZpY2Uuc2xpY2tHcmlkLm9uU29ydCwgdGhpcy5kaXNwb3NlQWxsVmlld0NvbXBvbmVudHMuYmluZCh0aGlzKSk7XHJcblxyXG4gICAgICAgIC8vIG9uIGZpbHRlciBjaGFuZ2VkLCB3ZSBuZWVkIHRvIHJlLXJlbmRlciBhbGwgVmlld3NcclxuICAgICAgICB0aGlzLl9zdWJzY3JpcHRpb25zLnB1c2goXHJcbiAgICAgICAgICB0aGlzLmV2ZW50UHViU3ViU2VydmljZS5zdWJzY3JpYmUoJ29uRmlsdGVyQ2hhbmdlZCcsIHRoaXMucmVkcmF3QWxsVmlld0NvbXBvbmVudHMuYmluZCh0aGlzKSlcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0aGlzLl9hZGRvbjtcclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqIFJlZHJhdyAocmUtcmVuZGVyKSBhbGwgdGhlIGV4cGFuZGVkIHJvdyBkZXRhaWwgVmlldyBDb21wb25lbnRzICovXHJcbiAgcmVkcmF3QWxsVmlld0NvbXBvbmVudHMoKSB7XHJcbiAgICB0aGlzLl92aWV3cy5mb3JFYWNoKChjb21wUmVmKSA9PiB7XHJcbiAgICAgIHRoaXMucmVkcmF3Vmlld0NvbXBvbmVudChjb21wUmVmKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIFJlbmRlciBhbGwgdGhlIGV4cGFuZGVkIHJvdyBkZXRhaWwgVmlldyBDb21wb25lbnRzICovXHJcbiAgcmVuZGVyQWxsVmlld0NvbXBvbmVudHMoKSB7XHJcbiAgICB0aGlzLl92aWV3cy5mb3JFYWNoKCh2aWV3KSA9PiB7XHJcbiAgICAgIGlmICh2aWV3ICYmIHZpZXcuZGF0YUNvbnRleHQpIHtcclxuICAgICAgICB0aGlzLnJlbmRlclZpZXdNb2RlbCh2aWV3LmRhdGFDb250ZXh0KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKiogUmVkcmF3IHRoZSBuZWNlc3NhcnkgVmlldyBDb21wb25lbnQgKi9cclxuICByZWRyYXdWaWV3Q29tcG9uZW50KGNyZWF0ZWRWaWV3OiBDcmVhdGVkVmlldykge1xyXG4gICAgY29uc3QgY29udGFpbmVyRWxlbWVudHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGAke1JPV19ERVRBSUxfQ09OVEFJTkVSX1BSRUZJWH0ke2NyZWF0ZWRWaWV3LmlkfWApO1xyXG4gICAgaWYgKGNvbnRhaW5lckVsZW1lbnRzICYmIGNvbnRhaW5lckVsZW1lbnRzLmxlbmd0aCA+PSAwKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyVmlld01vZGVsKGNyZWF0ZWRWaWV3LmRhdGFDb250ZXh0KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBSZW5kZXIgKG9yIHJlLXJlbmRlcikgdGhlIFZpZXcgQ29tcG9uZW50IChSb3cgRGV0YWlsKSAqL1xyXG4gIHJlbmRlclByZWxvYWRWaWV3KCkge1xyXG4gICAgY29uc3QgY29udGFpbmVyRWxlbWVudHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGAke1BSRUxPQURfQ09OVEFJTkVSX1BSRUZJWH1gKTtcclxuICAgIGlmIChjb250YWluZXJFbGVtZW50cyAmJiBjb250YWluZXJFbGVtZW50cy5sZW5ndGggPj0gMCkge1xyXG4gICAgICB0aGlzLmFuZ3VsYXJVdGlsU2VydmljZS5jcmVhdGVBbmd1bGFyQ29tcG9uZW50QXBwZW5kVG9Eb20odGhpcy5fcHJlbG9hZENvbXBvbmVudCwgY29udGFpbmVyRWxlbWVudHNbY29udGFpbmVyRWxlbWVudHMubGVuZ3RoIC0gMV0sIHRydWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFJlbmRlciAob3IgcmUtcmVuZGVyKSB0aGUgVmlldyBDb21wb25lbnQgKFJvdyBEZXRhaWwpICovXHJcbiAgcmVuZGVyVmlld01vZGVsKGl0ZW06IGFueSk6IENyZWF0ZWRWaWV3IHwgdW5kZWZpbmVkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lckVsZW1lbnRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShgJHtST1dfREVUQUlMX0NPTlRBSU5FUl9QUkVGSVh9JHtpdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdfWApO1xyXG4gICAgaWYgKGNvbnRhaW5lckVsZW1lbnRzICYmIGNvbnRhaW5lckVsZW1lbnRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgY29uc3QgY29tcG9uZW50T3V0cHV0ID0gdGhpcy5hbmd1bGFyVXRpbFNlcnZpY2UuY3JlYXRlQW5ndWxhckNvbXBvbmVudEFwcGVuZFRvRG9tKHRoaXMuX3ZpZXdDb21wb25lbnQsIGNvbnRhaW5lckVsZW1lbnRzW2NvbnRhaW5lckVsZW1lbnRzLmxlbmd0aCAtIDFdLCB0cnVlKTtcclxuICAgICAgaWYgKGNvbXBvbmVudE91dHB1dCAmJiBjb21wb25lbnRPdXRwdXQuY29tcG9uZW50UmVmICYmIGNvbXBvbmVudE91dHB1dC5jb21wb25lbnRSZWYuaW5zdGFuY2UpIHtcclxuICAgICAgICAvLyBwYXNzIGEgZmV3IHByb3BlcnRpZXMgdG8gdGhlIFJvdyBEZXRhaWwgdGVtcGxhdGUgY29tcG9uZW50XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbihjb21wb25lbnRPdXRwdXQuY29tcG9uZW50UmVmLmluc3RhbmNlLCB7XHJcbiAgICAgICAgICBtb2RlbDogaXRlbSxcclxuICAgICAgICAgIGFkZG9uOiB0aGlzLl9hZGRvbixcclxuICAgICAgICAgIGdyaWQ6IHRoaXMuc2hhcmVkU2VydmljZS5zbGlja0dyaWQsXHJcbiAgICAgICAgICBkYXRhVmlldzogdGhpcy5zaGFyZWRTZXJ2aWNlLmRhdGFWaWV3LFxyXG4gICAgICAgICAgcGFyZW50OiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMucGFyZW50LFxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBjb25zdCB2aWV3T2JqID0gdGhpcy5fdmlld3MuZmluZChvYmogPT4gb2JqLmlkID09PSBpdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdKTtcclxuICAgICAgICBpZiAodmlld09iaikge1xyXG4gICAgICAgICAgdmlld09iai5jb21wb25lbnRSZWYgPSBjb21wb25lbnRPdXRwdXQuY29tcG9uZW50UmVmO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdmlld09iajtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8vIC0tXHJcbiAgLy8gcHJpdmF0ZSBmdW5jdGlvbnNcclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgcHJpdmF0ZSBkaXNwb3NlVmlld0NvbXBvbmVudChleHBhbmRlZFZpZXc6IENyZWF0ZWRWaWV3KSB7XHJcbiAgICBjb25zdCBjb21wUmVmID0gZXhwYW5kZWRWaWV3Py5jb21wb25lbnRSZWY7XHJcbiAgICBpZiAoY29tcFJlZikge1xyXG4gICAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KGNvbXBSZWYuaG9zdFZpZXcpO1xyXG4gICAgICBpZiAoY29tcFJlZj8uZGVzdHJveSkge1xyXG4gICAgICAgIGNvbXBSZWYuZGVzdHJveSgpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBleHBhbmRlZFZpZXc7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIG5vdGlmeSB0aGUgb25Bc3luY1Jlc3BvbnNlIHdpdGggdGhlIFwiYXJncy5pdGVtXCIgKHJlcXVpcmVkIHByb3BlcnR5KVxyXG4gICAqIHRoZSBwbHVnaW4gd2lsbCB0aGVuIHVzZSBpdGVtIHRvIHBvcHVsYXRlIHRoZSByb3cgZGV0YWlsIHBhbmVsIHdpdGggdGhlIFwicG9zdFRlbXBsYXRlXCJcclxuICAgKiBAcGFyYW0gaXRlbVxyXG4gICAqL1xyXG4gIHByaXZhdGUgbm90aWZ5VGVtcGxhdGUoaXRlbTogYW55KSB7XHJcbiAgICBpZiAodGhpcy5fYWRkb24pIHtcclxuICAgICAgdGhpcy5fYWRkb24ub25Bc3luY1Jlc3BvbnNlLm5vdGlmeSh7IGl0ZW0gfSwgdW5kZWZpbmVkLCB0aGlzKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE9uIFByb2Nlc3NpbmcsIHdlIHdpbGwgbm90aWZ5IHRoZSBwbHVnaW4gd2l0aCB0aGUgbmV3IGl0ZW0gZGV0YWlsIG9uY2UgYmFja2VuZCBzZXJ2ZXIgY2FsbCBjb21wbGV0ZXNcclxuICAgKiBAcGFyYW0gaXRlbVxyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgb25Qcm9jZXNzaW5nKGl0ZW06IGFueSkge1xyXG4gICAgaWYgKGl0ZW0gJiYgdHlwZW9mIHRoaXMuX3VzZXJQcm9jZXNzRm4gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgbGV0IGF3YWl0ZWRJdGVtRGV0YWlsOiBhbnk7XHJcbiAgICAgIGNvbnN0IHVzZXJQcm9jZXNzRm4gPSB0aGlzLl91c2VyUHJvY2Vzc0ZuKGl0ZW0pO1xyXG5cclxuICAgICAgLy8gd2FpdCBmb3IgdGhlIFwidXNlclByb2Nlc3NGblwiLCBvbmNlIHJlc29sdmVkIHdlIHdpbGwgc2F2ZSBpdCBpbnRvIHRoZSBcImNvbGxlY3Rpb25cIlxyXG4gICAgICBjb25zdCByZXNwb25zZTogYW55IHwgYW55W10gPSBhd2FpdCB1c2VyUHJvY2Vzc0ZuO1xyXG5cclxuICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KHRoaXMuZGF0YXNldElkUHJvcE5hbWUpKSB7XHJcbiAgICAgICAgYXdhaXRlZEl0ZW1EZXRhaWwgPSByZXNwb25zZTsgLy8gZnJvbSBQcm9taXNlXHJcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UgaW5zdGFuY2VvZiBPYnNlcnZhYmxlIHx8IHJlc3BvbnNlIGluc3RhbmNlb2YgUHJvbWlzZSkge1xyXG4gICAgICAgIGF3YWl0ZWRJdGVtRGV0YWlsID0gYXdhaXQgY2FzdE9ic2VydmFibGVUb1Byb21pc2UodGhpcy5yeGpzIGFzIFJ4SnNGYWNhZGUsIHJlc3BvbnNlKTsgLy8gZnJvbSBBbmd1bGFyLWh0dHAtY2xpZW50XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICghYXdhaXRlZEl0ZW1EZXRhaWwgfHwgIWF3YWl0ZWRJdGVtRGV0YWlsLmhhc093blByb3BlcnR5KHRoaXMuZGF0YXNldElkUHJvcE5hbWUpKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbQW5ndWxhci1TbGlja2dyaWRdIGNvdWxkIG5vdCBwcm9jZXNzIHRoZSBSb3cgRGV0YWlsLCB5b3UgbXVzdCBtYWtlIHN1cmUgdGhhdCB5b3VyIFwicHJvY2Vzc1wiIGNhbGxiYWNrXHJcbiAgICAgICAgICAoYSBQcm9taXNlIG9yIGFuIEh0dHBDbGllbnQgY2FsbCByZXR1cm5pbmcgYW4gT2JzZXJ2YWJsZSkgcmV0dXJucyBhbiBpdGVtIG9iamVjdCB0aGF0IGhhcyBhbiBcIiR7dGhpcy5kYXRhc2V0SWRQcm9wTmFtZX1cIiBwcm9wZXJ0eWApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBub3RpZnkgdGhlIHBsdWdpbiB3aXRoIHRoZSBuZXcgaXRlbSBkZXRhaWxzXHJcbiAgICAgIHRoaXMubm90aWZ5VGVtcGxhdGUoYXdhaXRlZEl0ZW1EZXRhaWwgfHwge30pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSnVzdCBiZWZvcmUgdGhlIHJvdyBnZXQgZXhwYW5kZWQgb3IgY29sbGFwc2VkIHdlIHdpbGwgZG8gdGhlIGZvbGxvd2luZ1xyXG4gICAqIEZpcnN0IGRldGVybWluZSBpZiB0aGUgcm93IGlzIGV4cGFuZGluZyBvciBjb2xsYXBzaW5nLFxyXG4gICAqIGlmIGl0J3MgZXhwYW5kaW5nIHdlIHdpbGwgYWRkIGl0IHRvIG91ciBWaWV3IENvbXBvbmVudHMgcmVmZXJlbmNlIGFycmF5IGlmIHdlIGRvbid0IGFscmVhZHkgaGF2ZSBpdFxyXG4gICAqIG9yIGlmIGl0J3MgY29sbGFwc2luZyB3ZSB3aWxsIHJlbW92ZSBpdCBmcm9tIG91ciBWaWV3IENvbXBvbmVudHMgcmVmZXJlbmNlIGFycmF5XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBvbkJlZm9yZVJvd0RldGFpbFRvZ2dsZShlOiBFdmVudCwgYXJnczogeyBncmlkOiBTbGlja0dyaWQ7IGl0ZW06IGFueTsgfSkge1xyXG4gICAgLy8gZXhwYW5kaW5nXHJcbiAgICBpZiAoYXJncyAmJiBhcmdzLml0ZW0gJiYgYXJncy5pdGVtLl9fY29sbGFwc2VkKSB7XHJcbiAgICAgIC8vIGV4cGFuZGluZyByb3cgZGV0YWlsXHJcbiAgICAgIGNvbnN0IHZpZXdJbmZvOiBDcmVhdGVkVmlldyA9IHtcclxuICAgICAgICBpZDogYXJncy5pdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdLFxyXG4gICAgICAgIGRhdGFDb250ZXh0OiBhcmdzLml0ZW1cclxuICAgICAgfTtcclxuICAgICAgY29uc3QgaWRQcm9wTmFtZSA9IHRoaXMuZ3JpZE9wdGlvbnMuZGF0YXNldElkUHJvcGVydHlOYW1lIHx8ICdpZCc7XHJcbiAgICAgIGFkZFRvQXJyYXlXaGVuTm90RXhpc3RzKHRoaXMuX3ZpZXdzLCB2aWV3SW5mbywgaWRQcm9wTmFtZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBjb2xsYXBzaW5nLCBzbyBkaXNwb3NlIG9mIHRoZSBWaWV3L0NvbXBvbmVudFxyXG4gICAgICBjb25zdCBmb3VuZFZpZXdJbmRleCA9IHRoaXMuX3ZpZXdzLmZpbmRJbmRleCgodmlldzogQ3JlYXRlZFZpZXcpID0+IHZpZXcuaWQgPT09IGFyZ3MuaXRlbVt0aGlzLmRhdGFzZXRJZFByb3BOYW1lXSk7XHJcbiAgICAgIGlmIChmb3VuZFZpZXdJbmRleCA+PSAwICYmIHRoaXMuX3ZpZXdzLmhhc093blByb3BlcnR5KGZvdW5kVmlld0luZGV4KSkge1xyXG4gICAgICAgIGNvbnN0IGNvbXBSZWYgPSB0aGlzLl92aWV3c1tmb3VuZFZpZXdJbmRleF0uY29tcG9uZW50UmVmO1xyXG4gICAgICAgIGlmIChjb21wUmVmKSB7XHJcbiAgICAgICAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KGNvbXBSZWYuaG9zdFZpZXcpO1xyXG4gICAgICAgICAgY29tcFJlZi5kZXN0cm95KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuX3ZpZXdzLnNwbGljZShmb3VuZFZpZXdJbmRleCwgMSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBXaGVuIFJvdyBjb21lcyBiYWNrIHRvIFZpZXdwb3J0IFJhbmdlLCB3ZSBuZWVkIHRvIHJlZHJhdyB0aGUgVmlldyAqL1xyXG4gIHByaXZhdGUgb25Sb3dCYWNrVG9WaWV3cG9ydFJhbmdlKGU6IEV2ZW50LCBhcmdzOiB7IGdyaWQ6IFNsaWNrR3JpZDsgaXRlbTogYW55OyByb3dJZDogbnVtYmVyOyByb3dJbmRleDogbnVtYmVyOyBleHBhbmRlZFJvd3M6IGFueVtdOyByb3dJZHNPdXRPZlZpZXdwb3J0OiBudW1iZXJbXTsgfSkge1xyXG4gICAgaWYgKGFyZ3MgJiYgYXJncy5pdGVtKSB7XHJcbiAgICAgIHRoaXMuX3ZpZXdzLmZvckVhY2goKHZpZXcpID0+IHtcclxuICAgICAgICBpZiAodmlldy5pZCA9PT0gYXJncy5pdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdKSB7XHJcbiAgICAgICAgICB0aGlzLnJlZHJhd1ZpZXdDb21wb25lbnQodmlldyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19