UNPKG

@catull/igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

591 lines 57.3 kB
import { __decorate, __metadata, __param } from "tslib"; import { useAnimation } from '@angular/animations'; import { CommonModule } from '@angular/common'; import { Component, ElementRef, EventEmitter, HostBinding, Input, NgModule, OnDestroy, OnInit, Optional, Output, ViewChild, AfterContentInit } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { IgxNavigationService, IToggleView } from '../core/navigation'; import { IgxButtonModule } from '../directives/button/button.directive'; import { IgxRippleModule } from '../directives/ripple/ripple.directive'; import { IgxDialogActionsDirective, IgxDialogTitleDirective } from './dialog.directives'; import { IgxToggleModule, IgxToggleDirective } from '../directives/toggle/toggle.directive'; import { GlobalPositionStrategy, NoOpScrollStrategy } from '../services'; import { slideInBottom, slideOutTop } from '../animations/slide/index'; import { IgxFocusModule } from '../directives/focus/focus.directive'; var DIALOG_ID = 0; /** * **Ignite UI for Angular Dialog Window** - * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/dialog.html) * * The Ignite UI Dialog Window presents a dialog window to the user which can simply display messages or display * more complicated visuals such as a user sign-in form. It also provides a right and left button * which can be used for custom actions. * * Example: * ```html * <button (click)="form.open()">Show Dialog</button> * <igx-dialog #form title="Sign In" rightButtonLabel="OK"> * <div> * <input type="text" igxInput/> * <label igxLabel>Username</label> * </div> * <div> * <input type="password" igxInput/> * <label igxLabel>Password</label> * </div> * </igx-dialog> * ``` */ var IgxDialogComponent = /** @class */ (function () { function IgxDialogComponent(elementRef, navService) { this.elementRef = elementRef; this.navService = navService; /** * An @Input property that sets the value of the `id` attribute. If not provided it will be automatically generated. *```html *<igx-dialog [id]="'igx-dialog-56'" #alert title="Notification" leftButtonLabel="OK" (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.id = "igx-dialog-" + DIALOG_ID++; /** * An @Input property controlling the `title` of the dialog. *```html *<igx-dialog title="Notification" #alert leftButtonLabel="OK" (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.title = ''; /** * An @Input property controlling the `message` of the dialog. *```html *<igx-dialog message="Your email was sent!" #alert leftButtonLabel="OK" (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.message = ''; /** * An @Input property to set the `label` of the left button of the dialog. *```html *<igx-dialog leftButtonLabel="OKAY" #alert title="Notification" (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.leftButtonLabel = ''; /** * An @Input property to set the left button `type`. The types are `flat`, `raised` and `fab`. * The `flat` type button is a rectangle and doesn't have a shadow. <br> * The `raised` type button is also a rectangle but has a shadow. <br> * The `fab` type button is a circle with a shadow. <br> * The default value is `flat`. *```html *<igx-dialog leftButtonType="raised" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.leftButtonType = 'flat'; /** * An @Input property to set the left button color. The property accepts all valid CSS color property values. *```html *<igx-dialog leftButtonColor="yellow" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.leftButtonColor = ''; /** * An @Input property to set the left button `background-color`. The property accepts all valid CSS color property values. *```html *<igx-dialog leftButtonBackgroundColor="black" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.leftButtonBackgroundColor = ''; /** * An @Input property to set the left button `ripple`. The `ripple` animates a click/tap to a component as a series of fading waves. * The property accepts all valid CSS color property values. *```html *<igx-dialog leftButtonRipple="green" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.leftButtonRipple = ''; /** * An @Input property to set the `label` of the right button of the dialog. *```html *<igx-dialog rightButtonLabel="OKAY" #alert title="Notification" (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.rightButtonLabel = ''; /** * An @Input property to set the right button `type`. The types are `flat`, `raised` and `fab`. * The `flat` type button is a rectangle and doesn't have a shadow. <br> * The `raised` type button is also a rectangle but has a shadow. <br> * The `fab` type button is a circle with a shadow. <br> * The default value is `flat`. *```html *<igx-dialog rightButtonType="fab" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.rightButtonType = 'flat'; /** * An @Input property to set the right button `color`. The property accepts all valid CSS color property values. *```html *<igx-dialog rightButtonColor="yellow" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.rightButtonColor = ''; /** * An @Input property to set the right button `background-color`. The property accepts all valid CSS color property values. *```html *<igx-dialog rightButtonBackgroundColor="black" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.rightButtonBackgroundColor = ''; /** * An @Input property to set the right button `ripple`. *```html *<igx-dialog rightButtonRipple="green" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog> *``` */ this.rightButtonRipple = ''; /** * An event that is emitted when the dialog is opened. *```html *<igx-dialog (onOpen)="onDialogOpenHandler($event)" (onLeftButtonSelect)="dialog.close()" rightButtonLabel="OK"> *</igx-dialog> *``` */ this.onOpen = new EventEmitter(); /** * An event that is emitted when the dialog is closed. *```html *<igx-dialog (onClose)="onDialogCloseHandler($event)" title="Confirmation" leftButtonLabel="Cancel" rightButtonLabel="OK"> *</igx-dialog> *``` */ this.onClose = new EventEmitter(); /** * An event that is emitted when the left button is clicked. *```html *<igx-dialog (onLeftButtonSelect)="onDialogOKSelected($event)" #dialog leftButtonLabel="OK" rightButtonLabel="Cancel"> *</igx-dialog> *``` */ this.onLeftButtonSelect = new EventEmitter(); /** * An event that is emitted when the right button is clicked. * ```html *<igx-dialog (onRightButtonSelect)="onDialogOKSelected($event)" *#dialog title="Confirmation" (onLeftButtonSelect)="dialog.close()" rightButtonLabel="OK" *rightButtonRipple="#4CAF50" closeOnOutsideSelect="true"> *</igx-dialog> *``` */ this.onRightButtonSelect = new EventEmitter(); this._positionSettings = { openAnimation: useAnimation(slideInBottom, { params: { fromPosition: 'translateY(100%)' } }), closeAnimation: useAnimation(slideOutTop, { params: { toPosition: 'translateY(-100%)' } }) }; this._closeOnOutsideSelect = false; this._isModal = true; this.destroy$ = new Subject(); /** * The default `tabindex` attribute for the component * * @hidden */ this.tabindex = -1; this._titleId = IgxDialogComponent_1.NEXT_ID++ + '_title'; this._overlayDefaultSettings = { positionStrategy: new GlobalPositionStrategy(this._positionSettings), scrollStrategy: new NoOpScrollStrategy(), modal: this.isModal, closeOnOutsideClick: this.closeOnOutsideSelect }; } IgxDialogComponent_1 = IgxDialogComponent; Object.defineProperty(IgxDialogComponent.prototype, "isModal", { get: function () { return this._isModal; }, set: function (val) { this._overlayDefaultSettings.modal = val; this._isModal = val; }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "closeOnOutsideSelect", { /** * An @Input property that allows you to enable the "close on click outside the dialog". By default it's disabled. *```html *<igx-dialog closeOnOutsideSelect="true" leftButtonLabel="Cancel" (onLeftButtonSelect)="dialog.close()" *rightButtonLabel="OK" rightButtonRipple="#4CAF50" (onRightButtonSelect)="onDialogOKSelected($event)"> *</igx-dialog> *``` */ get: function () { return this._closeOnOutsideSelect; }, set: function (val) { this._overlayDefaultSettings.closeOnOutsideClick = val; this._closeOnOutsideSelect = val; }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "positionSettings", { /** * Get the position and animation settings used by the dialog. * ```typescript * @ViewChild('alert', { static: true }) public alert: IgxDialogComponent; * let currentPosition: PositionSettings = this.alert.positionSettings * ``` */ get: function () { return this._positionSettings; }, /** * Set the position and animation settings used by the dialog. * ```typescript * import { slideInLeft, slideOutRight } from 'igniteui-angular'; * ... * @ViewChild('alert', { static: true }) public alert: IgxDialogComponent; * public newPositionSettings: PositionSettings = { * openAnimation: useAnimation(slideInTop, { params: { duration: '2000ms' } }), * closeAnimation: useAnimation(slideOutBottom, { params: { duration: '2000ms'} }), * horizontalDirection: HorizontalAlignment.Left, * verticalDirection: VerticalAlignment.Middle, * horizontalStartPoint: HorizontalAlignment.Left, * verticalStartPoint: VerticalAlignment.Middle, * minSize: { height: 100, width: 100 } * }; * this.alert.positionSettings = this.newPositionSettings; * ``` */ set: function (settings) { this._positionSettings = settings; this._overlayDefaultSettings.positionStrategy = new GlobalPositionStrategy(this._positionSettings); }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "element", { /** * @hidden */ get: function () { return this.elementRef.nativeElement; }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "state", { /** * Returns the value of state. Possible state values are "open" or "close". *```typescript *@ViewChild("MyDialog") *public dialog: IgxDialogComponent; *ngAfterViewInit() { * let dialogState = this.dialog.state; *} *``` */ get: function () { return this.isOpen ? 'open' : 'close'; }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "isOpen", { /** * Returns whether the dialog is visible to the end user. *```typescript *@ViewChild("MyDialog") *public dialog: IgxDialogComponent; *ngAfterViewInit() { * let dialogOpen = this.dialog.isOpen; *} * ``` */ get: function () { return !this.toggleRef.collapsed; }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "isCollapsed", { get: function () { return this.toggleRef.collapsed; }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "role", { /** *Returns the value of the role of the dialog. The valid values are `dialog`, `alertdialog`, `alert`. *```typescript *@ViewChild("MyDialog") *public dialog: IgxDialogComponent; *ngAfterViewInit() { * let dialogRole = this.dialog.role; *} * ``` */ get: function () { if (this.leftButtonLabel !== '' && this.rightButtonLabel !== '') { return 'dialog'; } else if (this.leftButtonLabel !== '' || this.rightButtonLabel !== '') { return 'alertdialog'; } else { return 'alert'; } }, enumerable: true, configurable: true }); Object.defineProperty(IgxDialogComponent.prototype, "titleId", { /** *Returns the value of the title id. *```typescript *@ViewChild("MyDialog") *public dialog: IgxDialogComponent; *ngAfterViewInit() { * let dialogTitle = this.dialog.titleId; *} * ``` */ get: function () { return this._titleId; }, enumerable: true, configurable: true }); IgxDialogComponent.prototype.ngAfterContentInit = function () { var _this = this; this.toggleRef.onClosing.pipe(takeUntil(this.destroy$)).subscribe(function () { return _this.emitCloseFromDialog(); }); }; IgxDialogComponent.prototype.emitCloseFromDialog = function () { this.onClose.emit({ dialog: this, event: null }); }; /** * A method that opens the dialog. * @memberOf {@link IgxDialogComponent} *```html *<button (click)="dialog.open() igxButton="raised" igxButtonColor="white" igxRipple="white">Trigger Dialog</button> *<igx-dialog #dialog></igx-dialog> *``` */ IgxDialogComponent.prototype.open = function (overlaySettings) { if (overlaySettings === void 0) { overlaySettings = this._overlayDefaultSettings; } this.toggleRef.open(overlaySettings); this.onOpen.emit({ dialog: this, event: null }); if (!this.leftButtonLabel && !this.rightButtonLabel) { this.toggleRef.element.focus(); } }; /** *A method that that closes the dialog. *@memberOf {@link IgxDialogComponent} *```html *<button (click)="dialog.close() igxButton="raised" igxButtonColor="white" igxRipple="white">Trigger Dialog</button> *<igx-dialog #dialog></igx-dialog> *``` */ IgxDialogComponent.prototype.close = function () { // `onClose` will emit from `toggleRef.onClosing` subscription this.toggleRef.close(); }; /** * A method that opens/closes the dialog. *@memberOf {@link IgxDialogComponent} *```html *<button (click)="dialog.toggle() igxButton="raised" igxButtonColor="white" igxRipple="white">Trigger Dialog</button> *<igx-dialog #dialog></igx-dialog> *``` */ IgxDialogComponent.prototype.toggle = function () { this.isOpen ? this.close() : this.open(); }; /** * @hidden */ IgxDialogComponent.prototype.onDialogSelected = function (event) { event.stopPropagation(); if (this.isOpen && this.closeOnOutsideSelect && event.target.classList.contains(IgxDialogComponent_1.DIALOG_CLASS)) { this.close(); } }; /** * @hidden */ IgxDialogComponent.prototype.onInternalLeftButtonSelect = function (event) { this.onLeftButtonSelect.emit({ dialog: this, event: event }); }; /** * @hidden */ IgxDialogComponent.prototype.onInternalRightButtonSelect = function (event) { this.onRightButtonSelect.emit({ dialog: this, event: event }); }; /** * @hidden */ IgxDialogComponent.prototype.ngOnInit = function () { if (this.navService && this.id) { this.navService.add(this.id, this); } }; /** * @hidden */ IgxDialogComponent.prototype.ngOnDestroy = function () { if (this.navService && this.id) { this.navService.remove(this.id); } }; var IgxDialogComponent_1; IgxDialogComponent.NEXT_ID = 1; IgxDialogComponent.DIALOG_CLASS = 'igx-dialog'; IgxDialogComponent.ctorParameters = function () { return [ { type: ElementRef }, { type: IgxNavigationService, decorators: [{ type: Optional }] } ]; }; __decorate([ ViewChild(IgxToggleDirective, { static: true }), __metadata("design:type", IgxToggleDirective) ], IgxDialogComponent.prototype, "toggleRef", void 0); __decorate([ HostBinding('attr.id'), Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "id", void 0); __decorate([ Input(), __metadata("design:type", Boolean), __metadata("design:paramtypes", [Boolean]) ], IgxDialogComponent.prototype, "isModal", null); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "title", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "message", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "leftButtonLabel", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "leftButtonType", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "leftButtonColor", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "leftButtonBackgroundColor", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "leftButtonRipple", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "rightButtonLabel", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "rightButtonType", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "rightButtonColor", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "rightButtonBackgroundColor", void 0); __decorate([ Input(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "rightButtonRipple", void 0); __decorate([ Input(), __metadata("design:type", Boolean), __metadata("design:paramtypes", [Boolean]) ], IgxDialogComponent.prototype, "closeOnOutsideSelect", null); __decorate([ Input(), __metadata("design:type", Object), __metadata("design:paramtypes", [Object]) ], IgxDialogComponent.prototype, "positionSettings", null); __decorate([ Output(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "onOpen", void 0); __decorate([ Output(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "onClose", void 0); __decorate([ Output(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "onLeftButtonSelect", void 0); __decorate([ Output(), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "onRightButtonSelect", void 0); __decorate([ HostBinding('attr.tabindex'), __metadata("design:type", Object) ], IgxDialogComponent.prototype, "tabindex", void 0); __decorate([ Input(), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxDialogComponent.prototype, "isOpen", null); __decorate([ HostBinding('class.igx-dialog--hidden'), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxDialogComponent.prototype, "isCollapsed", null); __decorate([ Input(), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxDialogComponent.prototype, "role", null); __decorate([ Input(), __metadata("design:type", Object), __metadata("design:paramtypes", []) ], IgxDialogComponent.prototype, "titleId", null); IgxDialogComponent = IgxDialogComponent_1 = __decorate([ Component({ selector: 'igx-dialog', template: "<div tabindex=\"0\" #dialog class=\"igx-dialog\" igxToggle (click)=\"onDialogSelected($event)\">\n <div #dialogWindow class=\"igx-dialog__window\" [attr.role]=\"role\" [attr.aria-labelledby]=\"titleId\">\n\n <div *ngIf=\"title\" [attr.id]=\"titleId\" class=\"igx-dialog__window-title\">\n {{ title }}\n </div>\n <ng-content *ngIf=\"!title\" select=\"igx-dialog-title,[igxDialogTitle]\"></ng-content>\n\n <div class=\"igx-dialog__window-content\" *ngIf=\"message\">{{ message }}</div>\n <ng-content *ngIf=\"!message\"></ng-content>\n\n <div *ngIf=\"leftButtonLabel || rightButtonLabel\" class=\"igx-dialog__window-actions\">\n <button *ngIf=\"leftButtonLabel\" type=\"button\" [igxFocus]=\"isOpen\" igxButton=\"{{ leftButtonType }}\" igxButtonColor=\"{{ leftButtonColor }}\" igxButtonBackground=\"{{ leftButtonBackgroundColor }}\"\n igxRipple=\"{{ leftButtonRipple }}\" (click)=\"onInternalLeftButtonSelect($event)\">\n {{ leftButtonLabel }}\n </button>\n <button *ngIf=\"rightButtonLabel\" type=\"button\" [igxFocus]=\"isOpen\" igxButton=\"{{ rightButtonType }}\" igxButtonColor=\"{{ rightButtonColor }}\" igxButtonBackground=\"{{ rightButtonBackgroundColor }}\"\n igxRipple=\"{{ rightButtonRipple }}\" (click)=\"onInternalRightButtonSelect($event)\">\n {{ rightButtonLabel }}\n </button>\n </div>\n <ng-content *ngIf=\"!leftButtonLabel && !rightButtonLabel\" select=\"igx-dialog-actions,[igxDialogActions]\"></ng-content>\n\n </div>\n</div>\n" }), __param(1, Optional()), __metadata("design:paramtypes", [ElementRef, IgxNavigationService]) ], IgxDialogComponent); return IgxDialogComponent; }()); export { IgxDialogComponent }; /** * @hidden */ var IgxDialogModule = /** @class */ (function () { function IgxDialogModule() { } IgxDialogModule = __decorate([ NgModule({ declarations: [IgxDialogComponent, IgxDialogTitleDirective, IgxDialogActionsDirective], exports: [IgxDialogComponent, IgxDialogTitleDirective, IgxDialogActionsDirective], imports: [CommonModule, IgxToggleModule, IgxButtonModule, IgxRippleModule, IgxFocusModule] }) ], IgxDialogModule); return IgxDialogModule; }()); export { IgxDialogModule }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhbG9nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGlhbG9nL2RpYWxvZy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFdBQVcsRUFDWCxLQUFLLEVBQ0wsUUFBUSxFQUNSLFNBQVMsRUFDVCxNQUFNLEVBQ04sUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ25CLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDeEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pGLE9BQU8sRUFBRSxlQUFlLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUM1RixPQUFPLEVBQW1CLHNCQUFzQixFQUFFLGtCQUFrQixFQUFvQixNQUFNLGFBQWEsQ0FBQztBQUM1RyxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUdyRSxJQUFJLFNBQVMsR0FBRyxD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TUFBTSxFQUFFOzt1REFDNkM7SUFVdEQ7UUFEQyxNQUFNLEVBQUU7O2tFQUN3RDtJQVlqRTtRQURDLE1BQU0sRUFBRTs7bUVBQ3lEO0lBeUJsRTtRQURDLFdBQVcsQ0FBQyxlQUFlLENBQUM7O3dEQUNSO0lBNkJyQjtRQURDLEtBQUssRUFBRTs7O29EQUdQO0lBR0Q7UUFEQyxXQUFXLENBQUMsMEJBQTBCLENBQUM7Ozt5REFHdkM7SUFhRDtRQURDLEtBQUssRUFBRTs7O2tEQVlQO0lBYUQ7UUFEQyxLQUFLLEVBQUU7OztxREFHUDtJQWhWUSxrQkFBa0I7UUFKOUIsU0FBUyxDQUFDO1lBQ1AsUUFBUSxFQUFFLFlBQVk7WUFDdEIsaW1EQUE0QztTQUMvQyxDQUFDO1FBcVZPLFdBQUEsUUFBUSxFQUFFLENBQUE7eUNBRFMsVUFBVTtZQUNFLG9CQUFvQjtPQXBWL0Msa0JBQWtCLENBZ2M5QjtJQUFELHlCQUFDO0NBQUEsQUFoY0QsSUFnY0M7U0FoY1ksa0JBQWtCO0FBdWMvQjs7R0FFRztBQU1IO0lBQUE7SUFBK0IsQ0FBQztJQUFuQixlQUFlO1FBTDNCLFFBQVEsQ0FBQztZQUNOLFlBQVksRUFBRSxDQUFDLGtCQUFrQixFQUFFLHVCQUF1QixFQUFFLHlCQUF5QixDQUFDO1lBQ3RGLE9BQU8sRUFBRSxDQUFDLGtCQUFrQixFQUFFLHVCQUF1QixFQUFFLHlCQUF5QixDQUFDO1lBQ2pGLE9BQU8sRUFBRSxDQUFDLFlBQVksRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxjQUFjLENBQUM7U0FDN0YsQ0FBQztPQUNXLGVBQWUsQ0FBSTtJQUFELHNCQUFDO0NBQUEsQUFBaEMsSUFBZ0M7U0FBbkIsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZUFuaW1hdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE5nTW9kdWxlLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3B0aW9uYWwsXG4gICAgT3V0cHV0LFxuICAgIFZpZXdDaGlsZCxcbiAgICBBZnRlckNvbnRlbnRJbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSWd4TmF2aWdhdGlvblNlcnZpY2UsIElUb2dnbGVWaWV3IH0gZnJvbSAnLi4vY29yZS9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IElneEJ1dHRvbk1vZHVsZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvYnV0dG9uL2J1dHRvbi5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSWd4UmlwcGxlTW9kdWxlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9yaXBwbGUvcmlwcGxlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBJZ3hEaWFsb2dBY3Rpb25zRGlyZWN0aXZlLCBJZ3hEaWFsb2dUaXRsZURpcmVjdGl2ZSB9IGZyb20gJy4vZGlhbG9nLmRpcmVjdGl2ZXMnO1xuaW1wb3J0IHsgSWd4VG9nZ2xlTW9kdWxlLCBJZ3hUb2dnbGVEaXJlY3RpdmUgfSBmcm9tICcuLi9kaXJlY3RpdmVzL3RvZ2dsZS90b2dnbGUuZGlyZWN0aXZlJztcbmltcG9ydCB7IE92ZXJsYXlTZXR0aW5ncywgR2xvYmFsUG9zaXRpb25TdHJhdGVneSwgTm9PcFNjcm9sbFN0cmF0ZWd5LCBQb3NpdGlvblNldHRpbmdzIH0gZnJvbSAnLi4vc2VydmljZXMnO1xuaW1wb3J0IHsgc2xpZGVJbkJvdHRvbSwgc2xpZGVPdXRUb3AgfSBmcm9tICcuLi9hbmltYXRpb25zL3NsaWRlL2luZGV4JztcbmltcG9ydCB7IElneEZvY3VzTW9kdWxlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9mb2N1cy9mb2N1cy5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSUJhc2VFdmVudEFyZ3MgfSBmcm9tICcuLi9jb3JlL3V0aWxzJztcblxubGV0IERJQUxPR19JRCA9IDA7XG4vKipcbiAqICoqSWduaXRlIFVJIGZvciBBbmd1bGFyIERpYWxvZyBXaW5kb3cqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvZGlhbG9nLmh0bWwpXG4gKlxuICogVGhlIElnbml0ZSBVSSBEaWFsb2cgV2luZG93IHByZXNlbnRzIGEgZGlhbG9nIHdpbmRvdyB0byB0aGUgdXNlciB3aGljaCBjYW4gc2ltcGx5IGRpc3BsYXkgbWVzc2FnZXMgb3IgZGlzcGxheVxuICogbW9yZSBjb21wbGljYXRlZCB2aXN1YWxzIHN1Y2ggYXMgYSB1c2VyIHNpZ24taW4gZm9ybS4gIEl0IGFsc28gcHJvdmlkZXMgYSByaWdodCBhbmQgbGVmdCBidXR0b25cbiAqIHdoaWNoIGNhbiBiZSB1c2VkIGZvciBjdXN0b20gYWN0aW9ucy5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgaHRtbFxuICogPGJ1dHRvbiAoY2xpY2spPVwiZm9ybS5vcGVuKClcIj5TaG93IERpYWxvZzwvYnV0dG9uPlxuICogPGlneC1kaWFsb2cgI2Zvcm0gdGl0bGU9XCJTaWduIEluXCIgcmlnaHRCdXR0b25MYWJlbD1cIk9LXCI+XG4gKiAgIDxkaXY+XG4gKiAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgaWd4SW5wdXQvPlxuICogICAgIDxsYWJlbCBpZ3hMYWJlbD5Vc2VybmFtZTwvbGFiZWw+XG4gKiAgIDwvZGl2PlxuICogICA8ZGl2PlxuICogICAgIDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBpZ3hJbnB1dC8+XG4gKiAgICAgPGxhYmVsIGlneExhYmVsPlBhc3N3b3JkPC9sYWJlbD5cbiAqICAgPC9kaXY+XG4gKiA8L2lneC1kaWFsb2c+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdpZ3gtZGlhbG9nJyxcbiAgICB0ZW1wbGF0ZVVybDogJ2RpYWxvZy1jb250ZW50LmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBJZ3hEaWFsb2dDb21wb25lbnQgaW1wbGVtZW50cyBJVG9nZ2xlVmlldywgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQge1xuICAgIHByaXZhdGUgc3RhdGljIE5FWFRfSUQgPSAxO1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IERJQUxPR19DTEFTUyA9ICdpZ3gtZGlhbG9nJztcblxuICAgIEBWaWV3Q2hpbGQoSWd4VG9nZ2xlRGlyZWN0aXZlLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHB1YmxpYyB0b2dnbGVSZWY6IElneFRvZ2dsZURpcmVjdGl2ZTtcblxuICAgIC8qKlxuICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc2V0cyB0aGUgdmFsdWUgb2YgdGhlIGBpZGAgYXR0cmlidXRlLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZC5cbiAgICAqYGBgaHRtbFxuICAgICo8aWd4LWRpYWxvZyBbaWRdPVwiJ2lneC1kaWFsb2ctNTYnXCIgI2FsZXJ0IHRpdGxlPVwiTm90aWZpY2F0aW9uXCIgbGVmdEJ1dHRvbkxhYmVsPVwiT0tcIiAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgKmBgYFxuICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmlkJylcbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZCA9IGBpZ3gtZGlhbG9nLSR7RElBTE9HX0lEKyt9YDtcblxuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGlzTW9kYWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc01vZGFsO1xuICAgIH1cblxuICAgIHNldCBpc01vZGFsKHZhbDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdFNldHRpbmdzLm1vZGFsID0gdmFsO1xuICAgICAgICB0aGlzLl9pc01vZGFsID0gdmFsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICogQW4gQElucHV0IHByb3BlcnR5IGNvbnRyb2xsaW5nIHRoZSBgdGl0bGVgIG9mIHRoZSBkaWFsb2cuXG4gICAgKmBgYGh0bWxcbiAgICAqPGlneC1kaWFsb2cgdGl0bGU9XCJOb3RpZmljYXRpb25cIiAjYWxlcnQgbGVmdEJ1dHRvbkxhYmVsPVwiT0tcIiAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgKmBgYFxuICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgdGl0bGUgPSAnJztcblxuICAgIC8qKlxuICAgICAqICBBbiBASW5wdXQgcHJvcGVydHkgY29udHJvbGxpbmcgdGhlIGBtZXNzYWdlYCBvZiB0aGUgZGlhbG9nLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgbWVzc2FnZT1cIllvdXIgZW1haWwgd2FzIHNlbnQhXCIgI2FsZXJ0IGxlZnRCdXR0b25MYWJlbD1cIk9LXCIgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbWVzc2FnZSA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRvIHNldCB0aGUgYGxhYmVsYCBvZiB0aGUgbGVmdCBidXR0b24gb2YgdGhlIGRpYWxvZy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIGxlZnRCdXR0b25MYWJlbD1cIk9LQVlcIiAjYWxlcnQgdGl0bGU9XCJOb3RpZmljYXRpb25cIiAgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbGVmdEJ1dHRvbkxhYmVsID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSBsZWZ0IGJ1dHRvbiBgdHlwZWAuIFRoZSB0eXBlcyBhcmUgYGZsYXRgLCBgcmFpc2VkYCBhbmQgYGZhYmAuXG4gICAgICogVGhlIGBmbGF0YCB0eXBlIGJ1dHRvbiBpcyBhIHJlY3RhbmdsZSBhbmQgZG9lc24ndCBoYXZlIGEgc2hhZG93LiA8YnI+XG4gICAgICogVGhlIGByYWlzZWRgIHR5cGUgYnV0dG9uIGlzIGFsc28gYSByZWN0YW5nbGUgYnV0IGhhcyBhIHNoYWRvdy4gPGJyPlxuICAgICAqIFRoZSBgZmFiYCB0eXBlIGJ1dHRvbiBpcyBhIGNpcmNsZSB3aXRoIGEgc2hhZG93LiA8YnI+XG4gICAgICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgYGZsYXRgLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgbGVmdEJ1dHRvblR5cGU9XCJyYWlzZWRcIiBsZWZ0QnV0dG9uTGFiZWw9XCJPS0FZXCIgI2FsZXJ0IChvbkxlZnRCdXR0b25TZWxlY3QpPVwiYWxlcnQuY2xvc2UoKVwiPjwvaWd4LWRpYWxvZz5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGxlZnRCdXR0b25UeXBlID0gJ2ZsYXQnO1xuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0byBzZXQgdGhlIGxlZnQgYnV0dG9uIGNvbG9yLiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIGxlZnRCdXR0b25Db2xvcj1cInllbGxvd1wiIGxlZnRCdXR0b25MYWJlbD1cIk9LQVlcIiAjYWxlcnQgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbGVmdEJ1dHRvbkNvbG9yID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSBsZWZ0IGJ1dHRvbiBgYmFja2dyb3VuZC1jb2xvcmAuIFRoZSBwcm9wZXJ0eSBhY2NlcHRzIGFsbCB2YWxpZCBDU1MgY29sb3IgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgbGVmdEJ1dHRvbkJhY2tncm91bmRDb2xvcj1cImJsYWNrXCIgbGVmdEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBsZWZ0QnV0dG9uQmFja2dyb3VuZENvbG9yID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSBsZWZ0IGJ1dHRvbiBgcmlwcGxlYC4gVGhlIGByaXBwbGVgIGFuaW1hdGVzIGEgY2xpY2svdGFwIHRvIGEgY29tcG9uZW50IGFzIGEgc2VyaWVzIG9mIGZhZGluZyB3YXZlcy5cbiAgICAgKiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIGxlZnRCdXR0b25SaXBwbGU9XCJncmVlblwiIGxlZnRCdXR0b25MYWJlbD1cIk9LQVlcIiAjYWxlcnQgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbGVmdEJ1dHRvblJpcHBsZSA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRvIHNldCB0aGUgYGxhYmVsYCBvZiB0aGUgcmlnaHQgYnV0dG9uIG9mIHRoZSBkaWFsb2cuXG4gICAgICpgYGBodG1sXG4gICAgICo8aWd4LWRpYWxvZyByaWdodEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCB0aXRsZT1cIk5vdGlmaWNhdGlvblwiICAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByaWdodEJ1dHRvbkxhYmVsID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSByaWdodCBidXR0b24gYHR5cGVgLiBUaGUgdHlwZXMgYXJlIGBmbGF0YCwgYHJhaXNlZGAgYW5kIGBmYWJgLlxuICAgICAqIFRoZSBgZmxhdGAgdHlwZSBidXR0b24gaXMgYSByZWN0YW5nbGUgYW5kIGRvZXNuJ3QgaGF2ZSBhIHNoYWRvdy4gPGJyPlxuICAgICAqIFRoZSBgcmFpc2VkYCB0eXBlIGJ1dHRvbiBpcyBhbHNvIGEgcmVjdGFuZ2xlIGJ1dCBoYXMgYSBzaGFkb3cuIDxicj5cbiAgICAgKiBUaGUgYGZhYmAgdHlwZSBidXR0b24gaXMgYSBjaXJjbGUgd2l0aCBhIHNoYWRvdy4gPGJyPlxuICAgICAqIFRoZSBkZWZhdWx0IHZhbHVlIGlzIGBmbGF0YC5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIHJpZ2h0QnV0dG9uVHlwZT1cImZhYlwiIHJpZ2h0QnV0dG9uTGFiZWw9XCJPS0FZXCIgI2FsZXJ0IChvbkxlZnRCdXR0b25TZWxlY3QpPVwiYWxlcnQuY2xvc2UoKVwiPjwvaWd4LWRpYWxvZz5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHJpZ2h0QnV0dG9uVHlwZSA9ICdmbGF0JztcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0byBzZXQgdGhlIHJpZ2h0IGJ1dHRvbiBgY29sb3JgLiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIHJpZ2h0QnV0dG9uQ29sb3I9XCJ5ZWxsb3dcIiByaWdodEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByaWdodEJ1dHRvbkNvbG9yID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSByaWdodCBidXR0b24gYGJhY2tncm91bmQtY29sb3JgLiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIHJpZ2h0QnV0dG9uQmFja2dyb3VuZENvbG9yPVwiYmxhY2tcIiByaWdodEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByaWdodEJ1dHRvbkJhY2tncm91bmRDb2xvciA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRvIHNldCB0aGUgcmlnaHQgYnV0dG9uIGByaXBwbGVgLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgcmlnaHRCdXR0b25SaXBwbGU9XCJncmVlblwiIHJpZ2h0QnV0dG9uTGFiZWw9XCJPS0FZXCIgI2FsZXJ0IChvbkxlZnRCdXR0b25TZWxlY3QpPVwiYWxlcnQuY2xvc2UoKVwiPjwvaWd4LWRpYWxvZz5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHJpZ2h0QnV0dG9uUmlwcGxlID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBhbGxvd3MgeW91IHRvIGVuYWJsZSB0aGUgXCJjbG9zZSBvbiBjbGljayBvdXRzaWRlIHRoZSBkaWFsb2dcIi4gQnkgZGVmYXVsdCBpdCdzIGRpc2FibGVkLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgY2xvc2VPbk91dHNpZGVTZWxlY3Q9XCJ0cnVlXCIgbGVmdEJ1dHRvbkxhYmVsPVwiQ2FuY2VsXCIgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJkaWFsb2cuY2xvc2UoKVwiXG4gICAgICpyaWdodEJ1dHRvbkxhYmVsPVwiT0tcIiByaWdodEJ1dHRvblJpcHBsZT1cIiM0Q0FGNTBcIiAob25SaWdodEJ1dHRvblNlbGVjdCk9XCJvbkRpYWxvZ09LU2VsZWN0ZWQoJGV2ZW50KVwiPlxuICAgICAqPC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBnZXQgY2xvc2VPbk91dHNpZGVTZWxlY3QoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jbG9zZU9uT3V0c2lkZVNlbGVjdDtcbiAgICB9XG5cbiAgICBzZXQgY2xvc2VPbk91dHNpZGVTZWxlY3QodmFsOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0U2V0dGluZ3MuY2xvc2VPbk91dHNpZGVDbGljayA9IHZhbDtcbiAgICAgICAgdGhpcy5fY2xvc2VPbk91dHNpZGVTZWxlY3QgPSB2YWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBwb3NpdGlvbiBhbmQgYW5pbWF0aW9uIHNldHRpbmdzIHVzZWQgYnkgdGhlIGRpYWxvZy5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogQFZpZXdDaGlsZCgnYWxlcnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwdWJsaWMgYWxlcnQ6IElneERpYWxvZ0NvbXBvbmVudDtcbiAgICAgKiBsZXQgY3VycmVudFBvc2l0aW9uOiBQb3NpdGlvblNldHRpbmdzID0gdGhpcy5hbGVydC5wb3NpdGlvblNldHRpbmdzXG4gICAgICogYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2V0IHBvc2l0aW9uU2V0dGluZ3MoKTogUG9zaXRpb25TZXR0aW5ncyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wb3NpdGlvblNldHRpbmdzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgcG9zaXRpb24gYW5kIGFuaW1hdGlvbiBzZXR0aW5ncyB1c2VkIGJ5IHRoZSBkaWFsb2cuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGltcG9ydCB7IHNsaWRlSW5MZWZ0LCBzbGlkZU91dFJpZ2h0IH0gZnJvbSAnaWduaXRldWktYW5ndWxhcic7XG4gICAgICogLi4uXG4gICAgICogQFZpZXdDaGlsZCgnYWxlcnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwdWJsaWMgYWxlcnQ6IElneERpYWxvZ0NvbXBvbmVudDtcbiAgICAgKiAgcHVibGljIG5ld1Bvc2l0aW9uU2V0dGluZ3M6IFBvc2l0aW9uU2V0dGluZ3MgPSB7XG4gICAgICogICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2xpZGVJblRvcCwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICcyMDAwbXMnIH0gfSksXG4gICAgICogICAgICBjbG9zZUFuaW1hdGlvbjogdXNlQW5pbWF0aW9uKHNsaWRlT3V0Qm90dG9tLCB7IHBhcmFtczogeyBkdXJhdGlvbjogJzIwMDBtcyd9IH0pLFxuICAgICAqICAgICAgaG9yaXpvbnRhbERpcmVjdGlvbjogSG9yaXpvbnRhbEFsaWdubWVudC5MZWZ0LFxuICAgICAqICAgICAgdmVydGljYWxEaXJlY3Rpb246IFZlcnRpY2FsQWxpZ25tZW50Lk1pZGRsZSxcbiAgICAgKiAgICAgIGhvcml6b250YWxTdGFydFBvaW50OiBIb3Jpem9udGFsQWxpZ25tZW50LkxlZnQsXG4gICAgICogICAgICB2ZXJ0aWNhbFN0YXJ0UG9pbnQ6IFZlcnRpY2FsQWxpZ25tZW50Lk1pZGRsZSxcbiAgICAgKiAgICAgIG1pblNpemU6IHsgaGVpZ2h0OiAxMDAsIHdpZHRoOiAxMDAgfVxuICAgICAqICB9O1xuICAgICAqIHRoaXMuYWxlcnQucG9zaXRpb25TZXR0aW5ncyA9IHRoaXMubmV3UG9zaXRpb25TZXR0aW5ncztcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IHBvc2l0aW9uU2V0dGluZ3Moc2V0dGluZ3M6IFBvc2l0aW9uU2V0dGluZ3MpIHtcbiAgICAgICAgdGhpcy5fcG9zaXRpb25TZXR0aW5ncyA9IHNldHRpbmdzO1xuICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdFNldHRpbmdzLnBvc2l0aW9uU3RyYXRlZ3kgPSBuZXcgR2xvYmFsUG9zaXRpb25TdHJhdGVneSh0aGlzLl9wb3NpdGlvblNldHRpbmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiB0aGUgZGlhbG9nIGlzIG9wZW5lZC5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIChvbk9wZW4pPVwib25EaWFsb2dPcGVuSGFuZGxlcigkZXZlbnQpXCIgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJkaWFsb2cuY2xvc2UoKVwiIHJpZ2h0QnV0dG9uTGFiZWw9XCJPS1wiPlxuICAgICAqPC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uT3BlbiA9IG5ldyBFdmVudEVtaXR0ZXI8SURpYWxvZ0V2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIHRoZSBkaWFsb2cgaXMgY2xvc2VkLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgKG9uQ2xvc2UpPVwib25EaWFsb2dDbG9zZUhhbmRsZXIoJGV2ZW50KVwiIHRpdGxlPVwiQ29uZmlybWF0aW9uXCIgbGVmdEJ1dHRvbkxhYmVsPVwiQ2FuY2VsXCIgcmlnaHRCdXR0b25MYWJlbD1cIk9LXCI+XG4gICAgICo8L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25DbG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8SURpYWxvZ0V2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIHRoZSBsZWZ0IGJ1dHRvbiBpcyBjbGlja2VkLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJvbkRpYWxvZ09LU2VsZWN0ZWQoJGV2ZW50KVwiICNkaWFsb2cgbGVmdEJ1dHRvbkxhYmVsPVwiT0tcIiByaWdodEJ1dHRvbkxhYmVsPVwiQ2FuY2VsXCI+XG4gICAgICo8L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25MZWZ0QnV0dG9uU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxJRGlhbG9nRXZlbnRBcmdzPigpO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gdGhlIHJpZ2h0IGJ1dHRvbiBpcyBjbGlja2VkLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIChvblJpZ2h0QnV0dG9uU2VsZWN0KT1cIm9uRGlhbG9nT0tTZWxlY3RlZCgkZXZlbnQpXCJcbiAgICAgKiNkaWFsb2cgdGl0bGU9XCJDb25maXJtYXRpb25cIiAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImRpYWxvZy5jbG9zZSgpXCIgcmlnaHRCdXR0b25MYWJlbD1cIk9LXCJcbiAgICAgKnJpZ2h0QnV0dG9uUmlwcGxlPVwiIzRDQUY1MFwiIGNsb3NlT25PdXRzaWRlU2VsZWN0PVwidHJ1ZVwiPlxuICAgICAqPC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uUmlnaHRCdXR0b25TZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPElEaWFsb2dFdmVudEFyZ3M+KCk7XG5cbiAgICBwcml2YXRlIF9wb3NpdGlvblNldHRpbmdzOiBQb3NpdGlvblNldHRpbmdzID0ge1xuICAgICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2xpZGVJbkJvdHRvbSwgeyBwYXJhbXM6IHsgZnJvbVBvc2l0aW9uOiAndHJhbnNsYXRlWSgxMDAlKScgfSB9KSxcbiAgICAgICAgY2xvc2VBbmltYXRpb246IHVzZUFuaW1hdGlvbihzbGlkZU91dFRvcCwgeyBwYXJhbXM6IHsgdG9Qb3NpdGlvbjogJ3RyYW5zbGF0ZVkoLTEwMCUpJyB9IH0pXG4gICAgfTtcblxuICAgIHByaXZhdGUgX292ZXJsYXlEZWZhdWx0U2V0dGluZ3M6IE92ZXJsYXlTZXR0aW5ncztcbiAgICBwcml2YXRlIF9jbG9zZU9uT3V0c2lkZVNlbGVjdCA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2lzTW9kYWwgPSB0cnVlO1xuICAgIHByb3RlY3RlZCBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBlbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGRlZmF1bHQgYHRhYmluZGV4YCBhdHRyaWJ1dGUgZm9yIHRoZSBjb21wb25lbnRcbiAgICAgKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIudGFiaW5kZXgnKVxuICAgIHB1YmxpYyB0YWJpbmRleCA9IC0xO1xuXG4gICAgcHJpdmF0ZSBfdGl0bGVJZDogc3RyaW5nO1xuXG4gICAgLyoqX