@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
588 lines • 60.7 kB
JavaScript
import { __decorate, __metadata, __param } from "tslib";
import { Directive, ElementRef, HostListener, Input, NgModule, ChangeDetectorRef, OnInit, Output, EventEmitter, Optional, HostBinding, Inject } from '@angular/core';
import { useAnimation } from '@angular/animations';
import { scaleInCenter } from '../../animations/scale/index';
import { fadeOut } from '../../animations/fade/index';
import { IgxOverlayService } from '../../services/overlay/overlay';
import { HorizontalAlignment, AutoPositionStrategy } from '../../services';
import { CommonModule } from '@angular/common';
import { IgxNavigationService } from '../../core/navigation';
import { IgxToggleDirective, IgxToggleActionDirective } from '../toggle/toggle.directive';
/**
* **Ignite UI for Angular Tooltip Target** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/tooltip.html)
*
* The Ignite UI for Angular Tooltip Target directive is used to mark an HTML element in the markup as one that has a tooltip.
* The tooltip target is used in combination with the Ignite UI for Angular Tooltip by assigning the exported tooltip reference to the
* target's selector property.
*
* Example:
* ```html
* <button [igxTooltipTarget]="tooltipRef">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
let IgxTooltipTargetDirective = class IgxTooltipTargetDirective extends IgxToggleActionDirective {
constructor(_element, _navigationService) {
super(_element, _navigationService);
this._element = _element;
this._navigationService = _navigationService;
/**
* Gets/sets the amount of milliseconds that should pass before showing the tooltip.
*
* ```typescript
* // get
* let tooltipShowDelay = this.tooltipTarget.showDelay;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" showDelay="1500">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.showDelay = 500;
/**
* Gets/sets the amount of milliseconds that should pass before hiding the tooltip.
*
* ```typescript
* // get
* let tooltipHideDelay = this.tooltipTarget.hideDelay;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" hideDelay="1500">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.hideDelay = 500;
/**
* Specifies if the tooltip should not show when hovering its target with the mouse. (defaults to false)
* While setting this property to 'true' will disable the user interactions that shows/hides the tooltip,
* the developer will still be able to show/hide the tooltip through the API.
*
* ```typescript
* // get
* let tooltipDisabledValue = this.tooltipTarget.tooltipDisabled;
* ```
*
* ```html
* <!--set-->
* <button [igxTooltipTarget]="tooltipRef" [tooltipDisabled]="true">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.tooltipDisabled = false;
/**
* Emits an event when the tooltip that is associated with this target starts showing.
* This event is fired before the start of the countdown to showing the tooltip.
*
* ```typescript
* tooltipShowing(args: ITooltipShowEventArgs) {
* alert("Tooltip started showing!");
* }
* ```
*
* ```html
* <button [igxTooltipTarget]="tooltipRef"
* (onTooltipShow)='tooltipShowing($event)'>Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.onTooltipShow = new EventEmitter();
/**
* Emits an event when the tooltip that is associated with this target starts hiding.
* This event is fired before the start of the countdown to hiding the tooltip.
*
* ```typescript
* tooltipHiding(args: ITooltipHideEventArgs) {
* alert("Tooltip started hiding!");
* }
* ```
*
* ```html
* <button [igxTooltipTarget]="tooltipRef"
* (onTooltipHide)='tooltipHiding($event)'>Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
this.onTooltipHide = new EventEmitter();
}
/**
* @hidden
*/
set target(target) {
if (target !== null && target !== '') {
this._target = target;
}
}
/**
* @hidden
*/
get target() {
if (typeof this._target === 'string') {
return this._navigationService.get(this._target);
}
return this._target;
}
/**
* Gets the respective native element of the directive.
*
* ```typescript
* let tooltipTargetElement = this.tooltipTarget.nativeElement;
* ```
*/
get nativeElement() {
return this._element.nativeElement;
}
/**
* Indicates if the tooltip that is is associated with this target is currently hidden.
*
* ```typescript
* let tooltipHiddenValue = this.tooltipTarget.tooltipHidden;
* ```
*/
get tooltipHidden() {
return !this.target || this.target.collapsed;
}
/**
* @hidden
*/
ngOnInit() {
super.ngOnInit();
const positionSettings = {
target: this.nativeElement,
horizontalDirection: HorizontalAlignment.Center,
horizontalStartPoint: HorizontalAlignment.Center,
openAnimation: useAnimation(scaleInCenter, { params: { duration: '150ms' } }),
closeAnimation: useAnimation(fadeOut, { params: { duration: '75ms' } })
};
this._overlayDefaults.positionStrategy = new AutoPositionStrategy(positionSettings);
this._overlayDefaults.closeOnOutsideClick = false;
}
checkOutletAndOutsideClick() {
if (this.outlet) {
this._overlayDefaults.outlet = this.outlet;
}
}
get mergedOverlaySettings() {
return Object.assign({}, this._overlayDefaults, this.overlaySettings);
}
// Return true if the execution in onMouseEnter should be terminated after this method
preMouseEnterCheck() {
// If tooltip is about to be opened
if (this.target.toBeShown) {
clearTimeout(this.target.timeoutId);
this.target.toBeShown = false;
}
// If Tooltip is opened or about to be hidden
if (!this.target.collapsed || this.target.toBeHidden) {
clearTimeout(this.target.timeoutId);
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return true;
}
// if close animation has started finish it, or close the tooltip with no animation
this.target.forceClose(this.mergedOverlaySettings);
this.target.toBeHidden = false;
}
return false;
}
// Return true if the execution in onMouseLeave should be terminated after this method
preMouseLeaveCheck() {
clearTimeout(this.target.timeoutId);
// If tooltip is about to be opened
if (this.target.toBeShown) {
this.target.toBeShown = false;
this.target.toBeHidden = false;
return true;
}
return false;
}
/**
* @hidden
*/
onKeydownEscape(event) {
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.toBeHidden = true;
this.target.close();
this.target.toBeHidden = false;
}
/**
* @hidden
*/
onClick() {
if (!this.target.collapsed) {
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.forceClose(this.mergedOverlaySettings);
}
}
/**
* @hidden
*/
onMouseEnter() {
if (this.tooltipDisabled) {
return;
}
this.checkOutletAndOutsideClick();
const shouldReturn = this.preMouseEnterCheck();
if (shouldReturn) {
return;
}
const showingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipShow.emit(showingArgs);
if (showingArgs.cancel) {
return;
}
this.target.toBeShown = true;
this.target.timeoutId = setTimeout(() => {
this.target.open(this.mergedOverlaySettings); // Call open() of IgxTooltipDirective
this.target.toBeShown = false;
}, this.showDelay);
}
/**
* @hidden
*/
onMouseLeave() {
if (this.tooltipDisabled) {
return;
}
this.checkOutletAndOutsideClick();
const shouldReturn = this.preMouseLeaveCheck();
if (shouldReturn || this.target.collapsed) {
return;
}
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.toBeHidden = true;
this.target.timeoutId = setTimeout(() => {
this.target.close(); // Call close() of IgxTooltipDirective
this.target.toBeHidden = false;
}, this.hideDelay);
}
/**
* @hidden
*/
onTouchStart(event) {
if (this.tooltipDisabled) {
return;
}
this.showTooltip();
}
/**
* @hidden
*/
onDocumentTouchStart(event) {
if (this.tooltipDisabled) {
return;
}
if (this.nativeElement !== event.target &&
!this.nativeElement.contains(event.target)) {
this.hideTooltip();
}
}
/**
* Shows the tooltip by respecting the 'showDelay' property.
*
* ```typescript
* this.tooltipTarget.showTooltip();
* ```
*/
showTooltip() {
clearTimeout(this.target.timeoutId);
if (!this.target.collapsed) {
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
// if close animation has started finish it, or close the tooltip with no animation
this.target.forceClose(this.mergedOverlaySettings);
this.target.toBeHidden = false;
}
const showingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipShow.emit(showingArgs);
if (showingArgs.cancel) {
return;
}
this.target.toBeShown = true;
this.target.timeoutId = setTimeout(() => {
this.target.open(this.mergedOverlaySettings); // Call open() of IgxTooltipDirective
this.target.toBeShown = false;
}, this.showDelay);
}
/**
* Hides the tooltip by respecting the 'hideDelay' property.
*
* ```typescript
* this.tooltipTarget.hideTooltip();
* ```
*/
hideTooltip() {
if (this.target.collapsed && this.target.toBeShown) {
clearTimeout(this.target.timeoutId);
}
if (this.target.collapsed || this.target.toBeHidden) {
return;
}
const hidingArgs = { target: this, tooltip: this.target, cancel: false };
this.onTooltipHide.emit(hidingArgs);
if (hidingArgs.cancel) {
return;
}
this.target.toBeHidden = true;
this.target.timeoutId = setTimeout(() => {
this.target.close(); // Call close() of IgxTooltipDirective
this.target.toBeHidden = false;
}, this.hideDelay);
}
};
IgxTooltipTargetDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: IgxNavigationService, decorators: [{ type: Optional }] }
];
__decorate([
Input('showDelay'),
__metadata("design:type", Object)
], IgxTooltipTargetDirective.prototype, "showDelay", void 0);
__decorate([
Input('hideDelay'),
__metadata("design:type", Object)
], IgxTooltipTargetDirective.prototype, "hideDelay", void 0);
__decorate([
Input('tooltipDisabled'),
__metadata("design:type", Object)
], IgxTooltipTargetDirective.prototype, "tooltipDisabled", void 0);
__decorate([
Input('igxTooltipTarget'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [Object])
], IgxTooltipTargetDirective.prototype, "target", null);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxTooltipTargetDirective.prototype, "onTooltipShow", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxTooltipTargetDirective.prototype, "onTooltipHide", void 0);
__decorate([
HostListener('document:keydown.escape', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxTooltipTargetDirective.prototype, "onKeydownEscape", null);
__decorate([
HostListener('click'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], IgxTooltipTargetDirective.prototype, "onClick", null);
__decorate([
HostListener('mouseenter'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], IgxTooltipTargetDirective.prototype, "onMouseEnter", null);
__decorate([
HostListener('mouseleave'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], IgxTooltipTargetDirective.prototype, "onMouseLeave", null);
__decorate([
HostListener('touchstart', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxTooltipTargetDirective.prototype, "onTouchStart", null);
__decorate([
HostListener('document:touchstart', ['$event']),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], IgxTooltipTargetDirective.prototype, "onDocumentTouchStart", null);
IgxTooltipTargetDirective = __decorate([
Directive({
exportAs: 'tooltipTarget',
selector: '[igxTooltipTarget]'
}),
__param(1, Optional()),
__metadata("design:paramtypes", [ElementRef,
IgxNavigationService])
], IgxTooltipTargetDirective);
export { IgxTooltipTargetDirective };
let NEXT_ID = 0;
/**
* **Ignite UI for Angular Tooltip** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/tooltip.html)
*
* The Ignite UI for Angular Tooltip directive is used to mark an HTML element in the markup as one that should behave as a tooltip.
* The tooltip is used in combination with the Ignite UI for Angular Tooltip Target by assigning the exported tooltip reference to the
* respective target's selector property.
*
* Example:
* ```html
* <button [igxTooltipTarget]="tooltipRef">Hover me</button>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
let IgxTooltipDirective = class IgxTooltipDirective extends IgxToggleDirective {
/** @hidden */
constructor(elementRef, cdr, overlayService, navigationService) {
// D.P. constructor duplication due to es6 compilation, might be obsolete in the future
super(elementRef, cdr, overlayService, navigationService);
/**
* @hidden
* Returns whether close time out has started
*/
this.toBeHidden = false;
/**
* @hidden
* Returns whether open time out has started
*/
this.toBeShown = false;
/**
* Identifier for the tooltip.
* If this is property is not explicitly set, it will be automatically generated.
*
* ```typescript
* let tooltipId = this.tooltip.id;
* ```
*/
this.id = `igx-tooltip-${NEXT_ID++}`;
}
/**
* @hidden
*/
get hiddenClass() {
return this.collapsed;
}
/**
* @hidden
*/
get defaultClass() {
return !this.collapsed;
}
/**
* Get the role attribute of the tooltip.
*
* ```typescript
* let tooltipRole = this.tooltip.role;
* ```
*/
get role() {
return 'tooltip';
}
/**
* If there is open animation in progress this method will finish is.
* If there is no open animation in progress this method will open the toggle with no animation.
* @param overlaySettings setting to use for opening the toggle
*/
forceOpen(overlaySettings) {
const info = this.overlayService.getOverlayById(this._overlayId);
const hasOpenAnimation = info ? info.openAnimationPlayer : false;
if (hasOpenAnimation) {
info.openAnimationPlayer.finish();
info.openAnimationPlayer.reset();
info.openAnimationPlayer = null;
}
else if (this.collapsed) {
const animation = overlaySettings.positionStrategy.settings.openAnimation;
overlaySettings.positionStrategy.settings.openAnimation = null;
this.open(overlaySettings);
overlaySettings.positionStrategy.settings.openAnimation = animation;
}
}
/**
* If there is close animation in progress this method will finish is.
* If there is no close animation in progress this method will close the toggle with no animation.
* @param overlaySettings settings to use for closing the toggle
*/
forceClose(overlaySettings) {
const info = this.overlayService.getOverlayById(this._overlayId);
const hasCloseAnimation = info ? info.closeAnimationPlayer : false;
if (hasCloseAnimation) {
info.closeAnimationPlayer.finish();
info.closeAnimationPlayer.reset();
info.closeAnimationPlayer = null;
}
else if (!this.collapsed) {
const animation = overlaySettings.positionStrategy.settings.closeAnimation;
overlaySettings.positionStrategy.settings.closeAnimation = null;
this.close();
overlaySettings.positionStrategy.settings.closeAnimation = animation;
}
}
};
IgxTooltipDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: ChangeDetectorRef },
{ type: IgxOverlayService, decorators: [{ type: Inject, args: [IgxOverlayService,] }] },
{ type: IgxNavigationService, decorators: [{ type: Optional }] }
];
__decorate([
HostBinding('class.igx-tooltip--hidden'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxTooltipDirective.prototype, "hiddenClass", null);
__decorate([
HostBinding('class.igx-tooltip--desktop'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxTooltipDirective.prototype, "defaultClass", null);
__decorate([
Input('context'),
__metadata("design:type", Object)
], IgxTooltipDirective.prototype, "context", void 0);
__decorate([
HostBinding('attr.id'),
Input(),
__metadata("design:type", Object)
], IgxTooltipDirective.prototype, "id", void 0);
__decorate([
HostBinding('attr.role'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxTooltipDirective.prototype, "role", null);
IgxTooltipDirective = __decorate([
Directive({
exportAs: 'tooltip',
selector: '[igxTooltip]'
}),
__param(2, Inject(IgxOverlayService)),
__param(3, Optional()),
__metadata("design:paramtypes", [ElementRef,
ChangeDetectorRef,
IgxOverlayService,
IgxNavigationService])
], IgxTooltipDirective);
export { IgxTooltipDirective };
/**
* @hidden
*/
let IgxTooltipModule = class IgxTooltipModule {
};
IgxTooltipModule = __decorate([
NgModule({
declarations: [IgxTooltipDirective, IgxTooltipTargetDirective],
exports: [IgxTooltipDirective, IgxTooltipTargetDirective],
imports: [CommonModule],
providers: [IgxOverlayService]
})
], IgxTooltipModule);
export { IgxTooltipModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9pZ25pdGV1aS1hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL2RpcmVjdGl2ZXMvdG9vbHRpcC90b29sdGlwLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNILFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxFQUMvRSxNQUFNLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUN0RCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzdELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsb0JBQW9CLEVBQXFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUcsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzdELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBYzFGOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFLSCxJQUFhLHlCQUF5QixHQUF0QyxNQUFhLHlCQUEwQixTQUFRLHdCQUF3QjtJQXNJbkUsWUFBb0IsUUFBb0IsRUFDaEIsa0JBQXdDO1FBQzVELEtBQUssQ0FBQyxRQUFRLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUZwQixhQUFRLEdBQVIsUUFBUSxDQUFZO1FBQ2hCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBc0I7UUF0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ICAgIERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBJbnB1dCwgTmdNb2R1bGUsIENoYW5nZURldGVjdG9yUmVmLCBPbkluaXQsXG4gICAgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9wdGlvbmFsLCBIb3N0QmluZGluZywgSW5qZWN0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdXNlQW5pbWF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQgeyBzY2FsZUluQ2VudGVyIH0gZnJvbSAnLi4vLi4vYW5pbWF0aW9ucy9zY2FsZS9pbmRleCc7XG5pbXBvcnQgeyBmYWRlT3V0IH0gZnJvbSAnLi4vLi4vYW5pbWF0aW9ucy9mYWRlL2luZGV4JztcbmltcG9ydCB7IElneE92ZXJsYXlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvb3ZlcmxheS9vdmVybGF5JztcbmltcG9ydCB7IEhvcml6b250YWxBbGlnbm1lbnQsIEF1dG9Qb3NpdGlvblN0cmF0ZWd5LCBQb3NpdGlvblNldHRpbmdzLCBPdmVybGF5U2V0dGluZ3MgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcyc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSWd4TmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL25hdmlnYXRpb24nO1xuaW1wb3J0IHsgSWd4VG9nZ2xlRGlyZWN0aXZlLCBJZ3hUb2dnbGVBY3Rpb25EaXJlY3RpdmUgfSBmcm9tICcuLi90b2dnbGUvdG9nZ2xlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBJQmFzZUV2ZW50QXJncyB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIElUb29sdGlwU2hvd0V2ZW50QXJncyBleHRlbmRzIElCYXNlRXZlbnRBcmdzIHtcbiAgICB0YXJnZXQ6IElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmU7XG4gICAgdG9vbHRpcDogSWd4VG9vbHRpcERpcmVjdGl2ZTtcbiAgICBjYW5jZWw6IGJvb2xlYW47XG59XG5leHBvcnQgaW50ZXJmYWNlIElUb29sdGlwSGlkZUV2ZW50QXJncyBleHRlbmRzIElCYXNlRXZlbnRBcmdzIHtcbiAgICB0YXJnZXQ6IElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmU7XG4gICAgdG9vbHRpcDogSWd4VG9vbHRpcERpcmVjdGl2ZTtcbiAgICBjYW5jZWw6IGJvb2xlYW47XG59XG5cbi8qKlxuICogKipJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgVG9vbHRpcCBUYXJnZXQqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvdG9vbHRpcC5odG1sKVxuICpcbiAqIFRoZSBJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgVG9vbHRpcCBUYXJnZXQgZGlyZWN0aXZlIGlzIHVzZWQgdG8gbWFyayBhbiBIVE1MIGVsZW1lbnQgaW4gdGhlIG1hcmt1cCBhcyBvbmUgdGhhdCBoYXMgYSB0b29sdGlwLlxuICogVGhlIHRvb2x0aXAgdGFyZ2V0IGlzIHVzZWQgaW4gY29tYmluYXRpb24gd2l0aCB0aGUgSWduaXRlIFVJIGZvciBBbmd1bGFyIFRvb2x0aXAgYnkgYXNzaWduaW5nIHRoZSBleHBvcnRlZCB0b29sdGlwIHJlZmVyZW5jZSB0byB0aGVcbiAqIHRhcmdldCdzIHNlbGVjdG9yIHByb3BlcnR5LlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGBodG1sXG4gKiA8YnV0dG9uIFtpZ3hUb29sdGlwVGFyZ2V0XT1cInRvb2x0aXBSZWZcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICogYGBgXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIGV4cG9ydEFzOiAndG9vbHRpcFRhcmdldCcsXG4gICAgc2VsZWN0b3I6ICdbaWd4VG9vbHRpcFRhcmdldF0nXG59KVxuZXhwb3J0IGNsYXNzIElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmUgZXh0ZW5kcyBJZ3hUb2dnbGVBY3Rpb25EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xuICAgIC8qKlxuICAgICAqIEdldHMvc2V0cyB0aGUgYW1vdW50IG9mIG1pbGxpc2Vjb25kcyB0aGF0IHNob3VsZCBwYXNzIGJlZm9yZSBzaG93aW5nIHRoZSB0b29sdGlwLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIC8vIGdldFxuICAgICAqIGxldCB0b29sdGlwU2hvd0RlbGF5ID0gdGhpcy50b29sdGlwVGFyZ2V0LnNob3dEZWxheTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogPGJ1dHRvbiBbaWd4VG9vbHRpcFRhcmdldF09XCJ0b29sdGlwUmVmXCIgc2hvd0RlbGF5PVwiMTUwMFwiPkhvdmVyIG1lPC9idXR0b24+XG4gICAgICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgnc2hvd0RlbGF5JylcbiAgICBwdWJsaWMgc2hvd0RlbGF5ID0gNTAwO1xuXG4gICAgLyoqXG4gICAgICogR2V0cy9zZXRzIHRoZSBhbW91bnQgb2YgbWlsbGlzZWNvbmRzIHRoYXQgc2hvdWxkIHBhc3MgYmVmb3JlIGhpZGluZyB0aGUgdG9vbHRpcC5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgdG9vbHRpcEhpZGVEZWxheSA9IHRoaXMudG9vbHRpcFRhcmdldC5oaWRlRGVsYXk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPCEtLXNldC0tPlxuICAgICAqIDxidXR0b24gW2lneFRvb2x0aXBUYXJnZXRdPVwidG9vbHRpcFJlZlwiIGhpZGVEZWxheT1cIjE1MDBcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ2hpZGVEZWxheScpXG4gICAgcHVibGljIGhpZGVEZWxheSA9IDUwMDtcblxuICAgIC8qKlxuICAgICAqIFNwZWNpZmllcyBpZiB0aGUgdG9vbHRpcCBzaG91bGQgbm90IHNob3cgd2hlbiBob3ZlcmluZyBpdHMgdGFyZ2V0IHdpdGggdGhlIG1vdXNlLiAoZGVmYXVsdHMgdG8gZmFsc2UpXG4gICAgICogV2hpbGUgc2V0dGluZyB0aGlzIHByb3BlcnR5IHRvICd0cnVlJyB3aWxsIGRpc2FibGUgdGhlIHVzZXIgaW50ZXJhY3Rpb25zIHRoYXQgc2hvd3MvaGlkZXMgdGhlIHRvb2x0aXAsXG4gICAgICogdGhlIGRldmVsb3BlciB3aWxsIHN0aWxsIGJlIGFibGUgdG8gc2hvdy9oaWRlIHRoZSB0b29sdGlwIHRocm91Z2ggdGhlIEFQSS5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgdG9vbHRpcERpc2FibGVkVmFsdWUgPSB0aGlzLnRvb2x0aXBUYXJnZXQudG9vbHRpcERpc2FibGVkO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDwhLS1zZXQtLT5cbiAgICAgKiA8YnV0dG9uIFtpZ3hUb29sdGlwVGFyZ2V0XT1cInRvb2x0aXBSZWZcIiBbdG9vbHRpcERpc2FibGVkXT1cInRydWVcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ3Rvb2x0aXBEaXNhYmxlZCcpXG4gICAgcHVibGljIHRvb2x0aXBEaXNhYmxlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBJbnB1dCgnaWd4VG9vbHRpcFRhcmdldCcpXG4gICAgc2V0IHRhcmdldCh0YXJnZXQ6IGFueSkge1xuICAgICAgICBpZiAodGFyZ2V0ICE9PSBudWxsICYmIHRhcmdldCAhPT0gJycpIHtcbiAgICAgICAgICAgIHRoaXMuX3RhcmdldCA9IHRhcmdldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXQgdGFyZ2V0KCk6IGFueSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5fdGFyZ2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX25hdmlnYXRpb25TZXJ2aWNlLmdldCh0aGlzLl90YXJnZXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl90YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmVzcGVjdGl2ZSBuYXRpdmUgZWxlbWVudCBvZiB0aGUgZGlyZWN0aXZlLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0b29sdGlwVGFyZ2V0RWxlbWVudCA9IHRoaXMudG9vbHRpcFRhcmdldC5uYXRpdmVFbGVtZW50O1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgbmF0aXZlRWxlbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgaWYgdGhlIHRvb2x0aXAgdGhhdCBpcyBpcyBhc3NvY2lhdGVkIHdpdGggdGhpcyB0YXJnZXQgaXMgY3VycmVudGx5IGhpZGRlbi5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdG9vbHRpcEhpZGRlblZhbHVlID0gdGhpcy50b29sdGlwVGFyZ2V0LnRvb2x0aXBIaWRkZW47XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldCB0b29sdGlwSGlkZGVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gIXRoaXMudGFyZ2V0IHx8IHRoaXMudGFyZ2V0LmNvbGxhcHNlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSB0b29sdGlwIHRoYXQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFyZ2V0IHN0YXJ0cyBzaG93aW5nLlxuICAgICAqIFRoaXMgZXZlbnQgaXMgZmlyZWQgYmVmb3JlIHRoZSBzdGFydCBvZiB0aGUgY291bnRkb3duIHRvIHNob3dpbmcgdGhlIHRvb2x0aXAuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdG9vbHRpcFNob3dpbmcoYXJnczogSVRvb2x0aXBTaG93RXZlbnRBcmdzKSB7XG4gICAgICogICAgYWxlcnQoXCJUb29sdGlwIHN0YXJ0ZWQgc2hvd2luZyFcIik7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxidXR0b24gW2lneFRvb2x0aXBUYXJnZXRdPVwidG9vbHRpcFJlZlwiXG4gICAgICogICAgICAgICAob25Ub29sdGlwU2hvdyk9J3Rvb2x0aXBTaG93aW5nKCRldmVudCknPkhvdmVyIG1lPC9idXR0b24+XG4gICAgICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvblRvb2x0aXBTaG93ID0gbmV3IEV2ZW50RW1pdHRlcjxJVG9vbHRpcFNob3dFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSB0b29sdGlwIHRoYXQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFyZ2V0IHN0YXJ0cyBoaWRpbmcuXG4gICAgICogVGhpcyBldmVudCBpcyBmaXJlZCBiZWZvcmUgdGhlIHN0YXJ0IG9mIHRoZSBjb3VudGRvd24gdG8gaGlkaW5nIHRoZSB0b29sdGlwLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRvb2x0aXBIaWRpbmcoYXJnczogSVRvb2x0aXBIaWRlRXZlbnRBcmdzKSB7XG4gICAgICogICAgYWxlcnQoXCJUb29sdGlwIHN0YXJ0ZWQgaGlkaW5nIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGJ1dHRvbiBbaWd4VG9vbHRpcFRhcmdldF09XCJ0b29sdGlwUmVmXCJcbiAgICAgKiAgICAgICAgIChvblRvb2x0aXBIaWRlKT0ndG9vbHRpcEhpZGluZygkZXZlbnQpJz5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Ub29sdGlwSGlkZSA9IG5ldyBFdmVudEVtaXR0ZXI8SVRvb2x0aXBIaWRlRXZlbnRBcmdzPigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZixcbiAgICAgICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBfbmF2aWdhdGlvblNlcnZpY2U6IElneE5hdmlnYXRpb25TZXJ2aWNlKSB7XG4gICAgICAgIHN1cGVyKF9lbGVtZW50LCBfbmF2aWdhdGlvblNlcnZpY2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgICAgIHN1cGVyLm5nT25Jbml0KCk7XG5cbiAgICAgICAgY29uc3QgcG9zaXRpb25TZXR0aW5nczogUG9zaXRpb25TZXR0aW5ncyA9IHtcbiAgICAgICAgICAgIHRhcmdldDogdGhpcy5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgaG9yaXpvbnRhbERpcmVjdGlvbjogSG9yaXpvbnRhbEFsaWdubWVudC5DZW50ZXIsXG4gICAgICAgICAgICBob3Jpem9udGFsU3RhcnRQb2ludDogSG9yaXpvbnRhbEFsaWdubWVudC5DZW50ZXIsXG4gICAgICAgICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2NhbGVJbkNlbnRlciwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICcxNTBtcycgfSB9KSxcbiAgICAgICAgICAgIGNsb3NlQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oZmFkZU91dCwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICc3NW1zJyB9IH0pXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5fb3ZlcmxheURlZmF1bHRzLnBvc2l0aW9uU3RyYXRlZ3kgPSBuZXcgQXV0b1Bvc2l0aW9uU3RyYXRlZ3kocG9zaXRpb25TZXR0aW5ncyk7XG4gICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0cy5jbG9zZU9uT3V0c2lkZUNsaWNrID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaGVja091dGxldEFuZE91dHNpZGVDbGljaygpIHtcbiAgICAgICAgaWYgKHRoaXMub3V0bGV0KSB7XG4gICAgICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdHMub3V0bGV0ID0gdGhpcy5vdXRsZXQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCBtZXJnZWRPdmVybGF5U2V0dGluZ3MoKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCB0aGlzLl9vdmVybGF5RGVmYXVsdHMsIHRoaXMub3ZlcmxheVNldHRpbmdzKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm4gdHJ1ZSBpZiB0aGUgZXhlY3V0aW9uIGluIG9uTW91c2VFbnRlciBzaG91bGQgYmUgdGVybWluYXRlZCBhZnRlciB0aGlzIG1ldGhvZFxuICAgIHByaXZhdGUgcHJlTW91c2VFbnRlckNoZWNrKCkge1xuICAgICAgICAvLyBJZiB0b29sdGlwIGlzIGFib3V0IHRvIGJlIG9wZW5lZFxuICAgICAgICBpZiAodGhpcy50YXJnZXQudG9CZVNob3duKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50YXJnZXQudGltZW91dElkKTtcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0LnRvQmVTaG93biA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgVG9vbHRpcCBpcyBvcGVuZWQgb3IgYWJvdXQgdG8gYmUgaGlkZGVuXG4gICAgICAgIGlmICghdGhpcy50YXJnZXQuY29sbGFwc2VkIHx8IHRoaXMudGFyZ2V0LnRvQmVIaWRkZW4pIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRhcmdldC50aW1lb3V0SWQpO1xuXG4gICAgICAgICAgICBjb25zdCBoaWRpbmdBcmdzID0geyB0YXJnZXQ6IHRoaXMsIHRvb2x0aXA6IHRoaXMudGFyZ2V0LCBjYW5jZWw6IGZhbHNlIH07XG4gICAgICAgICAgICB0aGlzLm9uVG9vbHRpcEhpZGUuZW1pdChoaWRpbmdBcmdzKTtcblxuICAgICAgICAgICAgaWYgKGhpZGluZ0FyZ3MuY2FuY2VsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vICBpZiBjbG9zZSBhbmltYXRpb24gaGFzIHN0YXJ0ZWQgZmluaXNoIGl0LCBvciBjbG9zZSB0aGUgdG9vbHRpcCB3aXRoIG5vIGFuaW1hdGlvblxuICAgICAgICAgICAgdGhpcy50YXJnZXQuZm9yY2VDbG9zZSh0aGlzLm1lcmdlZE92ZXJsYXlTZXR0aW5ncyk7XG4gICAgICAgICAgICB0aGlzLnRhcmdldC50b0JlSGlkZGVuID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIHRydWUgaWYgdGhlIGV4ZWN1dGlvbiBpbiBvbk1vdXNlTGVhdmUgc2hvdWxkIGJlIHRlcm1pbmF0ZWQgYWZ0ZXIgdGhpcyBtZXRob2RcbiAgICBwcml2YXRlIHByZU1vdXNlTGVhdmVDaGVjaygpOiBib29sZWFuIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMudGFyZ2V0LnRpbWVvdXRJZCk7XG5cbiAgICAgICAgLy8gSWYgdG9vbHRpcCBpcyBhYm91dCB0byBiZSBvcGVuZWRcbiAgICAgICAgaWYgKHRoaXMudGFyZ2V0LnRvQmVTaG93bikge1xuICAgICAgICAgICAgdGhpcy50YXJnZXQudG9CZVNob3duID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnRhcmdldC50b0JlSGlkZGVuID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5ZG93bi5lc2NhcGUnLCBbJyRldmVudCddKVxuICAgIHB1YmxpYyBvbktleWRvd25Fc2NhcGUoZXZlbnQpIHtcbiAgICAgICAgY29uc3QgaGlkaW5nQXJncyA9IHsgdGFyZ2V0OiB0aGlzLCB0b29sdGlwOiB0aGlzLnRhcmdldCwgY2FuY2VsOiBmYWxzZSB9O1xuICAgICAgICB0aGlzLm9uVG9vbHRpcEhpZGUuZW1pdChoaWRpbmdBcmdzKTtcblxuICAgICAgICBpZiAoaGlkaW5nQXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudGFyZ2V0LnRvQmVIaWRkZW4gPSB0cnVlO1xuICAgICAgICB0aGlzLnRhcmdldC5jbG9zZSgpO1xuICAgICAgICB0aGlzLnRhcmdldC50b0JlSGlkZGVuID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBIb3N0TGlzdGVuZXIoJ2NsaWNrJylcbiAgICBwdWJsaWMgb25DbGljaygpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRhcmdldC5jb2xsYXBzZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGhpZGluZ0FyZ3MgPSB7IHRhcmdldDogdGhpcywgdG9vbHRpcDogdGhpcy50YXJnZXQsIGNhbmNlbDogZmFsc2UgfTtcbiAgICAgICAgICAgIHRoaXMub25Ub29sdGlwSGlkZS5lbWl0KGhpZGluZ0FyZ3MpO1xuXG4gICAgICAgICAgICBpZiAoaGlkaW5nQXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudGFyZ2V0LmZvcmNlQ2xvc2UodGhpcy5tZXJnZWRPdmVybGF5U2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBIb3N0TGlzdGVuZXIoJ21vdXNlZW50ZXInKVxuICAgIHB1YmxpYyBvbk1vdXNlRW50ZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLnRvb2x0aXBEaXNhYmxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jaGVja091dGxldEFuZE91dHNpZGVDbGljaygpO1xuICAgICAgICBjb25zdCBzaG91bGRSZXR1cm4gPSB0aGlzLnByZU1vdXNlRW50ZXJDaGVjaygpO1xuICAgICAgICBpZiAoc2hvdWxkUmV0dXJuKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzaG93aW5nQXJncyA9IHsgdGFyZ2V0OiB0aGlzLCB0b29sdGlwOiB0aGlzLnRhcmdldCwgY2FuY2VsOiBmYWxzZSB9O1xuICAgICAgICB0aGlzLm9uVG9vbHRpcFNob3cuZW1pdChzaG93aW5nQXJncyk7XG5cbiAgICAgICAgaWYgKHNob3dpbmdBcmdzLmNhbmNlbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50YXJnZXQudG9CZVNob3duID0gdHJ1ZTtcbiAgICAgICAgdGhpcy50YXJnZXQudGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnRhcmdldC5vcGVuKHRoaXMubWVyZ2VkT3ZlcmxheVNldHRpbmdzKTsgLy8gQ2FsbCBvcGVuKCkgb2YgSWd4VG9vbHRpcERpcmVjdGl2ZVxuICAgICAgICAgICAgdGhpcy50YXJnZXQudG9CZVNob3duID0gZmFsc2U7XG4gICAgICAgIH0sIHRoaXMuc2hvd0RlbGF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXG4gICAgcHVibGljIG9uTW91c2VMZWF2ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMudG9vbHRpcERpc2FibGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNoZWNrT3V0bGV0QW5kT3V0c2lkZUNsaWNrKCk7XG4gICAgICAgIGNvbnN0IHNob3VsZFJldHVybiA9IHRoaXMucHJlTW91c2VMZWF2ZUNoZWNrKCk7XG4gICAgICAgIGlmIChzaG91bGRSZXR1cm4gfHwgdGhpcy50YXJnZXQuY29sbGFwc2VkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBoaWRpbmdBcmdzID0geyB0YXJnZXQ6IHRoaXMsIHRvb2x0aXA6IHRoaXMudGFyZ2V0LCBjYW5jZWw6IGZhbHNlIH07XG4gICAgICAgIHRoaXMub25Ub29sdGlwSGlkZS5lbWl0KGhpZGluZ0FyZ3MpO1xuXG4gICAgICAgIGlmIChoaWRpbmdBcmdzLmNhbmNlbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgd