UNPKG

angular-slickgrid

Version:

Slickgrid components made available in Angular

301 lines 51.6 kB
import { addToArrayWhenNotExists, castObservableToPromise, createDomElement, SlickEventData, SlickRowSelectionModel, unsubscribeAll, } from '@slickgrid-universal/common'; import { SlickRowDetailView as UniversalSlickRowDetailView } from '@slickgrid-universal/row-detail-view-plugin'; import { Observable } from 'rxjs'; const ROW_DETAIL_CONTAINER_PREFIX = 'container_'; const PRELOAD_CONTAINER_PREFIX = 'container_loading'; export class SlickRowDetailView extends UniversalSlickRowDetailView { angularUtilService; appRef; eventPubSubService; gridContainerElement; rxjs; rowDetailContainer; _preloadComponent; _preloadCompRef; _views = []; _viewComponent; _subscriptions = []; _userProcessFn; constructor(angularUtilService, appRef, eventPubSubService, gridContainerElement, rxjs) { super(eventPubSubService); this.angularUtilService = angularUtilService; this.appRef = appRef; this.eventPubSubService = eventPubSubService; this.gridContainerElement = gridContainerElement; this.rxjs = rxjs; } get addonOptions() { return this.getOptions(); } get datasetIdPropName() { return this.gridOptions.datasetIdPropertyName || 'id'; } /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions() { return (this._grid?.getOptions() || {}); } get rowDetailViewOptions() { return this.gridOptions.rowDetailView; } addRxJsResource(rxjs) { this.rxjs = rxjs; } /** Dispose of the RowDetailView Extension */ dispose() { this.disposeAllViewComponents(); this._subscriptions = unsubscribeAll(this._subscriptions); // also unsubscribe all RxJS subscriptions super.dispose(); } /** Dispose of all the opened Row Detail Panels Angular View Components */ disposeAllViewComponents() { do { const view = this._views.pop(); if (view) { this.disposeView(view); } } while (this._views.length > 0); } /** Get the instance of the SlickGrid addon (control or plugin). */ getAddonInstance() { return this; } init(grid) { this._grid = grid; super.init(this._grid); this.register(grid?.getSelectionModel()); } /** * Create the plugin before the Grid creation, else it will behave oddly. * Mostly because the column definitions might change after the grid creation */ register(rowSelectionPlugin) { if (typeof this.gridOptions.rowDetailView?.process === 'function') { // we need to keep the user "process" method and replace it with our own execution method // we do this because when we get the item detail, we need to call "onAsyncResponse.notify" for the plugin to work this._userProcessFn = this.gridOptions.rowDetailView.process; // keep user's process method this.addonOptions.process = (item) => this.onProcessing(item); // replace process method & run our internal one } else { throw new Error('[Angular-Slickgrid] You need to provide a "process" function for the Row Detail Extension to work properly'); } if (this._grid && this.gridOptions?.rowDetailView) { // load the Preload & RowDetail Templates (could be straight HTML or Angular View/ViewModel) // when those are Angular View/ViewModel, we need to create View Component & provide the html containers to the Plugin (preTemplate/postTemplate methods) if (!this.gridOptions.rowDetailView.preTemplate) { this._preloadComponent = this.gridOptions?.rowDetailView?.preloadComponent; this.addonOptions.preTemplate = () => createDomElement('div', { className: `${PRELOAD_CONTAINER_PREFIX}` }); } if (!this.gridOptions.rowDetailView.postTemplate) { this._viewComponent = this.gridOptions?.rowDetailView?.viewComponent; this.addonOptions.postTemplate = (itemDetail) => createDomElement('div', { className: `${ROW_DETAIL_CONTAINER_PREFIX}${itemDetail[this.datasetIdPropName]}` }); } // this also requires the Row Selection Model to be registered as well if (!rowSelectionPlugin || !this._grid.getSelectionModel()) { rowSelectionPlugin = new SlickRowSelectionModel(this.gridOptions.rowSelectionOptions || { selectActiveRow: true }); this._grid.setSelectionModel(rowSelectionPlugin); } // hook all events if (this._grid && this.rowDetailViewOptions) { if (this.rowDetailViewOptions.onExtensionRegistered) { this.rowDetailViewOptions.onExtensionRegistered(this); } this.eventHandler.subscribe(this.onAsyncResponse, (event, args) => { if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncResponse === 'function') { this.rowDetailViewOptions.onAsyncResponse(event, args); } }); this.eventHandler.subscribe(this.onAsyncEndUpdate, (e, args) => { // destroy preload if exists this._preloadCompRef?.destroy(); // triggers after backend called "onAsyncResponse.notify()" this.renderViewModel(args?.item); if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncEndUpdate === 'function') { this.rowDetailViewOptions.onAsyncEndUpdate(e, args); } }); this.eventHandler.subscribe(this.onAfterRowDetailToggle, (e, args) => { // display preload template & re-render all the other Detail Views after toggling // the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event this.renderPreloadView(); if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAfterRowDetailToggle === 'function') { this.rowDetailViewOptions.onAfterRowDetailToggle(e, args); } }); this.eventHandler.subscribe(this.onBeforeRowDetailToggle, (e, args) => { // before toggling row detail, we need to create View Component if it doesn't exist this.handleOnBeforeRowDetailToggle(e, args); if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onBeforeRowDetailToggle === 'function') { return this.rowDetailViewOptions.onBeforeRowDetailToggle(e, args); } return true; }); this.eventHandler.subscribe(this.onRowBackToViewportRange, (e, args) => { // when row is back to viewport range, we will re-render the View Component(s) this.handleOnRowBackToViewportRange(e, args); if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowBackToViewportRange === 'function') { this.rowDetailViewOptions.onRowBackToViewportRange(e, args); } }); this._eventHandler.subscribe(this.onBeforeRowOutOfViewportRange, (event, args) => { if (typeof this.rowDetailViewOptions?.onBeforeRowOutOfViewportRange === 'function') { this.rowDetailViewOptions.onBeforeRowOutOfViewportRange(event, args); } this.disposeViewByItem(args.item); }); this.eventHandler.subscribe(this.onRowOutOfViewportRange, (e, args) => { if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowOutOfViewportRange === 'function') { this.rowDetailViewOptions.onRowOutOfViewportRange(e, args); } }); // -- // hook some events needed by the Plugin itself // we need to redraw the open detail views if we change column position (column reorder) this.eventHandler.subscribe(this._grid.onColumnsReordered, this.redrawAllViewComponents.bind(this, false)); // on row selection changed, we also need to redraw if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) { this.eventHandler.subscribe(this._grid.onSelectedRowsChanged, this.redrawAllViewComponents.bind(this, false)); } // on sort, all row detail are collapsed so we can dispose of all the Views as well this.eventHandler.subscribe(this._grid.onSort, this.disposeAllViewComponents.bind(this)); // redraw all Views whenever certain events are triggered this._subscriptions.push(this.eventPubSubService?.subscribe(['onFilterChanged', 'onGridMenuColumnsChanged', 'onColumnPickerColumnsChanged'], this.redrawAllViewComponents.bind(this, false)), this.eventPubSubService?.subscribe(['onGridMenuClearAllFilters', 'onGridMenuClearAllSorting'], () => window.setTimeout(() => this.redrawAllViewComponents()))); } } return this; } /** Redraw (re-render) all the expanded row detail View Components */ redrawAllViewComponents(forceRedraw = false) { this.resetRenderedRows(); this._views.forEach((view) => { if (!view.rendered || forceRedraw) { forceRedraw && view.componentRef?.destroy(); this.redrawViewComponent(view); } }); } /** Redraw the necessary View Component */ redrawViewComponent(createdView) { const containerElement = this.gridContainerElement.querySelector(`.${ROW_DETAIL_CONTAINER_PREFIX}${createdView.id}`); if (containerElement) { this.renderViewModel(createdView.dataContext); } } /** Render (or re-render) the View Component (Row Detail) */ renderPreloadView() { const containerElement = this.gridContainerElement.querySelector(`.${PRELOAD_CONTAINER_PREFIX}`); if (this._preloadComponent && containerElement) { const preloadComp = this.angularUtilService.createAngularComponentAppendToDom(this._preloadComponent, containerElement, {}, { sanitizer: this._grid.sanitizeHtmlString }); this._preloadCompRef = preloadComp.componentRef; } } /** Render (or re-render) the View Component (Row Detail) */ renderViewModel(item) { const containerElement = this.gridContainerElement.querySelector(`.${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`); if (this._viewComponent && containerElement) { // render row detail const componentOutput = this.angularUtilService.createAngularComponentAppendToDom(this._viewComponent, containerElement, { model: item, addon: this, grid: this._grid, dataView: this.dataView, parent: this.rowDetailViewOptions?.parent, }, { sanitizer: this._grid.sanitizeHtmlString, }); if (componentOutput?.componentRef) { const viewObj = this._views.find((obj) => obj.id === item[this.datasetIdPropName]); if (viewObj) { viewObj.componentRef = componentOutput.componentRef; viewObj.rendered = true; } return viewObj; } } return undefined; } // -- // protected functions // ------------------ disposeViewByItem(item, removeFromArray = false) { const foundViewIndex = this._views.findIndex((view) => view.id === item[this.datasetIdPropName]); if (foundViewIndex >= 0) { this.disposeView(this._views[foundViewIndex]); if (removeFromArray) { this._views.splice(foundViewIndex, 1); } } } disposeView(expandedView) { expandedView.rendered = false; const compRef = expandedView?.componentRef; if (compRef) { this.appRef.detachView(compRef.hostView); if (typeof compRef?.destroy === 'function') { compRef.destroy(); } return expandedView; } } /** * notify the onAsyncResponse with the "args.item" (required property) * the plugin will then use item to populate the row detail panel with the "postTemplate" * @param item */ notifyTemplate(item) { this.onAsyncResponse.notify({ item, itemDetail: item }, new SlickEventData(), this); } /** * On Processing, we will notify the plugin with the new item detail once backend server call completes * @param item */ async onProcessing(item) { if (item && typeof this._userProcessFn === 'function') { let awaitedItemDetail; const userProcessFn = this._userProcessFn(item); // wait for the "userProcessFn", once resolved we will save it into the "collection" const response = await userProcessFn; if (this.datasetIdPropName in response) { awaitedItemDetail = response; // from Promise } else if ((response && response instanceof Observable) || response instanceof Promise) { awaitedItemDetail = await castObservableToPromise(this.rxjs, response); // from Angular-http-client } if (!awaitedItemDetail || !(this.datasetIdPropName in awaitedItemDetail)) { throw new Error('[Angular-Slickgrid] could not process the Row Detail, you must make sure that your "process" callback ' + `returns an item object that has an "${this.datasetIdPropName}" property`); } // notify the plugin with the new item details this.notifyTemplate(awaitedItemDetail || {}); } } /** * Just before the row get expanded or collapsed we will do the following * First determine if the row is expanding or collapsing, * if it's expanding we will add it to our View Components reference array if we don't already have it * or if it's collapsing we will remove it from our View Components reference array */ handleOnBeforeRowDetailToggle(_e, args) { // expanding if (args?.item?.__collapsed) { // expanding row detail const viewInfo = { id: args.item[this.datasetIdPropName], dataContext: args.item, rendered: false, }; addToArrayWhenNotExists(this._views, viewInfo, this.datasetIdPropName); } else { // collapsing, so dispose of the View/Component this.disposeViewByItem(args.item, true); } } /** When Row comes back to Viewport Range, we need to redraw the View */ handleOnRowBackToViewportRange(_e, args) { const viewModel = this._views.find((x) => x.id === args.rowId); if (viewModel && !viewModel.rendered) { this.redrawViewComponent(viewModel); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpY2tSb3dEZXRhaWxWaWV3LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9tb2R1bGVzL2FuZ3VsYXItc2xpY2tncmlkL2V4dGVuc2lvbnMvc2xpY2tSb3dEZXRhaWxWaWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsdUJBQXVCLEVBQ3ZCLGdCQUFnQixFQUNoQixjQUFjLEVBQ2Qsc0JBQXNCLEVBQ3RCLGNBQWMsR0FDZixNQUFNLDZCQUE2QixDQUFDO0FBRXJDLE9BQU8sRUFBRSxrQkFBa0IsSUFBSSwyQkFBMkIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2hILE9BQU8sRUFBRSxVQUFVLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBS2hELE1BQU0sMkJBQTJCLEdBQUcsWUFBWSxDQUFDO0FBQ2pELE1BQU0sd0JBQXdCLEdBQUcsbUJBQW1CLENBQUM7QUFTckQsTUFBTSxPQUFPLGtCQUFtQixTQUFRLDJCQUEyQjtJQVU1QztJQUNBO0lBQ0E7SUFDQTtJQUNUO0lBYlosa0JBQWtCLENBQW9CO0lBQzVCLGlCQUFpQixDQUEyQjtJQUM1QyxlQUFlLENBQXFCO0lBQ3BDLE1BQU0sR0FBa0IsRUFBRSxDQUFDO0lBQzNCLGNBQWMsQ0FBZ0I7SUFDOUIsY0FBYyxHQUF3QixFQUFFLENBQUM7SUFDekMsY0FBYyxDQUFnRTtJQUV4RixZQUNxQixrQkFBc0MsRUFDdEMsTUFBc0IsRUFDdEIsa0JBQXNDLEVBQ3RDLG9CQUFvQyxFQUM3QyxJQUFpQjtRQUUzQixLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQU5QLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDdEMsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFDdEIsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUN0Qyx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQWdCO1FBQzdDLFNBQUksR0FBSixJQUFJLENBQWE7SUFHN0IsQ0FBQztJQUVELElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxJQUFjLGlCQUFpQjtRQUM3QixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMscUJBQXFCLElBQUksSUFBSSxDQUFDO0lBQ3hELENBQUM7SUFFRCxpRUFBaUU7SUFDakUsSUFBSSxXQUFXO1FBQ2IsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFlLENBQUM7SUFDeEQsQ0FBQztJQUVELElBQUksb0JBQW9CO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUM7SUFDeEMsQ0FBQztJQUVELGVBQWUsQ0FBQyxJQUFnQjtRQUM5QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNuQixDQUFDO0lBRUQsNkNBQTZDO0lBQzdDLE9BQU87UUFDTCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQywwQ0FBMEM7UUFDckcsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsd0JBQXdCO1FBQ3RCLEdBQUcsQ0FBQztZQUNGLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDL0IsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDVCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3pCLENBQUM7UUFDSCxDQUFDLFFBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0lBQ25DLENBQUM7SUFFRCxtRUFBbUU7SUFDbkUsZ0JBQWdCO1FBQ2QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBSSxDQUFDLElBQWU7UUFDbEIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDbEIsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQTRCLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsUUFBUSxDQUFDLGtCQUEyQztRQUNsRCxJQUFJLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEVBQUUsT0FBTyxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQ2xFLHlGQUF5RjtZQUN6RixrSEFBa0g7WUFDbEgsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxPQUFzQyxDQUFDLENBQUMsNkJBQTZCO1lBQzFILElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsZ0RBQWdEO1FBQ2pILENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLEtBQUssQ0FDYiw0R0FBNEcsQ0FDN0csQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsQ0FBQztZQUNsRCw0RkFBNEY7WUFDNUYseUpBQXlKO1lBQ3pKLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDaEQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixDQUFDO2dCQUMzRSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyx3QkFBd0IsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUM5RyxDQUFDO1lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNqRCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLGFBQWEsQ0FBQztnQkFDckUsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxVQUFlLEVBQUUsRUFBRSxDQUNuRCxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRywyQkFBMkIsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbEgsQ0FBQztZQUVELHNFQUFzRTtZQUN0RSxJQUFJLENBQUMsa0JBQWtCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQztnQkFDM0Qsa0JBQWtCLEdBQUcsSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLG1CQUFtQixJQUFJLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ25ILElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUNuRCxDQUFDO1lBRUQsa0JBQWtCO1lBQ2xCLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxJQUFJLENBQUMsb0JBQW9CLENBQUMscUJBQXFCLEVBQUUsQ0FBQztvQkFDcEQsSUFBSSxDQUFDLG9CQUFvQixDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN4RCxDQUFDO2dCQUVELElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7b0JBQ2hFLElBQUksSUFBSSxDQUFDLG9CQUFvQixJQUFJLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLGVBQWUsS0FBSyxVQUFVLEVBQUUsQ0FBQzt3QkFDakcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBQ3pELENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFO29CQUM3RCw0QkFBNEI7b0JBQzVCLElBQUksQ0FBQyxlQUFlLEVBQUUsT0FBTyxFQUFFLENBQUM7b0JBRWhDLDJEQUEyRDtvQkFDM0QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBRWpDLElBQUksSUFBSSxDQUFDLG9CQUFvQixJQUFJLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLGdCQUFnQixLQUFLLFVBQVUsRUFBRSxDQUFDO3dCQUNsRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO29CQUN0RCxDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUN6QixJQUFJLENBQUMsc0JBQXNCLEVBQzNCLENBQUMsQ0FBTSxFQUFFLElBQTBFLEVBQUUsRUFBRTtvQkFDckYsaUZBQWlGO29CQUNqRix3R0FBd0c7b0JBQ3hHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO29CQUV6QixJQUFJLElBQUksQ0FBQyxvQkFBb0IsSUFBSSxPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxzQkFBc0IsS0FBSyxVQUFVLEVBQUUsQ0FBQzt3QkFDeEcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLHNCQUFzQixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFDNUQsQ0FBQztnQkFDSCxDQUFDLENBQ0YsQ0FBQztnQkFFRixJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUU7b0JBQ3BFLG1GQUFtRjtvQkFDbkYsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFFNUMsSUFBSSxJQUFJLENBQUMsb0JBQW9CLElBQUksT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsdUJBQXVCLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQ3pHLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLHVCQUF1QixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFDcEUsQ0FBQztvQkFDRCxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDLENBQUMsQ0FBQztnQkFFSCxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUU7b0JBQ3JFLDhFQUE4RTtvQkFDOUUsSUFBSSxDQUFDLDhCQUE4QixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFFN0MsSUFBSSxJQUFJLENBQUMsb0JBQW9CLElBQUksT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsd0JBQXdCLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQzFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBQzlELENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO29CQUMvRSxJQUFJLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixFQUFFLDZCQUE2QixLQUFLLFVBQVUsRUFBRSxDQUFDO3dCQUNuRixJQUFJLENBQUMsb0JBQW9CLENBQUMsNkJBQTZCLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO29CQUN2RSxDQUFDO29CQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3BDLENBQUMsQ0FBQyxDQUFDO2dCQUVILElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRTtvQkFDcEUsSUFBSSxJQUFJLENBQUMsb0JBQW9CLElBQUksT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsdUJBQXVCLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQ3pHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBQzdELENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsS0FBSztnQkFDTCwrQ0FBK0M7Z0JBRS9DLHdGQUF3RjtnQkFDeEYsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUUzRyxtREFBbUQ7Z0JBQ25ELElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLHNCQUFzQixFQUFFLENBQUM7b0JBQ25GLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMscUJBQXFCLEVBQUUsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDaEgsQ0FBQztnQkFFRCxtRkFBbUY7Z0JBQ25GLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFFekYseURBQXlEO2dCQUN6RCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FDdEIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFNBQVMsQ0FDaEMsQ0FBQyxpQkFBaUIsRUFBRSwwQkFBMEIsRUFBRSw4QkFBOEIsQ0FBQyxFQUMvRSxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FDL0MsRUFDRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsU0FBUyxDQUFDLENBQUMsMkJBQTJCLEVBQUUsMkJBQTJCLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FDbEcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxDQUN4RCxDQUNGLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELHFFQUFxRTtJQUNyRSx1QkFBdUIsQ0FBQyxXQUFXLEdBQUcsS0FBSztRQUN6QyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQzNCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNsQyxXQUFXLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCwwQ0FBMEM7SUFDMUMsbUJBQW1CLENBQUMsV0FBd0I7UUFDMUMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLElBQUksMkJBQTJCLEdBQUcsV0FBVyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDckgsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2hELENBQUM7SUFDSCxDQUFDO0lBRUQsNERBQTREO0lBQzVELGlCQUFpQjtRQUNmLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGFBQWEsQ0FBQyxJQUFJLHdCQUF3QixFQUFFLENBQUMsQ0FBQztRQUNqRyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQy9DLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxpQ0FBaUMsQ0FDM0UsSUFBSSxDQUFDLGlCQUFpQixFQUN0QixnQkFBZ0IsRUFDaEIsRUFBRSxFQUNGLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FDN0MsQ0FBQztZQUNGLElBQUksQ0FBQyxlQUFlLEdBQUcsV0FBVyxDQUFDLFlBQVksQ0FBQztRQUNsRCxDQUFDO0lBQ0gsQ0FBQztJQUVELDREQUE0RDtJQUM1RCxlQUFlLENBQUMsSUFBUztRQUN2QixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLENBQzlELElBQUksMkJBQTJCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQ2pFLENBQUM7UUFDRixJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztZQUM1QyxvQkFBb0I7WUFDcEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGlDQUFpQyxDQUMvRSxJQUFJLENBQUMsY0FBYyxFQUNuQixnQkFBZ0IsRUFDaEI7Z0JBQ0UsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLO2dCQUNoQixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7Z0JBQ3ZCLE1BQU0sRUFBRSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsTUFBTTthQUMxQyxFQUNEO2dCQUNFLFNBQVMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLGtCQUFrQjthQUN6QyxDQUNGLENBQUM7WUFFRixJQUFJLGVBQWUsRUFBRSxZQUFZLEVBQUUsQ0FBQztnQkFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ25GLElBQUksT0FBTyxFQUFFLENBQUM7b0JBQ1osT0FBTyxDQUFDLFlBQVksR0FBRyxlQUFlLENBQUMsWUFBWSxDQUFDO29CQUNwRCxPQUFPLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztnQkFDMUIsQ0FBQztnQkFDRCxPQUFPLE9BQU8sQ0FBQztZQUNqQixDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxLQUFLO0lBQ0wsc0JBQXNCO0lBQ3RCLHFCQUFxQjtJQUVYLGlCQUFpQixDQUFDLElBQVMsRUFBRSxlQUFlLEdBQUcsS0FBSztRQUM1RCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQWlCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFDOUcsSUFBSSxjQUFjLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDOUMsSUFBSSxlQUFlLEVBQUUsQ0FBQztnQkFDcEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVTLFdBQVcsQ0FBQyxZQUF5QjtRQUM3QyxZQUFZLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUM5QixNQUFNLE9BQU8sR0FBRyxZQUFZLEVBQUUsWUFBWSxDQUFDO1FBQzNDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDekMsSUFBSSxPQUFPLE9BQU8sRUFBRSxPQUFPLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQzNDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNwQixDQUFDO1lBQ0QsT0FBTyxZQUFZLENBQUM7UUFDdEIsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ08sY0FBYyxDQUFDLElBQVM7UUFDaEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxFQUFFLElBQUksY0FBYyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdEYsQ0FBQztJQUVEOzs7T0FHRztJQUNPLEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBUztRQUNwQyxJQUFJLElBQUksSUFBSSxPQUFPLElBQUksQ0FBQyxjQUFjLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDdEQsSUFBSSxpQkFBc0IsQ0FBQztZQUMzQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWhELG9GQUFvRjtZQUNwRixNQUFNLFFBQVEsR0FBZ0IsTUFBTSxhQUFhLENBQUM7WUFFbEQsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ3ZDLGlCQUFpQixHQUFHLFFBQVEsQ0FBQyxDQUFDLGVBQWU7WUFDL0MsQ0FBQztpQkFBTSxJQUFJLENBQUMsUUFBUSxJQUFJLFFBQVEsWUFBWSxVQUFVLENBQUMsSUFBSSxRQUFRLFlBQVksT0FBTyxFQUFFLENBQUM7Z0JBQ3ZGLGlCQUFpQixHQUFHLE1BQU0sdUJBQXVCLENBQUMsSUFBSSxDQUFDLElBQWtCLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQywyQkFBMkI7WUFDbkgsQ0FBQztZQUVELElBQUksQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixJQUFJLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztnQkFDekUsTUFBTSxJQUFJLEtBQUssQ0FDYix3R0FBd0c7b0JBQ3RHLHVDQUF1QyxJQUFJLENBQUMsaUJBQWlCLFlBQVksQ0FDNUUsQ0FBQztZQUNKLENBQUM7WUFFRCw4Q0FBOEM7WUFDOUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ08sNkJBQTZCLENBQUMsRUFBK0MsRUFBRSxJQUFvQztRQUMzSCxZQUFZO1FBQ1osSUFBSSxJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxDQUFDO1lBQzVCLHVCQUF1QjtZQUN2QixNQUFNLFFBQVEsR0FBZ0I7Z0JBQzVCLEVBQUUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDckMsV0FBVyxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUN0QixRQUFRLEVBQUUsS0FBSzthQUNoQixDQUFDO1lBQ0YsdUJBQXVCLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDekUsQ0FBQzthQUFNLENBQUM7WUFDTiwrQ0FBK0M7WUFDL0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7SUFFRCx3RUFBd0U7SUFDOUQsOEJBQThCLENBQUMsRUFBZ0QsRUFBRSxJQUFrQztRQUMzSCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0QsSUFBSSxTQUFTLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDckMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEFwcGxpY2F0aW9uUmVmLCBDb21wb25lbnRSZWYsIFR5cGUsIFZpZXdDb250YWluZXJSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB0eXBlIHtcbiAgRXZlbnRTdWJzY3JpcHRpb24sXG4gIE9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlQXJncyxcbiAgT25Sb3dCYWNrVG9WaWV3cG9ydFJhbmdlQXJncyxcbiAgUnhKc0ZhY2FkZSxcbiAgU2xpY2tHcmlkLFxufSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9jb21tb24nO1xuaW1wb3J0IHtcbiAgYWRkVG9BcnJheVdoZW5Ob3RFeGlzdHMsXG4gIGNhc3RPYnNlcnZhYmxlVG9Qcm9taXNlLFxuICBjcmVhdGVEb21FbGVtZW50LFxuICBTbGlja0V2ZW50RGF0YSxcbiAgU2xpY2tSb3dTZWxlY3Rpb25Nb2RlbCxcbiAgdW5zdWJzY3JpYmVBbGwsXG59IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL2NvbW1vbic7XG5pbXBvcnQgdHlwZSB7IEV2ZW50UHViU3ViU2VydmljZSB9IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL2V2ZW50LXB1Yi1zdWInO1xuaW1wb3J0IHsgU2xpY2tSb3dEZXRhaWxWaWV3IGFzIFVuaXZlcnNhbFNsaWNrUm93RGV0YWlsVmlldyB9IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL3Jvdy1kZXRhaWwtdmlldy1wbHVnaW4nO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgdHlwZSBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB0eXBlIHsgR3JpZE9wdGlvbiwgUm93RGV0YWlsVmlldyB9IGZyb20gJy4uL21vZGVscy9pbmRleCc7XG5pbXBvcnQgdHlwZSB7IEFuZ3VsYXJVdGlsU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2FuZ3VsYXJVdGlsLnNlcnZpY2UnO1xuXG5jb25zdCBST1dfREVUQUlMX0NPTlRBSU5FUl9QUkVGSVggPSAnY29udGFpbmVyXyc7XG5jb25zdCBQUkVMT0FEX0NPTlRBSU5FUl9QUkVGSVggPSAnY29udGFpbmVyX2xvYWRpbmcnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZWRWaWV3IHtcbiAgaWQ6IHN0cmluZyB8IG51bWJlcjtcbiAgZGF0YUNvbnRleHQ6IGFueTtcbiAgY29tcG9uZW50UmVmPzogQ29tcG9uZW50UmVmPGFueT47XG4gIHJlbmRlcmVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIFNsaWNrUm93RGV0YWlsVmlldyBleHRlbmRzIFVuaXZlcnNhbFNsaWNrUm93RGV0YWlsVmlldyB7XG4gIHJvd0RldGFpbENvbnRhaW5lciE6IFZpZXdDb250YWluZXJSZWY7XG4gIHByb3RlY3RlZCBfcHJlbG9hZENvbXBvbmVudDogVHlwZTxvYmplY3Q+IHwgdW5kZWZpbmVkO1xuICBwcm90ZWN0ZWQgX3ByZWxvYWRDb21wUmVmPzogQ29tcG9uZW50UmVmPGFueT47XG4gIHByb3RlY3RlZCBfdmlld3M6IENyZWF0ZWRWaWV3W10gPSBbXTtcbiAgcHJvdGVjdGVkIF92aWV3Q29tcG9uZW50ITogVHlwZTxvYmplY3Q+O1xuICBwcm90ZWN0ZWQgX3N1YnNjcmlwdGlvbnM6IEV2ZW50U3Vic2NyaXB0aW9uW10gPSBbXTtcbiAgcHJvdGVjdGVkIF91c2VyUHJvY2Vzc0ZuITogKGl0ZW06IGFueSkgPT4gUHJvbWlzZTxhbnk+IHwgT2JzZXJ2YWJsZTxhbnk+IHwgU3ViamVjdDxhbnk+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCByZWFkb25seSBhbmd1bGFyVXRpbFNlcnZpY2U6IEFuZ3VsYXJVdGlsU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgYXBwUmVmOiBBcHBsaWNhdGlvblJlZixcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXZlbnRQdWJTdWJTZXJ2aWNlOiBFdmVudFB1YlN1YlNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGdyaWRDb250YWluZXJFbGVtZW50OiBIVE1MRGl2RWxlbWVudCxcbiAgICBwcm90ZWN0ZWQgcnhqcz86IFJ4SnNGYWNhZGVcbiAgKSB7XG4gICAgc3VwZXIoZXZlbnRQdWJTdWJTZXJ2aWNlKTtcbiAgfVxuXG4gIGdldCBhZGRvbk9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0T3B0aW9ucygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBkYXRhc2V0SWRQcm9wTmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmRhdGFzZXRJZFByb3BlcnR5TmFtZSB8fCAnaWQnO1xuICB9XG5cbiAgLyoqIEdldHRlciBmb3IgdGhlIEdyaWQgT3B0aW9ucyBwdWxsZWQgdGhyb3VnaCB0aGUgR3JpZCBPYmplY3QgKi9cbiAgZ2V0IGdyaWRPcHRpb25zKCk6IEdyaWRPcHRpb24ge1xuICAgIHJldHVybiAodGhpcy5fZ3JpZD8uZ2V0T3B0aW9ucygpIHx8IHt9KSBhcyBHcmlkT3B0aW9uO1xuICB9XG5cbiAgZ2V0IHJvd0RldGFpbFZpZXdPcHRpb25zKCk6IFJvd0RldGFpbFZpZXcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXc7XG4gIH1cblxuICBhZGRSeEpzUmVzb3VyY2UocnhqczogUnhKc0ZhY2FkZSkge1xuICAgIHRoaXMucnhqcyA9IHJ4anM7XG4gIH1cblxuICAvKiogRGlzcG9zZSBvZiB0aGUgUm93RGV0YWlsVmlldyBFeHRlbnNpb24gKi9cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLmRpc3Bvc2VBbGxWaWV3Q29tcG9uZW50cygpO1xuICAgIHRoaXMuX3N1YnNjcmlwdGlvbnMgPSB1bnN1YnNjcmliZUFsbCh0aGlzLl9zdWJzY3JpcHRpb25zKTsgLy8gYWxzbyB1bnN1YnNjcmliZSBhbGwgUnhKUyBzdWJzY3JpcHRpb25zXG4gICAgc3VwZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgLyoqIERpc3Bvc2Ugb2YgYWxsIHRoZSBvcGVuZWQgUm93IERldGFpbCBQYW5lbHMgQW5ndWxhciBWaWV3IENvbXBvbmVudHMgKi9cbiAgZGlzcG9zZUFsbFZpZXdDb21wb25lbnRzKCkge1xuICAgIGRvIHtcbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLl92aWV3cy5wb3AoKTtcbiAgICAgIGlmICh2aWV3KSB7XG4gICAgICAgIHRoaXMuZGlzcG9zZVZpZXcodmlldyk7XG4gICAgICB9XG4gICAgfSB3aGlsZSAodGhpcy5fdmlld3MubGVuZ3RoID4gMCk7XG4gIH1cblxuICAvKiogR2V0IHRoZSBpbnN0YW5jZSBvZiB0aGUgU2xpY2tHcmlkIGFkZG9uIChjb250cm9sIG9yIHBsdWdpbikuICovXG4gIGdldEFkZG9uSW5zdGFuY2UoKTogU2xpY2tSb3dEZXRhaWxWaWV3IHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBpbml0KGdyaWQ6IFNsaWNrR3JpZCkge1xuICAgIHRoaXMuX2dyaWQgPSBncmlkO1xuICAgIHN1cGVyLmluaXQodGhpcy5fZ3JpZCk7XG4gICAgdGhpcy5yZWdpc3RlcihncmlkPy5nZXRTZWxlY3Rpb25Nb2RlbCgpIGFzIFNsaWNrUm93U2VsZWN0aW9uTW9kZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSB0aGUgcGx1Z2luIGJlZm9yZSB0aGUgR3JpZCBjcmVhdGlvbiwgZWxzZSBpdCB3aWxsIGJlaGF2ZSBvZGRseS5cbiAgICogTW9zdGx5IGJlY2F1c2UgdGhlIGNvbHVtbiBkZWZpbml0aW9ucyBtaWdodCBjaGFuZ2UgYWZ0ZXIgdGhlIGdyaWQgY3JlYXRpb25cbiAgICovXG4gIHJlZ2lzdGVyKHJvd1NlbGVjdGlvblBsdWdpbj86IFNsaWNrUm93U2VsZWN0aW9uTW9kZWwpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMuZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldz8ucHJvY2VzcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gd2UgbmVlZCB0byBrZWVwIHRoZSB1c2VyIFwicHJvY2Vzc1wiIG1ldGhvZCBhbmQgcmVwbGFjZSBpdCB3aXRoIG91ciBvd24gZXhlY3V0aW9uIG1ldGhvZFxuICAgICAgLy8gd2UgZG8gdGhpcyBiZWNhdXNlIHdoZW4gd2UgZ2V0IHRoZSBpdGVtIGRldGFpbCwgd2UgbmVlZCB0byBjYWxsIFwib25Bc3luY1Jlc3BvbnNlLm5vdGlmeVwiIGZvciB0aGUgcGx1Z2luIHRvIHdvcmtcbiAgICAgIHRoaXMuX3VzZXJQcm9jZXNzRm4gPSB0aGlzLmdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcucHJvY2VzcyBhcyAoaXRlbTogYW55KSA9PiBQcm9taXNlPGFueT47IC8vIGtlZXAgdXNlcidzIHByb2Nlc3MgbWV0aG9kXG4gICAgICB0aGlzLmFkZG9uT3B0aW9ucy5wcm9jZXNzID0gKGl0ZW0pID0+IHRoaXMub25Qcm9jZXNzaW5nKGl0ZW0pOyAvLyByZXBsYWNlIHByb2Nlc3MgbWV0aG9kICYgcnVuIG91ciBpbnRlcm5hbCBvbmVcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnW0FuZ3VsYXItU2xpY2tncmlkXSBZb3UgbmVlZCB0byBwcm92aWRlIGEgXCJwcm9jZXNzXCIgZnVuY3Rpb24gZm9yIHRoZSBSb3cgRGV0YWlsIEV4dGVuc2lvbiB0byB3b3JrIHByb3Blcmx5J1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZ3JpZCAmJiB0aGlzLmdyaWRPcHRpb25zPy5yb3dEZXRhaWxWaWV3KSB7XG4gICAgICAvLyBsb2FkIHRoZSBQcmVsb2FkICYgUm93RGV0YWlsIFRlbXBsYXRlcyAoY291bGQgYmUgc3RyYWlnaHQgSFRNTCBvciBBbmd1bGFyIFZpZXcvVmlld01vZGVsKVxuICAgICAgLy8gd2hlbiB0aG9zZSBhcmUgQW5ndWxhciBWaWV3L1ZpZXdNb2RlbCwgd2UgbmVlZCB0byBjcmVhdGUgVmlldyBDb21wb25lbnQgJiBwcm92aWRlIHRoZSBodG1sIGNvbnRhaW5lcnMgdG8gdGhlIFBsdWdpbiAocHJlVGVtcGxhdGUvcG9zdFRlbXBsYXRlIG1ldGhvZHMpXG4gICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldy5wcmVUZW1wbGF0ZSkge1xuICAgICAgICB0aGlzLl9wcmVsb2FkQ29tcG9uZW50ID0gdGhpcy5ncmlkT3B0aW9ucz8ucm93RGV0YWlsVmlldz8ucHJlbG9hZENvbXBvbmVudDtcbiAgICAgICAgdGhpcy5hZGRvbk9wdGlvbnMucHJlVGVtcGxhdGUgPSAoKSA9PiBjcmVhdGVEb21FbGVtZW50KCdkaXYnLCB7IGNsYXNzTmFtZTogYCR7UFJFTE9BRF9DT05UQUlORVJfUFJFRklYfWAgfSk7XG4gICAgICB9XG4gICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldy5wb3N0VGVtcGxhdGUpIHtcbiAgICAgICAgdGhpcy5fdmlld0NvbXBvbmVudCA9IHRoaXMuZ3JpZE9wdGlvbnM/LnJvd0RldGFpbFZpZXc/LnZpZXdDb21wb25lbnQ7XG4gICAgICAgIHRoaXMuYWRkb25PcHRpb25zLnBvc3RUZW1wbGF0ZSA9IChpdGVtRGV0YWlsOiBhbnkpID0+XG4gICAgICAgICAgY3JlYXRlRG9tRWxlbWVudCgnZGl2JywgeyBjbGFzc05hbWU6IGAke1JPV19ERVRBSUxfQ09OVEFJTkVSX1BSRUZJWH0ke2l0ZW1EZXRhaWxbdGhpcy5kYXRhc2V0SWRQcm9wTmFtZV19YCB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gdGhpcyBhbHNvIHJlcXVpcmVzIHRoZSBSb3cgU2VsZWN0aW9uIE1vZGVsIHRvIGJlIHJlZ2lzdGVyZWQgYXMgd2VsbFxuICAgICAgaWYgKCFyb3dTZWxlY3Rpb25QbHVnaW4gfHwgIXRoaXMuX2dyaWQuZ2V0U2VsZWN0aW9uTW9kZWwoKSkge1xuICAgICAgICByb3dTZWxlY3Rpb25QbHVnaW4gPSBuZXcgU2xpY2tSb3dTZWxlY3Rpb25Nb2RlbCh0aGlzLmdyaWRPcHRpb25zLnJvd1NlbGVjdGlvbk9wdGlvbnMgfHwgeyBzZWxlY3RBY3RpdmVSb3c6IHRydWUgfSk7XG4gICAgICAgIHRoaXMuX2dyaWQuc2V0U2VsZWN0aW9uTW9kZWwocm93U2VsZWN0aW9uUGx1Z2luKTtcbiAgICAgIH1cblxuICAgICAgLy8gaG9vayBhbGwgZXZlbnRzXG4gICAgICBpZiAodGhpcy5fZ3JpZCAmJiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zKSB7XG4gICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uRXh0ZW5zaW9uUmVnaXN0ZXJlZCkge1xuICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25FeHRlbnNpb25SZWdpc3RlcmVkKHRoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMub25Bc3luY1Jlc3BvbnNlLCAoZXZlbnQsIGFyZ3MpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucyAmJiB0eXBlb2YgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFzeW5jUmVzcG9uc2UgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25Bc3luY1Jlc3BvbnNlKGV2ZW50LCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLm9uQXN5bmNFbmRVcGRhdGUsIChlLCBhcmdzKSA9PiB7XG4gICAgICAgICAgLy8gZGVzdHJveSBwcmVsb2FkIGlmIGV4aXN0c1xuICAgICAgICAgIHRoaXMuX3ByZWxvYWRDb21wUmVmPy5kZXN0cm95KCk7XG5cbiAgICAgICAgICAvLyB0cmlnZ2VycyBhZnRlciBiYWNrZW5kIGNhbGxlZCBcIm9uQXN5bmNSZXNwb25zZS5ub3RpZnkoKVwiXG4gICAgICAgICAgdGhpcy5yZW5kZXJWaWV3TW9kZWwoYXJncz8uaXRlbSk7XG5cbiAgICAgICAgICBpZiAodGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucyAmJiB0eXBlb2YgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFzeW5jRW5kVXBkYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQXN5bmNFbmRVcGRhdGUoZSwgYXJncyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmV2ZW50SGFuZGxlci5zdWJzY3JpYmUoXG4gICAgICAgICAgdGhpcy5vbkFmdGVyUm93RGV0YWlsVG9nZ2xlLFxuICAgICAgICAgIChlOiBhbnksIGFyZ3M6IHsgZ3JpZDogU2xpY2tHcmlkOyBpdGVtOiBhbnk7IGV4cGFuZGVkUm93czogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPiB9KSA9PiB7XG4gICAgICAgICAgICAvLyBkaXNwbGF5IHByZWxvYWQgdGVtcGxhdGUgJiByZS1yZW5kZXIgYWxsIHRoZSBvdGhlciBEZXRhaWwgVmlld3MgYWZ0ZXIgdG9nZ2xpbmdcbiAgICAgICAgICAgIC8vIHRoZSBwcmVsb2FkIFZpZXcgd2lsbCBldmVudHVhbGx5IGdvIGF3YXkgb25jZSB0aGUgZGF0YSBnZXRzIGxvYWRlZCBhZnRlciB0aGUgXCJvbkFzeW5jRW5kVXBkYXRlXCIgZXZlbnRcbiAgICAgICAgICAgIHRoaXMucmVuZGVyUHJlbG9hZFZpZXcoKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25BZnRlclJvd0RldGFpbFRvZ2dsZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQWZ0ZXJSb3dEZXRhaWxUb2dnbGUoZSwgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLm9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlLCAoZSwgYXJncykgPT4ge1xuICAgICAgICAgIC8vIGJlZm9yZSB0b2dnbGluZyByb3cgZGV0YWlsLCB3ZSBuZWVkIHRvIGNyZWF0ZSBWaWV3IENvbXBvbmVudCBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgICAgdGhpcy5oYW5kbGVPbkJlZm9yZVJvd0RldGFpbFRvZ2dsZShlLCBhcmdzKTtcblxuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkJlZm9yZVJvd0RldGFpbFRvZ2dsZShlLCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLm9uUm93QmFja1RvVmlld3BvcnRSYW5nZSwgKGUsIGFyZ3MpID0+IHtcbiAgICAgICAgICAvLyB3aGVuIHJvdyBpcyBiYWNrIHRvIHZpZXdwb3J0IHJhbmdlLCB3ZSB3aWxsIHJlLXJlbmRlciB0aGUgVmlldyBDb21wb25lbnQocylcbiAgICAgICAgICB0aGlzLmhhbmRsZU9uUm93QmFja1RvVmlld3BvcnRSYW5nZShlLCBhcmdzKTtcblxuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uUm93QmFja1RvVmlld3BvcnRSYW5nZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vblJvd0JhY2tUb1ZpZXdwb3J0UmFuZ2UoZSwgYXJncyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLl9ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMub25CZWZvcmVSb3dPdXRPZlZpZXdwb3J0UmFuZ2UsIChldmVudCwgYXJncykgPT4ge1xuICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucz8ub25CZWZvcmVSb3dPdXRPZlZpZXdwb3J0UmFuZ2UgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25CZWZvcmVSb3dPdXRPZlZpZXdwb3J0UmFuZ2UoZXZlbnQsIGFyZ3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmRpc3Bvc2VWaWV3QnlJdGVtKGFyZ3MuaXRlbSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLm9uUm93T3V0T2ZWaWV3cG9ydFJhbmdlLCAoZSwgYXJncykgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zICYmIHR5cGVvZiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uUm93T3V0T2ZWaWV3cG9ydFJhbmdlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uUm93T3V0T2ZWaWV3cG9ydFJhbmdlKGUsIGFyZ3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gLS1cbiAgICAgICAgLy8gaG9vayBzb21lIGV2ZW50cyBuZWVkZWQgYnkgdGhlIFBsdWdpbiBpdHNlbGZcblxuICAgICAgICAvLyB3ZSBuZWVkIHRvIHJlZHJhdyB0aGUgb3BlbiBkZXRhaWwgdmlld3MgaWYgd2UgY2hhbmdlIGNvbHVtbiBwb3NpdGlvbiAoY29sdW1uIHJlb3JkZXIpXG4gICAgICAgIHRoaXMuZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLl9ncmlkLm9uQ29sdW1uc1Jlb3JkZXJlZCwgdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cy5iaW5kKHRoaXMsIGZhbHNlKSk7XG5cbiAgICAgICAgLy8gb24gcm93IHNlbGVjdGlvbiBjaGFuZ2VkLCB3ZSBhbHNvIG5lZWQgdG8gcmVkcmF3XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLmVuYWJsZVJvd1NlbGVjdGlvbiB8fCB0aGlzLmdyaWRPcHRpb25zLmVuYWJsZUNoZWNrYm94U2VsZWN0b3IpIHtcbiAgICAgICAgICB0aGlzLmV2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5fZ3JpZC5vblNlbGVjdGVkUm93c0NoYW5nZWQsIHRoaXMucmVkcmF3QWxsVmlld0NvbXBvbmVudHMuYmluZCh0aGlzLCBmYWxzZSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gb24gc29ydCwgYWxsIHJvdyBkZXRhaWwgYXJlIGNvbGxhcHNlZCBzbyB3ZSBjYW4gZGlzcG9zZSBvZiBhbGwgdGhlIFZpZXdzIGFzIHdlbGxcbiAgICAgICAgdGhpcy5ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMuX2dyaWQub25Tb3J0LCB0aGlzLmRpc3Bvc2VBbGxWaWV3Q29tcG9uZW50cy5iaW5kKHRoaXMpKTtcblxuICAgICAgICAvLyByZWRyYXcgYWxsIFZpZXdzIHdoZW5ldmVyIGNlcnRhaW4gZXZlbnRzIGFyZSB0cmlnZ2VyZWRcbiAgICAgICAgdGhpcy5fc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgICAgIHRoaXMuZXZlbnRQdWJTdWJTZXJ2aWNlPy5zdWJzY3JpYmUoXG4gICAgICAgICAgICBbJ29uRmlsdGVyQ2hhbmdlZCcsICdvbkdyaWRNZW51Q29sdW1uc0NoYW5nZWQnLCAnb25Db2x1bW5QaWNrZXJDb2x1bW5zQ2hhbmdlZCddLFxuICAgICAgICAgICAgdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cy5iaW5kKHRoaXMsIGZhbHNlKVxuICAgICAgICAgICksXG4gICAgICAgICAgdGhpcy5ldmVudFB1YlN1YlNlcnZpY2U/LnN1YnNjcmliZShbJ29uR3JpZE1lbnVDbGVhckFsbEZpbHRlcnMnLCAnb25HcmlkTWVudUNsZWFyQWxsU29ydGluZyddLCAoKSA9PlxuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoKCkgPT4gdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cygpKVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKiogUmVkcmF3IChyZS1yZW5kZXIpIGFsbCB0aGUgZXhwYW5kZWQgcm93IGRldGFpbCBWaWV3IENvbXBvbmVudHMgKi9cbiAgcmVkcmF3QWxsVmlld0NvbXBvbmVudHMoZm9yY2VSZWRyYXcgPSBmYWxzZSkge1xuICAgIHRoaXMucmVzZXRSZW5kZXJlZFJvd3MoKTtcbiAgICB0aGlzLl92aWV3cy5mb3JFYWNoKCh2aWV3KSA9PiB7XG4gICAgICBpZiAoIXZpZXcucmVuZGVyZWQgfHwgZm9yY2VSZWRyYXcpIHtcbiAgICAgICAgZm9yY2VSZWRyYXcgJiYgdmlldy5jb21wb25lbnRSZWY/LmRlc3Ryb3koKTtcbiAgICAgICAgdGhpcy5yZWRyYXdWaWV3Q29tcG9uZW50KHZpZXcpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFJlZHJhdyB0aGUgbmVjZXNzYXJ5IFZpZXcgQ29tcG9uZW50ICovXG4gIHJlZHJhd1ZpZXdDb21wb25lbnQoY3JlYXRlZFZpZXc6IENyZWF0ZWRWaWV3KSB7XG4gICAgY29uc3QgY29udGFpbmVyRWxlbWVudCA9IHRoaXMuZ3JpZENvbnRhaW5lckVsZW1lbnQucXVlcnlTZWxlY3RvcihgLiR7Uk9XX0RFVEFJTF9DT05UQUlORVJfUFJFRklYfSR7Y3JlYXRlZFZpZXcuaWR9YCk7XG4gICAgaWYgKGNvbnRhaW5lckVsZW1lbnQpIHtcbiAgICAgIHRoaXMucmVuZGVyVmlld01vZGVsKGNyZWF0ZWRWaWV3LmRhdGFDb250ZXh0KTtcbiAgICB9XG4gIH1cblxuICAvKiogUmVuZGVyIChvciByZS1yZW5kZXIpIHRoZSBWaWV3IENvbXBvbmVudCAoUm93IERldGFpbCkgKi9cbiAgcmVuZGVyUHJlbG9hZFZpZXcoKSB7XG4gICAgY29uc3QgY29udGFpbmVyRWxlbWVudCA9IHRoaXMuZ3JpZENvbnRhaW5lckVsZW1lbnQucXVlcnlTZWxlY3RvcihgLiR7UFJFTE9BRF9DT05UQUlORVJfUFJFRklYfWApO1xuICAgIGlmICh0aGlzLl9wcmVsb2FkQ29tcG9uZW50ICYmIGNvbnRhaW5lckVsZW1lbnQpIHtcbiAgICAgIGNvbnN0IHByZWxvYWRDb21wID0gdGhpcy5hbmd1bGFyVXRpbFNlcnZpY2UuY3JlYXRlQW5ndWxhckNvbXBvbmVudEFwcGVuZFRvRG9tKFxuICAgICAgICB0aGlzLl9wcmVsb2FkQ29tcG9uZW50LFxuICAgICAgICBjb250YWluZXJFbGVtZW50LFxuICAgICAgICB7fSxcbiAgICAgICAgeyBzYW5pdGl6ZXI6IHRoaXMuX2dyaWQuc2FuaXRpemVIdG1sU3RyaW5nIH1cbiAgICAgICk7XG4gICAgICB0aGlzLl9wcmVsb2FkQ29tcFJlZiA9IHByZWxvYWRDb21wLmNvbXBvbmVudFJlZjtcbiAgICB9XG4gIH1cblxuICAvKiogUmVuZGVyIChvciByZS1yZW5kZXIpIHRoZSBWaWV3IENvbXBvbmVudCAoUm93IERldGFpbCkgKi9cbiAgcmVuZGVyVmlld01vZGVsKGl0ZW06IGFueSk6IENyZWF0ZWRWaWV3IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjb250YWluZXJFbGVtZW50ID0gdGhpcy5ncmlkQ29udGFpbmVyRWxlbWVudC5xdWVyeVNlbGVjdG9yKFxuICAgICAgYC4ke1JPV19ERVRBSUxfQ09OVEFJTkVSX1BSRUZJWH0ke2l0ZW1bdGhpcy5kYXRhc2V0SWRQcm9wTmFtZV19YFxuICAgICk7XG4gICAgaWYgKHRoaXMuX3ZpZXdDb21wb25lbnQgJiYgY29udGFpbmVyRWxlbWVudCkge1xuICAgICAgLy8gcmVuZGVyIHJvdyBkZXRhaWxcbiAgICAgIGNvbnN0IGNvbXBvbmVudE91dHB1dCA9IHRoaXMuYW5ndWxhclV0aWxTZXJ2aWNlLmNyZWF0ZUFuZ3VsYXJDb21wb25lbnRBcHBlbmRUb0RvbShcbiAgICAgICAgdGhpcy5fdmlld0NvbXBvbmVudCxcbiAgICAgICAgY29udGFpbmVyRWxlbWVudCxcbiAgICAgICAge1xuICAgICAgICAgIG1vZGVsOiBpdGVtLFxuICAgICAgICAgIGFkZG9uOiB0aGlzLFxuICAgICAgICAgIGdyaWQ6IHRoaXMuX2dyaWQsXG4gICAgICAgICAgZGF0YVZpZXc6IHRoaXMuZGF0YVZpZXcsXG4gICAgICAgICAgcGFyZW50OiB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zPy5wYXJlbnQsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBzYW5pdGl6ZXI6IHRoaXMuX2dyaWQuc2FuaXRpemVIdG1sU3RyaW5nLFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICBpZiAoY29tcG9uZW50T3V0cHV0Py5jb21wb25lbnRSZWYpIHtcbiAgICAgICAgY29uc3Qgdmlld09iaiA9IHRoaXMuX3ZpZXdzLmZpbmQoKG9iaikgPT4gb2JqLmlkID09PSBpdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdKTtcbiAgICAgICAgaWYgKHZpZXdPYmopIHtcbiAgICAgICAgICB2aWV3T2JqLmNvbXBvbmVudFJlZiA9IGNvbXBvbmVudE91dHB1dC5jb21wb25lbnRSZWY7XG4gICAgICAgICAgdmlld09iai5yZW5kZXJlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZpZXdPYmo7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyAtLVxuICAvLyBwcm90ZWN0ZWQgZnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHByb3RlY3RlZCBkaXNwb3NlVmlld0J5SXRlbShpdGVtOiBhbnksIHJlbW92ZUZyb21BcnJheSA9IGZhbHNlKTogdm9pZCB7XG4gICAgY29uc3QgZm91bmRWaWV3SW5kZXggPSB0aGlzLl92aWV3cy5maW5kSW5kZXgoKHZpZXc6IENyZWF0ZWRWaWV3KSA9PiB2aWV3LmlkID09PSBpdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdKTtcbiAgICBpZiAoZm91bmRWaWV3SW5kZXggPj0gMCkge1xuICAgICAgdGhpcy5kaXNwb3NlVmlldyh0aGlzLl92aWV3c1tmb3VuZFZpZXdJbmRleF0pO1xuICAgICAgaWYgKHJlbW92ZUZyb21BcnJheSkge1xuICAgICAgICB0aGlzLl92aWV3cy5zcGxpY2UoZm91bmRWaWV3SW5kZXgsIDEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBkaXNwb3NlVmlldyhleHBhbmRlZFZpZXc6IENyZWF0ZWRWaWV3KTogQ3JlYXRlZFZpZXcgfCB2b2lkIHtcbiAgICBleHBhbmRlZFZpZXcucmVuZGVyZWQgPSBmYWxzZTtcbiAgICBjb25zdCBjb21wUmVmID0gZXhwYW5kZWRWaWV3Py5jb21wb25lbnRSZWY7XG4gICAgaWYgKGNvbXBSZWYpIHtcbiAgICAgIHRoaXMuYXBwUmVmLmRldGFjaFZpZXcoY29tcFJlZi5ob3N0Vmlldyk7XG4gICAgICBpZiAodHlwZW9mIGNvbXBSZWY/LmRlc3Ryb3kgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29tcFJlZi5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZXhwYW5kZWRWaWV3O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBub3RpZnkgdGhlIG9uQXN5bmNSZXNwb25zZSB3aXRoIHRoZSBcImFyZ3MuaXRlbVwiIChyZXF1aXJlZCBwcm9wZXJ0eSlcbiAgICogdGhlIHBsdWdpbiB3aWxsIHRoZW4gdXNlIGl0ZW0gdG8gcG9wdWxhdGUgdGhlIHJvdyBkZXRhaWwgcGFuZWwgd2l0aCB0aGUgXCJwb3N0VGVtcGxhdGVcIlxuICAgKiBAcGFyYW0gaXRlbVxuICAgKi9cbiAgcHJvdGVjdGVkIG5vdGlmeVRlbXBsYXRlKGl0ZW06IGFueSkge1xuICAgIHRoaXMub25Bc3luY1Jlc3BvbnNlLm5vdGlmeSh7IGl0ZW0sIGl0ZW1EZXRhaWw6IGl0ZW0gfSwgbmV3IFNsaWNrRXZlbnREYXRhKCksIHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9uIFByb2Nlc3NpbmcsIHdlIHdpbGwgbm90aWZ5IHRoZSBwbHVnaW4gd2l0aCB0aGUgbmV3IGl0ZW0gZGV0YWlsIG9uY2UgYmFja2VuZCBzZXJ2ZXIgY2FsbCBjb21wbGV0ZXNcbiAgICogQHBhcmFtIGl0ZW1cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBvblByb2Nlc3NpbmcoaXRlbTogYW55KSB7XG4gICAgaWYgKGl0ZW0gJiYgdHlwZW9mIHRoaXMuX3VzZXJQcm9jZXNzRm4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGxldCBhd2FpdGVkSXRlbURldGFpbDogYW55O1xuICAgICAgY29uc3QgdXNlclByb2Nlc3NGbiA9IHRoaXMuX3VzZXJQcm9jZXNzRm4oaXRlbSk7XG5cbiAgICAgIC8vIHdhaXQgZm9yIHRoZSBcInVzZXJQcm9jZXNzRm5cIiwgb25jZSByZXNvbHZlZCB3ZSB3aWxsIHNhdmUgaXQgaW50byB0aGUgXCJjb2xsZWN0aW9uXCJcbiAgICAgIGNvbnN0IHJlc3BvbnNlOiBhbnkgfCBhbnlbXSA9IGF3YWl0IHVzZXJQcm9jZXNzRm47XG5cbiAgICAgIGlmICh0aGlzLmRhdGFzZXRJZFByb3BOYW1lIGluIHJlc3BvbnNlKSB7XG4gICAgICAgIGF3YWl0ZWRJdGVtRGV0YWlsID0gcmVzcG9uc2U7IC8vIGZyb20gUHJvbWlzZVxuICAgICAgfSBlbHNlIGlmICgocmVzcG9uc2UgJiYgcmVzcG9uc2UgaW5zdGFuY2VvZiBPYnNlcnZhYmxlKSB8fCByZXNwb25zZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgYXdhaXRlZEl0ZW1EZXRhaWwgPSBhd2FpdCBjYXN0T2JzZXJ2YWJsZVRvUHJvbWlzZSh0aGlzLnJ4anMgYXMgUnhKc0ZhY2FkZSwgcmVzcG9uc2UpOyAvLyBmcm9tIEFuZ3VsYXItaHR0cC1jbGllbnRcbiAgICAgIH1cblxuICAgICAgaWYgKCFhd2FpdGVkSXRlbURldGFpbCB8fCAhKHRoaXMuZGF0YXNldElkUHJvcE5hbWUgaW4gYXdhaXRlZEl0ZW1EZXRhaWwpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnW0FuZ3VsYXItU2xpY2tncmlkXSBjb3VsZCBub3QgcHJvY2VzcyB0aGUgUm93IERldGFpbCwgeW91IG11c3QgbWFrZSBzdXJlIHRoYXQgeW91ciBcInByb2Nlc3NcIiBjYWxsYmFjayAnICtcbiAgICAgICAgICAgIGByZXR1cm5zIGFuIGl0ZW0gb2JqZWN0IHRoYXQgaGFzIGFuIFwiJHt0aGlzLmRhdGFzZXRJZFByb3BOYW1lfVwiIHByb3BlcnR5YFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBub3RpZnkgdGhlIHBsdWdpbiB3aXRoIHRoZSBuZXcgaXRlbSBkZXRhaWxzXG4gICAgICB0aGlzLm5vdGlmeVRlbXBsYXRlKGF3YWl0ZWRJdGVtRGV0YWlsIHx8IHt9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSnVzdCBiZWZvcmUgdGhlIHJvdyBnZXQgZXhwYW5kZWQgb3IgY29sbGFwc2VkIHdlIHdpbGwgZG8gdGhlIGZvbGxvd2