UNPKG

@igor2017/sat-popover

Version:
397 lines 56.7 kB
import { ElementRef, Injectable, Optional } from '@angular/core'; import { ConnectionPositionPair, OverlayConfig } from '@angular/cdk/overlay'; import { ESCAPE } from '@angular/cdk/keycodes'; import { TemplatePortal } from '@angular/cdk/portal'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { Subject } from 'rxjs'; import { takeUntil, take, filter, tap } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "@angular/cdk/overlay"; import * as i2 from "@angular/cdk/bidi"; class SatPopoverAnchoringService { _overlay; _ngZone; _dir; /** Emits when the popover is opened. */ popoverOpened = new Subject(); /** Emits when the popover is closed. */ popoverClosed = new Subject(); /** Reference to the overlay containing the popover component. */ _overlayRef; /** Reference to the target popover. */ _popover; /** Reference to the view container for the popover template. */ _viewContainerRef; /** Reference to the anchor element. */ _anchor; /** Reference to a template portal where the overlay will be attached. */ _portal; /** Single subscription to notifications service events. */ _notificationsSubscription; /** Single subscription to position changes. */ _positionChangeSubscription; /** Whether the popover is presently open. */ _popoverOpen = false; /** Emits when the service is destroyed. */ _onDestroy = new Subject(); constructor(_overlay, _ngZone, _dir) { this._overlay = _overlay; this._ngZone = _ngZone; this._dir = _dir; } ngOnDestroy() { // Destroy popover before terminating subscriptions so that any resulting // detachments update 'closed state' this._destroyPopover(); // Terminate subscriptions if (this._notificationsSubscription) { this._notificationsSubscription.unsubscribe(); } if (this._positionChangeSubscription) { this._positionChangeSubscription.unsubscribe(); } this._onDestroy.next(); this._onDestroy.complete(); this.popoverOpened.complete(); this.popoverClosed.complete(); } /** Anchor a popover instance to a view and connection element. */ anchor(popover, viewContainerRef, anchor) { // If we're just changing the anchor element and the overlayRef already exists, // simply update the existing _overlayRef's anchor. if (this._popover === popover && this._viewContainerRef === viewContainerRef && this._overlayRef) { this._anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor; const config = this._overlayRef.getConfig(); const strategy = config.positionStrategy; strategy.setOrigin(this._anchor); this._overlayRef.updatePosition(); return; } // Destroy any previous popovers this._destroyPopover(); // Assign local refs this._popover = popover; this._viewContainerRef = viewContainerRef; this._anchor = anchor instanceof ElementRef ? anchor.nativeElement : anchor; } /** Gets whether the popover is presently open. */ isPopoverOpen() { return this._popoverOpen; } /** Toggles the popover between the open and closed states. */ togglePopover() { return this._popoverOpen ? this.closePopover() : this.openPopover(); } /** Opens the popover. */ openPopover(options = {}) { if (!this._popoverOpen) { this._applyOpenOptions(options); this._createOverlay(); this._subscribeToBackdrop(); this._subscribeToEscape(); this._subscribeToDetachments(); this._saveOpenedState(); } } /** Closes the popover. */ closePopover(value) { if (this._overlayRef) { this._saveClosedState(value); this._overlayRef.detach(); } } /** TODO: implement when the overlay's position can be dynamically changed */ repositionPopover() { this.updatePopoverConfig(); } /** TODO: when the overlay's position can be dynamically changed, do not destroy */ updatePopoverConfig() { this._destroyPopoverOnceClosed(); } /** Realign the popover to the anchor. */ realignPopoverToAnchor() { if (this._overlayRef) { const config = this._overlayRef.getConfig(); const strategy = config.positionStrategy; strategy.reapplyLastPosition(); } } /** Get a reference to the anchor element. */ getAnchorElement() { return this._anchor; } /** Apply behavior properties on the popover based on the open options. */ _applyOpenOptions(options) { // Only override restoreFocus as `false` if the option is explicitly `false` const restoreFocus = options.restoreFocus !== false; this._popover._restoreFocusOverride = restoreFocus; // Only override autoFocus as `false` if the option is explicitly `false` const autoFocus = options.autoFocus !== false; this._popover._autoFocusOverride = autoFocus; } /** Create an overlay to be attached to the portal. */ _createOverlay() { // Create overlay if it doesn't yet exist if (!this._overlayRef) { this._portal = new TemplatePortal(this._popover._templateRef, this._viewContainerRef); const popoverConfig = { horizontalAlign: this._popover.horizontalAlign, verticalAlign: this._popover.verticalAlign, hasBackdrop: coerceBooleanProperty(this._popover.hasBackdrop), backdropClass: this._popover.backdropClass, scrollStrategy: this._popover.scrollStrategy, forceAlignment: coerceBooleanProperty(this._popover.forceAlignment), lockAlignment: coerceBooleanProperty(this._popover.lockAlignment), panelClass: this._popover.panelClass }; const overlayConfig = this._getOverlayConfig(popoverConfig, this._anchor); this._subscribeToPositionChanges(overlayConfig.positionStrategy); this._overlayRef = this._overlay.create(overlayConfig); } // Actually open the popover this._overlayRef.attach(this._portal); return this._overlayRef; } /** Removes the popover from the DOM. Does NOT update open state. */ _destroyPopover() { if (this._overlayRef) { this._overlayRef.dispose(); this._overlayRef = null; } } /** * Destroys the popover immediately if it is closed, or waits until it * has been closed to destroy it. */ _destroyPopoverOnceClosed() { if (this.isPopoverOpen() && this._overlayRef) { this._overlayRef .detachments() .pipe(take(1), takeUntil(this._onDestroy)) .subscribe(() => this._destroyPopover()); } else { this._destroyPopover(); } } /** Close popover when backdrop is clicked. */ _subscribeToBackdrop() { this._overlayRef .backdropClick() .pipe(tap(() => this._popover.backdropClicked.emit()), filter(() => this._popover.interactiveClose), takeUntil(this.popoverClosed), takeUntil(this._onDestroy)) .subscribe(() => this.closePopover()); } /** Close popover when escape keydown event occurs. */ _subscribeToEscape() { this._overlayRef .keydownEvents() .pipe(tap((event) => this._popover.overlayKeydown.emit(event)), filter((event) => event.keyCode === ESCAPE), filter(() => this._popover.interactiveClose), takeUntil(this.popoverClosed), takeUntil(this._onDestroy)) .subscribe(() => this.closePopover()); } /** Set state back to closed when detached. */ _subscribeToDetachments() { this._overlayRef .detachments() .pipe(takeUntil(this._onDestroy)) .subscribe(() => this._saveClosedState()); } /** Save the opened state of the popover and emit. */ _saveOpenedState() { if (!this._popoverOpen) { this._popover._state = 'enter'; this._popover._open = this._popoverOpen = true; this.popoverOpened.next(); this._popover.opened.emit(); } } /** Save the closed state of the popover and emit. */ _saveClosedState(value) { if (this._popoverOpen) { this._popover._open = this._popoverOpen = false; this._popover._startExitAnimation(); this.popoverClosed.next(value); this._popover.closed.emit(value); } } /** Gets the text direction of the containing app. */ _getDirection() { return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr'; } /** Create and return a config for creating the overlay. */ _getOverlayConfig(config, anchor) { return new OverlayConfig({ positionStrategy: this._getPositionStrategy(config.horizontalAlign, config.verticalAlign, config.forceAlignment, config.lockAlignment, anchor), hasBackdrop: config.hasBackdrop, backdropClass: config.backdropClass || 'cdk-overlay-transparent-backdrop', scrollStrategy: this._getScrollStrategyInstance(config.scrollStrategy), direction: this._getDirection(), panelClass: config.panelClass }); } /** * Listen to changes in the position of the overlay and set the correct alignment classes, * ensuring that the animation origin is correct, even with a fallback position. */ _subscribeToPositionChanges(position) { if (this._positionChangeSubscription) { this._positionChangeSubscription.unsubscribe(); } this._positionChangeSubscription = position.positionChanges.pipe(takeUntil(this._onDestroy)).subscribe((change) => { // Position changes may occur outside the Angular zone this._ngZone.run(() => { this._popover._setAlignmentClasses(getHorizontalPopoverAlignment(change.connectionPair.overlayX), getVerticalPopoverAlignment(change.connectionPair.overlayY)); }); }); } /** Map a scroll strategy string type to an instance of a scroll strategy. */ _getScrollStrategyInstance(strategy) { switch (strategy) { case 'block': return this._overlay.scrollStrategies.block(); case 'reposition': return this._overlay.scrollStrategies.reposition(); case 'close': return this._overlay.scrollStrategies.close(); case 'noop': default: return this._overlay.scrollStrategies.noop(); } } /** Create and return a position strategy based on config provided to the component instance. */ _getPositionStrategy(horizontalTarget, verticalTarget, forceAlignment, lockAlignment, anchor) { // Attach the overlay at the preferred position const targetPosition = getPosition(horizontalTarget, verticalTarget); const positions = [targetPosition]; const strategy = this._overlay .position() .flexibleConnectedTo(anchor) .withFlexibleDimensions(false) .withPush(false) .withViewportMargin(0) .withLockedPosition(lockAlignment); // Unless the alignment is forced, add fallbacks based on the preferred positions if (!forceAlignment) { const fallbacks = this._getFallbacks(horizontalTarget, verticalTarget); positions.push(...fallbacks); } return strategy.withPositions(positions); } /** Get fallback positions based around target alignments. */ _getFallbacks(hTarget, vTarget) { // Determine if the target alignments overlap the anchor const horizontalOverlapAllowed = hTarget !== 'before' && hTarget !== 'after'; const verticalOverlapAllowed = vTarget !== 'above' && vTarget !== 'below'; // If a target alignment doesn't cover the anchor, don't let any of the fallback alignments // cover the anchor const possibleHorizontalAlignments = horizontalOverlapAllowed ? ['before', 'start', 'center', 'end', 'after'] : ['before', 'after']; const possibleVerticalAlignments = verticalOverlapAllowed ? ['above', 'start', 'center', 'end', 'below'] : ['above', 'below']; // Create fallbacks for each allowed prioritized fallback alignment combo const fallbacks = []; prioritizeAroundTarget(hTarget, possibleHorizontalAlignments).forEach((h) => { prioritizeAroundTarget(vTarget, possibleVerticalAlignments).forEach((v) => { fallbacks.push(getPosition(h, v)); }); }); // Remove the first item since it will be the target alignment and isn't considered a fallback return fallbacks.slice(1, fallbacks.length); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: SatPopoverAnchoringService, deps: [{ token: i1.Overlay }, { token: i0.NgZone }, { token: i2.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: SatPopoverAnchoringService }); } export { SatPopoverAnchoringService }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: SatPopoverAnchoringService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.Overlay }, { type: i0.NgZone }, { type: i2.Directionality, decorators: [{ type: Optional }] }]; } }); /** Helper function to get a cdk position pair from SatPopover alignments. */ function getPosition(h, v) { const { originX, overlayX } = getHorizontalConnectionPosPair(h); const { originY, overlayY } = getVerticalConnectionPosPair(v); return new ConnectionPositionPair({ originX, originY }, { overlayX, overlayY }); } /** Helper function to convert an overlay connection position to equivalent popover alignment. */ function getHorizontalPopoverAlignment(h) { if (h === 'start') { return 'after'; } if (h === 'end') { return 'before'; } return 'center'; } /** Helper function to convert an overlay connection position to equivalent popover alignment. */ function getVerticalPopoverAlignment(v) { if (v === 'top') { return 'below'; } if (v === 'bottom') { return 'above'; } return 'center'; } /** Helper function to convert alignment to origin/overlay position pair. */ function getHorizontalConnectionPosPair(h) { switch (h) { case 'before': return { originX: 'start', overlayX: 'end' }; case 'start': return { originX: 'start', overlayX: 'start' }; case 'end': return { originX: 'end', overlayX: 'end' }; case 'after': return { originX: 'end', overlayX: 'start' }; default: return { originX: 'center', overlayX: 'center' }; } } /** Helper function to convert alignment to origin/overlay position pair. */ function getVerticalConnectionPosPair(v) { switch (v) { case 'above': return { originY: 'top', overlayY: 'bottom' }; case 'start': return { originY: 'top', overlayY: 'top' }; case 'end': return { originY: 'bottom', overlayY: 'bottom' }; case 'below': return { originY: 'bottom', overlayY: 'top' }; default: return { originY: 'center', overlayY: 'center' }; } } /** * Helper function that takes an ordered array options and returns a reorderded * array around the target item. e.g.: * * target: 3; options: [1, 2, 3, 4, 5, 6, 7]; * * return: [3, 4, 2, 5, 1, 6, 7] */ function prioritizeAroundTarget(target, options) { const targetIndex = options.indexOf(target); // Set the first item to be the target const reordered = [target]; // Make left and right stacks where the highest priority item is last const left = options.slice(0, targetIndex); const right = options.slice(targetIndex + 1, options.length).reverse(); // Alternate between stacks until one is empty while (left.length && right.length) { reordered.push(right.pop()); reordered.push(left.pop()); } // Flush out right side while (right.length) { reordered.push(right.pop()); } // Flush out left side while (left.length) { reordered.push(left.pop()); } return reordered; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wb3Zlci1hbmNob3Jpbmcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcG9wb3Zlci9wb3BvdmVyLWFuY2hvcmluZy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFxQixRQUFRLEVBQW9CLE1BQU0sZUFBZSxDQUFDO0FBQ3RHLE9BQU8sRUFDTCxzQkFBc0IsRUFJdEIsYUFBYSxFQUlkLE1BQU0sc0JBQXNCLENBQUM7QUFFOUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RCxPQUFPLEVBQWdCLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3QyxPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUF5QjlELE1BQ2EsMEJBQTBCO0lBa0NqQjtJQUEyQjtJQUFxQztJQWpDcEYsd0NBQXdDO0lBQ3hDLGFBQWEsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0lBRXBDLHdDQUF3QztJQUN4QyxhQUFhLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQUVwQyxpRUFBaUU7SUFDakUsV0FBVyxDQUFhO0lBRXhCLHVDQUF1QztJQUMvQixRQUFRLENBQWE7SUFFN0IsZ0VBQWdFO0lBQ3hELGlCQUFpQixDQUFtQjtJQUU1Qyx1Q0FBdUM7SUFDL0IsT0FBTyxDQUFjO0lBRTdCLHlFQUF5RTtJQUNqRSxPQUFPLENBQXNCO0lBRXJDLDJEQUEyRDtJQUNuRCwwQkFBMEIsQ0FBZTtJQUVqRCwrQ0FBK0M7SUFDdkMsMkJBQTJCLENBQWU7SUFFbEQsNkNBQTZDO0lBQ3JDLFlBQVks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LENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7S0FDN0I7SUFFRCxzQkFBc0I7SUFDdEIsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ2xCLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7S0FDNUI7SUFFRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRWxlbWVudFJlZiwgSW5qZWN0YWJsZSwgTmdab25lLCBPbkRlc3Ryb3ksIE9wdGlvbmFsLCBWaWV3Q29udGFpbmVyUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBDb25uZWN0aW9uUG9zaXRpb25QYWlyLFxuICBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3ksXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxuICBPdmVybGF5LFxuICBPdmVybGF5Q29uZmlnLFxuICBPdmVybGF5UmVmLFxuICBTY3JvbGxTdHJhdGVneSxcbiAgVmVydGljYWxDb25uZWN0aW9uUG9zXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7IERpcmVjdGlvbmFsaXR5LCBEaXJlY3Rpb24gfSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQgeyBFU0NBUEUgfSBmcm9tICdAYW5ndWxhci9jZGsva2V5Y29kZXMnO1xuaW1wb3J0IHsgVGVtcGxhdGVQb3J0YWwgfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcbmltcG9ydCB7IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCwgdGFrZSwgZmlsdGVyLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFNhdFBvcG92ZXIgfSBmcm9tICcuL3BvcG92ZXIuY29tcG9uZW50JztcbmltcG9ydCB7XG4gIFNhdFBvcG92ZXJIb3Jpem9udGFsQWxpZ24sXG4gIFNhdFBvcG92ZXJWZXJ0aWNhbEFsaWduLFxuICBTYXRQb3BvdmVyU2Nyb2xsU3RyYXRlZ3ksXG4gIFNhdFBvcG92ZXJPcGVuT3B0aW9uc1xufSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIHByb3ZpZGVkIGJ5IHRoZSBwb3BvdmVyIGZvciB0aGUgYW5jaG9yaW5nIHNlcnZpY2VcbiAqIHRvIGJ1aWxkIHRoZSBjb3JyZWN0IG92ZXJsYXkgY29uZmlnLlxuICovXG5pbnRlcmZhY2UgUG9wb3ZlckNvbmZpZyB7XG4gIGhvcml6b250YWxBbGlnbjogU2F0UG9wb3Zlckhvcml6b250YWxBbGlnbjtcbiAgdmVydGljYWxBbGlnbjogU2F0UG9wb3ZlclZlcnRpY2FsQWxpZ247XG4gIGhhc0JhY2tkcm9wOiBib29sZWFuO1xuICBiYWNrZHJvcENsYXNzOiBzdHJpbmc7XG4gIHNjcm9sbFN0cmF0ZWd5OiBTYXRQb3BvdmVyU2Nyb2xsU3RyYXRlZ3k7XG4gIGZvcmNlQWxpZ25tZW50OiBib29sZWFuO1xuICBsb2NrQWxpZ25tZW50OiBib29sZWFuO1xuICBwYW5lbENsYXNzOiBzdHJpbmcgfCBzdHJpbmdbXTtcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNhdFBvcG92ZXJBbmNob3JpbmdTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHBvcG92ZXIgaXMgb3BlbmVkLiAqL1xuICBwb3BvdmVyT3BlbmVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgcG9wb3ZlciBpcyBjbG9zZWQuICovXG4gIHBvcG92ZXJDbG9zZWQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIG92ZXJsYXkgY29udGFpbmluZyB0aGUgcG9wb3ZlciBjb21wb25lbnQuICovXG4gIF9vdmVybGF5UmVmOiBPdmVybGF5UmVmO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHRhcmdldCBwb3BvdmVyLiAqL1xuICBwcml2YXRlIF9wb3BvdmVyOiBTYXRQb3BvdmVyO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHZpZXcgY29udGFpbmVyIGZvciB0aGUgcG9wb3ZlciB0ZW1wbGF0ZS4gKi9cbiAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZjtcblxuICAvKiogUmVmZXJlbmNlIHRvIHRoZSBhbmNob3IgZWxlbWVudC4gKi9cbiAgcHJpdmF0ZSBfYW5jaG9yOiBIVE1MRWxlbWVudDtcblxuICAvKiogUmVmZXJlbmNlIHRvIGEgdGVtcGxhdGUgcG9ydGFsIHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgYmUgYXR0YWNoZWQuICovXG4gIHByaXZhdGUgX3BvcnRhbDogVGVtcGxhdGVQb3J0YWw8YW55PjtcblxuICAvKiogU2luZ2xlIHN1YnNjcmlwdGlvbiB0byBub3RpZmljYXRpb25zIHNlcnZpY2UgZXZlbnRzLiAqL1xuICBwcml2YXRlIF9ub3RpZmljYXRpb25zU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgLyoqIFNpbmdsZSBzdWJzY3JpcHRpb24gdG8gcG9zaXRpb24gY2hhbmdlcy4gKi9cbiAgcHJpdmF0ZSBfcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuICAvKiogV2hldGhlciB0aGUgcG9wb3ZlciBpcyBwcmVzZW50bHkgb3Blbi4gKi9cbiAgcHJpdmF0ZSBfcG9wb3Zlck9wZW4gPSBmYWxzZTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgc2VydmljZSBpcyBkZXN0cm95ZWQuICovXG4gIHByaXZhdGUgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfb3ZlcmxheTogT3ZlcmxheSwgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsIEBPcHRpb25hbCgpIHByaXZhdGUgX2RpcjogRGlyZWN0aW9uYWxpdHkpIHt9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgLy8gRGVzdHJveSBwb3BvdmVyIGJlZm9yZSB0ZXJtaW5hdGluZyBzdWJzY3JpcHRpb25zIHNvIHRoYXQgYW55IHJlc3VsdGluZ1xuICAgIC8vIGRldGFjaG1lbnRzIHVwZGF0ZSAnY2xvc2VkIHN0YXRlJ1xuICAgIHRoaXMuX2Rlc3Ryb3lQb3BvdmVyKCk7XG5cbiAgICAvLyBUZXJtaW5hdGUgc3Vic2NyaXB0aW9uc1xuICAgIGlmICh0aGlzLl9ub3RpZmljYXRpb25zU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9ub3RpZmljYXRpb25zU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9wb3NpdGlvbkNoYW5nZVN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5fcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcblxuICAgIHRoaXMucG9wb3Zlck9wZW5lZC5jb21wbGV0ZSgpO1xuICAgIHRoaXMucG9wb3ZlckNsb3NlZC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgLyoqIEFuY2hvciBhIHBvcG92ZXIgaW5zdGFuY2UgdG8gYSB2aWV3IGFuZCBjb25uZWN0aW9uIGVsZW1lbnQuICovXG4gIGFuY2hvcihwb3BvdmVyOiBTYXRQb3BvdmVyLCB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLCBhbmNob3I6IEVsZW1lbnRSZWYgfCBIVE1MRWxlbWVudCk6IHZvaWQge1xuICAgIC8vIElmIHdlJ3JlIGp1c3QgY2hhbmdpbmcgdGhlIGFuY2hvciBlbGVtZW50IGFuZCB0aGUgb3ZlcmxheVJlZiBhbHJlYWR5IGV4aXN0cyxcbiAgICAvLyBzaW1wbHkgdXBkYXRlIHRoZSBleGlzdGluZyBfb3ZlcmxheVJlZidzIGFuY2hvci5cbiAgICBpZiAodGhpcy5fcG9wb3ZlciA9PT0gcG9wb3ZlciAmJiB0aGlzLl92aWV3Q29udGFpbmVyUmVmID09PSB2aWV3Q29udGFpbmVyUmVmICYmIHRoaXMuX292ZXJsYXlSZWYpIHtcbiAgICAgIHRoaXMuX2FuY2hvciA9IGFuY2hvciBpbnN0YW5jZW9mIEVsZW1lbnRSZWYgPyBhbmNob3IubmF0aXZlRWxlbWVudCA6IGFuY2hvcjtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCk7XG4gICAgICBjb25zdCBzdHJhdGVneSA9IGNvbmZpZy5wb3NpdGlvblN0cmF0ZWd5IGFzIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneTtcbiAgICAgIHN0cmF0ZWd5LnNldE9yaWdpbih0aGlzLl9hbmNob3IpO1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZi51cGRhdGVQb3NpdGlvbigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIERlc3Ryb3kgYW55IHByZXZpb3VzIHBvcG92ZXJzXG4gICAgdGhpcy5fZGVzdHJveVBvcG92ZXIoKTtcblxuICAgIC8vIEFzc2lnbiBsb2NhbCByZWZzXG4gICAgdGhpcy5fcG9wb3ZlciA9IHBvcG92ZXI7XG4gICAgdGhpcy5fdmlld0NvbnRhaW5lclJlZiA9IHZpZXdDb250YWluZXJSZWY7XG4gICAgdGhpcy5fYW5jaG9yID0gYW5jaG9yIGluc3RhbmNlb2YgRWxlbWVudFJlZiA/IGFuY2hvci5uYXRpdmVFbGVtZW50IDogYW5jaG9yO1xuICB9XG5cbiAgLyoqIEdldHMgd2hldGhlciB0aGUgcG9wb3ZlciBpcyBwcmVzZW50bHkgb3Blbi4gKi9cbiAgaXNQb3BvdmVyT3BlbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fcG9wb3Zlck9wZW47XG4gIH1cblxuICAvKiogVG9nZ2xlcyB0aGUgcG9wb3ZlciBiZXR3ZWVuIHRoZSBvcGVuIGFuZCBjbG9zZWQgc3RhdGVzLiAqL1xuICB0b2dnbGVQb3BvdmVyKCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLl9wb3BvdmVyT3BlbiA/IHRoaXMuY2xvc2VQb3BvdmVyKCkgOiB0aGlzLm9wZW5Qb3BvdmVyKCk7XG4gIH1cblxuICAvKiogT3BlbnMgdGhlIHBvcG92ZXIuICovXG4gIG9wZW5Qb3BvdmVyKG9wdGlvbnM6IFNhdFBvcG92ZXJPcGVuT3B0aW9ucyA9IHt9KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9wb3BvdmVyT3Blbikge1xuICAgICAgdGhpcy5fYXBwbHlPcGVuT3B0aW9ucyhvcHRpb25zKTtcbiAgICAgIHRoaXMuX2NyZWF0ZU92ZXJsYXkoKTtcbiAgICAgIHRoaXMuX3N1YnNjcmliZVRvQmFja2Ryb3AoKTtcbiAgICAgIHRoaXMuX3N1YnNjcmliZVRvRXNjYXBlKCk7XG4gICAgICB0aGlzLl9zdWJzY3JpYmVUb0RldGFjaG1lbnRzKCk7XG4gICAgICB0aGlzLl9zYXZlT3BlbmVkU3RhdGUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xvc2VzIHRoZSBwb3BvdmVyLiAqL1xuICBjbG9zZVBvcG92ZXIodmFsdWU/OiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgdGhpcy5fc2F2ZUNsb3NlZFN0YXRlKHZhbHVlKTtcbiAgICAgIHRoaXMuX292ZXJsYXlSZWYuZGV0YWNoKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFRPRE86IGltcGxlbWVudCB3aGVuIHRoZSBvdmVybGF5J3MgcG9zaXRpb24gY2FuIGJlIGR5bmFtaWNhbGx5IGNoYW5nZWQgKi9cbiAgcmVwb3NpdGlvblBvcG92ZXIoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVQb3BvdmVyQ29uZmlnKCk7XG4gIH1cblxuICAvKiogVE9ETzogd2hlbiB0aGUgb3ZlcmxheSdzIHBvc2l0aW9uIGNhbiBiZSBkeW5hbWljYWxseSBjaGFuZ2VkLCBkbyBub3QgZGVzdHJveSAqL1xuICB1cGRhdGVQb3BvdmVyQ29uZmlnKCk6IHZvaWQge1xuICAgIHRoaXMuX2Rlc3Ryb3lQb3BvdmVyT25jZUNsb3NlZCgpO1xuICB9XG5cbiAgLyoqIFJlYWxpZ24gdGhlIHBvcG92ZXIgdG8gdGhlIGFuY2hvci4gKi9cbiAgcmVhbGlnblBvcG92ZXJUb0FuY2hvcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgY29uc3QgY29uZmlnID0gdGhpcy5fb3ZlcmxheVJlZi5nZXRDb25maWcoKTtcbiAgICAgIGNvbnN0IHN0cmF0ZWd5ID0gY29uZmlnLnBvc2l0aW9uU3RyYXRlZ3kgYXMgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5O1xuICAgICAgc3RyYXRlZ3kucmVhcHBseUxhc3RQb3NpdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBHZXQgYSByZWZlcmVuY2UgdG8gdGhlIGFuY2hvciBlbGVtZW50LiAqL1xuICBnZXRBbmNob3JFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5fYW5jaG9yO1xuICB9XG5cbiAgLyoqIEFwcGx5IGJlaGF2aW9yIHByb3BlcnRpZXMgb24gdGhlIHBvcG92ZXIgYmFzZWQgb24gdGhlIG9wZW4gb3B0aW9ucy4gKi9cbiAgcHJpdmF0ZSBfYXBwbHlPcGVuT3B0aW9ucyhvcHRpb25zOiBTYXRQb3BvdmVyT3Blbk9wdGlvbnMpOiB2b2lkIHtcbiAgICAvLyBPbmx5IG92ZXJyaWRlIHJlc3RvcmVGb2N1cyBhcyBgZmFsc2VgIGlmIHRoZSBvcHRpb24gaXMgZXhwbGljaXRseSBgZmFsc2VgXG4gICAgY29uc3QgcmVzdG9yZUZvY3VzID0gb3B0aW9ucy5yZXN0b3JlRm9jdXMgIT09IGZhbHNlO1xuICAgIHRoaXMuX3BvcG92ZXIuX3Jlc3RvcmVGb2N1c092ZXJyaWRlID0gcmVzdG9yZUZvY3VzO1xuXG4gICAgLy8gT25seSBvdmVycmlkZSBhdXRvRm9jdXMgYXMgYGZhbHNlYCBpZiB0aGUgb3B0aW9uIGlzIGV4cGxpY2l0bHkgYGZhbHNlYFxuICAgIGNvbnN0IGF1dG9Gb2N1cyA9IG9wdGlvbnMuYXV0b0ZvY3VzICE9PSBmYWxzZTtcbiAgICB0aGlzLl9wb3BvdmVyLl9hdXRvRm9jdXNPdmVycmlkZSA9IGF1dG9Gb2N1cztcbiAgfVxuXG4gIC8qKiBDcmVhdGUgYW4gb3ZlcmxheSB0byBiZSBhdHRhY2hlZCB0byB0aGUgcG9ydGFsLiAqL1xuICBwcml2YXRlIF9jcmVhdGVPdmVybGF5KCk6IE92ZXJsYXlSZWYge1xuICAgIC8vIENyZWF0ZSBvdmVybGF5IGlmIGl0IGRvZXNuJ3QgeWV0IGV4aXN0XG4gICAgaWYgKCF0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICB0aGlzLl9wb3J0YWwgPSBuZXcgVGVtcGxhdGVQb3J0YWwodGhpcy5fcG9wb3Zlci5fdGVtcGxhdGVSZWYsIHRoaXMuX3ZpZXdDb250YWluZXJSZWYpO1xuXG4gICAgICBjb25zdCBwb3BvdmVyQ29uZmlnOiBQb3BvdmVyQ29uZmlnID0ge1xuICAgICAgICBob3Jpem9udGFsQWxpZ246IHRoaXMuX3BvcG92ZXIuaG9yaXpvbnRhbEFsaWduLFxuICAgICAgICB2ZXJ0aWNhbEFsaWduOiB0aGlzLl9wb3BvdmVyLnZlcnRpY2FsQWxpZ24sXG4gICAgICAgIGhhc0JhY2tkcm9wOiBjb2VyY2VCb29sZWFuUHJvcGVydHkodGhpcy5fcG9wb3Zlci5oYXNCYWNrZHJvcCksXG4gICAgICAgIGJhY2tkcm9wQ2xhc3M6IHRoaXMuX3BvcG92ZXIuYmFja2Ryb3BDbGFzcyxcbiAgICAgICAgc2Nyb2xsU3RyYXRlZ3k6IHRoaXMuX3BvcG92ZXIuc2Nyb2xsU3RyYXRlZ3ksXG4gICAgICAgIGZvcmNlQWxpZ25tZW50OiBjb2VyY2VCb29sZWFuUHJvcGVydHkodGhpcy5fcG9wb3Zlci5mb3JjZUFsaWdubWVudCksXG4gICAgICAgIGxvY2tBbGlnbm1lbnQ6IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh0aGlzLl9wb3BvdmVyLmxvY2tBbGlnbm1lbnQpLFxuICAgICAgICBwYW5lbENsYXNzOiB0aGlzLl9wb3BvdmVyLnBhbmVsQ2xhc3NcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG92ZXJsYXlDb25maWcgPSB0aGlzLl9nZXRPdmVybGF5Q29uZmlnKHBvcG92ZXJDb25maWcsIHRoaXMuX2FuY2hvcik7XG5cbiAgICAgIHRoaXMuX3N1YnNjcmliZVRvUG9zaXRpb25DaGFuZ2VzKG92ZXJsYXlDb25maWcucG9zaXRpb25TdHJhdGVneSBhcyBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kpO1xuXG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gdGhpcy5fb3ZlcmxheS5jcmVhdGUob3ZlcmxheUNvbmZpZyk7XG4gICAgfVxuXG4gICAgLy8gQWN0dWFsbHkgb3BlbiB0aGUgcG9wb3ZlclxuICAgIHRoaXMuX292ZXJsYXlSZWYuYXR0YWNoKHRoaXMuX3BvcnRhbCk7XG4gICAgcmV0dXJuIHRoaXMuX292ZXJsYXlSZWY7XG4gIH1cblxuICAvKiogUmVtb3ZlcyB0aGUgcG9wb3ZlciBmcm9tIHRoZSBET00uIERvZXMgTk9UIHVwZGF0ZSBvcGVuIHN0YXRlLiAqL1xuICBwcml2YXRlIF9kZXN0cm95UG9wb3ZlcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZi5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVzdHJveXMgdGhlIHBvcG92ZXIgaW1tZWRpYXRlbHkgaWYgaXQgaXMgY2xvc2VkLCBvciB3YWl0cyB1bnRpbCBpdFxuICAgKiBoYXMgYmVlbiBjbG9zZWQgdG8gZGVzdHJveSBpdC5cbiAgICovXG4gIHByaXZhdGUgX2Rlc3Ryb3lQb3BvdmVyT25jZUNsb3NlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1BvcG92ZXJPcGVuKCkgJiYgdGhpcy5fb3ZlcmxheVJlZikge1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZlxuICAgICAgICAuZGV0YWNobWVudHMoKVxuICAgICAgICAucGlwZSh0YWtlKDEpLCB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9kZXN0cm95UG9wb3ZlcigpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZGVzdHJveVBvcG92ZXIoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xvc2UgcG9wb3ZlciB3aGVuIGJhY2tkcm9wIGlzIGNsaWNrZWQuICovXG4gIHByaXZhdGUgX3N1YnNjcmliZVRvQmFja2Ryb3AoKTogdm9pZCB7XG4gICAgdGhpcy5fb3ZlcmxheVJlZlxuICAgICAgLmJhY2tkcm9wQ2xpY2soKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgoKSA9PiB0aGlzLl9wb3BvdmVyLmJhY2tkcm9wQ2xpY2tlZC5lbWl0KCkpLFxuICAgICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5fcG9wb3Zlci5pbnRlcmFjdGl2ZUNsb3NlKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMucG9wb3ZlckNsb3NlZCksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuY2xvc2VQb3BvdmVyKCkpO1xuICB9XG5cbiAgLyoqIENsb3NlIHBvcG92ZXIgd2hlbiBlc2NhcGUga2V5ZG93biBldmVudCBvY2N1cnMuICovXG4gIHByaXZhdGUgX3N1YnNjcmliZVRvRXNjYXBlKCk6IHZvaWQge1xuICAgIHRoaXMuX292ZXJsYXlSZWZcbiAgICAgIC5rZXlkb3duRXZlbnRzKClcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKGV2ZW50KSA9PiB0aGlzLl9wb3BvdmVyLm92ZXJsYXlLZXlkb3duLmVtaXQoZXZlbnQpKSxcbiAgICAgICAgZmlsdGVyKChldmVudCkgPT4gZXZlbnQua2V5Q29kZSA9PT0gRVNDQVBFKSxcbiAgICAgICAgZmlsdGVyKCgpID0+IHRoaXMuX3BvcG92ZXIuaW50ZXJhY3RpdmVDbG9zZSksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLnBvcG92ZXJDbG9zZWQpLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNsb3NlUG9wb3ZlcigpKTtcbiAgfVxuXG4gIC8qKiBTZXQgc3RhdGUgYmFjayB0byBjbG9zZWQgd2hlbiBkZXRhY2hlZC4gKi9cbiAgcHJpdmF0ZSBfc3Vic2NyaWJlVG9EZXRhY2htZW50cygpOiB2b2lkIHtcbiAgICB0aGlzLl9vdmVybGF5UmVmXG4gICAgICAuZGV0YWNobWVudHMoKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuX3NhdmVDbG9zZWRTdGF0ZSgpKTtcbiAgfVxuXG4gIC8qKiBTYXZlIHRoZSBvcGVuZWQgc3RhdGUgb2YgdGhlIHBvcG92ZXIgYW5kIGVtaXQuICovXG4gIHByaXZhdGUgX3NhdmVPcGVuZWRTdGF0ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX3BvcG92ZXJPcGVuKSB7XG4gICAgICB0aGlzLl9wb3BvdmVyLl9zdGF0ZSA9ICdlbnRlcic7XG4gICAgICB0aGlzLl9wb3BvdmVyLl9vcGVuID0gdGhpcy5fcG9wb3Zlck9wZW4gPSB0cnVlO1xuXG4gICAgICB0aGlzLnBvcG92ZXJPcGVuZWQubmV4dCgpO1xuICAgICAgdGhpcy5fcG9wb3Zlci5vcGVuZWQuZW1pdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTYXZlIHRoZSBjbG9zZWQgc3RhdGUgb2YgdGhlIHBvcG92ZXIgYW5kIGVtaXQuICovXG4gIHByaXZhdGUgX3NhdmVDbG9zZWRTdGF0ZSh2YWx1ZT86IGFueSk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9wb3BvdmVyT3Blbikge1xuICAgICAgdGhpcy5fcG9wb3Zlci5fb3BlbiA9IHRoaXMuX3BvcG92ZXJPcGVuID0gZmFsc2U7XG5cbiAgICAgIHRoaXMuX3BvcG92ZXIuX3N0YXJ0RXhpdEFuaW1hdGlvbigpO1xuICAgICAgdGhpcy5wb3BvdmVyQ2xvc2VkLm5leHQodmFsdWUpO1xuICAgICAgdGhpcy5fcG9wb3Zlci5jbG9zZWQuZW1pdCh2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEdldHMgdGhlIHRleHQgZGlyZWN0aW9uIG9mIHRoZSBjb250YWluaW5nIGFwcC4gKi9cbiAgcHJpdmF0ZSBfZ2V0RGlyZWN0aW9uKCk6IERpcmVjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX2RpciAmJiB0aGlzLl9kaXIudmFsdWUgPT09ICdydGwnID8gJ3J0bCcgOiAnbHRyJztcbiAgfVxuXG4gIC8qKiBDcmVhdGUgYW5kIHJldHVybiBhIGNvbmZpZyBmb3IgY3JlYXRpbmcgdGhlIG92ZXJsYXkuICovXG4gIHByaXZhdGUgX2dldE92ZXJsYXlDb25maWcoY29uZmlnOiBQb3BvdmVyQ29uZmlnLCBhbmNob3I6IEhUTUxFbGVtZW50KTogT3ZlcmxheUNvbmZpZyB7XG4gICAgcmV0dXJuIG5ldyBPdmVybGF5Q29uZmlnKHtcbiAgICAgIHBvc2l0aW9uU3RyYXRlZ3k6IHRoaXMuX2dldFBvc2l0aW9uU3RyYXRlZ3koXG4gICAgICAgIGNvbmZpZy5ob3Jpem9udGFsQWxpZ24sXG4gICAgICAgIGNvbmZpZy52ZXJ0aWNhbEFsaWduLFxuICAgICAgICBjb25maWcuZm9yY2VBbGlnbm1lbnQsXG4gICAgICAgIGNvbmZpZy5sb2NrQWxpZ25tZW50LFxuICAgICAgICBhbmNob3JcbiAgICAgICksXG4gICAgICBoYXNCYWNrZHJvcDogY29uZmlnLmhhc0JhY2tkcm9wLFxuICAgICAgYmFja2Ryb3BDbGFzczogY29uZmlnLmJhY2tkcm9wQ2xhc3MgfHwgJ2Nkay1vdmVybGF5LXRyYW5zcGFyZW50LWJhY2tkcm9wJyxcbiAgICAgIHNjcm9sbFN0cmF0ZWd5OiB0aGlzLl9nZXRTY3JvbGxTdHJhdGVneUluc3RhbmNlKGNvbmZpZy5zY3JvbGxTdHJhdGVneSksXG4gICAgICBkaXJlY3Rpb246IHRoaXMuX2dldERpcmVjdGlvbigpLFxuICAgICAgcGFuZWxDbGFzczogY29uZmlnLnBhbmVsQ2xhc3NcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0ZW4gdG8gY2hhbmdlcyBpbiB0aGUgcG9zaXRpb24gb2YgdGhlIG92ZXJsYXkgYW5kIHNldCB0aGUgY29ycmVjdCBhbGlnbm1lbnQgY2xhc3NlcyxcbiAgICogZW5zdXJpbmcgdGhhdCB0aGUgYW5pbWF0aW9uIG9yaWdpbiBpcyBjb3JyZWN0LCBldmVuIHdpdGggYSBmYWxsYmFjayBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX3N1YnNjcmliZVRvUG9zaXRpb25DaGFuZ2VzKHBvc2l0aW9uOiBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuX3Bvc2l0aW9uQ2hhbmdlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fcG9zaXRpb25DaGFuZ2VTdWJzY3JpcHRpb24gPSBwb3NpdGlvbi5wb3NpdGlvbkNoYW5nZXMucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKChjaGFuZ2UpID0+IHtcbiAgICAgIC8vIFBvc2l0aW9uIGNoYW5nZXMgbWF5IG9jY3VyIG91dHNpZGUgdGhlIEFuZ3VsYXIgem9uZVxuICAgICAgdGhpcy5fbmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgIHRoaXMuX3BvcG92ZXIuX3NldEFsaWdubWVudENsYXNzZXMoXG4gICAgICAgICAgZ2V0SG9yaXpvbnRhbFBvcG92ZXJBbGlnbm1lbnQoY2hhbmdlLmNvbm5lY3Rpb25QYWlyLm92ZXJsYXlYKSxcbiAgICAgICAgICBnZXRWZXJ0aWNhbFBvcG92ZXJBbGlnbm1lbnQoY2hhbmdlLmNvbm5lY3Rpb25QYWlyLm92ZXJsYXlZKVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogTWFwIGEgc2Nyb2xsIHN0cmF0ZWd5IHN0cmluZyB0eXBlIHRvIGFuIGluc3RhbmNlIG9mIGEgc2Nyb2xsIHN0cmF0ZWd5LiAqL1xuICBwcml2YXRlIF9nZXRTY3JvbGxTdHJhdGVneUluc3RhbmNlKHN0cmF0ZWd5OiBTYXRQb3BvdmVyU2Nyb2xsU3RyYXRlZ3kpOiBTY3JvbGxTdHJhdGVneSB7XG4gICAgc3dpdGNoIChzdHJhdGVneSkge1xuICAgICAgY2FzZSAnYmxvY2snOlxuICAgICAgICByZXR1cm4gdGhpcy5fb3ZlcmxheS5zY3JvbGxTdHJhdGVnaWVzLmJsb2NrKCk7XG4gICAgICBjYXNlICdyZXBvc2l0aW9uJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX292ZXJsYXkuc2Nyb2xsU3RyYXRlZ2llcy5yZXBvc2l0aW9uKCk7XG4gICAgICBjYXNlICdjbG9zZSc6XG4gICAgICAgIHJldHVybiB0aGlzLl9vdmVybGF5LnNjcm9sbFN0cmF0ZWdpZXMuY2xvc2UoKTtcbiAgICAgIGNhc2UgJ25vb3AnOlxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHRoaXMuX292ZXJsYXkuc2Nyb2xsU3RyYXRlZ2llcy5ub29wKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENyZWF0ZSBhbmQgcmV0dXJuIGEgcG9zaXRpb24gc3RyYXRlZ3kgYmFzZWQgb24gY29uZmlnIHByb3ZpZGVkIHRvIHRoZSBjb21wb25lbnQgaW5zdGFuY2UuICovXG4gIHByaXZhdGUgX2dldFBvc2l0aW9uU3RyYXRlZ3koXG4gICAgaG9yaXpvbnRhbFRhcmdldDogU2F0UG9wb3Zlckhvcml6b250YWxBbGlnbixcbiAgICB2ZXJ0aWNhbFRhcmdldDogU2F0UG9wb3ZlclZlcnRpY2FsQWxpZ24sXG4gICAgZm9yY2VBbGlnbm1lbnQ6IGJvb2xlYW4sXG4gICAgbG9ja0FsaWdubWVudDogYm9vbGVhbixcbiAgICBhbmNob3I6IEhUTUxFbGVtZW50XG4gICk6IEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneSB7XG4gICAgLy8gQXR0YWNoIHRoZSBvdmVybGF5IGF0IHRoZSBwcmVmZXJyZWQgcG9zaXRpb25cbiAgICBjb25zdCB0YXJnZXRQb3NpdGlvbiA9IGdldFBvc2l0aW9uKGhvcml6b250YWxUYXJnZXQsIHZlcnRpY2FsVGFyZ2V0KTtcbiAgICBjb25zdCBwb3NpdGlvbnMgPSBbdGFyZ2V0UG9zaXRpb25dO1xuXG4gICAgY29uc3Qgc3RyYXRlZ3kgPSB0aGlzLl9vdmVybGF5XG4gICAgICAucG9zaXRpb24oKVxuICAgICAgLmZsZXhpYmxlQ29ubmVjdGVkVG8oYW5jaG9yKVxuICAgICAgLndpdGhGbGV4aWJsZURpbWVuc2lvbnMoZmFsc2UpXG4gICAgICAud2l0aFB1c2goZmFsc2UpXG4gICAgICAud2l0aFZpZXdwb3J0TWFyZ2luKDApXG4gICAgICAud2l0aExvY2tlZFBvc2l0aW9uKGxvY2tBbGlnbm1lbnQ