@nova-ui/bits
Version:
SolarWinds Nova Framework
273 lines • 38.7 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { Injectable, Injector, SecurityContext } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";
import _assign from "lodash/assign";
import _cloneDeep from "lodash/cloneDeep";
import _isArray from "lodash/isArray";
import _toInteger from "lodash/toInteger";
import { take } from "rxjs/operators";
import { ToastContainerService } from "./toast-container.service";
import { ToastInjector } from "./toast-injector";
import { ToastPackage } from "./toast-package";
import { ToastRef } from "./toast-ref";
import { ToastComponent } from "./toast.component";
import { SwitchState } from "../../services/notification-args";
import { NotificationService } from "../../services/notification-service";
import * as i0 from "@angular/core";
import * as i1 from "../../services/notification-service";
import * as i2 from "./toast-container.service";
import * as i3 from "@angular/platform-browser";
/**
* __Name : __
* Toast Service
*
* __Usage :__
* Used to show toast messages and to trigger highlight of items
*/
/**
* @ignore
*/
export class ToastService {
constructor(notificationService, toastContainerService, _injector, sanitizer) {
this.notificationService = notificationService;
this.toastContainerService = toastContainerService;
this._injector = _injector;
this.sanitizer = sanitizer;
this.index = 0;
this.currentlyActive = 0;
this.toasts = [];
this.defaultToastConfig = {
maxOpened: 0,
autoDismiss: false,
newestOnTop: true,
preventDuplicates: false,
positionClass: "nui-toast--top-right" /* ToastPositionClass.TOP_RIGHT */,
progressAnimation: "decreasing",
timeOut: 5000,
progressBar: true,
toastClass: "nui-toast",
extendedTimeOut: 2000,
closeButton: true,
clickToDismiss: false,
enableHtml: true,
stickyError: false,
};
this.notifyHighlights = (itemsToHighlight, status) => {
if (itemsToHighlight) {
this.notificationService.post("Highlight", {
highlightState: SwitchState.on,
status: status,
items: itemsToHighlight,
itemIdentificator: this.itemIdentificator,
});
}
};
this.toastConfig = _assign({}, this.defaultToastConfig);
}
/**
*
* __Description:__ set global config for all kind of toasts and itemIdentificator that is
* used for identification of item in nuiToast directive
* @param config
* @param itemIdentificator
* @return void
*/
setConfig(config, itemIdentificator) {
_assign(this.toastConfig, config);
this.itemIdentificator = itemIdentificator;
}
/**
*
* __Description:__ show success toast trigger highlight of items and trigger fade out of highlighting when
* toast is gone
*
* @param toastDeclaration
* @return void
*/
success(toastDeclaration) {
const toastInstance = this.buildNotification("success", toastDeclaration.message, toastDeclaration.title, this.applyConfig(toastDeclaration.options));
this.notifyHighlights(toastDeclaration.itemsToHighlight, "success");
this.toastRemoveHighlight(toastInstance, toastDeclaration.itemsToHighlight);
return toastInstance;
}
warning(toastDeclaration) {
const toastInstance = this.buildNotification("warning", toastDeclaration.message, toastDeclaration.title, this.applyConfig(toastDeclaration.options));
this.notifyHighlights(toastDeclaration.itemsToHighlight, "warning");
this.toastRemoveHighlight(toastInstance, toastDeclaration.itemsToHighlight);
return toastInstance;
}
error(toastDeclaration) {
const config = _cloneDeep(toastDeclaration.options);
if (toastDeclaration.options &&
toastDeclaration.options.stickyError &&
config) {
config.timeOut = 0;
config.extendedTimeOut = 0;
config.progressBar = false;
config.closeButton = false;
}
const toastInstance = this.buildNotification("error", toastDeclaration.message, toastDeclaration.title, this.applyConfig(config));
this.notifyHighlights(toastDeclaration.itemsToHighlight, "error");
this.toastRemoveHighlight(toastInstance, toastDeclaration.itemsToHighlight);
return toastInstance;
}
info(toastDeclaration) {
const toastInstance = this.buildNotification("info", toastDeclaration.message, toastDeclaration.title, this.applyConfig(toastDeclaration.options));
this.notifyHighlights(toastDeclaration.itemsToHighlight, "info");
this.toastRemoveHighlight(toastInstance, toastDeclaration.itemsToHighlight);
return toastInstance;
}
/**
*
* __Description:__ calls toasts' close methods to close them
*
* @param toastId
* @return void
*/
clear(toastId) {
for (const toast of this.toasts) {
if (toastId !== undefined) {
if (toast.toastId === toastId) {
toast.toastRef.manualClose();
return;
}
}
else {
toast.toastRef.manualClose();
}
}
}
/**
*
* __Description:__ removes toast by id and activates next toast in queue (when maxOpened !== 0)
*
* @param toastId
* @return boolean
*/
remove(toastId) {
const toastInstance = this.findToast(toastId);
if (!toastInstance) {
return false;
}
toastInstance.activeToast.toastRef.close();
this.toasts.splice(toastInstance.index, 1);
this.currentlyActive = this.currentlyActive - 1;
if (!this.toastConfig.maxOpened || !this.toasts.length) {
return false;
}
if (this.currentlyActive <= +this.toastConfig.maxOpened &&
this.toasts[this.currentlyActive]) {
const activeToastRef = this.toasts[this.currentlyActive].toastRef;
if (!activeToastRef.isInactive()) {
this.currentlyActive = this.currentlyActive + 1;
activeToastRef.activate();
}
}
return true;
}
toastRemoveHighlight(toastInstance, itemsToRemoveHighlight) {
if (toastInstance) {
toastInstance?.onHidden?.pipe(take(1)).subscribe(() => {
if (_isArray(itemsToRemoveHighlight) &&
itemsToRemoveHighlight.length > 0) {
this.notificationService.post("Highlight", {
highlightState: SwitchState.off,
items: itemsToRemoveHighlight,
});
}
});
}
}
applyConfig(override = {}) {
const resultConfig = _assign({}, this.toastConfig, override);
resultConfig.timeOut = _toInteger(resultConfig.timeOut);
resultConfig.extendedTimeOut = _toInteger(resultConfig.extendedTimeOut);
return resultConfig;
}
buildNotification(toastType, body, title, config) {
// max opened and auto dismiss = true
if (body && config.preventDuplicates && this.isDuplicate(body)) {
// TODO: Update buildNotification return type in V10 in the scope of NUI-5824
// @ts-ignore: Suppressing error until v10 to prevent API breaking changes
return null;
}
this.toastContainerService.getContainerElement(config.positionClass);
let keepInactive = false;
let sanitizedBody = body;
if (this.toastConfig.maxOpened &&
this.currentlyActive >= this.toastConfig.maxOpened) {
keepInactive = true;
if (this.toastConfig.autoDismiss) {
this.clear(this.toasts[this.toasts.length - 1].toastId);
}
}
this.index = this.index + 1;
if (body && config.enableHtml) {
sanitizedBody = (this.sanitizer.sanitize(SecurityContext.HTML, body));
}
const toastRef = new ToastRef(this.toastContainerService);
const toastPackage = new ToastPackage(this.index, config, sanitizedBody, title, toastType, toastRef);
const toastInjector = new ToastInjector(toastPackage, this._injector);
toastRef.componentInstance = this.toastContainerService.attachToast(ToastComponent, toastInjector, !!config.newestOnTop);
const toastInstance = {
toastId: this.index,
body: sanitizedBody,
toastRef,
onShown: toastRef.afterActivate(),
onHidden: toastRef.afterClosed(),
onClick: toastPackage.onClick(),
};
if (!keepInactive) {
setTimeout(() => {
toastInstance.toastRef.activate();
this.currentlyActive = this.currentlyActive + 1;
});
}
this.toasts.push(toastInstance);
return toastInstance;
}
/**
* Determines if toast message is already shown
*/
isDuplicate(body) {
for (let i = 0; i < this.toasts.length; i++) {
if (this.toasts[i].body === body) {
return true;
}
}
return false;
}
findToast(toastId) {
for (let i = 0; i < this.toasts.length; i++) {
if (this.toasts[i].toastId === toastId) {
return { index: i, activeToast: this.toasts[i] };
}
}
return null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToastService, deps: [{ token: i1.NotificationService }, { token: i2.ToastContainerService }, { token: i0.Injector }, { token: i3.DomSanitizer }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToastService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToastService, decorators: [{
type: Injectable,
args: [{ providedIn: "root" }]
}], ctorParameters: () => [{ type: i1.NotificationService }, { type: i2.ToastContainerService }, { type: i0.Injector }, { type: i3.DomSanitizer }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9hc3Quc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdG9hc3QvdG9hc3Quc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDcEMsT0FBTyxVQUFVLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsT0FBTyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxVQUFVLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBU3RDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQy9ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDOzs7OztBQUUxRTs7Ozs7O0dBTUc7QUFDSDs7R0FFRztBQUVILE1BQU0sT0FBTyxZQUFZO0lBdUJyQixZQUNZLG1CQUF3QyxFQUN4QyxxQkFBNEMsRUFDNUMsU0FBbUIsRUFDbkIsU0FBdUI7UUFIdkIsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUN4QywwQkFBcUIsR0FBckIscUJBQXFCLENBQXVCO1FBQzVDLGNBQVMsR0FBVCxTQUFTLENBQVU7UUFDbkIsY0FBUyxHQUFULFNBQVMsQ0FBYztRQTFCM0IsVUFBSyxHQUFHLENBQUMsQ0FBQztRQUNWLG9CQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLFdBQU0sR0FBbUIsRUFBRSxDQUFDO1FBQzVCLHVCQUFrQixHQUFpQjtZQUN2QyxTQUFTLEVBQUUsQ0FBQztZQUNaLFdBQVcsRUFBRSxLQUFLO1lBQ2xCLFdBQVcsRUFBRSxJQUFJO1lBQ2pCLGlCQUFpQixFQUFFLEtBQUs7WUFDeEIsYUFBYSwyREFBOEI7WUFDM0MsaUJBQWlCLEVBQUUsWUFBWTtZQUMvQixPQUFPLEVBQUUsSUFBSTtZQUNiLFdBQVcsRUFBRSxJQUFJO1lBQ2pCLFVBQVUsRUFBRSxXQUFXO1lBQ3ZCLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLFdBQVcsRUFBRSxJQUFJO1lBQ2pCLGNBQWMsRUFBRSxLQUFLO1lBQ3JCLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFdBQVcsRUFBRSxLQUFLO1NBQ3JCLENBQUM7UUE0Uk0scUJBQWdCLEdBQUcsQ0FDdkIsZ0JBQTBDLEVBQzFDLE1BQWMsRUFDVixFQUFFO1lBQ04sSUFBSSxnQkFBZ0IsRUFBRTtnQkFDbEIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7b0JBQ3ZDLGNBQWMsRUFBRSxXQUFXLENBQUMsRUFBRTtvQkFDOUIsTUFBTSxFQUFFLE1BQU07b0JBQ2QsS0FBSyxFQUFFLGdCQUFnQjtvQkFDdkIsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGlCQUFpQjtpQkFDNUMsQ0FBQyxDQUFDO2FBQ047UUFDTCxDQUFDLENBQUM7UUE5UkUsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksU0FBUyxDQUFDLE1BQW9CLEVBQUUsaUJBQTBCO1FBQzdELE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztJQUMvQyxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNJLE9BQU8sQ0FBQyxnQkFBbUM7UUFDOUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUN4QyxTQUFTLEVBQ1QsZ0JBQWdCLENBQUMsT0FBTyxFQUN4QixnQkFBZ0IsQ0FBQyxLQUFLLEVBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQzdDLENBQUM7UUFDRixJQUFJLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLG9CQUFvQixDQUNyQixhQUFhLEVBQ2IsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQ3BDLENBQUM7UUFDRixPQUFPLGFBQWEsQ0FBQztJQUN6QixDQUFDO0lBRU0sT0FBTyxDQUFDLGdCQUFtQztRQUM5QyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQ3hDLFNBQVMsRUFDVCxnQkFBZ0IsQ0FBQyxPQUFPLEVBQ3hCLGdCQUFnQixDQUFDLEtBQUssRUFDdEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FDN0MsQ0FBQztRQUNGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsb0JBQW9CLENBQ3JCLGFBQWEsRUFDYixnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FDcEMsQ0FBQztRQUNGLE9BQU8sYUFBYSxDQUFDO0lBQ3pCLENBQUM7SUFFTSxLQUFLLENBQUMsZ0JBQW1DO1FBQzVDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVwRCxJQUNJLGdCQUFnQixDQUFDLE9BQU87WUFDeEIsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDcEMsTUFBTSxFQUNSO1lBQ0UsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7WUFDbkIsTUFBTSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUM7WUFDM0IsTUFBTSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7WUFDM0IsTUFBTSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7U0FDOUI7UUFFRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQ3hDLE9BQU8sRUFDUCxnQkFBZ0IsQ0FBQyxPQUFPLEVBQ3hCLGdCQUFnQixDQUFDLEtBQUssRUFDdEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FDM0IsQ0FBQztRQUNGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsb0JBQW9CLENBQ3JCLGFBQWEsRUFDYixnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FDcEMsQ0FBQztRQUNGLE9BQU8sYUFBYSxDQUFDO0lBQ3pCLENBQUM7SUFFTSxJQUFJLENBQUMsZ0JBQW1DO1FBQzNDLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FDeEMsTUFBTSxFQUNOLGdCQUFnQixDQUFDLE9BQU8sRUFDeEIsZ0JBQWdCLENBQUMsS0FBSyxFQUN0QixJQUFJLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUM3QyxDQUFDO1FBQ0YsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyxvQkFBb0IsQ0FDckIsYUFBYSxFQUNiLGdCQUFnQixDQUFDLGdCQUFnQixDQUNwQyxDQUFDO1FBQ0YsT0FBTyxhQUFhLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLEtBQUssQ0FBQyxPQUFnQjtRQUN6QixLQUFLLE1BQU0sS0FBSyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDN0IsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFO2dCQUN2QixJQUFJLEtBQUssQ0FBQyxPQUFPLEtBQUssT0FBTyxFQUFFO29CQUMzQixLQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO29CQUM3QixPQUFPO2lCQUNWO2FBQ0o7aUJBQU07Z0JBQ0gsS0FBSyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQzthQUNoQztTQUNKO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLE1BQU0sQ0FBQyxPQUFlO1FBQ3pCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFOUMsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNoQixPQUFPLEtBQUssQ0FBQztTQUNoQjtRQUVELGFBQWEsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzNDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQztRQUVoRCxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUNwRCxPQUFPLEtBQUssQ0FBQztTQUNoQjtRQUVELElBQ0ksSUFBSSxDQUFDLGVBQWUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUztZQUNuRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsRUFDbkM7WUFDRSxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLENBQUM7WUFDbEUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsRUFBRTtnQkFDOUIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQztnQkFDaEQsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDO2FBQzdCO1NBQ0o7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRU8sb0JBQW9CLENBQ3hCLGFBQWtDLEVBQ2xDLHNCQUE4QjtRQUU5QixJQUFJLGFBQWEsRUFBRTtZQUNmLGFBQWEsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2xELElBQ0ksUUFBUSxDQUFDLHNCQUFzQixDQUFDO29CQUNoQyxzQkFBc0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUNuQztvQkFDRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTt3QkFDdkMsY0FBYyxFQUFFLFdBQVcsQ0FBQyxHQUFHO3dCQUMvQixLQUFLLEVBQUUsc0JBQXNCO3FCQUNoQyxDQUFDLENBQUM7aUJBQ047WUFDTCxDQUFDLENBQUMsQ0FBQztTQUNOO0lBQ0wsQ0FBQztJQUVPLFdBQVcsQ0FBQyxXQUF5QixFQUFFO1FBQzNDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUM3RCxZQUFZLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEQsWUFBWSxDQUFDLGVBQWUsR0FBRyxVQUFVLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sWUFBWSxDQUFDO0lBQ3hCLENBQUM7SUFFTyxpQkFBaUIsQ0FDckIsU0FBaUIsRUFDakIsSUFBd0IsRUFDeEIsS0FBeUIsRUFDekIsTUFBb0I7UUFFcEIscUNBQXFDO1FBQ3JDLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxpQkFBaUIsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQzVELDZFQUE2RTtZQUM3RSwwRUFBMEU7WUFDMUUsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDckUsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLElBQUksYUFBYSxHQUF1QixJQUFJLENBQUM7UUFFN0MsSUFDSSxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVM7WUFDMUIsSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFDcEQ7WUFDRSxZQUFZLEdBQUcsSUFBSSxDQUFDO1lBQ3BCLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUU7Z0JBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUMzRDtTQUNKO1FBRUQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUU1QixJQUFJLElBQUksSUFBSSxNQUFNLENBQUMsVUFBVSxFQUFFO1lBQzNCLGFBQWEsR0FBVyxDQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUN0RCxDQUFDO1NBQ0w7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUMxRCxNQUFNLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FDakMsSUFBSSxDQUFDLEtBQUssRUFDVixNQUFNLEVBQ04sYUFBYSxFQUNiLEtBQUssRUFDTCxTQUFTLEVBQ1QsUUFBUSxDQUNYLENBQUM7UUFDRixNQUFNLGFBQWEsR0FBRyxJQUFJLGFBQWEsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RFLFFBQVEsQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUMvRCxjQUFjLEVBQ2QsYUFBYSxFQUNiLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUN2QixDQUFDO1FBQ0YsTUFBTSxhQUFhLEdBQUc7WUFDbEIsT0FBTyxFQUFFLElBQUksQ0FBQyxLQUFLO1lBQ25CLElBQUksRUFBRSxhQUFhO1lBQ25CLFFBQVE7WUFDUixPQUFPLEVBQUUsUUFBUSxDQUFDLGFBQWEsRUFBRTtZQUNqQyxRQUFRLEVBQUUsUUFBUSxDQUFDLFdBQVcsRUFBRTtZQUNoQyxPQUFPLEVBQUUsWUFBWSxDQUFDLE9BQU8sRUFBRTtTQUNsQyxDQUFDO1FBRUYsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNmLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ1osYUFBYSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbEMsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQztZQUNwRCxDQUFDLENBQUMsQ0FBQztTQUNOO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDaEMsT0FBTyxhQUFhLENBQUM7SUFDekIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssV0FBVyxDQUFDLElBQVk7UUFDNUIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3pDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxFQUFFO2dCQUM5QixPQUFPLElBQUksQ0FBQzthQUNmO1NBQ0o7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRU8sU0FBUyxDQUNiLE9BQWU7UUFFZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDekMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxPQUFPLEVBQUU7Z0JBQ3BDLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDcEQ7U0FDSjtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7K0dBN1NRLFlBQVk7bUhBQVosWUFBWSxjQURDLE1BQU07OzRGQUNuQixZQUFZO2tCQUR4QixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbIi8vIMKpIDIwMjIgU29sYXJXaW5kcyBXb3JsZHdpZGUsIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyAgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbi8vICBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyAgVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3RvciwgU2VjdXJpdHlDb250ZXh0IH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gXCJAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyXCI7XG5pbXBvcnQgX2Fzc2lnbiBmcm9tIFwibG9kYXNoL2Fzc2lnblwiO1xuaW1wb3J0IF9jbG9uZURlZXAgZnJvbSBcImxvZGFzaC9jbG9uZURlZXBcIjtcbmltcG9ydCBfaXNBcnJheSBmcm9tIFwibG9kYXNoL2lzQXJyYXlcIjtcbmltcG9ydCBfdG9JbnRlZ2VyIGZyb20gXCJsb2Rhc2gvdG9JbnRlZ2VyXCI7XG5pbXBvcnQgeyB0YWtlIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5cbmltcG9ydCB7XG4gICAgSUFjdGl2ZVRvYXN0LFxuICAgIElUb2FzdENvbmZpZyxcbiAgICBJVG9hc3REZWNsYXJhdGlvbixcbiAgICBJVG9hc3RTZXJ2aWNlLFxuICAgIFRvYXN0UG9zaXRpb25DbGFzcyxcbn0gZnJvbSBcIi4vcHVibGljLWFwaVwiO1xuaW1wb3J0IHsgVG9hc3RDb250YWluZXJTZXJ2aWNlIH0gZnJvbSBcIi4vdG9hc3QtY29udGFpbmVyLnNlcnZpY2VcIjtcbmltcG9ydCB7IFRvYXN0SW5qZWN0b3IgfSBmcm9tIFwiLi90b2FzdC1pbmplY3RvclwiO1xuaW1wb3J0IHsgVG9hc3RQYWNrYWdlIH0gZnJvbSBcIi4vdG9hc3QtcGFja2FnZVwiO1xuaW1wb3J0IHsgVG9hc3RSZWYgfSBmcm9tIFwiLi90b2FzdC1yZWZcIjtcbmltcG9ydCB7IFRvYXN0Q29tcG9uZW50IH0gZnJvbSBcIi4vdG9hc3QuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBTd2l0Y2hTdGF0ZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9ub3RpZmljYXRpb24tYXJnc1wiO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9ub3RpZmljYXRpb24tc2VydmljZVwiO1xuXG4vKipcbiAqIF9fTmFtZSA6IF9fXG4gKiBUb2FzdCBTZXJ2aWNlXG4gKlxuICogX19Vc2FnZSA6X19cbiAqIFVzZWQgdG8gc2hvdyB0b2FzdCBtZXNzYWdlcyBhbmQgdG8gdHJpZ2dlciBoaWdobGlnaHQgb2YgaXRlbXNcbiAqL1xuLyoqXG4gKiBAaWdub3JlXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogXCJyb290XCIgfSlcbmV4cG9ydCBjbGFzcyBUb2FzdFNlcnZpY2UgaW1wbGVtZW50cyBJVG9hc3RTZXJ2aWNlIHtcbiAgICBwcml2YXRlIGluZGV4ID0gMDtcbiAgICBwcml2YXRlIGN1cnJlbnRseUFjdGl2ZSA9IDA7XG4gICAgcHJpdmF0ZSB0b2FzdHM6IElBY3RpdmVUb2FzdFtdID0gW107XG4gICAgcHJpdmF0ZSBkZWZhdWx0VG9hc3RDb25maWc6IElUb2FzdENvbmZpZyA9IHtcbiAgICAgICAgbWF4T3BlbmVkOiAwLFxuICAgICAgICBhdXRvRGlzbWlzczogZmFsc2UsXG4gICAgICAgIG5ld2VzdE9uVG9wOiB0cnVlLFxuICAgICAgICBwcmV2ZW50RHVwbGljYXRlczogZmFsc2UsXG4gICAgICAgIHBvc2l0aW9uQ2xhc3M6IFRvYXN0UG9zaXRpb25DbGFzcy5UT1BfUklHSFQsXG4gICAgICAgIHByb2dyZXNzQW5pbWF0aW9uOiBcImRlY3JlYXNpbmdcIixcbiAgICAgICAgdGltZU91dDogNTAwMCxcbiAgICAgICAgcHJvZ3Jlc3NCYXI6IHRydWUsXG4gICAgICAgIHRvYXN0Q2xhc3M6IFwibnVpLXRvYXN0XCIsXG4gICAgICAgIGV4dGVuZGVkVGltZU91dDogMjAwMCxcbiAgICAgICAgY2xvc2VCdXR0b246IHRydWUsXG4gICAgICAgIGNsaWNrVG9EaXNtaXNzOiBmYWxzZSxcbiAgICAgICAgZW5hYmxlSHRtbDogdHJ1ZSxcbiAgICAgICAgc3RpY2t5RXJyb3I6IGZhbHNlLFxuICAgIH07XG4gICAgcHJpdmF0ZSB0b2FzdENvbmZpZzogSVRvYXN0Q29uZmlnO1xuICAgIHByaXZhdGUgaXRlbUlkZW50aWZpY2F0b3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIG5vdGlmaWNhdGlvblNlcnZpY2U6IE5vdGlmaWNhdGlvblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdG9hc3RDb250YWluZXJTZXJ2aWNlOiBUb2FzdENvbnRhaW5lclNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgX2luamVjdG9yOiBJbmplY3RvcixcbiAgICAgICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplclxuICAgICkge1xuICAgICAgICB0aGlzLnRvYXN0Q29uZmlnID0gX2Fzc2lnbih7fSwgdGhpcy5kZWZhdWx0VG9hc3RDb25maWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogX19EZXNjcmlwdGlvbjpfXyBzZXQgZ2xvYmFsIGNvbmZpZyBmb3IgYWxsIGtpbmQgb2YgdG9hc3RzIGFuZCBpdGVtSWRlbnRpZmljYXRvciB0aGF0IGlzXG4gICAgICogdXNlZCBmb3IgaWRlbnRpZmljYXRpb24gb2YgaXRlbSBpbiBudWlUb2FzdCBkaXJlY3RpdmVcbiAgICAgKiBAcGFyYW0gY29uZmlnXG4gICAgICogQHBhcmFtIGl0ZW1JZGVudGlmaWNhdG9yXG4gICAgICogQHJldHVybiB2b2lkXG4gICAgICovXG4gICAgcHVibGljIHNldENvbmZpZyhjb25maWc6IElUb2FzdENvbmZpZywgaXRlbUlkZW50aWZpY2F0b3I/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgX2Fzc2lnbih0aGlzLnRvYXN0Q29uZmlnLCBjb25maWcpO1xuICAgICAgICB0aGlzLml0ZW1JZGVudGlmaWNhdG9yID0gaXRlbUlkZW50aWZpY2F0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBfX0Rlc2NyaXB0aW9uOl9fIHNob3cgc3VjY2VzcyB0b2FzdCB0cmlnZ2VyIGhpZ2hsaWdodCBvZiBpdGVtcyBhbmQgdHJpZ2dlciBmYWRlIG91dCBvZiBoaWdobGlnaHRpbmcgd2hlblxuICAgICAqIHRvYXN0IGlzIGdvbmVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB0b2FzdERlY2xhcmF0aW9uXG4gICAgICogQHJldHVybiB2b2lkXG4gICAgICovXG4gICAgcHVibGljIHN1Y2Nlc3ModG9hc3REZWNsYXJhdGlvbjogSVRvYXN0RGVjbGFyYXRpb24pOiBJQWN0aXZlVG9hc3Qge1xuICAgICAgICBjb25zdCB0b2FzdEluc3RhbmNlID0gdGhpcy5idWlsZE5vdGlmaWNhdGlvbihcbiAgICAgICAgICAgIFwic3VjY2Vzc1wiLFxuICAgICAgICAgICAgdG9hc3REZWNsYXJhdGlvbi5tZXNzYWdlLFxuICAgICAgICAgICAgdG9hc3REZWNsYXJhdGlvbi50aXRsZSxcbiAgICAgICAgICAgIHRoaXMuYXBwbHlDb25maWcodG9hc3REZWNsYXJhdGlvbi5vcHRpb25zKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm5vdGlmeUhpZ2hsaWdodHModG9hc3REZWNsYXJhdGlvbi5pdGVtc1RvSGlnaGxpZ2h0LCBcInN1Y2Nlc3NcIik7XG4gICAgICAgIHRoaXMudG9hc3RSZW1vdmVIaWdobGlnaHQoXG4gICAgICAgICAgICB0b2FzdEluc3RhbmNlLFxuICAgICAgICAgICAgdG9hc3REZWNsYXJhdGlvbi5pdGVtc1RvSGlnaGxpZ2h0XG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB0b2FzdEluc3RhbmNlO1xuICAgIH1cblxuICAgIHB1YmxpYyB3YXJuaW5nKHRvYXN0RGVjbGFyYXRpb246IElUb2FzdERlY2xhcmF0aW9uKTogSUFjdGl2ZVRvYXN0IHtcbiAgICAgICAgY29uc3QgdG9hc3RJbnN0YW5jZSA9IHRoaXMuYnVpbGROb3RpZmljYXRpb24oXG4gICAgICAgICAgICBcIndhcm5pbmdcIixcbiAgICAgICAgICAgIHRvYXN0RGVjbGFyYXRpb24ubWVzc2FnZSxcbiAgICAgICAgICAgIHRvYXN0RGVjbGFyYXRpb24udGl0bGUsXG4gICAgICAgICAgICB0aGlzLmFwcGx5Q29uZmlnKHRvYXN0RGVjbGFyYXRpb24ub3B0aW9ucylcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5ub3RpZnlIaWdobGlnaHRzKHRvYXN0RGVjbGFyYXRpb24uaXRlbXNUb0hpZ2hsaWdodCwgXCJ3YXJuaW5nXCIpO1xuICAgICAgICB0aGlzLnRvYXN0UmVtb3ZlSGlnaGxpZ2h0KFxuICAgICAgICAgICAgdG9hc3RJbnN0YW5jZSxcbiAgICAgICAgICAgIHRvYXN0RGVjbGFyYXRpb24uaXRlbXNUb0hpZ2hsaWdodFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdG9hc3RJbnN0YW5jZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZXJyb3IodG9hc3REZWNsYXJhdGlvbjogSVRvYXN0RGVjbGFyYXRpb24pOiBJQWN0aXZlVG9hc3Qge1xuICAgICAgICBjb25zdCBjb25maWcgPSBfY2xvbmVEZWVwKHRvYXN0RGVjbGFyYXRpb24ub3B0aW9ucyk7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdG9hc3REZWNsYXJhdGlvbi5vcHRpb25zICYmXG4gICAgICAgICAgICB0b2FzdERlY2xhcmF0aW9uLm9wdGlvbnMuc3RpY2t5RXJyb3IgJiZcbiAgICAgICAgICAgIGNvbmZpZ1xuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbmZpZy50aW1lT3V0ID0gMDtcbiAgICAgICAgICAgIGNvbmZpZy5leHRlbmRlZFRpbWVPdXQgPSAwO1xuICAgICAgICAgICAgY29uZmlnLnByb2dyZXNzQmFyID0gZmFsc2U7XG4gICAgICAgICAgICBjb25maWcuY2xvc2VCdXR0b24gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRvYXN0SW5zdGFuY2UgPSB0aGlzLmJ1aWxkTm90aWZpY2F0aW9uKFxuICAgICAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICAgICAgdG9hc3REZWNsYXJhdGlvbi5tZXNzYWdlLFxuICAgICAgICAgICAgdG9hc3REZWNsYXJhdGlvbi50aXRsZSxcbiAgICAgICAgICAgIHRoaXMuYXBwbHlDb25maWcoY29uZmlnKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm5vdGlmeUhpZ2hsaWdodHModG9hc3REZWNsYXJhdGlvbi5pdGVtc1RvSGlnaGxpZ2h0LCBcImVycm9yXCIpO1xuICAgICAgICB0aGlzLnRvYXN0UmVtb3ZlSGlnaGxpZ2h0KFxuICAgICAgICAgICAgdG9hc3RJbnN0YW5jZSxcbiAgICAgICAgICAgIHRvYXN0RGVjbGFyYXRpb24uaXRlbXNUb0hpZ2hsaWdodFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdG9hc3RJbnN0YW5jZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5mbyh0b2FzdERlY2xhcmF0aW9uOiBJVG9hc3REZWNsYXJhdGlvbik6IElBY3RpdmVUb2FzdCB7XG4gICAgICAgIGNvbnN0IHRvYXN0SW5zdGFuY2UgPSB0aGlzLmJ1aWxkTm90aWZpY2F0aW9uKFxuICAgICAgICAgICAgXCJpbmZvXCIsXG4gICAgICAgICAgICB0b2FzdERlY2xhcmF0aW9uLm1lc3NhZ2UsXG4gICAgICAgICAgICB0b2FzdERlY2xhcmF0aW9uLnRpdGxlLFxuICAgICAgICAgICAgdGhpcy5hcHBseUNvbmZpZyh0b2FzdERlY2xhcmF0aW9uLm9wdGlvbnMpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMubm90aWZ5SGlnaGxpZ2h0cyh0b2FzdERlY2xhcmF0aW9uLml0ZW1zVG9IaWdobGlnaHQsIFwiaW5mb1wiKTtcbiAgICAgICAgdGhpcy50b2FzdFJlbW92ZUhpZ2hsaWdodChcbiAgICAgICAgICAgIHRvYXN0SW5zdGFuY2UsXG4gICAgICAgICAgICB0b2FzdERlY2xhcmF0aW9uLml0ZW1zVG9IaWdobGlnaHRcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHRvYXN0SW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBfX0Rlc2NyaXB0aW9uOl9fIGNhbGxzIHRvYXN0cycgY2xvc2UgbWV0aG9kcyB0byBjbG9zZSB0aGVtXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdG9hc3RJZFxuICAgICAqIEByZXR1cm4gdm9pZFxuICAgICAqL1xuICAgIHB1YmxpYyBjbGVhcih0b2FzdElkPzogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGZvciAoY29uc3QgdG9hc3Qgb2YgdGhpcy50b2FzdHMpIHtcbiAgICAgICAgICAgIGlmICh0b2FzdElkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodG9hc3QudG9hc3RJZCA9PT0gdG9hc3RJZCkge1xuICAgICAgICAgICAgICAgICAgICB0b2FzdC50b2FzdFJlZi5tYW51YWxDbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0b2FzdC50b2FzdFJlZi5tYW51YWxDbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBfX0Rlc2NyaXB0aW9uOl9fIHJlbW92ZXMgdG9hc3QgYnkgaWQgYW5kIGFjdGl2YXRlcyBuZXh0IHRvYXN0IGluIHF1ZXVlICh3aGVuIG1heE9wZW5lZCAhPT0gMClcbiAgICAgKlxuICAgICAqIEBwYXJhbSB0b2FzdElkXG4gICAgICogQHJldHVybiBib29sZWFuXG4gICAgICovXG4gICAgcHVibGljIHJlbW92ZSh0b2FzdElkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgdG9hc3RJbnN0YW5jZSA9IHRoaXMuZmluZFRvYXN0KHRvYXN0SWQpO1xuXG4gICAgICAgIGlmICghdG9hc3RJbnN0YW5jZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdG9hc3RJbnN0YW5jZS5hY3RpdmVUb2FzdC50b2FzdFJlZi5jbG9zZSgpO1xuICAgICAgICB0aGlzLnRvYXN0cy5zcGxpY2UodG9hc3RJbnN0YW5jZS5pbmRleCwgMSk7XG4gICAgICAgIHRoaXMuY3VycmVudGx5QWN0aXZlID0gdGhpcy5jdXJyZW50bHlBY3RpdmUgLSAxO1xuXG4gICAgICAgIGlmICghdGhpcy50b2FzdENvbmZpZy5tYXhPcGVuZWQgfHwgIXRoaXMudG9hc3RzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5jdXJyZW50bHlBY3RpdmUgPD0gK3RoaXMudG9hc3RDb25maWcubWF4T3BlbmVkICYmXG4gICAgICAgICAgICB0aGlzLnRvYXN0c1t0aGlzLmN1cnJlbnRseUFjdGl2ZV1cbiAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBhY3RpdmVUb2FzdFJlZiA9IHRoaXMudG9hc3RzW3RoaXMuY3VycmVudGx5QWN0aXZlXS50b2FzdFJlZjtcbiAgICAgICAgICAgIGlmICghYWN0aXZlVG9hc3RSZWYuaXNJbmFjdGl2ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50bHlBY3RpdmUgPSB0aGlzLmN1cnJlbnRseUFjdGl2ZSArIDE7XG4gICAgICAgICAgICAgICAgYWN0aXZlVG9hc3RSZWYuYWN0aXZhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgdG9hc3RSZW1vdmVIaWdobGlnaHQoXG4gICAgICAgIHRvYXN0SW5zdGFuY2U6IElBY3RpdmVUb2FzdCB8IG51bGwsXG4gICAgICAgIGl0ZW1zVG9SZW1vdmVIaWdobGlnaHQ/OiBhbnlbXVxuICAgICk6IHZvaWQge1xuICAgICAgICBpZiAodG9hc3RJbnN0YW5jZSkge1xuICAgICAgICAgICAgdG9hc3RJbnN0YW5jZT8ub25IaWRkZW4/LnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIF9pc0FycmF5KGl0ZW1zVG9SZW1vdmVIaWdobGlnaHQpICYmXG4gICAgICAgICAgICAgICAgICAgIGl0ZW1zVG9SZW1vdmVIaWdobGlnaHQubGVuZ3RoID4gMFxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2UucG9zdChcIkhpZ2hsaWdodFwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHRTdGF0ZTogU3dpdGNoU3RhdGUub2ZmLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXM6IGl0ZW1zVG9SZW1vdmVIaWdobGlnaHQsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBseUNvbmZpZyhvdmVycmlkZTogSVRvYXN0Q29uZmlnID0ge30pOiBJVG9hc3RDb25maWcge1xuICAgICAgICBjb25zdCByZXN1bHRDb25maWcgPSBfYXNzaWduKHt9LCB0aGlzLnRvYXN0Q29uZmlnLCBvdmVycmlkZSk7XG4gICAgICAgIHJlc3VsdENvbmZpZy50aW1lT3V0ID0gX3RvSW50ZWdlcihyZXN1bHRDb25maWcudGltZU91dCk7XG4gICAgICAgIHJlc3VsdENvbmZpZy5leHRlbmRlZFRpbWVPdXQgPSBfdG9JbnRlZ2VyKHJlc3VsdENvbmZpZy5leHRlbmRlZFRpbWVPdXQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0Q29uZmlnO1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGROb3RpZmljYXRpb24oXG4gICAgICAgIHRvYXN0VHlwZTogc3RyaW5nLFxuICAgICAgICBib2R5OiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgICAgIHRpdGxlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgICAgIGNvbmZpZzogSVRvYXN0Q29uZmlnXG4gICAgKTogSUFjdGl2ZVRvYXN0IHtcbiAgICAgICAgLy8gbWF4IG9wZW5lZCBhbmQgYXV0byBkaXNtaXNzID0gdHJ1ZVxuICAgICAgICBpZiAoYm9keSAmJiBjb25maWcucHJldmVudER1cGxpY2F0ZXMgJiYgdGhpcy5pc0R1cGxpY2F0ZShib2R5KSkge1xuICAgICAgICAgICAgLy8gVE9ETzogVXBkYXRlIGJ1aWxkTm90aWZpY2F0aW9uIHJldHVybiB0eXBlIGluIFYxMCBpbiB0aGUgc2NvcGUgb2YgTlVJLTU4MjRcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmU6IFN1cHByZXNzaW5nIGVycm9yIHVudGlsIHYxMCB0byBwcmV2ZW50IEFQSSBicmVha2luZyBjaGFuZ2VzXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudG9hc3RDb250YWluZXJTZXJ2aWNlLmdldENvbnRhaW5lckVsZW1lbnQoY29uZmlnLnBvc2l0aW9uQ2xhc3MpO1xuICAgICAgICBsZXQga2VlcEluYWN0aXZlID0gZmFsc2U7XG4gICAgICAgIGxldCBzYW5pdGl6ZWRCb2R5OiBzdHJpbmcgfCB1bmRlZmluZWQgPSBib2R5O1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMudG9hc3RDb25maWcubWF4T3BlbmVkICYmXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRseUFjdGl2ZSA+PSB0aGlzLnRvYXN0Q29uZmlnLm1heE9wZW5lZFxuICAgICAgICApIHtcbiAgICAgICAgICAgIGtlZXBJbmFjdGl2ZSA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGhpcy50b2FzdENvbmZpZy5hdXRvRGlzbWlzcykge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIodGhpcy50b2FzdHNbdGhpcy50b2FzdHMubGVuZ3RoIC0gMV0udG9hc3RJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluZGV4ID0gdGhpcy5pbmRleCArIDE7XG5cbiAgICAgICAgaWYgKGJvZHkgJiYgY29uZmlnLmVuYWJsZUh0bWwpIHtcbiAgICAgICAgICAgIHNhbml0aXplZEJvZHkgPSA8c3RyaW5nPihcbiAgICAgICAgICAgICAgICB0aGlzLnNhbml0aXplci5zYW5pdGl6ZShTZWN1cml0eUNvbnRleHQuSFRNTCwgYm9keSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0b2FzdFJlZiA9IG5ldyBUb2FzdFJlZih0aGlzLnRvYXN0Q29udGFpbmVyU2VydmljZSk7XG4gICAgICAgIGNvbnN0IHRvYXN0UGFja2FnZSA9IG5ldyBUb2FzdFBhY2thZ2UoXG4gICAgICAgICAgICB0aGlzLmluZGV4LFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgc2FuaXRpemVkQm9keSxcbiAgICAgICAgICAgIHRpdGxlLFxuICAgICAgICAgICAgdG9hc3RUeXBlLFxuICAgICAgICAgICAgdG9hc3RSZWZcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdG9hc3RJbmplY3RvciA9IG5ldyBUb2FzdEluamVjdG9yKHRvYXN0UGFja2FnZSwgdGhpcy5faW5qZWN0b3IpO1xuICAgICAgICB0b2FzdFJlZi5jb21wb25lbnRJbnN0YW5jZSA9IHRoaXMudG9hc3RDb250YWluZXJTZXJ2aWNlLmF0dGFjaFRvYXN0KFxuICAgICAgICAgICAgVG9hc3RDb21wb25lbnQsXG4gICAgICAgICAgICB0b2FzdEluamVjdG9yLFxuICAgICAgICAgICAgISFjb25maWcubmV3ZXN0T25Ub3BcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdG9hc3RJbnN0YW5jZSA9IHtcbiAgICAgICAgICAgIHRvYXN0SWQ6IHRoaXMuaW5kZXgsXG4gICAgICAgICAgICBib2R5OiBzYW5pdGl6ZWRCb2R5LFxuICAgICAgICAgICAgdG9hc3RSZWYsXG4gICAgICAgICAgICBvblNob3duOiB0b2FzdFJlZi5hZnRlckFjdGl2YXRlKCksXG4gICAgICAgICAgICBvbkhpZGRlbjogdG9hc3RSZWYuYWZ0ZXJDbG9zZWQoKSxcbiAgICAgICAgICAgIG9uQ2xpY2s6IHRvYXN0UGFja2FnZS5vbkNsaWNrKCksXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKCFrZWVwSW5hY3RpdmUpIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRvYXN0SW5zdGFuY2UudG9hc3RSZWYuYWN0aXZhdGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRseUFjdGl2ZSA9IHRoaXMuY3VycmVudGx5QWN0aXZlICsgMTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50b2FzdHMucHVzaCh0b2FzdEluc3RhbmNlKTtcbiAgICAgICAgcmV0dXJuIHRvYXN0SW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyBpZiB0b2FzdCBtZXNzYWdlIGlzIGFscmVhZHkgc2hvd25cbiAgICAgKi9cbiAgICBwcml2YXRlIGlzRHVwbGljYXRlKGJvZHk6IHN0cmluZykge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudG9hc3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50b2FzdHNbaV0uYm9keSA9PT0gYm9keSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgZmluZFRvYXN0KFxuICAgICAgICB0b2FzdElkOiBudW1iZXJcbiAgICApOiB7IGluZGV4OiBudW1iZXI7IGFjdGl2ZVRvYXN0OiBJQWN0aXZlVG9hc3QgfSB8IG51bGwge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudG9hc3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50b2FzdHNbaV0udG9hc3RJZCA9PT0gdG9hc3RJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGluZGV4OiBpLCBhY3RpdmVUb2FzdDogdGhpcy50b2FzdHNbaV0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgbm90aWZ5SGlnaGxpZ2h0cyA9IChcbiAgICAgICAgaXRlbXNUb0hpZ2hsaWdodDogYW55W10gfCBudWxsIHwgdW5kZWZpbmVkLFxuICAgICAgICBzdGF0dXM6IHN0cmluZ1xuICAgICk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoaXRlbXNUb0hpZ2hsaWdodCkge1xuICAgICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLnBvc3QoXCJIaWdobGlnaHRcIiwge1xuICAgICAgICAgICAgICAgIGhpZ2hsaWdodFN0YXRlOiBTd2l0Y2hTdGF0ZS5vbixcbiAgICAgICAgICAgICAgICBzdGF0dXM6IHN0YXR1cyxcbiAgICAgICAgICAgICAgICBpdGVtczogaXRlbXNUb0hpZ2hsaWdodCxcbiAgICAgICAgICAgICAgICBpdGVtSWRlbnRpZmljYXRvcjogdGhpcy5pdGVtSWRlbnRpZmljYXRvcixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbn1cbiJdfQ==