@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
452 lines • 52.6 kB
JavaScript
var IgxTabsComponent_1;
import { __decorate, __metadata } from "tslib";
import { CommonModule } from '@angular/common';
import { AfterViewInit, Component, ContentChildren, ElementRef, EventEmitter, forwardRef, HostBinding, Input, NgModule, Output, QueryList, ViewChild, ViewChildren, OnDestroy, NgZone } from '@angular/core';
import { IgxBadgeModule } from '../badge/badge.component';
import { IgxRippleModule } from '../directives/ripple/ripple.directive';
import { IgxIconModule } from '../icon/index';
import { IgxTabItemComponent } from './tab-item.component';
import { IgxTabsGroupComponent } from './tabs-group.component';
import { IgxLeftButtonStyleDirective, IgxRightButtonStyleDirective, IgxTabItemTemplateDirective } from './tabs.directives';
import { IgxTabsBase } from './tabs.common';
import ResizeObserver from 'resize-observer-polyfill';
export var TabsType;
(function (TabsType) {
TabsType["FIXED"] = "fixed";
TabsType["CONTENTFIT"] = "contentfit";
})(TabsType || (TabsType = {}));
let IgxTabsComponent = IgxTabsComponent_1 = class IgxTabsComponent {
constructor(_element, _ngZone) {
this._element = _element;
this._ngZone = _ngZone;
/**
*@hidden
*/
this.selectedIndexChange = new EventEmitter();
/**
* Defines the tab header sizing mode. You can choose between `contentfit` or `fixed`.
* By default the header sizing mode is `contentfit`.
* ```html
* <igx-tabs tabsType="fixed">
* <igx-tabs-group label="HOME">Home</igx-tabs-group>
* </igx-tabs>
* ```
*/
this.tabsType = 'contentfit';
/**
* @hidden
*/
this.class = '';
/**
* Emitted when a tab item is deselected.
* ```html
* <igx-tabs (onTabItemDeselected)="itemDeselected($event)">
* <igx-tabs-group label="Tab 1">This is Tab 1 content.</igx-tabs-group>
* <igx-tabs-group label="Tab 2">This is Tab 2 content.</igx-tabs-group>
* </igx-tabs>
* ```
* ```typescript
* itemDeselected(e){
* const tabGroup = e.group;
* const tabItem = e.tab;
* }
* ```
*/
this.onTabItemDeselected = new EventEmitter();
/**
* Emitted when a tab item is selected.
* ```html
* <igx-tabs (onTabItemSelected)="itemSelected($event)">
* <igx-tabs-group label="Tab 1">This is Tab 1 content.</igx-tabs-group>
* <igx-tabs-group label="Tab 2">This is Tab 2 content.</igx-tabs-group>
* </igx-tabs>
* ```
* ```typescript
* itemSelected(e){
* const tabGroup = e.group;
* const tabItem = e.tab;
* }
* ```
*/
this.onTabItemSelected = new EventEmitter();
/**
* @hidden
*/
this.offset = 0;
this._selectedIndex = -1;
}
/**
* An @Input property that sets the value of the `selectedIndex`.
* Default value is 0.
* ```html
* <igx-tabs selectedIndex="1">
* ```
*
* Two-way data binding.
* ```html
* <igx-tabs [(selectedIndex)]="model.selectedIndex">
* ```
*/
get selectedIndex() {
return this._selectedIndex;
}
set selectedIndex(index) {
const newIndex = typeof index !== 'number' ? parseInt(index, 10) : index;
if (this._selectedIndex !== newIndex) {
if (this.tabs && this.tabs.length > 0) {
const newTab = this.tabs.toArray()[newIndex];
if (newTab) {
this.performSelectionChange(newTab);
}
}
else {
this._selectedIndex = newIndex;
}
}
}
/**
* Provides an observable collection of all `IgxTabItemComponent`s.
* First try to get them as content children if not available get them as view children.
* ```typescript
* const tabItems = this.myTabComponent.tabs;
* ```
*/
get tabs() {
if (this.hasContentTabs) {
return this.contentTabs;
}
return this.viewTabs;
}
/**
*@hidden
*/
get hasContentTabs() {
return (this.contentTabs && this.contentTabs.length > 0);
}
/**
* @hidden
*/
get cssClass() {
const defaultStyle = `igx-tabs`;
const fixedStyle = `igx-tabs--fixed`;
const iconStyle = `igx-tabs--icons`;
const iconLabelFoundInGroups = this.groups.find((group) => group.icon != null && group.label != null);
const iconLabelFoundInTabs = this.contentTabs.find((tab) => tab.icon != null && tab.label != null);
let css;
switch (TabsType[this.tabsType.toUpperCase()]) {
case TabsType.FIXED: {
css = fixedStyle;
break;
}
default: {
css = defaultStyle;
break;
}
}
// Layout fix for items with icons
if (iconLabelFoundInGroups !== undefined || iconLabelFoundInTabs !== undefined) {
css = `${css} ${iconStyle}`;
}
return `${css} ${this.class}`;
}
/**
* @hidden
*/
scrollLeft(event) {
this.scroll(false);
}
/**
* @hidden
*/
scrollRight(event) {
this.scroll(true);
}
/**
* @hidden
*/
scrollElement(element, scrollRight) {
const viewPortWidth = this.viewPort.nativeElement.offsetWidth;
this.offset = (scrollRight) ? element.offsetWidth + element.offsetLeft - viewPortWidth : element.offsetLeft;
this.itemsContainer.nativeElement.style.transform = `translate(${-this.offset}px)`;
}
/**
* Gets the selected `IgxTabItemComponent`.
* ```
* const selectedItem = this.myTabComponent.selectedTabItem;
* ```
*/
get selectedTabItem() {
if (this.tabs && this.selectedIndex !== undefined) {
return this.tabs.toArray()[this.selectedIndex];
}
}
/**
* @hidden
*/
ngAfterViewInit() {
if (this._selectedIndex === -1) {
this.tabs.forEach((t) => {
if (t.isSelected) {
this._selectedIndex = t.index;
}
});
}
if (!this.hasContentTabs && (this.selectedIndex < 0 || this.selectedIndex >= this.groups.length)) {
this._selectedIndex = 0;
}
requestAnimationFrame(() => {
const newTab = this.tabs.toArray()[this._selectedIndex];
if (newTab) {
this.performSelection(newTab);
}
else {
this.hideIndicator();
}
});
this._groupChanges$ = this.groups.changes.subscribe(() => {
this.resetSelectionOnCollectionChanged();
});
this._ngZone.runOutsideAngular(() => {
this._resizeObserver = new ResizeObserver(() => {
if (!this.hasContentTabs && this._selectedIndex >= 0 && this._selectedIndex < this.tabs.length) {
const newTab = this.tabs.toArray()[this._selectedIndex];
this.transformContentAnimation(newTab, 0);
}
});
this._resizeObserver.observe(this.tabsContainer.nativeElement);
});
}
/**
* @hidden
*/
ngOnDestroy() {
if (this._groupChanges$) {
this._groupChanges$.unsubscribe();
}
this._ngZone.runOutsideAngular(() => {
this._resizeObserver.disconnect();
});
}
resetSelectionOnCollectionChanged() {
requestAnimationFrame(() => {
const currentTab = this.tabs.toArray()[this.selectedIndex];
if (currentTab) {
this.performSelectionChange(currentTab);
}
else if (this.selectedIndex >= this.tabs.length) {
this.performSelectionChange(this.tabs.last);
}
else {
this.hideIndicator();
}
});
}
scroll(scrollRight) {
const tabsArray = this.tabs.toArray();
for (const tab of tabsArray) {
const element = tab.nativeTabItem.nativeElement;
if (scrollRight) {
if (element.offsetWidth + element.offsetLeft > this.viewPort.nativeElement.offsetWidth + this.offset) {
this.scrollElement(element, scrollRight);
break;
}
}
else {
if (element.offsetWidth + element.offsetLeft >= this.offset) {
this.scrollElement(element, scrollRight);
break;
}
}
}
}
/**
* @hidden
*/
performSelectionChange(newTab) {
const oldTab = this.selectedTabItem;
if (oldTab) {
this.performDeselection(oldTab);
}
if (newTab) {
this.performSelection(newTab);
}
else {
// if there is no new selected tab hide the selection indicator
this.hideIndicator();
}
this.selectedIndexChange.emit(this._selectedIndex);
}
performDeselection(oldTab) {
oldTab.setSelectedInternal(false);
const oldTabRelatedGroup = this.groups.toArray()[oldTab.index];
if (oldTabRelatedGroup) {
oldTabRelatedGroup.setSelectedInternal(false);
}
this._selectedIndex = -1;
this.onTabItemDeselected.emit({ tab: oldTab, group: oldTabRelatedGroup });
}
performSelection(newTab) {
newTab.setSelectedInternal(true);
this._selectedIndex = newTab.index;
let newTabRelatedGroup = null;
if (!this.hasContentTabs && this.groups) {
newTabRelatedGroup = this.groups.toArray()[newTab.index];
if (newTabRelatedGroup) {
newTabRelatedGroup.setSelectedInternal(true);
}
}
this.onTabItemSelected.emit({ tab: newTab, group: newTabRelatedGroup });
requestAnimationFrame(() => {
// bring the new selected tab into view if it is not
this.bringNewTabIntoView(newTab);
// animate the new selection indicator
this.transformIndicatorAnimation(newTab.nativeTabItem.nativeElement);
// animate the new tab's group content
if (!this.hasContentTabs) {
this.transformContentAnimation(newTab, 0.2);
}
});
}
bringNewTabIntoView(newTab) {
const tabNativeElement = newTab.nativeTabItem.nativeElement;
// Scroll left if there is need
if (tabNativeElement.offsetLeft < this.offset) {
this.scrollElement(tabNativeElement, false);
}
// Scroll right if there is need
const viewPortOffsetWidth = this.viewPort.nativeElement.offsetWidth;
const delta = (tabNativeElement.offsetLeft + tabNativeElement.offsetWidth) - (viewPortOffsetWidth + this.offset);
// Fix for IE 11, a difference is accumulated from the widths calculations
if (delta > 1) {
this.scrollElement(tabNativeElement, true);
}
}
/**
* @hidden
*/
// animation for the new panel/group (not needed for tab only mode)
transformContentAnimation(tab, duration) {
const contentOffset = this.tabsContainer.nativeElement.offsetWidth * tab.index;
this.contentsContainer.nativeElement.style.transitionDuration = duration > 0 ? `${duration}s` : 'initial';
this.contentsContainer.nativeElement.style.transform = `translate(${-contentOffset}px)`;
}
/**
* @hidden
*/
transformIndicatorAnimation(element, duration = 0.3) {
if (this.selectedIndicator) {
this.selectedIndicator.nativeElement.style.visibility = 'visible';
this.selectedIndicator.nativeElement.style.transitionDuration = duration > 0 ? `${duration}s` : 'initial';
this.selectedIndicator.nativeElement.style.width = `${element.offsetWidth}px`;
this.selectedIndicator.nativeElement.style.transform = `translate(${element.offsetLeft}px)`;
}
}
hideIndicator() {
if (this.selectedIndicator) {
this.selectedIndicator.nativeElement.style.visibility = 'hidden';
}
}
};
IgxTabsComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: NgZone }
];
__decorate([
ContentChildren(forwardRef(() => IgxTabsGroupComponent)),
__metadata("design:type", QueryList)
], IgxTabsComponent.prototype, "groups", void 0);
__decorate([
ContentChildren(forwardRef(() => IgxTabItemComponent)),
__metadata("design:type", QueryList)
], IgxTabsComponent.prototype, "contentTabs", void 0);
__decorate([
Input(),
__metadata("design:type", Number),
__metadata("design:paramtypes", [Number])
], IgxTabsComponent.prototype, "selectedIndex", null);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxTabsComponent.prototype, "selectedIndexChange", void 0);
__decorate([
Input('tabsType'),
__metadata("design:type", String)
], IgxTabsComponent.prototype, "tabsType", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxTabsComponent.prototype, "class", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxTabsComponent.prototype, "onTabItemDeselected", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxTabsComponent.prototype, "onTabItemSelected", void 0);
__decorate([
ViewChild('contentsContainer', { static: true }),
__metadata("design:type", ElementRef)
], IgxTabsComponent.prototype, "contentsContainer", void 0);
__decorate([
ViewChild('headerContainer', { static: true }),
__metadata("design:type", ElementRef)
], IgxTabsComponent.prototype, "headerContainer", void 0);
__decorate([
ViewChild('itemsContainer', { static: true }),
__metadata("design:type", ElementRef)
], IgxTabsComponent.prototype, "itemsContainer", void 0);
__decorate([
ViewChild('selectedIndicator'),
__metadata("design:type", ElementRef)
], IgxTabsComponent.prototype, "selectedIndicator", void 0);
__decorate([
ViewChild('tabsContainer', { static: true }),
__metadata("design:type", ElementRef)
], IgxTabsComponent.prototype, "tabsContainer", void 0);
__decorate([
ViewChild('viewPort', { static: true }),
__metadata("design:type", ElementRef)
], IgxTabsComponent.prototype, "viewPort", void 0);
__decorate([
ViewChildren(forwardRef(() => IgxTabItemComponent)),
__metadata("design:type", QueryList)
], IgxTabsComponent.prototype, "viewTabs", void 0);
__decorate([
HostBinding('attr.class'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxTabsComponent.prototype, "cssClass", null);
IgxTabsComponent = IgxTabsComponent_1 = __decorate([
Component({
selector: 'igx-tabs',
template: "<!-- TODO Remove tab container from here -->\n<div #tabsContainer>\n <div class=\"igx-tabs__header\" #headerContainer>\n <button igxRipple class=\"igx-tabs__header-button\" igxButton=\"icon\" (click)=\"scrollLeft($event)\" igxLeftButtonStyle>\n <igx-icon fontSet=\"material\">navigate_before</igx-icon>\n </button>\n <div class=\"igx-tabs__header-wrapper-fixed\" #viewPort>\n <div #itemsContainer class=\"igx-tabs__header-wrapper-fluid\">\n <ng-container *ngIf=\"!hasContentTabs\">\n <igx-tab-item igxRipple *ngFor=\"let group of groups\" [relatedGroup]=\"group\">\n </igx-tab-item>\n </ng-container>\n <ng-content select=\"igx-tab-item\"></ng-content>\n <div #selectedIndicator *ngIf=\"groups.length > 0 || contentTabs.length > 0\" class=\"igx-tabs__header-menu-item-indicator\"></div>\n </div>\n </div>\n <button igxRipple class=\"igx-tabs__header-button\" igxButton=\"icon\" (click)=\"scrollRight($event)\" igxRightButtonStyle>\n <igx-icon fontSet=\"material\">navigate_next</igx-icon>\n </button>\n </div>\n <div class=\"igx-tabs__content-fixed\">\n <div #contentsContainer class=\"igx-tabs__content-fluid\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>",
providers: [{ provide: IgxTabsBase, useExisting: IgxTabsComponent_1 }]
}),
__metadata("design:paramtypes", [ElementRef, NgZone])
], IgxTabsComponent);
export { IgxTabsComponent };
/**
* @hidden
*/
let IgxTabsModule = class IgxTabsModule {
};
IgxTabsModule = __decorate([
NgModule({
declarations: [IgxTabsComponent,
IgxTabsGroupComponent,
IgxTabItemComponent,
IgxTabItemTemplateDirective,
IgxRightButtonStyleDirective,
IgxLeftButtonStyleDirective],
exports: [IgxTabsComponent,
IgxTabsGroupComponent,
IgxTabItemComponent,
IgxTabItemTemplateDirective,
IgxRightButtonStyleDirective,
IgxLeftButtonStyleDirective],
imports: [CommonModule, IgxBadgeModule, IgxIconModule, IgxRippleModule]
})
], IgxTabsModule);
export { IgxTabsModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFicy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9pZ25pdGV1aS1hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL3RhYnMvdGFicy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUNILGFBQWEsRUFDYixTQUFTLEVBQ1QsZUFBZSxFQUNmLFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxLQUFLLEVBQ0wsUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNULFlBQVksRUFDWixTQUFTLEVBQ1QsTUFBTSxFQUNULE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDeEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsNEJBQTRCLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMzSCxPQUFPLEVBQUUsV0FBVyxFQUFrQixNQUFNLGVBQWUsQ0FBQztBQUM1RCxPQUFPLGNBQWMsTUFBTSwwQkFBMEIsQ0FBQztBQUV0RCxNQUFNLENBQU4sSUFBWSxRQUdYO0FBSEQsV0FBWSxRQUFRO0lBQ2hCLDJCQUFlLENBQUE7SUFDZixxQ0FBeUIsQ0FBQTtBQUM3QixDQUFDLEVBSFcsUUFBUSxLQUFSLFFBQVEsUUFHbkI7QUFRRCxJQUFhLGdCQUFnQix3QkFBN0IsTUFBYSxnQkFBZ0I7SUFxUXpCLFlBQW9CLFFBQW9CLEVBQVUs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LENBQUM7UUFDUCxRQUFRLEVBQUUsVUFBVTtRQUNwQix1M0NBQWtDO1FBQ2xDLFNBQVMsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsa0JBQWdCLEVBQUUsQ0FBQztLQUN2RSxDQUFDO3FDQXVRZ0MsVUFBVSxFQUFtQixNQUFNO0dBclF4RCxnQkFBZ0IsQ0FnYzVCO1NBaGNZLGdCQUFnQjtBQWtjN0I7O0dBRUc7QUFpQkgsSUFBYSxhQUFhLEdBQTFCLE1BQWEsYUFBYTtDQUN6QixDQUFBO0FBRFksYUFBYTtJQWhCekIsUUFBUSxDQUFDO1FBQ04sWUFBWSxFQUFFLENBQUMsZ0JBQWdCO1lBQzNCLHFCQUFxQjtZQUNyQixtQkFBbUI7WUFDbkIsMkJBQTJCO1lBQzNCLDRCQUE0QjtZQUM1QiwyQkFBMkIsQ0FBQztRQUNoQyxPQUFPLEVBQUUsQ0FBQyxnQkFBZ0I7WUFDdEIscUJBQXFCO1lBQ3JCLG1CQUFtQjtZQUNuQiwyQkFBMkI7WUFDM0IsNEJBQTRCO1lBQzVCLDJCQUEyQixDQUFDO1FBQ2hDLE9BQU8sRUFBRSxDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLGVBQWUsQ0FBQztLQUMxRSxDQUFDO0dBRVcsYUFBYSxDQUN6QjtTQURZLGFBQWEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENvbXBvbmVudCxcbiAgICBDb250ZW50Q2hpbGRyZW4sXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgZm9yd2FyZFJlZixcbiAgICBIb3N0QmluZGluZyxcbiAgICBJbnB1dCxcbiAgICBOZ01vZHVsZSxcbiAgICBPdXRwdXQsXG4gICAgUXVlcnlMaXN0LFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3Q2hpbGRyZW4sXG4gICAgT25EZXN0cm95LFxuICAgIE5nWm9uZVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgSWd4QmFkZ2VNb2R1bGUgfSBmcm9tICcuLi9iYWRnZS9iYWRnZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgSWd4UmlwcGxlTW9kdWxlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9yaXBwbGUvcmlwcGxlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBJZ3hJY29uTW9kdWxlIH0gZnJvbSAnLi4vaWNvbi9pbmRleCc7XG5pbXBvcnQgeyBJZ3hUYWJJdGVtQ29tcG9uZW50IH0gZnJvbSAnLi90YWItaXRlbS5jb21wb25lbnQnO1xuaW1wb3J0IHsgSWd4VGFic0dyb3VwQ29tcG9uZW50IH0gZnJvbSAnLi90YWJzLWdyb3VwLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hMZWZ0QnV0dG9uU3R5bGVEaXJlY3RpdmUsIElneFJpZ2h0QnV0dG9uU3R5bGVEaXJlY3RpdmUsIElneFRhYkl0ZW1UZW1wbGF0ZURpcmVjdGl2ZSB9IGZyb20gJy4vdGFicy5kaXJlY3RpdmVzJztcbmltcG9ydCB7IElneFRhYnNCYXNlLCBJZ3hUYWJJdGVtQmFzZSB9IGZyb20gJy4vdGFicy5jb21tb24nO1xuaW1wb3J0IFJlc2l6ZU9ic2VydmVyIGZyb20gJ3Jlc2l6ZS1vYnNlcnZlci1wb2x5ZmlsbCc7XG5cbmV4cG9ydCBlbnVtIFRhYnNUeXBlIHtcbiAgICBGSVhFRCA9ICdmaXhlZCcsXG4gICAgQ09OVEVOVEZJVCA9ICdjb250ZW50Zml0J1xufVxuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2lneC10YWJzJyxcbiAgICB0ZW1wbGF0ZVVybDogJ3RhYnMuY29tcG9uZW50Lmh0bWwnLFxuICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogSWd4VGFic0Jhc2UsIHVzZUV4aXN0aW5nOiBJZ3hUYWJzQ29tcG9uZW50IH1dXG59KVxuXG5leHBvcnQgY2xhc3MgSWd4VGFic0NvbXBvbmVudCBpbXBsZW1lbnRzIElneFRhYnNCYXNlLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICAgIC8qKlxuICAgICogUHJvdmlkZXMgYW4gb2JzZXJ2YWJsZSBjb2xsZWN0aW9uIG9mIGFsbCBgSWd4VGFic0dyb3VwQ29tcG9uZW50YHMuXG4gICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgKiBjb25zdCBncm91cEl0ZW1zID0gdGhpcy5teVRhYkNvbXBvbmVudC5ncm91cHM7XG4gICAgKiBgYGBcbiAgICAqL1xuICAgIEBDb250ZW50Q2hpbGRyZW4oZm9yd2FyZFJlZigoKSA9PiBJZ3hUYWJzR3JvdXBDb21wb25lbnQpKVxuICAgIHB1YmxpYyBncm91cHM6IFF1ZXJ5TGlzdDxJZ3hUYWJzR3JvdXBDb21wb25lbnQ+O1xuXG4gICAgLyoqXG4gICAgKiBQcm92aWRlcyBhbiBvYnNlcnZhYmxlIGNvbGxlY3Rpb24gb2YgYWxsIGBJZ3hUYWJJdGVtQ29tcG9uZW50YHMgZGVmaW5lZCBpbiB0aGUgcGFnZS5cbiAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAqIGNvbnN0IHRhYkl0ZW1zID0gdGhpcy5teVRhYkNvbXBvbmVudC5jb250ZW50VGFicztcbiAgICAqIGBgYFxuICAgICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihmb3J3YXJkUmVmKCgpID0+IElneFRhYkl0ZW1Db21wb25lbnQpKVxuICAgIHB1YmxpYyBjb250ZW50VGFiczogUXVlcnlMaXN0PElneFRhYkl0ZW1Db21wb25lbnQ+O1xuXG4gICAgLyoqXG4gICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzZXRzIHRoZSB2YWx1ZSBvZiB0aGUgYHNlbGVjdGVkSW5kZXhgLlxuICAgICogRGVmYXVsdCB2YWx1ZSBpcyAwLlxuICAgICogYGBgaHRtbFxuICAgICogPGlneC10YWJzIHNlbGVjdGVkSW5kZXg9XCIxXCI+XG4gICAgKiBgYGBcbiAgICAqXG4gICAgKiBUd28td2F5IGRhdGEgYmluZGluZy5cbiAgICAqIGBgYGh0bWxcbiAgICAqIDxpZ3gtdGFicyBbKHNlbGVjdGVkSW5kZXgpXT1cIm1vZGVsLnNlbGVjdGVkSW5kZXhcIj5cbiAgICAqIGBgYFxuICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2V0IHNlbGVjdGVkSW5kZXgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkSW5kZXg7XG4gICAgfVxuXG4gICAgcHVibGljIHNldCBzZWxlY3RlZEluZGV4KGluZGV4OiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgbmV3SW5kZXggPSB0eXBlb2YgaW5kZXggIT09ICdudW1iZXInID8gcGFyc2VJbnQoaW5kZXgsIDEwKSA6IGluZGV4O1xuICAgICAgICBpZiAodGhpcy5fc2VsZWN0ZWRJbmRleCAhPT0gbmV3SW5kZXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRhYnMgJiYgdGhpcy50YWJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdUYWIgPSB0aGlzLnRhYnMudG9BcnJheSgpW25ld0luZGV4XTtcbiAgICAgICAgICAgICAgICBpZiAobmV3VGFiKSB7XG4gICAgICAgICAgICAgICAgICAgdGhpcy5wZXJmb3JtU2VsZWN0aW9uQ2hhbmdlKG5ld1RhYik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3RlZEluZGV4ID0gbmV3SW5kZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgc2VsZWN0ZWRJbmRleENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyB0aGUgdGFiIGhlYWRlciBzaXppbmcgbW9kZS4gWW91IGNhbiBjaG9vc2UgYmV0d2VlbiBgY29udGVudGZpdGAgb3IgYGZpeGVkYC5cbiAgICAgKiBCeSBkZWZhdWx0IHRoZSBoZWFkZXIgc2l6aW5nIG1vZGUgaXMgYGNvbnRlbnRmaXRgLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LXRhYnMgdGFic1R5cGU9XCJmaXhlZFwiPlxuICAgICAqICAgICA8aWd4LXRhYnMtZ3JvdXAgbGFiZWw9XCJIT01FXCI+SG9tZTwvaWd4LXRhYnMtZ3JvdXA+XG4gICAgICogPC9pZ3gtdGFicz5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoJ3RhYnNUeXBlJylcbiAgICBwdWJsaWMgdGFic1R5cGU6IHN0cmluZyB8IFRhYnNUeXBlID0gJ2NvbnRlbnRmaXQnO1xuXG4gICAgLyoqXG4gICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBjbGFzcyA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHRlZCB3aGVuIGEgdGFiIGl0ZW0gaXMgZGVzZWxlY3RlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC10YWJzIChvblRhYkl0ZW1EZXNlbGVjdGVkKT1cIml0ZW1EZXNlbGVjdGVkKCRldmVudClcIj5cbiAgICAgKiAgICAgIDxpZ3gtdGFicy1ncm91cCBsYWJlbD1cIlRhYiAxXCI+VGhpcyBpcyBUYWIgMSBjb250ZW50LjwvaWd4LXRhYnMtZ3JvdXA+XG4gICAgICogICAgICA8aWd4LXRhYnMtZ3JvdXAgbGFiZWw9XCJUYWIgMlwiPlRoaXMgaXMgVGFiIDIgY29udGVudC48L2lneC10YWJzLWdyb3VwPlxuICAgICAqIDwvaWd4LXRhYnM+XG4gICAgICogYGBgXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGl0ZW1EZXNlbGVjdGVkKGUpe1xuICAgICAqICAgICAgY29uc3QgdGFiR3JvdXAgPSBlLmdyb3VwO1xuICAgICAqICAgICAgY29uc3QgdGFiSXRlbSA9IGUudGFiO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25UYWJJdGVtRGVzZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICogRW1pdHRlZCB3aGVuIGEgdGFiIGl0ZW0gaXMgc2VsZWN0ZWQuXG4gICAgKiBgYGBodG1sXG4gICAgKiA8aWd4LXRhYnMgKG9uVGFiSXRlbVNlbGVjdGVkKT1cIml0ZW1TZWxlY3RlZCgkZXZlbnQpXCI+XG4gICAgKiAgICAgIDxpZ3gtdGFicy1ncm91cCBsYWJlbD1cIlRhYiAxXCI+VGhpcyBpcyBUYWIgMSBjb250ZW50LjwvaWd4LXRhYnMtZ3JvdXA+XG4gICAgKiAgICAgIDxpZ3gtdGFicy1ncm91cCBsYWJlbD1cIlRhYiAyXCI+VGhpcyBpcyBUYWIgMiBjb250ZW50LjwvaWd4LXRhYnMtZ3JvdXA+XG4gICAgKiA8L2lneC10YWJzPlxuICAgICogYGBgXG4gICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgKiBpdGVtU2VsZWN0ZWQoZSl7XG4gICAgKiAgICAgIGNvbnN0IHRhYkdyb3VwID0gZS5ncm91cDtcbiAgICAqICAgICAgY29uc3QgdGFiSXRlbSA9IGUudGFiO1xuICAgICogfVxuICAgICogYGBgXG4gICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25UYWJJdGVtU2VsZWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnY29udGVudHNDb250YWluZXInLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHB1YmxpYyBjb250ZW50c0NvbnRhaW5lcjogRWxlbWVudFJlZjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBAVmlld0NoaWxkKCdoZWFkZXJDb250YWluZXInLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHB1YmxpYyBoZWFkZXJDb250YWluZXI6IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnaXRlbXNDb250YWluZXInLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHB1YmxpYyBpdGVtc0NvbnRhaW5lcjogRWxlbWVudFJlZjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBAVmlld0NoaWxkKCdzZWxlY3RlZEluZGljYXRvcicpXG4gICAgcHVibGljIHNlbGVjdGVkSW5kaWNhdG9yOiBFbGVtZW50UmVmO1xuXG4gICAgLyoqXG4gICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBAVmlld0NoaWxkKCd0YWJzQ29udGFpbmVyJywgeyBzdGF0aWM6IHRydWUgfSlcbiAgICBwdWJsaWMgdGFic0NvbnRhaW5lcjogRWxlbWVudFJlZjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBAVmlld0NoaWxkKCd2aWV3UG9ydCcsIHsgc3RhdGljOiB0cnVlIH0pXG4gICAgcHVibGljIHZpZXdQb3J0OiBFbGVtZW50UmVmO1xuXG4gICAgLyoqXG4gICAgICogUHJvdmlkZXMgYW4gb2JzZXJ2YWJsZSBjb2xsZWN0aW9uIG9mIGFsbCBgSWd4VGFiSXRlbUNvbXBvbmVudGBzLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCB0YWJJdGVtcyA9IHRoaXMubXlUYWJDb21wb25lbnQudmlld1RhYnM7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQFZpZXdDaGlsZHJlbihmb3J3YXJkUmVmKCgpID0+IElneFRhYkl0ZW1Db21wb25lbnQpKVxuICAgIHB1YmxpYyB2aWV3VGFiczogUXVlcnlMaXN0PElneFRhYkl0ZW1Db21wb25lbnQ+O1xuXG4gICAgLyoqXG4gICAgICogUHJvdmlkZXMgYW4gb2JzZXJ2YWJsZSBjb2xsZWN0aW9uIG9mIGFsbCBgSWd4VGFiSXRlbUNvbXBvbmVudGBzLlxuICAgICAqIEZpcnN0IHRyeSB0byBnZXQgdGhlbSBhcyBjb250ZW50IGNoaWxkcmVuIGlmIG5vdCBhdmFpbGFibGUgZ2V0IHRoZW0gYXMgdmlldyBjaGlsZHJlbi5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgdGFiSXRlbXMgPSB0aGlzLm15VGFiQ29tcG9uZW50LnRhYnM7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldCB0YWJzKCk6IFF1ZXJ5TGlzdDxJZ3hUYWJJdGVtQ29tcG9uZW50PiB7XG4gICAgICAgIGlmICh0aGlzLmhhc0NvbnRlbnRUYWJzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZW50VGFicztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy52aWV3VGFicztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGhhc0NvbnRlbnRUYWJzKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKHRoaXMuY29udGVudFRhYnMgJiYgdGhpcy5jb250ZW50VGFicy5sZW5ndGggPiAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGNhbGN1bGF0ZWRXaWR0aDogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyB2aXNpYmxlSXRlbXNXaWR0aDogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBvZmZzZXQgPSAwO1xuXG4gICAgcHJpdmF0ZSBfZ3JvdXBDaGFuZ2VzJDogU3Vic2NyaXB0aW9uO1xuICAgIHByaXZhdGUgX3NlbGVjdGVkSW5kZXggPSAtMTtcbiAgICBwcml2YXRlIF9yZXNpemVPYnNlcnZlcjogUmVzaXplT2JzZXJ2ZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmNsYXNzJylcbiAgICBwdWJsaWMgZ2V0IGNzc0NsYXNzKCkge1xuICAgICAgICBjb25zdCBkZWZhdWx0U3R5bGUgPSBgaWd4LXRhYnNgO1xuICAgICAgICBjb25zdCBmaXhlZFN0eWxlID0gYGlneC10YWJzLS1maXhlZGA7XG4gICAgICAgIGNvbnN0IGljb25TdHlsZSA9IGBpZ3gtdGFicy0taWNvbnNgO1xuICAgICAgICBjb25zdCBpY29uTGFiZWxGb3VuZEluR3JvdXBzID0gdGhpcy5ncm91cHMuZmluZCgoZ3JvdXApID0+IGdyb3VwLmljb24gIT0gbnVsbCAmJiBncm91cC5sYWJlbCAhPSBudWxsKTtcbiAgICAgICAgY29uc3QgaWNvbkxhYmVsRm91bmRJblRhYnMgPSB0aGlzLmNvbnRlbnRUYWJzLmZpbmQoKHRhYikgPT4gdGFiLmljb24gIT0gbnVsbCAmJiB0YWIubGFiZWwgIT0gbnVsbCk7XG4gICAgICAgIGxldCBjc3M7XG4gICAgICAgIHN3aXRjaCAoVGFic1R5cGVbdGhpcy50YWJzVHlwZS50b1VwcGVyQ2FzZSgpXSkge1xuICAgICAgICAgICAgY2FzZSBUYWJzVHlwZS5GSVhFRDoge1xuICAgICAgICAgICAgICAgIGNzcyA9IGZpeGVkU3R5bGU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgICAgICAgY3NzID0gZGVmYXVsdFN0eWxlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTGF5b3V0IGZpeCBmb3IgaXRlbXMgd2l0aCBpY29uc1xuICAgICAgICBpZiAoaWNvbkxhYmVsRm91bmRJbkdyb3VwcyAhPT0gdW5kZWZpbmVkIHx8IGljb25MYWJlbEZvdW5kSW5UYWJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNzcyA9IGAke2Nzc30gJHtpY29uU3R5bGV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBgJHtjc3N9ICR7dGhpcy5jbGFzc31gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2Nyb2xsTGVmdChldmVudCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjcm9sbChmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBzY3JvbGxSaWdodChldmVudCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjcm9sbCh0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIHNjcm9sbEVsZW1lbnQoZWxlbWVudDogYW55LCBzY3JvbGxSaWdodDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBjb25zdCB2aWV3UG9ydFdpZHRoID0gdGhpcy52aWV3UG9ydC5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoO1xuXG4gICAgICAgIHRoaXMub2Zmc2V0ID0gKHNjcm9sbFJpZ2h0KSA/IGVsZW1lbnQub2Zmc2V0V2lkdGggKyBlbGVtZW50Lm9mZnNldExlZnQgLSB2aWV3UG9ydFdpZHRoIDogZWxlbWVudC5vZmZzZXRMZWZ0O1xuICAgICAgICB0aGlzLml0ZW1zQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc3R5bGUudHJhbnNmb3JtID0gYHRyYW5zbGF0ZSgkey10aGlzLm9mZnNldH1weClgO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHNlbGVjdGVkIGBJZ3hUYWJJdGVtQ29tcG9uZW50YC5cbiAgICAgKiBgYGBcbiAgICAgKiBjb25zdCBzZWxlY3RlZEl0ZW0gPSB0aGlzLm15VGFiQ29tcG9uZW50LnNlbGVjdGVkVGFiSXRlbTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXQgc2VsZWN0ZWRUYWJJdGVtKCk6IElneFRhYkl0ZW1Db21wb25lbnQge1xuICAgICAgICBpZiAodGhpcy50YWJzICYmIHRoaXMuc2VsZWN0ZWRJbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50YWJzLnRvQXJyYXkoKVt0aGlzLnNlbGVjdGVkSW5kZXhdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZiwgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUpIHtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3NlbGVjdGVkSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnRhYnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0LmlzU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWRJbmRleCA9IHQuaW5kZXg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuaGFzQ29udGVudFRhYnMgJiYgKHRoaXMuc2VsZWN0ZWRJbmRleCA8IDAgfHwgdGhpcy5zZWxlY3RlZEluZGV4ID49IHRoaXMuZ3JvdXBzLmxlbmd0aCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdGVkSW5kZXggPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1RhYiA9IHRoaXMudGFicy50b0FycmF5KClbdGhpcy5fc2VsZWN0ZWRJbmRleF07XG4gICAgICAgICAgICBpZiAobmV3VGFiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wZXJmb3JtU2VsZWN0aW9uKG5ld1RhYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZUluZGljYXRvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLl9ncm91cENoYW5nZXMkID0gdGhpcy5ncm91cHMuY2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZXNldFNlbGVjdGlvbk9uQ29sbGVjdGlvbkNoYW5nZWQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5fbmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZU9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKCgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaGFzQ29udGVudFRhYnMgJiYgdGhpcy5fc2VsZWN0ZWRJbmRleCA+PSAwICYmIHRoaXMuX3NlbGVjdGVkSW5kZXggPCB0aGlzLnRhYnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld1RhYiA9IHRoaXMudGFicy50b0FycmF5KClbdGhpcy5fc2VsZWN0ZWRJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNmb3JtQ29udGVudEFuaW1hdGlvbihuZXdUYWIsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLl9yZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMudGFic0NvbnRhaW5lci5uYXRpdmVFbGVtZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuX2dyb3VwQ2hhbmdlcyQpIHtcbiAgICAgICAgICAgIHRoaXMuX2dyb3VwQ2hhbmdlcyQudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX25nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZXNpemVPYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVzZXRTZWxlY3Rpb25PbkNvbGxlY3Rpb25DaGFuZ2VkKCk6IHZvaWQge1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFRhYiA9IHRoaXMudGFicy50b0FycmF5KClbdGhpcy5zZWxlY3RlZEluZGV4XTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50VGFiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wZXJmb3JtU2VsZWN0aW9uQ2hhbmdlKGN1cnJlbnRUYWIpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlbGVjdGVkSW5kZXggPj0gdGhpcy50YWJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGVyZm9ybVNlbGVjdGlvbkNoYW5nZSh0aGlzLnRhYnMubGFzdCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlkZUluZGljYXRvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNjcm9sbChzY3JvbGxSaWdodDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBjb25zdCB0YWJzQXJyYXkgPSB0aGlzLnRhYnMudG9BcnJheSgpO1xuICAgICAgICBmb3IgKGNvbnN0IHRhYiBvZiB0YWJzQXJyYXkpIHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0YWIubmF0aXZlVGFiSXRlbS5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgICAgaWYgKHNjcm9sbFJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQub2Zmc2V0V2lkdGggKyBlbGVtZW50Lm9mZnNldExlZnQgPiB0aGlzLnZpZXdQb3J0Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGggKyB0aGlzLm9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbEVsZW1lbnQoZWxlbWVudCwgc2Nyb2xsUmlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50Lm9mZnNldFdpZHRoICsgZWxlbWVudC5vZmZzZXRMZWZ0ID49IHRoaXMub2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsRWxlbWVudChlbGVtZW50LCBzY3JvbGxSaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgcGVyZm9ybVNlbGVjdGlvbkNoYW5nZShuZXdUYWI6IElneFRhYkl0ZW1CYXNlKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG9sZFRhYiA9IHRoaXMuc2VsZWN0ZWRUYWJJdGVtO1xuICAgICAgICBpZiAob2xkVGFiKSB7XG4gICAgICAgICAgICB0aGlzLnBlcmZvcm1EZXNlbGVjdGlvbihvbGRUYWIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdUYWIpIHtcbiAgICAgICAgICAgIHRoaXMucGVyZm9ybVNlbGVjdGlvbihuZXdUYWIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgbm8gbmV3IHNlbGVjdGVkIHRhYiBoaWRlIHRoZSBzZWxlY3Rpb24gaW5kaWNhdG9yXG4gICAgICAgICAgICB0aGlzLmhpZGVJbmRpY2F0b3IoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlbGVjdGVkSW5kZXhDaGFuZ2UuZW1pdCh0aGlzLl9zZWxlY3RlZEluZGV4KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHBlcmZvcm1EZXNlbGVjdGlvbihvbGRUYWI6IElneFRhYkl0ZW1CYXNlKTogdm9pZCB7XG4gICAgICAgIG9sZFRhYi5zZXRTZWxlY3RlZEludGVybmFsKGZhbHNlKTtcbiAgICAgICAgY29uc3Qgb2xkVGFiUmVsYXRlZEdyb3VwID0gdGhpcy5ncm91cHMudG9BcnJheSgpW29sZFRhYi5pbmRleF07XG4gICAgICAgIGlmIChvbGRUYWJSZWxhdGVkR3JvdXApIHtcbiAgICAgICAgICAgIG9sZFRhYlJlbGF0ZWRHcm91cC5zZXRTZWxlY3RlZEludGVybmFsKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zZWxlY3RlZEluZGV4ID0gLTE7XG4gICAgICAgIHRoaXMub25UYWJJdGVtRGVzZWxlY3RlZC5lbWl0KHsgdGFiOiBvbGRUYWIsIGdyb3VwOiBvbGRUYWJSZWxhdGVkR3JvdXAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwZXJmb3JtU2VsZWN0aW9uKG5ld1RhYjogSWd4VGFiSXRlbUJhc2UpOiB2b2lkIHtcbiAgICAgICAgbmV3VGFiLnNldFNlbGVjdGVkSW50ZXJuYWwodHJ1ZSk7XG4gICAgICAgIHRoaXMuX3NlbGVjdGVkSW5kZXggPSBuZXdUYWIuaW5kZXg7XG5cbiAgICAgICAgbGV0IG5ld1RhYlJlbGF0ZWRHcm91cCA9IG51bGw7XG4gICAgICAgIGlmICghdGhpcy5oYXNDb250ZW50VGFicyAmJiB0aGlzLmdyb3Vwcykge1xuICAgICAgICAgICAgbmV3VGFiUmVsYXRlZEdyb3VwID0gdGhpcy5ncm91cHMudG9BcnJheSgpW25ld1RhYi5pbmRleF07XG4gICAgICAgICAgICBpZiAobmV3VGFiUmVsYXRlZEdyb3VwKSB7XG4gICAgICAgICAgICAgICAgbmV3VGFiUmVsYXRlZEdyb3VwLnNldFNlbGVjdGVkSW50ZXJuYWwodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9uVGFiSXRlbVNlbGVjdGVkLmVtaXQoeyB0YWI6IG5ld1RhYiwgZ3JvdXA6IG5ld1RhYlJlbGF0ZWRHcm91cCB9KTtcblxuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAgICAgLy8gYnJpbmcgdGhlIG5ldyBzZWxlY3RlZCB0YWIgaW50byB2aWV3IGlmIGl0IGlzIG5vdFxuICAgICAgICAgICAgdGhpcy5icmluZ05ld1RhYkludG9WaWV3KG5ld1RhYik7XG4gICAgICAgICAgICAvLyBhbmltYXRlIHRoZSBuZXcgc2VsZWN0aW9uIGluZGljYXRvclxuICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm1JbmRpY2F0b3JBbmltYXRpb24obmV3VGFiLm5hdGl2ZVRhYkl0ZW0ubmF0aXZlRWxlbWVudCk7XG4gICAgICAgICAgICAvLyBhbmltYXRlIHRoZSBuZXcgdGFiJ3MgZ3JvdXAgY29udGVudFxuICAgICAgICAgICAgaWYgKCF0aGlzLmhhc0NvbnRlbnRUYWJzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm1Db250ZW50QW5pbWF0aW9uKG5ld1RhYiwgMC4yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBicmluZ05ld1RhYkludG9WaWV3KG5ld1RhYjogSWd4VGFiSXRlbUJhc2UpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdGFiTmF0aXZlRWxlbWVudCA9IG5ld1RhYi5uYXRpdmVUYWJJdGVtLm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICAgICAgLy8gU2Nyb2xsIGxlZnQgaWYgdGhlcmUgaXMgbmVlZFxuICAgICAgICBpZiAodGFiTmF0aXZlRWxlbWVudC5vZmZzZXRMZWZ0IDwgdGhpcy5vZmZzZXQpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsRWxlbWVudCh0YWJOYXRpdmVFbGVtZW50LCBmYWxzZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTY3JvbGwgcmlnaHQgaWYgdGhlcmUgaXMgbmVlZFxuICAgICAgICBjb25zdCB2aWV3UG9ydE9mZnNldFdpZHRoID0gdGhpcy52aWV3UG9ydC5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoO1xuICAgICAgICBjb25zdCBkZWx0YSA9ICh0YWJOYXRpdmVFbGVtZW50Lm9mZnNldExlZnQgKyB0YWJOYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoKSAtICh2aWV3UG9ydE9mZnNldFdpZHRoICsgdGhpcy5vZmZzZXQpO1xuXG4gICAgICAgIC8vIEZpeCBmb3IgSUUgMTEsIGEgZGlmZmVyZW5jZSBpcyBhY2N1bXVsYXRlZCBmcm9tIHRoZSB3aWR0aHMgY2FsY3VsYXRpb25zXG4gICAgICAgIGlmIChkZWx0YSA+IDEp