@netgrif/components-core
Version:
Netgrif Application engine frontend core Angular library
524 lines • 78.2 kB
JavaScript
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 { HeaderSortingMode } from './models/header-sorting-mode';
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";
import * as i6 from "./models/header-sorting-mode";
export class AbstractHeaderService {
_headerType;
_preferences;
_logger;
_viewIdService;
_overflowService;
static DEFAULT_HEADER_COUNT = 5;
static DEFAULT_HEADER_RESPONSIVITY = true;
_headerColumnCount$;
_preferenceColumnCount$;
_responsiveHeaders$;
_headerState;
_headerChange$;
_appliedSorts$;
_clearHeaderSearch$;
_initDefaultHeaders;
_initializedCount;
_sortingMode;
loading;
fieldsGroup;
constructor(_headerType, _preferences, _logger, _viewIdService, _overflowService, sortingMode = HeaderSortingMode.SINGLE) {
this._headerType = _headerType;
this._preferences = _preferences;
this._logger = _logger;
this._viewIdService = _viewIdService;
this._overflowService = _overflowService;
this._sortingMode = sortingMode ?? HeaderSortingMode.SINGLE;
this.loading = new LoadingEmitter(true);
this._headerChange$ = new Subject();
this._appliedSorts$ = new ReplaySubject(1);
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.loadSortsFromPreferences();
});
this.initializeHeaderState();
}
/**
* Provides Observable for all changes in header
*/
get headerChange$() {
return this._headerChange$.asObservable();
}
get selectedHeaders$() {
return this._headerState.selectedHeaders$;
}
get selectedSorts$() {
return this._headerState.selectedSorts$;
}
get sortingMode() {
return this._sortingMode;
}
get appliedSorts$() {
return this._appliedSorts$.asObservable();
}
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();
this.loadSortsFromPreferences();
}
/**
* 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);
}
loadSortsFromPreferences() {
const viewId = this.getViewId();
if (!viewId) {
this.applySelectedSorts();
return;
}
const preferredSorts = this._preferences.getSorts(viewId);
const headersWithSortState = new Set(this._headerState.selectedSorts);
this.fieldsGroup.forEach(fieldGroup => fieldGroup.fields.forEach(header => headersWithSortState.add(header)));
headersWithSortState.forEach(header => header.sortDirection = '');
if (!preferredSorts) {
this._headerState.updateSelectedSorts([]);
this.applySelectedSorts();
return;
}
const headersByUniqueId = new Map();
this.fieldsGroup.forEach(fieldGroup => fieldGroup.fields.forEach(header => {
if (!headersByUniqueId.has(header.uniqueId)) {
headersByUniqueId.set(header.uniqueId, header);
}
}));
const resolvedSorts = preferredSorts
.map(preference => ({
header: headersByUniqueId.get(preference.headerUniqueId),
direction: preference.sortDirection
}))
.filter((resolved) => !!resolved.header);
const applicableSorts = this._sortingMode === HeaderSortingMode.SINGLE
? resolvedSorts.slice(0, 1)
: resolvedSorts;
applicableSorts.forEach(sort => sort.header.sortDirection = sort.direction);
const newSorts = applicableSorts.map(sort => sort.header);
this._headerState.updateSelectedSorts(newSorts);
this.applySelectedSorts();
}
/**
* 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) {
const selectedHeaders = this.headerState.selectedHeaders.filter(header => !!header);
const sortingHeader = selectedHeaders.find(header => header.uniqueId === active);
const headersWithSortState = new Set([
...selectedHeaders,
...this._headerState.selectedSorts
]);
headersWithSortState.forEach(header => header.sortDirection = header === sortingHeader ? direction : '');
this._headerState.updateSelectedSorts(sortingHeader && direction ? [sortingHeader] : []);
const sortChangeDescription = sortingHeader ? {
sortDirection: direction,
columnType: sortingHeader.type,
fieldIdentifier: sortingHeader.fieldIdentifier,
petriNetIdentifier: sortingHeader.petriNetIdentifier,
columnIdentifier: columnIndex,
fieldType: sortingHeader.fieldType
} : undefined;
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);
const previousHeader = newHeaders[columnIndex];
newHeaders[columnIndex] = newHeaderColumn;
if (!!previousHeader && !newHeaders.includes(previousHeader)) {
previousHeader.sortDirection = '';
previousHeader.searchInput = undefined;
this._headerState.updateSelectedSorts(this._headerState.selectedSorts.filter(header => header !== previousHeader));
}
this._headerState.updateSelectedHeaders(newHeaders);
this._headerChange$.next({
headerType: this.headerType,
changeType: HeaderChangeType.EDIT,
description: { preferredHeaders: this._headerState.selectedHeaders }
});
}
sortingColumnSelected(newHeaderColumn) {
if (!newHeaderColumn) {
return;
}
const multiSelection = this._sortingMode === HeaderSortingMode.MULTI ||
(this._sortingMode === HeaderSortingMode.COMBINED && this._headerState.mode === HeaderMode.EDIT);
const newSortingHeaders = multiSelection ?
this._headerState.selectedSorts.filter(header => header.uniqueId !== newHeaderColumn.uniqueId) : [];
this._headerState.selectedSorts
.filter(header => header !== newHeaderColumn &&
(!multiSelection || header.uniqueId === newHeaderColumn.uniqueId))
.forEach(header => header.sortDirection = '');
if (!!newHeaderColumn.sortDirection) {
newSortingHeaders.push(newHeaderColumn);
}
this._headerState.updateSelectedSorts(newSortingHeaders);
}
/**
* 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;
const sorts = this.headerState.selectedSorts;
this._preferences.setHeadersAndSorts(viewId, headers.map(header => !!header ? header.uniqueId : ''), sorts.map(sort => {
return { headerUniqueId: sort.uniqueId, sortDirection: sort.sortDirection };
}));
}
this.applySelectedSorts();
this._headerChange$.next(change);
}
updateSortMode() {
const change = this.modeChangeAfterSort();
this.applySelectedSorts();
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();
this.applySelectedSorts();
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._appliedSorts$.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);
}
modeChangeAfterSort() {
return this.createModeChange(HeaderMode.SORT, 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 snapshot of the currently selected sorting so registered views can reload without persisting user preferences.
*/
applySelectedSorts() {
const appliedSorts = this._headerState.selectedSorts.map(header => {
const snapshot = new HeaderColumn(header.type, header.fieldIdentifier, header.title, header.fieldType, header.initial, header.petriNetIdentifier);
snapshot.sortDirection = header.sortDirection;
return snapshot;
});
this._appliedSorts$.next(appliedSorts);
}
/**
* 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 }, { token: i6.HeaderSortingMode }], 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
}] }, { type: i6.HeaderSortingMode }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3QtaGVhZGVyLXNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZXRncmlmLWNvbXBvbmVudHMtY29yZS9zcmMvbGliL2hlYWRlci9hYnN0cmFjdC1oZWFkZXItc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsZUFBZSxFQUFjLGFBQWEsRUFBRSxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFFekUsT0FBTyxFQUFDLFdBQVcsRUFBdUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRSxPQUFPLEVBQUMsVUFBVSxFQUFhLFFBQVEsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQU05RCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDaEQsT0FBTyxFQUFDLFlBQVksRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBR3RFLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUUxRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSwwQ0FBMEMsQ0FBQztBQUsxRSxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSw4QkFBOEIsQ0FBQzs7Ozs7Ozs7QUFHL0QsTUFBTSxPQUFnQixxQkFBcUI7SUFtQlA7SUFDQTtJQUNBO0lBQ1U7SUFDRTtJQXJCckMsTUFBTSxDQUFVLG9CQUFvQixHQUFHLENBQUMsQ0FBQztJQUN6QyxNQUFNLENBQVUsMkJBQTJCLEdBQUcsSUFBSSxDQUFDO0lBRWhELG1CQUFtQixDQUEwQjtJQUM3Qyx1QkFBdUIsQ0FBd0I7SUFDL0MsbUJBQW1CLENBQTJCO0lBQzlDLFlBQVksQ0FBYztJQUMxQixjQUFjLENBQXdCO0lBQ3RDLGNBQWMsQ0FBcUM7SUFDbkQsbUJBQW1CLENBQWtCO0lBQ3ZDLG1CQUFtQixDQUFnQjtJQUNuQyxpQkFBaUIsQ0FBVTtJQUNsQixZQUFZLENBQW9CO0lBRTFDLE9B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O1NBQzlCLENBQUM7SUFDTixDQUFDO0lBRUQ7O09BRUc7SUFDSSxrQkFBa0I7UUFDckIsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQzlELE1BQU0sUUFBUSxHQUFHLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLGVBQWUsRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQ2pHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDL0MsUUFBUSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDO1lBQzlDLE9BQU8sUUFBUSxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxpQkFBaUIsQ0FBQyxXQUFtQjtRQUN4QyxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRDs7T0FFRztJQUNPLFNBQVM7UUFDZixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDckIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQztTQUNyQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7d0dBaGpCaUIscUJBQXFCOzRHQUFyQixxQkFBcUI7OzRGQUFyQixxQkFBcUI7a0JBRDFDLFVBQVU7OzBCQXVCZ0IsUUFBUTs7MEJBQ1IsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBSZXBsYXlTdWJqZWN0LCBTdWJqZWN0fSBmcm9tICdyeGpzJztcbmltcG9ydCB7RmllbGRzR3JvdXB9IGZyb20gJy4vbW9kZWxzL2ZpZWxkcy1ncm91cCc7XG5pbXBvcnQge0hlYWRlclN0YXRlLCBIZWFkZXJTdGF0ZUludGVyZmFjZX0gZnJvbSAnLi9oZWFkZXItc3RhdGUnO1xuaW1wb3J0IHtJbmplY3RhYmxlLCBPbkRlc3Ryb3ksIE9wdGlvbmFsfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7U29ydENoYW5nZURlc2NyaXB0aW9ufSBmcm9tICcuL21vZGVscy91c2VyLWNoYW5nZXMvc29ydC1jaGFuZ2UtZGVzY3JpcHRpb24nO1xuaW1wb3J0IHtTZWFyY2hDaGFuZ2VEZXNjcmlwdGlvbn0gZnJvbSAnLi9tb2RlbHMvdXNlci1jaGFuZ2VzL3NlYXJjaC1jaGFuZ2UtZGVzY3JpcHRpb24nO1xuaW1wb3J0IHtIZWFkZXJDaGFuZ2V9IGZyb20gJy4vbW9kZWxzL3VzZXItY2hhbmdlcy9oZWFkZXItY2hhbmdlJztcbmltcG9ydCB7UGV0cmlOZXRSZWZlcmVuY2V9IGZyb20gJy4uL3Jlc291cmNlcy9pbnRlcmZhY2UvcGV0cmktbmV0LXJlZmVyZW5jZSc7XG5pbXBvcnQge0hlYWRlclR5cGV9IGZyb20gJy4vbW9kZWxzL2hlYWRlci10eXBlJztcbmltcG9ydCB7SGVhZGVyTW9kZX0gZnJvbSAnLi9tb2RlbHMvaGVhZGVyLW1vZGUnO1xuaW1wb3J0IHtIZWFkZXJDb2x1bW4sIEhlYWRlckNvbHVtblR5cGV9IGZyb20gJy4vbW9kZWxzL2hlYWRlci1jb2x1bW4nO1xuaW1wb3J0IHtVc2VyUHJlZmVyZW5jZVNlcnZpY2V9IGZyb20gJy4uL3VzZXIvc2VydmljZXMvdXNlci1wcmVmZXJlbmNlLnNlcnZpY2UnO1xuaW1wb3J0IHtMb2dnZXJTZXJ2aWNlfSBmcm9tICcuLi9sb2dnZXIvc2VydmljZXMvbG9nZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHtMb2FkaW5nRW1pdHRlcn0gZnJvbSAnLi4vdXRpbGl0eS9sb2FkaW5nLWVtaXR0ZXInO1xuaW1wb3J0IHtTb3J0RGlyZWN0aW9ufSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zb3J0JztcbmltcG9ydCB7SGVhZGVyQ2hhbmdlVHlwZX0gZnJvbSAnLi9tb2RlbHMvdXNlci1jaGFuZ2VzL2hlYWRlci1jaGFuZ2UtdHlwZSc7XG5pbXBvcnQge1ZpZXdJZFNlcnZpY2V9IGZyb20gJy4uL3VzZXIvc2VydmljZXMvdmlldy1pZC5zZXJ2aWNlJztcbmltcG9ydCB7TmV0fSBmcm9tICcuLi9wcm9jZXNzL25ldCc7XG5pbXBvcnQge092ZXJmbG93U2VydmljZX0gZnJvbSAnLi9zZXJ2aWNlcy9vdmVyZmxvdy5zZXJ2aWNlJztcbmltcG9ydCB7U29ydGluZ0hlYWRlcn0gZnJvbSBcIi4uL3Jlc291cmNlcy9pbnRlcmZhY2Uvc29ydGluZy1oZWFkZXJcIjtcbmltcG9ydCB7SGVhZGVyU29ydGluZ01vZGV9IGZyb20gJy4vbW9kZWxzL2hlYWRlci1zb3J0aW5nLW1vZGUnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQWJzdHJhY3RIZWFkZXJTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcblxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9IRUFERVJfQ09VTlQgPSA1O1xuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9IRUFERVJfUkVTUE9OU0lWSVRZID0gdHJ1ZTtcblxuICAgIHByb3RlY3RlZCBfaGVhZGVyQ29sdW1uQ291bnQkOiBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPjtcbiAgICBwcm90ZWN0ZWQgX3ByZWZlcmVuY2VDb2x1bW5Db3VudCQ6IFJlcGxheVN1YmplY3Q8bnVtYmVyPjtcbiAgICBwcm90ZWN0ZWQgX3Jlc3BvbnNpdmVIZWFkZXJzJDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+O1xuICAgIHByb3RlY3RlZCBfaGVhZGVyU3RhdGU6IEhlYWRlclN0YXRlO1xuICAgIHByb3RlY3RlZCBfaGVhZGVyQ2hhbmdlJDogU3ViamVjdDxIZWFkZXJDaGFuZ2U+O1xuICAgIHByb3RlY3RlZCBfYXBwbGllZFNvcnRzJDogUmVwbGF5U3ViamVjdDxBcnJheTxIZWFkZXJDb2x1bW4+PjtcbiAgICBwcm90ZWN0ZWQgX2NsZWFySGVhZGVyU2VhcmNoJDogU3ViamVjdDxudW1iZXI+O1xuICAgIHByaXZhdGUgX2luaXREZWZhdWx0SGVhZGVyczogQXJyYXk8c3RyaW5nPjtcbiAgICBwcml2YXRlIF9pbml0aWFsaXplZENvdW50OiBib29sZWFuO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3NvcnRpbmdNb2RlOiBIZWFkZXJTb3J0aW5nTW9kZTtcblxuICAgIHB1YmxpYyBsb2FkaW5nOiBMb2FkaW5nRW1pdHRlcjtcbiAgICBwdWJsaWMgZmllbGRzR3JvdXA6IEFycmF5PEZpZWxkc0dyb3VwPjtcblxuICAgIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX2hlYWRlclR5cGU6IEhlYWRlclR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfcHJlZmVyZW5jZXM6IFVzZXJQcmVmZXJlbmNlU2VydmljZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9sb2dnZXI6IExvZ2dlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByaXZhdGUgX3ZpZXdJZFNlcnZpY2U6IFZpZXdJZFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByb3RlY3RlZCBfb3ZlcmZsb3dTZXJ2aWNlOiBPdmVyZmxvd1NlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHNvcnRpbmdNb2RlOiBIZWFkZXJTb3J0aW5nTW9kZSA9IEhlYWRlclNvcnRpbmdNb2RlLlNJTkdMRSkge1xuICAgICAgICB0aGlzLl9zb3J0aW5nTW9kZSA9IHNvcnRpbmdNb2RlID8/IEhlYWRlclNvcnRpbmdNb2RlLlNJTkdMRTtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gbmV3IExvYWRpbmdFbWl0dGVyKHRydWUpO1xuICAgICAgICB0aGlzLl9oZWFkZXJDaGFuZ2UkID0gbmV3IFN1YmplY3Q8SGVhZGVyQ2hhbmdlPigpO1xuICAgICAgICB0aGlzLl9hcHBsaWVkU29ydHMkID0gbmV3IFJlcGxheVN1YmplY3Q8QXJyYXk8SGVhZGVyQ29sdW1uPj4oMSk7XG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAgPSBbe2dyb3VwVGl0bGU6ICdNZXRhIGRhdGEnLCBmaWVsZHM6IHRoaXMuY3JlYXRlTWV0YUhlYWRlcnMoKX1dO1xuICAgICAgICB0aGlzLl9oZWFkZXJDb2x1bW5Db3VudCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PG51bWJlcj4oQWJzdHJhY3RIZWFkZXJTZXJ2aWNlLkRFRkFVTFRfSEVBREVSX0NPVU5UKTtcbiAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUhlYWRlcnMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihBYnN0cmFjdEhlYWRlclNlcnZpY2UuREVGQVVMVF9IRUFERVJfUkVTUE9OU0lWSVRZKTtcbiAgICAgICAgdGhpcy5fcHJlZmVyZW5jZUNvbHVtbkNvdW50JCA9IG5ldyBSZXBsYXlTdWJqZWN0PG51bWJlcj4oKTtcbiAgICAgICAgdGhpcy5fY2xlYXJIZWFkZXJTZWFyY2gkID0gbmV3IFN1YmplY3Q8bnVtYmVyPigpO1xuICAgICAgICB0aGlzLl9pbml0aWFsaXplZENvdW50ID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRoaXMuX3ZpZXdJZFNlcnZpY2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvZ2dlci53YXJuKCdIZWFkZXIgc2VydmljZSBjb3VsZCBub3QgaW5qZWN0IFZpZXdJZFNlcnZpY2UhIFVzZXIgcHJlZmVyZW5jZXMgd29uXFwndCBiZSBsb2FkZWQgb3Igc2F2ZWQhJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9wcmVmZXJlbmNlcy5wcmVmZXJlbmNlc0NoYW5nZWQkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvYWRIZWFkZXJzRnJvbVByZWZlcmVuY2VzKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRTb3J0c0Zyb21QcmVmZXJlbmNlcygpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVIZWFkZXJTdGF0ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb3ZpZGVzIE9ic2VydmFibGUgZm9yIGFsbCBjaGFuZ2VzIGluIGhlYWRlclxuICAgICAqL1xuICAgIGdldCBoZWFkZXJDaGFuZ2UkKCk6IE9ic2VydmFibGU8SGVhZGVyQ2hhbmdlPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJDaGFuZ2UkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIGdldCBzZWxlY3RlZEhlYWRlcnMkKCk6IE9ic2VydmFibGU8QXJyYXk8SGVhZGVyQ29sdW1uPj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyU3RhdGUuc2VsZWN0ZWRIZWFkZXJzJDtcbiAgICB9XG5cbiAgICBnZXQgc2VsZWN0ZWRTb3J0cyQoKTogT2JzZXJ2YWJsZTxBcnJheTxIZWFkZXJDb2x1bW4+PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZFNvcnRzJDtcbiAgICB9XG5cbiAgICBnZXQgc29ydGluZ01vZGUoKTogSGVhZGVyU29ydGluZ01vZGUge1xuICAgICAgICByZXR1cm4gdGhpcy5fc29ydGluZ01vZGU7XG4gICAgfVxuXG4gICAgZ2V0IGFwcGxpZWRTb3J0cyQoKTogT2JzZXJ2YWJsZTxBcnJheTxIZWFkZXJDb2x1bW4+PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBsaWVkU29ydHMkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIGdldCBoZWFkZXJTdGF0ZSgpOiBIZWFkZXJTdGF0ZUludGVyZmFjZSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJTdGF0ZS5hc0ludGVyZmFjZSgpO1xuICAgIH1cblxuICAgIGdldCBoZWFkZXJUeXBlKCk6IEhlYWRlclR5cGUge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyVHlwZTtcbiAgICB9XG5cbiAgICBnZXQgb3ZlcmZsb3dNb2RlKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoISF0aGlzLl9vdmVyZmxvd1NlcnZpY2UpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vdmVyZmxvd1NlcnZpY2Uub3ZlcmZsb3dNb2RlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0IGhlYWRlckNvbHVtbkNvdW50KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJDb2x1bW5Db3VudCQuZ2V0VmFsdWUoKTtcbiAgICB9XG5cbiAgICBzZXQgaGVhZGVyQ29sdW1uQ291bnQobWF4Q29sdW1uczogbnVtYmVyKSB7XG4gICAgICAgIGlmIChtYXhDb2x1bW5zICE9PSB0aGlzLmhlYWRlckNvbHVtbkNvdW50KSB7XG4gICAgICAgICAgICB0aGlzLl9oZWFkZXJDb2x1bW5Db3VudCQubmV4dChtYXhDb2x1bW5zKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSGVhZGVyQ29sdW1uQ291bnQoKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5faW5pdGlhbGl6ZWRDb3VudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZURlZmF1bHRIZWFkZXJTdGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRpYWxpemVkQ291bnQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0IGhlYWRlckNvbHVtbkNvdW50JCgpOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyQ29sdW1uQ291bnQkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIGdldCByZXNwb25zaXZlSGVhZGVycygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Jlc3BvbnNpdmVIZWFkZXJzJC5nZXRWYWx1ZSgpO1xuICAgIH1cblxuICAgIHNldCByZXNwb25zaXZlSGVhZGVycyhyZXNwb25zaXZlSGVhZGVyczogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9yZXNwb25zaXZlSGVhZGVycyQubmV4dChyZXNwb25zaXZlSGVhZGVycyk7XG4gICAgfVxuXG4gICAgZ2V0IHJlc3BvbnNpdmVIZWFkZXJzJCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Jlc3BvbnNpdmVIZWFkZXJzJC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBnZXQgY2xlYXJIZWFkZXJTZWFyY2gkKCk6IE9ic2VydmFibGU8bnVtYmVyPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jbGVhckhlYWRlclNlYXJjaCQuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgc2V0IGluaXREZWZhdWx0SGVhZGVycyhkZWZhdWx0SGVhZGVyczogQXJyYXk8c3RyaW5nPikge1xuICAgICAgICB0aGlzLl9pbml0RGVmYXVsdEhlYWRlcnMgPSBkZWZhdWx0SGVhZGVycztcbiAgICB9XG5cbiAgICBnZXQgaW5pdERlZmF1bHRIZWFkZXJzKCk6IEFycmF5PHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faW5pdERlZmF1bHRIZWFkZXJzO1xuICAgIH1cblxuICAgIGdldCBwcmVmZXJlbmNlQ29sdW1uQ291bnQkKCk6IE9ic2VydmFibGU8bnVtYmVyPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wcmVmZXJlbmNlQ29sdW1uQ291bnQkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdGlhbGl6ZUhlYWRlclN0YXRlKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBkZWZhdWx0SGVhZGVycyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZmllbGRzR3JvdXBbMF0uZmllbGRzLmxlbmd0aCAmJiBkZWZhdWx0SGVhZGVycy5sZW5ndGggPCB0aGlzLmhlYWRlckNvbHVtbkNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmZpZWxkc0dyb3VwWzBdLmZpZWxkc1tpXS5pbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdEhlYWRlcnMucHVzaCh0aGlzLmZpZWxkc0dyb3VwWzBdLmZpZWxkc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKGRlZmF1bHRIZWFkZXJzLmxlbmd0aCA8IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQpIHtcbiAgICAgICAgICAgIGRlZmF1bHRIZWFkZXJzLnB1c2gobnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUgPSBuZXcgSGVhZGVyU3RhdGUoZGVmYXVsdEhlYWRlcnMpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBpbml0aWFsaXplRGVmYXVsdEhlYWRlclN0YXRlKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pbml0RGVmYXVsdEhlYWRlcnMgJiYgQXJyYXkuaXNBcnJheSh0aGlzLmluaXREZWZhdWx0SGVhZGVycykpIHtcbiAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRIZWFkZXJzID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGRlZmF1bHRIZWFkZXJzLnB1c2gobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaW5pdERlZmF1bHRIZWFkZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPj0gdGhpcy5oZWFkZXJDb2x1bW5Db3VudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2dnZXIud2FybigndGhlcmUgYXJlIG1vcmUgTkFFX0RFRkFVTFRfSEVBREVSUyB0aGFuIGhlYWRlciBjb2x1bW5zLiBTa2lwcGluZyB0aGUgcmVzdC4uLicpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBoIG9mIHRoaXMuZmllbGRzR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVhZCA9IGguZmllbGRzLmZpbmQoaGVhZGVyID0+IGhlYWRlci51bmlxdWVJZCA9PT0gdGhpcy5pbml0RGVmYXVsdEhlYWRlcnNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGVhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdEhlYWRlcnNbaV0gPSBoZWFkO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9oZWFkZXJTdGF0ZS51cGRhdGVTZWxlY3RlZEhlYWRlcnMoZGVmYXVsdEhlYWRlcnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubG9hZEhlYWRlcnNGcm9tUHJlZmVyZW5jZXMoKTtcbiAgICAgICAgdGhpcy5sb2FkU29ydHNGcm9tUHJlZmVyZW5jZXMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGBudWxsYCBoZWFkZXJzIGlmIHRoZSBuZXcgY291bnQgaXMgZ3JlYXRlciB0aGFuIHRoZSBjdXJyZW50IGNvdW50LlxuICAgICAqXG4gICAgICogUmVtb3ZlcyBleHRyYSBoZWFkZXJzIGlmIHRoZSBuZXcgY291bnQgaXMgc21hbGxlciB0aGFuIHRoZSBjdXJyZW50IGNvdW50LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGRhdGVIZWFkZXJDb2x1bW5Db3VudCgpOiB2b2lkIHtcbiAgICAgICAgbGV0IGhlYWRlcnMgPSB0aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZEhlYWRlcnM7XG4gICAgICAgIGlmIChoZWFkZXJzLmxlbmd0aCA8IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RTZWxlY3RlZEhlYWRlcnMgPSB0aGlzLl9oZWFkZXJTdGF0ZS5sYXN0U2VsZWN0ZWRIZWFkZXJzO1xuICAgICAgICAgICAgaWYgKGhlYWRlcnMubGVuZ3RoIDwgdGhpcy5oZWFkZXJDb2x1bW5Db3VudCAmJiAhIWxhc3RTZWxlY3RlZEhlYWRlcnMgJiYgaGVhZGVycy5sZW5ndGggPCBsYXN0U2VsZWN0ZWRIZWFkZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGhlYWRlcnMucHVzaCguLi5sYXN0U2VsZWN0ZWRIZWFkZXJzLnNsaWNlKGhlYWRlcnMubGVuZ3RoLCB0aGlzLmhlYWRlckNvbHVtbkNvdW50KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoaGVhZGVycy5sZW5ndGggPD0gdGhpcy5oZWFkZXJDb2x1bW5Db3VudCkge1xuICAgICAgICAgICAgICAgIGhlYWRlcnMucHVzaChudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChoZWFkZXJzLmxlbmd0aCA+IHRoaXMuaGVhZGVyQ29sdW1uQ291bnQpIHtcbiAgICAgICAgICAgIGhlYWRlcnMgPSBoZWFkZXJzLnNsaWNlKDAsIHRoaXMuaGVhZGVyQ29sdW1uQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnVwZGF0ZVNlbGVjdGVkSGVhZGVycyhoZWFkZXJzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0QWxsb3dlZE5ldHMoYWxsb3dlZE5ldHM6IEFycmF5PFBldHJpTmV0UmVmZXJlbmNlPikge1xuICAgICAgICAvKiBUT0RPIGJ5IHNpbXBseSByZXBsYWNpbmcgdGhlIHNlbGVjdCBvcHRpb25zIHdpdGggbmV3IG9iamVjdCwgd2UgZG9uJ3QgbG9vc2UgdGhlIG9sZCByZWZlcmVuY2VzLlxuICAgICAgICAgICAgIENvbHVtbnMgd2l0aCBoZWFkZXJzIGZyb20gbmV0cyB0aGF0IGFyZSBubyBsb25nZXIgYWxsb3dlZCBzaG91bGQgaGF2ZSB0aGVpciB2YWx1ZSBjbGVhcmVkLlxuICAgICAgICAgICAgIENvbHVtbnMgd2l0aCB2YWxpZCB2YWx1ZXMgdGhhdCBhcmUgbm90IG1ldGFkYXRhIHNob3VsZCBoYXZlIHRoZWlyIHNlbGVjdGlvbiByZW1hcHBlZCB0byB0aGUgbmV3IG9iamVjdHMuXG4gICAgICAgICAqL1xuXG4gICAgICAgIGNvbnN0IGZpZWxkc0dyb3VwczogQXJyYXk8RmllbGRzR3JvdXA+ID0gW107XG4gICAgICAgIGFsbG93ZWROZXRzLmZvckVhY2goYWxsb3dlZE5ldCA9PiB7XG4gICAgICAgICAgICBjb25zdCBmaWVsZHNHcm91cDogRmllbGRzR3JvdXAgPSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBUaXRsZTogYWxsb3dlZE5ldC50aXRsZSxcbiAgICAgICAgICAgICAgICBmaWVsZHM6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYWxsb3dlZE5ldC5pbW1lZGlhdGVEYXRhLmZvckVhY2goaW1tZWRpYXRlID0+IHtcbiAgICAgICAgICAgICAgICBmaWVsZHNHcm91cC5maWVsZHMucHVzaChcbiAgICAgICAgICAgICAgICAgICAgbmV3IEhlYWRlckNvbHVtbihIZWFkZXJDb2x1bW5UeXBlLklNTUVESUFURSwgaW1tZWRpYXRlLnN0cmluZ0lkLCBpbW1lZGlhdGUudGl0bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbW1lZGlhdGUudHlwZSwgZmFsc2UsIGFsbG93ZWROZXQuaWRlbnRpZmllcilcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmaWVsZHNHcm91cHMucHVzaChmaWVsZHNHcm91cCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAuc3BsaWNlKDEsIHRoaXMuZmllbGRzR3JvdXAubGVuZ3RoIC0gMSk7XG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAucHVzaCguLi5maWVsZHNHcm91cHMpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRUYXNrQWxsb3dlZE5ldHMoYWxsb3dlZE5ldHM6IEFycmF5PE5ldD4pIHtcbiAgICAgICAgLyogVE9ETyBieSBzaW1wbHkgcmVwbGFjaW5nIHRoZSBzZWxlY3Qgb3B0aW9ucyB3aXRoIG5ldyBvYmplY3QsIHdlIGRvbid0IGxvb3NlIHRoZSBvbGQgcmVmZXJlbmNlcy5cbiAgICAgICAgICAgICBDb2x1bW5zIHdpdGggaGVhZGVycyBmcm9tIG5ldHMgdGhhdCBhcmUgbm8gbG9uZ2VyIGFsbG93ZWQgc2hvdWxkIGhhdmUgdGhlaXIgdmFsdWUgY2xlYXJlZC5cbiAgICAgICAgICAgICBDb2x1bW5zIHdpdGggdmFsaWQgdmFsdWVzIHRoYXQgYXJlIG5vdCBtZXRhZGF0YSBzaG91bGQgaGF2ZSB0aGVpciBzZWxlY3Rpb24gcmVtYXBwZWQgdG8gdGhlIG5ldyBvYmplY3RzLlxuICAgICAgICAgKi9cblxuICAgICAgICBjb25zdCBmaWVsZHNHcm91cHM6IEFycmF5PEZpZWxkc0dyb3VwPiA9IFtdO1xuICAgICAgICBhbGxvd2VkTmV0cy5mb3JFYWNoKGFsbG93ZWROZXQgPT4ge1xuICAgICAgICAgICAgY29uc3QgZmllbGRzR3JvdXA6IEZpZWxkc0dyb3VwID0ge1xuICAgICAgICAgICAgICAgIGdyb3VwVGl0bGU6IGFsbG93ZWROZXQudGl0bGUsXG4gICAgICAgICAgICAgICAgZmllbGRzOiBbXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gbmV3IFNldCgpO1xuICAgICAgICAgICAgYWxsb3dlZE5ldC50cmFuc2l0aW9ucy5mb3JFYWNoKHRyYW5zID0+IHtcbiAgICAgICAgICAgICAgICB0cmFucy5pbW1lZGlhdGVEYXRhLmZvckVhY2goZGF0YSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RpbmcuaGFzKGRhdGEuc3RyaW5nSWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZy5hZGQoZGF0YS5zdHJpbmdJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHNHcm91cC5maWVsZHMucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgSGVhZGVyQ29sdW1uKEhlYWRlckNvbHVtblR5cGUuSU1NRURJQVRFLCBkYXRhLnN0cmluZ0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRpdGxlLCBkYXRhLnR5cGUsIGZhbHNlLCBhbGxvd2VkTmV0LmlkZW50aWZpZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZpZWxkc0dyb3Vwcy5wdXNoKGZpZWxkc0dyb3VwKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5maWVsZHNHcm91cC5zcGxpY2UoMSwgdGhpcy5maWVsZHNHcm91cC5sZW5ndGggLSAxKTtcbiAgICAgICAgdGhpcy5maWVsZHNHcm91cC5wdXNoKC4uLmZpZWxkc0dyb3Vwcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSWYgdGhpcyB2aWV3IGhhcyBzb20gaGVhZGVycyBzdG9yZWQgaW4gaXQncyBwcmVmZXJlbmNlcyBhdHRlbXB0cyB0byBsb2FkIHRoZW0uXG4gICAgICogSWYgdGhlIHByZWZlcmVuY2VzIGNvbnRhaW4gbm9uZXhpc3RlbnQgaGVhZGVycyB0aGV5IHdpbGwgYmUgc2tpcHBlZC5cbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgTk9UIGNhbGxlZCBieSB0aGUgYWJzdHJhY3QgY2xhc3MnIGNvbnN0cnVjdG9yLlxuICAgICAqIEl0IGlzIHRoZSByZXNwb25zaWJpbGl0eSBvZiB0aGUgY2hpbGQgY2xhc3MgdG8gY2FsbCBpdCBhdCBhbiBhcHByb3ByaWF0ZSBtb21lbnQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGxvYWRIZWFkZXJzRnJvbVByZWZlcmVuY2VzKCk6IHZvaWQge1xuICAgICAgICBjb25zdCB2aWV3SWQgPSB0aGlzLmdldFZpZXdJZCgpO1xuICAgICAgICBpZiAoIXZpZXdJZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByZWZlcnJlZEhlYWRlcktleXMgPSB0aGlzLl9wcmVmZXJlbmNlcy5nZXRIZWFkZXJzKHZpZXdJZCk7XG4gICAgICAgIGlmICghcHJlZmVycmVkSGVhZGVyS2V5cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5ld0hlYWRlcnMgPSBbXTtcbiAgICAgICAgcHJlZmVycmVkSGVhZGVyS2V5cy5mb3JFYWNoKGhlYWRlcktleSA9PiB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkR3JvdXAgb2YgdGhpcy5maWVsZHNHcm91cCkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaGVhZGVyIG9mIGZpZWxkR3JvdXAuZmllbGRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoZWFkZXIudW5pcXVlSWQgPT09IGhlYWRlcktleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVhZGVycy5wdXNoKGhlYWRlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIGNvbnRpbnVlIHRoZSBvdXRlcm1vc3QgbG9vcFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbm8gbWF0Y2ggZm91bmRcbiAgICAgICAgICAgIG5ld0hlYWRlcnMucHVzaChudWxsKTtcbiAgICAgICAgICAgIHRoaXMuX2xvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgIGBDb3VsZCBub3QgcmVzdG9yZSBoZWFkZXIgd2l0aCBJRCAnJHtoZWFkZXJLZXl9JyBmcm9tIHByZWZlcmVuY2VzLiBJdCBpcyBub3Qgb25lIG9mIHRoZSBhdmFpbGFibGUgaGVhZGVycyBmb3IgdGhpcyB2aWV3LmApO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fcHJlZmVyZW5jZUNvbHVtbkNvdW50JC5uZXh0KG5ld0hlYWRlcnMubGVuZ3RoKTtcbiAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUudXBkYXRlU2VsZWN0ZWRIZWFkZXJzKG5ld0hlYWRlcnMpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBsb2FkU29ydHNGcm9tUHJlZmVyZW5jZXMoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHZpZXdJZCA9IHRoaXMuZ2V0Vmlld0lkKCk7XG4gICAgICAgIGlmICghdmlld0lkKSB7XG4gICAgICAgICAgICB0aGlzLmFwcGx5U2VsZWN0ZWRTb3J0cygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByZWZlcnJlZFNvcnRzID0gdGhpcy5fcHJlZmVyZW5jZXMuZ2V0U29ydHModmlld0lkKTtcbiAgICAgICAgY29uc3QgaGVhZGVyc1dpdGhTb3J0U3RhdGUgPSBuZXcgU2V0PEhlYWRlckNvbHVtbj4odGhpcy5faGVhZGVyU3RhdGUuc2VsZWN0ZWRTb3J0cyk7XG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAuZm9yRWFjaChmaWVsZEdyb3VwID0+IGZpZWxkR3JvdXAuZmllbGRzLmZvckVhY2goaGVhZGVyID0+IGhlYWRlcnNXaXRoU29ydFN0YXRlLmFkZChoZWFkZXIpKSk7XG4gICAgICAgIGhlYWRlcnNXaXRoU29ydFN0YXRlLmZvckVhY2goaGVhZGVyID0+IGhlYWRlci5zb3J0RGlyZWN0aW9uID0gJycpO1xuXG4gICAgICAgIGlmICghcHJlZmVycmVkU29ydHMpIHtcbiAgICAgICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnVwZGF0ZVNlbGVjdGVkU29ydHMoW10pO1xuICAgICAgICAgICAgdGhpcy5hcHBseVNlbGVjdGVkU29ydHMoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBoZWFkZXJzQnlVbmlxdWVJZCA9IG5ldyBNYXA8c3RyaW5nLCBIZWFkZXJDb2x1bW4+KCk7XG4gICAgICAgIHRoaXMuZmllbGRzR3JvdXAuZm9yRWFjaChmaWVsZEdyb3VwID0+IGZpZWxkR3JvdXAuZmllbGRzLmZvckVhY2goaGVhZGVyID0+IHtcbiAgICAgICAgICAgIGlmICghaGVhZGVyc0J5VW5pcXVlSWQuaGFzKGhlYWRlci51bmlxdWVJZCkpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXJzQnlVbmlxdWVJZC5zZXQoaGVhZGVyLnVuaXF1ZUlkLCBoZWFkZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICAgIGNvbnN0IHJlc29sdmVkU29ydHMgPSBwcmVmZXJyZWRTb3J0c1xuICAgICAgICAgICAgLm1hcChwcmVmZXJlbmNlID0+ICh7XG4gICAgICAgICAgICAgICAgaGVhZGVyOiBoZWFkZXJzQnlVbmlxdWVJZC5nZXQocHJlZmVyZW5jZS5oZWFkZXJVbmlxdWVJZCksXG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uOiBwcmVmZXJlbmNlLnNvcnREaXJlY3Rpb25cbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmZpbHRlcigocmVzb2x2ZWQpOiByZXNvbHZlZCBpcyB7aGVhZGVyOiBIZWFkZXJDb2x1bW47IGRpcmVjdGlvbjogU29ydERpcmVjdGlvbn0gPT4gISFyZXNvbHZlZC5oZWFkZXIpO1xuICAgICAgICBjb25zdCBhcHBsaWNhYmxlU29ydHMgPSB0aGlzLl9zb3J0aW5nTW9kZSA9PT0gSGVhZGVyU29ydGluZ01vZGUuU0lOR0xFXG4gICAgICAgICAgICA/IHJlc29sdmVkU29ydHMuc2xpY2UoMCwgMSlcbiAgICAgICAgICAgIDogcmVzb2x2ZWRTb3J0cztcbiAgICAgICAgYXBwbGljYWJsZVNvcnRzLmZvckVhY2goc29ydCA9PiBzb3J0LmhlYWRlci5zb3J0RGlyZWN0aW9uID0gc29ydC5kaXJlY3Rpb24pO1xuICAgICAgICBjb25zdCBuZXdTb3J0cyA9IGFwcGxpY2FibGVTb3J0cy5tYXAoc29ydCA9PiBzb3J0LmhlYWRlcik7XG4gICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnVwZGF0ZVNlbGVjdGVkU29ydHMobmV3U29ydHMpO1xuICAgICAgICB0aGlzLmFwcGx5U2VsZWN0ZWRTb3J0cygpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBjcmVhdGVNZXRhSGVhZGVycygpOiBBcnJheTxIZWFkZXJDb2x1bW4+O1xuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlIHNvcnQgbW9kZSBmb3Igc2VsZWN0ZWQgY29sdW1uIGFsbCBvdGhlciBjb2x1bW4gYXJlIHNldCB0byBkZWZhdWx0IHNvcnQgbW9kZVxuICAgICAqIEVtaXQgcmVxdWVzdCBmb3Igc29ydGVkIHBhbmVsc1xuICAgICAqIEBwYXJhbSBjb2x1bW5JbmRleCBpbmRleCBvZiB0aGUgY29sdW1uIHRoYXQgY2F1c2VkIHRoZSBzb3J0IGNoYW5nZVxuICAgICAqIEBwYXJhbSBhY3RpdmUgUmVwcmVzZW50cyBjb2x1bW4gaWRlbnRpZmllclxuICAgICAqIEBwYXJhbSBkaXJlY3Rpb24gUmVwcmVzZW50IG9uZSBvZiBzb3J0IG1vZGVzOiBhc2QsIGRlc2MgYW5kICcnXG4gICAgICovXG4gICAgcHVibGljIHNvcnRIZWFkZXJDaGFuZ2VkKGNvbHVtbkluZGV4OiBudW1iZXIsIGFjdGl2ZTogc3RyaW5nLCBkaXJlY3Rpb246IFNvcnREaXJlY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRIZWFkZXJzID0gdGhpcy5oZWFkZXJTdGF0ZS5zZWxlY3RlZEhlYWRlcnMuZmlsdGVyKGhlYWRlciA9PiAhIWhlYWRlcik7XG4gICAgICAgIGNvbnN0IHNvcnRpbmdIZWFkZXIgPSBzZWxlY3RlZEhlYWRlcnMuZmluZChoZWFkZXIgPT4gaGVhZGVyLnVuaXF1ZUlkID09PSBhY3RpdmUpO1xuICAgICAgICBjb25zdCBoZWFkZXJzV2l0aFNvcnRTdGF0ZSA9IG5ldyBTZXQ8SGVhZGVyQ29sdW1uPihbXG4gICAgICAgICAgICAuLi5zZWxlY3RlZEhlYWRlcnMsXG4gICAgICAgICAgICAuLi50aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZFNvcnRzXG4gICAgICAgIF0pO1xuICAgICAgICBoZWFkZXJzV2l0aFNvcnRTdGF0ZS5mb3JFYWNoKGhlYWRlciA9PiBoZWFkZXIuc29ydERpcmVjdGlvbiA9IGhlYWRlciA9PT0gc29ydGluZ0hlYWRlciA/IGRpcmVjdGlvbiA6ICcnKTtcbiAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUudXBkYXRlU2VsZWN0ZWRTb3J0cyhzb3J0aW5nSGVhZGVyICYmIGRpcmVjdGlvbiA/IFtzb3J0aW5nSGVhZGVyXSA6IFtdKTtcblxuICAgICAgICBjb25zdCBzb3J0Q2hhbmdlRGVzY3JpcHRpb246IFNvcnRDaGFuZ2VEZXNjcmlwdGlvbiA9IHNvcnRpbmdIZWFkZXIgPyB7XG4gICAgICAgICAgICBzb3J0RGlyZWN0aW9uOiBkaXJlY3Rpb24sXG4gICAgICAgICAgICBjb2x1bW5UeXBlOiBzb3J0aW5nSGVhZGVyLnR5cGUsXG4gICAgICAgICAgICBmaWVsZElkZW50aWZpZXI6IHNvcnRpbmdIZWFkZXIuZmllbGRJZGVudGlmaWVyLFxuICAgICAgICAgICAgcGV0cmlOZXRJZGVudGlmaWVyOiBzb3J0aW5nSGVhZGVyLnBldHJpTmV0SWRlbnRpZmllcixcbiAgICAgICAgICAgIGNvbHVtbklkZW50aWZpZXI6IGNvbHVtbkluZGV4LFxuICAgICAgICAgICAgZmllbGRUeXBlOiBzb3J0aW5nSGVhZGVyLmZpZWxkVHlwZVxuICAgICAgICB9IDogdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9oZWFkZXJDaGFuZ2UkLm5leHQoe1xuICAgICAgICAgICAgaGVhZGVyVHlwZTogdGhpcy5oZWFkZXJUeXBlLFxuICAgICAgICAgICAgY2hhbmdlVHlwZTogSGVhZGVyQ2hhbmdlVHlwZS5TT1JULFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHNvcnRDaGFuZ2VEZXNjcmlwdGlvblxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlcyB0aGUgc2VhcmNoIHZhbHVlIGluIHRoZSBhcHByb3ByaWF0ZSBjb2x1bW4gaW4gdGhlIGhlYWRlclxuICAgICAqIEVtaXQgcmVxdWVzdCBmb3Igc2VhcmNoZWQgcGFuZWxzIGJ5IHVzZXIgaW5wdXQgcXVlcnlcbiAgICAgKi9cbiAgICBwdWJsaWMgaGVhZGVyU2VhcmNoSW5wdXRDaGFuZ2VkKGNvbHVtbkluZGV4OiBudW1iZXIsIHNlYXJjaElucHV0OiBhbnkpIHtcbiAgICAgICAgY29uc3QgYWZmZWN0ZWRIZWFkZXIgPSB0aGlzLmhlYWRlclN0YXRlLnNlbGVjdGVkSGVhZGVyc1tjb2x1bW5JbmRleF07XG4gICAgICAgIGFmZmVjdGVkSGVhZGVyLnNlYXJjaElucHV0ID0gc2VhcmNoSW5wdXQ7XG4gICAgICAgIGNvbnN0IHNlYXJjaENoYW5nZURlc2NyaXB0aW9uOiBTZWFyY2hDaGFuZ2VEZXNjcmlwdGlvbiA9IHtcbiAgICAgICAgICAgIGZpZWxkSWRlbnRpZmllcjogYWZmZWN0ZWRIZWFkZXIuZmllbGRJZGVudGlmaWVyLFxuICAgICAgICAgICAgZmllbGRUeXBlOiBhZmZlY3RlZEhlYWRlci5maWVsZFR5cGUsXG4gICAgICAgICAgICBmaWVsZFRpdGxlOiBhZmZlY3RlZEhlYWRlci50aXRsZSxcbiAgICAgICAgICAgIHNlYXJjaElucHV0LFxuICAgICAgICAgICAgdHlwZTogYWZmZWN0ZWRIZWFkZXIudHlwZSxcbiAgICAgICAgICAgIHBldHJpTmV0SWRlbnRpZmllcjogYWZmZWN0ZWRIZWFkZXIucGV0cmlOZXRJZGVudGlmaWVyLFxuICAgICAgICAgICAgY29sdW1uSWRlbnRpZmllcjogY29sdW1uSW5kZXhcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5faGVhZGVyQ2hhbmdlJC5uZXh0KHtcbiAgICAgICAgICAgIGhlYWRlclR5cGU6IHRoaXMuaGVhZGVyVHlwZSxcbiAgICAgICAgICAgIGNoYW5nZVR5cGU6IEhlYWRlckNoYW5nZVR5cGUuU0VBUkNILFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHNlYXJjaENoYW5nZURlc2NyaXB0aW9uXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZSBhY3RpdmUgaGVhZGVyIGFuZCB0aXRsZXMgb2YgcGFuZWxzXG4gICAgICovXG4gICAgcHVibGljIGhlYWRlckNvbHVtblNlbGVjdGVkKGNvbHVtbkluZGV4OiBudW1iZXIsIG5ld0hlYWRlckNvbHVtbjogSGVhZGVyQ29sdW1uKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG5ld0hlYWRlcnM6IEFycmF5PEhlYWRlckNvbHVtbj4gPSBbXTtcbiAgICAgICAgbmV3SGVhZGVycy5wdXNoKC4uLnRoaXMuX2hlYWRlclN0YXRlLnNlbGVjdGVkSGVhZGVycyk7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzSGVhZGVyID0gbmV3SGVhZGVyc1tjb2x1bW5JbmRleF07XG4gICAgICAgIG5ld0hlYWRlcnNbY29sdW1uSW5kZXhdID0gbmV3SGVhZGVyQ29sdW1uO1xuICAgICAgICBpZiAoISFwcmV2aW91c0hlYWRlciAmJiAhbmV3SGVhZGVycy5pbmNsdWRlcyhwcmV2aW91c0hlYWRlcikpIHtcbiAgICAgICAgICAgIHByZXZpb3VzSGVhZGVyLnNvcnREaXJlY3Rpb24gPSAnJztcbiAgICAgICAgICAgIHByZXZpb3VzSGVhZGVyLnNlYXJjaElucHV0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUudXBkYXRlU2VsZWN0ZWRTb3J0cyhcbiAgICAgICAgICAgICAgICB0aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZFNvcnRzLmZpbHRlcihoZWFkZXIgPT4gaGVhZGVyICE9PSBwcmV2aW91c0hlYWRlcilcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUudXBkYXRlU2VsZWN0ZWRIZWFkZXJzKG5ld0hlYWRlcnMpO1xuICAgICAgICB0aGlzLl9oZWFkZXJDaGFuZ2UkLm5leHQoe1xuICAgICAgICAgICAgaGVhZGVyVHlwZTogdGhpcy5oZWFkZXJUeXBlLFxuICAgICAgICAgICAgY2hhbmdlVHlwZTogSGVhZGVyQ2hhbmdlVHlwZS5FRElULFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHtwcmVmZXJyZWRIZWFkZXJzOiB0aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZEhlYWRlcnN9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBzb3J0aW5nQ29sdW1uU2VsZWN0ZWQobmV3SGVhZGVyQ29sdW1uOiBIZWFkZXJDb2x1bW4gfCBudWxsIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgICAgIGlmICghbmV3SGVhZGVyQ29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBtdWx0aVNlbGVjdGlvbiA9IHRoaXMuX3NvcnRpbmdNb2RlID09PSBIZWFkZXJTb3J0aW5nTW9kZS5NVUxUSSB8fFxuICAgICAgICAgICAgKHRoaXMuX3NvcnRpbmdNb2RlID09PSBIZWFkZXJTb3J0aW5nTW9kZS5DT01CSU5FRCAmJiB0aGlzLl9oZWFkZXJTdGF0ZS5tb2RlID09PSBIZWFkZXJNb2RlLkVESVQpO1xuICAgICAgICBjb25zdCBuZXdTb3J0aW5nSGVhZGVycyA9IG11bHRpU2VsZWN0aW9uID9cbiAgICAgICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnNlbGVjdGVkU29ydHMuZmlsdGVyKGhlYWRlciA9PiBoZWFkZXIudW5pcXVlSWQgIT09IG5ld0hlYWRlckNvbHVtbi51bmlxdWVJZCkgOiBbXTtcbiAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUuc2VsZWN0ZWRTb3J0c1xuICAgICAgICAgICAgLmZpbHRlcihoZWFkZXIgPT4gaGVhZGVyICE9PSBuZXdIZWFkZXJDb2x1bW4gJiZcbiAgICAgICAgICAgICAgICAoIW11bHRpU2VsZWN0aW9uIHx8IGhlYWRlci51bmlxdWVJZCA9PT0gbmV3SGVhZGVyQ29sdW1uLnVuaXF1ZUlkKSlcbiAgICAgICAgICAgIC5mb3JFYWNoKGhlYWRlciA9PiBoZWFkZXIuc29ydERpcmVjdGlvbiA9ICcnKTtcblxuICAgICAgICBpZiAoISFuZXdIZWFkZXJDb2x1bW4uc29ydERpcmVjdGlvbikge1xuICAgICAgICAgICAgbmV3U29ydGluZ0hlYWRlcnMucHVzaChuZXdIZWFkZXJDb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnVwZGF0ZVNlbGVjdGVkU29ydHMobmV3U29ydGluZ0hlYWRlcnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZSBzZWxlY3RlZCBoZWFkZXIgbW9kZSB0aGVyZSBhcmUgdGhyZWUgcG9zc2libGUgbW9kZXM6IFNPUlQsIFNFQVJDSCBhbmQgRURJVFxuICAgICAqIEBwYXJhbSBuZXdNb2RlIHRoZSBtb2RlIHRoYXQgdGhlIGhlYWRlciBzaG91bGQgY2hhbmdlIHRvXG4gICAgICogQHBhcmFtIHNhdmVMYXN0TW9kZSB3aGV0aGVyIHRoZSBsYXN0IHN0YXRlIHNob3VsZCBiZSByZW1lbWJlcmVkLlxuICAgICAqIEl0IGNhbiBiZSByZXN0b3JlZCB3aXRoIHRoZSBbSGVhZGVyU3RhdGUucmVzdG9yZUxhc3RNb2RlKClde0BsaW5rIEhlYWRlclN0YXRlI3Jlc3RvcmVMYXN0TW9kZX0gbWV0aG9kLlxuICAgICAqL1xuICAgIHB1YmxpYyBjaGFuZ2VNb2RlKG5ld01vZGU6IEhlYWRlck1vZGUsIHNhdmVMYXN0TW9kZSA9IHRydWUpOiB2b2lkIHtcbiAgICAgICAgaWYgKG5ld01vZGUgPT09IHRoaXMuX2hlYWRlclN0YXRlLm1vZGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzYXZlTGFzdE1vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnNhdmVTdGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5zYXZlU3RhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNoYW5nZSA9IHRoaXMubW9kZUNoYW5nZUZyb21DdXJyZW50KG5ld01vZGUpO1xuICAgICAgICB0aGlzLl9oZWFkZXJTdGF0ZS5tb2RlID0gbmV3TW9kZTtcbiAgICAgICAgdGhpcy5faGVhZGVyQ2hhbmdlJC5uZXh0KGNoYW5nZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbmZpcm1FZGl0TW9kZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5faGVhZGVyU3RhdGUucmVzdG9yZUxhc3RNb2RlKCk7XG4gICAgICAgIHRoaXMuc2F2ZU5ld1N0YXRlKCk7XG4gICAgICAgIGNvbnN0IGNoYW5nZSA9IHRoaXMubW9kZUNoYW5nZUFmdGVyRWRpdCgpO1xuICAgICAgICBjb25zdCB2aWV3SWQgPSB0aGlzLmdldFZpZXdJZCgpO1xuICAgICAgICBpZiAoISF2aWV3SWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGhlYWRlcnMgPSB0aGlzLmhlYWRlclN0YXRlLnNlbGVjdGVkSGVhZGVycztcbiAgICAgICAgICAgIGNvbnN0IHNvcnRzID0gdGhpcy5oZWFkZXJTdGF0ZS5zZWxlY3RlZFNvcnRzO1xuICAgICAgICAgICAgdGhpcy5fcHJlZmVyZW5jZXMuc2V0SGVhZGVyc0FuZFNvcnRzKHZpZXdJZCwgaGVhZGVycy5tYXAoaGVhZGVyID0+ICEhaGVhZGVyID8gaGVhZGVyLnVuaXF1ZUlkIDogJycpLCBzb3J0cy5tYXAoc29ydCA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtoZWFkZXJVbmlxdWVJZDogc29ydC51bmlxdWVJZCwgc29ydERpcmVjdGlvbjogc29ydC5zb3J0RGlyZWN0aW9ufSBhcyBTb3J0aW5nSGVhZGVyO1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYXBwbHlTZWxlY3RlZFNvcnRzKCk7XG4gICAgICAgIHRoaXMuX2hlYWRlckNoYW5nZSQubmV4dChjaGFuZ2UpO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVTb3J0TW9kZSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2hhbmdlID0gdGhpcy5tb2RlQ2hhbmdlQWZ0ZXJTb3J0KCk7XG4gICAgICAgIHRoaXMuYXBwbHlTZWxlY3RlZFNvcnRzKCk7XG4gICAgICAgIHRoaXMuX2hlYWRlckNoYW5nZSQubmV4dChjaGFuZ2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gdXNlciBjYW5jZWxzIHRoZSBlZGl0IG1vZGUsIHRoZSBsYXN0IHNhdmVkIGhlYWRlcnMgc3RhdGUgaXMgbG9hZGVkIGFuZCBlbWl0dGVkXG4gICAgICogTGFzdCBtb2RlIGluIGhlYWRlciBpcyByZWxvYWRlZCBhcyB3ZWxsLiBQb3NzaWJsZSByZWxvYWRlZCBtb2Rlczogc29ydCBvciBzZWFyY2hcbiAgICAgKi9cbiAgICBwdWJsaWMgcmV2ZXJ0RWRpdE1vZGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2hlYWRlclN0YXRlLnJlc3RvcmVMYXN0U3RhdGUoKTtcbiAgICAgICAgdGhpcy5yZXN0b3JlTGFzdFN0YXRlKCk7XG4gICAgICAgIHRoaXMuYXBwbHlTZWxlY3RlZFNvcnRzKCk7XG4gICAgICAgIGNvbnN0IGNoYW5nZSA9IHRoaXMubW9kZUNoYW5nZUFmdGVyRWRpdCgpO1xuICAgICAgICB0aGlzLl9oZWFkZXJDaGFuZ2UkLm5leHQoe1xuICAgICAgICAgICAgaGVhZGVyVHlwZTogdGhpcy5oZWFkZXJUeXBlLFxuICAgICAgICAgICAgY2hhbmdlVHlwZTogSGVhZGVyQ2hhbmdlVHlwZS5FRElULFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHtwcmVmZXJyZWRIZWFkZXJzOiB0aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZEhlYWRlcnN9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9oZWFkZXJDaGFuZ2UkLm5leHQoY2hhbmdlKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5faGVhZGVyQ2hhbmdlJC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLl9hcHBsaWVkU29ydHMkLmNvbXBsZXRlKCk7XG4gICAgICAgIHRoaXMuX2NsZWFySGVhZGVyU2VhcmNoJC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLl9oZWFkZXJDb2x1bW5Db3VudCQuY29tcGxldGUoKTtcbiAgICAgICAgdGhpcy5fcmVzcG9uc2l2ZUhlYWRlcnMkLmNvbXBsZXRlKCk7XG4gICAgICAgIHRoaXMubG9hZGluZy5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLl9wcmVmZXJlbmNlQ29sdW1uQ291bnQkLmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG5ld01vZGUgdGhlIHtAbGluayBIZWFkZXJNb2RlfSB0aGF0IGlzIGJlaW5nIHNlbGVjdGVkIGFzIHRoZSBuZXh0IG1vZGVcbiAgICAgKiBAcmV0dXJuc2Ege0BsaW5rIEhlYWRlckNoYW5nZX0gb2JqZWN0IHdpdGgge0BsaW5rIE1vZGVDaGFuZ2VEZXNjcmlwdGlvbn0gb2JqZWN0IGFzIGl0J3MgYGRlc2NyaXB0aW9uYCxcbiAgICAgKiB3aGVyZSB0aGUgYHByZXZpb3VzTW9kZWAgaXMgc2V0IHRvIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgbW9kZSBhbmQgdGhlIGBjdXJyZW50TW9kZWAgaXMgc2V0IHRvIHRoZSBwcm92aWRlZCBhcmd1bWVudFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBtb2RlQ2hhbmdlRnJvbUN1cnJlbnQobmV3TW9kZTogSGVhZGVyTW9kZSk6IEhlYWRlckNoYW5nZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU1vZGVDaGFuZ2UodGhpcy5faGVhZGVyU3RhdGUubW9kZSwgbmV3TW9kZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgYSB7QGxpbmsgSGVhZGVyQ2hhbmdlfSBvYmplY3Qgd2l0aCB7QGxpbmsgTW9kZUNoYW5nZURlc2NyaXB0aW9ufSBvYmplY3QgYXMgaXQncyBgZGVzY3JpcHRpb25gLFxuICAgICAqIHdoZXJlIHRoZSBgcHJldmlvdXNNb2RlYCBpcyBzZXQgdG8gW0VESVRde0BsaW5rIEhlYWRlck1vZGUjRURJVH0gYW5kIHRoZSBgY3VycmVudE1vZGVgIHRvIHRoZSBtb2RlXG4gICAgICogdGhhdCBpcyBjdXJyZW50bHkgc2VsZWN0ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgbW9kZUNoYW5nZUFmdGVyRWRpdCgpOiBIZWFkZXJDaGFuZ2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVNb2RlQ2hhbmdlKEhlYWRlck1vZGUuRURJVCwgdGhpcy5faGVhZGVyU3RhdGUubW9kZSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIG1vZGVDaGFuZ2VBZnRlclNvcnQoKTogSGVhZGVyQ2hhbmdlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlTW9kZUNoYW5nZShIZWFkZXJNb2RlLlNPUlQsIHRoaXMuX2hlYWRlclN0YXRlLm1vZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbGRNb2RlIHRoZSB7QGxpbmsgSGVhZGVyTW9kZX0gdGhhdCB3YXMgcHJldmlvdXNseSBzZWxlY3RlZFxuICAgICAqIEBwYXJhbSBuZXdNb2RlIHRoZSB7QGxpbmsgSGVhZGVyTW9kZX0gdGhhdCBpcyBzZWxlY3RlZCBub3dcbiAgICAgKiBAcmV0dXJucyBhIHtAbGluayBIZWFkZXJDaGFuZ2V9IG9iamVjdCB3aXRoIHtAbGluayBNb2RlQ2hhbmdlRGVzY3JpcHRpb259IG9iamVjdCBhcyBpdCdzIGBkZXNjcmlwdGlvbmBcbiAgICAgKiBjb250YWluaW5nIGluZm9ybWF0aW9uIGFib3V0IGEgY2hhbmdlIHRvIHRoZSBoZWFkZXIgbW9kZVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVNb2RlQ2hhbmdlKG9sZE1vZGU6IEhlYWRlck1vZGUsIG5ld01vZGU6IEhlYWRlck1vZGUpOiBIZWFkZXJDaGFuZ2Uge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY2hhbmdlVHlwZTogSGVhZGVyQ2hhbmdlVHlwZS5NT0RFX0NIQU5HRUQsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjoge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRNb2RlOiBuZXdNb2RlLFxuICAgICAgICAgICAgICAgIHByZXZpb3VzTW9kZTogb2xkTW9kZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGhlYWRlclR5cGU6IHRoaXMuaGVhZGVyVHlwZVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGEgc25hcHNob3Qgb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzb3J0aW5nIHNvIHJlZ2lzdGVyZWQgdmlld3MgY2FuIHJlbG9hZCB3aXRob3V0IHBlcnNpc3RpbmcgdXNlciBwcmVmZXJlbmNlcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXBwbHlTZWxlY3RlZFNvcnRzKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBhcHBsaWVkU29ydHMgPSB0aGlzLl9oZWFkZXJTdGF0ZS5zZWxlY3RlZFNvcnRzLm1hcChoZWFkZXIgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc25hcHNob3QgPSBuZXcgSGVhZGVyQ29sdW1uKGhlYWRlci50eXBlLCBoZWFkZXIuZmllbGRJZGVudGlmaWVyLCBoZWFkZXIudGl0bGUsIGhlYWRlci5maWVsZFR5cGUsXG4gICAgICAgICAgICAgICAgaGVhZGVyLmluaXRpYWwsIGhlYWRlci5wZXRyaU5ldElkZW50aWZpZXIpO1xuICAgICAgICAgICAgc25hcHNob3Quc29ydERpcmVjdGlvbiA9IGhlYWRlci5zb3J0RGlyZWN0aW9uO1xuICAgICAgICAgICAgcmV0dXJuIHNuYXBzaG90O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fYXBwbGllZFNvcnRzJC5uZXh0KGFwcGxpZWRTb3J0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYSBuZXcgdmFsdWUgaW50byB0aGUgW2NsZWFySGVhZGVyU2VhcmNoJF17QGxpbmsgQWJzdHJhY3RIZWFkZXJTZXJ2aWNlI2NsZWFySGVhZGVyU2VhcmNoJH0gc3RyZWFtLCB0aGF0IG5vdGlmaWVzXG4gICAgICogdGhlIGhlYWRlciBzZWFyY2ggY29tcG9uZW50LCB0aGF0IGl0IHNob3VsZCBjbGVhciB0aGUgaW5wdXQgZm9yIHRoZSBzcGVjaWZpZWQgY29sdW1uLlxuICAgICAqIEBwYXJhbSBjb2x1bW5JbmRleCB0aGUgaW5kZXggb2YgdGhlIGNvbHVtbiB0aGF0IHNob3VsZCBiZSBjbGVhcmVkXG4gICAgICovXG4gICAgcHVibGljIGNsZWFySGVhZGVyU2VhcmNoKGNvbHVtbkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fY2xlYXJIZWFkZXJTZWFyY2gkLm5leHQoY29sdW1uSW5kZXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIHRoZSBJZCBvZiB0aGUgdmlldywgaWYgdGhlIFZpZXdJZFNlcnZpY2Ugd2FzIGluamVjdGVkLiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSBzZXJ2aWNlIHdhcyBub3QgaW5qZWN0ZWQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGdldFZpZXdJZCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgICAgICBpZiAodGhpcy5fdmlld0lkU2VydmljZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdJZFNlcnZpY2Uudmlld0lkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHNhdmVTdGF0ZSgpO1xuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHNhdmVOZXdTdGF0ZSgpO1xuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlc3RvcmVMYXN0U3RhdGUoKTtcbn1cbiJdfQ==