UNPKG

@netgrif/components-core

Version:

Netgrif Application engine frontend core Angular library

431 lines 61.2 kB
import { BehaviorSubject, ReplaySubject, Subject } from 'rxjs'; import { HeaderState } from './header-state'; import { Injectable, Optional } from '@angular/core'; import { HeaderMode } from './models/header-mode'; import { HeaderColumn, HeaderColumnType } from './models/header-column'; import { LoadingEmitter } from '../utility/loading-emitter'; import { HeaderChangeType } from './models/user-changes/header-change-type'; import * as i0 from "@angular/core"; import * as i1 from "./models/header-type"; import * as i2 from "../user/services/user-preference.service"; import * as i3 from "../logger/services/logger.service"; import * as i4 from "../user/services/view-id.service"; import * as i5 from "./services/overflow.service"; export class AbstractHeaderService { _headerType; _preferences; _logger; _viewIdService; _overflowService; static DEFAULT_HEADER_COUNT = 5; static DEFAULT_HEADER_RESPONSIVITY = true; _headerColumnCount$; _preferenceColumnCount$; _responsiveHeaders$; _headerState; _headerChange$; _clearHeaderSearch$; _initDefaultHeaders; _initializedCount; loading; fieldsGroup; constructor(_headerType, _preferences, _logger, _viewIdService, _overflowService) { this._headerType = _headerType; this._preferences = _preferences; this._logger = _logger; this._viewIdService = _viewIdService; this._overflowService = _overflowService; this.loading = new LoadingEmitter(true); this._headerChange$ = new Subject(); this.fieldsGroup = [{ groupTitle: 'Meta data', fields: this.createMetaHeaders() }]; this._headerColumnCount$ = new BehaviorSubject(AbstractHeaderService.DEFAULT_HEADER_COUNT); this._responsiveHeaders$ = new BehaviorSubject(AbstractHeaderService.DEFAULT_HEADER_RESPONSIVITY); this._preferenceColumnCount$ = new ReplaySubject(); this._clearHeaderSearch$ = new Subject(); this._initializedCount = false; if (this._viewIdService === null) { this._logger.warn('Header service could not inject ViewIdService! User preferences won\'t be loaded or saved!'); } this._preferences.preferencesChanged$.subscribe(() => { this.loadHeadersFromPreferences(); }); this.initializeHeaderState(); } /** * Provides Observable for all changes in header */ get headerChange$() { return this._headerChange$.asObservable(); } get selectedHeaders$() { return this._headerState.selectedHeaders$; } get headerState() { return this._headerState.asInterface(); } get headerType() { return this._headerType; } get overflowMode() { if (!!this._overflowService) { return this._overflowService.overflowMode; } else { return false; } } get headerColumnCount() { return this._headerColumnCount$.getValue(); } set headerColumnCount(maxColumns) { if (maxColumns !== this.headerColumnCount) { this._headerColumnCount$.next(maxColumns); this.updateHeaderColumnCount(); if (!this._initializedCount) { this.initializeDefaultHeaderState(); this._initializedCount = true; } } } get headerColumnCount$() { return this._headerColumnCount$.asObservable(); } get responsiveHeaders() { return this._responsiveHeaders$.getValue(); } set responsiveHeaders(responsiveHeaders) { this._responsiveHeaders$.next(responsiveHeaders); } get responsiveHeaders$() { return this._responsiveHeaders$.asObservable(); } get clearHeaderSearch$() { return this._clearHeaderSearch$.asObservable(); } set initDefaultHeaders(defaultHeaders) { this._initDefaultHeaders = defaultHeaders; } get initDefaultHeaders() { return this._initDefaultHeaders; } get preferenceColumnCount$() { return this._preferenceColumnCount$.asObservable(); } initializeHeaderState() { const defaultHeaders = []; for (let i = 0; i < this.fieldsGroup[0].fields.length && defaultHeaders.length < this.headerColumnCount; i++) { if (this.fieldsGroup[0].fields[i].initial) { defaultHeaders.push(this.fieldsGroup[0].fields[i]); } } while (defaultHeaders.length < this.headerColumnCount) { defaultHeaders.push(null); } this._headerState = new HeaderState(defaultHeaders); } initializeDefaultHeaderState() { if (this.initDefaultHeaders && Array.isArray(this.initDefaultHeaders)) { const defaultHeaders = []; for (let i = 0; i < this.headerColumnCount; i++) { defaultHeaders.push(null); } for (let i = 0; i < this.initDefaultHeaders.length; i++) { if (i >= this.headerColumnCount) { this._logger.warn('there are more NAE_DEFAULT_HEADERS than header columns. Skipping the rest...'); break; } for (const h of this.fieldsGroup) { const head = h.fields.find(header => header.uniqueId === this.initDefaultHeaders[i]); if (head) { defaultHeaders[i] = head; break; } } } this._headerState.updateSelectedHeaders(defaultHeaders); } this.loadHeadersFromPreferences(); } /** * Adds `null` headers if the new count is greater than the current count. * * Removes extra headers if the new count is smaller than the current count. */ updateHeaderColumnCount() { let headers = this._headerState.selectedHeaders; if (headers.length < this.headerColumnCount) { const lastSelectedHeaders = this._headerState.lastSelectedHeaders; if (headers.length < this.headerColumnCount && !!lastSelectedHeaders && headers.length < lastSelectedHeaders.length) { headers.push(...lastSelectedHeaders.slice(headers.length, this.headerColumnCount)); } while (headers.length <= this.headerColumnCount) { headers.push(null); } } else if (headers.length > this.headerColumnCount) { headers = headers.slice(0, this.headerColumnCount); } this._headerState.updateSelectedHeaders(headers); } setAllowedNets(allowedNets) { /* TODO by simply replacing the select options with new object, we don't loose the old references. Columns with headers from nets that are no longer allowed should have their value cleared. Columns with valid values that are not metadata should have their selection remapped to the new objects. */ const fieldsGroups = []; allowedNets.forEach(allowedNet => { const fieldsGroup = { groupTitle: allowedNet.title, fields: [] }; allowedNet.immediateData.forEach(immediate => { fieldsGroup.fields.push(new HeaderColumn(HeaderColumnType.IMMEDIATE, immediate.stringId, immediate.title, immediate.type, false, allowedNet.identifier)); }); fieldsGroups.push(fieldsGroup); }); this.fieldsGroup.splice(1, this.fieldsGroup.length - 1); this.fieldsGroup.push(...fieldsGroups); } setTaskAllowedNets(allowedNets) { /* TODO by simply replacing the select options with new object, we don't loose the old references. Columns with headers from nets that are no longer allowed should have their value cleared. Columns with valid values that are not metadata should have their selection remapped to the new objects. */ const fieldsGroups = []; allowedNets.forEach(allowedNet => { const fieldsGroup = { groupTitle: allowedNet.title, fields: [] }; const existing = new Set(); allowedNet.transitions.forEach(trans => { trans.immediateData.forEach(data => { if (!existing.has(data.stringId)) { existing.add(data.stringId); fieldsGroup.fields.push(new HeaderColumn(HeaderColumnType.IMMEDIATE, data.stringId, data.title, data.type, false, allowedNet.identifier)); } }); }); fieldsGroups.push(fieldsGroup); }); this.fieldsGroup.splice(1, this.fieldsGroup.length - 1); this.fieldsGroup.push(...fieldsGroups); } /** * If this view has som headers stored in it's preferences attempts to load them. * If the preferences contain nonexistent headers they will be skipped. * * This function is NOT called by the abstract class' constructor. * It is the responsibility of the child class to call it at an appropriate moment. */ loadHeadersFromPreferences() { const viewId = this.getViewId(); if (!viewId) { return; } const preferredHeaderKeys = this._preferences.getHeaders(viewId); if (!preferredHeaderKeys) { return; } const newHeaders = []; preferredHeaderKeys.forEach(headerKey => { for (const fieldGroup of this.fieldsGroup) { for (const header of fieldGroup.fields) { if (header.uniqueId === headerKey) { newHeaders.push(header); return; // continue the outermost loop } } } // no match found newHeaders.push(null); this._logger.warn(`Could not restore header with ID '${headerKey}' from preferences. It is not one of the available headers for this view.`); }); this._preferenceColumnCount$.next(newHeaders.length); this._headerState.updateSelectedHeaders(newHeaders); } /** * Change sort mode for selected column all other column are set to default sort mode * Emit request for sorted panels * @param columnIndex index of the column that caused the sort change * @param active Represents column identifier * @param direction Represent one of sort modes: asd, desc and '' */ sortHeaderChanged(columnIndex, active, direction) { let sortChangeDescription; let foundFirstMatch = false; // column can feature in the header in multiple positions => we don't want to send multiple events this.headerState.selectedHeaders.filter(header => !!header).forEach(header => { if (header.uniqueId === active && !foundFirstMatch) { sortChangeDescription = { sortDirection: direction, columnType: header.type, fieldIdentifier: header.fieldIdentifier, petriNetIdentifier: header.petriNetIdentifier, columnIdentifier: columnIndex, fieldType: header.fieldType }; header.sortDirection = direction; foundFirstMatch = true; } else { header.sortDirection = ''; } }); this._headerChange$.next({ headerType: this.headerType, changeType: HeaderChangeType.SORT, description: sortChangeDescription }); } /** * Saves the search value in the appropriate column in the header * Emit request for searched panels by user input query */ headerSearchInputChanged(columnIndex, searchInput) { const affectedHeader = this.headerState.selectedHeaders[columnIndex]; affectedHeader.searchInput = searchInput; const searchChangeDescription = { fieldIdentifier: affectedHeader.fieldIdentifier, fieldType: affectedHeader.fieldType, fieldTitle: affectedHeader.title, searchInput, type: affectedHeader.type, petriNetIdentifier: affectedHeader.petriNetIdentifier, columnIdentifier: columnIndex }; this._headerChange$.next({ headerType: this.headerType, changeType: HeaderChangeType.SEARCH, description: searchChangeDescription }); } /** * Change active header and titles of panels */ headerColumnSelected(columnIndex, newHeaderColumn) { const newHeaders = []; newHeaders.push(...this._headerState.selectedHeaders); if (!!newHeaders[columnIndex]) { newHeaders[columnIndex].sortDirection = ''; newHeaders[columnIndex].searchInput = undefined; } newHeaders[columnIndex] = newHeaderColumn; this._headerState.updateSelectedHeaders(newHeaders); this._headerChange$.next({ headerType: this.headerType, changeType: HeaderChangeType.EDIT, description: { preferredHeaders: this._headerState.selectedHeaders } }); } /** * Change selected header mode there are three possible modes: SORT, SEARCH and EDIT * @param newMode the mode that the header should change to * @param saveLastMode whether the last state should be remembered. * It can be restored with the [HeaderState.restoreLastMode()]{@link HeaderState#restoreLastMode} method. */ changeMode(newMode, saveLastMode = true) { if (newMode === this._headerState.mode) { return; } if (saveLastMode) { this._headerState.saveState(); this.saveState(); } const change = this.modeChangeFromCurrent(newMode); this._headerState.mode = newMode; this._headerChange$.next(change); } confirmEditMode() { this._headerState.restoreLastMode(); this.saveNewState(); const change = this.modeChangeAfterEdit(); const viewId = this.getViewId(); if (!!viewId) { const headers = this.headerState.selectedHeaders; this._preferences.setHeaders(viewId, headers.map(header => !!header ? header.uniqueId : '')); } this._headerChange$.next(change); } /** * When user cancels the edit mode, the last saved headers state is loaded and emitted * Last mode in header is reloaded as well. Possible reloaded modes: sort or search */ revertEditMode() { this._headerState.restoreLastState(); this.restoreLastState(); const change = this.modeChangeAfterEdit(); this._headerChange$.next({ headerType: this.headerType, changeType: HeaderChangeType.EDIT, description: { preferredHeaders: this._headerState.selectedHeaders } }); this._headerChange$.next(change); } ngOnDestroy() { this._headerChange$.complete(); this._clearHeaderSearch$.complete(); this._headerColumnCount$.complete(); this._responsiveHeaders$.complete(); this.loading.complete(); this._preferenceColumnCount$.complete(); } /** * @param newMode the {@link HeaderMode} that is being selected as the next mode * @returnsa {@link HeaderChange} object with {@link ModeChangeDescription} object as it's `description`, * where the `previousMode` is set to the currently selected mode and the `currentMode` is set to the provided argument */ modeChangeFromCurrent(newMode) { return this.createModeChange(this._headerState.mode, newMode); } /** * @returns a {@link HeaderChange} object with {@link ModeChangeDescription} object as it's `description`, * where the `previousMode` is set to [EDIT]{@link HeaderMode#EDIT} and the `currentMode` to the mode * that is currently selected */ modeChangeAfterEdit() { return this.createModeChange(HeaderMode.EDIT, this._headerState.mode); } /** * @param oldMode the {@link HeaderMode} that was previously selected * @param newMode the {@link HeaderMode} that is selected now * @returns a {@link HeaderChange} object with {@link ModeChangeDescription} object as it's `description` * containing information about a change to the header mode */ createModeChange(oldMode, newMode) { return { changeType: HeaderChangeType.MODE_CHANGED, description: { currentMode: newMode, previousMode: oldMode }, headerType: this.headerType }; } /** * Emits a new value into the [clearHeaderSearch$]{@link AbstractHeaderService#clearHeaderSearch$} stream, that notifies * the header search component, that it should clear the input for the specified column. * @param columnIndex the index of the column that should be cleared */ clearHeaderSearch(columnIndex) { this._clearHeaderSearch$.next(columnIndex); } /** * @returns the Id of the view, if the ViewIdService was injected. Returns `undefined` if the service was not injected. */ getViewId() { if (this._viewIdService) { return this._viewIdService.viewId; } return undefined; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AbstractHeaderService, deps: [{ token: i1.HeaderType }, { token: i2.UserPreferenceService }, { token: i3.LoggerService }, { token: i4.ViewIdService, optional: true }, { token: i5.OverflowService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AbstractHeaderService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AbstractHeaderService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.HeaderType }, { type: i2.UserPreferenceService }, { type: i3.LoggerService }, { type: i4.ViewIdService, decorators: [{ type: Optional }] }, { type: i5.OverflowService, decorators: [{ type: Optional }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3QtaGVhZGVyLXNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZXRncmlmLWNvbXBvbmVudHMtY29yZS9zcmMvbGliL2hlYWRlci9hYnN0cmFjdC1oZWFkZXItc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsZUFBZSxFQUFjLGFBQWEsRUFBRSxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFFekUsT0FBTyxFQUFDLFdBQVcsRUFBdUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRSxPQUFPLEVBQUMsVUFBVSxFQUFhLFFBQVEsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQU05RCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDaEQsT0FBTyxFQUFDLFlBQVksRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBR3RFLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUUxRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSwwQ0FBMEMsQ0FBQzs7Ozs7OztBQU0xRSxNQUFNLE9BQWdCLHFCQUFxQjtJQWlCUDtJQUNBO0lBQ0E7SUFDVTtJQUNFO0lBbkJyQyxNQUFNLENBQVUsb0JBQW9CLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sQ0FBVSwyQkFBMkIsR0FBRyxJQUFJLENBQUM7SUFFaEQsbUJBQW1CLENBQTBCO0lBQzdDLHVCQUF1QixDQUF3QjtJQUMvQyxtQkFBbUIsQ0FBMkI7SUFDOUMsWUFBWSxDQUFjO0lBQzFCLGNBQWMsQ0FBd0I7SUFDdEMsbUJBQW1CLENBQWtCO0lBQ3ZDLG1CQUFtQixDQUFnQjtJQUNuQyxpQkFBaUIsQ0FBVTtJQUU1QixPQUFPLENBQWlCO0lBQ3hCLFdBQVcsQ0FBcUI7SUFFdkMsWUFBZ0MsV0FBdUIsRUFDdkIsWUFBbUMsRUFDbkMsT0FBc0IsRUFDWixjQUE2QixF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Q3JDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDckIsQ0FBQzt3R0FwY2lCLHFCQUFxQjs0R0FBckIscUJBQXFCOzs0RkFBckIscUJBQXFCO2tCQUQxQyxVQUFVOzswQkFxQmdCLFFBQVE7OzBCQUNSLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0ZpZWxkc0dyb3VwfSBmcm9tICcuL21vZGVscy9maWVsZHMtZ3JvdXAnO1xuaW1wb3J0IHtIZWFkZXJTdGF0ZSwgSGVhZGVyU3RhdGVJbnRlcmZhY2V9IGZyb20gJy4vaGVhZGVyLXN0YXRlJztcbmltcG9ydCB7SW5qZWN0YWJsZSwgT25EZXN0cm95LCBPcHRpb25hbH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1NvcnRDaGFuZ2VEZXNjcmlwdGlvbn0gZnJvbSAnLi9tb2RlbHMvdXNlci1jaGFuZ2VzL3NvcnQtY2hhbmdlLWRlc2NyaXB0aW9uJztcbmltcG9ydCB7U2VhcmNoQ2hhbmdlRGVzY3JpcHRpb259IGZyb20gJy4vbW9kZWxzL3VzZXItY2hhbmdlcy9zZWFyY2gtY2hhbmdlLWRlc2NyaXB0aW9uJztcbmltcG9ydCB7SGVhZGVyQ2hhbmdlfSBmcm9tICcuL21vZGVscy91c2VyLWNoYW5nZXMvaGVhZGVyLWNoYW5nZSc7XG5pbXBvcnQge1BldHJpTmV0UmVmZXJlbmNlfSBmcm9tICcuLi9yZXNvdXJjZXMvaW50ZXJmYWNlL3BldHJpLW5ldC1yZWZlcmVuY2UnO1xuaW1wb3J0IHtIZWFkZXJUeXBlfSBmcm9tICcuL21vZGVscy9oZWFkZXItdHlwZSc7XG5pbXBvcnQge0hlYWRlck1vZGV9IGZyb20gJy4vbW9kZWxzL2hlYWRlci1tb2RlJztcbmltcG9ydCB7SGVhZGVyQ29sdW1uLCBIZWFkZXJDb2x1bW5UeXBlfSBmcm9tICcuL21vZGVscy9oZWFkZXItY29sdW1uJztcbmltcG9ydCB7VXNlclByZWZlcmVuY2VTZXJ2aWNlfSBmcm9tICcuLi91c2VyL3NlcnZpY2VzL3VzZXItcHJlZmVyZW5jZS5zZXJ2aWNlJztcbmltcG9ydCB7TG9nZ2VyU2VydmljZX0gZnJvbSAnLi4vbG9nZ2VyL3NlcnZpY2VzL2xvZ2dlci5zZXJ2aWNlJztcbmltcG9ydCB7TG9hZGluZ0VtaXR0ZXJ9IGZyb20gJy4uL3V0aWxpdHkvbG9hZGluZy1lbWl0dGVyJztcbmltcG9ydCB7U29ydERpcmVjdGlvbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc29ydCc7XG5pbXBvcnQge0hlYWRlckNoYW5nZVR5cGV9IGZyb20gJy4vbW9kZWxzL3VzZXItY2hhbmdlcy9oZWFkZXItY2hhbmdlLXR5cGUnO1xuaW1wb3J0IHtWaWV3SWRTZXJ2aWNlfSBmcm9tICcuLi91c2VyL3NlcnZpY2VzL3ZpZXctaWQuc2VydmljZSc7XG5pbXBvcnQge05ldH0gZnJvbSAnLi4vcHJvY2Vzcy9uZXQnO1xuaW1wb3J0IHtPdmVyZmxvd1NlcnZpY2V9IGZyb20gJy4vc2VydmljZXMvb3ZlcmZsb3cuc2VydmljZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBYnN0cmFjdEhlYWRlclNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0hFQURFUl9DT1VOVCA9IDU7XG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0hFQURFUl9SRVNQT05TSVZJVFkgPSB0cnVlO1xuXG4gICAgcHJvdGVjdGVkIF9oZWFkZXJDb2x1bW5Db3VudCQ6IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+O1xuICAgIHByb3RlY3RlZCBfcHJlZmVyZW5jZUNvbHVtbkNvdW50JDogUmVwbGF5U3ViamVjdDxudW1iZXI+O1xuICAgIHByb3RlY3RlZCBfcmVzcG9uc2l2ZUhlYWRlcnMkOiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj47XG4gICAgcHJvdGVjdGVkIF9oZWFkZXJTdGF0ZTogSGVhZGVyU3RhdGU7XG4gICAgcHJvdGVjdGVkIF9oZWFkZXJDaGFuZ2UkOiBTdWJqZWN0PEhlYWRlckNoYW5nZT47XG4gICAgcHJvdGVjdGVkIF9jbGVhckhlYWRlclNlYXJjaCQ6IFN1YmplY3Q8bnVtYmVyPjtcbiAgICBwcml2YXRlIF9pbml0RGVmYXVsdEhlYWRlcnM6IEFycmF5PHN0cmluZz47XG4gICAgcHJpdmF0ZSBfaW5pdGlhbGl6ZWRDb3VudDogYm9vbGVhbjtcblxuICAgIHB1YmxpYyBsb2FkaW5nOiBMb2FkaW5nRW1pdHRlcjtcbiAgICBwdWJsaWMgZmllbGRzR3JvdXA6IEFycmF5PEZpZWxkc0dyb3VwPjtcblxuICAgIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX2hlYWRlclR5cGU6IEhlYWRlclR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfcHJlZmVyZW5jZXM6IFVzZXJQcmVmZXJlbmNlU2VydmljZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9sb2dnZXI6IExvZ2dlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByaXZhdGUgX3ZpZXdJZFNlcnZpY2U6IFZpZXdJZFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByb3RlY3RlZCBfb3ZlcmZsb3dTZXJ2aWNlOiBPdmVyZmxvd1NlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gbmV3IExvYWRpbmdFbWl0dGVyKHRydWUpO1xuICAgICAgICB0aGlzLl9oZWFkZXJDaGFuZ2UkID0gbmV3IFN1YmplY3Q8SGVhZGVyQ2hhbmdlPigpO1xuICAgICAgICB0aGlzLmZpZWxkc0dyb3VwID0gW3tncm91cFRpdGxlOiAnTWV0YSBkYXRhJywgZmllbGRzOiB0aGlzLmNyZWF0ZU1ldGFIZWFkZXJzKCl9XTtcbiAgICAgICAgdGhpcy5faGVhZGVyQ29sdW1uQ291bnQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KEFic3RyYWN0SGVhZGVyU2VydmljZS5ERUZBVUxUX0hFQURFUl9DT1VOVCk7XG4gICAgICAgIHRoaXMuX3Jlc3BvbnNpdmVIZWFkZXJzJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oQWJzdHJhY3RIZWFkZXJTZXJ2aWNlLkRFRkFVTFRfSEVBREVSX1JFU1BPTlNJVklUWSk7XG4gICAgICAgIHRoaXMuX3ByZWZlcmVuY2VDb2x1bW5Db3VudCQgPSBuZXcgUmVwbGF5U3ViamVjdDxudW1iZXI+KCk7XG4gICAgICAgIHRoaXMuX2NsZWFySGVhZGVyU2VhcmNoJCA9IG5ldyBTdWJqZWN0PG51bWJlcj4oKTtcbiAgICAgICAgdGhpcy5faW5pdGlhbGl6ZWRDb3VudCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh0aGlzLl92aWV3SWRTZXJ2aWNlID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2dnZXIud2FybignSGVhZGVyIHNlcnZpY2UgY291bGQgbm90IGluamVjdCBWaWV3SWRTZXJ2aWNlISBVc2VyIHByZWZlcmVuY2VzIHdvblxcJ3QgYmUgbG9hZGVkIG9yIHNhdmVkIScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcHJlZmVyZW5jZXMucHJlZmVyZW5jZXNDaGFuZ2VkJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2FkSGVhZGVyc0Zyb21QcmVmZXJlbmNlcygpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVIZWFkZXJTdGF0ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb3ZpZGVzIE9ic2VydmFibGUgZm9yIGFsbCBjaGFuZ2VzIGluIGhlYWRlclxuICAgICAqL1xuICAgIGdldCBoZWFkZXJDaGFuZ2UkKCk6IE9ic2VydmFibGU8SGVhZGVyQ2hhbmdlPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJDaGFuZ2UkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIGdldCBzZWxlY3RlZEhlYWRlcnMkKCk6IE9ic2VydmFibGU8QXJyYXk8SGVhZGVyQ29sdW1uPj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyU3RhdGUuc2VsZWN0ZWRIZWFkZXJzJDtcbiAgICB9XG5cbiAgICBnZXQgaGVhZGVyU3RhdGUoKTogSGVhZGVyU3RhdGVJbnRlcmZhY2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyU3RhdGUuYXNJbnRlcmZhY2UoKTtcbiAgICB9XG5cbiAgICBnZXQgaGVhZGVyVHlwZSgpOiBIZWFkZXJUeXBlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYWRlclR5cGU7XG4gICAgfVxuXG4gICAgZ2V0IG92ZXJmbG93TW9kZSgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCEhdGhpcy5fb3ZlcmZsb3dTZXJ2aWNlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3ZlcmZsb3dTZXJ2aWNlLm92ZXJmbG93TW9kZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldCBoZWFkZXJDb2x1bW5Db3VudCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyQ29sdW1uQ291bnQkLmdldFZhbHVlKCk7XG4gICAgfVxuXG4gICAgc2V0IGhlYWRlckNvbHVtbkNvdW50KG1heENvbHVtbnM6IG51bWJlcikge1xuICAgICAgICBpZiAobWF4Q29sdW1ucyAhPT0gdGhpcy5oZWFkZXJDb2x1bW5Db3VudCkge1xuICAgICAgICAgICAgdGhpcy5faGVhZGVyQ29sdW1uQ291bnQkLm5leHQobWF4Q29sdW1ucyk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUhlYWRlckNvbHVtbkNvdW50KCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2luaXRpYWxpemVkQ291bnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRpYWxpemVEZWZhdWx0SGVhZGVyU3RhdGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0aWFsaXplZENvdW50ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldCBoZWFkZXJDb2x1bW5Db3VudCQoKTogT2JzZXJ2YWJsZTxudW1iZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYWRlckNvbHVtbkNvdW50JC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBnZXQgcmVzcG9uc2l2ZUhlYWRlcnMoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXNwb25zaXZlSGVhZGVycyQuZ2V0VmFsdWUoKTtcbiAgICB9XG5cbiAgICBzZXQgcmVzcG9uc2l2ZUhlYWRlcnMocmVzcG9uc2l2ZUhlYWRlcnM6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUhlYWRlcnMkLm5leHQocmVzcG9uc2l2ZUhlYWRlcnMpO1xuICAgIH1cblxuICAgIGdldCByZXNwb25zaXZlSGVhZGVycyQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXNwb25zaXZlSGVhZGVycyQuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgZ2V0IGNsZWFySGVhZGVyU2VhcmNoJCgpOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xlYXJIZWFkZXJTZWFyY2gkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHNldCBpbml0RGVmYXVsdEhlYWRlcnMoZGVmYXVsdEhlYWRlcnM6IEFycmF5PHN0cmluZz4pIHtcbiAgICAgICAgdGhpcy5faW5pdERlZmF1bHRIZWFkZXJzID0gZGVmYXVsdEhlYWRlcnM7XG4gICAgfVxuXG4gICAgZ2V0IGluaXREZWZhdWx0SGVhZGVycygpOiBBcnJheTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2luaXREZWZhdWx0SGVhZGVycztcbiAgICB9XG5cbiAgICBnZXQgcHJlZmVyZW5jZUNvbHVtbkNvdW50JCgpOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcHJlZmVyZW5jZUNvbHVtbkNvdW50JC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRpYWxpemVIZWFkZXJTdGF0ZSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZGVmYXVsdEhlYWRlcnMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmZpZWxkc0dyb3VwWzBdLmZpZWxkcy5sZW5ndGggJiYgZGVmYXVsdEhlYWRlcnMubGVuZ3RoIDwgdGhpcy5oZWFkZXJDb2x1bW5Db3VudDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5maWVsZHNHcm91cFswXS5maWVsZHNbaV0uaW5pdGlhbCkge1xuICAgICAgICAgICAgICAgIGRlZmF1bHRIZWFkZXJzLnB1c2godGhpcy5maWVsZHNHcm91cFswXS5maWVsZHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChkZWZhdWx0SGVhZGVycy5sZW5ndGggPCB0aGlzLmhlYWRlckNvbHVtbkNvdW50KSB7XG4gICAgICAgICAgICBkZWZhdWx0SGVhZGVycy5wdXNoKG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2hlYWRlclN0YXRlID0gbmV3IEhlYWRlclN0YXRlKGRlZmF1bHRIZWFkZXJzKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaW5pdGlhbGl6ZURlZmF1bHRIZWFkZXJTdGF0ZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaW5pdERlZmF1bHRIZWFkZXJzICYmIEFycmF5LmlzQXJyYXkodGhpcy5pbml0RGVmYXVsdEhlYWRlcnMpKSB7XG4gICAgICAgICAgICBjb25zdCBkZWZhdWx0SGVhZGVycyA9IFtdO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmhlYWRlckNvbHVtbkNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0SGVhZGVycy5wdXNoKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmluaXREZWZhdWx0SGVhZGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChpID49IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9nZ2VyLndhcm4oJ3RoZXJlIGFyZSBtb3JlIE5BRV9ERUZBVUxUX0hFQURFUlMgdGhhbiBoZWFkZXIgY29sdW1ucy4gU2tpcHBpbmcgdGhlIHJlc3QuLi4nKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaCBvZiB0aGlzLmZpZWxkc0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlYWQgPSBoLmZpZWxkcy5maW5kKGhlYWRlciA9PiBoZWFkZXIudW5pcXVlSWQgPT09IHRoaXMuaW5pdERlZmF1bHRIZWFkZXJzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGhlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRIZWFkZXJzW2ldID0gaGVhZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUudXBkYXRlU2VsZWN0ZWRIZWFkZXJzKGRlZmF1bHRIZWFkZXJzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxvYWRIZWFkZXJzRnJvbVByZWZlcmVuY2VzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBgbnVsbGAgaGVhZGVycyBpZiB0aGUgbmV3IGNvdW50IGlzIGdyZWF0ZXIgdGhhbiB0aGUgY3VycmVudCBjb3VudC5cbiAgICAgKlxuICAgICAqIFJlbW92ZXMgZXh0cmEgaGVhZGVycyBpZiB0aGUgbmV3IGNvdW50IGlzIHNtYWxsZXIgdGhhbiB0aGUgY3VycmVudCBjb3VudC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgdXBkYXRlSGVhZGVyQ29sdW1uQ291bnQoKTogdm9pZCB7XG4gICAgICAgIGxldCBoZWFkZXJzID0gdGhpcy5faGVhZGVyU3RhdGUuc2VsZWN0ZWRIZWFkZXJzO1xuICAgICAgICBpZiAoaGVhZGVycy5sZW5ndGggPCB0aGlzLmhlYWRlckNvbHVtbkNvdW50KSB7XG4gICAgICAgICAgICBjb25zdCBsYXN0U2VsZWN0ZWRIZWFkZXJzID0gdGhpcy5faGVhZGVyU3RhdGUubGFzdFNlbGVjdGVkSGVhZGVycztcbiAgICAgICAgICAgIGlmIChoZWFkZXJzLmxlbmd0aCA8IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQgJiYgISFsYXN0U2VsZWN0ZWRIZWFkZXJzICYmIGhlYWRlcnMubGVuZ3RoIDwgbGFzdFNlbGVjdGVkSGVhZGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXJzLnB1c2goLi4ubGFzdFNlbGVjdGVkSGVhZGVycy5zbGljZShoZWFkZXJzLmxlbmd0aCwgdGhpcy5oZWFkZXJDb2x1bW5Db3VudCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGhlYWRlcnMubGVuZ3RoIDw9IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXJzLnB1c2gobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaGVhZGVycy5sZW5ndGggPiB0aGlzLmhlYWRlckNvbHVtbkNvdW50KSB7XG4gICAgICAgICAgICBoZWFkZXJzID0gaGVhZGVycy5zbGljZSgwLCB0aGlzLmhlYWRlckNvbHVtbkNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9oZWFkZXJTdGF0ZS51cGRhdGVTZWxlY3RlZEhlYWRlcnMoaGVhZGVycyk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldEFsbG93ZWROZXRzKGFsbG93ZWROZXRzOiBBcnJheTxQZXRyaU5ldFJlZmVyZW5jZT4pIHtcbiAgICAgICAgLyogVE9ETyBieSBzaW1wbHkgcmVwbGFjaW5nIHRoZSBzZWxlY3Qgb3B0aW9ucyB3aXRoIG5ldyBvYmplY3QsIHdlIGRvbid0IGxvb3NlIHRoZSBvbGQgcmVmZXJlbmNlcy5cbiAgICAgICAgICAgICBDb2x1bW5zIHdpdGggaGVhZGVycyBmcm9tIG5ldHMgdGhhdCBhcmUgbm8gbG9uZ2VyIGFsbG93ZWQgc2hvdWxkIGhhdmUgdGhlaXIgdmFsdWUgY2xlYXJlZC5cbiAgICAgICAgICAgICBDb2x1bW5zIHdpdGggdmFsaWQgdmFsdWVzIHRoYXQgYXJlIG5vdCBtZXRhZGF0YSBzaG91bGQgaGF2ZSB0aGVpciBzZWxlY3Rpb24gcmVtYXBwZWQgdG8gdGhlIG5ldyBvYmplY3RzLlxuICAgICAgICAgKi9cblxuICAgICAgICBjb25zdCBmaWVsZHNHcm91cHM6IEFycmF5PEZpZWxkc0dyb3VwPiA9IFtdO1xuICAgICAgICBhbGxvd2VkTmV0cy5mb3JFYWNoKGFsbG93ZWROZXQgPT4ge1xuICAgICAgICAgICAgY29uc3QgZmllbGRzR3JvdXA6IEZpZWxkc0dyb3VwID0ge1xuICAgICAgICAgICAgICAgIGdyb3VwVGl0bGU6IGFsbG93ZWROZXQudGl0bGUsXG4gICAgICAgICAgICAgICAgZmllbGRzOiBbXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGFsbG93ZWROZXQuaW1tZWRpYXRlRGF0YS5mb3JFYWNoKGltbWVkaWF0ZSA9PiB7XG4gICAgICAgICAgICAgICAgZmllbGRzR3JvdXAuZmllbGRzLnB1c2goXG4gICAgICAgICAgICAgICAgICAgIG5ldyBIZWFkZXJDb2x1bW4oSGVhZGVyQ29sdW1uVHlwZS5JTU1FRElBVEUsIGltbWVkaWF0ZS5zdHJpbmdJZCwgaW1tZWRpYXRlLnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW1tZWRpYXRlLnR5cGUsIGZhbHNlLCBhbGxvd2VkTmV0LmlkZW50aWZpZXIpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZmllbGRzR3JvdXBzLnB1c2goZmllbGRzR3JvdXApO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmZpZWxkc0dyb3VwLnNwbGljZSgxLCB0aGlzLmZpZWxkc0dyb3VwLmxlbmd0aCAtIDEpO1xuICAgICAgICB0aGlzLmZpZWxkc0dyb3VwLnB1c2goLi4uZmllbGRzR3JvdXBzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0VGFza0FsbG93ZWROZXRzKGFsbG93ZWROZXRzOiBBcnJheTxOZXQ+KSB7XG4gICAgICAgIC8qIFRPRE8gYnkgc2ltcGx5IHJlcGxhY2luZyB0aGUgc2VsZWN0IG9wdGlvbnMgd2l0aCBuZXcgb2JqZWN0LCB3ZSBkb24ndCBsb29zZSB0aGUgb2xkIHJlZmVyZW5jZXMuXG4gICAgICAgICAgICAgQ29sdW1ucyB3aXRoIGhlYWRlcnMgZnJvbSBuZXRzIHRoYXQgYXJlIG5vIGxvbmdlciBhbGxvd2VkIHNob3VsZCBoYXZlIHRoZWlyIHZhbHVlIGNsZWFyZWQuXG4gICAgICAgICAgICAgQ29sdW1ucyB3aXRoIHZhbGlkIHZhbHVlcyB0aGF0IGFyZSBub3QgbWV0YWRhdGEgc2hvdWxkIGhhdmUgdGhlaXIgc2VsZWN0aW9uIHJlbWFwcGVkIHRvIHRoZSBuZXcgb2JqZWN0cy5cbiAgICAgICAgICovXG5cbiAgICAgICAgY29uc3QgZmllbGRzR3JvdXBzOiBBcnJheTxGaWVsZHNHcm91cD4gPSBbXTtcbiAgICAgICAgYWxsb3dlZE5ldHMuZm9yRWFjaChhbGxvd2VkTmV0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkc0dyb3VwOiBGaWVsZHNHcm91cCA9IHtcbiAgICAgICAgICAgICAgICBncm91cFRpdGxlOiBhbGxvd2VkTmV0LnRpdGxlLFxuICAgICAgICAgICAgICAgIGZpZWxkczogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBleGlzdGluZyA9IG5ldyBTZXQoKTtcbiAgICAgICAgICAgIGFsbG93ZWROZXQudHJhbnNpdGlvbnMuZm9yRWFjaCh0cmFucyA9PiB7XG4gICAgICAgICAgICAgICAgdHJhbnMuaW1tZWRpYXRlRGF0YS5mb3JFYWNoKGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV4aXN0aW5nLmhhcyhkYXRhLnN0cmluZ0lkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcuYWRkKGRhdGEuc3RyaW5nSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmllbGRzR3JvdXAuZmllbGRzLnB1c2goXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEhlYWRlckNvbHVtbihIZWFkZXJDb2x1bW5UeXBlLklNTUVESUFURSwgZGF0YS5zdHJpbmdJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50aXRsZSwgZGF0YS50eXBlLCBmYWxzZSwgYWxsb3dlZE5ldC5pZGVudGlmaWVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmaWVsZHNHcm91cHMucHVzaChmaWVsZHNHcm91cCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAuc3BsaWNlKDEsIHRoaXMuZmllbGRzR3JvdXAubGVuZ3RoIC0gMSk7XG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAucHVzaCguLi5maWVsZHNHcm91cHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHRoaXMgdmlldyBoYXMgc29tIGhlYWRlcnMgc3RvcmVkIGluIGl0J3MgcHJlZmVyZW5jZXMgYXR0ZW1wdHMgdG8gbG9hZCB0aGVtLlxuICAgICAqIElmIHRoZSBwcmVmZXJlbmNlcyBjb250YWluIG5vbmV4aXN0ZW50IGhlYWRlcnMgdGhleSB3aWxsIGJlIHNraXBwZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIE5PVCBjYWxsZWQgYnkgdGhlIGFic3RyYWN0IGNsYXNzJyBjb25zdHJ1Y3Rvci5cbiAgICAgKiBJdCBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgdGhlIGNoaWxkIGNsYXNzIHRvIGNhbGwgaXQgYXQgYW4gYXBwcm9wcmlhdGUgbW9tZW50LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBsb2FkSGVhZGVyc0Zyb21QcmVmZXJlbmNlcygpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgdmlld0lkID0gdGhpcy5nZXRWaWV3SWQoKTtcbiAgICAgICAgaWYgKCF2aWV3SWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcmVmZXJyZWRIZWFkZXJLZXlzID0gdGhpcy5fcHJlZmVyZW5jZXMuZ2V0SGVhZGVycyh2aWV3SWQpO1xuICAgICAgICBpZiAoIXByZWZlcnJlZEhlYWRlcktleXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuZXdIZWFkZXJzID0gW107XG4gICAgICAgIHByZWZlcnJlZEhlYWRlcktleXMuZm9yRWFjaChoZWFkZXJLZXkgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZEdyb3VwIG9mIHRoaXMuZmllbGRzR3JvdXApIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGhlYWRlciBvZiBmaWVsZEdyb3VwLmZpZWxkcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGVhZGVyLnVuaXF1ZUlkID09PSBoZWFkZXJLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0hlYWRlcnMucHVzaChoZWFkZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBjb250aW51ZSB0aGUgb3V0ZXJtb3N0IGxvb3BcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG5vIG1hdGNoIGZvdW5kXG4gICAgICAgICAgICBuZXdIZWFkZXJzLnB1c2gobnVsbCk7XG4gICAgICAgICAgICB0aGlzLl9sb2dnZXIud2F