UNPKG

igniteui-angular

Version:

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

664 lines • 45.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { CommonModule } from '@angular/common'; import { Component, ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, forwardRef, HostBinding, HostListener, Input, NgModule, Output, QueryList, TemplateRef, ViewChildren } from '@angular/core'; import { IgxBadgeModule } from '../badge/badge.component'; import { IgxIconModule } from '../icon/index'; /** * @record */ export function ISelectTabEventArgs() { } if (false) { /** @type {?} */ ISelectTabEventArgs.prototype.tab; /** @type {?} */ ISelectTabEventArgs.prototype.panel; } /** @type {?} */ let NEXT_ID = 0; export class IgxTabTemplateDirective { /** * @param {?} template */ constructor(template) { this.template = template; } } IgxTabTemplateDirective.decorators = [ { type: Directive, args: [{ selector: '[igxTab]' },] } ]; /** @nocollapse */ IgxTabTemplateDirective.ctorParameters = () => [ { type: TemplateRef } ]; if (false) { /** @type {?} */ IgxTabTemplateDirective.prototype.template; } /** * **Ignite UI for Angular Tab Bar** - * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/tabbar.html) * * The Ignite UI Tab Bar enables the user to navigate among a number of content panels displayed in a single view. * * Example: * ```html * <igx-bottom-nav> * <igx-tab-panel label="Tab 1">Tab 1 Content</igx-tab-panel> * <igx-tab-panel label="Tab 2">Tab 2 Content</igx-tab-panel> * <igx-tab-panel label="Tab 3">Tab 3 Content</igx-tab-panel> * </igx-bottom-nav> * ``` */ export class IgxBottomNavComponent { /** * @param {?} _element */ constructor(_element) { this._element = _element; /** * Sets/gets the `id` of the tab bar. * If not set, the `id` of the first tab bar component will be `"igx-bottom-nav-0"`. * ```html * <igx-bottom-nav id = "my-first-tab-bar"></igx-bottom-nav> * ``` * ```typescript * let tabBarId = this.tabBar.id; * ``` * \@memberof IgxBottomNavComponent */ this.id = `igx-bottom-nav-${NEXT_ID++}`; /** * Emits an event when a new tab is selected. * Provides references to the `IgxTabComponent` and `IgxTabPanelComponent` as event arguments. * ```html * <igx-bottom-nav (onTableSelected) = "onTabSelected($event)"><igx-bottom-nav> * ``` * \@memberof IgxBottomNavComponent */ this.onTabSelected = new EventEmitter(); /** * Emits an event when a tab is deselected. * Provides references to the `IgxTabComponent` and `IgxTabPanelComponent` as event arguments. * ```html * <igx-bottom-nav (onTabDeselected) = "onTabDeselected($event)"><igx-bottom-nav> * ``` * \@memberof IgxBottomNavComponent */ this.onTabDeselected = new EventEmitter(); /** * Gets the `index` of selected tab/panel in the respective collection. * ```typescript * let index = this.tabBar.selectedIndex; * ``` * \@memberof IgxBottomNavComponent */ this.selectedIndex = -1; /** * @hidden */ this._itemStyle = 'igx-bottom-nav'; } /** * Gets the `itemStyle` of the tab bar. * ```typescript * let itemStyle = this.tabBar.itemStyle; * ``` * \@memberof IgxBottomNavComponent * @return {?} */ get itemStyle() { return this._itemStyle; } /** * Gets the selected tab in the tab bar. * ```typescript * let tab = this.tabBar.selectedTab; * ``` * \@memberof IgxBottomNavComponent * @return {?} */ get selectedTab() { if (this.tabs && this.selectedIndex !== undefined) { return this.tabs.toArray()[this.selectedIndex]; } } /** * @hidden * @return {?} */ ngAfterViewInit() { // initial selection setTimeout(() => { if (this.selectedIndex === -1) { /** @type {?} */ const selectablePanels = this.panels.filter((p) => !p.disabled); /** @type {?} */ const panel = selectablePanels[0]; if (panel) { panel.select(); } } }, 0); } /** * @hidden * @param {?} args * @return {?} */ _selectedPanelHandler(args) { this.selectedIndex = args.panel.index; this.panels.forEach((p) => { if (p.index !== this.selectedIndex) { this._deselectPanel(p); } }); } /** * @hidden * @private * @param {?} panel * @return {?} */ _deselectPanel(panel) { // Cannot deselect the selected tab - this will mean that there will be not selected tab left if (panel.disabled || this.selectedTab.index === panel.index) { return; } panel.isSelected = false; this.onTabDeselected.emit({ tab: this.tabs[panel.index], panel }); } } IgxBottomNavComponent.decorators = [ { type: Component, args: [{ selector: 'igx-bottom-nav', template: "<div>\n <ng-content></ng-content>\n</div>\n<div #tablist class=\"{{itemStyle}}__menu {{itemStyle}}__menu--bottom\" role=\"tablist\" aria-orientation=\"horizontal\">\n <igx-tab *ngFor=\"let panel of panels\" [id]=\"'igx-tab-' + panel.index\" [attr.aria-label]=\"panel.label\" [attr.aria-disabled]=\"panel.disabled\"\n [attr.aria-selected]=\"panel.isSelected\" [attr.aria-controls]=\"'igx-tab-panel-'+ panel.index\" [ngClass]=\"{\n 'igx-bottom-nav__menu-item': !panel.isSelected && !panel.disabled,\n 'igx-bottom-nav__menu-item--selected': panel.isSelected,\n 'igx-bottom-nav__menu-item--disabled': panel.disabled\n }\" [relatedPanel]=\"panel\" (click)=\"panel.select()\" role=\"tab\">\n </igx-tab>\n</div>\n", styles: [` :host { display: block; } `] }] } ]; /** @nocollapse */ IgxBottomNavComponent.ctorParameters = () => [ { type: ElementRef } ]; IgxBottomNavComponent.propDecorators = { tabs: [{ type: ViewChildren, args: [forwardRef(() => IgxTabComponent),] }], panels: [{ type: ContentChildren, args: [forwardRef(() => IgxTabPanelComponent),] }], id: [{ type: HostBinding, args: ['attr.id',] }, { type: Input }], onTabSelected: [{ type: Output }], onTabDeselected: [{ type: Output }], _selectedPanelHandler: [{ type: HostListener, args: ['onTabSelected', ['$event'],] }] }; if (false) { /** * Gets the `IgxTabComponent` elements in the tab bar component. * ```typescript * let tabs: QueryList<IgxTabComponent> = this.tabBar.tabs; * ``` * \@memberof IgxBottomNavComponent * @type {?} */ IgxBottomNavComponent.prototype.tabs; /** * Gets the `IgxTabPanelComponent` elements in the tab bar component. * ```typescript * let tabPanels: QueryList<IgxTabPanelComponent> = this.tabBar.panels; * ``` * \@memberof IgxBottomNavComponent * @type {?} */ IgxBottomNavComponent.prototype.panels; /** * Sets/gets the `id` of the tab bar. * If not set, the `id` of the first tab bar component will be `"igx-bottom-nav-0"`. * ```html * <igx-bottom-nav id = "my-first-tab-bar"></igx-bottom-nav> * ``` * ```typescript * let tabBarId = this.tabBar.id; * ``` * \@memberof IgxBottomNavComponent * @type {?} */ IgxBottomNavComponent.prototype.id; /** * Emits an event when a new tab is selected. * Provides references to the `IgxTabComponent` and `IgxTabPanelComponent` as event arguments. * ```html * <igx-bottom-nav (onTableSelected) = "onTabSelected($event)"><igx-bottom-nav> * ``` * \@memberof IgxBottomNavComponent * @type {?} */ IgxBottomNavComponent.prototype.onTabSelected; /** * Emits an event when a tab is deselected. * Provides references to the `IgxTabComponent` and `IgxTabPanelComponent` as event arguments. * ```html * <igx-bottom-nav (onTabDeselected) = "onTabDeselected($event)"><igx-bottom-nav> * ``` * \@memberof IgxBottomNavComponent * @type {?} */ IgxBottomNavComponent.prototype.onTabDeselected; /** * Gets the `index` of selected tab/panel in the respective collection. * ```typescript * let index = this.tabBar.selectedIndex; * ``` * \@memberof IgxBottomNavComponent * @type {?} */ IgxBottomNavComponent.prototype.selectedIndex; /** * @hidden * @type {?} * @private */ IgxBottomNavComponent.prototype._itemStyle; /** * @type {?} * @private */ IgxBottomNavComponent.prototype._element; } // ================================= IgxTabPanelComponent ====================================== export class IgxTabPanelComponent { /** * @param {?} _tabBar * @param {?} _element */ constructor(_tabBar, _element) { this._tabBar = _tabBar; this._element = _element; /** * @hidden */ this._itemStyle = 'igx-tab-panel'; /** * Gets the role of the tab panel. * ```typescript * let tabPanelRole = this.tabPanel.role; * ``` * \@memberof IgxTabPanelComponent */ this.role = 'tabpanel'; /** * Sets/gets whether a tab panel is selected. * ```typescript * this.tabPanel.isSelected = true; * ``` * ```typescript * let isSelected = this.tabPanelIsSelected; * ``` * \@memberof IgxTabPanelComponent */ this.isSelected = false; } /** * Gets whether a tab panel will have `igx-bottom-nav__panel` class. * ```typescript * let styleClass = this.tabPanel.styleClass; * ``` * \@memberof IgxTabPanelComponent * @return {?} */ get styleClass() { return (!this.isSelected); } /** * Gets the `itemStyle` of the tab panel. * ```typescript * let itemStyle = this.tabPanel.itemStyle; * ``` * \@memberof IgxTabPanelComponent * @return {?} */ get itemStyle() { return this._itemStyle; } /** * Gets the tab associated with the panel. * ```typescript * let tab = this.tabPanel.relatedTab; * ``` * \@memberof IgxTabPanelComponent * @return {?} */ get relatedTab() { if (this._tabBar.tabs) { return this._tabBar.tabs.toArray()[this.index]; } } /** * Gets the index of a panel in the panels collection. * ```typescript * let panelIndex = this.tabPanel.index * ``` * \@memberof IgxTabPanelComponent * @return {?} */ get index() { if (this._tabBar.panels) { return this._tabBar.panels.toArray().indexOf(this); } } /** * Gets the tab template. * ```typescript * let tabTemplate = this.tabPanel.customTabTemplate * ``` * \@memberof IgxTabPanelComponent * @return {?} */ get customTabTemplate() { return this._tabTemplate; } /** * Sets the tab template. * ```typescript * this.tabPanel.customTabTemplate(tabTemplate); * ``` * \@memberof IgxTabPanelComponent * @param {?} template * @return {?} */ set customTabTemplate(template) { this._tabTemplate = template; } /** * @hidden * @return {?} */ ngAfterContentInit() { if (this.tabTemplate) { this._tabTemplate = this.tabTemplate.template; } } /** * @hidden * @return {?} */ ngAfterViewChecked() { this._element.nativeElement.setAttribute('aria-labelledby', `igx-tab-${this.index}`); this._element.nativeElement.setAttribute('id', `igx-bottom-nav__panel-${this.index}`); } /** * Selects the current tab and the tab panel. * ```typescript * this.tabPanel.select(); * ``` * \@memberof IgxTabPanelComponent * @return {?} */ select() { if (this.disabled || this._tabBar.selectedIndex === this.index) { return; } this.isSelected = true; this._tabBar.onTabSelected.emit({ tab: this._tabBar.tabs.toArray()[this.index], panel: this }); } } IgxTabPanelComponent.decorators = [ { type: Component, args: [{ selector: 'igx-tab-panel', template: "<ng-content></ng-content>\n" }] } ]; /** @nocollapse */ IgxTabPanelComponent.ctorParameters = () => [ { type: IgxBottomNavComponent }, { type: ElementRef } ]; IgxTabPanelComponent.propDecorators = { label: [{ type: Input }], icon: [{ type: Input }], disabled: [{ type: Input }], role: [{ type: HostBinding, args: ['attr.role',] }], styleClass: [{ type: HostBinding, args: ['class.igx-bottom-nav__panel',] }], isSelected: [{ type: HostBinding, args: ['class.igx-bottom-nav__panel--selected',] }], tabTemplate: [{ type: ContentChild, args: [IgxTabTemplateDirective, { read: IgxTabTemplateDirective },] }] }; if (false) { /** * @hidden * @type {?} * @private */ IgxTabPanelComponent.prototype._itemStyle; /** * Sets/gets the `label` of the tab panel. * ```html * <igx-tab-panel [label] = "'Tab panel label'"><igx-tab-panel> * ``` * ```typescript * let tabPanelLabel = this.tabPanel.label; * ``` * \@memberof IgxTabPanelComponent * @type {?} */ IgxTabPanelComponent.prototype.label; /** * Sets/gets the `icon` of the tab panel. * ```html * <igx-tab-panel [icon] = "panel_icon"><igx-tab-panel> * ``` * ```typescript * let tabPanelIcon = this.tabPanel.icon; * ``` * \@memberof IgxTabPanelComponent * @type {?} */ IgxTabPanelComponent.prototype.icon; /** * Sets/gets whether the tab panel is disabled. * ```html * <igx-tab-panel [disabled] = "true"><igx-tab-panel> * ``` * ```typescript * let isDisabled = this.tabPanel.disabled; * ``` * \@memberof IgxTabPanelComponent * @type {?} */ IgxTabPanelComponent.prototype.disabled; /** * Gets the role of the tab panel. * ```typescript * let tabPanelRole = this.tabPanel.role; * ``` * \@memberof IgxTabPanelComponent * @type {?} */ IgxTabPanelComponent.prototype.role; /** * Sets/gets whether a tab panel is selected. * ```typescript * this.tabPanel.isSelected = true; * ``` * ```typescript * let isSelected = this.tabPanelIsSelected; * ``` * \@memberof IgxTabPanelComponent * @type {?} */ IgxTabPanelComponent.prototype.isSelected; /** * @hidden * @type {?} * @private */ IgxTabPanelComponent.prototype._tabTemplate; /** * @hidden * @type {?} * @protected */ IgxTabPanelComponent.prototype.tabTemplate; /** * @type {?} * @private */ IgxTabPanelComponent.prototype._tabBar; /** * @type {?} * @private */ IgxTabPanelComponent.prototype._element; } // ======================================= IgxTabComponent ========================================== export class IgxTabComponent { /** * @param {?} _tabBar * @param {?} _element */ constructor(_tabBar, _element) { this._tabBar = _tabBar; this._element = _element; /** * Gets the `role` attribute. * ```typescript * let tabRole = this.tab.role; * ``` * \@memberof IgxTabComponent */ this.role = 'tab'; /** * @hidden */ this._changesCount = 0; // changes and updates accordingly applied to the tab. } // changes and updates accordingly applied to the tab. /** * Gets the changes and updates accordingly applied to the tab. * * \@memberof IgxTabComponent * @return {?} */ get changesCount() { return this._changesCount; } /** * Gets whether the tab is disabled. * ```typescript * let isDisabled = this.tab.disabled; * ``` * \@memberof IgxTabComponent * @return {?} */ get disabled() { /** @type {?} */ const panel = this.relatedPanel; if (panel) { return panel.disabled; } } /** * Gets whether the tab is selected. * ```typescript * let isSelected = this.tab.isSelected; * ``` * \@memberof IgxTabComponent * @return {?} */ get isSelected() { /** @type {?} */ const panel = this.relatedPanel; if (panel) { return panel.isSelected; } } /** * Gets the `index` of the tab. * ```typescript * let tabIndex = this.tab.index; * ``` * \@memberof IgxTabComponent * @return {?} */ get index() { return this._tabBar.tabs.toArray().indexOf(this); } /** * Selects the current tab and the associated panel. * ```typescript * this.tab.select(); * ``` * \@memberof IgxTabComponent * @return {?} */ select() { this.relatedPanel.select(); } } IgxTabComponent.decorators = [ { type: Component, args: [{ selector: 'igx-tab', template: "<ng-template #defaultTabTemplate>\n <div *ngIf=\"relatedPanel.icon\" class=\"tab-icon\">\n <igx-icon fontSet=\"material\">{{relatedPanel.icon}}</igx-icon>\n <igx-badge [value]=\"changesCount\" [hidden]=\"changesCount === 0\"></igx-badge>\n </div>\n <div *ngIf=\"relatedPanel.label\" ngClass=\"tab-label\">{{relatedPanel.label}}</div>\n</ng-template>\n<ng-container *ngTemplateOutlet=\"relatedPanel.customTabTemplate ? relatedPanel.customTabTemplate : defaultTabTemplate; context: { $implicit: relatedPanel }\">\n</ng-container>" }] } ]; /** @nocollapse */ IgxTabComponent.ctorParameters = () => [ { type: IgxBottomNavComponent }, { type: ElementRef } ]; IgxTabComponent.propDecorators = { role: [{ type: HostBinding, args: ['attr.role',] }], relatedPanel: [{ type: Input }] }; if (false) { /** * Gets the `role` attribute. * ```typescript * let tabRole = this.tab.role; * ``` * \@memberof IgxTabComponent * @type {?} */ IgxTabComponent.prototype.role; /** * Gets the panel associated with the tab. * ```typescript * let tabPanel = this.tab.relatedPanel; * ``` * \@memberof IgxTabComponent * @type {?} */ IgxTabComponent.prototype.relatedPanel; /** * @hidden * @type {?} * @private */ IgxTabComponent.prototype._changesCount; /** * @type {?} * @private */ IgxTabComponent.prototype._tabBar; /** * @type {?} * @private */ IgxTabComponent.prototype._element; } /** * @hidden */ export class IgxBottomNavModule { } IgxBottomNavModule.decorators = [ { type: NgModule, args: [{ declarations: [IgxBottomNavComponent, IgxTabPanelComponent, IgxTabComponent, IgxTabTemplateDirective], exports: [IgxBottomNavComponent, IgxTabPanelComponent, IgxTabComponent, IgxTabTemplateDirective], imports: [CommonModule, IgxBadgeModule, IgxIconModule] },] } ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvdGFiYmFyL3RhYmJhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBSUgsU0FBUyxFQUNULFlBQVksRUFDWixlQUFlLEVBQ2YsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osS0FBSyxFQUNMLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULFdBQVcsRUFFWCxZQUFZLEVBQ2YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxlQUFlLENBQUM7Ozs7QUFFOUMseUNBR0M7OztJQUZHLGtDQUFxQjs7SUFDckIsb0NBQTRCOzs7SUFHNUIsT0FBTyxHQUFHLENBQUM7QUFLZixNQUFNLE9BQU8sdUJBQXVCOzs7O0lBRWhDLFlBQW1CLFFBQTBCO1FBQTFCLGFBQVEsR0FBUixRQUFRLENBQWtCO0lBQzdDLENBQUM7OztZQU5KLFNBQVMsU0FBQztnQkFDUCxRQUFRLEVBQUUsVUFBVTthQUN2Qjs7OztZQWhCRyxXQUFXOzs7O0lBbUJDLDJDQUFpQzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUEyQmpELE1BQU0sT0FBTyxxQkFBcUI7Ozs7SUFxRjlCLFlBQW9CLFFBQW9CO1FBQXBCLGFBQVEsR0FBUixRQUFRLENBQVk7Ozs7Ozs7Ozs7OztRQXREakMsT0FBRSxHQUFHLGtCQUFrQixPQUFPLEVBQUUsRUFBRSxDQUFDOzs7Ozs7Ozs7UUFTekIsa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBdUIsQ0FBQzs7Ozs7Ozs7O1FBU3hELG9CQUFlLEdBQUcsSUFBSSxZ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Ozs7SUFROUMsdUNBQW1EOzs7Ozs7SUFJbkQsd0NBQTBCOzs7OztJQWdEZCxrQ0FBc0M7Ozs7O0lBQUUsbUNBQTRCOzs7OztBQXNCcEYsTUFBTSxPQUFPLGtCQUFrQjs7O1lBTDlCLFFBQVEsU0FBQztnQkFDTixZQUFZLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxvQkFBb0IsRUFBRSxlQUFlLEVBQUUsdUJBQXVCLENBQUM7Z0JBQ3JHLE9BQU8sRUFBRSxDQUFDLHFCQUFxQixFQUFFLG9CQUFvQixFQUFFLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQztnQkFDaEcsT0FBTyxFQUFFLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxhQUFhLENBQUM7YUFDekQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBBZnRlckNvbnRlbnRJbml0LFxuICAgIEFmdGVyVmlld0NoZWNrZWQsXG4gICAgQWZ0ZXJWaWV3SW5pdCxcbiAgICBDb21wb25lbnQsXG4gICAgQ29udGVudENoaWxkLFxuICAgIENvbnRlbnRDaGlsZHJlbixcbiAgICBEaXJlY3RpdmUsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgZm9yd2FyZFJlZixcbiAgICBIb3N0QmluZGluZyxcbiAgICBIb3N0TGlzdGVuZXIsXG4gICAgSW5wdXQsXG4gICAgTmdNb2R1bGUsXG4gICAgT3V0cHV0LFxuICAgIFF1ZXJ5TGlzdCxcbiAgICBUZW1wbGF0ZVJlZixcbiAgICBWaWV3Q2hpbGQsXG4gICAgVmlld0NoaWxkcmVuXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSWd4QmFkZ2VNb2R1bGUgfSBmcm9tICcuLi9iYWRnZS9iYWRnZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgSWd4SWNvbk1vZHVsZSB9IGZyb20gJy4uL2ljb24vaW5kZXgnO1xuXG5leHBvcnQgaW50ZXJmYWNlIElTZWxlY3RUYWJFdmVudEFyZ3Mge1xuICAgIHRhYjogSWd4VGFiQ29tcG9uZW50O1xuICAgIHBhbmVsOiBJZ3hUYWJQYW5lbENvbXBvbmVudDtcbn1cblxubGV0IE5FWFRfSUQgPSAwO1xuXG5ARGlyZWN0aXZlKHtcbiAgICBzZWxlY3RvcjogJ1tpZ3hUYWJdJ1xufSlcbmV4cG9ydCBjbGFzcyBJZ3hUYWJUZW1wbGF0ZURpcmVjdGl2ZSB7XG5cbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4pIHtcbiAgICB9XG59XG4vKipcbiAqICoqSWduaXRlIFVJIGZvciBBbmd1bGFyIFRhYiBCYXIqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvdGFiYmFyLmh0bWwpXG4gKlxuICogVGhlIElnbml0ZSBVSSBUYWIgQmFyIGVuYWJsZXMgdGhlIHVzZXIgdG8gbmF2aWdhdGUgYW1vbmcgYSBudW1iZXIgb2YgY29udGVudCBwYW5lbHMgZGlzcGxheWVkIGluIGEgc2luZ2xlIHZpZXcuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYGh0bWxcbiAqIDxpZ3gtYm90dG9tLW5hdj5cbiAqICAgPGlneC10YWItcGFuZWwgbGFiZWw9XCJUYWIgMVwiPlRhYiAxIENvbnRlbnQ8L2lneC10YWItcGFuZWw+XG4gKiAgIDxpZ3gtdGFiLXBhbmVsIGxhYmVsPVwiVGFiIDJcIj5UYWIgMiBDb250ZW50PC9pZ3gtdGFiLXBhbmVsPlxuICogICA8aWd4LXRhYi1wYW5lbCBsYWJlbD1cIlRhYiAzXCI+VGFiIDMgQ29udGVudDwvaWd4LXRhYi1wYW5lbD5cbiAqIDwvaWd4LWJvdHRvbS1uYXY+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdpZ3gtYm90dG9tLW5hdicsXG4gICAgdGVtcGxhdGVVcmw6ICd0YWItYmFyLWNvbnRlbnQuY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlczogW2BcbiAgICAgICAgOmhvc3Qge1xuICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgIH1cbiAgICBgXVxufSlcbmV4cG9ydCBjbGFzcyBJZ3hCb3R0b21OYXZDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0IHtcbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBgSWd4VGFiQ29tcG9uZW50YCBlbGVtZW50cyBpbiB0aGUgdGFiIGJhciBjb21wb25lbnQuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0YWJzOiBRdWVyeUxpc3Q8SWd4VGFiQ29tcG9uZW50PiA9ICB0aGlzLnRhYkJhci50YWJzO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hCb3R0b21OYXZDb21wb25lbnRcbiAgICAgKi9cbiAgICBAVmlld0NoaWxkcmVuKGZvcndhcmRSZWYoKCkgPT4gSWd4VGFiQ29tcG9uZW50KSkgcHVibGljIHRhYnM6IFF1ZXJ5TGlzdDxJZ3hUYWJDb21wb25lbnQ+O1xuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGBJZ3hUYWJQYW5lbENvbXBvbmVudGAgZWxlbWVudHMgaW4gdGhlIHRhYiBiYXIgY29tcG9uZW50LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdGFiUGFuZWxzOiBRdWVyeUxpc3Q8SWd4VGFiUGFuZWxDb21wb25lbnQ+ID0gdGhpcy50YWJCYXIucGFuZWxzO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hCb3R0b21OYXZDb21wb25lbnRcbiAgICAgKi9cbiAgICBAQ29udGVudENoaWxkcmVuKGZvcndhcmRSZWYoKCkgPT4gSWd4VGFiUGFuZWxDb21wb25lbnQpKSBwdWJsaWMgcGFuZWxzOiBRdWVyeUxpc3Q8SWd4VGFiUGFuZWxDb21wb25lbnQ+O1xuXG4gICAgLyoqXG4gICAgICogU2V0cy9nZXRzIHRoZSBgaWRgIG9mIHRoZSB0YWIgYmFyLlxuICAgICAqIElmIG5vdCBzZXQsIHRoZSBgaWRgIG9mIHRoZSBmaXJzdCB0YWIgYmFyIGNvbXBvbmVudCB3aWxsIGJlIGBcImlneC1ib3R0b20tbmF2LTBcImAuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtYm90dG9tLW5hdiBpZCA9IFwibXktZmlyc3QtdGFiLWJhclwiPjwvaWd4LWJvdHRvbS1uYXY+XG4gICAgICogYGBgXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0YWJCYXJJZCA9ICB0aGlzLnRhYkJhci5pZDtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4Qm90dG9tTmF2Q29tcG9uZW50XG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmlkJylcbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZCA9IGBpZ3gtYm90dG9tLW5hdi0ke05FWFRfSUQrK31gO1xuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gYSBuZXcgdGFiIGlzIHNlbGVjdGVkLlxuICAgICAqIFByb3ZpZGVzIHJlZmVyZW5jZXMgdG8gdGhlIGBJZ3hUYWJDb21wb25lbnRgIGFuZCBgSWd4VGFiUGFuZWxDb21wb25lbnRgIGFzIGV2ZW50IGFyZ3VtZW50cy5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1ib3R0b20tbmF2IChvblRhYmxlU2VsZWN0ZWQpID0gXCJvblRhYlNlbGVjdGVkKCRldmVudClcIj48aWd4LWJvdHRvbS1uYXY+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEJvdHRvbU5hdkNvbXBvbmVudFxuICAgICAqL1xuICAgIEBPdXRwdXQoKSBwdWJsaWMgb25UYWJTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8SVNlbGVjdFRhYkV2ZW50QXJncz4oKTtcbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIGEgdGFiIGlzIGRlc2VsZWN0ZWQuXG4gICAgICogUHJvdmlkZXMgcmVmZXJlbmNlcyB0byB0aGUgYElneFRhYkNvbXBvbmVudGAgYW5kIGBJZ3hUYWJQYW5lbENvbXBvbmVudGAgYXMgZXZlbnQgYXJndW1lbnRzLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LWJvdHRvbS1uYXYgKG9uVGFiRGVzZWxlY3RlZCkgPSBcIm9uVGFiRGVzZWxlY3RlZCgkZXZlbnQpXCI+PGlneC1ib3R0b20tbmF2PlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hCb3R0b21OYXZDb21wb25lbnRcbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcHVibGljIG9uVGFiRGVzZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8SVNlbGVjdFRhYkV2ZW50QXJncz4oKTtcbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBgaW5kZXhgIG9mIHNlbGVjdGVkIHRhYi9wYW5lbCBpbiB0aGUgcmVzcGVjdGl2ZSBjb2xsZWN0aW9uLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgaW5kZXggPSAgdGhpcy50YWJCYXIuc2VsZWN0ZWRJbmRleDtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4Qm90dG9tTmF2Q29tcG9uZW50XG4gICAgICovXG4gICAgcHVibGljIHNlbGVjdGVkSW5kZXggPSAtMTtcbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBgaXRlbVN0eWxlYCBvZiB0aGUgdGFiIGJhci5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IGl0ZW1TdHlsZSA9ICB0aGlzLnRhYkJhci5pdGVtU3R5bGU7XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneEJvdHRvbU5hdkNvbXBvbmVudFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgaXRlbVN0eWxlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pdGVtU3R5bGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqQGhpZGRlblxuICAgICAqL1xuICAgIHByaXZhdGUgX2l0ZW1TdHlsZSA9ICdpZ3gtYm90dG9tLW5hdic7XG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgc2VsZWN0ZWQgdGFiIGluIHRoZSB0YWIgYmFyLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdGFiID0gIHRoaXMudGFiQmFyLnNlbGVjdGVkVGFiO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hCb3R0b21OYXZDb21wb25lbnRcbiAgICAgKi9cbiAgICBnZXQgc2VsZWN0ZWRUYWIoKTogSWd4VGFiQ29tcG9uZW50IHtcbiAgICAgICAgaWYgKHRoaXMudGFicyAmJiB0aGlzLnNlbGVjdGVkSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGFicy50b0FycmF5KClbdGhpcy5zZWxlY3RlZEluZGV4XTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX2VsZW1lbnQ6IEVsZW1lbnRSZWYpIHtcbiAgICB9XG4gICAgLyoqXG4gICAgICpAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAgICAgLy8gaW5pdGlhbCBzZWxlY3Rpb25cbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGFibGVQYW5lbHMgPSB0aGlzLnBhbmVscy5maWx0ZXIoKHApID0+ICFwLmRpc2FibGVkKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwYW5lbCA9IHNlbGVjdGFibGVQYW5lbHNbMF07XG5cbiAgICAgICAgICAgICAgICBpZiAocGFuZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFuZWwuc2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICpAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RMaXN0ZW5lcignb25UYWJTZWxlY3RlZCcsIFsnJGV2ZW50J10pXG4gICAgcHVibGljIF9zZWxlY3RlZFBhbmVsSGFuZGxlcihhcmdzKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRJbmRleCA9IGFyZ3MucGFuZWwuaW5kZXg7XG5cbiAgICAgICAgdGhpcy5wYW5lbHMuZm9yRWFjaCgocCkgPT4ge1xuICAgICAgICAgICAgaWYgKHAuaW5kZXggIT09IHRoaXMuc2VsZWN0ZWRJbmRleCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2VsZWN0UGFuZWwocCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9kZXNlbGVjdFBhbmVsKHBhbmVsOiBJZ3hUYWJQYW5lbENvbXBvbmVudCkge1xuICAgICAgICAvLyBDYW5ub3QgZGVzZWxlY3QgdGhlIHNlbGVjdGVkIHRhYiAtIHRoaXMgd2lsbCBtZWFuIHRoYXQgdGhlcmUgd2lsbCBiZSBub3Qgc2VsZWN0ZWQgdGFiIGxlZnRcbiAgICAgICAgaWYgKHBhbmVsLmRpc2FibGVkIHx8IHRoaXMuc2VsZWN0ZWRUYWIuaW5kZXggPT09IHBhbmVsLmluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBwYW5lbC5pc1NlbGVjdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMub25UYWJEZXNlbGVjdGVkLmVtaXQoeyB0YWI6IHRoaXMudGFic1twYW5lbC5pbmRleF0sIHBhbmVsIH0pO1xuICAgIH1cbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IElneFRhYlBhbmVsQ29tcG9uZW50ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnaWd4LXRhYi1wYW5lbCcsXG4gICAgdGVtcGxhdGVVcmw6ICd0YWItcGFuZWwuY29tcG9uZW50Lmh0bWwnXG59KVxuXG5leHBvcnQgY2xhc3MgSWd4VGFiUGFuZWxDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBBZnRlclZpZXdDaGVja2VkIHtcbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9pdGVtU3R5bGUgPSAnaWd4LXRhYi1wYW5lbCc7XG4gICAgLyoqXG4gICAgICogU2V0cy9nZXRzIHRoZSBgbGFiZWxgIG9mIHRoZSB0YWIgcGFuZWwuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtdGFiLXBhbmVsIFtsYWJlbF0gPSBcIidUYWIgcGFuZWwgbGFiZWwnXCI+PGlneC10YWItcGFuZWw+XG4gICAgICogYGBgXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0YWJQYW5lbExhYmVsID0gdGhpcy50YWJQYW5lbC5sYWJlbDtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiUGFuZWxDb21wb25lbnRcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgbGFiZWw6IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBTZXRzL2dldHMgIHRoZSBgaWNvbmAgb2YgdGhlIHRhYiBwYW5lbC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC10YWItcGFuZWwgW2ljb25dID0gXCJwYW5lbF9pY29uXCI+PGlneC10YWItcGFuZWw+XG4gICAgICogYGBgXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGxldCB0YWJQYW5lbEljb24gPSAgdGhpcy50YWJQYW5lbC5pY29uO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJQYW5lbENvbXBvbmVudFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBpY29uOiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogU2V0cy9nZXRzIHdoZXRoZXIgdGhlIHRhYiBwYW5lbCBpcyBkaXNhYmxlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC10YWItcGFuZWwgW2Rpc2FibGVkXSA9IFwidHJ1ZVwiPjxpZ3gtdGFiLXBhbmVsPlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgaXNEaXNhYmxlZCA9IHRoaXMudGFiUGFuZWwuZGlzYWJsZWQ7XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneFRhYlBhbmVsQ29tcG9uZW50XG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIGRpc2FibGVkOiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJvbGUgb2YgdGhlIHRhYiBwYW5lbC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IHRhYlBhbmVsUm9sZSA9IHRoaXMudGFiUGFuZWwucm9sZTtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiUGFuZWxDb21wb25lbnRcbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIucm9sZScpIHB1YmxpYyByb2xlID0gJ3RhYnBhbmVsJztcbiAgICAvKipcbiAgICAgKiBHZXRzIHdoZXRoZXIgYSB0YWIgcGFuZWwgd2lsbCBoYXZlIGBpZ3gtYm90dG9tLW5hdl9fcGFuZWxgIGNsYXNzLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgc3R5bGVDbGFzcyA9IHRoaXMudGFiUGFuZWwuc3R5bGVDbGFzcztcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiUGFuZWxDb21wb25lbnRcbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLmlneC1ib3R0b20tbmF2X19wYW5lbCcpXG4gICAgZ2V0IHN0eWxlQ2xhc3MoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoIXRoaXMuaXNTZWxlY3RlZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldHMvZ2V0cyB3aGV0aGVyIGEgdGFiIHBhbmVsIGlzIHNlbGVjdGVkLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnRhYlBhbmVsLmlzU2VsZWN0ZWQgPSB0cnVlO1xuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgaXNTZWxlY3RlZCA9ICB0aGlzLnRhYlBhbmVsSXNTZWxlY3RlZDtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiUGFuZWxDb21wb25lbnRcbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLmlneC1ib3R0b20tbmF2X19wYW5lbC0tc2VsZWN0ZWQnKVxuICAgIHB1YmxpYyBpc1NlbGVjdGVkID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYGl0ZW1TdHlsZWAgb2YgdGhlIHRhYiBwYW5lbC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IGl0ZW1TdHlsZSA9IHRoaXMudGFiUGFuZWwuaXRlbVN0eWxlO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJQYW5lbENvbXBvbmVudFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgaXRlbVN0eWxlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pdGVtU3R5bGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHRhYiBhc3NvY2lhdGVkIHdpdGggdGhlIHBhbmVsLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdGFiID0gdGhpcy50YWJQYW5lbC5yZWxhdGVkVGFiO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJQYW5lbENvbXBvbmVudFxuICAgICAqL1xuICAgIGdldCByZWxhdGVkVGFiKCk6IElneFRhYkNvbXBvbmVudCB7XG4gICAgICAgIGlmICh0aGlzLl90YWJCYXIudGFicykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RhYkJhci50YWJzLnRvQXJyYXkoKVt0aGlzLmluZGV4XTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbmRleCBvZiBhIHBhbmVsIGluIHRoZSBwYW5lbHMgY29sbGVjdGlvbi5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IHBhbmVsSW5kZXggPSAgdGhpcy50YWJQYW5lbC5pbmRleFxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJQYW5lbENvbXBvbmVudFxuICAgICAqL1xuICAgIGdldCBpbmRleCgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3RhYkJhci5wYW5lbHMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl90YWJCYXIucGFuZWxzLnRvQXJyYXkoKS5pbmRleE9mKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHRhYiB0ZW1wbGF0ZS5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IHRhYlRlbXBsYXRlID0gdGhpcy50YWJQYW5lbC5jdXN0b21UYWJUZW1wbGF0ZVxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJQYW5lbENvbXBvbmVudFxuICAgICAqL1xuICAgIGdldCBjdXN0b21UYWJUZW1wbGF0ZSgpOiBUZW1wbGF0ZVJlZjxhbnk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RhYlRlbXBsYXRlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0YWIgdGVtcGxhdGUuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMudGFiUGFuZWwuY3VzdG9tVGFiVGVtcGxhdGUodGFiVGVtcGxhdGUpO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJQYW5lbENvbXBvbmVudFxuICAgICAqL1xuICAgIHNldCBjdXN0b21UYWJUZW1wbGF0ZSh0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55Pikge1xuICAgICAgICB0aGlzLl90YWJUZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIF90YWJUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgICAvKipcbiAgICAgKkBoaWRkZW5cbiAgICAgKi9cbiAgICBAQ29udGVudENoaWxkKElneFRhYlRlbXBsYXRlRGlyZWN0aXZlLCB7IHJlYWQ6IElneFRhYlRlbXBsYXRlRGlyZWN0aXZlIH0pXG4gICAgcHJvdGVjdGVkIHRhYlRlbXBsYXRlOiBJZ3hUYWJUZW1wbGF0ZURpcmVjdGl2ZTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX3RhYkJhcjogSWd4Qm90dG9tTmF2Q29tcG9uZW50LCBwcml2YXRlIF9lbGVtZW50OiBFbGVtZW50UmVmKSB7XG4gICAgfVxuICAgIC8qKlxuICAgICAqQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ0FmdGVyQ29udGVudEluaXQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnRhYlRlbXBsYXRlKSB7XG4gICAgICAgICAgICB0aGlzLl90YWJUZW1wbGF0ZSA9IHRoaXMudGFiVGVtcGxhdGUudGVtcGxhdGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICpAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3Q2hlY2tlZCgpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbGxlZGJ5JywgYGlneC10YWItJHt0aGlzLmluZGV4fWApO1xuICAgICAgICB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdpZCcsIGBpZ3gtYm90dG9tLW5hdl9fcGFuZWwtJHt0aGlzLmluZGV4fWApO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIHRoZSBjdXJyZW50IHRhYiBhbmQgdGhlIHRhYiBwYW5lbC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy50YWJQYW5lbC5zZWxlY3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiUGFuZWxDb21wb25lbnRcbiAgICAgKi9cbiAgICBwdWJsaWMgc2VsZWN0KCkge1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCB0aGlzLl90YWJCYXIuc2VsZWN0ZWRJbmRleCA9PT0gdGhpcy5pbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5pc1NlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fdGFiQmFyLm9uVGFiU2VsZWN0ZWQuZW1pdCh7IHRhYjogdGhpcy5fdGFiQmFyLnRhYnMudG9BcnJheSgpW3RoaXMuaW5kZXhdLCBwYW5lbDogdGhpcyB9KTtcbiAgICB9XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSBJZ3hUYWJDb21wb25lbnQgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnaWd4LXRhYicsXG4gICAgdGVtcGxhdGVVcmw6ICd0YWIuY29tcG9uZW50Lmh0bWwnXG59KVxuXG5leHBvcnQgY2xhc3MgSWd4VGFiQ29tcG9uZW50IHtcbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBgcm9sZWAgYXR0cmlidXRlLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgdGFiUm9sZSA9IHRoaXMudGFiLnJvbGU7XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneFRhYkNvbXBvbmVudFxuICAgICAqL1xuICAgIEBIb3N0QmluZGluZygnYXR0ci5yb2xlJykgcHVibGljIHJvbGUgPSAndGFiJztcbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwYW5lbCBhc3NvY2lhdGVkIHdpdGggdGhlIHRhYi5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IHRhYlBhbmVsID0gIHRoaXMudGFiLnJlbGF0ZWRQYW5lbDtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiQ29tcG9uZW50XG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIHJlbGF0ZWRQYW5lbDogSWd4VGFiUGFuZWxDb21wb25lbnQ7XG4gICAgLyoqXG4gICAgICpAaGlkZGVuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfY2hhbmdlc0NvdW50ID0gMDsgLy8gY2hhbmdlcyBhbmQgdXBkYXRlcyBhY2NvcmRpbmdseSBhcHBsaWVkIHRvIHRoZSB0YWIuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgY2hhbmdlcyBhbmQgdXBkYXRlcyBhY2NvcmRpbmdseSBhcHBsaWVkIHRvIHRoZSB0YWIuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiQ29tcG9uZW50XG4gICAgICovXG4gICAgZ2V0IGNoYW5nZXNDb3VudCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2hhbmdlc0NvdW50O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXRzIHdoZXRoZXIgdGhlIHRhYiBpcyBkaXNhYmxlZC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IGlzRGlzYWJsZWQgPSB0aGlzLnRhYi5kaXNhYmxlZDtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiQ29tcG9uZW50XG4gICAgICovXG4gICAgZ2V0IGRpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBwYW5lbCA9IHRoaXMucmVsYXRlZFBhbmVsO1xuXG4gICAgICAgIGlmIChwYW5lbCkge1xuICAgICAgICAgICAgcmV0dXJuIHBhbmVsLmRpc2FibGVkO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgd2hldGhlciB0aGUgdGFiIGlzIHNlbGVjdGVkLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBsZXQgaXNTZWxlY3RlZCAgPSB0aGlzLnRhYi5pc1NlbGVjdGVkO1xuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hUYWJDb21wb25lbnRcbiAgICAgKi9cbiAgICBnZXQgaXNTZWxlY3RlZCgpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgcGFuZWwgPSB0aGlzLnJlbGF0ZWRQYW5lbDtcblxuICAgICAgICBpZiAocGFuZWwpIHtcbiAgICAgICAgICAgIHJldHVybiBwYW5lbC5pc1NlbGVjdGVkO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGBpbmRleGAgb2YgdGhlIHRhYi5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbGV0IHRhYkluZGV4ID0gdGhpcy50YWIuaW5kZXg7XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneFRhYkNvbXBvbmVudFxuICAgICAqL1xuICAgIGdldCBpbmRleCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fdGFiQmFyLnRhYnMudG9BcnJheSgpLmluZGV4T2YodGhpcyk7XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfdGFiQmFyOiBJZ3hCb3R0b21OYXZDb21wb25lbnQsIHByaXZhdGUgX2VsZW1lbnQ6IEVsZW1lbnRSZWYpIHtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VsZWN0cyB0aGUgY3VycmVudCB0YWIgYW5kIHRoZSBhc3NvY2lhdGVkIHBhbmVsLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnRhYi5zZWxlY3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4VGFiQ29tcG9uZW50XG4gICAgICovXG4gICAgcHVibGljIHNlbGVjdCgpIHtcbiAgICAgICAgdGhpcy5yZWxhdGVkUGFuZWwuc2VsZWN0KCk7XG4gICAgfVxufVxuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuQE5nTW9kdWxlKHtcbiAgICBkZWNsYXJhdGlvbnM6IFtJZ3hCb3R0b21OYXZDb21wb25lbnQsIElneFRhYlBhbmVsQ29tcG9uZW50LCBJZ3hUYWJDb21wb25lbnQsIElneFRhYlRlbXBsYXRlRGlyZWN0aXZlXSxcbiAgICBleHBvcnRzOiBbSWd4Qm90dG9tTmF2Q29tcG9uZW50LCBJZ3hUYWJQYW5lbENvbXBvbmVudCwgSWd4VGFiQ29tcG9uZW50LCBJZ3hUYWJUZW1wbGF0ZURpcmVjdGl2ZV0sXG4gICAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgSWd4QmFkZ2VNb2R1bGUsIElneEljb25Nb2R1bGVdXG59KVxuZXhwb3J0IGNsYXNzIElneEJvdHRvbU5hdk1vZHVsZSB7XG59XG4iXX0=