@linid-dm/directory-manager-client-core
Version:
Core package by providing a set of angular components for the Directory Manager app.
152 lines • 43.4 kB
JavaScript
import { __decorate } from "tslib";
import { Component, EventEmitter, Input, Output, } from '@angular/core';
import { Select } from '@ngxs/store';
import { Subject, catchError, debounceTime, distinctUntilChanged, filter, of, startWith, switchMap, takeUntil, tap, } from 'rxjs';
import { EResourceComponent, UiState, getDisplayedColumnsIds, getFlattenTreeWithoutTriggeredNodeChildren, getParentNodeId, getSearchRequestScimBody, simpleSearchFormDataElement, } from '../../shared';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "../../shared";
import * as i3 from "@angular/common";
import * as i4 from "@angular/flex-layout/flex";
import * as i5 from "@angular/material/button";
import * as i6 from "@angular/material/form-field";
import * as i7 from "@angular/material/icon";
import * as i8 from "@angular/material/input";
import * as i9 from "@angular/material/tooltip";
import * as i10 from "../../ui/loading-spinner/loading-spinner.component";
export class SearchBarComponent {
constructor(fb, _errorsHandlerService, _dataService, _interactionsService, _el) {
this.fb = fb;
this._errorsHandlerService = _errorsHandlerService;
this._dataService = _dataService;
this._interactionsService = _interactionsService;
this._el = _el;
this._onDestroy$ = new Subject();
this.lastSearchValueHandled = '';
this.isFetchingResources = false;
// Local search inputs
this.isLocalSearchModeEnabled = false;
this.searchResult = new EventEmitter();
this.resetSearch = new EventEmitter();
this.isActiveSearch = new EventEmitter();
this.elementRef = this._el;
}
ngOnInit() {
this.searchForm = this.fb.group({
search: '',
});
this.searchForm
.get('search')
.valueChanges.pipe(debounceTime(600), takeUntil(this._onDestroy$), startWith(this.searchForm.value), distinctUntilChanged((prev, curr) => prev === curr), filter((curr) => {
if (curr === null || curr.length <= 2) {
this.isFetchingResources = false;
this._interactionsService.cancelRequest();
this.resetSearch.emit();
this.isActiveSearch.emit(false);
}
else if (curr === this.lastSearchValueHandled) {
this.isFetchingResources = false;
this._interactionsService.cancelRequest();
}
return (curr !== null &&
curr.length > 2 &&
curr !== this.lastSearchValueHandled);
}), switchMap((_) => {
if (this.isLocalSearchModeEnabled) {
switch (this.resourceTypeComponent) {
case EResourceComponent.TREE:
const flattenDataTree = getFlattenTreeWithoutTriggeredNodeChildren(this.dataToFilter, this.triggerElementId);
const parentNodeId = getParentNodeId(this.triggerElementId, this.dataToFilter);
this.searchResult.emit(flattenDataTree
.map((node) => ({
...node,
link: node.link
.split('/')
.map((linkPart) => decodeURIComponent(linkPart))
.join('/'),
}))
.filter((node) => node.link
.getRidOfDiacritics()
.toLocaleUpperCase()
.includes(this.searchForm
.get('search')
.value.getRidOfDiacritics()
.toLocaleUpperCase()) && node.ids.id !== parentNodeId));
this.isActiveSearch.emit(true);
break;
default:
break;
}
return of(null);
}
else {
const filterScim = simpleSearchFormDataElement(this.searchForm.get('search').value, getDisplayedColumnsIds(this.config));
const searchRequestScimBody = getSearchRequestScimBody(this.searchRequestAttributes);
this.isFetchingResources = true;
return this._dataService
.search(this.endpoint, filterScim, true, searchRequestScimBody, this.extendedMeta)
.pipe(tap((response) => {
this.isFetchingResources = false;
if (response.status === 200 || response.status === 201) {
this.searchResult.emit(response.body);
this.isActiveSearch.emit(true);
this.lastSearchValueHandled =
this.searchForm.get('search').value;
}
}), catchError((err) => {
this.lastSearchValueHandled =
this.searchForm.get('search').value;
this.isFetchingResources = false;
this.isActiveSearch.emit(false);
return this._errorsHandlerService.handleError(err);
}));
}
}))
.subscribe();
}
ngOnDestroy() {
this._onDestroy$.next();
this._onDestroy$.complete();
}
resetSearchForm() {
this._interactionsService.cancelRequest();
this.searchForm.reset();
this.searchForm.enable({ emitEvent: false });
this.resetSearch.emit();
this.isActiveSearch.emit(false);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: SearchBarComponent, deps: [{ token: i1.FormBuilder }, { token: i2.ErrorsHandlerService }, { token: i2.DataService }, { token: i2.InteractionsService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: SearchBarComponent, selector: "dm-search-bar", inputs: { placeholder: "placeholder", triggerElementId: "triggerElementId", config: "config", endpoint: "endpoint", searchRequestAttributes: "searchRequestAttributes", extendedMeta: "extendedMeta", isLocalSearchModeEnabled: "isLocalSearchModeEnabled", dataToFilter: "dataToFilter", resourceTypeComponent: "resourceTypeComponent" }, outputs: { searchResult: "searchResult", resetSearch: "resetSearch", isActiveSearch: "isActiveSearch" }, ngImport: i0, template: "<!-- Copyright (C) 2020-2024 Linagora\n\nThis program is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your option) any\nlater version, provided you comply with the Additional Terms applicable for\nLinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU\nAffero General Public License, subsections (b), (c), and (e), pursuant to\nwhich these Appropriate Legal Notices must notably (i) retain the display of\nthe \"LinID\u2122\" trademark/logo at the top of the interface window, the display\nof the \u201CYou are using the Open Source and free version of LinID\u2122, powered by\nLinagora \u00A9 2009\u20132013. Contribute to LinID R&D by subscribing to an Enterprise\noffer!\u201D infobox and in the e-mails sent with the Program, notice appended to\nany type of outbound messages (e.g. e-mail and meeting requests) as well as\nin the LinID Directory Manager user interface, (ii) retain all hypertext\nlinks between LinID Directory Manager and https://linid.org/, as well as\nbetween LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA\nintellectual property rights over its trademarks and commercial brands. Other\nAdditional Terms apply, see <http://www.linagora.com/licenses/> for more\ndetails.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\ndetails.\n\nYou should have received a copy of the GNU Affero General Public License and\nits applicable Additional Terms for LinID Directory Manager along with this\nprogram. If not, see <http://www.gnu.org/licenses/> for the GNU Affero\nGeneral Public License version 3 and <http://www.linagora.com/licenses/> for\nthe Additional Terms applicable to the LinID Directory Manager software. -->\n\n<form [formGroup]=\"searchForm\" class=\"search-form\">\n <div class=\"div-form-search-input\">\n <div fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <mat-form-field\n *ngIf=\"searchBarAccessibility$ | async as searchBarAccessibility\"\n fxFlex\n color=\"accent\"\n appearance=\"fill\"\n class=\"search-form-field\"\n >\n <mat-label>\n <mat-icon aria-hidden=\"true\">search</mat-icon>\n {{ searchBarAccessibility.label }}\n </mat-label>\n <input\n #searchInput\n type=\"text\"\n matInput\n cdkFocusInitial\n formControlName=\"search\"\n [placeholder]=\"placeholder\"\n (keydown.enter)=\"$event.preventDefault()\"\n class=\"search-input\"\n />\n <mat-hint *ngIf=\"searchInput?.value?.length < 3\">\n {{ searchBarAccessibility.hint }}\n </mat-hint>\n <div\n *ngIf=\"searchInput?.value?.length > 0\"\n matSuffix\n class=\"div-search-suffix-btn\"\n >\n <button\n mat-icon-button\n [attr.aria-label]=\"searchBarAccessibility.clearSearch\"\n (click)=\"resetSearchForm()\"\n class=\"clear-input-btn\"\n [matTooltip]=\"searchBarAccessibility.clearSearch\"\n >\n <mat-icon aria-hidden=\"true\"> clear </mat-icon>\n </button>\n </div>\n </mat-form-field>\n </div>\n </div>\n</form>\n<dm-loading-spinner *ngIf=\"isFetchingResources\"></dm-loading-spinner>\n", styles: ["@charset \"UTF-8\";.div-search-suffix-btn{display:flex}.div-search-suffix-btn mat-icon{display:flex;align-items:center;justify-content:center}.mdc-icon-button:hover{background-color:#e0e0e0}.advanced-search-menu-content{padding:0 20px 20px}.search-form{overflow:hidden}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i4.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i4.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i4.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i10.LoadingSpinnerComponent, selector: "dm-loading-spinner" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
}
__decorate([
Select(UiState.getSearchBarAccessibility)
], SearchBarComponent.prototype, "searchBarAccessibility$", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: SearchBarComponent, decorators: [{
type: Component,
args: [{ selector: 'dm-search-bar', template: "<!-- Copyright (C) 2020-2024 Linagora\n\nThis program is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your option) any\nlater version, provided you comply with the Additional Terms applicable for\nLinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU\nAffero General Public License, subsections (b), (c), and (e), pursuant to\nwhich these Appropriate Legal Notices must notably (i) retain the display of\nthe \"LinID\u2122\" trademark/logo at the top of the interface window, the display\nof the \u201CYou are using the Open Source and free version of LinID\u2122, powered by\nLinagora \u00A9 2009\u20132013. Contribute to LinID R&D by subscribing to an Enterprise\noffer!\u201D infobox and in the e-mails sent with the Program, notice appended to\nany type of outbound messages (e.g. e-mail and meeting requests) as well as\nin the LinID Directory Manager user interface, (ii) retain all hypertext\nlinks between LinID Directory Manager and https://linid.org/, as well as\nbetween LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA\nintellectual property rights over its trademarks and commercial brands. Other\nAdditional Terms apply, see <http://www.linagora.com/licenses/> for more\ndetails.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\ndetails.\n\nYou should have received a copy of the GNU Affero General Public License and\nits applicable Additional Terms for LinID Directory Manager along with this\nprogram. If not, see <http://www.gnu.org/licenses/> for the GNU Affero\nGeneral Public License version 3 and <http://www.linagora.com/licenses/> for\nthe Additional Terms applicable to the LinID Directory Manager software. -->\n\n<form [formGroup]=\"searchForm\" class=\"search-form\">\n <div class=\"div-form-search-input\">\n <div fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <mat-form-field\n *ngIf=\"searchBarAccessibility$ | async as searchBarAccessibility\"\n fxFlex\n color=\"accent\"\n appearance=\"fill\"\n class=\"search-form-field\"\n >\n <mat-label>\n <mat-icon aria-hidden=\"true\">search</mat-icon>\n {{ searchBarAccessibility.label }}\n </mat-label>\n <input\n #searchInput\n type=\"text\"\n matInput\n cdkFocusInitial\n formControlName=\"search\"\n [placeholder]=\"placeholder\"\n (keydown.enter)=\"$event.preventDefault()\"\n class=\"search-input\"\n />\n <mat-hint *ngIf=\"searchInput?.value?.length < 3\">\n {{ searchBarAccessibility.hint }}\n </mat-hint>\n <div\n *ngIf=\"searchInput?.value?.length > 0\"\n matSuffix\n class=\"div-search-suffix-btn\"\n >\n <button\n mat-icon-button\n [attr.aria-label]=\"searchBarAccessibility.clearSearch\"\n (click)=\"resetSearchForm()\"\n class=\"clear-input-btn\"\n [matTooltip]=\"searchBarAccessibility.clearSearch\"\n >\n <mat-icon aria-hidden=\"true\"> clear </mat-icon>\n </button>\n </div>\n </mat-form-field>\n </div>\n </div>\n</form>\n<dm-loading-spinner *ngIf=\"isFetchingResources\"></dm-loading-spinner>\n", styles: ["@charset \"UTF-8\";.div-search-suffix-btn{display:flex}.div-search-suffix-btn mat-icon{display:flex;align-items:center;justify-content:center}.mdc-icon-button:hover{background-color:#e0e0e0}.advanced-search-menu-content{padding:0 20px 20px}.search-form{overflow:hidden}\n"] }]
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.ErrorsHandlerService }, { type: i2.DataService }, { type: i2.InteractionsService }, { type: i0.ElementRef }], propDecorators: { searchBarAccessibility$: [], placeholder: [{
type: Input
}], triggerElementId: [{
type: Input
}], config: [{
type: Input
}], endpoint: [{
type: Input
}], searchRequestAttributes: [{
type: Input
}], extendedMeta: [{
type: Input
}], isLocalSearchModeEnabled: [{
type: Input
}], dataToFilter: [{
type: Input
}], resourceTypeComponent: [{
type: Input
}], searchResult: [{
type: Output
}], resetSearch: [{
type: Output
}], isActiveSearch: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLWJhci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9saWJzL2NsaWVudC1jb3JlL3NyYy9saWIvZmVhdHVyZS9zZWFyY2gtYmFyL3NlYXJjaC1iYXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvbGlicy9jbGllbnQtY29yZS9zcmMvbGliL2ZlYXR1cmUvc2VhcmNoLWJhci9zZWFyY2gtYmFyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFtQ0EsT0FBTyxFQUNMLFNBQVMsRUFFVCxZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sRUFFTCxPQUFPLEVBQ1AsVUFBVSxFQUNWLFlBQVksRUFDWixvQkFBb0IsRUFDcEIsTUFBTSxFQUNOLEVBQUUsRUFDRixTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsRUFDVCxHQUFHLEdBQ0osTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBRUwsa0JBQWtCLEVBUWxCLE9BQU8sRUFDUCxzQkFBc0IsRUFDdEIsMENBQTBDLEVBQzFDLGVBQWUsRUFDZix3QkFBd0IsRUFDeEIsMkJBQTJCLEdBQzVCLE1BQU0sY0FBYyxDQUFDOzs7Ozs7Ozs7Ozs7QUFPdEIsTUFBTSxPQUFPLGtCQUFrQjtJQStCN0IsWUFDVSxFQUFlLEVBQ2YscUJBQTJDLEVBQzNDLFlBQXlCLEVBQ3pCLG9CQUF5QyxFQUN6QyxHQUFlO1FBSmYsT0FBRSxHQUFGLEVBQUUsQ0FBYTtRQUNmLDBCQUFxQixHQUFyQixxQkFBcUIsQ0FBc0I7UUFDM0MsaUJBQVksR0FBWixZQUFZLENBQWE7UUFDekIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFxQjtRQUN6QyxRQUFHLEdBQUgsR0FB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LEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsQyxDQUFDOzhHQWxLVSxrQkFBa0I7a0dBQWxCLGtCQUFrQiwwZUNsRi9CLHFpSEErRUE7O0FES0U7SUFEQyxNQUFNLENBQUMsT0FBTyxDQUFDLHlCQUF5QixDQUFDO21FQUNtQjsyRkFGbEQsa0JBQWtCO2tCQUw5QixTQUFTOytCQUNFLGVBQWU7d01BTXpCLHVCQUF1QixNQVdkLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUdHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUdHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFFSSxZQUFZO3NCQUFyQixNQUFNO2dCQUNHLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChDKSAyMDIwLTIwMjQgTGluYWdvcmFcbiAqXG4gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdCB1bmRlclxuICogdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlXG4gKiBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueVxuICogbGF0ZXIgdmVyc2lvbiwgcHJvdmlkZWQgeW91IGNvbXBseSB3aXRoIHRoZSBBZGRpdGlvbmFsIFRlcm1zIGFwcGxpY2FibGUgZm9yXG4gKiBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciBzb2Z0d2FyZSBieSBMSU5BR09SQSBwdXJzdWFudCB0byBTZWN0aW9uIDcgb2YgdGhlIEdOVVxuICogQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsIHN1YnNlY3Rpb25zIChiKSwgKGMpLCBhbmQgKGUpLCBwdXJzdWFudCB0b1xuICogd2hpY2ggdGhlc2UgQXBwcm9wcmlhdGUgTGVnYWwgTm90aWNlcyBtdXN0IG5vdGFibHkgKGkpIHJldGFpbiB0aGUgZGlzcGxheSBvZlxuICogdGhlIFwiTGluSUTihKJcIiB0cmFkZW1hcmsvbG9nbyBhdCB0aGUgdG9wIG9mIHRoZSBpbnRlcmZhY2Ugd2luZG93LCB0aGUgZGlzcGxheVxuICogb2YgdGhlIOKAnFlvdSBhcmUgdXNpbmcgdGhlIE9wZW4gU291cmNlIGFuZCBmcmVlIHZlcnNpb24gb2YgTGluSUTihKIsIHBvd2VyZWQgYnlcbiAqIExpbmFnb3JhIMKpIDIwMDnigJMyMDEzLiBDb250cmlidXRlIHRvIExpbklEIFImRCBieSBzdWJzY3JpYmluZyB0byBhbiBFbnRlcnByaXNlXG4gKiBvZmZlciHigJ0gaW5mb2JveCBhbmQgaW4gdGhlIGUtbWFpbHMgc2VudCB3aXRoIHRoZSBQcm9ncmFtLCBub3RpY2UgYXBwZW5kZWQgdG9cbiAqIGFueSB0eXBlIG9mIG91dGJvdW5kIG1lc3NhZ2VzIChlLmcuIGUtbWFpbCBhbmQgbWVldGluZyByZXF1ZXN0cykgYXMgd2VsbCBhc1xuICogaW4gdGhlIExpbklEIERpcmVjdG9yeSBNYW5hZ2VyIHVzZXIgaW50ZXJmYWNlLCAoaWkpIHJldGFpbiBhbGwgaHlwZXJ0ZXh0XG4gKiBsaW5rcyBiZXR3ZWVuIExpbklEIERpcmVjdG9yeSBNYW5hZ2VyIGFuZCBodHRwczovL2xpbmlkLm9yZy8sIGFzIHdlbGwgYXNcbiAqIGJldHdlZW4gTElOQUdPUkEgYW5kIExJTkFHT1JBLmNvbSwgYW5kIChpaWkpIHJlZnJhaW4gZnJvbSBpbmZyaW5naW5nIExJTkFHT1JBXG4gKiBpbnRlbGxlY3R1YWwgcHJvcGVydHkgcmlnaHRzIG92ZXIgaXRzIHRyYWRlbWFya3MgYW5kIGNvbW1lcmNpYWwgYnJhbmRzLiBPdGhlclxuICogQWRkaXRpb25hbCBUZXJtcyBhcHBseSwgc2VlIDxodHRwOi8vd3d3LmxpbmFnb3JhLmNvbS9saWNlbnNlcy8+IGZvciBtb3JlXG4gKiBkZXRhaWxzLlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1NcbiAqIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmVcbiAqIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFuZFxuICogaXRzIGFwcGxpY2FibGUgQWRkaXRpb25hbCBUZXJtcyBmb3IgTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgYWxvbmcgd2l0aCB0aGlzXG4gKiBwcm9ncmFtLiBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4gZm9yIHRoZSBHTlUgQWZmZXJvXG4gKiBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMyBhbmQgPGh0dHA6Ly93d3cubGluYWdvcmEuY29tL2xpY2Vuc2VzLz4gZm9yXG4gKiB0aGUgQWRkaXRpb25hbCBUZXJtcyBhcHBsaWNhYmxlIHRvIHRoZSBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciBzb2Z0d2FyZS5cbiAqL1xuXG5pbXBvcnQgeyBIdHRwUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFNlbGVjdCB9IGZyb20gJ0BuZ3hzL3N0b3JlJztcbmltcG9ydCB7XG4gIE9ic2VydmFibGUsXG4gIFN1YmplY3QsXG4gIGNhdGNoRXJyb3IsXG4gIGRlYm91bmNlVGltZSxcbiAgZGlzdGluY3RVbnRpbENoYW5nZWQsXG4gIGZpbHRlcixcbiAgb2YsXG4gIHN0YXJ0V2l0aCxcbiAgc3dpdGNoTWFwLFxuICB0YWtlVW50aWwsXG4gIHRhcCxcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBEYXRhU2VydmljZSxcbiAgRVJlc291cmNlQ29tcG9uZW50LFxuICBFcnJvcnNIYW5kbGVyU2VydmljZSxcbiAgSUNvbmZpZyxcbiAgSURhdGEsXG4gIElEYXRhSXRlbSxcbiAgSURhdGFOb2RlLFxuICBJU2VhcmNoQmFyQWNjZXNzaWJpbGl0eSxcbiAgSW50ZXJhY3Rpb25zU2VydmljZSxcbiAgVWlTdGF0ZSxcbiAgZ2V0RGlzcGxheWVkQ29sdW1uc0lkcyxcbiAgZ2V0RmxhdHRlblRyZWVXaXRob3V0VHJpZ2dlcmVkTm9kZUNoaWxkcmVuLFxuICBnZXRQYXJlbnROb2RlSWQsXG4gIGdldFNlYXJjaFJlcXVlc3RTY2ltQm9keSxcbiAgc2ltcGxlU2VhcmNoRm9ybURhdGFFbGVtZW50LFxufSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdkbS1zZWFyY2gtYmFyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3NlYXJjaC1iYXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9zZWFyY2gtYmFyLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIFNlYXJjaEJhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQFNlbGVjdChVaVN0YXRlLmdldFNlYXJjaEJhckFjY2Vzc2liaWxpdHkpXG4gIHNlYXJjaEJhckFjY2Vzc2liaWxpdHkkOiBPYnNlcnZhYmxlPElTZWFyY2hCYXJBY2Nlc3NpYmlsaXR5PjtcblxuICBwcml2YXRlIF9vbkRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBwdWJsaWMgc2VhcmNoRm9ybTogRm9ybUdyb3VwO1xuXG4gIHB1YmxpYyBlbGVtZW50UmVmOiBFbGVtZW50UmVmO1xuXG4gIHB1YmxpYyBsYXN0U2VhcmNoVmFsdWVIYW5kbGVkID0gJyc7XG4gIHB1YmxpYyBpc0ZldGNoaW5nUmVzb3VyY2VzID0gZmFsc2U7XG5cbiAgQElucHV0KCkgcGxhY2Vob2xkZXI6IHN0cmluZztcbiAgQElucHV0KCkgdHJpZ2dlckVsZW1lbnRJZDogc3RyaW5nO1xuXG4gIC8vIEJhY2tlbmQgc2VhcmNoIGlucHV0c1xuICBASW5wdXQoKSBjb25maWc6IElDb25maWc7XG4gIEBJbnB1dCgpIGVuZHBvaW50OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHNlYXJjaFJlcXVlc3RBdHRyaWJ1dGVzOiBzdHJpbmdbXTtcbiAgQElucHV0KCkgZXh0ZW5kZWRNZXRhOiBib29sZWFuO1xuXG4gIC8vIExvY2FsIHNlYXJjaCBpbnB1dHNcbiAgQElucHV0KCkgaXNMb2NhbFNlYXJjaE1vZGVFbmFibGVkID0gZmFsc2U7XG4gIEBJbnB1dCgpIGRhdGFUb0ZpbHRlcjogSURhdGFOb2RlW10gfCBJRGF0YSB8IElEYXRhSXRlbVtdO1xuICBASW5wdXQoKSByZXNvdXJjZVR5cGVDb21wb25lbnQ6IEVSZXNvdXJjZUNvbXBvbmVudDtcblxuICBAT3V0cHV0KCkgc2VhcmNoUmVzdWx0ID0gbmV3IEV2ZW50RW1pdHRlcjxJRGF0YSB8IElEYXRhTm9kZVtdPigpO1xuICBAT3V0cHV0KCkgcmVzZXRTZWFyY2ggPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIEBPdXRwdXQoKSBpc0FjdGl2ZVNlYXJjaCA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGZiOiBGb3JtQnVpbGRlcixcbiAgICBwcml2YXRlIF9lcnJvcnNIYW5kbGVyU2VydmljZTogRXJyb3JzSGFuZGxlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBfZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlLFxuICAgIHByaXZhdGUgX2ludGVyYWN0aW9uc1NlcnZpY2U6IEludGVyYWN0aW9uc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBfZWw6IEVsZW1lbnRSZWZcbiAgKSB7XG4gICAgdGhpcy5lbGVtZW50UmVmID0gdGhpcy5fZWw7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnNlYXJjaEZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIHNlYXJjaDogJycsXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlYXJjaEZvcm1cbiAgICAgIC5nZXQoJ3NlYXJjaCcpXG4gICAgICAudmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICAgIGRlYm91bmNlVGltZSg2MDApLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95JCksXG4gICAgICAgIHN0YXJ0V2l0aCh0aGlzLnNlYXJjaEZvcm0udmFsdWUpLFxuICAgICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgocHJldiwgY3VycikgPT4gcHJldiA9PT0gY3VyciksXG4gICAgICAgIGZpbHRlcigoY3Vycjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgaWYgKGN1cnIgPT09IG51bGwgfHwgY3Vyci5sZW5ndGggPD0gMikge1xuICAgICAgICAgICAgdGhpcy5pc0ZldGNoaW5nUmVzb3VyY2VzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9pbnRlcmFjdGlvbnNTZXJ2aWNlLmNhbmNlbFJlcXVlc3QoKTtcbiAgICAgICAgICAgIHRoaXMucmVzZXRTZWFyY2guZW1pdCgpO1xuICAgICAgICAgICAgdGhpcy5pc0FjdGl2ZVNlYXJjaC5lbWl0KGZhbHNlKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGN1cnIgPT09IHRoaXMubGFzdFNlYXJjaFZhbHVlSGFuZGxlZCkge1xuICAgICAgICAgICAgdGhpcy5pc0ZldGNoaW5nUmVzb3VyY2VzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9pbnRlcmFjdGlvbnNTZXJ2aWNlLmNhbmNlbFJlcXVlc3QoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGN1cnIgIT09IG51bGwgJiZcbiAgICAgICAgICAgIGN1cnIubGVuZ3RoID4gMiAmJlxuICAgICAgICAgICAgY3VyciAhPT0gdGhpcy5sYXN0U2VhcmNoVmFsdWVIYW5kbGVkXG4gICAgICAgICAgKTtcbiAgICAgICAgfSksXG4gICAgICAgIHN3aXRjaE1hcCgoXykgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLmlzTG9jYWxTZWFyY2hNb2RlRW5hYmxlZCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnJlc291cmNlVHlwZUNvbXBvbmVudCkge1xuICAgICAgICAgICAgICBjYXNlIEVSZXNvdXJjZUNvbXBvbmVudC5UUkVFOlxuICAgICAgICAgICAgICAgIGNvbnN0IGZsYXR0ZW5EYXRhVHJlZTogSURhdGFOb2RlW10gPVxuICAgICAgICAgICAgICAgICAgZ2V0RmxhdHRlblRyZWVXaXRob3V0VHJpZ2dlcmVkTm9kZUNoaWxkcmVuKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFUb0ZpbHRlciBhcyBJRGF0YU5vZGVbXSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyRWxlbWVudElkXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmVudE5vZGVJZDogc3RyaW5nID0gZ2V0UGFyZW50Tm9kZUlkKFxuICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyRWxlbWVudElkLFxuICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhVG9GaWx0ZXIgYXMgSURhdGFOb2RlW11cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMuc2VhcmNoUmVzdWx0LmVtaXQoXG4gICAgICAgICAgICAgICAgICBmbGF0dGVuRGF0YVRyZWVcbiAgICAgICAgICAgICAgICAgICAgLm1hcCgobm9kZTogSURhdGFOb2RlKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgIC4uLm5vZGUsXG4gICAgICAgICAgICAgICAgICAgICAgbGluazogbm9kZS5saW5rXG4gICAgICAgICAgICAgICAgICAgICAgICAuc3BsaXQoJy8nKVxuICAgICAgICAgICAgICAgICAgICAgICAgLm1hcCgobGlua1BhcnQ6IHN0cmluZykgPT4gZGVjb2RlVVJJQ29tcG9uZW50KGxpbmtQYXJ0KSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5qb2luKCcvJyksXG4gICAgICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgIChub2RlOiBJRGF0YU5vZGUpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmxpbmtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLmdldFJpZE9mRGlhY3JpdGljcygpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC50b0xvY2FsZVVwcGVyQ2FzZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5pbmNsdWRlcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlYXJjaEZvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5nZXQoJ3NlYXJjaCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudmFsdWUuZ2V0UmlkT2ZEaWFjcml0aWNzKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50b0xvY2FsZVVwcGVyQ2FzZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICkgJiYgbm9kZS5pZHMuaWQgIT09IHBhcmVudE5vZGVJZFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLmlzQWN0aXZlU2VhcmNoLmVtaXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlclNjaW06IHN0cmluZyA9IHNpbXBsZVNlYXJjaEZvcm1EYXRhRWxlbWVudChcbiAgICAgICAgICAgICAgdGhpcy5zZWFyY2hGb3JtLmdldCgnc2VhcmNoJykudmFsdWUsXG4gICAgICAgICAgICAgIGdldERpc3BsYXllZENvbHVtbnNJZHModGhpcy5jb25maWcpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3Qgc2VhcmNoUmVxdWVzdFNjaW1Cb2R5OiBhbnkgPSBnZXRTZWFyY2hSZXF1ZXN0U2NpbUJvZHkoXG4gICAgICAgICAgICAgIHRoaXMuc2VhcmNoUmVxdWVzdEF0dHJpYnV0ZXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmlzRmV0Y2hpbmdSZXNvdXJjZXMgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGFTZXJ2aWNlXG4gICAgICAgICAgICAgIC5zZWFyY2goXG4gICAgICAgICAgICAgICAgdGhpcy5lbmRwb2ludCxcbiAgICAgICAgICAgICAgICBmaWx0ZXJTY2ltLFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgc2VhcmNoUmVxdWVzdFNjaW1Cb2R5LFxuICAgICAgICAgICAgICAgIHRoaXMuZXh0ZW5kZWRNZXRhXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgdGFwKChyZXNwb25zZTogSHR0cFJlc3BvbnNlPElEYXRhPikgPT4ge1xuICAgICAgICAgICAgICAgICAgdGhpcy5pc0ZldGNoaW5nUmVzb3VyY2VzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAyMDAgfHwgcmVzcG9uc2Uuc3RhdHVzID09PSAyMDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWFyY2hSZXN1bHQuZW1pdChyZXNwb25zZS5ib2R5KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0FjdGl2ZVNlYXJjaC5lbWl0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxhc3RTZWFyY2hWYWx1ZUhhbmRsZWQgPVxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VhcmNoRm9ybS5nZXQoJ3NlYXJjaCcpLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0U2VhcmNoVmFsdWVIYW5kbGVkID1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWFyY2hGb3JtLmdldCgnc2VhcmNoJykudmFsdWU7XG4gICAgICAgICAgICAgICAgICB0aGlzLmlzRmV0Y2hpbmdSZXNvdXJjZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuaXNBY3RpdmVTZWFyY2guZW1pdChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzSGFuZGxlclNlcnZpY2UuaGFuZGxlRXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuX29uRGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuX29uRGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIHJlc2V0U2VhcmNoRm9ybSgpOiB2b2lkIHtcbiAgICB0aGlzLl9pbnRlcmFjdGlvbnNTZXJ2aWNlLmNhbmNlbFJlcXVlc3QoKTtcbiAgICB0aGlzLnNlYXJjaEZvcm0ucmVzZXQoKTtcbiAgICB0aGlzLnNlYXJjaEZvcm0uZW5hYmxlKHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICB0aGlzLnJlc2V0U2VhcmNoLmVtaXQoKTtcbiAgICB0aGlzLmlzQWN0aXZlU2VhcmNoLmVtaXQoZmFsc2UpO1xuICB9XG59XG4iLCI8IS0tIENvcHlyaWdodCAoQykgMjAyMC0yMDI0IExpbmFnb3JhXG5cblRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0IHVuZGVyXG50aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWVcblNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55XG5sYXRlciB2ZXJzaW9uLCBwcm92aWRlZCB5b3UgY29tcGx5IHdpdGggdGhlIEFkZGl0aW9uYWwgVGVybXMgYXBwbGljYWJsZSBmb3JcbkxpbklEIERpcmVjdG9yeSBNYW5hZ2VyIHNvZnR3YXJlIGJ5IExJTkFHT1JBIHB1cnN1YW50IHRvIFNlY3Rpb24gNyBvZiB0aGUgR05VXG5BZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSwgc3Vic2VjdGlvbnMgKGIpLCAoYyksIGFuZCAoZSksIHB1cnN1YW50IHRvXG53aGljaCB0aGVzZSBBcHByb3ByaWF0ZSBMZWdhbCBOb3RpY2VzIG11c3Qgbm90YWJseSAoaSkgcmV0YWluIHRoZSBkaXNwbGF5IG9mXG50aGUgXCJMaW5JROKEolwiIHRyYWRlbWFyay9sb2dvIGF0IHRoZSB0b3Agb2YgdGhlIGludGVyZmFjZSB3aW5kb3csIHRoZSBkaXNwbGF5XG5vZiB0aGUg4oCcWW91IGFyZSB1c2luZyB0aGUgT3BlbiBTb3VyY2UgYW5kIGZyZWUgdmVyc2lvbiBvZiBMaW5JROKEoiwgcG93ZXJlZCBieVxuTGluYWdvcmEgwqkgMjAwOeKAkzIwMTMuIENvbnRyaWJ1dGUgdG8gTGluSUQgUiZEIGJ5IHN1YnNjcmliaW5nIHRvIGFuIEVudGVycHJpc2Vcbm9mZmVyIeKAnSBpbmZvYm94IGFuZCBpbiB0aGUgZS1tYWlscyBzZW50IHdpdGggdGhlIFByb2dyYW0sIG5vdGljZSBhcHBlbmRlZCB0b1xuYW55IHR5cGUgb2Ygb3V0Ym91bmQgbWVzc2FnZXMgKGUuZy4gZS1tYWlsIGFuZCBtZWV0aW5nIHJlcXVlc3RzKSBhcyB3ZWxsIGFzXG5pbiB0aGUgTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgdXNlciBpbnRlcmZhY2UsIChpaSkgcmV0YWluIGFsbCBoeXBlcnRleHRcbmxpbmtzIGJldHdlZW4gTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgYW5kIGh0dHBzOi8vbGluaWQub3JnLywgYXMgd2VsbCBhc1xuYmV0d2VlbiBMSU5BR09SQSBhbmQgTElOQUdPUkEuY29tLCBhbmQgKGlpaSkgcmVmcmFpbiBmcm9tIGluZnJpbmdpbmcgTElOQUdPUkFcbmludGVsbGVjdHVhbCBwcm9wZXJ0eSByaWdodHMgb3ZlciBpdHMgdHJhZGVtYXJrcyBhbmQgY29tbWVyY2lhbCBicmFuZHMuIE90aGVyXG5BZGRpdGlvbmFsIFRlcm1zIGFwcGx5LCBzZWUgPGh0dHA6Ly93d3cubGluYWdvcmEuY29tL2xpY2Vuc2VzLz4gZm9yIG1vcmVcbmRldGFpbHMuXG5cblRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1NcbkZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmVcbmRldGFpbHMuXG5cbllvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbmRcbml0cyBhcHBsaWNhYmxlIEFkZGl0aW9uYWwgVGVybXMgZm9yIExpbklEIERpcmVjdG9yeSBNYW5hZ2VyIGFsb25nIHdpdGggdGhpc1xucHJvZ3JhbS4gSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+IGZvciB0aGUgR05VIEFmZmVyb1xuR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDMgYW5kIDxodHRwOi8vd3d3LmxpbmFnb3JhLmNvbS9saWNlbnNlcy8+IGZvclxudGhlIEFkZGl0aW9uYWwgVGVybXMgYXBwbGljYWJsZSB0byB0aGUgTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgc29mdHdhcmUuIC0tPlxuXG48Zm9ybSBbZm9ybUdyb3VwXT1cInNlYXJjaEZvcm1cIiBjbGFzcz1cInNlYXJjaC1mb3JtXCI+XG4gIDxkaXYgY2xhc3M9XCJkaXYtZm9ybS1zZWFyY2gtaW5wdXRcIj5cbiAgICA8ZGl2IGZ4TGF5b3V0PVwicm93XCIgZnhMYXlvdXRBbGlnbj1cInN0YXJ0IGNlbnRlclwiPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkXG4gICAgICAgICpuZ0lmPVwic2VhcmNoQmFyQWNjZXNzaWJpbGl0eSQgfCBhc3luYyBhcyBzZWFyY2hCYXJBY2Nlc3NpYmlsaXR5XCJcbiAgICAgICAgZnhGbGV4XG4gICAgICAgIGNvbG9yPVwiYWNjZW50XCJcbiAgICAgICAgYXBwZWFyYW5jZT1cImZpbGxcIlxuICAgICAgICBjbGFzcz1cInNlYXJjaC1mb3JtLWZpZWxkXCJcbiAgICAgID5cbiAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICA8bWF0LWljb24gYXJpYS1oaWRkZW49XCJ0cnVlXCI+c2VhcmNoPC9tYXQtaWNvbj5cbiAgICAgICAgICB7eyBzZWFyY2hCYXJBY2Nlc3NpYmlsaXR5LmxhYmVsIH19XG4gICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICAjc2VhcmNoSW5wdXRcbiAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICBjZGtGb2N1c0luaXRpYWxcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJzZWFyY2hcIlxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiXG4gICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIlxuICAgICAgICAgIGNsYXNzPVwic2VhcmNoLWlucHV0XCJcbiAgICAgICAgLz5cbiAgICAgICAgPG1hdC1oaW50ICpuZ0lmPVwic2VhcmNoSW5wdXQ/LnZhbHVlPy5sZW5ndGggPCAzXCI+XG4gICAgICAgICAge3sgc2VhcmNoQmFyQWNjZXNzaWJpbGl0eS5oaW50IH19XG4gICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICAqbmdJZj1cInNlYXJjaElucHV0Py52YWx1ZT8ubGVuZ3RoID4gMFwiXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgY2xhc3M9XCJkaXYtc2VhcmNoLXN1ZmZpeC1idG5cIlxuICAgICAgICA+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cInNlYXJjaEJhckFjY2Vzc2liaWxpdHkuY2xlYXJTZWFyY2hcIlxuICAgICAgICAgICAgKGNsaWNrKT1cInJlc2V0U2VhcmNoRm9ybSgpXCJcbiAgICAgICAgICAgIGNsYXNzPVwiY2xlYXItaW5wdXQtYnRuXCJcbiAgICAgICAgICAgIFttYXRUb29sdGlwXT1cInNlYXJjaEJhckFjY2Vzc2liaWxpdHkuY2xlYXJTZWFyY2hcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxtYXQtaWNvbiBhcmlhLWhpZGRlbj1cInRydWVcIj4gY2xlYXIgPC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZm9ybT5cbjxkbS1sb2FkaW5nLXNwaW5uZXIgKm5nSWY9XCJpc0ZldGNoaW5nUmVzb3VyY2VzXCI+PC9kbS1sb2FkaW5nLXNwaW5uZXI+XG4iXX0=