UNPKG

@catull/igniteui-angular

Version:

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

717 lines 101 kB
var IgxHierarchicalGridComponent_1;
import { __decorate, __metadata } from "tslib";
import { ChangeDetectionStrategy, Component, HostBinding, Input, forwardRef, TemplateRef, ViewChild, ViewChildren, QueryList, ContentChildren, ElementRef, EventEmitter, Output } from '@angular/core';
import { IgxGridBaseDirective } from '../grid-base.directive';
import { GridBaseAPIService } from '../api.service';
import { IgxHierarchicalGridAPIService } from './hierarchical-grid-api.service';
import { IgxRowIslandComponent } from './row-island.component';
import { IgxChildGridRowComponent } from './child-grid-row.component';
import { IgxFilteringService } from '../filtering/grid-filtering.service';
import { DisplayDensity } from '../../core/displayDensity';
import { IgxHierarchicalGridNavigationService } from './hierarchical-grid-navigation.service';
import { IgxGridSummaryService } from '../summaries/grid-summary.service';
import { IgxHierarchicalGridBaseDirective } from './hierarchical-grid-base.directive';
import { takeUntil } from 'rxjs/operators';
import { IgxTemplateOutletDirective } from '../../directives/template-outlet/template_outlet.directive';
import { IgxGridSelectionService, IgxGridCRUDService } from '../selection/selection.service';
import { IgxTransactionService } from '../../services/index';
import { IgxForOfSyncService, IgxForOfScrollSyncService } from '../../directives/for-of/for_of.sync.service';
import { IgxRowIslandAPIService } from './row-island-api.service';
let NEXT_ID = 0;
let IgxHierarchicalGridComponent = IgxHierarchicalGridComponent_1 = class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirective {
    constructor() {
        super(...arguments);
        /**
         *@hidden
         */
        this.hierarchicalStateChange = new EventEmitter();
        /**
         * @hidden
         */
        this.childLayoutKeys = [];
        /**
         * @hidden
         */
        this.highlightedRowID = null;
        /**
         * @hidden
         */
        this.updateOnRender = false;
        /**
         * @hidden
         */
        this.parent = null;
        this._hierarchicalState = [];
        this._filteredData = null;
        this.h_id = `igx-hierarchical-grid-${NEXT_ID++}`;
        this.childGridTemplates = new Map();
        this.scrollTop = 0;
        this.scrollLeft = 0;
    }
    /**
     * Sets the value of the `id` attribute. If not provided it will be automatically generated.
     * ```html
     * <igx-hierarchical-grid [id]="'igx-hgrid-1'" [data]="Data" [autoGenerate]="true"></igx-hierarchical-grid>
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    get id() {
        return this.h_id;
    }
    /**
     * An @Input property that lets you fill the `IgxHierarchicalGridComponent` with an array of data.
     * ```html
     * <igx-hierarchical-grid [data]="Data" [autoGenerate]="true"></igx-hierarchical-grid>
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    set data(value) {
        this._data = value || [];
        this.summaryService.clearSummaryCache();
        if (this.shouldGenerate) {
            this.setupColumns();
            this.reflow();
        }
        this.cdr.markForCheck();
        if (this.parent && (this.height === null || this.height.indexOf('%') !== -1)) {
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
            this.notifyChanges(true);
        }
    }
    /**
     * Returns an array of data set to the `IgxHierarchicalGridComponent`.
     * ```typescript
     * let filteredData = this.grid.filteredData;
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    get data() {
        return this._data;
    }
    /**
    * Sets the state of the `IgxHierarchicalGridComponent` containing which rows are expanded.
    * ```typescript
    * this.gridState = [{ rowID: 1 }, { rowID: 4}];
    * ```
    * ```html
    * <igx-hierarchical-grid [primaryKey]="'ID'" [data]="Data" [autoGenerate]="false" [hierarchicalState]="hgridState">
    *      <igx-column field="ID"  [dataType]='number'></igx-column>
    *      <igx-column field="Product"  [dataType]='string'></igx-column>
    *      <igx-column field="Description"  [dataType]='string'></igx-column>
    * </igx-hierarchical-grid>
    * ```
    *
    * Two-way data binding.
    * ```html
    * <igx-hierarchical-grid [primaryKey]="'ID'" [data]="Data" [autoGenerate]="false" [(hierarchicalState)]="hgridState">
    *      <igx-column field="ID"  [dataType]='number'></igx-column>
    *      <igx-column field="Product"  [dataType]='string'></igx-column>
    *      <igx-column field="Description"  [dataType]='string'></igx-column>
    * </igx-hierarchical-grid>
    * ```
    * @memberof IgxHierarchicalGridComponent
    */
    get hierarchicalState() {
        return this._hierarchicalState;
    }
    set hierarchicalState(val) {
        if (this._hierarchicalState !== val) {
            this.hierarchicalStateChange.emit(val);
        }
        if (this.hasChildrenKey) {
            val = val.filter(item => {
                const rec = this.primaryKey ? this.data.find(x => x[this.primaryKey] === item.rowID) : item.rowID;
                return rec[this.hasChildrenKey];
            });
        }
        this._hierarchicalState = val;
        if (this.parent) {
            this.notifyChanges(true);
        }
    }
    /**
     * Sets an array of objects containing the filtered data in the `IgxHierarchicalGridComponent`.
     * ```typescript
     * this.grid.filteredData = [{
     *       ID: 1,
     *       Name: "A"
     * }];
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    set filteredData(value) {
        this._filteredData = value;
    }
    /**
     * Returns an array of objects containing the filtered data in the `IgxHierarchicalGridComponent`.
     * ```typescript
     * let filteredData = this.grid.filteredData;
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    get filteredData() {
        return this._filteredData;
    }
    /**
     * Sets if all immediate children of the `IgxHierarchicalGridComponent` should be expanded/collapsed.
     * Defult value is false.
     * ```html
     * <igx-hierarchical-grid [id]="'igx-grid-1'" [data]="Data" [autoGenerate]="true" [expandChildren]="true"></igx-hierarchical-grid>
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    set expandChildren(value) {
        this._expandChildren = value;
        if (value && this.data) {
            this.hierarchicalState = this.data.map((rec) => {
                return { rowID: this.primaryKey ? rec[this.primaryKey] : rec };
            });
        }
        else if (this.data) {
            this.hierarchicalState = [];
        }
    }
    /**
     * Gets if all immediate children of the `IgxHierarchicalGridComponent` previously have been set to be expanded/collapsed.
     * If previously set and some rows have been manually expanded/collapsed it will still return the last set value.
     * ```typescript
     * const expanded = this.grid.expandChildren;
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    get expandChildren() {
        return this._expandChildren;
    }
    /**
     * Gets the unique identifier of the parent row. It may be a `string` or `number` if `primaryKey` of the
     * parent grid is set or an object reference of the parent record otherwise.
     * ```typescript
     * const foreignKey = this.grid.foreignKey;
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    get foreignKey() {
        if (!this.parent) {
            return null;
        }
        return this.parent.hgridAPI.getParentRowId(this);
    }
    /**
     * @hidden
     */
    get hasExpandableChildren() {
        return !!this.childLayoutKeys.length;
    }
    /**
     * @hidden
     */
    ngOnInit() {
        if (this._transactions instanceof IgxTransactionService) {
            // transaction service cannot be injected in a derived class in a factory manner
            this._transactions = new IgxTransactionService();
        }
        super.ngOnInit();
    }
    ngDoCheck() {
        if (this._cdrRequestRepaint && !this._init) {
            this.updateSizes();
        }
        super.ngDoCheck();
    }
    /**
     * @hidden
     */
    ngAfterViewInit() {
        super.ngAfterViewInit();
        this.verticalScrollContainer.getScroll().addEventListener('scroll', this.hg_verticalScrollHandler.bind(this));
        this.headerContainer.getScroll().addEventListener('scroll', this.hg_horizontalScrollHandler.bind(this));
        if (this.expandChildren && this.data && this.hierarchicalState.length !== this.data.length) {
            this.hierarchicalState = this.data.map((rec) => {
                return { rowID: this.primaryKey ? rec[this.primaryKey] : rec };
            });
            this.cdr.detectChanges();
        }
        this.verticalScrollContainer.onBeforeViewDestroyed.pipe(takeUntil(this.destroy$)).subscribe((view) => {
            const rowData = view.context.$implicit;
            if (this.isChildGridRecord(rowData)) {
                const cachedData = this.childGridTemplates.get(rowData.rowID);
                if (cachedData) {
                    const tmlpOutlet = cachedData.owner;
                    tmlpOutlet._viewContainerRef.detach(0);
                }
            }
        });
        if (this.parent) {
            this._displayDensity = this.rootGrid._displayDensity;
            this.rootGrid.onDensityChanged.pipe(takeUntil(this.destroy$)).subscribe(() => {
                this._displayDensity = this.rootGrid._displayDensity;
                this.notifyChanges(true);
                this.cdr.markForCheck();
            });
            this.childLayoutKeys = this.parentIsland.children.map((item) => item.key);
        }
        this.toolbarCustomContentTemplates = this.parentIsland ?
            this.parentIsland.toolbarCustomContentTemplates :
            this.toolbarCustomContentTemplates;
        this.headSelectorsTemplates = this.parentIsland ?
            this.parentIsland.headSelectorsTemplates :
            this.headSelectorsTemplates;
        this.rowSelectorsTemplates = this.parentIsland ?
            this.parentIsland.rowSelectorsTemplates :
            this.rowSelectorsTemplates;
        this.dragIndicatorIconTemplate = this.parentIsland ?
            this.parentIsland.dragIndicatorIconTemplate :
            this.dragIndicatorIconTemplate;
        this.rowExpandedIndicatorTemplate = this.rootGrid.rowExpandedIndicatorTemplate;
        this.rowCollapsedIndicatorTemplate = this.rootGrid.rowCollapsedIndicatorTemplate;
        this.headerCollapseIndicatorTemplate = this.rootGrid.headerCollapseIndicatorTemplate;
        this.headerExpandIndicatorTemplate = this.rootGrid.headerExpandIndicatorTemplate;
        this.hasChildrenKey = this.parentIsland ?
            this.parentIsland.hasChildrenKey || this.rootGrid.hasChildrenKey :
            this.rootGrid.hasChildrenKey;
        this.showExpandAll = this.parentIsland ?
            this.parentIsland.showExpandAll : this.rootGrid.showExpandAll;
    }
    updateSizes() {
        if (document.body.contains(this.nativeElement) && this.isPercentWidth) {
            this.reflow();
            this.hgridAPI.getChildGrids(false).forEach((grid) => {
                grid.updateSizes();
            });
        }
    }
    _shouldAutoSize(renderedHeight) {
        if (this.isPercentHeight && this.parent) {
            return true;
        }
        return super._shouldAutoSize(renderedHeight);
    }
    get outletDirective() {
        return this.rootGrid._outletDirective;
    }
    /**
     * @hidden
     */
    ngAfterContentInit() {
        this.updateColumnList(false);
        this.childLayoutKeys = this.parent ?
            this.parentIsland.children.map((item) => item.key) :
            this.childLayoutKeys = this.childLayoutList.map((item) => item.key);
        this.childLayoutList.notifyOnChanges();
        this.childLayoutList.changes.pipe(takeUntil(this.destroy$))
            .subscribe(() => this.onRowIslandChange());
        super.ngAfterContentInit();
    }
    /**
    * @hidden
    */
    onRowIslandChange() {
        if (this.parent) {
            this.childLayoutKeys = this.parentIsland.children.filter(item => !item._destroyed).map((item) => item.key);
        }
        else {
            this.childLayoutKeys = this.childLayoutList.filter(item => !item._destroyed).map((item) => item.key);
        }
        if (!this.cdr.destroyed) {
            this.cdr.detectChanges();
        }
    }
    onColumnsChanged(change) {
        this.updateColumnList();
        const cols = change.filter(c => c.gridAPI.grid === this);
        if (cols.length > 0) {
            this.columnList.reset(cols);
            super.onColumnsChanged(this.columnList);
        }
    }
    updateColumnList(recalcColSizes = true) {
        const childLayouts = this.parent ? this.childLayoutList : this.allLayoutList;
        const nestedColumns = childLayouts.map((layout) => {
            return layout.columnList.toArray();
        });
        const colsArray = [].concat.apply([], nestedColumns);
        const colLength = this.columnList.length;
        if (colsArray.length > 0) {
            const topCols = this.columnList.filter((item) => {
                return colsArray.indexOf(item) === -1;
            });
            this.columnList.reset(topCols);
            if (recalcColSizes && this.columnList.length !== colLength) {
                this.calculateGridSizes();
            }
        }
    }
    ngOnDestroy() {
        if (!this.parent) {
            this.hgridAPI.getChildGrids(true).forEach((grid) => {
                if (!grid.childRow.cdr.destroyed) {
                    grid.childRow.cdr.destroy();
                }
            });
        }
        if (this.parent && this.selectionService.activeElement) {
            // in case selection is in destroyed child grid, selection should be cleared.
            this._clearSeletionHighlights();
        }
        super.ngOnDestroy();
    }
    _clearSeletionHighlights() {
        [this.rootGrid, ...this.rootGrid.getChildGrids(true)].forEach(grid => {
            grid.selectionService.clear();
            grid.selectionService.activeElement = null;
            grid.nativeElement.classList.remove('igx-grid__tr--highlighted');
            grid.highlightedRowID = null;
            grid.cdr.markForCheck();
        });
    }
    /**
    * @hidden
    */
    get template() {
        if (this.filteredData && this.filteredData.length === 0) {
            return this.emptyGridTemplate ? this.emptyGridTemplate : this.emptyFilteredGridTemplate;
        }
        if (this.isLoading && (!this.data || this.dataLength === 0)) {
            return this.loadingGridTemplate ? this.loadingGridTemplate : this.loadingGridDefaultTemplate;
        }
        if (this.dataLength === 0) {
            return this.emptyGridTemplate ? this.emptyGridTemplate : this.emptyGridDefaultTemplate;
        }
    }
    /**
     * @hidden
     * Gets the combined width of the columns that are specific to the enabled grid features. They are fixed.
     * TODO: Remove for Angular 8. Calling parent class getter using super is not supported for now.
     */
    getFeatureColumnsWidth() {
        let width = super.getFeatureColumnsWidth();
        if (this.hasExpandableChildren) {
            width += this.headerHierarchyExpander.nativeElement.offsetWidth || this.getDefaultExpanderWidth();
        }
        return width;
    }
    getDefaultExpanderWidth() {
        switch (this.displayDensity) {
            case DisplayDensity.cosy:
                return 57;
            case DisplayDensity.compact:
                return 49;
            default:
                return 72;
        }
    }
    /**
     * @hidden
     */
    isRowHighlighted(rowData) {
        return this.highlightedRowID === rowData.rowID;
    }
    /**
     * @hidden
     */
    isHierarchicalRecord(record) {
        return this.childLayoutList.length !== 0 && record[this.childLayoutList.first.key];
    }
    /**
     * @hidden
     */
    isChildGridRecord(record) {
        // Can be null when there is defined layout but no child data was found
        return record.childGridsData !== undefined;
    }
    /**
     * @hidden
     */
    trackChanges(index, rec) {
        if (rec.childGridsData !== undefined) {
            // if is child rec
            return rec.rowID;
        }
        return rec;
    }
    /**
     * @hidden
     */
    getContext(rowData) {
        if (this.isChildGridRecord(rowData)) {
            const cachedData = this.childGridTemplates.get(rowData.rowID);
            if (cachedData) {
                const view = cachedData.view;
                const tmlpOutlet = cachedData.owner;
                return {
                    $implicit: rowData,
                    moveView: view,
                    owner: tmlpOutlet,
                    index: this.dataView.indexOf(rowData)
                };
            }
            else {
                const rowID = this.primaryKey ? rowData.rowID : this.data.indexOf(rowData.rowID);
                // child rows contain unique grids, hence should have unique templates
                return {
                    $implicit: rowData,
                    templateID: 'childRow-' + rowID,
                    index: this.dataView.indexOf(rowData)
                };
            }
        }
        else {
            return {
                $implicit: rowData,
                templateID: 'dataRow',
                index: this.dataView.indexOf(rowData)
            };
        }
    }
    /**
     * @hidden
    */
    get rootGrid() {
        let currGrid = this;
        while (currGrid.parent) {
            currGrid = currGrid.parent;
        }
        return currGrid;
    }
    /**
     * @hidden
    */
    get iconTemplate() {
        const expanded = this.hierarchicalState.length > 0 && this.hasExpandableChildren;
        if (!expanded && this.showExpandAll) {
            return this.headerCollapseIndicatorTemplate || this.defaultCollapsedTemplate;
        }
        else {
            return this.headerExpandIndicatorTemplate || this.defaultExpandedTemplate;
        }
    }
    /**
     * @hidden
     * @internal
     */
    getDragGhostCustomTemplate() {
        if (this.parentIsland) {
            return this.parentIsland.getDragGhostCustomTemplate();
        }
        return super.getDragGhostCustomTemplate();
    }
    /**
     * @hidden
    */
    initColumns(collection, cb = null) {
        if (this.hasColumnLayouts) {
            // invalid configuration - hierarchical grid should not allow column layouts
            // remove column layouts
            const nonColumnLayoutColumns = this.columnList.filter((col) => !col.columnLayout && !col.columnLayoutChild);
            this.columnList.reset(nonColumnLayoutColumns);
        }
        super.initColumns(collection, cb);
    }
    /**
     * @hidden
     * Gets the visible content height that includes header + tbody + footer.
     * For hierarchical child grid it may be scrolled and not fully visible.
     */
    getVisibleContentHeight() {
        let height = super.getVisibleContentHeight();
        if (this.parent) {
            const rootHeight = this.rootGrid.getVisibleContentHeight();
            const topDiff = this.nativeElement.getBoundingClientRect().top - this.rootGrid.nativeElement.getBoundingClientRect().top;
            height = rootHeight - topDiff > height ? height : rootHeight - topDiff;
        }
        return height;
    }
    /**
     * @hidden
    */
    toggleAll() {
        const expanded = this.hierarchicalState.length > 0 && this.hasExpandableChildren;
        if (!expanded && this.showExpandAll) {
            this.expandAll();
        }
        else {
            this.collapseAll();
        }
    }
    /**
     * Collapses all rows of the current hierarchical grid.
     * ```typescript
     * this.grid.collapseAll();
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    collapseAll() {
        this.hierarchicalState = [];
    }
    /**
     * Expands all rows of the current hierarchical grid.
     * ```typescript
     * this.grid.expandAll();
     * ```
     * @memberof IgxHierarchicalGridComponent
     */
    expandAll() {
        if (this.data) {
            this.hierarchicalState = this.data.map((rec) => {
                return { rowID: this.primaryKey ? rec[this.primaryKey] : rec };
            });
        }
    }
    /**
     * @hidden
     */
    isExpanded(record) {
        let inState;
        if (record.childGridsData !== undefined) {
            inState = !!this.hierarchicalState.find(v => v.rowID === record.rowID);
        }
        else {
            inState = !!this.hierarchicalState.find(v => {
                return this.primaryKey ? v.rowID === record[this.primaryKey] : v.rowID === record;
            });
        }
        return inState && this.childLayoutList.length !== 0;
    }
    /**
     * @hidden
     */
    viewCreatedHandler(args) {
        if (this.isChildGridRecord(args.context.$implicit)) {
            const key = args.context.$implicit.rowID;
            this.childGridTemplates.set(key, args);
        }
    }
    /**
     * @hidden
     */
    viewMovedHandler(args) {
        if (this.isChildGridRecord(args.context.$implicit)) {
            // view was moved, update owner in cache
            const key = args.context.$implicit.rowID;
            const cachedData = this.childGridTemplates.get(key);
            cachedData.owner = args.owner;
            this.childLayoutList.forEach((layout) => {
                const relatedGrid = this.hgridAPI.getChildGridByID(layout.key, args.context.$implicit.rowID);
                if (relatedGrid && relatedGrid.updateOnRender) {
                    // Detect changes if `expandChildren` has changed when the grid wasn't visible. This is for performance reasons.
                    relatedGrid.notifyChanges(true);
                    relatedGrid.updateOnRender = false;
                }
            });
            const childGrids = this.getChildGrids(true);
            childGrids.forEach((grid) => {
                if (grid.isPercentWidth) {
                    grid.notifyChanges(true);
                }
                grid.updateScrollPosition();
            });
        }
    }
    /**
     * @hidden
     */
    updateScrollPosition() {
        const vScr = this.verticalScrollContainer.getScroll();
        const hScr = this.headerContainer.getScroll();
        if (vScr) {
            vScr.scrollTop = this.scrollTop;
        }
        if (hScr) {
            hScr.scrollLeft = this.scrollLeft;
        }
    }
    getChildGrids(inDeph) {
        return this.hgridAPI.getChildGrids(inDeph);
    }
    generateDataFields(data) {
        return super.generateDataFields(data).filter((field) => {
            const layoutsList = this.parentIsland ? this.parentIsland.children : this.childLayoutList;
            const keys = layoutsList.map((item) => item.key);
            return keys.indexOf(field) === -1;
        });
    }
    hg_verticalScrollHandler(event) {
        this.scrollTop = event.target.scrollTop;
    }
    onContainerScroll() {
        this.hideOverlays();
    }
    hg_horizontalScrollHandler(event) {
        this.scrollLeft = event.target.scrollLeft;
    }
};
__decorate([
    HostBinding('attr.id'),
    Input(),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [])
], IgxHierarchicalGridComponent.prototype, "id", null);
__decorate([
    Input(),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], IgxHierarchicalGridComponent.prototype, "data", null);
