@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
385 lines • 54.6 kB
JavaScript
import { Injectable, Optional, SkipSelf } from '@angular/core';
import { Net } from '@microsoft/windows-admin-center-sdk/core/data/net';
import { Dom } from '@microsoft/windows-admin-center-sdk/core/dom/dom';
import { EnvironmentModuleEntryPointType } from '@microsoft/windows-admin-center-sdk/core/manifest/environment-modules';
import { EMPTY, of, ReplaySubject } from 'rxjs';
import { catchError, map, mergeMap, takeLast } from 'rxjs/operators';
import { AppContextService } from '../../service/app-context.service';
import { DialogCloseReason } from './dialog.component';
import * as i0 from "@angular/core";
import * as i1 from "../../service/app-context.service";
export var DialogChangeEvent;
(function (DialogChangeEvent) {
DialogChangeEvent[DialogChangeEvent["Show"] = 0] = "Show";
DialogChangeEvent[DialogChangeEvent["Hide"] = 1] = "Hide";
})(DialogChangeEvent || (DialogChangeEvent = {}));
export class DialogService {
constructor(appContext, parentDialogService) {
this.appContext = appContext;
this.parentDialogService = parentDialogService;
this.commonIds = {
choice: 'sme-common-choice-dialog',
confirmation: 'sme-common-confirmation-dialog',
confirmationList: 'sme-common-confirmation-list-dialog',
message: 'sme-common-message-dialog',
notificationsPane: 'sme-common-notifications-pane',
settings: 'sme-common-settings-pane',
help: 'sme-common-help-pane',
userPane: 'sme-common-user-pane',
manageAs: 'sme-common-manage-as-dialog',
powerShellShowScript: 'sme-common-powershell-show-script',
credSSPConfirmation: 'sme-credssp-confirmation-dialog',
userAlive: 'sme-user-alive-dialog'
};
this.activeDialogsStack = [];
this.strings = MsftSme.getStrings().MsftSmeShell.Angular;
this.componentMap = {};
this.dialogOrigins = {};
this.iFrameDialogCount = 0;
this.changedEventSubject = new ReplaySubject(1);
}
/**
* Gets the subject of notification changed event.
*/
get changed() {
return this.changedEventSubject;
}
get currentDialogLevel() {
return this.activeDialogsStack ? this.activeDialogsStack.length + this.iFrameDialogCount : this.iFrameDialogCount;
}
/**
* Registers the dialog with the service.
*
* TOptions the type of the dialog options.
* TResult the type of the dialog results.
* @param id The unique identifier of the dialog.
* @param component The dialog component.
*/
register(id, component) {
if (!id) {
throw new Error('DialogService.register: ID is required to register a dialog.');
}
if (!component) {
throw new Error('DialogService.register: A dialog is required to register a dialog.');
}
/**
* removing until we understand cases where angular can call ngOnInit twice.
* see: http://stackoverflow.com/questions/42700116/angular2-routing-issue-and-ngoninit-called-twice
* and @msft-sme/local-users-groups for examples
*/
// if (this.componentMap[id]) {
// console.warn(`DialogService.register: A dialog with the ID \'${id}\' has already been registered`);
// }
this.componentMap[id] = component;
}
/**
* Unregisters the dialog with the service.
*
* @param id The unique identifier of the dialog.
*/
unregister(id) {
if (this.componentMap[id]) {
delete this.componentMap[id];
}
if (this.activeDialogsStack && this.activeDialogsStack.length > 0 && MsftSme.last(this.activeDialogsStack).id === id) {
this.activeDialogsStack.pop();
}
}
addIFrameDialog() {
this.iFrameDialogCount++;
}
removeIFrameDialog() {
this.iFrameDialogCount = Math.max(this.iFrameDialogCount - 1, 0);
}
/**
* Shows the dialog.
*
* TOptions The type of the dialog options.
* TResult The result of the dialog.
* @param id The unique identifier of the dialog.
* @param options The dialog options.
*/
show(id, options) {
if (!id) {
throw new Error('DialogService.show: ID is required to show a dialog.');
}
if (!this.componentMap[id]) {
if (this.parentDialogService) {
return this.parentDialogService.show(id, options);
}
else {
throw new Error(`DialogService.show: No dialog associated with provided ID \'${id}\'.`);
}
}
const newDialog = this.componentMap[id];
const oldDialog = MsftSme.last(this.activeDialogsStack);
// accessibility
if (options && !options.isFromRpc) { // if from Rpc then don't resume focus since it will focus back on iframe
const origin = document.activeElement;
if (origin) {
this.dialogOrigins[id] = origin;
}
}
// dont do anything unless we have a subscriber
return of(oldDialog)
.pipe(mergeMap(it => {
// create a placeholder for the new dialog result
let resultObservable;
// remember if there was an active dialog when we started
const existingActiveDialog = !!oldDialog;
if (existingActiveDialog) {
if (oldDialog.keepOpen) {
// If the currently active dialog wants to stay open, then keep it open and show the new dialog on top
this.activeDialogsStack.push(newDialog);
this.overlayOpen(true, newDialog.id);
// we set the dialog level as the length of the active dialogs stack
newDialog.setLevel(this.currentDialogLevel);
this.activeDialogResult = newDialog.show(options)
.pipe(map(result => {
this.overlayOpen(false, newDialog.id);
this.activeDialogsStack.pop();
if (oldDialog) {
oldDialog.autoFocus();
}
return result;
}));
resultObservable = this.activeDialogResult;
}
else {
// if there is an active dialog, wait for it to complete, then show a the new one
resultObservable = this.activeDialogResult
.pipe(takeLast(1), mergeMap(() => {
return this.show(id, options);
}));
}
}
else {
// if there is no active dialog, then just show the new one
this.activeDialogsStack.push(newDialog);
this.overlayOpen(true, newDialog.id);
newDialog.setLevel(this.currentDialogLevel);
this.activeDialogResult = newDialog.show(options)
.pipe(map(result => {
this.overlayOpen(false, newDialog.id);
if (oldDialog) {
oldDialog.autoFocus();
}
this.activeDialogsStack.pop();
return result;
}));
resultObservable = this.activeDialogResult;
}
// if we had an active dialog, request the previous dialog to close unless it wants to stay open
if (existingActiveDialog && !oldDialog.keepOpen) {
oldDialog.closeRequested(DialogCloseReason.CompetingDialog);
}
this.emitDialogChangeEvent(id, DialogChangeEvent.Show);
return resultObservable;
}));
}
/**
* Shows a message dialog with the given options
*
* @param options The dialog options.
* @returns A subject that will be published one time with the dialog result
* @deprecated Please use 'AppContextService.frame.showDialogMessage' on extensions.
*/
showMessage(options) {
// if running from shell, manually launch dialog
if (this.appContext.rpc.isShell) {
return this.show(this.commonIds.message, options);
}
else {
// otherwise ask the shell to do it for us.
return this.appContext.frame.showDialogMessage({
buttonText: options.buttonText,
checkboxText: options.checkboxText,
externalLink: options.externalLink,
message: options.message,
title: options.title
});
}
}
/**
* Hide a message dialog.
*/
hideMessage() {
this.hide(this.commonIds.message);
}
/**
* Shows a choice dialog with the given options.
*
* @param options The dialog options.
* @returns A subject that will be published one time with the dialog result.
*/
showChoice(options) {
if (this.appContext.rpc.isShell) {
return this.show(this.commonIds.choice, options);
}
else {
return this.appContext.frame.showDialogChoice({
cancelButtonText: options.cancelButtonText,
choices: options.choices,
confirmButtonText: options.confirmButtonText,
footnote: options.footnote,
message: options.message,
title: options.title
});
}
}
/**
* Hide a choice dialog.
*/
hideChoice() {
this.hide(this.commonIds.choice);
}
/**
* Shows a confirmation dialog with the given options
*
* @param options The dialog options.
* @returns A subject that will be published one time with the dialog result
* @deprecated since 02/20/18. Please use 'AppContextService.frame.showDialogConfirmation' instead
*/
showConfirmation(options) {
let confirmationObservable;
// if running from shell, manually launch dialog
if (this.appContext.rpc.isShell) {
confirmationObservable = this.show(this.commonIds.confirmation, options);
}
else {
// otherwise ask the shell to do it for us.
confirmationObservable = this.appContext.frame.showDialogConfirmation({
cancelButtonText: options.cancelButtonText,
checkboxText: options.checkboxText,
confirmButtonText: options.confirmButtonText,
doubleCheckText: options.doubleCheckText,
message: options.message,
title: options.title
});
}
return confirmationObservable.pipe(map((response) => {
return response || { confirmed: false, checkboxResult: false };
}));
}
/**
* Hide a confirmation dialog.
*/
hideConfirmation() {
this.hide(this.commonIds.confirmation);
}
/**
* Shows a confirmation list dialog with the given options
*
* @param options The dialog options.
* @returns A subject that will be published one time with the dialog result
*/
showConfirmationList(options) {
return this.show(this.commonIds.confirmationList, options);
}
/**
* Hide a confirmation list dialog.
*/
hideConfirmationList() {
this.hide(this.commonIds.confirmationList);
}
/**
* Hides the dialog.
*
* TResult The type of the dialog result.
* @param id The unique identifier of the dialog.
* @param result The result of the dialog.
*/
hide(id, result) {
if (!id) {
throw new Error('DialogService.hide: ID is required to hide a dialog.');
}
if (!this.componentMap[id]) {
if (this.parentDialogService) {
this.parentDialogService.hide(id, result);
return;
}
else {
throw new Error(`DialogService.hide: No dialog associated with provided ID \'${id}\'.`);
}
}
this.componentMap[id].hide(result);
this.emitDialogChangeEvent(id, DialogChangeEvent.Hide);
}
/**
* Send Rpc request to shell to add/remove overlay
* @param overlay true: add, false: remove
* @param id id of the dialog
*/
overlayOpen(overlay, id) {
const startOverlay = MsftSme.isExtension()
&& (MsftSme.entryPointType() === EnvironmentModuleEntryPointType.Tool
|| MsftSme.entryPointType() === EnvironmentModuleEntryPointType.SettingsForm);
if (startOverlay) {
// there could be multiple dialog service instances for some reason
this.appContext.registerDialogService(this, id);
this.appContext.frame.overlayOpen(overlay, id)
.pipe(catchError(error => {
const notification = this.appContext.notification.create(null);
notification.showError(this.strings.Overlay.openErrorTitle, Net.getErrorMessage(error));
return EMPTY;
}));
}
}
/**
* Handle clicking on dialog background in shell
* @param dialogId id of dialog whose background was clicked
*/
overlayClicked(dialogId) {
const lastDialog = MsftSme.last(this.activeDialogsStack);
if (lastDialog && lastDialog.id === dialogId) {
lastDialog.onBackgroundClicked();
return true;
}
return false;
}
/**
* Resume focus back to the original element that shows the dialog.
* @param id The id of dialog
* @param delay If provided, delays resuming focus for a period of time in ms
*/
resumeFocus(id, delay = 0) {
// check to see if there is a dialog stack currently.
const wasInDialogStack = this.activeDialogsStack && this.activeDialogsStack.length > 0;
if (this.dialogOrigins[id]) {
setTimeout(() => {
const isInDialogStack = this.activeDialogsStack && this.activeDialogsStack.length > 0;
if (!wasInDialogStack && isInDialogStack) {
// a dialog was opened during the setTimeout.
// This means that the new dialog will resume focus to the wrong element and the new dialog will open unfocused.
this.dialogOrigins[this.activeDialogsStack[0].id] = this.dialogOrigins[id];
delete this.dialogOrigins[id];
}
else if (this.appContext.frame.activeRpcDialogsOrigins.size > 0) {
// an rpc dialog was opened during the setTimeout. So just wait a little longer and then refocus
this.resumeFocus(id, 100);
}
else {
const element = this.dialogOrigins[id];
const focusOn = Dom.getFocusOrigin(element);
if (focusOn) {
focusOn.focus();
}
delete this.dialogOrigins[id];
}
}, delay);
}
}
emitDialogChangeEvent(dialogId, changeEvent) {
this.changedEventSubject.next({ dialogId: dialogId, changeEvent: changeEvent });
}
}
/** @nocollapse */ DialogService.ɵfac = function DialogService_Factory(t) { return new (t || DialogService)(i0.ɵɵinject(i1.AppContextService), i0.ɵɵinject(DialogService, 12)); };
/** @nocollapse */ DialogService.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: DialogService, factory: DialogService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DialogService, [{
type: Injectable
}], function () { return [{ type: i1.AppContextService }, { type: DialogService, decorators: [{
type: SkipSelf
}, {
type: Optional
}] }]; }, null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhbG9nLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9kaWFsb2cvZGlhbG9nLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9ELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUN4RSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sa0RBQWtELENBQUM7QUFDdkUsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sdUVBQXVFLENBQUM7QUFDeEgsT0FBTyxFQUFFLEtBQUssRUFBYyxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzVELE9BQU8sRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVyRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUt0RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7O0FBR3ZELE1BQU0sQ0FBTixJQUFZLGlCQUdYO0FBSEQsV0FBWSxpQkFBaUI7SUFDekIseURBQUksQ0FBQTtJQUNKLHlEQUFJLENBQUE7QUFDUixDQUFDLEVBSFcsaUJBQWlCLEtBQWpCLGlCQUFpQixRQUc1QjtBQVFELE1BQU0sT0FBTyxhQUFhO0lBd0J0QixZQUFvQixVQUE2QixFQUFrQyxtQkFBbUM7UUFBbEcsZUFBVSxHQUFWLFVBQVUsQ0FBbUI7UUFBa0Msd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFnQjtRQXZCL0csY0FBUyxHQUFHO1lBQ2YsTUFBTSxFQUFFLDBCQUEwQjtZQUNsQyxZQUFZLEVBQUUsZ0NBQWdDO1lBQzlDLGdCQUFnQixFQUFFLHFDQUFxQztZQUN2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QUcsQ0FBQyxDQUFDO2lCQUM3QjtxQkFBTTtvQkFDSCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUN2QyxNQUFNLE9BQU8sR0FBZ0IsR0FBRyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDekQsSUFBSSxPQUFPLEVBQUU7d0JBQ1QsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO3FCQUNuQjtvQkFDRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7aUJBQ2pDO1lBRUwsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ2pCO0lBQ0wsQ0FBQztJQUVNLHFCQUFxQixDQUFDLFFBQWdCLEVBQUUsV0FBOEI7UUFDekUsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBYyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDakcsQ0FBQzs7NkZBL1lRLGFBQWE7a0dBQWIsYUFBYSxXQUFiLGFBQWE7dUZBQWIsYUFBYTtjQUR6QixVQUFVOztzQkF5QjZDLFFBQVE7O3NCQUFJLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBPcHRpb25hbCwgU2tpcFNlbGYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgTmV0IH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kYXRhL25ldCc7XHJcbmltcG9ydCB7IERvbSB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvZG9tL2RvbSc7XHJcbmltcG9ydCB7IEVudmlyb25tZW50TW9kdWxlRW50cnlQb2ludFR5cGUgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL21hbmlmZXN0L2Vudmlyb25tZW50LW1vZHVsZXMnO1xyXG5pbXBvcnQgeyBFTVBUWSwgT2JzZXJ2YWJsZSwgb2YsIFJlcGxheVN1YmplY3QgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgY2F0Y2hFcnJvciwgbWFwLCBtZXJnZU1hcCwgdGFrZUxhc3QgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IFN0cmluZ3MgfSBmcm9tICcuLi8uLi9nZW5lcmF0ZWQvc3RyaW5ncyc7XHJcbmltcG9ydCB7IEFwcENvbnRleHRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZS9hcHAtY29udGV4dC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQmFzZURpYWxvZ0NvbXBvbmVudCwgRGlhbG9nT3B0aW9ucywgRGlhbG9nUmVzdWx0IH0gZnJvbSAnLi9iYXNlLWRpYWxvZy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBDaG9pY2VEaWFsb2dPcHRpb25zLCBDaG9pY2VEaWFsb2dSZXN1bHQgfSBmcm9tICcuL2Nob2ljZS1kaWFsb2cvY2hvaWNlLWRpYWxvZy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBDb25maXJtYXRpb25EaWFsb2dPcHRpb25zLCBDb25maXJtYXRpb25EaWFsb2dSZXN1bHQgfSBmcm9tICcuL2NvbmZpcm1hdGlvbi1kaWFsb2cvY29uZmlybWF0aW9uLWRpYWxvZy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBDb25maXJtYXRpb25MaXN0RGlhbG9nT3B0aW9ucywgQ29uZmlybWF0aW9uTGlzdERpYWxvZ1Jlc3VsdCB9IGZyb20gJy4vY29uZmlybWF0aW9uLWxpc3QtZGlhbG9nL2NvbmZpcm1hdGlvbi1saXN0LWRpYWxvZy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBEaWFsb2dDbG9zZVJlYXNvbiB9IGZyb20gJy4vZGlhbG9nLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IE1lc3NhZ2VEaWFsb2dPcHRpb25zIH0gZnJvbSAnLi9tZXNzYWdlLWRpYWxvZy9tZXNzYWdlLWRpYWxvZy5jb21wb25lbnQnO1xyXG5cclxuZXhwb3J0IGVudW0gRGlhbG9nQ2hhbmdlRXZlbnQge1xyXG4gICAgU2hvdyxcclxuICAgIEhpZGVcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBEaWFsb2dFdmVudCB7XHJcbiAgICBkaWFsb2dJZDogc3RyaW5nO1xyXG4gICAgY2hhbmdlRXZlbnQ6IERpYWxvZ0NoYW5nZUV2ZW50O1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBEaWFsb2dTZXJ2aWNlIHtcclxuICAgIHB1YmxpYyBjb21tb25JZHMgPSB7XHJcbiAgICAgICAgY2hvaWNlOiAnc21lLWNvbW1vbi1jaG9pY2UtZGlhbG9nJyxcclxuICAgICAgICBjb25maXJtYXRpb246ICdzbWUtY29tbW9uLWNvbmZpcm1hdGlvbi1kaWFsb2cnLFxyXG4gICAgICAgIGNvbmZpcm1hdGlvbkxpc3Q6ICdzbWUtY29tbW9uLWNvbmZpcm1hdGlvbi1saXN0LWRpYWxvZycsXHJcbiAgICAgICAgbWVzc2FnZTogJ3NtZS1jb21tb24tbWVzc2FnZS1kaWFsb2cnLFxyXG4gICAgICAgIG5vdGlmaWNhdGlvbnNQYW5lOiAnc21lLWNvbW1vbi1ub3RpZmljYXRpb25zLXBhbmUnLFxyXG4gICAgICAgIHNldHRpbmdzOiAnc21lLWNvbW1vbi1zZXR0aW5ncy1wYW5lJyxcclxuICAgICAgICBoZWxwOiAnc21lLWNvbW1vbi1oZWxwLXBhbmUnLFxyXG4gICAgICAgIHVzZXJQYW5lOiAnc21lLWNvbW1vbi11c2VyLXBhbmUnLFxyXG4gICAgICAgIG1hbmFnZUFzOiAnc21lLWNvbW1vbi1tYW5hZ2UtYXMtZGlhbG9nJyxcclxuICAgICAgICBwb3dlclNoZWxsU2hvd1NjcmlwdDogJ3NtZS1jb21tb24tcG93ZXJzaGVsbC1zaG93LXNjcmlwdCcsXHJcbiAgICAgICAgY3JlZFNTUENvbmZpcm1hdGlvbjogJ3NtZS1jcmVkc3NwLWNvbmZpcm1hdGlvbi1kaWFsb2cnLFxyXG4gICAgICAgIHVzZXJBbGl2ZTogJ3NtZS11c2VyLWFsaXZlLWRpYWxvZydcclxuICAgIH07XHJcblxyXG4gICAgcHVibGljIGFjdGl2ZURpYWxvZ3NTdGFjazogQmFzZURpYWxvZ0NvbXBvbmVudDxEaWFsb2dPcHRpb25zLCBEaWFsb2dSZXN1bHQ+W10gPSBbXTtcclxuXHJcbiAgICBwcml2YXRlIHN0cmluZ3MgPSBNc2Z0U21lLmdldFN0cmluZ3M8U3RyaW5ncz4oKS5Nc2Z0U21lU2hlbGwuQW5ndWxhcjtcclxuICAgIHByaXZhdGUgY29tcG9uZW50TWFwOiB7IFtpbmRleDogc3RyaW5nXTogQmFzZURpYWxvZ0NvbXBvbmVudDxEaWFsb2dPcHRpb25zLCBEaWFsb2dSZXN1bHQ+IH0gPSB7fTtcclxuICAgIHByaXZhdGUgYWN0aXZlRGlhbG9nUmVzdWx0OiBPYnNlcnZhYmxlPERpYWxvZ1Jlc3VsdD47XHJcbiAgICBwcml2YXRlIGRpYWxvZ09yaWdpbnM6IHsgW2luZGV4OiBzdHJpbmddOiBIVE1MRWxlbWVudCB9ID0ge307XHJcbiAgICBwcml2YXRlIGNoYW5nZWRFdmVudFN1YmplY3Q6IFJlcGxheVN1YmplY3Q8RGlhbG9nRXZlbnQ+O1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBwQ29udGV4dDogQXBwQ29udGV4dFNlcnZpY2UsIEBTa2lwU2VsZigpIEBPcHRpb25hbCgpIHByaXZhdGUgcGFyZW50RGlhbG9nU2VydmljZT86IERpYWxvZ1NlcnZpY2UpIHtcclxuICAgICAgICB0aGlzLmNoYW5nZWRFdmVudFN1YmplY3QgPSBuZXcgUmVwbGF5U3ViamVjdDxEaWFsb2dFdmVudD4oMSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBzdWJqZWN0IG9mIG5vdGlmaWNhdGlvbiBjaGFuZ2VkIGV2ZW50LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IGNoYW5nZWQoKTogUmVwbGF5U3ViamVjdDxEaWFsb2dFdmVudD4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNoYW5nZWRFdmVudFN1YmplY3Q7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBjdXJyZW50RGlhbG9nTGV2ZWwoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2sgPyB0aGlzLmFjdGl2ZURpYWxvZ3NTdGFjay5sZW5ndGggKyB0aGlzLmlGcmFtZURpYWxvZ0NvdW50IDogdGhpcy5pRnJhbWVEaWFsb2dDb3VudDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGlGcmFtZURpYWxvZ0NvdW50ID0gMDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlZ2lzdGVycyB0aGUgZGlhbG9nIHdpdGggdGhlIHNlcnZpY2UuXHJcbiAgICAgKlxyXG4gICAgICogVE9wdGlvbnMgdGhlIHR5cGUgb2YgdGhlIGRpYWxvZyBvcHRpb25zLlxyXG4gICAgICogVFJlc3VsdCB0aGUgdHlwZSBvZiB0aGUgZGlhbG9nIHJlc3VsdHMuXHJcbiAgICAgKiBAcGFyYW0gaWQgVGhlIHVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBkaWFsb2cuXHJcbiAgICAgKiBAcGFyYW0gY29tcG9uZW50IFRoZSBkaWFsb2cgY29tcG9uZW50LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVnaXN0ZXI8VE9wdGlvbnMgZXh0ZW5kcyBEaWFsb2dPcHRpb25zLCBUUmVzdWx0IGV4dGVuZHMgRGlhbG9nUmVzdWx0PihcclxuICAgICAgICBpZDogc3RyaW5nLFxyXG4gICAgICAgIGNvbXBvbmVudDogQmFzZURpYWxvZ0NvbXBvbmVudDxUT3B0aW9ucywgVFJlc3VsdD5cclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIGlmICghaWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWFsb2dTZXJ2aWNlLnJlZ2lzdGVyOiBJRCBpcyByZXF1aXJlZCB0byByZWdpc3RlciBhIGRpYWxvZy4nKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghY29tcG9uZW50KSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGlhbG9nU2VydmljZS5yZWdpc3RlcjogQSBkaWFsb2cgaXMgcmVxdWlyZWQgdG8gcmVnaXN0ZXIgYSBkaWFsb2cuJyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiByZW1vdmluZyB1bnRpbCB3ZSB1bmRlcnN0YW5kIGNhc2VzIHdoZXJlIGFuZ3VsYXIgY2FuIGNhbGwgbmdPbkluaXQgdHdpY2UuXHJcbiAgICAgICAgICogc2VlOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQyNzAwMTE2L2FuZ3VsYXIyLXJvdXRpbmctaXNzdWUtYW5kLW5nb25pbml0LWNhbGxlZC10d2ljZVxyXG4gICAgICAgICAqIGFuZCBAbXNmdC1zbWUvbG9jYWwtdXNlcnMtZ3JvdXBzIGZvciBleGFtcGxlc1xyXG4gICAgICAgICAqL1xyXG4gICAgICAgIC8vIGlmICh0aGlzLmNvbXBvbmVudE1hcFtpZF0pIHtcclxuICAgICAgICAvLyAgICAgY29uc29sZS53YXJuKGBEaWFsb2dTZXJ2aWNlLnJlZ2lzdGVyOiBBIGRpYWxvZyB3aXRoIHRoZSBJRCBcXCcke2lkfVxcJyBoYXMgYWxyZWFkeSBiZWVuIHJlZ2lzdGVyZWRgKTtcclxuICAgICAgICAvLyB9XHJcblxyXG4gICAgICAgIHRoaXMuY29tcG9uZW50TWFwW2lkXSA9IGNvbXBvbmVudDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFVucmVnaXN0ZXJzIHRoZSBkaWFsb2cgd2l0aCB0aGUgc2VydmljZS5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gaWQgVGhlIHVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBkaWFsb2cuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB1bnJlZ2lzdGVyKGlkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5jb21wb25lbnRNYXBbaWRdKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNvbXBvbmVudE1hcFtpZF07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5hY3RpdmVEaWFsb2dzU3RhY2sgJiYgdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2subGVuZ3RoID4gMCAmJiBNc2Z0U21lLmxhc3QodGhpcy5hY3RpdmVEaWFsb2dzU3RhY2spLmlkID09PSBpZCkge1xyXG4gICAgICAgICAgICB0aGlzLmFjdGl2ZURpYWxvZ3NTdGFjay5wb3AoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGFkZElGcmFtZURpYWxvZygpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmlGcmFtZURpYWxvZ0NvdW50Kys7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHJlbW92ZUlGcmFtZURpYWxvZygpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmlGcmFtZURpYWxvZ0NvdW50ID0gTWF0aC5tYXgodGhpcy5pRnJhbWVEaWFsb2dDb3VudCAtIDEsIDApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2hvd3MgdGhlIGRpYWxvZy5cclxuICAgICAqXHJcbiAgICAgKiBUT3B0aW9ucyBUaGUgdHlwZSBvZiB0aGUgZGlhbG9nIG9wdGlvbnMuXHJcbiAgICAgKiBUUmVzdWx0IFRoZSByZXN1bHQgb2YgdGhlIGRpYWxvZy5cclxuICAgICAqIEBwYXJhbSBpZCBUaGUgdW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGRpYWxvZy5cclxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBkaWFsb2cgb3B0aW9ucy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHNob3c8VE9wdGlvbnMgZXh0ZW5kcyBEaWFsb2dPcHRpb25zLCBUUmVzdWx0IGV4dGVuZHMgRGlhbG9nUmVzdWx0PihpZDogc3RyaW5nLCBvcHRpb25zOiBUT3B0aW9ucyk6IE9ic2VydmFibGU8VFJlc3VsdD4ge1xyXG4gICAgICAgIGlmICghaWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWFsb2dTZXJ2aWNlLnNob3c6IElEIGlzIHJlcXVpcmVkIHRvIHNob3cgYSBkaWFsb2cuJyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXRoaXMuY29tcG9uZW50TWFwW2lkXSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5wYXJlbnREaWFsb2dTZXJ2aWNlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnREaWFsb2dTZXJ2aWNlLnNob3coaWQsIG9wdGlvbnMpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEaWFsb2dTZXJ2aWNlLnNob3c6IE5vIGRpYWxvZyBhc3NvY2lhdGVkIHdpdGggcHJvdmlkZWQgSUQgXFwnJHtpZH1cXCcuYCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld0RpYWxvZyA9IHRoaXMuY29tcG9uZW50TWFwW2lkXTtcclxuICAgICAgICBjb25zdCBvbGREaWFsb2cgPSBNc2Z0U21lLmxhc3QodGhpcy5hY3RpdmVEaWFsb2dzU3RhY2spO1xyXG5cclxuICAgICAgICAvLyBhY2Nlc3NpYmlsaXR5XHJcbiAgICAgICAgaWYgKG9wdGlvbnMgJiYgISg8YW55Pm9wdGlvbnMpLmlzRnJvbVJwYykgeyAvLyBpZiBmcm9tIFJwYyB0aGVuIGRvbid0IHJlc3VtZSBmb2N1cyBzaW5jZSBpdCB3aWxsIGZvY3VzIGJhY2sgb24gaWZyYW1lXHJcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbiA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgICAgICAgIGlmIChvcmlnaW4pIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGlhbG9nT3JpZ2luc1tpZF0gPSBvcmlnaW47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGRvbnQgZG8gYW55dGhpbmcgdW5sZXNzIHdlIGhhdmUgYSBzdWJzY3JpYmVyXHJcbiAgICAgICAgcmV0dXJuIG9mKG9sZERpYWxvZylcclxuICAgICAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICAgICAgICBtZXJnZU1hcChpdCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIGEgcGxhY2Vob2xkZXIgZm9yIHRoZSBuZXcgZGlhbG9nIHJlc3VsdFxyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZXN1bHRPYnNlcnZhYmxlOiBPYnNlcnZhYmxlPFRSZXN1bHQ+O1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbWVtYmVyIGlmIHRoZXJlIHdhcyBhbiBhY3RpdmUgZGlhbG9nIHdoZW4gd2Ugc3RhcnRlZFxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nQWN0aXZlRGlhbG9nID0gISFvbGREaWFsb2c7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nQWN0aXZlRGlhbG9nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvbGREaWFsb2cua2VlcE9wZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjdXJyZW50bHkgYWN0aXZlIGRpYWxvZyB3YW50cyB0byBzdGF5IG9wZW4sIHRoZW4ga2VlcCBpdCBvcGVuIGFuZCBzaG93IHRoZSBuZXcgZGlhbG9nIG9uIHRvcFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2sucHVzaChuZXdEaWFsb2cpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vdmVybGF5T3Blbih0cnVlLCBuZXdEaWFsb2cuaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2Ugc2V0IHRoZSBkaWFsb2cgbGV2ZWwgYXMgdGhlIGxlbmd0aCBvZiB0aGUgYWN0aXZlIGRpYWxvZ3Mgc3RhY2tcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0RpYWxvZy5zZXRMZXZlbCh0aGlzLmN1cnJlbnREaWFsb2dMZXZlbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZURpYWxvZ1Jlc3VsdCA9IG5ld0RpYWxvZy5zaG93KG9wdGlvbnMpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUobWFwKHJlc3VsdCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheU9wZW4oZmFsc2UsIG5ld0RpYWxvZy5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2xkRGlhbG9nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGREaWFsb2cuYXV0b0ZvY3VzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0T2JzZXJ2YWJsZSA9IDxPYnNlcnZhYmxlPFRSZXN1bHQ+PnRoaXMuYWN0aXZlRGlhbG9nUmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYW4gYWN0aXZlIGRpYWxvZywgd2FpdCBmb3IgaXQgdG8gY29tcGxldGUsIHRoZW4gc2hvdyBhIHRoZSBuZXcgb25lXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRPYnNlcnZhYmxlID0gPE9ic2VydmFibGU8VFJlc3VsdD4+dGhpcy5hY3RpdmVEaWFsb2dSZXN1bHRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucGlwZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFrZUxhc3QoMSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlTWFwKCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnNob3coaWQsIG9wdGlvbnMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGVyZSBpcyBubyBhY3RpdmUgZGlhbG9nLCB0aGVuIGp1c3Qgc2hvdyB0aGUgbmV3IG9uZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZURpYWxvZ3NTdGFjay5wdXNoKG5ld0RpYWxvZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheU9wZW4odHJ1ZSwgbmV3RGlhbG9nLmlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3RGlhbG9nLnNldExldmVsKHRoaXMuY3VycmVudERpYWxvZ0xldmVsKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVEaWFsb2dSZXN1bHQgPSBuZXdEaWFsb2cuc2hvdyhvcHRpb25zKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKHJlc3VsdCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheU9wZW4oZmFsc2UsIG5ld0RpYWxvZy5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvbGREaWFsb2cpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZERpYWxvZy5hdXRvRm9jdXMoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2sucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRPYnNlcnZhYmxlID0gPE9ic2VydmFibGU8VFJlc3VsdD4+dGhpcy5hY3RpdmVEaWFsb2dSZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBoYWQgYW4gYWN0aXZlIGRpYWxvZywgcmVxdWVzdCB0aGUgcHJldmlvdXMgZGlhbG9nIHRvIGNsb3NlIHVubGVzcyBpdCB3YW50cyB0byBzdGF5IG9wZW5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZXhpc3RpbmdBY3RpdmVEaWFsb2cgJiYgIW9sZERpYWxvZy5rZWVwT3Blbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbGREaWFsb2cuY2xvc2VSZXF1ZXN0ZWQoRGlhbG9nQ2xvc2VSZWFzb24uQ29tcGV0aW5nRGlhbG9nKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdERpYWxvZ0NoYW5nZUV2ZW50KGlkLCBEaWFsb2dDaGFuZ2VFdmVudC5TaG93KTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0T2JzZXJ2YWJsZTtcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNob3dzIGEgbWVzc2FnZSBkaWFsb2cgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9uc1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBkaWFsb2cgb3B0aW9ucy5cclxuICAgICAqIEByZXR1cm5zIEEgc3ViamVjdCB0aGF0IHdpbGwgYmUgcHVibGlzaGVkIG9uZSB0aW1lIHdpdGggdGhlIGRpYWxvZyByZXN1bHRcclxuICAgICAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2UgJ0FwcENvbnRleHRTZXJ2aWNlLmZyYW1lLnNob3dEaWFsb2dNZXNzYWdlJyBvbiBleHRlbnNpb25zLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2hvd01lc3NhZ2Uob3B0aW9uczogTWVzc2FnZURpYWxvZ09wdGlvbnMpOiBPYnNlcnZhYmxlPERpYWxvZ1Jlc3VsdD4ge1xyXG4gICAgICAgIC8vIGlmIHJ1bm5pbmcgZnJvbSBzaGVsbCwgbWFudWFsbHkgbGF1bmNoIGRpYWxvZ1xyXG4gICAgICAgIGlmICh0aGlzLmFwcENvbnRleHQucnBjLmlzU2hlbGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2hvdyh0aGlzLmNvbW1vbklkcy5tZXNzYWdlLCBvcHRpb25zKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBvdGhlcndpc2UgYXNrIHRoZSBzaGVsbCB0byBkbyBpdCBmb3IgdXMuXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFwcENvbnRleHQuZnJhbWUuc2hvd0RpYWxvZ01lc3NhZ2Uoe1xyXG4gICAgICAgICAgICAgICAgYnV0dG9uVGV4dDogb3B0aW9ucy5idXR0b25UZXh0LFxyXG4gICAgICAgICAgICAgICAgY2hlY2tib3hUZXh0OiBvcHRpb25zLmNoZWNrYm94VGV4dCxcclxuICAgICAgICAgICAgICAgIGV4dGVybmFsTGluazogb3B0aW9ucy5leHRlcm5hbExpbmssXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBvcHRpb25zLm1lc3NhZ2UsXHJcbiAgICAgICAgICAgICAgICB0aXRsZTogb3B0aW9ucy50aXRsZVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIaWRlIGEgbWVzc2FnZSBkaWFsb2cuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoaWRlTWVzc2FnZSgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmhpZGUodGhpcy5jb21tb25JZHMubWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTaG93cyBhIGNob2ljZSBkaWFsb2cgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgZGlhbG9nIG9wdGlvbnMuXHJcbiAgICAgKiBAcmV0dXJucyBBIHN1YmplY3QgdGhhdCB3aWxsIGJlIHB1Ymxpc2hlZCBvbmUgdGltZSB3aXRoIHRoZSBkaWFsb2cgcmVzdWx0LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2hvd0Nob2ljZShvcHRpb25zOiBDaG9pY2VEaWFsb2dPcHRpb25zKTogT2JzZXJ2YWJsZTxDaG9pY2VEaWFsb2dSZXN1bHQ+IHtcclxuICAgICAgICBpZiAodGhpcy5hcHBDb250ZXh0LnJwYy5pc1NoZWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNob3codGhpcy5jb21tb25JZHMuY2hvaWNlLCBvcHRpb25zKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hcHBDb250ZXh0LmZyYW1lLnNob3dEaWFsb2dDaG9pY2Uoe1xyXG4gICAgICAgICAgICAgICAgY2FuY2VsQnV0dG9uVGV4dDogb3B0aW9ucy5jYW5jZWxCdXR0b25UZXh0LFxyXG4gICAgICAgICAgICAgICAgY2hvaWNlczogb3B0aW9ucy5jaG9pY2VzLFxyXG4gICAgICAgICAgICAgICAgY29uZmlybUJ1dHRvblRleHQ6IG9wdGlvbnMuY29uZmlybUJ1dHRvblRleHQsXHJcbiAgICAgICAgICAgICAgICBmb290bm90ZTogb3B0aW9ucy5mb290bm90ZSxcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMubWVzc2FnZSxcclxuICAgICAgICAgICAgICAgIHRpdGxlOiBvcHRpb25zLnRpdGxlXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhpZGUgYSBjaG9pY2UgZGlhbG9nLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGlkZUNob2ljZSgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmhpZGU8Q2hvaWNlRGlhbG9nUmVzdWx0Pih0aGlzLmNvbW1vbklkcy5jaG9pY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2hvd3MgYSBjb25maXJtYXRpb24gZGlhbG9nIHdpdGggdGhlIGdpdmVuIG9wdGlvbnNcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgZGlhbG9nIG9wdGlvbnMuXHJcbiAgICAgKiBAcmV0dXJucyBBIHN1YmplY3QgdGhhdCB3aWxsIGJlIHB1Ymxpc2hlZCBvbmUgdGltZSB3aXRoIHRoZSBkaWFsb2cgcmVzdWx0XHJcbiAgICAgKiBAZGVwcmVjYXRlZCBzaW5jZSAwMi8yMC8xOC4gUGxlYXNlIHVzZSAnQXBwQ29udGV4dFNlcnZpY2UuZnJhbWUuc2hvd0RpYWxvZ0NvbmZpcm1hdGlvbicgaW5zdGVhZFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2hvd0NvbmZpcm1hdGlvbihvcHRpb25zOiBDb25maXJtYXRpb25EaWFsb2dPcHRpb25zKTogT2JzZXJ2YWJsZTxDb25maXJtYXRpb25EaWFsb2dSZXN1bHQ+IHtcclxuICAgICAgICBsZXQgY29uZmlybWF0aW9uT2JzZXJ2YWJsZTtcclxuXHJcbiAgICAgICAgLy8gaWYgcnVubmluZyBmcm9tIHNoZWxsLCBtYW51YWxseSBsYXVuY2ggZGlhbG9nXHJcbiAgICAgICAgaWYgKHRoaXMuYXBwQ29udGV4dC5ycGMuaXNTaGVsbCkge1xyXG4gICAgICAgICAgICBjb25maXJtYXRpb25PYnNlcnZhYmxlID0gdGhpcy5zaG93KHRoaXMuY29tbW9uSWRzLmNvbmZpcm1hdGlvbiwgb3B0aW9ucyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGFzayB0aGUgc2hlbGwgdG8gZG8gaXQgZm9yIHVzLlxyXG4gICAgICAgICAgICBjb25maXJtYXRpb25PYnNlcnZhYmxlID0gdGhpcy5hcHBDb250ZXh0LmZyYW1lLnNob3dEaWFsb2dDb25maXJtYXRpb24oe1xyXG4gICAgICAgICAgICAgICAgY2FuY2VsQnV0dG9uVGV4dDogb3B0aW9ucy5jYW5jZWxCdXR0b25UZXh0LFxyXG4gICAgICAgICAgICAgICAgY2hlY2tib3hUZXh0OiBvcHRpb25zLmNoZWNrYm94VGV4dCxcclxuICAgICAgICAgICAgICAgIGNvbmZpcm1CdXR0b25UZXh0OiBvcHRpb25zLmNvbmZpcm1CdXR0b25UZXh0LFxyXG4gICAgICAgICAgICAgICAgZG91YmxlQ2hlY2tUZXh0OiBvcHRpb25zLmRvdWJsZUNoZWNrVGV4dCxcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMubWVzc2FnZSxcclxuICAgICAgICAgICAgICAgIHRpdGxlOiBvcHRpb25zLnRpdGxlXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGNvbmZpcm1hdGlvbk9ic2VydmFibGUucGlwZShtYXAoKHJlc3BvbnNlOiBDb25maXJtYXRpb25EaWFsb2dSZXN1bHQpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IHsgY29uZmlybWVkOiBmYWxzZSwgY2hlY2tib3hSZXN1bHQ6IGZhbHNlIH07XHJcbiAgICAgICAgfSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGlkZSBhIGNvbmZpcm1hdGlvbiBkaWFsb2cuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoaWRlQ29uZmlybWF0aW9uKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuaGlkZSh0aGlzLmNvbW1vbklkcy5jb25maXJtYXRpb24pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2hvd3MgYSBjb25maXJtYXRpb24gbGlzdCBkaWFsb2cgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9uc1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBkaWFsb2cgb3B0aW9ucy5cclxuICAgICAqIEByZXR1cm5zIEEgc3ViamVjdCB0aGF0IHdpbGwgYmUgcHVibGlzaGVkIG9uZSB0aW1lIHdpdGggdGhlIGRpYWxvZyByZXN1bHRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHNob3dDb25maXJtYXRpb25MaXN0KG9wdGlvbnM6IENvbmZpcm1hdGlvbkxpc3REaWFsb2dPcHRpb25zKTogT2JzZXJ2YWJsZTxDb25maXJtYXRpb25MaXN0RGlhbG9nUmVzdWx0PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuc2hvdyh0aGlzLmNvbW1vbklkcy5jb25maXJtYXRpb25MaXN0LCBvcHRpb25zKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhpZGUgYSBjb25maXJtYXRpb24gbGlzdCAgZGlhbG9nLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGlkZUNvbmZpcm1hdGlvbkxpc3QoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5oaWRlKHRoaXMuY29tbW9uSWRzLmNvbmZpcm1hdGlvbkxpc3QpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGlkZXMgdGhlIGRpYWxvZy5cclxuICAgICAqXHJcbiAgICAgKiBUUmVzdWx0IFRoZSB0eXBlIG9mIHRoZSBkaWFsb2cgcmVzdWx0LlxyXG4gICAgICogQHBhcmFtIGlkIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgZGlhbG9nLlxyXG4gICAgICogQHBhcmFtIHJlc3VsdCBUaGUgcmVzdWx0IG9mIHRoZSBkaWFsb2cuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoaWRlPFRSZXN1bHQgZXh0ZW5kcyBEaWFsb2dSZXN1bHQ+KGlkOiBzdHJpbmcsIHJlc3VsdD86IFRSZXN1bHQpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIWlkKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGlhbG9nU2VydmljZS5oaWRlOiBJRCBpcyByZXF1aXJlZCB0byBoaWRlIGEgZGlhbG9nLicpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbXBvbmVudE1hcFtpZF0pIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMucGFyZW50RGlhbG9nU2VydmljZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnREaWFsb2dTZXJ2aWNlLmhpZGUoaWQsIHJlc3VsdCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERpYWxvZ1NlcnZpY2UuaGlkZTogTm8gZGlhbG9nIGFzc29jaWF0ZWQgd2l0aCBwcm92aWRlZCBJRCBcXCcke2lkfVxcJy5gKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5jb21wb25lbnRNYXBbaWRdLmhpZGUocmVzdWx0KTtcclxuICAgICAgICB0aGlzLmVtaXREaWFsb2dDaGFuZ2VFdmVudChpZCwgRGlhbG9nQ2hhbmdlRXZlbnQuSGlkZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZW5kIFJwYyByZXF1ZXN0IHRvIHNoZWxsIHRvIGFkZC9yZW1vdmUgb3ZlcmxheVxyXG4gICAgICogQHBhcmFtIG92ZXJsYXkgdHJ1ZTogYWRkLCBmYWxzZTog