UNPKG

igniteui-angular

Version:

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

756 lines • 64.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Directive, ElementRef, HostListener, Input, NgModule, ChangeDetectorRef, 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'; /** * @record */ export function ITooltipShowEventArgs() { } if (false) { /** @type {?} */ ITooltipShowEventArgs.prototype.target; /** @type {?} */ ITooltipShowEventArgs.prototype.tooltip; /** @type {?} */ ITooltipShowEventArgs.prototype.cancel; } /** * @record */ export function ITooltipHideEventArgs() { } if (false) { /** @type {?} */ ITooltipHideEventArgs.prototype.target; /** @type {?} */ ITooltipHideEventArgs.prototype.tooltip; /** @type {?} */ ITooltipHideEventArgs.prototype.cancel; } /** * **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> * ``` */ export class IgxTooltipTargetDirective extends IgxToggleActionDirective { /** * @param {?} _element * @param {?} _navigationService */ 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 * @param {?} target * @return {?} */ set target(target) { if (target !== null && target !== '') { this._target = target; } } /** * @hidden * @return {?} */ 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; * ``` * @return {?} */ 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; * ``` * @return {?} */ get tooltipHidden() { return !this.target || this.target.collapsed; } /** * @hidden * @return {?} */ ngOnInit() { super.ngOnInit(); /** @type {?} */ 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; } /** * @private * @return {?} */ checkOutletAndOutsideClick() { if (this.closeOnOutsideClick !== undefined) { this._overlayDefaults.closeOnOutsideClick = this.closeOnOutsideClick; } if (this.outlet) { this._overlayDefaults.outlet = this.outlet; } } /** * @private * @return {?} */ get mergedOverlaySettings() { return Object.assign({}, this._overlayDefaults, this.overlaySettings); } // Return true if the execution in onMouseEnter should be terminated after this method /** * @private * @return {?} */ 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); /** @type {?} */ 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 /** * @private * @return {?} */ 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 * @return {?} */ onKeydownEscape() { /** @type {?} */ 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 * @return {?} */ onClick() { if (!this.target.collapsed) { /** @type {?} */ const hidingArgs = { target: this, tooltip: this.target, cancel: false }; this.onTooltipHide.emit(hidingArgs); if (hidingArgs.cancel) { return; } this.target.forceClose(this.mergedOverlaySettings); } } /** * @hidden * @return {?} */ onMouseEnter() { if (this.tooltipDisabled) { return; } this.checkOutletAndOutsideClick(); /** @type {?} */ const shouldReturn = this.preMouseEnterCheck(); if (shouldReturn) { return; } /** @type {?} */ 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 * @return {?} */ onMouseLeave() { if (this.tooltipDisabled) { return; } this.checkOutletAndOutsideClick(); /** @type {?} */ const shouldReturn = this.preMouseLeaveCheck(); if (shouldReturn || this.target.collapsed) { return; } /** @type {?} */ 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 * @param {?} event * @return {?} */ onTouchStart(event) { if (this.tooltipDisabled) { return; } event.preventDefault(); this.showTooltip(); } /** * @hidden * @param {?} event * @return {?} */ 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(); * ``` * @return {?} */ showTooltip() { clearTimeout(this.target.timeoutId); if (!this.target.collapsed) { /** @type {?} */ 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; } /** @type {?} */ 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(); * ``` * @return {?} */ hideTooltip() { if (this.target.collapsed && this.target.toBeShown) { clearTimeout(this.target.timeoutId); } if (this.target.collapsed || this.target.toBeHidden) { return; } /** @type {?} */ 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.decorators = [ { type: Directive, args: [{ exportAs: 'tooltipTarget', selector: '[igxTooltipTarget]' },] } ]; /** @nocollapse */ IgxTooltipTargetDirective.ctorParameters = () => [ { type: ElementRef }, { type: IgxNavigationService, decorators: [{ type: Optional }] } ]; IgxTooltipTargetDirective.propDecorators = { showDelay: [{ type: Input, args: ['showDelay',] }], hideDelay: [{ type: Input, args: ['hideDelay',] }], tooltipDisabled: [{ type: Input, args: ['tooltipDisabled',] }], target: [{ type: Input, args: ['igxTooltipTarget',] }], onTooltipShow: [{ type: Output }], onTooltipHide: [{ type: Output }], onKeydownEscape: [{ type: HostListener, args: ['document:keydown.escape', ['$event'],] }], onClick: [{ type: HostListener, args: ['click',] }], onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }], onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }], onTouchStart: [{ type: HostListener, args: ['touchstart', ['$event'],] }], onDocumentTouchStart: [{ type: HostListener, args: ['document:touchstart', ['$event'],] }] }; if (false) { /** * 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> * ``` * @type {?} */ IgxTooltipTargetDirective.prototype.showDelay; /** * 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> * ``` * @type {?} */ IgxTooltipTargetDirective.prototype.hideDelay; /** * 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> * ``` * @type {?} */ IgxTooltipTargetDirective.prototype.tooltipDisabled; /** * 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> * ``` * @type {?} */ IgxTooltipTargetDirective.prototype.onTooltipShow; /** * 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> * ``` * @type {?} */ IgxTooltipTargetDirective.prototype.onTooltipHide; /** * @type {?} * @private */ IgxTooltipTargetDirective.prototype._element; /** * @type {?} * @private */ IgxTooltipTargetDirective.prototype._navigationService; } /** @type {?} */ 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> * ``` */ export class IgxTooltipDirective extends IgxToggleDirective { /** * @hidden * @param {?} elementRef * @param {?} cdr * @param {?} overlayService * @param {?} navigationService */ 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 * @return {?} */ get hiddenClass() { return this.collapsed; } /** * @hidden * @return {?} */ get defaultClass() { return !this.collapsed; } /** * Get the role attribute of the tooltip. * * ```typescript * let tooltipRole = this.tooltip.role; * ``` * @return {?} */ 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. * @protected * @param {?=} overlaySettings setting to use for opening the toggle * @return {?} */ forceOpen(overlaySettings) { /** @type {?} */ const info = this.overlayService.getOverlayById(this._overlayId); /** @type {?} */ const hasOpenAnimation = info ? info.openAnimationPlayer : false; if (hasOpenAnimation) { info.openAnimationPlayer.finish(); info.openAnimationPlayer.reset(); info.openAnimationPlayer = null; } else if (this.collapsed) { /** @type {?} */ 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. * @protected * @param {?=} overlaySettings settings to use for closing the toggle * @return {?} */ forceClose(overlaySettings) { /** @type {?} */ const info = this.overlayService.getOverlayById(this._overlayId); /** @type {?} */ const hasCloseAnimation = info ? info.closeAnimationPlayer : false; if (hasCloseAnimation) { info.closeAnimationPlayer.finish(); info.closeAnimationPlayer.reset(); info.closeAnimationPlayer = null; } else if (!this.collapsed) { /** @type {?} */ const animation = overlaySettings.positionStrategy.settings.closeAnimation; overlaySettings.positionStrategy.settings.closeAnimation = null; this.close(); overlaySettings.positionStrategy.settings.closeAnimation = animation; } } } IgxTooltipDirective.decorators = [ { type: Directive, args: [{ exportAs: 'tooltip', selector: '[igxTooltip]' },] } ]; /** @nocollapse */ IgxTooltipDirective.ctorParameters = () => [ { type: ElementRef }, { type: ChangeDetectorRef }, { type: IgxOverlayService, decorators: [{ type: Inject, args: [IgxOverlayService,] }] }, { type: IgxNavigationService, decorators: [{ type: Optional }] } ]; IgxTooltipDirective.propDecorators = { hiddenClass: [{ type: HostBinding, args: ['class.igx-tooltip--hidden',] }], defaultClass: [{ type: HostBinding, args: ['class.igx-tooltip--desktop',] }], context: [{ type: Input, args: ['context',] }], id: [{ type: HostBinding, args: ['attr.id',] }, { type: Input }], role: [{ type: HostBinding, args: ['attr.role',] }] }; if (false) { /** * @hidden * @type {?} */ IgxTooltipDirective.prototype.timeoutId; /** * @hidden * Returns whether close time out has started * @type {?} */ IgxTooltipDirective.prototype.toBeHidden; /** * @hidden * Returns whether open time out has started * @type {?} */ IgxTooltipDirective.prototype.toBeShown; /** * Gets/sets any tooltip related data. * The 'context' can be used for storing any information that is necessary * to access when working with the tooltip. * * ```typescript * // get * let tooltipContext = this.tooltip.context; * ``` * * ```typescript * // set * this.tooltip.context = "Tooltip's context"; * ``` * @type {?} */ IgxTooltipDirective.prototype.context; /** * Identifier for the tooltip. * If this is property is not explicitly set, it will be automatically generated. * * ```typescript * let tooltipId = this.tooltip.id; * ``` * @type {?} */ IgxTooltipDirective.prototype.id; } /** * @hidden */ export class IgxTooltipModule { } IgxTooltipModule.decorators = [ { type: NgModule, args: [{ declarations: [IgxTooltipDirective, IgxTooltipTargetDirective], exports: [IgxTooltipDirective, IgxTooltipTargetDirective], imports: [CommonModule], providers: [IgxOverlayService] },] } ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9pZ25pdGV1aS1hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL2RpcmVjdGl2ZXMvdG9vbHRpcC90b29sdGlwLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNILFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQ3ZFLE1BQU0sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBYSxNQUFNLEVBQ2pFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxvQkFBb0IsRUFBcUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHdCQUF3QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7QUFHMUYsMkNBSUM7OztJQUhHLHVDQUFrQzs7SUFDbEMsd0NBQTZCOztJQUM3Qix1Q0FBZ0I7Ozs7O0FBRXBCLDJDQUlDOzs7SUFIRyx1Q0FBa0M7O0lBQ2xDLHdDQUE2Qjs7SUFDN0IsdUNBQWdCOzs7Ozs7Ozs7Ozs7Ozs7O0FBcUJwQixNQUFNLE9BQU8seUJBQTBCLFNBQVEsd0JBQXdCOzs7OztJQXNJbkUsWUFBb0IsUUFBb0IsRUFDaEIsa0JBQXdDO1FBQzVELEtBQUss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LFNBQUMsU0FBUztpQkFXZixXQUFXLFNBQUMsU0FBUyxjQUNyQixLQUFLO21CQVVMLFdBQVcsU0FBQyxXQUFXOzs7Ozs7O0lBbkV4Qix3Q0FBaUI7Ozs7OztJQU1qQix5Q0FBMEI7Ozs7OztJQU0xQix3Q0FBeUI7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBaUN6QixzQ0FDZTs7Ozs7Ozs7OztJQVVmLGlDQUV1Qzs7Ozs7QUEyRTNDLE1BQU0sT0FBTyxnQkFBZ0I7OztZQU41QixRQUFRLFNBQUM7Z0JBQ04sWUFBWSxFQUFFLENBQUMsbUJBQW1CLEVBQUUseUJBQXlCLENBQUM7Z0JBQzlELE9BQU8sRUFBRSxDQUFDLG1CQUFtQixFQUFFLHlCQUF5QixDQUFDO2dCQUN6RCxPQUFPLEVBQUUsQ0FBQyxZQUFZLENBQUM7Z0JBQ3ZCLFNBQVMsRUFBRSxDQUFDLGlCQUFpQixDQUFDO2FBQ2pDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE5nTW9kdWxlLCBDaGFuZ2VEZXRlY3RvclJlZiwgT25Jbml0LFxuICAgIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPcHRpb25hbCwgSG9zdEJpbmRpbmcsIE9uRGVzdHJveSwgSW5qZWN0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdXNlQW5pbWF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQgeyBzY2FsZUluQ2VudGVyIH0gZnJvbSAnLi4vLi4vYW5pbWF0aW9ucy9zY2FsZS9pbmRleCc7XG5pbXBvcnQgeyBmYWRlT3V0IH0gZnJvbSAnLi4vLi4vYW5pbWF0aW9ucy9mYWRlL2luZGV4JztcbmltcG9ydCB7IElneE92ZXJsYXlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvb3ZlcmxheS9vdmVybGF5JztcbmltcG9ydCB7IEhvcml6b250YWxBbGlnbm1lbnQsIEF1dG9Qb3NpdGlvblN0cmF0ZWd5LCBQb3NpdGlvblNldHRpbmdzLCBPdmVybGF5U2V0dGluZ3MgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcyc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSWd4TmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL25hdmlnYXRpb24nO1xuaW1wb3J0IHsgSWd4VG9nZ2xlRGlyZWN0aXZlLCBJZ3hUb2dnbGVBY3Rpb25EaXJlY3RpdmUgfSBmcm9tICcuLi90b2dnbGUvdG9nZ2xlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuZXhwb3J0IGludGVyZmFjZSBJVG9vbHRpcFNob3dFdmVudEFyZ3Mge1xuICAgIHRhcmdldDogSWd4VG9vbHRpcFRhcmdldERpcmVjdGl2ZTtcbiAgICB0b29sdGlwOiBJZ3hUb29sdGlwRGlyZWN0aXZlO1xuICAgIGNhbmNlbDogYm9vbGVhbjtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgSVRvb2x0aXBIaWRlRXZlbnRBcmdzIHtcbiAgICB0YXJnZXQ6IElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmU7XG4gICAgdG9vbHRpcDogSWd4VG9vbHRpcERpcmVjdGl2ZTtcbiAgICBjYW5jZWw6IGJvb2xlYW47XG59XG5cbi8qKlxuICogKipJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgVG9vbHRpcCBUYXJnZXQqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvdG9vbHRpcC5odG1sKVxuICpcbiAqIFRoZSBJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgVG9vbHRpcCBUYXJnZXQgZGlyZWN0aXZlIGlzIHVzZWQgdG8gbWFyayBhbiBIVE1MIGVsZW1lbnQgaW4gdGhlIG1hcmt1cCBhcyBvbmUgdGhhdCBoYXMgYSB0b29sdGlwLlxuICogVGhlIHRvb2x0aXAgdGFyZ2V0IGlzIHVzZWQgaW4gY29tYmluYXRpb24gd2l0aCB0aGUgSWduaXRlIFVJIGZvciBBbmd1bGFyIFRvb2x0aXAgYnkgYXNzaWduaW5nIHRoZSBleHBvcnRlZCB0b29sdGlwIHJlZmVyZW5jZSB0byB0aGVcbiAqIHRhcmdldCdzIHNlbGVjdG9yIHByb3BlcnR5LlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGBodG1sXG4gKiA8YnV0dG9uIFtpZ3hUb29sdGlwVGFyZ2V0XT1cInRvb2x0aXBSZWZcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICogYGBgXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIGV4cG9ydEFzOiAndG9vbHRpcFRhcmdldCcsXG4gICAgc2VsZWN0b3I6ICdbaWd4VG9vbHRpcFRhcmdldF0nXG59KVxuZXhwb3J0IGNsYXNzIElneFRvb2x0aXBUYXJnZXREaXJlY3RpdmUgZXh0ZW5kcyBJZ3hUb2dnbGVBY3Rpb25EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xuICAgIC8qKlxuICAgICAqIEdldHMvc2V0cyB0aGUgYW1vdW50IG9mIG1pbGxpc2Vjb25kcyB0aGF0IHNob3VsZCBwYXNzIGJlZm9yZSBzaG93aW5nIHRoZSB0b29sdGlwLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIC8vIGdldFxuICAgICAqIGxldCB0b29sdGlwU2hvd0RlbGF5ID0gdGhpcy50b29sdGlwVGFyZ2V0LnNob3dEZWxheTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogPGJ1dHRvbiBbaWd4VG9vbHRpcFRhcmdldF09XCJ0b29sdGlwUmVmXCIgc2hvd0RlbGF5PVwiMTUwMFwiPkhvdmVyIG1lPC9idXR0b24+XG4gICAgICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgnc2hvd0RlbGF5JylcbiAgICBwdWJsaWMgc2hvd0RlbGF5ID0gNTAwO1xuXG4gICAgLyoqXG4gICAgICogR2V0cy9zZXRzIHRoZSBhbW91bnQgb2YgbWlsbGlzZWNvbmRzIHRoYXQgc2hvdWxkIHBhc3MgYmVmb3JlIGhpZGluZyB0aGUgdG9vbHRpcC5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgdG9vbHRpcEhpZGVEZWxheSA9IHRoaXMudG9vbHRpcFRhcmdldC5oaWRlRGVsYXk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPCEtLXNldC0tPlxuICAgICAqIDxidXR0b24gW2lneFRvb2x0aXBUYXJnZXRdPVwidG9vbHRpcFJlZlwiIGhpZGVEZWxheT1cIjE1MDBcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ2hpZGVEZWxheScpXG4gICAgcHVibGljIGhpZGVEZWxheSA9IDUwMDtcblxuICAgIC8qKlxuICAgICAqIFNwZWNpZmllcyBpZiB0aGUgdG9vbHRpcCBzaG91bGQgbm90IHNob3cgd2hlbiBob3ZlcmluZyBpdHMgdGFyZ2V0IHdpdGggdGhlIG1vdXNlLiAoZGVmYXVsdHMgdG8gZmFsc2UpXG4gICAgICogV2hpbGUgc2V0dGluZyB0aGlzIHByb3BlcnR5IHRvICd0cnVlJyB3aWxsIGRpc2FibGUgdGhlIHVzZXIgaW50ZXJhY3Rpb25zIHRoYXQgc2hvd3MvaGlkZXMgdGhlIHRvb2x0aXAsXG4gICAgICogdGhlIGRldmVsb3BlciB3aWxsIHN0aWxsIGJlIGFibGUgdG8gc2hvdy9oaWRlIHRoZSB0b29sdGlwIHRocm91Z2ggdGhlIEFQSS5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgdG9vbHRpcERpc2FibGVkVmFsdWUgPSB0aGlzLnRvb2x0aXBUYXJnZXQudG9vbHRpcERpc2FibGVkO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDwhLS1zZXQtLT5cbiAgICAgKiA8YnV0dG9uIFtpZ3hUb29sdGlwVGFyZ2V0XT1cInRvb2x0aXBSZWZcIiBbdG9vbHRpcERpc2FibGVkXT1cInRydWVcIj5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ3Rvb2x0aXBEaXNhYmxlZCcpXG4gICAgcHVibGljIHRvb2x0aXBEaXNhYmxlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBJbnB1dCgnaWd4VG9vbHRpcFRhcmdldCcpXG4gICAgc2V0IHRhcmdldCh0YXJnZXQ6IGFueSkge1xuICAgICAgICBpZiAodGFyZ2V0ICE9PSBudWxsICYmIHRhcmdldCAhPT0gJycpIHtcbiAgICAgICAgICAgIHRoaXMuX3RhcmdldCA9IHRhcmdldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXQgdGFyZ2V0KCk6IGFueSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5fdGFyZ2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX25hdmlnYXRpb25TZXJ2aWNlLmdldCh0aGlzLl90YXJnZXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl90YXJnZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmVzcGVjdGl2ZSBuYXRpdmUgZWxlbWVudCBvZiB0aGUgZGlyZWN0aXZlLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0b29sdGlwVGFyZ2V0RWxlbWVudCA9IHRoaXMudG9vbHRpcFRhcmdldC5uYXRpdmVFbGVtZW50O1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgbmF0aXZlRWxlbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgaWYgdGhlIHRvb2x0aXAgdGhhdCBpcyBpcyBhc3NvY2lhdGVkIHdpdGggdGhpcyB0YXJnZXQgaXMgY3VycmVudGx5IGhpZGRlbi5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdG9vbHRpcEhpZGRlblZhbHVlID0gdGhpcy50b29sdGlwVGFyZ2V0LnRvb2x0aXBIaWRkZW47XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldCB0b29sdGlwSGlkZGVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gIXRoaXMudGFyZ2V0IHx8IHRoaXMudGFyZ2V0LmNvbGxhcHNlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSB0b29sdGlwIHRoYXQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFyZ2V0IHN0YXJ0cyBzaG93aW5nLlxuICAgICAqIFRoaXMgZXZlbnQgaXMgZmlyZWQgYmVmb3JlIHRoZSBzdGFydCBvZiB0aGUgY291bnRkb3duIHRvIHNob3dpbmcgdGhlIHRvb2x0aXAuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdG9vbHRpcFNob3dpbmcoYXJnczogSVRvb2x0aXBTaG93RXZlbnRBcmdzKSB7XG4gICAgICogICAgYWxlcnQoXCJUb29sdGlwIHN0YXJ0ZWQgc2hvd2luZyFcIik7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxidXR0b24gW2lneFRvb2x0aXBUYXJnZXRdPVwidG9vbHRpcFJlZlwiXG4gICAgICogICAgICAgICAob25Ub29sdGlwU2hvdyk9J3Rvb2x0aXBTaG93aW5nKCRldmVudCknPkhvdmVyIG1lPC9idXR0b24+XG4gICAgICogPHNwYW4gI3Rvb2x0aXBSZWY9XCJ0b29sdGlwXCIgaWd4VG9vbHRpcD5IZWxsbyB0aGVyZSwgSSBhbSBhIHRvb2x0aXAhPC9zcGFuPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvblRvb2x0aXBTaG93ID0gbmV3IEV2ZW50RW1pdHRlcjxJVG9vbHRpcFNob3dFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSB0b29sdGlwIHRoYXQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFyZ2V0IHN0YXJ0cyBoaWRpbmcuXG4gICAgICogVGhpcyBldmVudCBpcyBmaXJlZCBiZWZvcmUgdGhlIHN0YXJ0IG9mIHRoZSBjb3VudGRvd24gdG8gaGlkaW5nIHRoZSB0b29sdGlwLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRvb2x0aXBIaWRpbmcoYXJnczogSVRvb2x0aXBIaWRlRXZlbnRBcmdzKSB7XG4gICAgICogICAgYWxlcnQoXCJUb29sdGlwIHN0YXJ0ZWQgaGlkaW5nIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGJ1dHRvbiBbaWd4VG9vbHRpcFRhcmdldF09XCJ0b29sdGlwUmVmXCJcbiAgICAgKiAgICAgICAgIChvblRvb2x0aXBIaWRlKT0ndG9vbHRpcEhpZGluZygkZXZlbnQpJz5Ib3ZlciBtZTwvYnV0dG9uPlxuICAgICAqIDxzcGFuICN0b29sdGlwUmVmPVwidG9vbHRpcFwiIGlneFRvb2x0aXA+SGVsbG8gdGhlcmUsIEkgYW0gYSB0b29sdGlwITwvc3Bhbj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Ub29sdGlwSGlkZSA9IG5ldyBFdmVudEVtaXR0ZXI8SVRvb2x0aXBIaWRlRXZlbnRBcmdzPigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZixcbiAgICAgICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBfbmF2aWdhdGlvblNlcnZpY2U6IElneE5hdmlnYXRpb25TZXJ2aWNlKSB7XG4gICAgICAgIHN1cGVyKF9lbGVtZW50LCBfbmF2aWdhdGlvblNlcnZpY2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgICAgIHN1cGVyLm5nT25Jbml0KCk7XG5cbiAgICAgICAgY29uc3QgcG9zaXRpb25TZXR0aW5nczogUG9zaXRpb25TZXR0aW5ncyA9IHtcbiAgICAgICAgICAgIHRhcmdldDogdGhpcy5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgaG9yaXpvbnRhbERpcmVjdGlvbjogSG9yaXpvbnRhbEFsaWdubWVudC5DZW50ZXIsXG4gICAgICAgICAgICBob3Jpem9udGFsU3RhcnRQb2ludDogSG9yaXpvbnRhbEFsaWdubWVudC5DZW50ZXIsXG4gICAgICAgICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2NhbGVJbkNlbnRlciwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICcxNTBtcycgfSB9KSxcbiAgICAgICAgICAgIGNsb3NlQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oZmFkZU91dCwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICc3NW1zJyB9IH0pXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5fb3ZlcmxheURlZmF1bHRzLnBvc2l0aW9uU3RyYXRlZ3kgPSBuZXcgQXV0b1Bvc2l0aW9uU3RyYXRlZ3kocG9zaXRpb25TZXR0aW5ncyk7XG4gICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0cy5jbG9zZU9uT3V0c2lkZUNsaWNrID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaGVja091dGxldEFuZE91dHNpZGVDbGljaygpIHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VPbk91dHNpZGVDbGljayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdHMuY2xvc2VPbk91dHNpZGVDbGljayA9IHRoaXMuY2xvc2VPbk91dHNpZGVDbGljaztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vdXRsZXQpIHtcbiAgICAgICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0cy5vdXRsZXQgPSB0aGlzLm91dGxldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IG1lcmdlZE92ZXJsYXlTZXR0aW5ncygpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX292ZXJsYXlEZWZhdWx0cywgdGhpcy5vdmVybGF5U2V0dGluZ3MpO1xuICAgIH1cblxuICAgIC8vIFJldHVybiB0cnVlIGlmIHRoZSBleGVjdXRpb24gaW4gb25Nb3VzZUVudGVyIHNob3VsZCBiZSB0ZXJtaW5hdGVkIGFmdGVyIHRoaXMgbWV0aG9kXG4gICAgcHJpdmF0ZSBwcmVNb3VzZUVudGVyQ2hlY2soKSB7XG4gICAgICAgIC8vIElmIHRvb2x0aXAgaXMgYWJvdXQgdG8gYmUgb3BlbmVkXG4gICAgICAgIGlmICh0aGlzLnRhcmdldC50b0JlU2hvd24pIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRhcmdldC50aW1lb3V0SWQpO1xuICAgICAgICAgICAgdGhpcy50YXJnZXQudG9CZVNob3duID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBUb29sdGlwIGlzIG9wZW5lZCBvciBhYm91dCB0byBiZSBoaWRkZW5cbiAgICAgICAgaWYgKCF0aGlzLnRhcmdldC5jb2xsYXBzZWQgfHwgdGhpcy50YXJnZXQudG9CZUhpZGRlbikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMudGFyZ2V0LnRpbWVvdXRJZCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGhpZGluZ0FyZ3MgPSB7IHRhcmdldDogdGhpcywgdG9vbHRpcDogdGhpcy50YXJnZXQsIGNhbmNlbDogZmFsc2UgfTtcbiAgICAgICAgICAgIHRoaXMub25Ub29sdGlwSGlkZS5lbWl0KGhpZGluZ0FyZ3MpO1xuXG4gICAgICAgICAgICBpZiAoaGlkaW5nQXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gIGlmIGNsb3NlIGFuaW1hdGlvbiBoYXMgc3RhcnRlZCBmaW5pc2ggaXQsIG9yIGNsb3NlIHRoZSB0b29sdGlwIHdpdGggbm8gYW5pbWF0aW9uXG4gICAgICAgICAgICB0aGlzLnRhcmdldC5mb3JjZUNsb3NlKHRoaXMubWVyZ2VkT3ZlcmxheVNldHRpbmdzKTtcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0LnRvQ