UNPKG

ngx-smart-modal-wgv

Version:

Smart modal handler to manage modals and data everywhere in Angular apps.

465 lines 54.4 kB
import { Inject, Injectable, PLATFORM_ID, TemplateRef, Type } from '@angular/core';
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
import { NgxSmartModalComponent } from '../components/ngx-smart-modal.component';
import { NgxSmartModalConfig } from '../config/ngx-smart-modal.config';
import * as i0 from "@angular/core";
import * as i1 from "./ngx-smart-modal-stack.service";
export class NgxSmartModalService {
    constructor(_appRef, _injector, _modalStack, _document, _platformId) {
        this._appRef = _appRef;
        this._injector = _injector;
        this._modalStack = _modalStack;
        this._document = _document;
        this._platformId = _platformId;
        /**
         * Close the latest opened modal if escape key event is emitted
         * @param event The Keyboard Event
         */
        this._escapeKeyboardEvent = (event) => {
            if (event.key === 'Escape') {
                try {
                    const modal = this.getTopOpenedModal();
                    if (!modal.escapable) {
                        return false;
                    }
                    modal.onEscape.emit(modal);
                    this.closeLatestModal();
                    return true;
                }
                catch (e) {
                    return false;
                }
            }
            return false;
        };
        /**
         * While modal is open, the focus stay on it
         * @param event The Keyboar dEvent
         */
        this._trapFocusModal = (event) => {
            if (event.key === 'Tab') {
                try {
                    const modal = this.getTopOpenedModal();
                    if (!modal.nsmDialog.first.nativeElement.contains(document.activeElement)) {
                        event.preventDefault();
                        event.stopPropagation();
                        modal.nsmDialog.first.nativeElement.focus();
                    }
                    return true;
                }
                catch (e) {
                    return false;
                }
            }
            return false;
        };
        this._addEvents();
    }
    /**
     * Add a new modal instance. This step is essential and allows to retrieve any modal at any time.
     * It stores an object that contains the given modal identifier and the modal itself directly in the `modalStack`.
     *
     * @param modalInstance The object that contains the given modal identifier and the modal itself.
     * @param force Optional parameter that forces the overriding of modal instance if it already exists.
     * @returns nothing special.
     */
    addModal(modalInstance, force) {
        this._modalStack.addModal(modalInstance, force);
    }
    /**
     * Retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    getModal(id) {
        return this._modalStack.getModal(id);
    }
    /**
     * Alias of `getModal` to retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    get(id) {
        return this.getModal(id);
    }
    /**
     * Open a given modal
     *
     * @param id The modal identifier used at creation time.
     * @param force Tell the modal to open top of all other opened modals
     */
    open(id, force = false) {
        return this._openModal(this.get(id), force);
    }
    /**
     * Close a given modal
     *
     * @param id The modal identifier used at creation time.
     */
    close(id) {
        return this._closeModal(this.get(id));
    }
    /**
     * Close all opened modals
     */
    closeAll() {
        this.getOpenedModals().forEach((instance) => {
            this._closeModal(instance.modal);
        });
    }
    /**
     * Toggles a given modal
     * If the retrieved modal is opened it closes it, else it opens it.
     *
     * @param id The modal identifier used at creation time.
     * @param force Tell the modal to open top of all other opened modals
     */
    toggle(id, force = false) {
        return this._toggleModal(this.get(id), force);
    }
    /**
     * Retrieve all the created modals.
     *
     * @returns an array that contains all modal instances.
     */
    getModalStack() {
        return this._modalStack.getModalStack();
    }
    /**
     * Retrieve all the opened modals. It looks for all modal instances with their `visible` property set to `true`.
     *
     * @returns an array that contains all the opened modals.
     */
    getOpenedModals() {
        return this._modalStack.getOpenedModals();
    }
    /**
     * Retrieve the opened modal with highest z-index.
     *
     * @returns the opened modal with highest z-index.
     */
    getTopOpenedModal() {
        return this._modalStack.getTopOpenedModal();
    }
    /**
     * Get the higher `z-index` value between all the modal instances. It iterates over the `ModalStack` array and
     * calculates a higher value (it takes the highest index value between all the modal instances and adds 1).
     * Use it to make a modal appear foreground.
     *
     * @returns a higher index from all the existing modal instances.
     */
    getHigherIndex() {
        return this._modalStack.getHigherIndex();
    }
    /**
     * It gives the number of modal instances. It's helpful to know if the modal stack is empty or not.
     *
     * @returns the number of modal instances.
     */
    getModalStackCount() {
        return this._modalStack.getModalStackCount();
    }
    /**
     * Remove a modal instance from the modal stack.
     *
     * @param id The modal identifier.
     * @returns the removed modal instance.
     */
    removeModal(id) {
        const modalInstance = this._modalStack.removeModal(id);
        if (modalInstance) {
            this._destroyModal(modalInstance.modal);
        }
    }
    /**
     * Associate data to an identified modal. If the modal isn't already associated to some data, it creates a new
     * entry in the `modalData` array with its `id` and the given `data`. If the modal already has data, it rewrites
     * them with the new ones. Finally if no modal found it returns an error message in the console and false value
     * as method output.
     *
     * @param data The data you want to associate to the modal.
     * @param id The modal identifier.
     * @param force If true, overrides the previous stored data if there was.
     * @returns true if the given modal exists and the process has been tried, either false.
     */
    setModalData(data, id, force) {
        const modal = this.get(id);
        if (modal) {
            modal.setData(data, force);
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Retrieve modal data by its identifier.
     *
     * @param id The modal identifier used at creation time.
     * @returns the associated modal data.
     */
    getModalData(id) {
        const modal = this.get(id);
        if (modal) {
            return modal.getData();
        }
        return null;
    }
    /**
     * Reset the data attached to a given modal.
     *
     * @param id The modal identifier used at creation time.
     * @returns the removed data or false if modal doesn't exist.
     */
    resetModalData(id) {
        if (this._modalStack.getModalStack().find((o) => o.id === id)) {
            const removed = this.getModal(id).getData();
            this.getModal(id).removeData();
            return removed;
        }
        else {
            return false;
        }
    }
    /**
     * Close the latest opened modal
     */
    closeLatestModal() {
        this.getTopOpenedModal().close();
    }
    /**
     * Create dynamic NgxSmartModalComponent
     * @param vcr A ViewContainerRef reference
     * @param id The modal identifier used at creation time
     * @param content The modal content (string, templateRef or Component)
     * @param options Any NgxSmartModalComponent available options
     */
    create(id, content, vcr, options = {}) {
        try {
            return this.getModal(id);
        }
        catch (e) {
            const ngContent = this._resolveNgContent(content);
            const componentRef = vcr.createComponent(NgxSmartModalComponent, { injector: this._injector, projectableNodes: ngContent });
            if (content instanceof Type) {
                componentRef.instance.contentComponent = content;
            }
            componentRef.instance.identifier = id;
            componentRef.instance.createFrom = 'service';
            if (typeof options.closable === 'boolean') {
                componentRef.instance.closable = options.closable;
            }
            if (typeof options.escapable === 'boolean') {
                componentRef.instance.escapable = options.escapable;
            }
            if (typeof options.dismissable === 'boolean') {
                componentRef.instance.dismissable = options.dismissable;
            }
            if (typeof options.customClass === 'string') {
                componentRef.instance.customClass = options.customClass;
            }
            if (typeof options.backdrop === 'boolean') {
                componentRef.instance.backdrop = options.backdrop;
            }
            if (typeof options.force === 'boolean') {
                componentRef.instance.force = options.force;
            }
            if (typeof options.hideDelay === 'number') {
                componentRef.instance.hideDelay = options.hideDelay;
            }
            if (typeof options.autostart === 'boolean') {
                componentRef.instance.autostart = options.autostart;
            }
            if (typeof options.target === 'string') {
                componentRef.instance.target = options.target;
            }
            if (typeof options.ariaLabel === 'string') {
                componentRef.instance.ariaLabel = options.ariaLabel;
            }
            if (typeof options.ariaLabelledBy === 'string') {
                componentRef.instance.ariaLabelledBy = options.ariaLabelledBy;
            }
            if (typeof options.ariaDescribedBy === 'string') {
                componentRef.instance.ariaDescribedBy = options.ariaDescribedBy;
            }
            if (typeof options.refocus === 'boolean') {
                componentRef.instance.refocus = options.refocus;
            }
            const domElem = componentRef.hostView.rootNodes[0];
            this._document.body.appendChild(domElem);
            return componentRef.instance;
        }
    }
    _addEvents() {
        if (!this.isBrowser) {
            return false;
        }
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'create', ((e) => {
            this._initModal(e.detail.instance);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'delete', ((e) => {
            this._deleteModal(e.detail.instance);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'open', ((e) => {
            this._openModal(e.detail.instance.modal, e.detail.extraData.top);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'toggle', ((e) => {
            this._toggleModal(e.detail.instance.modal, e.detail.extraData.top);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'close', ((e) => {
            this._closeModal(e.detail.instance.modal);
        }));
        window.addEventListener(NgxSmartModalConfig.prefixEvent + 'dismiss', ((e) => {
            this._dismissModal(e.detail.instance.modal);
        }));
        window.addEventListener('keyup', this._escapeKeyboardEvent);
        return true;
    }
    _initModal(modalInstance) {
        modalInstance.modal.layerPosition += this.getModalStackCount();
        this.addModal(modalInstance, modalInstance.modal.force);
        if (modalInstance.modal.autostart) {
            this.open(modalInstance.id);
        }
    }
    _openModal(modal, top) {
        if (modal.visible) {
            return false;
        }
        this.lastElementFocused = document.activeElement;
        if (modal.escapable) {
            window.addEventListener('keyup', this._escapeKeyboardEvent);
        }
        if (modal.backdrop) {
            window.addEventListener('keydown', this._trapFocusModal);
        }
        if (top) {
            modal.layerPosition = this.getHigherIndex();
        }
        modal.addBodyClass();
        modal.overlayVisible = true;
        modal.visible = true;
        modal.onOpen.emit(modal);
        modal.markForCheck();
        setTimeout(() => {
            modal.openedClass = true;
            if (modal.target) {
                modal.targetPlacement();
            }
            modal.nsmDialog.first.nativeElement.setAttribute('role', 'dialog');
            modal.nsmDialog.first.nativeElement.setAttribute('tabIndex', '-1');
            modal.nsmDialog.first.nativeElement.setAttribute('aria-modal', 'true');
            modal.nsmDialog.first.nativeElement.focus();
            modal.markForCheck();
            modal.onOpenFinished.emit(modal);
        });
        return true;
    }
    _toggleModal(modal, top) {
        if (modal.visible) {
            return this._closeModal(modal);
        }
        else {
            return this._openModal(modal, top);
        }
    }
    _closeModal(modal) {
        if (!modal.openedClass) {
            return false;
        }
        modal.openedClass = false;
        modal.onClose.emit(modal);
        modal.onAnyCloseEvent.emit(modal);
        if (this.getOpenedModals().length < 2) {
            modal.removeBodyClass();
            window.removeEventListener('keyup', this._escapeKeyboardEvent);
            window.removeEventListener('keydown', this._trapFocusModal);
        }
        setTimeout(() => {
            modal.visibleChange.emit(modal.visible);
            modal.visible = false;
            modal.overlayVisible = false;
            modal.nsmDialog.first.nativeElement.removeAttribute('tabIndex');
            modal.markForCheck();
            modal.onCloseFinished.emit(modal);
            modal.onAnyCloseEventFinished.emit(modal);
            if (modal.refocus) {
                this.lastElementFocused.focus();
            }
        }, modal.hideDelay);
        return true;
    }
    _dismissModal(modal) {
        if (!modal.openedClass) {
            return false;
        }
        modal.openedClass = false;
        modal.onDismiss.emit(modal);
        modal.onAnyCloseEvent.emit(modal);
        if (this.getOpenedModals().length < 2) {
            modal.removeBodyClass();
        }
        setTimeout(() => {
            modal.visible = false;
            modal.visibleChange.emit(modal.visible);
            modal.overlayVisible = false;
            modal.markForCheck();
            modal.onDismissFinished.emit(modal);
            modal.onAnyCloseEventFinished.emit(modal);
        }, modal.hideDelay);
        return true;
    }
    _deleteModal(modalInstance) {
        this.removeModal(modalInstance.id);
        if (!this.getModalStack().length) {
            modalInstance.modal.removeBodyClass();
        }
    }
    /**
     * Resolve content according to the types
     * @param content The modal content (string, templateRef or Component)
     */
    _resolveNgContent(content) {
        if (typeof content === 'string') {
            const element = this._document.createTextNode(content);
            return [[element]];
        }
        if (content instanceof TemplateRef) {
            const viewRef = content.createEmbeddedView(null);
            this._appRef.attachView(viewRef);
            return [viewRef.rootNodes];
        }
        return [];
    }
    /**
     * Is current platform browser
     */
    get isBrowser() {
        return isPlatformBrowser(this._platformId);
    }
    /**
     * Remove dynamically created modal from DOM
     */
    _destroyModal(modal) {
        // Prevent destruction of the inline modals
        if (modal.createFrom !== 'service') {
            return;
        }
        this._document.body.removeChild(modal.elementRef.nativeElement);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalService, deps: [{ token: i0.ApplicationRef }, { token: i0.Injector }, { token: i1.NgxSmartModalStackService }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.10", ngImport: i0, type: NgxSmartModalService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: function () { return [{ type: i0.ApplicationRef }, { type: i0.Injector }, { type: i1.NgxSmartModalStackService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DOCUMENT]
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [PLATFORM_ID]
                }] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNtYXJ0LW1vZGFsLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnQtbW9kYWwvc3JjL2xpYi9zZXJ2aWNlcy9uZ3gtc21hcnQtbW9kYWwuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQW1DLE1BQU0sRUFBRSxVQUFVLEVBQVksV0FBVyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQW9CLE1BQU0sZUFBZSxDQUFDO0FBQ2hKLE9BQU8sRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNqRixPQUFPLEVBQXlCLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7OztBQVM5RixNQUFNLE9BQU8sb0JBQW9CO0lBRy9CLFlBQ1UsT0FBdUIsRUFDdkIsU0FBbUIsRUFDbkIsV0FBc0MsRUFDcEIsU0FBYyxFQUNYLFdBQWdCO1FBSnJDLFlBQU8sR0FBUCxPQUFPLENBQWdCO1FBQ3ZCLGNBQVMsR0FBVCxTQUFTLENBQVU7UUFDbkIsZ0JBQVcsR0FBWCxXQUFXLENBQTJCO1FBQ3BCLGNBQVMsR0FBVCxTQUFTLENBQUs7UUFDWCxnQkFBVyxHQUFYLFdBQVcsQ0FBSztRQThaL0M7OztXQUdHO1FBQ0sseUJBQW9CLEdBQUcsQ0FBQyxLQUFvQixFQUFFLEVBQUU7WUFDdEQsSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLFFBQVEsRUFBRTtnQkFDMUIsSUFBSTtvQkFDRixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztvQkFFdkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUU7d0JBQ3BCLE9BQU8sS0FBSyxDQUFDO3FCQUNkO29CQUVELEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxD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QUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO1lBQy9CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7U0FDcEI7UUFFRCxJQUFJLE9BQU8sWUFBWSxXQUFXLEVBQUU7WUFDbEMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLElBQVcsQ0FBQyxDQUFDO1lBQ3hELElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDNUI7UUFFRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUEyQkQ7O09BRUc7SUFDSCxJQUFZLFNBQVM7UUFDbkIsT0FBTyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQTBCRDs7T0FFRztJQUNLLGFBQWEsQ0FBQyxLQUE2QjtRQUNqRCwyQ0FBMkM7UUFDM0MsSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLFNBQVMsRUFBRTtZQUNsQyxPQUFPO1NBQ1I7UUFFRCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNsRSxDQUFDOytHQXhlVSxvQkFBb0IsaUhBT3JCLFFBQVEsYUFDUixXQUFXO21IQVJWLG9CQUFvQixjQUZuQixNQUFNOzs0RkFFUCxvQkFBb0I7a0JBSGhDLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25COzswQkFRSSxNQUFNOzJCQUFDLFFBQVE7OzBCQUNmLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFwcGxpY2F0aW9uUmVmLCBFbWJlZGRlZFZpZXdSZWYsIEluamVjdCwgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIFBMQVRGT1JNX0lELCBUZW1wbGF0ZVJlZiwgVHlwZSwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRE9DVU1FTlQsIGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IE5neFNtYXJ0TW9kYWxDb21wb25lbnQgfSBmcm9tICcuLi9jb21wb25lbnRzL25neC1zbWFydC1tb2RhbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgSU5neFNtYXJ0TW9kYWxPcHRpb25zLCBOZ3hTbWFydE1vZGFsQ29uZmlnIH0gZnJvbSAnLi4vY29uZmlnL25neC1zbWFydC1tb2RhbC5jb25maWcnO1xuaW1wb3J0IHsgTmd4U21hcnRNb2RhbFN0YWNrU2VydmljZSB9IGZyb20gJy4vbmd4LXNtYXJ0LW1vZGFsLXN0YWNrLnNlcnZpY2UnO1xuaW1wb3J0IHsgTW9kYWxJbnN0YW5jZSB9IGZyb20gJy4vbW9kYWwtaW5zdGFuY2UnO1xuXG5leHBvcnQgdHlwZSBDb250ZW50PFQ+ID0gc3RyaW5nIHwgVGVtcGxhdGVSZWY8VD4gfCBUeXBlPFQ+O1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBOZ3hTbWFydE1vZGFsU2VydmljZSB7XG4gIHByaXZhdGUgbGFzdEVsZW1lbnRGb2N1c2VkOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYXBwUmVmOiBBcHBsaWNhdGlvblJlZixcbiAgICBwcml2YXRlIF9pbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSBfbW9kYWxTdGFjazogTmd4U21hcnRNb2RhbFN0YWNrU2VydmljZSxcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIF9kb2N1bWVudDogYW55LFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgX3BsYXRmb3JtSWQ6IGFueVxuICApIHtcbiAgICB0aGlzLl9hZGRFdmVudHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBuZXcgbW9kYWwgaW5zdGFuY2UuIFRoaXMgc3RlcCBpcyBlc3NlbnRpYWwgYW5kIGFsbG93cyB0byByZXRyaWV2ZSBhbnkgbW9kYWwgYXQgYW55IHRpbWUuXG4gICAqIEl0IHN0b3JlcyBhbiBvYmplY3QgdGhhdCBjb250YWlucyB0aGUgZ2l2ZW4gbW9kYWwgaWRlbnRpZmllciBhbmQgdGhlIG1vZGFsIGl0c2VsZiBkaXJlY3RseSBpbiB0aGUgYG1vZGFsU3RhY2tgLlxuICAgKlxuICAgKiBAcGFyYW0gbW9kYWxJbnN0YW5jZSBUaGUgb2JqZWN0IHRoYXQgY29udGFpbnMgdGhlIGdpdmVuIG1vZGFsIGlkZW50aWZpZXIgYW5kIHRoZSBtb2RhbCBpdHNlbGYuXG4gICAqIEBwYXJhbSBmb3JjZSBPcHRpb25hbCBwYXJhbWV0ZXIgdGhhdCBmb3JjZXMgdGhlIG92ZXJyaWRpbmcgb2YgbW9kYWwgaW5zdGFuY2UgaWYgaXQgYWxyZWFkeSBleGlzdHMuXG4gICAqIEByZXR1cm5zIG5vdGhpbmcgc3BlY2lhbC5cbiAgICovXG4gIHB1YmxpYyBhZGRNb2RhbChtb2RhbEluc3RhbmNlOiBNb2RhbEluc3RhbmNlLCBmb3JjZT86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLl9tb2RhbFN0YWNrLmFkZE1vZGFsKG1vZGFsSW5zdGFuY2UsIGZvcmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZSBhIG1vZGFsIGluc3RhbmNlIGJ5IGl0cyBpZGVudGlmaWVyLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lLlxuICAgKi9cbiAgcHVibGljIGdldE1vZGFsKGlkOiBzdHJpbmcpOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRNb2RhbChpZCk7XG4gIH1cblxuICAvKipcbiAgICogQWxpYXMgb2YgYGdldE1vZGFsYCB0byByZXRyaWV2ZSBhIG1vZGFsIGluc3RhbmNlIGJ5IGl0cyBpZGVudGlmaWVyLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lLlxuICAgKi9cbiAgcHVibGljIGdldChpZDogc3RyaW5nKTogTmd4U21hcnRNb2RhbENvbXBvbmVudCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0TW9kYWwoaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wZW4gYSBnaXZlbiBtb2RhbFxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lLlxuICAgKiBAcGFyYW0gZm9yY2UgVGVsbCB0aGUgbW9kYWwgdG8gb3BlbiB0b3Agb2YgYWxsIG90aGVyIG9wZW5lZCBtb2RhbHNcbiAgICovXG4gIHB1YmxpYyBvcGVuKGlkOiBzdHJpbmcsIGZvcmNlID0gZmFsc2UpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fb3Blbk1vZGFsKHRoaXMuZ2V0KGlkKSwgZm9yY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIGEgZ2l2ZW4gbW9kYWxcbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBtb2RhbCBpZGVudGlmaWVyIHVzZWQgYXQgY3JlYXRpb24gdGltZS5cbiAgICovXG4gIHB1YmxpYyBjbG9zZShpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2Nsb3NlTW9kYWwodGhpcy5nZXQoaWQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSBhbGwgb3BlbmVkIG1vZGFsc1xuICAgKi9cbiAgcHVibGljIGNsb3NlQWxsKCk6IHZvaWQge1xuICAgIHRoaXMuZ2V0T3BlbmVkTW9kYWxzKCkuZm9yRWFjaCgoaW5zdGFuY2U6IE1vZGFsSW5zdGFuY2UpID0+IHtcbiAgICAgIHRoaXMuX2Nsb3NlTW9kYWwoaW5zdGFuY2UubW9kYWwpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZXMgYSBnaXZlbiBtb2RhbFxuICAgKiBJZiB0aGUgcmV0cmlldmVkIG1vZGFsIGlzIG9wZW5lZCBpdCBjbG9zZXMgaXQsIGVsc2UgaXQgb3BlbnMgaXQuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgbW9kYWwgaWRlbnRpZmllciB1c2VkIGF0IGNyZWF0aW9uIHRpbWUuXG4gICAqIEBwYXJhbSBmb3JjZSBUZWxsIHRoZSBtb2RhbCB0byBvcGVuIHRvcCBvZiBhbGwgb3RoZXIgb3BlbmVkIG1vZGFsc1xuICAgKi9cbiAgcHVibGljIHRvZ2dsZShpZDogc3RyaW5nLCBmb3JjZSA9IGZhbHNlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3RvZ2dsZU1vZGFsKHRoaXMuZ2V0KGlkKSwgZm9yY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGFsbCB0aGUgY3JlYXRlZCBtb2RhbHMuXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIGFycmF5IHRoYXQgY29udGFpbnMgYWxsIG1vZGFsIGluc3RhbmNlcy5cbiAgICovXG4gIHB1YmxpYyBnZXRNb2RhbFN0YWNrKCk6IE1vZGFsSW5zdGFuY2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGFsU3RhY2suZ2V0TW9kYWxTdGFjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGFsbCB0aGUgb3BlbmVkIG1vZGFscy4gSXQgbG9va3MgZm9yIGFsbCBtb2RhbCBpbnN0YW5jZXMgd2l0aCB0aGVpciBgdmlzaWJsZWAgcHJvcGVydHkgc2V0IHRvIGB0cnVlYC5cbiAgICpcbiAgICogQHJldHVybnMgYW4gYXJyYXkgdGhhdCBjb250YWlucyBhbGwgdGhlIG9wZW5lZCBtb2RhbHMuXG4gICAqL1xuICBwdWJsaWMgZ2V0T3BlbmVkTW9kYWxzKCk6IE1vZGFsSW5zdGFuY2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGFsU3RhY2suZ2V0T3BlbmVkTW9kYWxzKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgdGhlIG9wZW5lZCBtb2RhbCB3aXRoIGhpZ2hlc3Qgei1pbmRleC5cbiAgICpcbiAgICogQHJldHVybnMgdGhlIG9wZW5lZCBtb2RhbCB3aXRoIGhpZ2hlc3Qgei1pbmRleC5cbiAgICovXG4gIHB1YmxpYyBnZXRUb3BPcGVuZWRNb2RhbCgpOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50IHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRUb3BPcGVuZWRNb2RhbCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgaGlnaGVyIGB6LWluZGV4YCB2YWx1ZSBiZXR3ZWVuIGFsbCB0aGUgbW9kYWwgaW5zdGFuY2VzLiBJdCBpdGVyYXRlcyBvdmVyIHRoZSBgTW9kYWxTdGFja2AgYXJyYXkgYW5kXG4gICAqIGNhbGN1bGF0ZXMgYSBoaWdoZXIgdmFsdWUgKGl0IHRha2VzIHRoZSBoaWdoZXN0IGluZGV4IHZhbHVlIGJldHdlZW4gYWxsIHRoZSBtb2RhbCBpbnN0YW5jZXMgYW5kIGFkZHMgMSkuXG4gICAqIFVzZSBpdCB0byBtYWtlIGEgbW9kYWwgYXBwZWFyIGZvcmVncm91bmQuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgaGlnaGVyIGluZGV4IGZyb20gYWxsIHRoZSBleGlzdGluZyBtb2RhbCBpbnN0YW5jZXMuXG4gICAqL1xuICBwdWJsaWMgZ2V0SGlnaGVySW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRIaWdoZXJJbmRleCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0IGdpdmVzIHRoZSBudW1iZXIgb2YgbW9kYWwgaW5zdGFuY2VzLiBJdCdzIGhlbHBmdWwgdG8ga25vdyBpZiB0aGUgbW9kYWwgc3RhY2sgaXMgZW1wdHkgb3Igbm90LlxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgbnVtYmVyIG9mIG1vZGFsIGluc3RhbmNlcy5cbiAgICovXG4gIHB1YmxpYyBnZXRNb2RhbFN0YWNrQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kYWxTdGFjay5nZXRNb2RhbFN0YWNrQ291bnQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSBtb2RhbCBpbnN0YW5jZSBmcm9tIHRoZSBtb2RhbCBzdGFjay5cbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBtb2RhbCBpZGVudGlmaWVyLlxuICAgKiBAcmV0dXJucyB0aGUgcmVtb3ZlZCBtb2RhbCBpbnN0YW5jZS5cbiAgICovXG4gIHB1YmxpYyByZW1vdmVNb2RhbChpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbW9kYWxJbnN0YW5jZSA9IHRoaXMuX21vZGFsU3RhY2sucmVtb3ZlTW9kYWwoaWQpO1xuICAgIGlmIChtb2RhbEluc3RhbmNlKSB7XG4gICAgICB0aGlzLl9kZXN0cm95TW9kYWwobW9kYWxJbnN0YW5jZS5tb2RhbCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzc29jaWF0ZSBkYXRhIHRvIGFuIGlkZW50aWZpZWQgbW9kYWwuIElmIHRoZSBtb2RhbCBpc24ndCBhbHJlYWR5IGFzc29jaWF0ZWQgdG8gc29tZSBkYXRhLCBpdCBjcmVhdGVzIGEgbmV3XG4gICAqIGVudHJ5IGluIHRoZSBgbW9kYWxEYXRhYCBhcnJheSB3aXRoIGl0cyBgaWRgIGFuZCB0aGUgZ2l2ZW4gYGRhdGFgLiBJZiB0aGUgbW9kYWwgYWxyZWFkeSBoYXMgZGF0YSwgaXQgcmV3cml0ZXNcbiAgICogdGhlbSB3aXRoIHRoZSBuZXcgb25lcy4gRmluYWxseSBpZiBubyBtb2RhbCBmb3VuZCBpdCByZXR1cm5zIGFuIGVycm9yIG1lc3NhZ2UgaW4gdGhlIGNvbnNvbGUgYW5kIGZhbHNlIHZhbHVlXG4gICAqIGFzIG1ldGhvZCBvdXRwdXQuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHlvdSB3YW50IHRvIGFzc29jaWF0ZSB0byB0aGUgbW9kYWwuXG4gICAqIEBwYXJhbSBpZCBUaGUgbW9kYWwgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIGZvcmNlIElmIHRydWUsIG92ZXJyaWRlcyB0aGUgcHJldmlvdXMgc3RvcmVkIGRhdGEgaWYgdGhlcmUgd2FzLlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBnaXZlbiBtb2RhbCBleGlzdHMgYW5kIHRoZSBwcm9jZXNzIGhhcyBiZWVuIHRyaWVkLCBlaXRoZXIgZmFsc2UuXG4gICAqL1xuICBwdWJsaWMgc2V0TW9kYWxEYXRhKGRhdGE6IGFueSwgaWQ6IHN0cmluZywgZm9yY2U/OiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbW9kYWwgPSB0aGlzLmdldChpZCk7XG4gICAgaWYgKG1vZGFsKSB7XG4gICAgICBtb2RhbC5zZXREYXRhKGRhdGEsIGZvcmNlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIG1vZGFsIGRhdGEgYnkgaXRzIGlkZW50aWZpZXIuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgbW9kYWwgaWRlbnRpZmllciB1c2VkIGF0IGNyZWF0aW9uIHRpbWUuXG4gICAqIEByZXR1cm5zIHRoZSBhc3NvY2lhdGVkIG1vZGFsIGRhdGEuXG4gICAqL1xuICBwdWJsaWMgZ2V0TW9kYWxEYXRhKGlkOiBzdHJpbmcpOiB1bmtub3duIHtcbiAgICBjb25zdCBtb2RhbCA9IHRoaXMuZ2V0KGlkKTtcbiAgICBpZiAobW9kYWwpIHtcbiAgICAgIHJldHVybiBtb2RhbC5nZXREYXRhKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgdGhlIGRhdGEgYXR0YWNoZWQgdG8gYSBnaXZlbiBtb2RhbC5cbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBtb2RhbCBpZGVudGlmaWVyIHVzZWQgYXQgY3JlYXRpb24gdGltZS5cbiAgICogQHJldHVybnMgdGhlIHJlbW92ZWQgZGF0YSBvciBmYWxzZSBpZiBtb2RhbCBkb2Vzbid0IGV4aXN0LlxuICAgKi9cbiAgcHVibGljIHJlc2V0TW9kYWxEYXRhKGlkOiBzdHJpbmcpOiB1bmtub3duIHwgYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuX21vZGFsU3RhY2suZ2V0TW9kYWxTdGFjaygpLmZpbmQoKG86IE1vZGFsSW5zdGFuY2UpID0+IG8uaWQgPT09IGlkKSkge1xuICAgICAgY29uc3QgcmVtb3ZlZDogdW5rbm93biA9IHRoaXMuZ2V0TW9kYWwoaWQpLmdldERhdGEoKTtcbiAgICAgIHRoaXMuZ2V0TW9kYWwoaWQpLnJlbW92ZURhdGEoKTtcbiAgICAgIHJldHVybiByZW1vdmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBsYXRlc3Qgb3BlbmVkIG1vZGFsXG4gICAqL1xuICBwdWJsaWMgY2xvc2VMYXRlc3RNb2RhbCgpOiB2b2lkIHtcbiAgICB0aGlzLmdldFRvcE9wZW5lZE1vZGFsKCkuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgZHluYW1pYyBOZ3hTbWFydE1vZGFsQ29tcG9uZW50XG4gICAqIEBwYXJhbSB2Y3IgQSBWaWV3Q29udGFpbmVyUmVmIHJlZmVyZW5jZVxuICAgKiBAcGFyYW0gaWQgVGhlIG1vZGFsIGlkZW50aWZpZXIgdXNlZCBhdCBjcmVhdGlvbiB0aW1lXG4gICAqIEBwYXJhbSBjb250ZW50IFRoZSBtb2RhbCBjb250ZW50IChzdHJpbmcsIHRlbXBsYXRlUmVmIG9yIENvbXBvbmVudClcbiAgICogQHBhcmFtIG9wdGlvbnMgQW55IE5neFNtYXJ0TW9kYWxDb21wb25lbnQgYXZhaWxhYmxlIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBjcmVhdGU8VD4oaWQ6IHN0cmluZywgY29udGVudDogQ29udGVudDxUPiwgdmNyOiBWaWV3Q29udGFpbmVyUmVmLCBvcHRpb25zOiBJTmd4U21hcnRNb2RhbE9wdGlvbnMgPSB7fSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRNb2RhbChpZCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc3QgbmdDb250ZW50ID0gdGhpcy5fcmVzb2x2ZU5nQ29udGVudChjb250ZW50KTtcblxuICAgICAgY29uc3QgY29tcG9uZW50UmVmID0gdmNyLmNyZWF0ZUNvbXBvbmVudChOZ3hTbWFydE1vZGFsQ29tcG9uZW50LCB7IGluamVjdG9yOiB0aGlzLl9pbmplY3RvciwgcHJvamVjdGFibGVOb2RlczogbmdDb250ZW50IH0pO1xuXG4gICAgICBpZiAoY29udGVudCBpbnN0YW5jZW9mIFR5cGUpIHtcbiAgICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmNvbnRlbnRDb21wb25lbnQgPSBjb250ZW50O1xuICAgICAgfVxuXG4gICAgICBjb21wb25lbnRSZWYuaW5zdGFuY2UuaWRlbnRpZmllciA9IGlkO1xuICAgICAgY29tcG9uZW50UmVmLmluc3RhbmNlLmNyZWF0ZUZyb20gPSAnc2VydmljZSc7XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jbG9zYWJsZSA9PT0gJ2Jvb2xlYW4nKSB7IGNvbXBvbmVudFJlZi5pbnN0YW5jZS5jbG9zYWJsZSA9IG9wdGlvbnMuY2xvc2FibGU7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5lc2NhcGFibGUgPT09ICdib29sZWFuJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UuZXNjYXBhYmxlID0gb3B0aW9ucy5lc2NhcGFibGU7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kaXNtaXNzYWJsZSA9PT0gJ2Jvb2xlYW4nKSB7IGNvbXBvbmVudFJlZi5pbnN0YW5jZS5kaXNtaXNzYWJsZSA9IG9wdGlvbnMuZGlzbWlzc2FibGU7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5jdXN0b21DbGFzcyA9PT0gJ3N0cmluZycpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmN1c3RvbUNsYXNzID0gb3B0aW9ucy5jdXN0b21DbGFzczsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmJhY2tkcm9wID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmJhY2tkcm9wID0gb3B0aW9ucy5iYWNrZHJvcDsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmZvcmNlID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmZvcmNlID0gb3B0aW9ucy5mb3JjZTsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmhpZGVEZWxheSA9PT0gJ251bWJlcicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmhpZGVEZWxheSA9IG9wdGlvbnMuaGlkZURlbGF5OyB9XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMuYXV0b3N0YXJ0ID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLmF1dG9zdGFydCA9IG9wdGlvbnMuYXV0b3N0YXJ0OyB9XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMudGFyZ2V0ID09PSAnc3RyaW5nJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UudGFyZ2V0ID0gb3B0aW9ucy50YXJnZXQ7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5hcmlhTGFiZWwgPT09ICdzdHJpbmcnKSB7IGNvbXBvbmVudFJlZi5pbnN0YW5jZS5hcmlhTGFiZWwgPSBvcHRpb25zLmFyaWFMYWJlbDsgfVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmFyaWFMYWJlbGxlZEJ5ID09PSAnc3RyaW5nJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UuYXJpYUxhYmVsbGVkQnkgPSBvcHRpb25zLmFyaWFMYWJlbGxlZEJ5OyB9XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMuYXJpYURlc2NyaWJlZEJ5ID09PSAnc3RyaW5nJykgeyBjb21wb25lbnRSZWYuaW5zdGFuY2UuYXJpYURlc2NyaWJlZEJ5ID0gb3B0aW9ucy5hcmlhRGVzY3JpYmVkQnk7IH1cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yZWZvY3VzID09PSAnYm9vbGVhbicpIHsgY29tcG9uZW50UmVmLmluc3RhbmNlLnJlZm9jdXMgPSBvcHRpb25zLnJlZm9jdXM7IH1cblxuICAgICAgY29uc3QgZG9tRWxlbSA9IChjb21wb25lbnRSZWYuaG9zdFZpZXcgYXMgRW1iZWRkZWRWaWV3UmVmPGFueT4pLnJvb3ROb2Rlc1swXSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIHRoaXMuX2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZG9tRWxlbSk7XG5cbiAgICAgIHJldHVybiBjb21wb25lbnRSZWYuaW5zdGFuY2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYWRkRXZlbnRzKCk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5pc0Jyb3dzZXIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgJ2NyZWF0ZScsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX2luaXRNb2RhbChlLmRldGFpbC5pbnN0YW5jZSk7XG4gICAgfSkgYXMgRXZlbnRMaXN0ZW5lcik7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgJ2RlbGV0ZScsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX2RlbGV0ZU1vZGFsKGUuZGV0YWlsLmluc3RhbmNlKTtcbiAgICB9KSBhcyBFdmVudExpc3RlbmVyKTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKE5neFNtYXJ0TW9kYWxDb25maWcucHJlZml4RXZlbnQgKyAnb3BlbicsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX29wZW5Nb2RhbChlLmRldGFpbC5pbnN0YW5jZS5tb2RhbCwgZS5kZXRhaWwuZXh0cmFEYXRhLnRvcCk7XG4gICAgfSkgYXMgRXZlbnRMaXN0ZW5lcik7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihOZ3hTbWFydE1vZGFsQ29uZmlnLnByZWZpeEV2ZW50ICsgJ3RvZ2dsZScsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX3RvZ2dsZU1vZGFsKGUuZGV0YWlsLmluc3RhbmNlLm1vZGFsLCBlLmRldGFpbC5leHRyYURhdGEudG9wKTtcbiAgICB9KSBhcyBFdmVudExpc3RlbmVyKTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKE5neFNtYXJ0TW9kYWxDb25maWcucHJlZml4RXZlbnQgKyAnY2xvc2UnLCAoKGU6IEN1c3RvbUV2ZW50KSA9PiB7XG4gICAgICB0aGlzLl9jbG9zZU1vZGFsKGUuZGV0YWlsLmluc3RhbmNlLm1vZGFsKTtcbiAgICB9KSBhcyBFdmVudExpc3RlbmVyKTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKE5neFNtYXJ0TW9kYWxDb25maWcucHJlZml4RXZlbnQgKyAnZGlzbWlzcycsICgoZTogQ3VzdG9tRXZlbnQpID0+IHtcbiAgICAgIHRoaXMuX2Rpc21pc3NNb2RhbChlLmRldGFpbC5pbnN0YW5jZS5tb2RhbCk7XG4gICAgfSkgYXMgRXZlbnRMaXN0ZW5lcik7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9lc2NhcGVLZXlib2FyZEV2ZW50KTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdE1vZGFsKG1vZGFsSW5zdGFuY2U6IE1vZGFsSW5zdGFuY2UpIHtcbiAgICBtb2RhbEluc3RhbmNlLm1vZGFsLmxheWVyUG9zaXRpb24gKz0gdGhpcy5nZXRNb2RhbFN0YWNrQ291bnQoKTtcbiAgICB0aGlzLmFkZE1vZGFsKG1vZGFsSW5zdGFuY2UsIG1vZGFsSW5zdGFuY2UubW9kYWwuZm9yY2UpO1xuXG4gICAgaWYgKG1vZGFsSW5zdGFuY2UubW9kYWwuYXV0b3N0YXJ0KSB7XG4gICAgICB0aGlzLm9wZW4obW9kYWxJbnN0YW5jZS5pZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfb3Blbk1vZGFsKG1vZGFsOiBOZ3hTbWFydE1vZGFsQ29tcG9uZW50LCB0b3A/OiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgaWYgKG1vZGFsLnZpc2libGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3RFbGVtZW50Rm9jdXNlZCA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG5cbiAgICBpZiAobW9kYWwuZXNjYXBhYmxlKSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9lc2NhcGVLZXlib2FyZEV2ZW50KTtcbiAgICB9XG5cbiAgICBpZiAobW9kYWwuYmFja2Ryb3ApIHtcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fdHJhcEZvY3VzTW9kYWwpO1xuICAgIH1cblxuICAgIGlmICh0b3ApIHtcbiAgICAgIG1vZGFsLmxheWVyUG9zaXRpb24gPSB0aGlzLmdldEhpZ2hlckluZGV4KCk7XG4gICAgfVxuXG4gICAgbW9kYWwuYWRkQm9keUNsYXNzKCk7XG4gICAgbW9kYWwub3ZlcmxheVZpc2libGUgPSB0cnVlO1xuICAgIG1vZGFsLnZpc2libGUgPSB0cnVlO1xuICAgIG1vZGFsLm9uT3Blbi5lbWl0KG1vZGFsKTtcbiAgICBtb2RhbC5tYXJrRm9yQ2hlY2soKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgbW9kYWwub3BlbmVkQ2xhc3MgPSB0cnVlO1xuXG4gICAgICBpZiAobW9kYWwudGFyZ2V0KSB7XG4gICAgICAgIG1vZGFsLnRhcmdldFBsYWNlbWVudCgpO1xuICAgICAgfVxuXG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnZGlhbG9nJyk7XG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3RhYkluZGV4JywgJy0xJyk7XG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtbW9kYWwnLCAndHJ1ZScpO1xuICAgICAgbW9kYWwubnNtRGlhbG9nLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcblxuICAgICAgbW9kYWwubWFya0ZvckNoZWNrKCk7XG4gICAgICBtb2RhbC5vbk9wZW5GaW5pc2hlZC5lbWl0KG1vZGFsKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfdG9nZ2xlTW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQsIHRvcD86IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICBpZiAobW9kYWwudmlzaWJsZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2Nsb3NlTW9kYWwobW9kYWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3Blbk1vZGFsKG1vZGFsLCB0b3ApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2Nsb3NlTW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQpOiBib29sZWFuIHtcbiAgICBpZiAoIW1vZGFsLm9wZW5lZENsYXNzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbW9kYWwub3BlbmVkQ2xhc3MgPSBmYWxzZTtcbiAgICBtb2RhbC5vbkNsb3NlLmVtaXQobW9kYWwpO1xuICAgIG1vZGFsLm9uQW55Q2xvc2VFdmVudC5lbWl0KG1vZGFsKTtcblxuICAgIGlmICh0aGlzLmdldE9wZW5lZE1vZGFscygpLmxlbmd0aCA8IDIpIHtcbiAgICAgIG1vZGFsLnJlbW92ZUJvZHlDbGFzcygpO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleXVwJywgdGhpcy5fZXNjYXBlS2V5Ym9hcmRFdmVudCk7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuX3RyYXBGb2N1c01vZGFsKTtcbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIG1vZGFsLnZpc2libGVDaGFuZ2UuZW1pdChtb2RhbC52aXNpYmxlKTtcbiAgICAgIG1vZGFsLnZpc2libGUgPSBmYWxzZTtcbiAgICAgIG1vZGFsLm92ZXJsYXlWaXNpYmxlID0gZmFsc2U7XG4gICAgICBtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3RhYkluZGV4Jyk7XG4gICAgICBtb2RhbC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIG1vZGFsLm9uQ2xvc2VGaW5pc2hlZC5lbWl0KG1vZGFsKTtcbiAgICAgIG1vZGFsLm9uQW55Q2xvc2VFdmVudEZpbmlzaGVkLmVtaXQobW9kYWwpO1xuICAgICAgaWYgKG1vZGFsLnJlZm9jdXMpIHtcbiAgICAgICAgdGhpcy5sYXN0RWxlbWVudEZvY3VzZWQuZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9LCBtb2RhbC5oaWRlRGVsYXkpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIF9kaXNtaXNzTW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQpOiBib29sZWFuIHtcbiAgICBpZiAoIW1vZGFsLm9wZW5lZENsYXNzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbW9kYWwub3BlbmVkQ2xhc3MgPSBmYWxzZTtcbiAgICBtb2RhbC5vbkRpc21pc3MuZW1pdChtb2RhbCk7XG4gICAgbW9kYWwub25BbnlDbG9zZUV2ZW50LmVtaXQobW9kYWwpO1xuXG4gICAgaWYgKHRoaXMuZ2V0T3BlbmVkTW9kYWxzKCkubGVuZ3RoIDwgMikge1xuICAgICAgbW9kYWwucmVtb3ZlQm9keUNsYXNzKCk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBtb2RhbC52aXNpYmxlID0gZmFsc2U7XG4gICAgICBtb2RhbC52aXNpYmxlQ2hhbmdlLmVtaXQobW9kYWwudmlzaWJsZSk7XG4gICAgICBtb2RhbC5vdmVybGF5VmlzaWJsZSA9IGZhbHNlO1xuICAgICAgbW9kYWwubWFya0ZvckNoZWNrKCk7XG4gICAgICBtb2RhbC5vbkRpc21pc3NGaW5pc2hlZC5lbWl0KG1vZGFsKTtcbiAgICAgIG1vZGFsLm9uQW55Q2xvc2VFdmVudEZpbmlzaGVkLmVtaXQobW9kYWwpO1xuICAgIH0sIG1vZGFsLmhpZGVEZWxheSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgX2RlbGV0ZU1vZGFsKG1vZGFsSW5zdGFuY2U6IE1vZGFsSW5zdGFuY2UpIHtcbiAgICB0aGlzLnJlbW92ZU1vZGFsKG1vZGFsSW5zdGFuY2UuaWQpO1xuXG4gICAgaWYgKCF0aGlzLmdldE1vZGFsU3RhY2soKS5sZW5ndGgpIHtcbiAgICAgIG1vZGFsSW5zdGFuY2UubW9kYWwucmVtb3ZlQm9keUNsYXNzKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgY29udGVudCBhY2NvcmRpbmcgdG8gdGhlIHR5cGVzXG4gICAqIEBwYXJhbSBjb250ZW50IFRoZSBtb2RhbCBjb250ZW50IChzdHJpbmcsIHRlbXBsYXRlUmVmIG9yIENvbXBvbmVudClcbiAgICovXG4gIHByaXZhdGUgX3Jlc29sdmVOZ0NvbnRlbnQ8VD4oY29udGVudDogQ29udGVudDxUPik6IGFueVtdW10gfCBUZXh0W11bXSB7XG4gICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2RvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNvbnRlbnQpO1xuICAgICAgcmV0dXJuIFtbZWxlbWVudF1dO1xuICAgIH1cblxuICAgIGlmIChjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYpIHtcbiAgICAgIGNvbnN0IHZpZXdSZWYgPSBjb250ZW50LmNyZWF0ZUVtYmVkZGVkVmlldyhudWxsIGFzIGFueSk7XG4gICAgICB0aGlzLl9hcHBSZWYuYXR0YWNoVmlldyh2aWV3UmVmKTtcbiAgICAgIHJldHVybiBbdmlld1JlZi5yb290Tm9kZXNdO1xuICAgIH1cblxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgbGF0ZXN0IG9wZW5lZCBtb2RhbCBpZiBlc2NhcGUga2V5IGV2ZW50IGlzIGVtaXR0ZWRcbiAgICogQHBhcmFtIGV2ZW50IFRoZSBLZXlib2FyZCBFdmVudFxuICAgKi9cbiAgcHJpdmF0ZSBfZXNjYXBlS2V5Ym9hcmRFdmVudCA9IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgIGlmIChldmVudC5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBtb2RhbCA9IHRoaXMuZ2V0VG9wT3BlbmVkTW9kYWwoKTtcblxuICAgICAgICBpZiAoIW1vZGFsLmVzY2FwYWJsZSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1vZGFsLm9uRXNjYXBlLmVtaXQobW9kYWwpO1xuICAgICAgICB0aGlzLmNsb3NlTGF0ZXN0TW9kYWwoKTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJcyBjdXJyZW50IHBsYXRmb3JtIGJyb3dzZXJcbiAgICovXG4gIHByaXZhdGUgZ2V0IGlzQnJvd3NlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5fcGxhdGZvcm1JZCk7XG4gIH1cblxuICAvKipcbiAgICogV2hpbGUgbW9kYWwgaXMgb3BlbiwgdGhlIGZvY3VzIHN0YXkgb24gaXRcbiAgICogQHBhcmFtIGV2ZW50IFRoZSBLZXlib2FyIGRFdmVudFxuICAgKi9cbiAgcHJpdmF0ZSBfdHJhcEZvY3VzTW9kYWwgPSAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpID0+IHtcbiAgICBpZiAoZXZlbnQua2V5ID09PSAnVGFiJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgbW9kYWwgPSB0aGlzLmdldFRvcE9wZW5lZE1vZGFsKCk7XG5cbiAgICAgICAgaWYgKCFtb2RhbC5uc21EaWFsb2cuZmlyc3QubmF0aXZlRWxlbWVudC5jb250YWlucyhkb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgbW9kYWwubnNtRGlhbG9nLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBkeW5hbWljYWxseSBjcmVhdGVkIG1vZGFsIGZyb20gRE9NXG4gICAqL1xuICBwcml2YXRlIF9kZXN0cm95TW9kYWwobW9kYWw6IE5neFNtYXJ0TW9kYWxDb21wb25lbnQpOiB2b2lkIHtcbiAgICAvLyBQcmV2ZW50IGRlc3RydWN0aW9uIG9mIHRoZSBpbmxpbmUgbW9kYWxzXG4gICAgaWYgKG1vZGFsLmNyZWF0ZUZyb20gIT09ICdzZXJ2aWNlJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2RvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQobW9kYWwuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KTtcbiAgfVxufVxuIl19