@nova-ui/bits
Version:
SolarWinds Nova Framework
323 lines • 53.1 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 { Directive, ElementRef, EventEmitter, Input, NgZone, Output, Renderer2, } from "@angular/core";
import debounce from "lodash/debounce";
import isFunction from "lodash/isFunction";
import isUndefined from "lodash/isUndefined";
import { ResizeDirection, resizeDirectionHelpers, ResizeUnit, } from "./public-api";
import { COMPLETE_RESIZE_EVENT } from "../../../constants/event.constants";
import { RESIZE_DEBOUNCE_TIME } from "../../../constants/resize.constants";
import { EventBusService } from "../../../services/event-bus.service";
import { UtilService } from "../../../services/util.service";
import * as i0 from "@angular/core";
import * as i1 from "../../../services/util.service";
import * as i2 from "../../../services/event-bus.service";
/** @ignore */
const resizeClass = "nui-resize-gutter";
/**
* @ignore
* <example-url>./../examples/index.html#/resizer</example-url>
*/
export class ResizerDirective {
set resizerDirection(direction) {
this._direction = direction;
this.refreshStyle();
}
get resizerDirection() {
return this._direction;
}
set resizerDisabled(isDisabled) {
this._disabled = isDisabled;
if (this.resizeGutter) {
this.switchDisabledClasses();
if (!isDisabled) {
this.refreshStyle();
}
}
}
get resizerDisabled() {
return this._disabled;
}
constructor(elRef, renderer, utilService, _element, ngZone, eventBusService) {
this.elRef = elRef;
this.renderer = renderer;
this.utilService = utilService;
this._element = _element;
this.ngZone = ngZone;
this.eventBusService = eventBusService;
/**
* Sets custom size of resizable element
*/
this._size = 16;
/**
* Disables element resizing
*/
this._disabled = false;
/**
* Choose resize value of your element(pixel, percent). By default pixels are used.
*/
this.resizerValue = ResizeUnit.pixel;
/**
* Emits new size of element on which directive was applied
*/
this.resizerSizeChanged = new EventEmitter();
this.resizeClass = resizeClass;
this.offsetSize = this._size / 2;
this._resizeElement = document.createElement("div");
this._oldSize = 0;
this._isDragging = false;
this._isFirstTimeInteracting = true;
this._isHovering = false;
this.eventSubscriptions = [];
}
ngOnChanges(changes) {
if (changes["resizerDirection"] && this.resizeGutter) {
this.appendResizeElement();
}
}
ngAfterViewInit() {
// as derived class doesn't inherits lifecycle hooks,
// we can reassign targetElement there, in this case we just use directive's nativeElement
this.targetElement = this.elRef;
this.addSubscription();
if (!this.isAtTheBeginning()) {
this.renderer.appendChild(this.targetElement.nativeElement, this._resizeElement);
this.resizeGutter =
this.targetElement.nativeElement.lastElementChild;
}
else {
this.renderer.insertBefore(this.targetElement.nativeElement, this._resizeElement, this.targetElement.nativeElement.firstElementChild);
this.resizeGutter =
this.targetElement.nativeElement.firstElementChild;
}
this.appendResizeElement();
this.resizeGutter.className = this.resizeClass;
this.parentContainerNode =
this.targetElement.nativeElement.parentElement;
this.addResizeObserver();
this.appendEvents();
this.refreshStyle();
}
ngOnDestroy() {
if (this.resizeObserver) {
this.resizeObserver.unobserve(this.targetElement.nativeElement.parentElement);
}
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
this.unlistenEvents();
}
addResizeObserver() {
const resizeHandler = debounce((entry) => this.refreshStyle(), RESIZE_DEBOUNCE_TIME);
this.resizeObserver = new ResizeObserver((entries) => {
entries.forEach((entry) => {
this.ngZone.run(() => {
if (!this.resizerDisabled) {
resizeHandler(entry);
}
});
});
});
this.ngZone.runOutsideAngular(() => {
this.resizeObserver?.observe(this.targetElement.nativeElement.parentElement);
});
}
addSubscription() {
this.resizeSubscription = this.eventBusService
.getStream(COMPLETE_RESIZE_EVENT)
.subscribe((resize) => this.refreshStyle());
}
onSizeChanged(newSize) {
this.resizerSizeChanged.emit(newSize);
}
refreshStyle() {
if (this.resizeGutter && !this.resizerDisabled) {
// fix safari bug about gutter height when direction is horizontal
this.renderer.setStyle(this.resizeGutter, this.resizePropObj.sizeToSet, `${this._size}px`);
this.renderer.setStyle(this.resizeGutter, this.resizePropObj.otherSizeProperty, "100%");
this.calculatePosition();
this.renderer.setStyle(this.resizeGutter, "cursor", this.resizePropObj.cursor);
this.switchDisabledClasses();
}
}
unlistenEvents() {
this.eventSubscriptions.forEach((unlistenFn) => {
if (isFunction(unlistenFn)) {
unlistenFn();
}
});
}
appendEvents() {
this.eventSubscriptions.push(this.renderer.listen(this.resizeGutter, "mouseenter", ($event) => this.onMouseEnter($event)));
this.eventSubscriptions.push(this.renderer.listen(this.resizeGutter, "mouseleave", () => this.onMouseLeave()));
this.eventSubscriptions.push(this.renderer.listen(this.resizeGutter, "mousedown", ($event) => this.onMouseDown($event)));
}
isResizeHorizontal() {
return (this.resizerDirection === ResizeDirection.left ||
this.resizerDirection === ResizeDirection.right);
}
isAtTheBeginning() {
return (this.resizerDirection === ResizeDirection.left ||
this.resizerDirection === ResizeDirection.top);
}
switchDisabledClasses() {
this.resizerDisabled
? this.renderer.addClass(this.resizeGutter, `${this.resizeClass}-disabled`)
: this.renderer.removeClass(this.resizeGutter, `${this.resizeClass}-disabled`);
}
appendResizeElement() {
if (this.resizerSplit) {
this.renderer.removeChild(this.resizeGutter, this.resizerSplit);
}
this.resizerSplit = document.createElement("div");
this.renderer.addClass(this.resizerSplit, `${this.resizeClass}__split`);
this.renderer.addClass(this.resizerSplit, `${this.resizeClass}__split-${this.isResizeHorizontal() ? "horizontal" : "vertical"}`);
this.renderer.appendChild(this.resizeGutter, this.resizerSplit);
this.resizePropObj = resizeDirectionHelpers[this.resizerDirection];
}
unlistenResizeEvents() {
if (isFunction(this.mouseMoveUnlisten) && !this._isHovering) {
this.mouseMoveUnlisten();
}
if (isFunction(this.mouseUpUnlisten)) {
this.mouseUpUnlisten();
}
}
// Registers mousemove
onMouseEnter(event) {
this._isHovering = true;
// Add hovering class only while mouse is not clicked
// "which" is supported by Safari
if ((!isUndefined(event.buttons) && event.buttons === 0) ||
(!isUndefined(event.which) && event.which === 0)) {
this.renderer.addClass(this.resizeGutter, `${this.resizeClass}--hovering`);
this.mouseMoveUnlisten = this.renderer.listen(document, "mousemove", ($event) => this.onMouseMove($event));
}
}
onMouseLeave() {
this.renderer.removeClass(this.resizeGutter, `${this.resizeClass}--hovering`);
if (!this._isDragging) {
this._isHovering = false;
this.unlistenResizeEvents();
}
}
onMouseMove(event) {
// No need to update styles for resizer that we're not dragging
if (this._isFirstTimeInteracting && this._isDragging) {
this.refreshStyle();
this._isFirstTimeInteracting = false;
}
if (this._isDragging) {
this.applyNewSize(event);
this.calculatePosition();
}
}
// Registers mouseup
onMouseDown(event) {
this.renderer.addClass(this.resizeGutter, `${this.resizeClass}--active`);
// Cursor should be there until mouseUp.
this.renderer.setStyle(document.documentElement, "cursor", this.resizePropObj.cursor);
this._isDragging = true;
this._oldSize = this.isResizeHorizontal()
? event.clientX
: event.clientY;
this.mouseUpUnlisten = this.renderer.listen(document, "mouseup", ($event) => this.onMouseUp($event));
event.preventDefault(); // This disables accidental text selection while resizingw
}
onMouseUp(event) {
this.renderer.removeStyle(document.documentElement, "cursor");
this.renderer.removeClass(this.resizeGutter, `${this.resizeClass}--active`);
this._isDragging = false;
this.eventBusService.getStream(COMPLETE_RESIZE_EVENT).next(event);
}
calculatePosition() {
if (this.resizerDisabled) {
return;
}
const parentCoord = this.parentContainerNode.getBoundingClientRect()[this.resizePropObj.appendDirection];
const elementCoord = this.targetElement.nativeElement.getBoundingClientRect()[this.resizePropObj.borderToCalculate];
this.renderer.setStyle(this.resizeGutter, this.resizePropObj.appendDirection, `${Math.abs(parentCoord - elementCoord) - this.offsetSize}px`);
}
applyNewSize(event) {
this.sibling = this.targetElement.nativeElement.nextSibling;
if (!this._isDragging || this.resizerDisabled) {
return;
}
const newSize = this.isResizeHorizontal()
? event.clientX
: event.clientY;
this.updateSize(newSize);
}
updateSize(newSize) {
const updatedProp = this.isMultiple
? "flex-basis"
: this.resizePropObj.sizeToSet;
const parentSize = this.parentContainerNode[this.resizePropObj.nativeElementSizeProperty];
const valueCoeff = this.resizerValue === ResizeUnit.pixel ? 1 : 100 / parentSize;
// if width is already defined then use it without calculating
const nativeElSize = `${this.calculateNativeElementSize(newSize, this.resizePropObj.nativeElementSizeProperty) * valueCoeff}${this.resizerValue}`;
const resizerPosition = `${this.targetElement.nativeElement[this.resizePropObj.nativeElementSizeProperty] - this.offsetSize}px`;
if (!this.isMultiple) {
this.renderer.setStyle(this.targetElement.nativeElement, updatedProp, nativeElSize);
}
else {
const siblingSize = `${this.calculateSiblingSize(newSize, this.resizePropObj.nativeElementSizeProperty) * valueCoeff}${this.resizerValue}`;
if (this.parentContainerNode.children.length > 2) {
// These 2 should ALWAYS be together
this.renderer.setStyle(this.sibling, updatedProp, siblingSize);
this.renderer.setStyle(this.targetElement.nativeElement, updatedProp, nativeElSize);
}
}
this.renderer.setStyle(this.resizeGutter, this.resizePropObj.appendDirection, resizerPosition);
this.onSizeChanged(nativeElSize);
this._oldSize = newSize;
}
calculateNativeElementSize(newSize, updatedProp) {
return this.isAtTheBeginning()
? this.targetElement.nativeElement[updatedProp] -
(newSize - this._oldSize)
: this.targetElement.nativeElement[updatedProp] +
(newSize - this._oldSize);
}
calculateSiblingSize(newSize, updatedProp) {
return this.isAtTheBeginning()
? this.sibling[updatedProp] + (newSize - this._oldSize)
: this.sibling[updatedProp] - (newSize - this._oldSize);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizerDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.UtilService }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: i2.EventBusService }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ResizerDirective, selector: "[nuiResizer]", inputs: { resizerDirection: "resizerDirection", resizerDisabled: "resizerDisabled", resizerValue: "resizerValue", isMultiple: "isMultiple" }, outputs: { resizerSizeChanged: "resizerSizeChanged" }, usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizerDirective, decorators: [{
type: Directive,
args: [{
selector: "[nuiResizer]",
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.UtilService }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: i2.EventBusService }], propDecorators: { resizerDirection: [{
type: Input
}], resizerDisabled: [{
type: Input
}], resizerValue: [{
type: Input
}], isMultiple: [{
type: Input
}], resizerSizeChanged: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvY29tbW9uL2RpcmVjdGl2ZXMvcmVzaXplci9yZXNpemVyLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUVILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEVBR04sTUFBTSxFQUNOLFNBQVMsR0FFWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQztBQUN2QyxPQUFPLFVBQVUsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQyxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQztBQUc3QyxPQUFPLEVBRUgsZUFBZSxFQUNmLHNCQUFzQixFQUN0QixVQUFVLEdBQ2IsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDM0UsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDM0UsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7OztBQUU3RCxjQUFjO0FBQ2QsTUFBTSxXQUFXLEdBQUcsbUJBQW1CLENBQUM7QUFFeEM7OztHQUdHO0FB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bUI7UUFDN0QsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDMUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUN2RCxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDaEUsQ0FBQzsrR0E3YlEsZ0JBQWdCO21HQUFoQixnQkFBZ0I7OzRGQUFoQixnQkFBZ0I7a0JBSDVCLFNBQVM7bUJBQUM7b0JBQ1AsUUFBUSxFQUFFLGNBQWM7aUJBQzNCOzZNQU9nQixnQkFBZ0I7c0JBQTVCLEtBQUs7Z0JBbUJPLGVBQWU7c0JBQTNCLEtBQUs7Z0JBZ0JVLFlBQVk7c0JBQTNCLEtBQUs7Z0JBS1UsVUFBVTtzQkFBekIsS0FBSztnQkFLVyxrQkFBa0I7c0JBQWxDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIERpcmVjdGl2ZSxcbiAgICBFbGVtZW50UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBJbnB1dCxcbiAgICBOZ1pvbmUsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uRGVzdHJveSxcbiAgICBPdXRwdXQsXG4gICAgUmVuZGVyZXIyLFxuICAgIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgZGVib3VuY2UgZnJvbSBcImxvZGFzaC9kZWJvdW5jZVwiO1xuaW1wb3J0IGlzRnVuY3Rpb24gZnJvbSBcImxvZGFzaC9pc0Z1bmN0aW9uXCI7XG5pbXBvcnQgaXNVbmRlZmluZWQgZnJvbSBcImxvZGFzaC9pc1VuZGVmaW5lZFwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcblxuaW1wb3J0IHtcbiAgICBJUmVzaXplUHJvcGVydGllcyxcbiAgICBSZXNpemVEaXJlY3Rpb24sXG4gICAgcmVzaXplRGlyZWN0aW9uSGVscGVycyxcbiAgICBSZXNpemVVbml0LFxufSBmcm9tIFwiLi9wdWJsaWMtYXBpXCI7XG5pbXBvcnQgeyBDT01QTEVURV9SRVNJWkVfRVZFTlQgfSBmcm9tIFwiLi4vLi4vLi4vY29uc3RhbnRzL2V2ZW50LmNvbnN0YW50c1wiO1xuaW1wb3J0IHsgUkVTSVpFX0RFQk9VTkNFX1RJTUUgfSBmcm9tIFwiLi4vLi4vLi4vY29uc3RhbnRzL3Jlc2l6ZS5jb25zdGFudHNcIjtcbmltcG9ydCB7IEV2ZW50QnVzU2VydmljZSB9IGZyb20gXCIuLi8uLi8uLi9zZXJ2aWNlcy9ldmVudC1idXMuc2VydmljZVwiO1xuaW1wb3J0IHsgVXRpbFNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vLi4vc2VydmljZXMvdXRpbC5zZXJ2aWNlXCI7XG5cbi8qKiBAaWdub3JlICovXG5jb25zdCByZXNpemVDbGFzcyA9IFwibnVpLXJlc2l6ZS1ndXR0ZXJcIjtcblxuLyoqXG4gKiBAaWdub3JlXG4gKiA8ZXhhbXBsZS11cmw+Li8uLi9leGFtcGxlcy9pbmRleC5odG1sIy9yZXNpemVyPC9leGFtcGxlLXVybD5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6IFwiW251aVJlc2l6ZXJdXCIsXG59KVxuZXhwb3J0IGNsYXNzIFJlc2l6ZXJEaXJlY3RpdmUgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gICAgLyoqXG4gICAgICogRGlyZWN0aW9uIGluIHdoaWNoIGVsZW1lbnQgY2FuIGJlIHJlc2l6YWJsZS4gY2FuIGJlIFwidG9wXCIsIFwicmlnaHRcIiwgXCJsZWZ0XCIgYW5kIFwiYm90dG9tXCJcbiAgICAgKi9cbiAgICBwcml2YXRlIF9kaXJlY3Rpb246IFJlc2l6ZURpcmVjdGlvbjtcblxuICAgIEBJbnB1dCgpIHNldCByZXNpemVyRGlyZWN0aW9uKGRpcmVjdGlvbjogUmVzaXplRGlyZWN0aW9uKSB7XG4gICAgICAgIHRoaXMuX2RpcmVjdGlvbiA9IGRpcmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWZyZXNoU3R5bGUoKTtcbiAgICB9XG5cbiAgICBnZXQgcmVzaXplckRpcmVjdGlvbigpOiBSZXNpemVEaXJlY3Rpb24ge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGlyZWN0aW9uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgY3VzdG9tIHNpemUgb2YgcmVzaXphYmxlIGVsZW1lbnRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX3NpemU6IG51bWJlciA9IDE2O1xuXG4gICAgLyoqXG4gICAgICogRGlzYWJsZXMgZWxlbWVudCByZXNpemluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgX2Rpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBASW5wdXQoKSBzZXQgcmVzaXplckRpc2FibGVkKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICAgICAgICBpZiAodGhpcy5yZXNpemVHdXR0ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuc3dpdGNoRGlzYWJsZWRDbGFzc2VzKCk7XG4gICAgICAgICAgICBpZiAoIWlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZnJlc2hTdHlsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0IHJlc2l6ZXJEaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaG9vc2UgcmVzaXplIHZhbHVlIG9mIHlvdXIgZWxlbWVudChwaXhlbCwgcGVyY2VudCkuIEJ5IGRlZmF1bHQgcGl4ZWxzIGFyZSB1c2VkLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyByZXNpemVyVmFsdWU6IFJlc2l6ZVVuaXQgPSBSZXNpemVVbml0LnBpeGVsO1xuXG4gICAgLyoqXG4gICAgICogU3dpdGNoIHRvIG1vZGUgaW4gd2hpY2ggcmVzaXplciBjaGFuZ2UgcGFyZW50J3MgYW5kIHNpYmxpbmcncyBmbGV4LWJhc2lzIChsYXlvdXQtc3BlY2lmaWMpXG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIGlzTXVsdGlwbGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBuZXcgc2l6ZSBvZiBlbGVtZW50IG9uIHdoaWNoIGRpcmVjdGl2ZSB3YXMgYXBwbGllZFxuICAgICAqL1xuICAgIEBPdXRwdXQoKSBwdWJsaWMgcmVzaXplclNpemVDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgICBwcm90ZWN0ZWQgcmVzaXplUHJvcE9iajogSVJlc2l6ZVByb3BlcnRpZXM7XG4gICAgcHJvdGVjdGVkIHBhcmVudENvbnRhaW5lck5vZGU6IEhUTUxFbGVtZW50O1xuICAgIHByb3RlY3RlZCByZXNpemVyU3BsaXQ6IEhUTUxFbGVtZW50O1xuICAgIHByb3RlY3RlZCB0YXJnZXRFbGVtZW50OiBFbGVtZW50UmVmO1xuICAgIHByb3RlY3RlZCByZXNpemVDbGFzcyA9IHJlc2l6ZUNsYXNzO1xuICAgIHByb3RlY3RlZCByZXNpemVHdXR0ZXI6IEhUTUxFbGVtZW50O1xuICAgIHByb3RlY3RlZCBvZmZzZXRTaXplID0gdGhpcy5fc2l6ZSAvIDI7XG5cbiAgICBwcml2YXRlIF9yZXNpemVFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICBwcml2YXRlIF9vbGRTaXplOiBudW1iZXIgPSAwO1xuICAgIHByaXZhdGUgX2lzRHJhZ2dpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcml2YXRlIF9pc0ZpcnN0VGltZUludGVyYWN0aW5nOiBib29sZWFuID0gdHJ1ZTtcbiAgICBwcml2YXRlIF9pc0hvdmVyaW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSByZXNpemVPYnNlcnZlcj86IFJlc2l6ZU9ic2VydmVyO1xuICAgIHByaXZhdGUgcmVzaXplU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gICAgcHJpdmF0ZSBldmVudFN1YnNjcmlwdGlvbnM6ICgoKSA9PiB2b2lkKVtdID0gW107XG4gICAgcHJpdmF0ZSBtb3VzZVVwVW5saXN0ZW46ICgpID0+IHZvaWQ7XG4gICAgcHJpdmF0ZSBtb3VzZU1vdmVVbmxpc3RlbjogKCkgPT4gdm9pZDtcbiAgICBwcml2YXRlIHNpYmxpbmc6IGFueTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBlbFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgICAgICBwcml2YXRlIHV0aWxTZXJ2aWNlOiBVdGlsU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZixcbiAgICAgICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICAgICAgcHJpdmF0ZSBldmVudEJ1c1NlcnZpY2U6IEV2ZW50QnVzU2VydmljZVxuICAgICkge31cblxuICAgIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGlmIChjaGFuZ2VzW1wicmVzaXplckRpcmVjdGlvblwiXSAmJiB0aGlzLnJlc2l6ZUd1dHRlcikge1xuICAgICAgICAgICAgdGhpcy5hcHBlbmRSZXNpemVFbGVtZW50KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICAvLyBhcyBkZXJpdmVkIGNsYXNzIGRvZXNuJ3QgaW5oZXJpdHMgbGlmZWN5Y2xlIGhvb2tzLFxuICAgICAgICAvLyB3ZSBjYW4gcmVhc3NpZ24gdGFyZ2V0RWxlbWVudCB0aGVyZSwgaW4gdGhpcyBjYXNlIHdlIGp1c3QgdXNlIGRpcmVjdGl2ZSdzIG5hdGl2ZUVsZW1lbnRcbiAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGhpcy5lbFJlZjtcbiAgICAgICAgdGhpcy5hZGRTdWJzY3JpcHRpb24oKTtcblxuICAgICAgICBpZiAoIXRoaXMuaXNBdFRoZUJlZ2lubmluZygpKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKFxuICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0RWxlbWVudC5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZUVsZW1lbnRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZUd1dHRlciA9XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQubGFzdEVsZW1lbnRDaGlsZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuaW5zZXJ0QmVmb3JlKFxuICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0RWxlbWVudC5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZUVsZW1lbnQsXG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZmlyc3RFbGVtZW50Q2hpbGRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZUd1dHRlciA9XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZmlyc3RFbGVtZW50Q2hpbGQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hcHBlbmRSZXNpemVFbGVtZW50KCk7XG4gICAgICAgIHRoaXMucmVzaXplR3V0dGVyLmNsYXNzTmFtZSA9IHRoaXMucmVzaXplQ2xhc3M7XG4gICAgICAgIHRoaXMucGFyZW50Q29udGFpbmVyTm9kZSA9XG4gICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQubmF0aXZlRWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgICAgICB0aGlzLmFkZFJlc2l6ZU9ic2VydmVyKCk7XG4gICAgICAgIHRoaXMuYXBwZW5kRXZlbnRzKCk7XG4gICAgICAgIHRoaXMucmVmcmVzaFN0eWxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5yZXNpemVPYnNlcnZlcikge1xuICAgICAgICAgICAgdGhpcy5yZXNpemVPYnNlcnZlci51bm9ic2VydmUoXG4gICAgICAgICAgICAgICAgPEVsZW1lbnQ+dGhpcy50YXJnZXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQucGFyZW50RWxlbWVudFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXNpemVTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMucmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51bmxpc3RlbkV2ZW50cygpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhZGRSZXNpemVPYnNlcnZlcigpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcmVzaXplSGFuZGxlciA9IGRlYm91bmNlKFxuICAgICAgICAgICAgKGVudHJ5KSA9PiB0aGlzLnJlZnJlc2hTdHlsZSgpLFxuICAgICAgICAgICAgUkVTSVpFX0RFQk9VTkNFX1RJTUVcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoZW50cmllcykgPT4ge1xuICAgICAgICAgICAgZW50cmllcy5mb3JFYWNoKChlbnRyeTogUmVzaXplT2JzZXJ2ZXJFbnRyeSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5yZXNpemVyRGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZUhhbmRsZXIoZW50cnkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXI/Lm9ic2VydmUoXG4gICAgICAgICAgICAgICAgPEVsZW1lbnQ+dGhpcy50YXJnZXRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQucGFyZW50RWxlbWVudFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFkZFN1YnNjcmlwdGlvbigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZXNpemVTdWJzY3JpcHRpb24gPSB0aGlzLmV2ZW50QnVzU2VydmljZVxuICAgICAgICAgICAgLmdldFN0cmVhbShDT01QTEVURV9SRVNJWkVfRVZFTlQpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChyZXNpemUpID0+IHRoaXMucmVmcmVzaFN0eWxlKCkpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBvblNpemVDaGFuZ2VkKG5ld1NpemU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlc2l6ZXJTaXplQ2hhbmdlZC5lbWl0KG5ld1NpemUpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCByZWZyZXNoU3R5bGUoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnJlc2l6ZUd1dHRlciAmJiAhdGhpcy5yZXNpemVyRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIC8vIGZpeCBzYWZhcmkgYnVnIGFib3V0IGd1dHRlciBoZWlnaHQgd2hlbiBkaXJlY3Rpb24gaXMgaG9yaXpvbnRhbFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZUd1dHRlcixcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZVByb3BPYmouc2l6ZVRvU2V0LFxuICAgICAgICAgICAgICAgIGAke3RoaXMuX3NpemV9cHhgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZUd1dHRlcixcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZVByb3BPYmoub3RoZXJTaXplUHJvcGVydHksXG4gICAgICAgICAgICAgICAgXCIxMDAlXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZVBvc2l0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgICAgIFwiY3Vyc29yXCIsXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVQcm9wT2JqLmN1cnNvclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuc3dpdGNoRGlzYWJsZWRDbGFzc2VzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgdW5saXN0ZW5FdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZXZlbnRTdWJzY3JpcHRpb25zLmZvckVhY2goKHVubGlzdGVuRm4pID0+IHtcbiAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKHVubGlzdGVuRm4pKSB7XG4gICAgICAgICAgICAgICAgdW5saXN0ZW5GbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXBwZW5kRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmV2ZW50U3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5saXN0ZW4oXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVHdXR0ZXIsXG4gICAgICAgICAgICAgICAgXCJtb3VzZWVudGVyXCIsXG4gICAgICAgICAgICAgICAgKCRldmVudDogTW91c2VFdmVudCkgPT4gdGhpcy5vbk1vdXNlRW50ZXIoJGV2ZW50KVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLmV2ZW50U3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5saXN0ZW4odGhpcy5yZXNpemVHdXR0ZXIsIFwibW91c2VsZWF2ZVwiLCAoKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMub25Nb3VzZUxlYXZlKClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5ldmVudFN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgICAgIFwibW91c2Vkb3duXCIsXG4gICAgICAgICAgICAgICAgKCRldmVudDogTW91c2VFdmVudCkgPT4gdGhpcy5vbk1vdXNlRG93bigkZXZlbnQpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzUmVzaXplSG9yaXpvbnRhbCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHRoaXMucmVzaXplckRpcmVjdGlvbiA9PT0gUmVzaXplRGlyZWN0aW9uLmxlZnQgfHxcbiAgICAgICAgICAgIHRoaXMucmVzaXplckRpcmVjdGlvbiA9PT0gUmVzaXplRGlyZWN0aW9uLnJpZ2h0XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzQXRUaGVCZWdpbm5pbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZXJEaXJlY3Rpb24gPT09IFJlc2l6ZURpcmVjdGlvbi5sZWZ0IHx8XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZXJEaXJlY3Rpb24gPT09IFJlc2l6ZURpcmVjdGlvbi50b3BcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN3aXRjaERpc2FibGVkQ2xhc3NlcygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZXNpemVyRGlzYWJsZWRcbiAgICAgICAgICAgID8gdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhcbiAgICAgICAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgICAgICAgYCR7dGhpcy5yZXNpemVDbGFzc30tZGlzYWJsZWRgXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIDogdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhcbiAgICAgICAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgICAgICAgYCR7dGhpcy5yZXNpemVDbGFzc30tZGlzYWJsZWRgXG4gICAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBlbmRSZXNpemVFbGVtZW50KCkge1xuICAgICAgICBpZiAodGhpcy5yZXNpemVyU3BsaXQpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2hpbGQodGhpcy5yZXNpemVHdXR0ZXIsIHRoaXMucmVzaXplclNwbGl0KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc2l6ZXJTcGxpdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5yZXNpemVyU3BsaXQsIGAke3RoaXMucmVzaXplQ2xhc3N9X19zcGxpdGApO1xuICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKFxuICAgICAgICAgICAgdGhpcy5yZXNpemVyU3BsaXQsXG4gICAgICAgICAgICBgJHt0aGlzLnJlc2l6ZUNsYXNzfV9fc3BsaXQtJHtcbiAgICAgICAgICAgICAgICB0aGlzLmlzUmVzaXplSG9yaXpvbnRhbCgpID8gXCJob3Jpem9udGFsXCIgOiBcInZlcnRpY2FsXCJcbiAgICAgICAgICAgIH1gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kQ2hpbGQodGhpcy5yZXNpemVHdXR0ZXIsIHRoaXMucmVzaXplclNwbGl0KTtcbiAgICAgICAgdGhpcy5yZXNpemVQcm9wT2JqID0gcmVzaXplRGlyZWN0aW9uSGVscGVyc1t0aGlzLnJlc2l6ZXJEaXJlY3Rpb25dO1xuICAgIH1cblxuICAgIHByaXZhdGUgdW5saXN0ZW5SZXNpemVFdmVudHMoKSB7XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKHRoaXMubW91c2VNb3ZlVW5saXN0ZW4pICYmICF0aGlzLl9pc0hvdmVyaW5nKSB7XG4gICAgICAgICAgICB0aGlzLm1vdXNlTW92ZVVubGlzdGVuKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzRnVuY3Rpb24odGhpcy5tb3VzZVVwVW5saXN0ZW4pKSB7XG4gICAgICAgICAgICB0aGlzLm1vdXNlVXBVbmxpc3RlbigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmVnaXN0ZXJzIG1vdXNlbW92ZVxuICAgIHByaXZhdGUgb25Nb3VzZUVudGVyKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIHRoaXMuX2lzSG92ZXJpbmcgPSB0cnVlO1xuICAgICAgICAvLyBBZGQgaG92ZXJpbmcgY2xhc3Mgb25seSB3aGlsZSBtb3VzZSBpcyBub3QgY2xpY2tlZFxuICAgICAgICAvLyBcIndoaWNoXCIgaXMgc3VwcG9ydGVkIGJ5IFNhZmFyaVxuICAgICAgICBpZiAoXG4gICAgICAgICAgICAoIWlzVW5kZWZpbmVkKGV2ZW50LmJ1dHRvbnMpICYmIGV2ZW50LmJ1dHRvbnMgPT09IDApIHx8XG4gICAgICAgICAgICAoIWlzVW5kZWZpbmVkKGV2ZW50LndoaWNoKSAmJiBldmVudC53aGljaCA9PT0gMClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKFxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgICAgIGAke3RoaXMucmVzaXplQ2xhc3N9LS1ob3ZlcmluZ2BcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLm1vdXNlTW92ZVVubGlzdGVuID0gdGhpcy5yZW5kZXJlci5saXN0ZW4oXG4gICAgICAgICAgICAgICAgZG9jdW1lbnQsXG4gICAgICAgICAgICAgICAgXCJtb3VzZW1vdmVcIixcbiAgICAgICAgICAgICAgICAoJGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB0aGlzLm9uTW91c2VNb3ZlKCRldmVudClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG9uTW91c2VMZWF2ZSgpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhcbiAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgYCR7dGhpcy5yZXNpemVDbGFzc30tLWhvdmVyaW5nYFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXRoaXMuX2lzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuX2lzSG92ZXJpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudW5saXN0ZW5SZXNpemVFdmVudHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25Nb3VzZU1vdmUoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgLy8gTm8gbmVlZCB0byB1cGRhdGUgc3R5bGVzIGZvciByZXNpemVyIHRoYXQgd2UncmUgbm90IGRyYWdnaW5nXG4gICAgICAgIGlmICh0aGlzLl9pc0ZpcnN0VGltZUludGVyYWN0aW5nICYmIHRoaXMuX2lzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaFN0eWxlKCk7XG4gICAgICAgICAgICB0aGlzLl9pc0ZpcnN0VGltZUludGVyYWN0aW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2lzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuYXBwbHlOZXdTaXplKGV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlUG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlZ2lzdGVycyBtb3VzZXVwXG4gICAgcHJpdmF0ZSBvbk1vdXNlRG93bihldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKFxuICAgICAgICAgICAgdGhpcy5yZXNpemVHdXR0ZXIsXG4gICAgICAgICAgICBgJHt0aGlzLnJlc2l6ZUNsYXNzfS0tYWN0aXZlYFxuICAgICAgICApO1xuICAgICAgICAvLyBDdXJzb3Igc2hvdWxkIGJlIHRoZXJlIHVudGlsIG1vdXNlVXAuXG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsXG4gICAgICAgICAgICBcImN1cnNvclwiLFxuICAgICAgICAgICAgdGhpcy5yZXNpemVQcm9wT2JqLmN1cnNvclxuICAgICAgICApO1xuICAgICAgICB0aGlzLl9pc0RyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fb2xkU2l6ZSA9IHRoaXMuaXNSZXNpemVIb3Jpem9udGFsKClcbiAgICAgICAgICAgID8gZXZlbnQuY2xpZW50WFxuICAgICAgICAgICAgOiBldmVudC5jbGllbnRZO1xuICAgICAgICB0aGlzLm1vdXNlVXBVbmxpc3RlbiA9IHRoaXMucmVuZGVyZXIubGlzdGVuKFxuICAgICAgICAgICAgZG9jdW1lbnQsXG4gICAgICAgICAgICBcIm1vdXNldXBcIixcbiAgICAgICAgICAgICgkZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHRoaXMub25Nb3VzZVVwKCRldmVudClcbiAgICAgICAgKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gVGhpcyBkaXNhYmxlcyBhY2NpZGVudGFsIHRleHQgc2VsZWN0aW9uIHdoaWxlIHJlc2l6aW5nd1xuICAgIH1cblxuICAgIHByaXZhdGUgb25Nb3VzZVVwKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlU3R5bGUoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCBcImN1cnNvclwiKTtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhcbiAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgYCR7dGhpcy5yZXNpemVDbGFzc30tLWFjdGl2ZWBcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5faXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmV2ZW50QnVzU2VydmljZS5nZXRTdHJlYW0oQ09NUExFVEVfUkVTSVpFX0VWRU5UKS5uZXh0KGV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNhbGN1bGF0ZVBvc2l0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5yZXNpemVyRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJlbnRDb29yZCA9XG4gICAgICAgICAgICB0aGlzLnBhcmVudENvbnRhaW5lck5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClbXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVQcm9wT2JqLmFwcGVuZERpcmVjdGlvblxuICAgICAgICAgICAgXTtcbiAgICAgICAgY29uc3QgZWxlbWVudENvb3JkID1cbiAgICAgICAgICAgIHRoaXMudGFyZ2V0RWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpW1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplUHJvcE9iai5ib3JkZXJUb0NhbGN1bGF0ZVxuICAgICAgICAgICAgXTtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZShcbiAgICAgICAgICAgIHRoaXMucmVzaXplR3V0dGVyLFxuICAgICAgICAgICAgdGhpcy5yZXNpemVQcm9wT2JqLmFwcGVuZERpcmVjdGlvbixcbiAgICAgICAgICAgIGAke01hdGguYWJzKHBhcmVudENvb3JkIC0gZWxlbWVudENvb3JkKSAtIHRoaXMub2Zmc2V0U2l6ZX1weGBcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGx5TmV3U2l6ZShldmVudDogTW91c2VFdmVudCkge1xuICAgICAgICB0aGlzLnNpYmxpbmcgPSB0aGlzLnRhcmdldEVsZW1lbnQubmF0aXZlRWxlbWVudC5uZXh0U2libGluZztcbiAgICAgICAgaWYgKCF0aGlzLl9pc0RyYWdnaW5nIHx8IHRoaXMucmVzaXplckRpc2FibGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbmV3U2l6ZSA9IHRoaXMuaXNSZXNpemVIb3Jpem9udGFsKClcbiAgICAgICAgICAgID8gZXZlbnQuY2xpZW50WFxuICAgICAgICAgICAgOiBldmVudC5jbGllbnRZO1xuICAgICAgICB0aGlzLnVwZGF0ZVNpemUobmV3U2l6ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVTaXplKG5ld1NpemU6IG51bWJlcikge1xuICAgICAgICBjb25zdCB1cGRhdGVkUHJvcCA9IHRoaXMuaXNNdWx0aXBsZVxuICAgICAgICAgICAgPyBcImZsZXgtYmFzaXNcIlxuICAgICAgICAgICAgOiB0aGlzLnJlc2l6ZVByb3BPYmouc2l6ZVRvU2V0O1xuICAgICAgICBjb25zdCBwYXJlbnRTaXplID1cbiAgICAgICAgICAgIHRoaXMucGFyZW50Q29udGFpbmVyTm9kZVtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZVByb3BPYmoubmF0aXZlRWxlbWVudFNpemVQcm9wZXJ0eVxuICAgICAgICAgICAgXTtcbiAgICAgICAgY29uc3QgdmFsdWVDb2VmZ