__decorate([
    Input(),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], IgxHierarchicalGridComponent.prototype, "hierarchicalState", null);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxHierarchicalGridComponent.prototype, "hierarchicalStateChange", void 0);
__decorate([
    Input(),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], IgxHierarchicalGridComponent.prototype, "expandChildren", null);
__decorate([
    ContentChildren(IgxRowIslandComponent, { read: IgxRowIslandComponent, descendants: false }),
    __metadata("design:type", QueryList)
], IgxHierarchicalGridComponent.prototype, "childLayoutList", void 0);
__decorate([
    ContentChildren(IgxRowIslandComponent, { read: IgxRowIslandComponent, descendants: true }),
    __metadata("design:type", QueryList)
], IgxHierarchicalGridComponent.prototype, "allLayoutList", void 0);
__decorate([
    ViewChild('hierarchical_record_template', { read: TemplateRef, static: true }),
    __metadata("design:type", TemplateRef)
], IgxHierarchicalGridComponent.prototype, "hierarchicalRecordTemplate", void 0);
__decorate([
    ViewChild('child_record_template', { read: TemplateRef, static: true }),
    __metadata("design:type", TemplateRef)
], IgxHierarchicalGridComponent.prototype, "childTemplate", void 0);
__decorate([
    ViewChild('headerHierarchyExpander', { read: ElementRef, static: true }),
    __metadata("design:type", ElementRef)
], IgxHierarchicalGridComponent.prototype, "headerHierarchyExpander", void 0);
__decorate([
    ViewChildren(IgxTemplateOutletDirective, { read: IgxTemplateOutletDirective }),
    __metadata("design:type", QueryList)
], IgxHierarchicalGridComponent.prototype, "templateOutlets", void 0);
__decorate([
    ViewChildren(IgxChildGridRowComponent, { read: IgxChildGridRowComponent }),
    __metadata("design:type", QueryList)
], IgxHierarchicalGridComponent.prototype, "hierarchicalRows", void 0);
IgxHierarchicalGridComponent = IgxHierarchicalGridComponent_1 = __decorate([
    Component({
        changeDetection: ChangeDetectionStrategy.OnPush,
        preserveWhitespaces: false,
        selector: 'igx-hierarchical-grid',
        template: "<igx-grid-toolbar role=\"rowgroup\" [style.flex-basis.px]=\"outerWidth\" *ngIf=\"showToolbar\" [gridID]=\"id\"\n    [displayDensity]=\"displayDensity\" #toolbar>\n</igx-grid-toolbar>\n\n<div class=\"igx-grid__thead\">\n    <div class=\"igx-grid__thead-wrapper\" role=\"rowgroup\" [style.width.px]='calcWidth' #theadRow>\n        <div class=\"igx-grid__tr\" role=\"row\" [style.width.px]='calcWidth'>\n            <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length <= 0\"\n                [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\" id=\"left\"\n                class=\"igx-grid__scroll-on-drag-left\"></span>\n            <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length > 0\"\n                [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\" id=\"left\"\n                class=\"igx-grid__scroll-on-drag-pinned\" [style.left.px]=\"pinnedWidth\"></span>\n                <div #headerHierarchyExpander (click)=\"toggleAll()\" [hidden]='!hasExpandableChildren || !hasVisibleColumns' [ngClass]=\"{\n                    'igx-grid__hierarchical-expander igx-grid__hierarchical-expander--header': hasExpandableChildren,\n                    'igx-grid__hierarchical-expander--push': filteringService.isFilterRowVisible,\n                    'igx-grid__hierarchical-expander--no-border': isRowSelectable || rowDraggable\n                }\">\n                <ng-container *ngTemplateOutlet=\"iconTemplate; context: { $implicit: this }\"></ng-container>\n            </div>\n            <ng-container *ngIf=\"rowDraggable\">\n                <div class=\"igx-grid__drag-indicator\" [ngClass]=\"{\n                        'igx-grid__drag-indicator--header': !isRowSelectable\n                    }\" #headerDragContainer>\n                    <div style=\"visibility: hidden;\">\n                        <ng-container\n                            *ngTemplateOutlet=\"this.dragIndicatorIconTemplate ? this.dragIndicatorIconTemplate : this.dragIndicatorIconBase\">\n                        </ng-container>\n                    </div>\n                </div>\n            </ng-container>\n            <ng-container *ngIf=\"showRowSelectors\">\n                <div class=\"igx-grid__cbx-selection\" (click)=\"onHeaderSelectorClick($event)\" #headerSelectorContainer [ngClass]=\"{\n                        'igx-grid__cbx-selection--push': filteringService.isFilterRowVisible\n                    }\">\n                    <ng-template #headSelector\n                        *ngTemplateOutlet=\"\n                        this.headSelectorTemplate ? this.headSelectorTemplate : headSelectorBaseTemplate;\n                        context: { $implicit: {\n                                        selectedCount: this.selectionService.filteredSelectedRowIds.length,\n                                        totalCount: this.totalRowsCountAfterFilter,\n                                        selectAll: selectAllRows.bind(this),\n                                        deselectAll: deselectAllRows.bind(this) }}\">\n                    </ng-template>\n                </div>\n            </ng-container>\n            <ng-container *ngIf=\"pinnedColumns.length > 0\">\n                <ng-template ngFor let-col [ngForOf]=\"pinnedColumns | igxTopLevel\">\n                    <igx-grid-header-group [column]=\"col\" [gridID]=\"id\" [style.min-width]=\"getHeaderGroupWidth(col)\"\n                        [style.flex-basis]=\"getHeaderGroupWidth(col)\"></igx-grid-header-group>\n                </ng-template>\n            </ng-container>\n            <ng-template igxGridFor let-col [igxGridForOf]=\"unpinnedColumns | igxTopLevel\"\n                [igxForScrollOrientation]=\"'horizontal'\" [igxForScrollContainer]=\"parentVirtDir\"\n                [igxForContainerSize]='unpinnedWidth' [igxForTrackBy]='trackColumnChanges'\n                [igxForSizePropName]='\"calcPixelWidth\"' #hContainer>\n                <igx-grid-header-group [column]=\"col\" [gridID]=\"id\" [style.min-width]=\"getHeaderGroupWidth(col)\"\n                    [style.flex-basis]=\"getHeaderGroupWidth(col)\"></igx-grid-header-group>\n            </ng-template>\n        </div>\n        <igx-grid-filtering-row #filteringRow [style.width.px]='calcWidth' *ngIf=\"filteringService.isFilterRowVisible\"\n            [column]=\"filteringService.filteredColumn\"></igx-grid-filtering-row>\n    </div>\n    <div [style.display]=\"shouldOverlayLoading ? 'flex' : 'none'\" #loadingOverlay>\n        <igx-circular-bar [indeterminate]=\"true\">\n        </igx-circular-bar>\n    </div>\n    <span *ngIf=\"hasMovableColumns && draggedColumn\" [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\"\n        id=\"right\" class=\"igx-grid__scroll-on-drag-right\"></span>\n    <div class=\"igx-grid__thead-thumb\" [hidden]='!hasVerticalSroll()' [style.width.px]=\"scrollWidth\"></div>\n</div>\n\n<div igxGridBody (keydown.control.c)=\"copyHandlerIE()\" (copy)=\"copyHandler($event)\" class=\"igx-grid__tbody\">\n    <div class=\"igx-grid__tbody-content\" (onDragStop)=\"selectionService.dragMode = $event\"\n        (onDragScroll)=\"dragScroll($event)\" [igxGridDragSelect]=\"selectionService.dragMode\" role=\"rowgroup\"\n        [style.height.px]='calcHeight' [style.width.px]='calcWidth' #tbody (scroll)='scrollHandler($event)'>\n        <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length <= 0\"\n            [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\" id=\"left\"\n            class=\"igx-grid__scroll-on-drag-left\"></span>\n        <span *ngIf=\"hasMovableColumns && draggedColumn && pinnedColumns.length > 0\"\n            [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\" id=\"left\"\n            class=\"igx-grid__scroll-on-drag-pinned\" [style.left.px]=\"pinnedWidth\"></span>\n        <ng-template igxGridFor let-rowData [igxGridForOf]=\"data\n        | gridTransaction:id:pipeTrigger\n        | visibleColumns:hasVisibleColumns\n        | gridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:id:pipeTrigger\n        | gridSort:sortingExpressions:sortStrategy:id:pipeTrigger\n        | gridHierarchicalPaging:page:perPage:id:pipeTrigger\n        | gridHierarchical:hierarchicalState:id:primaryKey:childLayoutKeys:pipeTrigger\" let-rowIndex=\"index\"\n            [igxForScrollOrientation]=\"'vertical'\" [igxForScrollContainer]='verticalScroll'\n            [igxForContainerSize]='calcHeight' [igxForItemSize]=\"renderedRowHeight\" [igxForTrackBy]='trackChanges'\n            #verticalScrollContainer (onChunkPreload)=\"dataLoading($event)\">\n            <ng-template #hierarchical_record_template>\n                <igx-hierarchical-grid-row [gridID]=\"id\" [index]=\"rowIndex\" [rowData]=\"rowData\" #row>\n                </igx-hierarchical-grid-row>\n            </ng-template>\n            <ng-template #child_record_template let-rowIndex=\"index\" let-rowData>\n                <div style=\"overflow:auto;width: 100%;\" [attr.data-rowindex]='rowIndex' (scroll)='onContainerScroll()'\n                    [ngClass]=\"{\n                    'igx-grid__tr-container': true,\n                    'igx-grid__tr--highlighted':isRowHighlighted(rowData)\n                }\">\n                    <igx-child-grid-row *ngFor=\"let layout of childLayoutList\" [parentGridID]=\"id\" [index]=\"rowIndex\"\n                        [rowData]=\"rowData\" [layout]='layout' #row>\n                    </igx-child-grid-row>\n                </div>\n            </ng-template>\n            <ng-template\n            [igxTemplateOutlet]='(isHierarchicalRecord(rowData) ? hierarchical_record_template : (isChildGridRecord(rowData) && isExpanded(rowData) ? child_record_template : hierarchical_record_template))'\n            [igxTemplateOutletContext]='getContext(rowData)' (onViewCreated)='viewCreatedHandler($event)'\n            (onViewMoved)='viewMovedHandler($event)' (onCachedViewLoaded)='cachedViewLoaded($event)'\n            (onBeforeViewDetach)='viewDetachHandler($event)'></ng-template>\n            <!-- <ng-container *igxTemplateOutlet=\"(isHierarchicalRecord(rowData) ? hierarchical_record_template : (isChildGridRecord(rowData) && isExpanded(rowData) ? child_record_template : hierarchical_record_template)); context: getContext(rowData)\"></ng-container> -->\n        </ng-template>\n        <ng-container *ngTemplateOutlet=\"template\"></ng-container>\n        <span *ngIf=\"hasMovableColumns && draggedColumn\" [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\"\n            id=\"right\" class=\"igx-grid__scroll-on-drag-right\"></span>\n        <div class=\"igx-grid__row-editing-outlet\" igxOverlayOutlet #igxRowEditingOverlayOutlet></div>\n    </div>\n    <span *ngIf=\"hasMovableColumns && draggedColumn\" [igxColumnMovingDrop]=\"headerContainer\" [attr.droppable]=\"true\"\n        id=\"right\" class=\"igx-grid__scroll-on-drag-right\"></span>\n    <div [hidden]='!hasVerticalSroll()' class=\"igx-grid__tbody-scrollbar\" [style.width.px]=\"scrollWidth\"\n        [style.height.px]='calcHeight'>\n        <ng-template igxGridFor [igxGridForOf]='[]' #verticalScrollHolder></ng-template>\n    </div>\n</div>\n\n\n<div class=\"igx-grid__tfoot\" role=\"rowgroup\" [style.height.px]='summariesHeight' #tfoot>\n    <igx-grid-summary-row [style.width.px]='calcWidth' [style.height.px]='summariesHeight'\n        *ngIf=\"hasSummarizedColumns && rootSummariesEnabled\" [gridID]=\"id\"\n        [summaries]=\"id | igxGridSummaryDataPipe:summaryService.retriggerRootPipe\" [index]=\"0\"\n        class=\"igx-grid__summaries\" #summaryRow>\n    </igx-grid-summary-row>\n    <div class=\"igx-grid__tfoot-thumb\" [hidden]='!hasVerticalSroll()' [style.height.px]='summariesHeight'\n        [style.width.px]=\"scrollWidth\"></div>\n</div>\n\n<div class=\"igx-grid__scroll\" [style.height]=\"'18px'\" #scr [hidden]=\"isHorizontalScrollHidden\">\n    <div class=\"igx-grid__scroll-start\" [style.width.px]='pinnedWidth' [hidden]=\"pinnedWidth === 0\"></div>\n    <div class=\"igx-grid__scroll-main\" [style.width.px]='unpinnedWidth'>\n        <ng-template igxGridFor [igxGridForOf]='[]' #scrollContainer>\n        </ng-template>\n    </div>\n</div>\n\n<div class=\"igx-grid__footer\" #footer>\n    <ng-content select=\"igx-grid-footer\"></ng-content>\n    <ng-container *ngIf=\"paging && totalRecords\">\n        <ng-container\n            *ngTemplateOutlet=\"paginationTemplate ? paginationTemplate : defaultPaginator; context: {$implicit: this}\">\n        </ng-container>\n    </ng-container>\n</div>\n\n<ng-template #defaultPaginator>\n    <igx-paginator [displayDensity]=\"displayDensity\" [(page)]=\"page\" [totalRecords]=\"totalRecords\" [(perPage)]=\"perPage\">\n    </igx-paginator>\n</ng-template>\n\n<ng-template #emptyFilteredGrid>\n    <span class=\"igx-grid__tbody-message\">{{emptyFilteredGridMessage}}</span>\n</ng-template>\n\n<ng-template #defaultEmptyGrid>\n    <span class=\"igx-grid__tbody-message\">{{emptyGridMessage}}</span>\n</ng-template>\n\n<ng-template #defaultLoadingGrid>\n    <div class=\"igx-grid__loading\">\n        <igx-circular-bar [indeterminate]=\"true\">\n        </igx-circular-bar>\n    </div>\n</ng-template>\n\n<ng-template #defaultCollapsedTemplate>\n    <igx-icon role=\"button\" fontSet=\"material\">unfold_more</igx-icon>\n</ng-template>\n\n<ng-template #defaultExpandedTemplate>\n    <igx-icon role=\"button\" [isActive]='hierarchicalState.length > 0 && hasExpandableChildren' [isActive]='true' fontSet=\"material\">unfold_less</igx-icon>\n</ng-template>\n\n<div *ngIf=\"rowEditable\" igxToggle>\n    <div [className]=\"bannerClass\">\n        <ng-container\n            *ngTemplateOutlet=\"rowEditContainer; context: { rowChangesCount: rowChangesCount, endEdit: endEdit.bind(this) }\">\n        </ng-container>\n    </div>\n</div>\n<ng-template #defaultRowEditText>\n    You have {{ rowChangesCount }} changes in this row\n</ng-template>\n<ng-template #defaultRowEditActions>\n    <button igxButton igxRowEditTabStop (click)=\"endEdit(false, $event)\">Cancel</button>\n    <button igxButton igxRowEditTabStop (click)=\"endEdit(true, $event)\">Done</button>\n</ng-template>\n<ng-template #defaultRowEditTemplate>\n    <div class=\"igx-banner__message\">\n        <span class=\"igx-banner__text\">\n            <ng-container\n                *ngTemplateOutlet=\"rowEditText ? rowEditText : defaultRowEditText; context: { $implicit: rowChangesCount }\">\n            </ng-container>\n        </span>\n    </div>\n    <div class=\"igx-banner__actions\">\n        <div class=\"igx-banner__row\">\n            <ng-container\n                *ngTemplateOutlet=\"rowEditActions ? rowEditActions : defaultRowEditActions; context: { $implicit: endEdit.bind(this) }\">\n            </ng-container>\n        </div>\n    </div>\n</ng-template>\n\n<ng-template #dragIndicatorIconBase>\n    <igx-icon fontSet=\"material\">drag_indicator</igx-icon>\n</ng-template>\n\n<ng-template #headSelectorBaseTemplate igxHeadSelector let-context>\n    <div class=\"igx-grid__cbx-padding\">\n        <igx-checkbox\n            [readonly]=\"true\"\n            [checked]=\"context.selectedCount > 0 && context.totalCount === context.selectedCount\"\n            disableRipple=\"true\"\n            [ngStyle]=\"{'visibility': isMultiRowSelectionEnabled? 'visible' : 'hidden' }\"\n            [indeterminate]=\"context.selectedCount > 0 && context.selectedCount !== context.totalCount\"\n            [aria-label]=\"headSelectorBaseAriaLabel\"\n            #headerCheckbox>\n        </igx-checkbox>\n    </div>\n</ng-template>\n\n<igx-grid-column-resizer *ngIf=\"colResizingService.showResizer\"></igx-grid-column-resizer>\n<div class=\"igx-grid__loading-outlet\" #igxLoadingOverlayOutlet igxOverlayOutlet></div>\n<div class=\"igx-grid__outlet\" #igxFilteringOverlayOutlet igxOverlayOutlet></div>\n",
        providers: [
            IgxGridSelectionService,
            IgxGridCRUDService,
            { provide: GridBaseAPIService, useClass: IgxHierarchicalGridAPIService },
            { provide: IgxGridBaseDirective, useExisting: forwardRef(() => IgxHierarchicalGridComponent_1) },
            IgxGridSummaryService,
            IgxFilteringService,
            IgxHierarchicalGridNavigationService,
            IgxForOfSyncService,
            IgxForOfScrollSyncService,
            IgxRowIslandAPIService
        ]
    })
], IgxHierarchicalGridComponent);
export { IgxHierarchicalGridComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGllcmFyY2hpY2FsLWdyaWQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9ncmlkcy9oaWVyYXJjaGljYWwtZ3JpZC9oaWVyYXJjaGljYWwtZ3JpZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQ0gsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxXQUFXLEVBQ1gsS0FBSyxFQUNMLFVBQVUsRUFDVixXQUFXLEVBQ1gsU0FBUyxFQUNULFlBQVksRUFDWixTQUFTLEVBQ1QsZUFBZSxFQUNmLFVBQVUsRUFNVixZQUFZLEVBQ1osTUFBTSxFQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzlELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQy9ELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUUzRCxPQUFPLEVBQUUsb0NBQW9DLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUM5RixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUMxRSxPQUFPLEVBQUUsZ0NBQWdDLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN0RixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sNERBQTRELENBQUM7QUFDeEcsT0FBTyxF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QjtJQWxCeEMsU0FBUyxDQUFDO1FBQ1AsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07UUFDL0MsbUJBQW1CLEVBQUUsS0FBSztRQUMxQixRQUFRLEVBQUUsdUJBQXVCO1FBQ2pDLHVxYkFBK0M7UUFDL0MsU0FBUyxFQUFFO1lBQ1AsdUJBQXVCO1lBQ3ZCLGtCQUFrQjtZQUNsQixFQUFFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsNkJBQTZCLEVBQUU7WUFDeEUsRUFBRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyw4QkFBNEIsQ0FBQyxFQUFFO1lBQzlGLHFCQUFxQjtZQUNyQixtQkFBbUI7WUFDbkIsb0NBQW9DO1lBQ3BDLG1CQUFtQjtZQUNuQix5QkFBeUI7WUFDekIsc0JBQXNCO1NBQ3pCO0tBQ0osQ0FBQztHQUNXLDRCQUE0QixDQWl0QnhDO1NBanRCWSw0QkFBNEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENvbXBvbmVudCxcbiAgICBIb3N0QmluZGluZyxcbiAgICBJbnB1dCxcbiAgICBmb3J3YXJkUmVmLFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3Q2hpbGRyZW4sXG4gICAgUXVlcnlMaXN0LFxuICAgIENvbnRlbnRDaGlsZHJlbixcbiAgICBFbGVtZW50UmVmLFxuICAgIEFmdGVyVmlld0luaXQsXG4gICAgQWZ0ZXJDb250ZW50SW5pdCxcbiAgICBPbkluaXQsXG4gICAgT25EZXN0cm95LFxuICAgIERvQ2hlY2ssXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIE91dHB1dFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElneEdyaWRCYXNlRGlyZWN0aXZlIH0gZnJvbSAnLi4vZ3JpZC1iYXNlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBHcmlkQmFzZUFQSVNlcnZpY2UgfSBmcm9tICcuLi9hcGkuc2VydmljZSc7XG5pbXBvcnQgeyBJZ3hIaWVyYXJjaGljYWxHcmlkQVBJU2VydmljZSB9IGZyb20gJy4vaGllcmFyY2hpY2FsLWdyaWQtYXBpLnNlcnZpY2UnO1xuaW1wb3J0IHsgSWd4Um93SXNsYW5kQ29tcG9uZW50IH0gZnJvbSAnLi9yb3ctaXNsYW5kLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hDaGlsZEdyaWRSb3dDb21wb25lbnQgfSBmcm9tICcuL2NoaWxkLWdyaWQtcm93LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hGaWx0ZXJpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vZmlsdGVyaW5nL2dyaWQtZmlsdGVyaW5nLnNlcnZpY2UnO1xuaW1wb3J0IHsgRGlzcGxheURlbnNpdHkgfSBmcm9tICcuLi8uLi9jb3JlL2Rpc3BsYXlEZW5zaXR5JztcbmltcG9ydCB7IElneENvbHVtbkNvbXBvbmVudCwgfSBmcm9tICcuLi9jb2x1bW5zL2NvbHVtbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgSWd4SGllcmFyY2hpY2FsR3JpZE5hdmlnYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi9oaWVyYXJjaGljYWwtZ3JpZC1uYXZpZ2F0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgSWd4R3JpZFN1bW1hcnlTZXJ2aWNlIH0gZnJvbSAnLi4vc3VtbWFyaWVzL2dyaWQtc3VtbWFyeS5zZXJ2aWNlJztcbmltcG9ydCB7IElneEhpZXJhcmNoaWNhbEdyaWRCYXNlRGlyZWN0aXZlIH0gZnJvbSAnLi9oaWVyYXJjaGljYWwtZ3JpZC1iYXNlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBJZ3hUZW1wbGF0ZU91dGxldERpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvdGVtcGxhdGUtb3V0bGV0L3RlbXBsYXRlX291dGxldC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSWd4R3JpZFNlbGVjdGlvblNlcnZpY2UsIElneEdyaWRDUlVEU2VydmljZSB9IGZyb20gJy4uL3NlbGVjdGlvbi9zZWxlY3Rpb24uc2VydmljZSc7XG5pbXBvcnQgeyBJZ3hUcmFuc2FjdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9pbmRleCc7XG5pbXBvcnQgeyBJZ3hGb3JPZlN5bmNTZXJ2aWNlLCBJZ3hGb3JPZlNjcm9sbFN5bmNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLnN5bmMuc2VydmljZSc7XG5pbXBvcnQgeyBHcmlkVHlwZSB9IGZyb20gJy4uL2NvbW1vbi9ncmlkLmludGVyZmFjZSc7XG5pbXBvcnQgeyBJZ3hSb3dJc2xhbmRBUElTZXJ2aWNlIH0gZnJvbSAnLi9yb3ctaXNsYW5kLWFwaS5zZXJ2aWNlJztcblxubGV0IE5FWFRfSUQgPSAwO1xuXG5leHBvcnQgaW50ZXJmYWNlIEhpZXJhcmNoaWNhbFN0YXRlUmVjb3JkIHtcbiAgICByb3dJRDogYW55O1xufVxuXG5AQ29tcG9uZW50KHtcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgICBwcmVzZXJ2ZVdoaXRlc3BhY2VzOiBmYWxzZSxcbiAgICBzZWxlY3RvcjogJ2lneC1oaWVyYXJjaGljYWwtZ3JpZCcsXG4gICAgdGVtcGxhdGVVcmw6ICdoaWVyYXJjaGljYWwtZ3JpZC5jb21wb25lbnQuaHRtbCcsXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIElneEdyaWRTZWxlY3Rpb25TZXJ2aWNlLFxuICAgICAgICBJZ3hHcmlkQ1JVRFNlcnZpY2UsXG4gICAgICAgIHsgcHJvdmlkZTogR3JpZEJhc2VBUElTZXJ2aWNlLCB1c2VDbGFzczogSWd4SGllcmFyY2hpY2FsR3JpZEFQSVNlcnZpY2UgfSxcbiAgICAgICAgeyBwcm92aWRlOiBJZ3hHcmlkQmFzZURpcmVjdGl2ZSwgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gSWd4SGllcmFyY2hpY2FsR3JpZENvbXBvbmVudCkgfSxcbiAgICAgICAgSWd4R3JpZFN1bW1hcnlTZXJ2aWNlLFxuICAgICAgICBJZ3hGaWx0ZXJpbmdTZXJ2aWNlLFxuICAgICAgICBJZ3hIaWVyYXJjaGljYWxHcmlkTmF2aWdhdGlvblNlcnZpY2UsXG4gICAgICAgIElneEZvck9mU3luY1NlcnZpY2UsXG4gICAgICAgIElneEZvck9mU2Nyb2xsU3luY1NlcnZpY2UsXG4gICAgICAgIElneFJvd0lzbGFuZEFQSVNlcnZpY2VcbiAgICBdXG59KVxuZXhwb3J0IGNsYXNzIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnQgZXh0ZW5kcyBJZ3hIaWVyYXJjaGljYWxHcmlkQmFzZURpcmVjdGl2ZVxuICAgIGltcGxlbWVudHMgR3JpZFR5cGUsIEFmdGVyVmlld0luaXQsIEFmdGVyQ29udGVudEluaXQsIE9uSW5pdCwgT25EZXN0cm95LCBEb0NoZWNrIHtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZhbHVlIG9mIHRoZSBgaWRgIGF0dHJpYnV0ZS4gSWYgbm90IHByb3ZpZGVkIGl0IHdpbGwgYmUgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtaGllcmFyY2hpY2FsLWdyaWQgW2lkXT1cIidpZ3gtaGdyaWQtMSdcIiBbZGF0YV09XCJEYXRhXCIgW2F1dG9HZW5lcmF0ZV09XCJ0cnVlXCI+PC9pZ3gtaGllcmFyY2hpY2FsLWdyaWQ+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRcbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIuaWQnKVxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGdldCBpZCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5oX2lkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IGxldHMgeW91IGZpbGwgdGhlIGBJZ3hIaWVyYXJjaGljYWxHcmlkQ29tcG9uZW50YCB3aXRoIGFuIGFycmF5IG9mIGRhdGEuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtaGllcmFyY2hpY2FsLWdyaWQgW2RhdGFdPVwiRGF0YVwiIFthdXRvR2VuZXJhdGVdPVwidHJ1ZVwiPjwvaWd4LWhpZXJhcmNoaWNhbC1ncmlkPlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hIaWVyYXJjaGljYWxHcmlkQ29tcG9uZW50XG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgc2V0IGRhdGEodmFsdWU6IGFueVtdKSB7XG4gICAgICAgIHRoaXMuX2RhdGEgPSB2YWx1ZSB8fCBbXTtcbiAgICAgICAgdGhpcy5zdW1tYXJ5U2VydmljZS5jbGVhclN1bW1hcnlDYWNoZSgpO1xuICAgICAgICBpZiAodGhpcy5zaG91bGRHZW5lcmF0ZSkge1xuICAgICAgICAgICAgdGhpcy5zZXR1cENvbHVtbnMoKTtcbiAgICAgICAgICAgIHRoaXMucmVmbG93KCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIGlmICh0aGlzLnBhcmVudCAmJiAodGhpcy5oZWlnaHQgPT09IG51bGwgfHwgdGhpcy5oZWlnaHQuaW5kZXhPZignJScpICE9PSAtMSkpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBoZWlnaHQgd2lsbCBjaGFuZ2UgYmFzZWQgb24gaG93IG11Y2ggZGF0YSB0aGVyZSBpcywgcmVjYWxjdWxhdGUgc2l6ZXMgaW4gaWd4Rm9yT2YuXG4gICAgICAgICAgICB0aGlzLm5vdGlmeUNoYW5nZXModHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIGRhdGEgc2V0IHRvIHRoZSBgSWd4SGllcmFyY2hpY2FsR3JpZENvbXBvbmVudGAuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCBmaWx0ZXJlZERhdGEgPSB0aGlzLmdyaWQuZmlsdGVyZWREYXRhO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hIaWVyYXJjaGljYWxHcmlkQ29tcG9uZW50XG4gICAgICovXG4gICAgcHVibGljIGdldCBkYXRhKCk6IGFueVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgKiBTZXRzIHRoZSBzdGF0ZSBvZiB0aGUgYElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRgIGNvbnRhaW5pbmcgd2hpY2ggcm93cyBhcmUgZXhwYW5kZWQuXG4gICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgKiB0aGlzLmdyaWRTdGF0ZSA9IFt7IHJvd0lEOiAxIH0sIHsgcm93SUQ6IDR9XTtcbiAgICAqIGBgYFxuICAgICogYGBgaHRtbFxuICAgICogPGlneC1oaWVyYXJjaGljYWwtZ3JpZCBbcHJpbWFyeUtleV09XCInSUQnXCIgW2RhdGFdPVwiRGF0YVwiIFthdXRvR2VuZXJhdGVdPVwiZmFsc2VcIiBbaGllcmFyY2hpY2FsU3RhdGVdPVwiaGdyaWRTdGF0ZVwiPlxuICAgICogICAgICA8aWd4LWNvbHVtbiBmaWVsZD1cIklEXCIgIFtkYXRhVHlwZV09J251bWJlcic+PC9pZ3gtY29sdW1uPlxuICAgICogICAgICA8aWd4LWNvbHVtbiBmaWVsZD1cIlByb2R1Y3RcIiAgW2RhdGFUeXBlXT0nc3RyaW5nJz48L2lneC1jb2x1bW4+XG4gICAgKiAgICAgIDxpZ3gtY29sdW1uIGZpZWxkPVwiRGVzY3JpcHRpb25cIiAgW2RhdGFUeXBlXT0nc3RyaW5nJz48L2lneC1jb2x1bW4+XG4gICAgKiA8L2lneC1oaWVyYXJjaGljYWwtZ3JpZD5cbiAgICAqIGBgYFxuICAgICpcbiAgICAqIFR3by13YXkgZGF0YSBiaW5kaW5nLlxuICAgICogYGBgaHRtbFxuICAgICogPGlneC1oaWVyYXJjaGljYWwtZ3JpZCBbcHJpbWFyeUtleV09XCInSUQnXCIgW2RhdGFdPVwiRGF0YVwiIFthdXRvR2VuZXJhdGVdPVwiZmFsc2VcIiBbKGhpZXJhcmNoaWNhbFN0YXRlKV09XCJoZ3JpZFN0YXRlXCI+XG4gICAgKiAgICAgIDxpZ3gtY29sdW1uIGZpZWxkPVwiSURcIiAgW2RhdGFUeXBlXT0nbnVtYmVyJz48L2lneC1jb2x1bW4+XG4gICAgKiAgICAgIDxpZ3gtY29sdW1uIGZpZWxkPVwiUHJvZHVjdFwiICBbZGF0YVR5cGVdPSdzdHJpbmcnPjwvaWd4LWNvbHVtbj5cbiAgICAqICAgICAgPGlneC1jb2x1bW4gZmllbGQ9XCJEZXNjcmlwdGlvblwiICBbZGF0YVR5cGVdPSdzdHJpbmcnPjwvaWd4LWNvbHVtbj5cbiAgICAqIDwvaWd4LWhpZXJhcmNoaWNhbC1ncmlkPlxuICAgICogYGBgXG4gICAgKiBAbWVtYmVyb2YgSWd4SGllcmFyY2hpY2FsR3JpZENvbXBvbmVudFxuICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2V0IGhpZXJhcmNoaWNhbFN0YXRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faGllcmFyY2hpY2FsU3RhdGU7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgaGllcmFyY2hpY2FsU3RhdGUodmFsKSB7XG4gICAgICAgIGlmICh0aGlzLl9oaWVyYXJjaGljYWxTdGF0ZSAhPT0gdmFsKSB7XG4gICAgICAgICAgICB0aGlzLmhpZXJhcmNoaWNhbFN0YXRlQ2hhbmdlLmVtaXQodmFsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5oYXNDaGlsZHJlbktleSkge1xuICAgICAgICAgICAgdmFsID0gdmFsLmZpbHRlcihpdGVtID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWMgPSB0aGlzLnByaW1hcnlLZXkgPyB0aGlzLmRhdGEuZmluZCh4ID0+IHhbdGhpcy5wcmltYXJ5S2V5XSA9PT0gaXRlbS5yb3dJRCkgOiBpdGVtLnJvd0lEO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWNbdGhpcy5oYXNDaGlsZHJlbktleV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9oaWVyYXJjaGljYWxTdGF0ZSA9IHZhbDtcbiAgICAgICAgaWYgKHRoaXMucGFyZW50KSB7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeUNoYW5nZXModHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgaGllcmFyY2hpY2FsU3RhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyBjb250YWluaW5nIHRoZSBmaWx0ZXJlZCBkYXRhIGluIHRoZSBgSWd4SGllcmFyY2hpY2FsR3JpZENvbXBvbmVudGAuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMuZ3JpZC5maWx0ZXJlZERhdGEgPSBbe1xuICAgICAqICAgICAgIElEOiAxLFxuICAgICAqICAgICAgIE5hbWU6IFwiQVwiXG4gICAgICogfV07XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IGZpbHRlcmVkRGF0YSh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9maWx0ZXJlZERhdGEgPSB2YWx1ZTtcblxuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgdGhlIGZpbHRlcmVkIGRhdGEgaW4gdGhlIGBJZ3hIaWVyYXJjaGljYWxHcmlkQ29tcG9uZW50YC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IGZpbHRlcmVkRGF0YSA9IHRoaXMuZ3JpZC5maWx0ZXJlZERhdGE7XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGZpbHRlcmVkRGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbHRlcmVkRGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGlmIGFsbCBpbW1lZGlhdGUgY2hpbGRyZW4gb2YgdGhlIGBJZ3hIaWVyYXJjaGljYWxHcmlkQ29tcG9uZW50YCBzaG91bGQgYmUgZXhwYW5kZWQvY29sbGFwc2VkLlxuICAgICAqIERlZnVsdCB2YWx1ZSBpcyBmYWxzZS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1oaWVyYXJjaGljYWwtZ3JpZCBbaWRdPVwiJ2lneC1ncmlkLTEnXCIgW2RhdGFdPVwiRGF0YVwiIFthdXRvR2VuZXJhdGVdPVwidHJ1ZVwiIFtleHBhbmRDaGlsZHJlbl09XCJ0cnVlXCI+PC9pZ3gtaGllcmFyY2hpY2FsLWdyaWQ+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHNldCBleHBhbmRDaGlsZHJlbih2YWx1ZTogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9leHBhbmRDaGlsZHJlbiA9IHZhbHVlO1xuICAgICAgICBpZiAodmFsdWUgJiYgdGhpcy5kYXRhKSB7XG4gICAgICAgICAgICB0aGlzLmhpZXJhcmNoaWNhbFN0YXRlID0gdGhpcy5kYXRhLm1hcCgocmVjKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgcm93SUQ6IHRoaXMucHJpbWFyeUtleSA/IHJlY1t0aGlzLnByaW1hcnlLZXldIDogcmVjIH07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuaGllcmFyY2hpY2FsU3RhdGUgPSBbXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgaWYgYWxsIGltbWVkaWF0ZSBjaGlsZHJlbiBvZiB0aGUgYElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRgIHByZXZpb3VzbHkgaGF2ZSBiZWVuIHNldCB0byBiZSBleHBhbmRlZC9jb2xsYXBzZWQuXG4gICAgICogSWYgcHJldmlvdXNseSBzZXQgYW5kIHNvbWUgcm93cyBoYXZlIGJlZW4gbWFudWFsbHkgZXhwYW5kZWQvY29sbGFwc2VkIGl0IHdpbGwgc3RpbGwgcmV0dXJuIHRoZSBsYXN0IHNldCB2YWx1ZS5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZXhwYW5kZWQgPSB0aGlzLmdyaWQuZXhwYW5kQ2hpbGRyZW47XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRcbiAgICAgKi9cbiAgICBnZXQgZXhwYW5kQ2hpbGRyZW4oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHBhbmRDaGlsZHJlbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgcGFyZW50IHJvdy4gSXQgbWF5IGJlIGEgYHN0cmluZ2Agb3IgYG51bWJlcmAgaWYgYHByaW1hcnlLZXlgIG9mIHRoZVxuICAgICAqIHBhcmVudCBncmlkIGlzIHNldCBvciBhbiBvYmplY3QgcmVmZXJlbmNlIG9mIHRoZSBwYXJlbnQgcmVjb3JkIG90aGVyd2lzZS5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZm9yZWlnbktleSA9IHRoaXMuZ3JpZC5mb3JlaWduS2V5O1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hIaWVyYXJjaGljYWxHcmlkQ29tcG9uZW50XG4gICAgICovXG4gICAgcHVibGljIGdldCBmb3JlaWduS2V5KCkge1xuICAgICAgICBpZiAoIXRoaXMucGFyZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnQuaGdyaWRBUEkuZ2V0UGFyZW50Um93SWQodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBDb250ZW50Q2hpbGRyZW4oSWd4Um93SXNsYW5kQ29tcG9uZW50LCB7IHJlYWQ6IElneFJvd0lzbGFuZENvbXBvbmVudCwgZGVzY2VuZGFudHM6IGZhbHNlIH0pXG4gICAgcHVibGljIGNoaWxkTGF5b3V0TGlzdDogUXVlcnlMaXN0PElneFJvd0lzbGFuZENvbXBvbmVudD47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihJZ3hSb3dJc2xhbmRDb21wb25lbnQsIHsgcmVhZDogSWd4Um93SXNsYW5kQ29tcG9uZW50LCBkZXNjZW5kYW50czogdHJ1ZSB9KVxuICAgIHB1YmxpYyBhbGxMYXlvdXRMaXN0OiBRdWVyeUxpc3Q8SWd4Um93SXNsYW5kQ29tcG9uZW50PjtcblxuICAgIEBWaWV3Q2hpbGQoJ2hpZXJhcmNoaWNhbF9yZWNvcmRfdGVtcGxhdGUnLCB7IHJlYWQ6IFRlbXBsYXRlUmVmLCBzdGF0aWM6IHRydWUgfSlcbiAgICBwcm90ZWN0ZWQgaGllcmFyY2hpY2FsUmVjb3JkVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgICBAVmlld0NoaWxkKCdjaGlsZF9yZWNvcmRfdGVtcGxhdGUnLCB7IHJlYWQ6IFRlbXBsYXRlUmVmLCBzdGF0aWM6IHRydWUgfSlcbiAgICBwcm90ZWN0ZWQgY2hpbGRUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuICAgIEBWaWV3Q2hpbGQoJ2hlYWRlckhpZXJhcmNoeUV4cGFuZGVyJywgeyByZWFkOiBFbGVtZW50UmVmLCBzdGF0aWM6IHRydWUgfSlcbiAgICBwcm90ZWN0ZWQgaGVhZGVySGllcmFyY2h5RXhwYW5kZXI6IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQFZpZXdDaGlsZHJlbihJZ3hUZW1wbGF0ZU91dGxldERpcmVjdGl2ZSwgeyByZWFkOiBJZ3hUZW1wbGF0ZU91dGxldERpcmVjdGl2ZSB9KVxuICAgIHB1YmxpYyB0ZW1wbGF0ZU91dGxldHM6IFF1ZXJ5TGlzdDxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBWaWV3Q2hpbGRyZW4oSWd4Q2hpbGRHcmlkUm93Q29tcG9uZW50LCB7IHJlYWQ6IElneENoaWxkR3JpZFJvd0NvbXBvbmVudCB9KVxuICAgIHB1YmxpYyBoaWVyYXJjaGljYWxSb3dzOiBRdWVyeUxpc3Q8SWd4Q2hpbGRHcmlkUm93Q29tcG9uZW50PjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXQgaGFzRXhwYW5kYWJsZUNoaWxkcmVuKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLmNoaWxkTGF5b3V0S2V5cy5sZW5ndGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBjaGlsZExheW91dEtleXMgPSBbXTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgaGlnaGxpZ2h0ZWRSb3dJRCA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIHVwZGF0ZU9uUmVuZGVyID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIHBhcmVudCA9IG51bGw7XG5cbiAgICBwcml2YXRlIF9oaWVyYXJjaGljYWxTdGF0ZSA9IFtdO1xuICAgIHByaXZhdGUgX2RhdGE7XG4gICAgcHJpdmF0ZSBfZmlsdGVyZWREYXRhID0gbnVsbDtcbiAgICBwcml2YXRlIGhfaWQgPSBgaWd4LWhpZXJhcmNoaWNhbC1ncmlkLSR7TkVYVF9JRCsrfWA7XG4gICAgcHJpdmF0ZSBjaGlsZEdyaWRUZW1wbGF0ZXM6IE1hcDxhbnksIGFueT4gPSBuZXcgTWFwKCk7XG4gICAgcHJpdmF0ZSBzY3JvbGxUb3AgPSAwO1xuICAgIHByaXZhdGUgc2Nyb2xsTGVmdCA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLl90cmFuc2FjdGlvbnMgaW5zdGFuY2VvZiBJZ3hUcmFuc2FjdGlvblNlcnZpY2UpIHtcbiAgICAgICAgICAgIC8vIHRyYW5zYWN0aW9uIHNlcnZpY2UgY2Fubm90IGJlIGluamVjdGVkIGluIGEgZGVyaXZlZCBjbGFzcyBpbiBhIGZhY3RvcnkgbWFubmVyXG4gICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbnMgPSBuZXcgSWd4VHJhbnNhY3Rpb25TZXJ2aWNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIubmdPbkluaXQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdEb0NoZWNrKCkge1xuICAgICAgICBpZiAodGhpcy5fY2RyUmVxdWVzdFJlcGFpbnQgJiYgIXRoaXMuX2luaXQpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlU2l6ZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBzdXBlci5uZ0RvQ2hlY2soKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgICAgICBzdXBlci5uZ0FmdGVyVmlld0luaXQoKTtcbiAgICAgICAgdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5nZXRTY3JvbGwoKS5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLmhnX3ZlcnRpY2FsU2Nyb2xsSGFuZGxlci5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5oZWFkZXJDb250YWluZXIuZ2V0U2Nyb2xsKCkuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5oZ19ob3Jpem9udGFsU2Nyb2xsSGFuZGxlci5iaW5kKHRoaXMpKTtcblxuICAgICAgICBpZiAodGhpcy5leHBhbmRDaGlsZHJlbiAmJiB0aGlzLmRhdGEgJiYgdGhpcy5oaWVyYXJjaGljYWxTdGF0ZS5sZW5ndGggIT09IHRoaXMuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuaGllcmFyY2hpY2FsU3RhdGUgPSB0aGlzLmRhdGEubWFwKChyZWMpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyByb3dJRDogdGhpcy5wcmltYXJ5S2V5ID8gcmVjW3RoaXMucHJpbWFyeUtleV0gOiByZWMgfTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5vbkJlZm9yZVZpZXdEZXN0cm95ZWQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgodmlldykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgcm93RGF0YSA9IHZpZXcuY29udGV4dC4kaW1wbGljaXQ7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0NoaWxkR3JpZFJlY29yZChyb3dEYXRhKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLmNoaWxkR3JpZFRlbXBsYXRlcy5nZXQocm93RGF0YS5yb3dJRCk7XG4gICAgICAgICAgICAgICAgaWYgKGNhY2hlZERhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG1scE91dGxldCA9IGNhY2hlZERhdGEub3duZXI7XG4gICAgICAgICAgICAgICAgICAgIHRtbHBPdXRsZXQuX3ZpZXdDb250YWluZXJSZWYuZGV0YWNoKDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRoaXMucGFyZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9kaXNwbGF5RGVuc2l0eSA9IHRoaXMucm9vdEdyaWQuX2Rpc3BsYXlEZW5zaXR5O1xuICAgICAgICAgICAgdGhpcy5yb290R3JpZC5vbkRlbnNpdHlDaGFuZ2VkLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rpc3BsYXlEZW5zaXR5ID0gdGhpcy5yb290R3JpZC5fZGlzcGxheURlbnNpdHk7XG4gICAgICAgICAgICAgICAgdGhpcy5ub3RpZnlDaGFuZ2VzKHRydWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmNoaWxkTGF5b3V0S2V5cyA9IHRoaXMucGFyZW50SXNsYW5kLmNoaWxkcmVuLm1hcCgoaXRlbSkgPT4gaXRlbS5rZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50b29sYmFyQ3VzdG9tQ29udGVudFRlbXBsYXRlcyA9IHRoaXMucGFyZW50SXNsYW5kID9cbiAgICAgICAgICAgIHRoaXMucGFyZW50SXNsYW5kLnRvb2xiYXJDdXN0b21Db250ZW50VGVtcGxhdGVzIDpcbiAgICAgICAgICAgIHRoaXMudG9vbGJhckN1c3RvbUNvbnRlbnRUZW1wbGF0ZXM7XG5cbiAgICAgICAgdGhpcy5oZWFkU2VsZWN0b3JzVGVtcGxhdGVzID0gdGhpcy5wYXJlbnRJc2xhbmQgP1xuICAgICAgICAgICAgdGhpcy5wYXJlbnRJc2xhbmQuaGVhZFNlbGVjdG9yc1RlbXBsYXRlcyA6XG4gICAgICAgICAgICB0aGlzLmhlYWRTZWxlY3RvcnNUZW1wbGF0ZXM7XG5cbiAgICAgICAgdGhpcy5yb3dTZWxlY3RvcnNUZW1wbGF0ZXMgPSB0aGlzLnBhcmVudElzbGFuZCA/XG4gICAgICAgICAgICB0aGlzLnBhcmVudElzbGFuZC5yb3dTZWxlY3RvcnNUZW1wbGF0ZXMgOlxuICAgICAgICAgICAgdGhpcy5yb3dTZWxlY3RvcnNUZW1wbGF0ZXM7XG4gICAgICAgIHRoaXMuZHJhZ0luZGljYXRvckljb25UZW1wbGF0ZSA9IHRoaXMucGFyZW50SXNsYW5kID9cbiAgICAgICAgICAgIHRoaXMucGFyZW50SXNsYW5kLmRyYWdJbmRpY2F0b3JJY29uVGVtcGxhdGUgOlxuICAgICAgICAgICAgdGhpcy5kcmFnSW5kaWNhdG9ySWNvblRlbXBsYXRlO1xuICAgICAgICB0aGlzLnJvd0V4cGFuZGVkSW5kaWNhdG9yVGVtcGxhdGUgID0gdGhpcy5yb290R3JpZC5yb3dFeHBhbmRlZEluZGljYXRvclRlbXBsYXRlO1xuICAgICAgICB0aGlzLnJvd0NvbGxhcHNlZEluZGljYXRvclRlbXBsYXRlICAgPSB0aGlzLnJvb3RHcmlkLnJvd0NvbGxhcHNlZEluZGljYXRvclRlbXBsYXRlO1xuICAgICAgICB0aGlzLmhlYWRlckNvbGxhcHNlSW5kaWNhdG9yVGVtcGxhdGUgPSB0aGlzLnJvb3RHcmlkLmhlYWRlckNvbGxhcHNlSW5kaWNhdG9yVGVtcGxhdGU7XG4gICAgICAgIHRoaXMuaGVhZGVyRXhwYW5kSW5kaWNhdG9yVGVtcGxhdGUgPSB0aGlzLnJvb3RHcmlkLmhlYWRlckV4cGFuZEluZGljYXRvclRlbXBsYXRlO1xuICAgICAgICB0aGlzLmhhc0NoaWxkcmVuS2V5ID0gdGhpcy5wYXJlbnRJc2xhbmQgP1xuICAgICAgICAgdGhpcy5wYXJlbnRJc2xhbmQuaGFzQ2hpbGRyZW5LZXkgfHwgdGhpcy5yb290R3JpZC5oYXNDaGlsZHJlbktleSA6XG4gICAgICAgICB0aGlzLnJvb3RHcmlkLmhhc0NoaWxkcmVuS2V5O1xuICAgICAgICAgdGhpcy5zaG93RXhwYW5kQWxsID0gdGhpcy5wYXJlbnRJc2xhbmQgP1xuICAgICAgICAgdGhpcy5wYXJlbnRJc2xhbmQuc2hvd0V4cGFuZEFsbCA6IHRoaXMucm9vdEdyaWQuc2hvd0V4cGFuZEFsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZVNpemVzKCkge1xuICAgICAgICBpZiAoZG9jdW1lbnQuYm9keS5jb250YWlucyh0aGlzLm5hdGl2ZUVsZW1lbnQpICYmIHRoaXMuaXNQZXJjZW50V2lkdGgpIHtcbiAgICAgICAgICAgIHRoaXMucmVmbG93KCk7XG5cbiAgICAgICAgICAgIHRoaXMuaGdyaWRBUEkuZ2V0Q2hpbGRHcmlkcyhmYWxzZSkuZm9yRWFjaCgoZ3JpZCkgPT4ge1xuICAgICAgICAgICAgICAgIGdyaWQudXBkYXRlU2l6ZXMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIF9zaG91bGRBdXRvU2l6ZShyZW5kZXJlZEhlaWdodCkge1xuICAgICAgICBpZiAodGhpcy5pc1BlcmNlbnRIZWlnaHQgJiYgdGhpcy5wYXJlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdXBlci5fc2hvdWxkQXV0b1NpemUocmVuZGVyZWRIZWlnaHQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgb3V0bGV0RGlyZWN0aXZlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb290R3JpZC5fb3V0bGV0RGlyZWN0aXZlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlQ29sdW1uTGlzdChmYWxzZSk7XG4gICAgICAgIHRoaXMuY2hpbGRMYXlvdXRLZXlzID0gdGhpcy5wYXJlbnQgP1xuICAgICAgICB0aGlzLnBhcmVudElzbGFuZC5jaGlsZHJlbi5tYXAoKGl0ZW0pID0+IGl0ZW0ua2V5KSA6XG4gICAgICAgIHRoaXMuY2hpbGRMYXlvdXRLZXlzID0gdGhpcy5jaGlsZExheW91dExpc3QubWFwKChpdGVtKSA9PiBpdGVtLmtleSk7XG4gICAgICAgIHRoaXMuY2hpbGRMYXlvdXRMaXN0Lm5vdGlmeU9uQ2hhbmdlcygpO1xuICAgICAgICB0aGlzLmNoaWxkTGF5b3V0TGlzdC5jaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMub25Sb3dJc2xhbmRDaGFuZ2UoKSk7XG4gICAgICAgIHN1cGVyLm5nQWZ0ZXJDb250ZW50SW5pdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICogQGhpZGRlblxuICAgICovXG4gICAgcHVibGljIG9uUm93SXNsYW5kQ2hhbmdlKCkge1xuICAgICAgICBpZiAodGhpcy5wYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuY2hpbGRMYXlvdXRLZXlzID0gdGhpcy5wYXJlbnRJc2xhbmQuY2hpbGRyZW4uZmlsdGVyKGl0ZW0gPT4gIShpdGVtIGFzIGFueSkuX2Rlc3Ryb3llZCkubWFwKChpdGVtKSA9PiBpdGVtLmtleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNoaWxkTGF5b3V0S2V5cyA9IHRoaXMuY2hpbGRMYXlvdXRMaXN0LmZpbHRlcihpdGVtID0+ICEoaXRlbSBhcyBhbnkpLl9kZXN0cm95ZWQpLm1hcCgoaXRlbSkgPT4gaXRlbS5rZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKHRoaXMuY2RyIGFzIGFueSkuZGVzdHJveWVkKSB7XG4gICAgICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgb25Db2x1bW5zQ2hhbmdlZChjaGFuZ2U6IFF1ZXJ5TGlzdDxJZ3hDb2x1bW5Db21wb25lbnQ+KSB7XG4gICAgICAgIHRoaXMudXBkYXRlQ29sdW1uTGlzdCgpO1xuICAgICAgICBjb25zdCBjb2xzID0gY2hhbmdlLmZpbHRlcihjID0+IGMuZ3JpZEFQSS5ncmlkID09PSB0aGlzKTtcbiAgICAgICAgaWYgKGNvbHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5MaXN0LnJlc2V0KGNvbHMpO1xuICAgICAgICAgICAgc3VwZXIub25Db2x1bW5zQ2hhbmdlZCh0aGlzLmNvbHVtbkxpc3QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVDb2x1bW5MaXN0KHJlY2FsY0NvbFNpemVzID0gdHJ1ZSkge1xuICAgICAgICBjb25zdCBjaGlsZExheW91dHMgPSB0aGlzLnBhcmVudCA/IHRoaXMuY2hpbGRMYXlvdXRMaXN0IDogdGhpcy5hbGxMYXlvdXRMaXN0O1xuICAgICAgICBjb25zdCBuZXN0ZWRDb2x1bW5zID0gY2hpbGRMYXlvdXRzLm1hcCgobGF5b3V0KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbGF5b3V0LmNvbHVtbkxpc3QudG9BcnJheSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY29sc0FycmF5ID0gW10uY29uY2F0LmFwcGx5KFtdLCBuZXN0ZWRDb2x1bW5zKTtcbiAgICAgICAgY29uc3QgY29sTGVuZ3RoID0gdGhpcy5jb2x1bW5MaXN0Lmxlbmd0aDtcbiAgICAgICAgaWYgKGNvbHNBcnJheS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCB0b3BDb2xzID0gdGhpcy5jb2x1bW5MaXN0LmZpbHRlcigoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBjb2xzQXJyYXkuaW5kZXhPZihpdGVtKSA9PT0gLTE7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuY29sdW1uTGlzdC5yZXNldCh0b3BDb2xzKTtcbiAgICAgICAgICAgIGlmIChyZWNhbGNDb2xTaXplcyAmJiB0aGlzLmNvbHVtbkxpc3QubGVuZ3RoICE9PSBjb2xMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUdyaWRTaXplcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIGlmICghdGhpcy5wYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuaGdyaWRBUEkuZ2V0Q2hpbGRHcmlkcyh0cnVlKS5mb3JFYWNoKChncmlkKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFncmlkLmNoaWxkUm93LmNkci5kZXN0cm95ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JpZC5jaGlsZFJvdy5jZHIuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhcmVudCAmJiB0aGlzLnNlbGVjdGlvblNlcnZpY2UuYWN0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgLy8gaW4gY2FzZSBzZWxlY3Rpb24gaXMgaW4gZGVzdHJveWVkIGNoaWxkIGdyaWQsIHNlbGVjdGlvbiBzaG91bGQgYmUgY2xlYXJlZC5cbiAgICAgICAgICAgIHRoaXMuX2NsZWFyU2VsZXRpb25IaWdobGlnaHRzKCk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jbGVhclNlbGV0aW9uSGlnaGxpZ2h0cygpIHtcbiAgICAgICAgW3RoaXMucm9vdEdyaWQsIC4uLnRoaXMucm9vdEdyaWQuZ2V0Q2hpbGRHcmlkcyh0cnVlKV0uZm9yRWFjaChncmlkID0+IHtcbiAgICAgICAgICAgIGdyaWQuc2VsZWN0aW9uU2VydmljZS5jbGVhcigpO1xuICAgICAgICAgICAgZ3JpZC5zZWxlY3Rpb25TZXJ2aWNlLmFjdGl2ZUVsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgZ3JpZC5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2lneC1ncmlkX190ci0taGlnaGxpZ2h0ZWQnKTtcbiAgICAgICAgICAgIGdyaWQuaGlnaGxpZ2h0ZWRSb3dJRCA9IG51bGw7XG4gICAgICAgICAgICBncmlkLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBwdWJsaWMgZ2V0IHRlbXBsYXRlKCk6IFRlbXBsYXRlUmVmPGFueT4ge1xuICAgICAgICBpZiAodGhpcy5maWx0ZXJlZERhdGEgJiYgdGhpcy5maWx0ZXJlZERhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbXB0eUdyaWRUZW1wbGF0ZSA/IHRoaXMuZW1wdHlHcmlkVGVtcGxhdGUgOiB0aGlzLmVtcHR5RmlsdGVyZWRHcmlkVGVtcGxhdGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pc0xvYWRpbmcgJiYgKCF0aGlzLmRhdGEgfHwgdGhpcy5kYXRhTGVuZ3RoID09PSAwKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9hZGluZ0dyaWRUZW1wbGF0ZSA/IHRoaXMubG9hZGluZ0dyaWRUZW1wbGF0ZSA6IHRoaXMubG9hZGluZ0dyaWREZWZhdWx0VGVtcGxhdGU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5kYXRhTGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbXB0eUdyaWRUZW1wbGF0ZSA/IHRoaXMuZW1wdHlHcmlkVGVtcGxhdGUgOiB0aGlzLmVtcHR5R3JpZERlZmF1bHRUZW1wbGF0ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBHZXRzIHRoZSBjb21iaW5lZCB3aWR0aCBvZiB0aGUgY29sdW1ucyB0aGF0IGFyZSBzcGVjaWZpYyB0byB0aGUgZW5hYmxlZCBncmlkIGZlYXR1cmVzLiBUaGV5IGFyZSBmaXhlZC5cbiAgICAgKiBUT0RPOiBSZW1vdmUgZm9yIEFuZ3VsYXIgOC4gQ2FsbGluZyBwYXJlbnQgY2xhc3MgZ2V0dGVyIHVzaW5nIHN1cGVyIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIG5vdy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0RmVhdHVyZUNvbHVtbnNXaWR0aCgpIHtcbiAgICAgICAgbGV0IHdpZHRoID0gc3VwZXIuZ2V0RmVhdHVyZUNvbHVtbnNXaWR0aCgpO1xuXG4gICAgICAgIGlmICh0aGlzLmhhc0V4cGFuZGFibGVDaGlsZHJlbikge1xuICAgICAgICAgICAgd2lkdGggKz0gdGhpcy5oZWFkZXJIaWVyYXJjaHlFeHBhbmRlci5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoIHx8IHRoaXMuZ2V0RGVmYXVsdEV4cGFuZGVyV2lkdGgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB3aWR0aDtcbiAgICB9XG5cbiAgICAgcHJpdmF0ZSBnZXREZWZhdWx0RXhwYW5kZXJXaWR0aCgpOiBudW1iZXIge1xuICAgICAgICBzd2l0Y2ggKHRoaXMuZGlzcGxheURlbnNpdHkpIHtcbiAgICAgICAgICAgIGNhc2UgRGlzcGxheURlbnNpdHkuY29zeTpcbiAgICAgICAgICAgICAgICByZXR1cm4gNTc7XG4gICAgICAgICAgICBjYXNlIERpc3BsYXlEZW5zaXR5LmNvbXBhY3Q6XG4gICAgICAgICAgICAgICAgcmV0dXJuIDQ5O1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gNzI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGlzUm93SGlnaGxpZ2h0ZWQocm93RGF0YSkge1xuICAgICAgICByZXR1cm4gdGhpcy5oaWdobGlnaHRlZFJvd0lEID09PSByb3dEYXRhLnJvd0lEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgaXNIaWVyYXJjaGljYWxSZWNvcmQocmVjb3JkOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hpbGRMYXlvdXRMaXN0Lmxlbmd0aCAhPT0gMCAmJiByZWNvcmRbdGhpcy5jaGlsZExheW91dExpc3QuZmlyc3Qua2V5XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGlzQ2hpbGRHcmlkUmVjb3JkKHJlY29yZDogYW55KTogYm9vbGVhbiB7XG4gICAgICAgIC8vIENhbiBiZSBudWxsIHdoZW4gdGhlcmUgaXMgZGVmaW5lZCBsYXlvdXQgYnV0IG5vIGNoaWxkIGRhdGEgd2FzIGZvdW5kXG4gICAgICAgIHJldHVybiByZWNvcmQuY2hpbGRHcmlkc0RhdGEgIT09IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIHRyYWNrQ2hhbmdlcyhpbmRleCwgcmVjKSB7XG4gICAgICAgIGlmIChyZWMuY2hpbGRHcmlkc0RhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gaWYgaXMgY2hpbGQgcmVjXG4gICAgICAgICAgICByZXR1cm4gcmVjLnJvd0lEO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRDb250ZXh0KHJvd0RhdGEpOiBhbnkge1xuICAgICAgICBpZiAodGhpcy5pc0NoaWxkR3JpZFJlY29yZChyb3dEYXRhKSkge1xuICAgICAgICAgICAgY29uc3QgY2FjaGVkRGF0YSA9IHRoaXMuY2hpbGRHcmlkVGVtcGxhdGVzLmdldChyb3dEYXRhLnJvd0lEKTtcbiAgICAgICAgICAgIGlmIChjYWNoZWREYXRhKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmlldyA9IGNhY2hlZERhdGEudmlldztcbiAgICAgICAgICAgICAgICBjb25zdCB0bWxwT3V0bGV0ID0gY2FjaGVkRGF0YS5vd25lcjtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAkaW1wbGljaXQ6IHJvd0RhdGEsXG4gICAgICAgICAgICAgICAgICAgIG1vdmVWaWV3OiB2aWV3LFxuICAgICAgICAgICAgICAgICAgICBvd25lcjogdG1scE91dGxldCxcbiAgICAgICAgICAgICAgICAgICAgaW5kZXg6IHRoaXMuZGF0YVZpZXcuaW5kZXhPZihyb3dEYXRhKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvd0lEID0gdGhpcy5wcmltYXJ5S2V5ID8gcm93RGF0YS5yb3dJRCA6IHRoaXMuZGF0YS5pbmRleE9mKHJvd0RhdGEucm93SUQpO1xuICAgICAgICAgICAgICAgIC8vIGNoaWxkIHJvd3MgY29udGFpbiB1bmlxdWUgZ3JpZHMsIGhlbmNlIHNob3VsZCBoYXZlIHVuaXF1ZSB0ZW1wbGF0ZXNcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAkaW1wbGljaXQ6IHJvd0RhdGEsXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlSUQ6ICdjaGlsZFJvdy0nICsgcm93SUQsXG4gICAgICAgICAgICAgICAgICAgIGluZGV4OiB0aGlzLmRhdGFWaWV3LmluZGV4T2Yocm93RGF0YSlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAkaW1wbGljaXQ6IHJvd0RhdGEsXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVJRDogJ2RhdGFSb3cnLFxuICAgICAgICAgICAgICAgIGluZGV4OiB0aGlzLmRhdGFWaWV3LmluZGV4T2Yocm93RGF0YSlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBwdWJsaWMgZ2V0IHJvb3RHcmlkKCkge1xuICAgICAgICBsZXQgY3VyckdyaWQgPSB0aGlzO1xuICAgICAgICB3aGlsZSAoY3VyckdyaWQucGFyZW50KSB7XG4gICAgICAgICAgICBjdXJyR3JpZCA9IGN1cnJHcmlkLnBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3VyckdyaWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICovXG4gICAgcHVibGljIGdldCBpY29uVGVtcGxhdGUoKSB7XG4gICAgICAgIGNvbnN0IGV4cGFuZGVkID0gdGhpcy5oaWVyYXJjaGljYWxTdGF0ZS5sZW5ndGggPiAwICYmIHRoaXMuaGFzRXhwYW5kYWJsZUNoaWxkcmVuO1xuICAgICAgICBpZiAoIWV4cGFuZGVkICYmIHRoaXMuc2hvd0V4cGFuZEFsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGVhZGVyQ29sbGFwc2VJbmRpY2F0b3JUZW1wbGF0ZSB8fCB0aGlzLmRlZmF1bHRDb2xsYXBzZWRUZW1wbGF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmhlYWRlckV4cGFuZEluZGljYXRvclRlbXBsYXRlIHx8IHRoaXMuZGVmYXVsdEV4cGFuZGVkVGVtcGxhdGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIGdldERyYWdHaG9zdEN1c3RvbVRlbXBsYXRlKCk6IFRlbXBsYXRlUmVmPGFueT4ge1xuICAgICAgICBpZiAodGhpcy5wYXJlbnRJc2xhbmQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudElzbGFuZC5nZXREcmFnR2hvc3RDdXN0b21UZW1wbGF0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdXBlci5nZXREcmFnR2hvc3RDdXN0b21UZW1wbGF0ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAqL1xuICAgIHByb3RlY3RlZCBpbml0Q29sdW1ucyhjb2xsZWN0aW9uOiBRdWVyeUxpc3Q8SWd4Q29sdW1uQ29tcG9uZW50PiwgY2I6IEZ1bmN0aW9uID0gbnVsbCkge1xuICAgICAgICBpZiAodGhpcy5oYXNDb2x1bW5MYXlvdXRzKSB7XG4gICAgICAgICAgICAvLyBpbnZhbGlkIGNvbmZpZ3VyYXRpb24gLSBoaWVyYXJjaGljYWwgZ3JpZCBzaG91bGQgbm90IGFsbG93IGNvbHVtbiBsYXlvdXRzXG4gICAgICAgICAgICAvLyByZW1vdmUgY29sdW1uIGxheW91dHNcbiAgICAgICAgICAgIGNvbnN0IG5vbkNvbHVtbkxheW91dENvbHVtbnMgPSB0aGlzLmNvbHVtbkxpc3QuZmlsdGVyKChjb2wpID0+ICFjb2wuY29sdW1uTGF5b3V0ICYmICFjb2wuY29sdW1uTGF5b3V0Q2hpbGQpO1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5MaXN0LnJlc2V0KG5vbkNvbHVtbkxheW91dENvbHVtbnMpO1xuICAgICAgICB9XG4gICAgICAgIHN1cGVyLmluaXRDb2x1bW5zKGNvbGxlY3Rpb24sIGNiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogR2V0cyB0aGUgdmlzaWJsZSBjb250ZW50IGhlaWdodCB0aGF0IGluY2x1ZGVzIGhlYWRlciArIHRib2R5ICsgZm9vdGVyLlxuICAgICAqIEZvciBoaWVyYXJjaGljYWwgY2hpbGQgZ3JpZCBpdCBtYXkgYmUgc2Nyb2xsZWQgYW5kIG5vdCBmdWxseSB2aXNpYmxlLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRWaXNpYmxlQ29udGVudEhlaWdodCgpIHtcbiAgICAgICAgbGV0IGhlaWdodCA9IHN1cGVyLmdldFZpc2libGVDb250ZW50SGVpZ2h0KCk7XG4gICAgICAgIGlmICh0aGlzLnBhcmVudCkge1xuICAgICAgICAgICAgY29uc3Qgcm9vdEhlaWdodCA9IHRoaXMucm9vdEdyaWQuZ2V0VmlzaWJsZUNvbnRlbnRIZWlnaHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHRvcERpZmYgPSB0aGlzLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gdGhpcy5yb290R3JpZC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcDtcbiAgICAgICAgICAgIGhlaWdodCA9IHJvb3RIZWlnaHQgLSB0b3BEaWZmID4gaGVpZ2h0ID8gaGVpZ2h0IDogcm9vdEhlaWdodCAtIHRvcERpZmY7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhlaWdodDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgIHRvZ2dsZUFsbCgpIHtcbiAgICBjb25zdCBleHBhbmRlZCA9IHRoaXMuaGllcmFyY2hpY2FsU3RhdGUubGVuZ3RoID4gMCAmJiB0aGlzLmhhc0V4cGFuZGFibGVDaGlsZHJlbjtcbiAgICBpZiAoIWV4cGFuZGVkICYmIHRoaXMuc2hvd0V4cGFuZEFsbCkge1xuICAgICAgICB0aGlzLmV4cGFuZEFsbCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY29sbGFwc2VBbGwoKTtcbiAgICB9XG4gICB9XG5cbiAgICAvKipcbiAgICAgKiBDb2xsYXBzZXMgYWxsIHJvd3Mgb2YgdGhlIGN1cnJlbnQgaGllcmFyY2hpY2FsIGdyaWQuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMuZ3JpZC5jb2xsYXBzZUFsbCgpO1xuICAgICAqIGBgYFxuXHQgKiBAbWVtYmVyb2YgSWd4SGllcmFyY2hpY2FsR3JpZENvbXBvbmVudFxuICAgICAqL1xuICAgIHB1YmxpYyBjb2xsYXBzZUFsbCgpIHtcbiAgICAgICAgdGhpcy5oaWVyYXJjaGljYWxTdGF0ZSA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4cGFuZHMgYWxsIHJvd3Mgb2YgdGhlIGN1cnJlbnQgaGllcmFyY2hpY2FsIGdyaWQuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMuZ3JpZC5leHBhbmRBbGwoKTtcbiAgICAgKiBgYGBcblx0ICogQG1lbWJlcm9mIElneEhpZXJhcmNoaWNhbEdyaWRDb21wb25lbnRcbiAgICAgKi9cbiAgICBwdWJsaWMgZXhwYW5kQWxsKCkge1xuICAgICAgICBpZiAodGhpcy5kYXRhKSB7XG4gICAgICAgICAgICB0aGlzLmhpZXJhcmNoaWNhbFN0YXRlID0gdGhpcy5kYXRhLm1hcCgocmVjKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgcm93SUQ6IHRoaXMucHJpbWFyeUtleSA/IHJlY1t0aGlzLnByaW1hcnlLZXldIDogcmVjIH07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgaXNFeHBhbmRlZChyZWNvcmQ6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgaW5TdGF0ZTtcbiAgICAgICAgaWYgKHJlY29yZC5jaGlsZEdyaWRzRGF0YSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpblN0YXRlID0gISF0aGlzLmhpZXJhcmNoaWNhbFN0YXRlLmZpbmQodiA9PiB2LnJvd0lEID09PSByZWNvcmQucm93SUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5TdGF0ZSA9ICEhdGhpcy5oaWVyYXJjaGljYWxTdGF0ZS5maW5kKHYgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnByaW1hcnlLZXkgPyB2LnJvd0lEID09PSByZWNvcmRbdGhpcy5wcmltYXJ5S2V5XSA6IHYucm93SUQgPT09IHJlY29yZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpblN0YXRlICYmIHRoaXMuY2hpbGRMYXlvdXRMaXN0Lmxlbmd0aCAhPT0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIHZpZXdDcmVhdGVkSGFuZGxlcihhcmdzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzQ2hpbGRHcmlkUmVjb3JkKGFyZ3MuY29udGV4dC4kaW1wbGljaXQpKSB7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSBhcmdzLmNvbnRleHQuJGltcGxpY2l0LnJvd0lEO1xuICAgICAgICAgICAgdGhpcy5jaGlsZEdyaWRUZW1wbGF0ZXMuc2V0KGtleSwgYXJncyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIHZpZXdNb3ZlZEhhbmRsZXIoYXJncykge1xuICAgICAgICBpZiAodGhpcy5pc0NoaWxkR3JpZFJlY29yZChhcmdzLmNvbnRleHQuJGltcGxpY2l0KSkge1xuICAgICAgICAgICAgLy8gdmlldyB3YXMgbW92ZWQsIHVwZGF0ZSBvd25lciBpbiBjYWNoZVxuICAgICAgICAgICAgY29uc3Qga2V5ID0gYXJncy5jb250ZXh0LiRpbXBsaWNpdC5yb3dJRDtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLmNoaWxkR3JpZFRlbXBsYXRlcy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGNhY2hlZERhdGEub3duZXIgPSBhcmdzLm93bmVyO1xuXG4gICAgICAgICAgICB0aGlzLmNoaWxkTGF5b3V0TGlzdC5mb3JFYWNoKChsYXlvdXQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkR3JpZCA9IHRoaXMuaGdyaWRBUEkuZ2V0Q2hpbGRHcmlkQnlJRChsYXlvdXQua2V5LCBhcmdzLmNvbnRleHQuJGltcGxpY2l0LnJvd0lEKTtcbiAgICAgICAgICAgICAgICBpZiAocmVsYXRlZEdyaWQgJiYgcmVsYXRlZEdyaWQudXBkYXRlT25SZW5kZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRGV0ZWN0IGNoYW5nZXMgaWYgYGV4cGFuZENoaWxkcmVuYCBoYXMgY2hhbmdlZCB3aGVuIHRoZSBncmlkIHdhc24ndCB2aXNpYmxlLiBUaGlzIGlzIGZvciBwZXJmb3JtYW5jZSByZWFzb25zLlxuICAgICAgICAgICAgICAgICAgICByZWxhdGVkR3JpZC5ub3RpZnlDaGFuZ2VzKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICByZWxhdGVkR3JpZC51cGRhdGVPblJlbmRlciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBjaGlsZEdyaWRzID0gdGhpcy5nZXRDaGlsZEdyaWRzKHRydWUpO1xuICAgICAgICAgICAgY2hpbGRHcmlkcy5mb3JFYWNoKChncmlkKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGdyaWQuaXNQZXJjZW50V2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JpZC5ub3RpZnlDaGFuZ2VzKHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBncmlkLnVwZGF0ZVNjcm9sbFBvc2l0aW9uKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgdXBkYXRlU2Nyb2xsUG9zaXRpb24oKSB7XG4gICAgICAgIGNvbnN0IHZTY3IgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsQ29udGFpbmVyLmdldFNjcm9sbCgpO1xuICAgICAgICBjb25zdCBoU2NyID0gdGhpcy5oZWFkZXJDb250YWluZXIuZ2V0U2Nyb2xsKCk7XG4gICAgICAgIGlmICh2U2NyKSB7XG4gICAgICAgICAgICB2U2NyLnNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsVG9wO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoU2NyKSB7XG4gICAgICAgICAgICBoU2NyLnNjcm9sbExlZnQgPSB0aGlzLnNjcm9sbExlZnQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0Q2hpbGRHcmlkcyhpbkRlcGg/OiBib29sZWFuKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhncmlkQVBJLmdldENoaWxkR3JpZHMoaW5EZXBoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2VuZXJhdGVEYXRhRmllbGRzKGRhdGE6IGFueVtdKTogc3RyaW5nW10ge1xuICAgICAgICByZXR1cm4gc3VwZXIuZ2VuZXJhdGVEYXRhRmllbGRzKGRhdGEpLmZpbHRlcigoZmllbGQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxheW91dHNMaXN0ID0gdGhpcy5wYXJlbnRJc2xhbmQgPyB0aGlzLnBhcmVudElzbGFuZC5jaGlsZHJlbiA6IHRoaXMuY2hpbGRMYXlvdXRMaXN0O1xuICAgICAgICAgICAgY29uc3Qga2V5cyA9IGxheW91dHNMaXN0Lm1hcCgoaXRlbSkgPT4gaXRlbS5rZXkpO1xuICAgICAgICAgICAgcmV0dXJuIGtleXMuaW5kZXhPZihmaWVsZCkgPT09IC0xO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIHByaXZhdGUgaGdfdmVydGljYWxTY3JvbGxIYW5kbGVyKGV2ZW50KSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG9wID0gZXZlbnQudGFyZ2V0LnNjcm9sbFRvcDtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25Db250YWluZXJTY3JvbGwoKSB7XG4gICAgICAgIHRoaXMuaGlkZU92ZXJsYXlzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoZ19ob3Jpem9udGFsU2Nyb2xsSGFuZGxlcihldmVudCkge1xuICAgICAgICB0aGlzLnNjcm9sbExlZnQgPSBldmVudC50YXJnZXQuc2Nyb2xsTGVmdDtcbiAgICB9XG59XG4iXX0=