right-angled
Version:
Lightweight and easy to use angular data grids. Integrates with your markup and styles rather than generating its own.
370 lines • 47.1 kB
JavaScript
import { EventEmitter, Inject, Injectable, InjectionToken, Optional, SkipSelf } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { RTFiltersService } from '../../filters/filters.service';
import { destroyAll } from '../../utilities';
import { RTSortingsService } from './sortings.service';
import { OperationStatus } from '../../core/operation-status';
import { AsyncSubscriber } from './async-subscriber';
import { NullObjectPager } from './null-object-pager';
import { map } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "./async-subscriber";
import * as i2 from "./state.service";
import * as i3 from "./sortings.service";
import * as i4 from "../../filters/filters.service";
export const RTFilterTarget = new InjectionToken('RTFilterTarget');
export class OperationStatusStream {
}
export class RTList {
/**
* Global settings of list..
*
* These settings are static and their values are copied to the properties of the same name for each instance of {@link RTList} type.
*
* So, changing of this settings will affect all instances of {@link RTList} type that will be created after such changes.
* If you want to change settings of concrete object you can use it the same name properties.
*/
static { this.settings = {
/**
* @see {@link RTList.keepRecordsOnLoad}
*/
keepRecordsOnLoad: false
}; }
constructor(asyncSubscriber, stateServices, // | RTStateService[],
filterTargets, sortingsService, filtersService) {
this.asyncSubscriber = asyncSubscriber;
this.sortingsService = sortingsService;
this.filtersService = filtersService;
this.loadStarted = new EventEmitter();
this.loadSucceed = new EventEmitter();
this.loadFailed = new EventEmitter();
this.filterTargets = [];
/**
* Specifies that list must destroy previously loaded records immediately or keep them until data request is completed.
*/
this.keepRecordsOnLoad = RTList.settings.keepRecordsOnLoad;
/**
* Can be used with `Observable` data sourceto specify that list must keep previously loaded records or destroy them when new value published
*/
this.appendStreamedData = null;
/**
* Array of registered {@link RTStateService} instances.
*/
this.stateServices = new Array();
/**
* Async implementation of @see RTList.status
*/
this.status$ = new BehaviorSubject(OperationStatus.Initial);
/**
* Async implementation of @see RTList.destroyed
*/
this.destroyed$ = new BehaviorSubject(false);
/**
* Async implementation of @see RTList.inited
*/
this.inited$ = new BehaviorSubject(false);
/**
* Async implementation of @see RTList.items
*/
this.items$ = new BehaviorSubject([]);
/**
* Async implementation of @see RTList.busy
*/
this.busy$ = this.status$.pipe(map(status => status === OperationStatus.Progress));
/**
* Async implementation of @see RTList.ready
*/
this.ready$ = this.status$.pipe(map(status => status !== OperationStatus.Progress));
this.loadDataSuccessCallback = (response) => {
if (this.tryInterceptStatusResponse(response)) {
return response;
}
this.tryCleanItemsOnLoad(true);
return this.loadSuccessCallback(response);
};
this.reloadDataSuccessCallback = (response) => {
if (this.tryInterceptStatusResponse(response)) {
return response;
}
this.tryCleanItemsOnReload(true);
return this.loadSuccessCallback(response);
};
this.loadDataFailCallback = () => {
this.tryCleanItemsOnLoad(true);
this.loadFailCallback();
};
this.reloadDataFailCallback = () => {
this.tryCleanItemsOnReload(true);
this.loadFailCallback();
};
if (stateServices != null) {
if (Array.isArray(stateServices)) {
this.stateServices.push(...stateServices);
}
else {
this.stateServices.push(stateServices);
}
}
this.pager = new NullObjectPager();
if (filterTargets != null) {
if (Array.isArray(filterTargets)) {
this.filterTargets.push(...filterTargets);
}
else {
this.filterTargets.push(filterTargets);
}
}
}
/**
* Array of elements transferred in the {@link ListResponse.items} property.
*/
get items() {
return this.items$.getValue();
}
/**
* Configured {@link Pager} service.
*/
get pager() {
return this.pagerInternal;
}
set pager(value) {
this.filtersService.removeFilterTarget(this.pagerInternal);
this.pagerInternal = value;
this.filtersService.registerFilterTarget(this.pagerInternal);
}
/**
* True if the service was already destroyed via {@link destroy} call.
*/
get destroyed() {
return this.destroyed$.getValue();
}
/**
* True if the service was already initialized via {@link init} call.
*/
get inited() {
return this.inited$.getValue();
}
/**
* Current execution status of the list.
*/
get status() {
return this.status$.getValue();
}
/**
* returns `true`, if there is a data request executed at the moment (i.e. {@link state} is equal to {@link ProgressState.Progress})
*/
get busy() {
return this.status === OperationStatus.Progress;
}
/**
* returns `true`, if there is no data request executed at the moment (i.e. {@link state} is NOT equal to {@link ProgressState.Progress})
*/
get ready() {
return this.status !== OperationStatus.Progress;
}
/**
* Performs initialization logic of the service. This method must be called before first use of the service.
*/
init() {
if (this.inited) {
return;
}
this.filtersService.registerFilterTarget(...this.filterTargets);
this.filtersService.registerFilterTarget(this.pager, this.sortingsService);
const restoredState = {};
Object.assign(restoredState, ...this.stateServices.map((service) => service.getState() || {}));
this.filtersService.applyParams(restoredState);
this.inited$.next(true);
}
/**
* Performs destroy logic of the list itself and all of the inner services.
*/
destroy() {
this.asyncSubscriber.destroy();
this.filtersService.destroy();
this.sortingsService.destroy();
this.clearData();
this.destroyed$.next(true);
}
/**
* Registers passed object(s) as state service to manage the list state.
*/
registerStateService(...services) {
services.forEach((service) => {
this.stateServices.push(service);
});
}
/**
* Removes passed object(s) from state services collection of the list.
*/
removeStateService(...services) {
services.forEach((service) => {
const index = this.stateServices.findIndex((s) => s === service);
if (index !== -1) {
this.stateServices.splice(index, 1);
}
});
}
/**
* Registers passed object(s) as filter targets in underlying {@link FiltersService} to include their configured properties as parameters to the data request.
* @see {@link FiltersService.registerFilterTarget}
*/
registerFilterTarget(...targets) {
this.filtersService.registerFilterTarget(...targets);
}
/**
* @see {@link FiltersService.removeFilterTarget}
*/
removeFilterTarget(...targets) {
this.filtersService.removeFilterTarget(...targets);
}
/**
* @see {@link FiltersService.getRequestState}
*/
getRequestState(filterFn) {
return this.filtersService.getRequestState(filterFn);
}
/**
* Resets the list parameters (sortings, paging, filters) to their default values.
*/
resetSettings() {
this.asyncSubscriber.detach();
this.filtersService.resetValues();
this.pager.reset();
this.clearData();
this.status$.next(OperationStatus.Initial);
}
/**
* Cancels the request executed at the moment.
*/
cancelRequests() {
if (this.busy || this.appendStreamedData !== null) {
this.asyncSubscriber.detach();
this.status$.next(OperationStatus.Cancelled);
this.clearData();
}
}
/**
* Clears {@link items} array. Calls {@link destroyAll} method for {@link items} array to perform optional destroy logic of the elements.
* {@see destroyAll}
*/
clearData() {
destroyAll(this.items);
this.items$.next([]);
}
/**
* Performs data loading by calling specified {@link fetchMethod} delegate.
* @return result of {@link fetchMethod} execution.
*/
loadData() {
if (this.busy) {
return null;
}
this.loadStarted.emit();
const subscribable = this.beginRequest();
this.tryCleanItemsOnLoad(false);
this.asyncSubscriber.attach(subscribable, this.loadDataSuccessCallback, this.loadDataFailCallback);
this.stateServices.forEach((service) => {
service.persistState(this.filtersService);
});
return subscribable;
}
/**
* Resets paging parameters and performs data loading by calling {@link loadData} if list not in {@link OperationStatus.Progress} state.
* @return result of {@link fetchMethod} if it was called. `null` otherwise.
*/
reloadData() {
if (this.busy) {
return null;
}
this.loadStarted.emit();
this.pager.reset();
const subscribable = this.beginRequest();
this.tryCleanItemsOnReload(false);
this.asyncSubscriber.attach(subscribable, this.reloadDataSuccessCallback, this.reloadDataFailCallback);
this.stateServices.forEach((service) => {
service.persistState(this.filtersService);
});
return subscribable;
}
/**
* Callback which is executed if {@link fetchMethod} execution finished successfully.
*/
loadSuccessCallback(response) {
const items = Array.isArray(response) ? response : response.items;
this.items$.next(this.items.concat(items));
this.pager.processResponse(response);
// In case when filter changed from last request and there's no data now
// Don't do this for flat responses since we don't know real count items
if (!Array.isArray(response) && this.pager.totalCount === 0) {
this.clearData();
this.pager.reset();
}
this.status$.next(this.pager.totalCount === 0 && this.items.length === 0 ? OperationStatus.NoData : OperationStatus.Done);
this.loadSucceed.emit(response);
return response;
}
/**
* Callback which is executed if {@link fetchMethod} execution finished with error.
*/
loadFailCallback() {
this.tryCleanItemsOnLoad(true);
this.status$.next(OperationStatus.Fail);
this.loadFailed.emit();
}
tryInterceptStatusResponse(response) {
if (this.responseHasStatus(response)) {
switch (response.status) {
case OperationStatus.Fail:
this.reloadDataFailCallback();
return true;
case OperationStatus.Cancelled:
this.cancelRequests();
return true;
case OperationStatus.Progress:
return true;
}
}
return false;
}
tryCleanItemsOnLoad(requestCompleted) {
if (this.keepRecordsOnLoad === requestCompleted && this.pager.appendedOnLoad === false) {
this.clearData();
}
if (requestCompleted && this.appendStreamedData === false) {
this.clearData();
}
}
tryCleanItemsOnReload(requestCompleted) {
if (this.keepRecordsOnLoad === requestCompleted) {
this.clearData();
}
if (requestCompleted && this.appendStreamedData === false) {
this.clearData();
}
}
beginRequest() {
this.status$.next(OperationStatus.Progress);
const requestState = this.filtersService.getRequestState();
return this.fetchMethod(requestState);
}
responseHasStatus(response) {
return response.status !== null && typeof response.status !== 'undefined';
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RTList, deps: [{ token: i1.AsyncSubscriber }, { token: i2.RTStateService, optional: true }, { token: RTFilterTarget, optional: true, skipSelf: true }, { token: i3.RTSortingsService }, { token: i4.RTFiltersService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RTList }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RTList, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.AsyncSubscriber }, { type: i2.RTStateService, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: SkipSelf
}, {
type: Optional
}, {
type: Inject,
args: [RTFilterTarget]
}] }, { type: i3.RTSortingsService }, { type: i4.RTFiltersService }]; } });
export const LIST_PROVIDERS = [AsyncSubscriber, RTList, RTFiltersService, RTSortingsService, { provide: OperationStatusStream, useExisting: RTList }];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3JpZ2h0LWFuZ2xlZC9zcmMvbGliL2xpc3RzL3Byb3ZpZGVycy9saXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNyRyxPQUFPLEVBQWMsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU3QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUd0RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7OztBQUNyQyxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQU0sZ0JBQWdCLENBQUMsQ0FBQztBQUV4RSxNQUFNLE9BQU8scUJBQXFCO0NBRWpDO0FBR0QsTUFBTSxPQUFPLE1BQU07SUFDakI7Ozs7Ozs7T0FPRzthQUNXLGFBQVEsR0FBRztRQUN2Qjs7V0FFRztRQUNILGlCQUFpQixFQUFFLEtBQUs7S0FDekIsQUFMcUIsQ0FLcEI7SUFLRixZQUNVLGVBQWdDLEVBQzVCLGFBQTZCLEVBQUUsc0JBQXNCO0lBSWpFLGFBQWtCLEVBQ1YsZUFBa0MsRUFDbEMsY0FBZ0M7UUFQaEMsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBTWhD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QUFpQixFQUFFLEVBQUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBJbmplY3QsIEluamVjdGFibGUsIEluamVjdGlvblRva2VuLCBPcHRpb25hbCwgU2tpcFNlbGYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFJURmlsdGVyc1NlcnZpY2UgfSBmcm9tICcuLi8uLi9maWx0ZXJzL2ZpbHRlcnMuc2VydmljZSc7XHJcbmltcG9ydCB7IGRlc3Ryb3lBbGwgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMnO1xyXG5pbXBvcnQgeyBSVFN0YXRlU2VydmljZSB9IGZyb20gJy4vc3RhdGUuc2VydmljZSc7XHJcbmltcG9ydCB7IFJUU29ydGluZ3NTZXJ2aWNlIH0gZnJvbSAnLi9zb3J0aW5ncy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgT3BlcmF0aW9uU3RhdHVzIH0gZnJvbSAnLi4vLi4vY29yZS9vcGVyYXRpb24tc3RhdHVzJztcclxuaW1wb3J0IHsgTGlzdFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vY29yZS9saXN0LXJlc3BvbnNlJztcclxuaW1wb3J0IHsgQXN5bmNTdWJzY3JpYmVyIH0gZnJvbSAnLi9hc3luYy1zdWJzY3JpYmVyJztcclxuaW1wb3J0IHsgTnVsbE9iamVjdFBhZ2VyIH0gZnJvbSAnLi9udWxsLW9iamVjdC1wYWdlcic7XHJcbmltcG9ydCB7IFBhZ2VyIH0gZnJvbSAnLi4vLi4vY29yZS9wYWdlcic7XHJcbmltcG9ydCB7IEZpbHRlckNvbmZpZyB9IGZyb20gJy4uLy4uL2NvcmUvZmlsdGVyLWNvbmZpZyc7XHJcbmltcG9ydCB7IG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuZXhwb3J0IGNvbnN0IFJURmlsdGVyVGFyZ2V0ID0gbmV3IEluamVjdGlvblRva2VuPGFueT4oJ1JURmlsdGVyVGFyZ2V0Jyk7XHJcblxyXG5leHBvcnQgY2xhc3MgT3BlcmF0aW9uU3RhdHVzU3RyZWFtIHtcclxuICBwdWJsaWMgc3RhdHVzJDogT2JzZXJ2YWJsZTxPcGVyYXRpb25TdGF0dXM+O1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBSVExpc3Qge1xyXG4gIC8qKlxyXG4gICAqIEdsb2JhbCBzZXR0aW5ncyBvZiBsaXN0Li5cclxuICAgKlxyXG4gICAqIFRoZXNlIHNldHRpbmdzIGFyZSBzdGF0aWMgYW5kIHRoZWlyIHZhbHVlcyBhcmUgY29waWVkIHRvIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBzYW1lIG5hbWUgZm9yIGVhY2ggaW5zdGFuY2Ugb2Yge0BsaW5rIFJUTGlzdH0gdHlwZS5cclxuICAgKlxyXG4gICAqIFNvLCBjaGFuZ2luZyBvZiB0aGlzIHNldHRpbmdzIHdpbGwgYWZmZWN0IGFsbCBpbnN0YW5jZXMgb2Yge0BsaW5rIFJUTGlzdH0gdHlwZSB0aGF0IHdpbGwgYmUgY3JlYXRlZCBhZnRlciBzdWNoIGNoYW5nZXMuXHJcbiAgICogSWYgeW91IHdhbnQgdG8gY2hhbmdlIHNldHRpbmdzIG9mIGNvbmNyZXRlIG9iamVjdCB5b3UgY2FuIHVzZSBpdCB0aGUgc2FtZSBuYW1lIHByb3BlcnRpZXMuXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXRpYyBzZXR0aW5ncyA9IHtcclxuICAgIC8qKlxyXG4gICAgICogQHNlZSB7QGxpbmsgUlRMaXN0LmtlZXBSZWNvcmRzT25Mb2FkfVxyXG4gICAgICovXHJcbiAgICBrZWVwUmVjb3Jkc09uTG9hZDogZmFsc2VcclxuICB9O1xyXG4gIHB1YmxpYyBsb2FkU3RhcnRlZDogRXZlbnRFbWl0dGVyPHZvaWQ+ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG4gIHB1YmxpYyBsb2FkU3VjY2VlZDogRXZlbnRFbWl0dGVyPExpc3RSZXNwb25zZTxhbnk+IHwgYW55W10+ID0gbmV3IEV2ZW50RW1pdHRlcjxMaXN0UmVzcG9uc2U8YW55PiB8IGFueVtdPigpO1xyXG4gIHB1YmxpYyBsb2FkRmFpbGVkOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIHByaXZhdGUgZmlsdGVyVGFyZ2V0czogb2JqZWN0W10gPSBbXTtcclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgYXN5bmNTdWJzY3JpYmVyOiBBc3luY1N1YnNjcmliZXIsXHJcbiAgICBAT3B0aW9uYWwoKSBzdGF0ZVNlcnZpY2VzOiBSVFN0YXRlU2VydmljZSwgLy8gfCBSVFN0YXRlU2VydmljZVtdLFxyXG4gICAgQFNraXBTZWxmKClcclxuICAgIEBPcHRpb25hbCgpXHJcbiAgICBASW5qZWN0KFJURmlsdGVyVGFyZ2V0KVxyXG4gICAgZmlsdGVyVGFyZ2V0czogYW55LFxyXG4gICAgcHJpdmF0ZSBzb3J0aW5nc1NlcnZpY2U6IFJUU29ydGluZ3NTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBmaWx0ZXJzU2VydmljZTogUlRGaWx0ZXJzU2VydmljZVxyXG4gICkge1xyXG4gICAgaWYgKHN0YXRlU2VydmljZXMgIT0gbnVsbCkge1xyXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShzdGF0ZVNlcnZpY2VzKSkge1xyXG4gICAgICAgIHRoaXMuc3RhdGVTZXJ2aWNlcy5wdXNoKC4uLnN0YXRlU2VydmljZXMpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuc3RhdGVTZXJ2aWNlcy5wdXNoKHN0YXRlU2VydmljZXMpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLnBhZ2VyID0gbmV3IE51bGxPYmplY3RQYWdlcigpO1xyXG4gICAgaWYgKGZpbHRlclRhcmdldHMgIT0gbnVsbCkge1xyXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShmaWx0ZXJUYXJnZXRzKSkge1xyXG4gICAgICAgIHRoaXMuZmlsdGVyVGFyZ2V0cy5wdXNoKC4uLmZpbHRlclRhcmdldHMpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZmlsdGVyVGFyZ2V0cy5wdXNoKGZpbHRlclRhcmdldHMpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTcGVjaWZpZXMgdGhhdCBsaXN0IG11c3QgZGVzdHJveSBwcmV2aW91c2x5IGxvYWRlZCByZWNvcmRzIGltbWVkaWF0ZWx5IG9yIGtlZXAgdGhlbSB1bnRpbCBkYXRhIHJlcXVlc3QgaXMgY29tcGxldGVkLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBrZWVwUmVjb3Jkc09uTG9hZDogYm9vbGVhbiA9IFJUTGlzdC5zZXR0aW5ncy5rZWVwUmVjb3Jkc09uTG9hZDtcclxuICAvKipcclxuICAgKiBDYW4gYmUgdXNlZCB3aXRoIGBPYnNlcnZhYmxlYCBkYXRhIHNvdXJjZXRvIHNwZWNpZnkgdGhhdCBsaXN0IG11c3Qga2VlcCBwcmV2aW91c2x5IGxvYWRlZCByZWNvcmRzIG9yIGRlc3Ryb3kgdGhlbSB3aGVuIG5ldyB2YWx1ZSBwdWJsaXNoZWRcclxuICAgKi9cclxuICBwdWJsaWMgYXBwZW5kU3RyZWFtZWREYXRhOiBib29sZWFuIHwgbnVsbCA9IG51bGw7XHJcbiAgLyoqXHJcbiAgICogTWV0aG9kIGZvciBnZXR0aW5nIGRhdGEuIFRoaXMgcGFyYW1ldGVyIGlzIHJlcXVpcmVkIGFuZCBpdHMgY29uZmlndXJhdGlvbiBpcyBuZWNlc3NhcnkuXHJcbiAgICpcclxuICAgKiBUaGlzIG1ldGhvZCBnZXQgb25lIHBhcmFtZXRlciB3aXRoIHRoZSBzZXR0aW5ncyBvZiB0aGUgcmVxdWVzdCBpbXBsZW1lbnRpbmcge0BsaW5rIExpc3RSZXF1ZXN0fSBjb250cmFjdCBmb3IgdGhlIHNpbXBsZSBsaXN0cyBhbmQge0BsaW5rIFBhZ2VkTGlzdFJlcXVlc3R9IG9uZSBmb3IgdGhlIHBhZ2VkIGxpc3RzLlxyXG4gICAqIFRoZSByZXR1cm4gdmFsdWUgb2YgdGhpcyBtZXRob2Qgc2hvdWxkIGJlIGFueSBzdWJzY3JpYmFibGUgb2JqZWN0IHdoaWNoIGNhbiBiZSBoYW5kbGVkIGJ5IHtAbGluayBBc3luY1N1YnNjcmliZXJ9LlxyXG4gICAqIEZvciB0aGUgc2ltcGxlIGxpc3RzIHRoZSByZXNwb25zZSBzaG91bGQgY29udGFpbiBhcnJheSB3aXRoIHRoZSByZWNvcmRzLiBBcyBmb3IgdGhlIHBhZ2VkIG9uZXMsIGl0IHNob3VsZCBpbXBsZW1lbnQge0BsaW5rIExpc3RSZXNwb25zZX0gY29udHJhY3QuXHJcbiAgICovXHJcbiAgcHVibGljIGZldGNoTWV0aG9kOiAocmVxdWVzdFBhcmFtczogYW55KSA9PiBhbnk7XHJcbiAgLyoqXHJcbiAgICogQXJyYXkgb2YgZWxlbWVudHMgdHJhbnNmZXJyZWQgaW4gdGhlIHtAbGluayBMaXN0UmVzcG9uc2UuaXRlbXN9IHByb3BlcnR5LlxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXQgaXRlbXMoKTogYW55W10ge1xyXG4gICAgcmV0dXJuICh0aGlzLml0ZW1zJCBhcyBCZWhhdmlvclN1YmplY3Q8YW55W10+KS5nZXRWYWx1ZSgpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBBcnJheSBvZiByZWdpc3RlcmVkIHtAbGluayBSVFN0YXRlU2VydmljZX0gaW5zdGFuY2VzLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0ZVNlcnZpY2VzOiBSVFN0YXRlU2VydmljZVtdID0gbmV3IEFycmF5PFJUU3RhdGVTZXJ2aWNlPigpO1xyXG4gIC8qKlxyXG4gICAqIEFzeW5jIGltcGxlbWVudGF0aW9uIG9mIEBzZWUgUlRMaXN0LnN0YXR1c1xyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0dXMkOiBPYnNlcnZhYmxlPE9wZXJhdGlvblN0YXR1cz4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KE9wZXJhdGlvblN0YXR1cy5Jbml0aWFsKTtcclxuICAvKipcclxuICAgKiBBc3luYyBpbXBsZW1lbnRhdGlvbiBvZiBAc2VlIFJUTGlzdC5kZXN0cm95ZWRcclxuICAgKi9cclxuICBwdWJsaWMgZGVzdHJveWVkJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpO1xyXG4gIC8qKlxyXG4gICAqIEFzeW5jIGltcGxlbWVudGF0aW9uIG9mIEBzZWUgUlRMaXN0LmluaXRlZFxyXG4gICAqL1xyXG4gIHB1YmxpYyBpbml0ZWQkOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChmYWxzZSk7XHJcbiAgLyoqXHJcbiAgICogQXN5bmMgaW1wbGVtZW50YXRpb24gb2YgQHNlZSBSVExpc3QuaXRlbXNcclxuICAgKi9cclxuICBwdWJsaWMgaXRlbXMkOiBPYnNlcnZhYmxlPGFueVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3QoW10pO1xyXG4gIC8qKlxyXG4gICAqIEFzeW5jIGltcGxlbWVudGF0aW9uIG9mIEBzZWUgUlRMaXN0LmJ1c3lcclxuICAgKi9cclxuICBwdWJsaWMgYnVzeSQ6IE9ic2VydmFibGU8Ym9vbGVhbj4gPSB0aGlzLnN0YXR1cyQucGlwZShtYXAoc3RhdHVzID0+IHN0YXR1cyA9PT0gT3BlcmF0aW9uU3RhdHVzLlByb2dyZXNzKSk7XHJcbiAgLyoqXHJcbiAgICogQXN5bmMgaW1wbGVtZW50YXRpb24gb2YgQHNlZSBSVExpc3QucmVhZHlcclxuICAgKi9cclxuICBwdWJsaWMgcmVhZHkkOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5zdGF0dXMkLnBpcGUobWFwKHN0YXR1cyA9PiBzdGF0dXMgIT09IE9wZXJhdGlvblN0YXR1cy5Qcm9ncmVzcykpO1xyXG5cclxuICBwcml2YXRlIHBhZ2VySW50ZXJuYWw6IFBhZ2VyO1xyXG4gIC8qKlxyXG4gICAqIENvbmZpZ3VyZWQge0BsaW5rIFBhZ2VyfSBzZXJ2aWNlLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXQgcGFnZXIoKTogUGFnZXIge1xyXG4gICAgcmV0dXJuIHRoaXMucGFnZXJJbnRlcm5hbDtcclxuICB9XHJcbiAgcHVibGljIHNldCBwYWdlcih2YWx1ZTogUGFnZXIpIHtcclxuICAgIHRoaXMuZmlsdGVyc1NlcnZpY2UucmVtb3ZlRmlsdGVyVGFyZ2V0KHRoaXMucGFnZXJJbnRlcm5hbCk7XHJcbiAgICB0aGlzLnBhZ2VySW50ZXJuYWwgPSB2YWx1ZTtcclxuICAgIHRoaXMuZmlsdGVyc1NlcnZpY2UucmVnaXN0ZXJGaWx0ZXJUYXJnZXQodGhpcy5wYWdlckludGVybmFsKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogVHJ1ZSBpZiB0aGUgc2VydmljZSB3YXMgYWxyZWFkeSBkZXN0cm95ZWQgdmlhIHtAbGluayBkZXN0cm95fSBjYWxsLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXQgZGVzdHJveWVkKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICh0aGlzLmRlc3Ryb3llZCQgYXMgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KS5nZXRWYWx1ZSgpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBUcnVlIGlmIHRoZSBzZXJ2aWNlIHdhcyBhbHJlYWR5IGluaXRpYWxpemVkIHZpYSB7QGxpbmsgaW5pdH0gY2FsbC5cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IGluaXRlZCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAodGhpcy5pbml0ZWQkIGFzIEJlaGF2aW9yU3ViamVjdDxib29sZWFuPikuZ2V0VmFsdWUoKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ3VycmVudCBleGVjdXRpb24gc3RhdHVzIG9mIHRoZSBsaXN0LlxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXQgc3RhdHVzKCk6IE9wZXJhdGlvblN0YXR1cyB7XHJcbiAgICByZXR1cm4gKHRoaXMuc3RhdHVzJCBhcyBCZWhhdmlvclN1YmplY3Q8T3BlcmF0aW9uU3RhdHVzPikuZ2V0VmFsdWUoKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogcmV0dXJucyBgdHJ1ZWAsIGlmIHRoZXJlIGlzIGEgZGF0YSByZXF1ZXN0IGV4ZWN1dGVkIGF0IHRoZSBtb21lbnQgKGkuZS4ge0BsaW5rIHN0YXRlfSBpcyBlcXVhbCB0byB7QGxpbmsgUHJvZ3Jlc3NTdGF0ZS5Qcm9ncmVzc30pXHJcbiAgICovXHJcbiAgcHVibGljIGdldCBidXN5KCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuc3RhdHVzID09PSBPcGVyYXRpb25TdGF0dXMuUHJvZ3Jlc3M7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIHJldHVybnMgYHRydWVgLCBpZiB0aGVyZSBpcyBubyBkYXRhIHJlcXVlc3QgZXhlY3V0ZWQgYXQgdGhlIG1vbWVudCAoaS5lLiB7QGxpbmsgc3RhdGV9IGlzIE5PVCBlcXVhbCB0byB7QGxpbmsgUHJvZ3Jlc3NTdGF0ZS5Qcm9ncmVzc30pXHJcbiAgICovXHJcbiAgcHVibGljIGdldCByZWFkeSgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLnN0YXR1cyAhPT0gT3BlcmF0aW9uU3RhdHVzLlByb2dyZXNzO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBQZXJmb3JtcyBpbml0aWFsaXphdGlvbiBsb2dpYyBvZiB0aGUgc2VydmljZS4gVGhpcyBtZXRob2QgbXVzdCBiZSBjYWxsZWQgYmVmb3JlIGZpcnN0IHVzZSBvZiB0aGUgc2VydmljZS5cclxuICAgKi9cclxuICBwdWJsaWMgaW5pdCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmluaXRlZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmZpbHRlcnNTZXJ2aWNlLnJlZ2lzdGVyRmlsdGVyVGFyZ2V0KC4uLnRoaXMuZmlsdGVyVGFyZ2V0cyk7XHJcbiAgICB0aGlzLmZpbHRlcnNTZXJ2aWNlLnJlZ2lzdGVyRmlsdGVyVGFyZ2V0KHRoaXMucGFnZXIsIHRoaXMuc29ydGluZ3NTZXJ2aWNlKTtcclxuICAgIGNvbnN0IHJlc3RvcmVkU3RhdGUgPSB7fTtcclxuICAgIE9iamVjdC5hc3NpZ24ocmVzdG9yZWRTdGF0ZSwgLi4udGhpcy5zdGF0ZVNlcnZpY2VzLm1hcCgoc2VydmljZTogUlRTdGF0ZVNlcnZpY2UpID0+IHNlcnZpY2UuZ2V0U3RhdGUoKSB8fCB7fSkpO1xyXG4gICAgdGhpcy5maWx0ZXJzU2VydmljZS5hcHBseVBhcmFtcyhyZXN0b3JlZFN0YXRlKTtcclxuICAgICh0aGlzLmluaXRlZCQgYXMgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KS5uZXh0KHRydWUpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBQZXJmb3JtcyBkZXN0cm95IGxvZ2ljIG9mIHRoZSBsaXN0IGl0c2VsZiBhbmQgYWxsIG9mIHRoZSBpbm5lciBzZXJ2aWNlcy5cclxuICAgKi9cclxuICBwdWJsaWMgZGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuYXN5bmNTdWJzY3JpYmVyLmRlc3Ryb3koKTtcclxuICAgIHRoaXMuZmlsdGVyc1NlcnZpY2UuZGVzdHJveSgpO1xyXG4gICAgdGhpcy5zb3J0aW5nc1NlcnZpY2UuZGVzdHJveSgpO1xyXG4gICAgdGhpcy5jbGVhckRhdGEoKTtcclxuICAgICh0aGlzLmRlc3Ryb3llZCQgYXMgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KS5uZXh0KHRydWUpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZWdpc3RlcnMgcGFzc2VkIG9iamVjdChzKSBhcyBzdGF0ZSBzZXJ2aWNlIHRvIG1hbmFnZSB0aGUgbGlzdCBzdGF0ZS5cclxuICAgKi9cclxuICBwdWJsaWMgcmVnaXN0ZXJTdGF0ZVNlcnZpY2UoLi4uc2VydmljZXM6IFJUU3RhdGVTZXJ2aWNlW10pOiB2b2lkIHtcclxuICAgIHNlcnZpY2VzLmZvckVhY2goKHNlcnZpY2U6IFJUU3RhdGVTZXJ2aWNlKSA9PiB7XHJcbiAgICAgIHRoaXMuc3RhdGVTZXJ2aWNlcy5wdXNoKHNlcnZpY2UpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFJlbW92ZXMgcGFzc2VkIG9iamVjdChzKSBmcm9tIHN0YXRlIHNlcnZpY2VzIGNvbGxlY3Rpb24gb2YgdGhlIGxpc3QuXHJcbiAgICovXHJcbiAgcHVibGljIHJlbW92ZVN0YXRlU2VydmljZSguLi5zZXJ2aWNlczogUlRTdGF0ZVNlcnZpY2VbXSk6IHZvaWQge1xyXG4gICAgc2VydmljZXMuZm9yRWFjaCgoc2VydmljZTogUlRTdGF0ZVNlcnZpY2UpID0+IHtcclxuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnN0YXRlU2VydmljZXMuZmluZEluZGV4KChzOiBSVFN0YXRlU2VydmljZSkgPT4gcyA9PT0gc2VydmljZSk7XHJcbiAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcclxuICAgICAgICB0aGlzLnN0YXRlU2VydmljZXMuc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdGVycyBwYXNzZWQgb2JqZWN0KHMpIGFzIGZpbHRlciB0YXJnZXRzIGluIHVuZGVybHlpbmcge0BsaW5rIEZpbHRlcnNTZXJ2aWNlfSB0byBpbmNsdWRlIHRoZWlyIGNvbmZpZ3VyZWQgcHJvcGVydGllcyBhcyBwYXJhbWV0ZXJzIHRvIHRoZSBkYXRhIHJlcXVlc3QuXHJcbiAgICogQHNlZSB7QGxpbmsgRmlsdGVyc1NlcnZpY2UucmVnaXN0ZXJGaWx0ZXJUYXJnZXR9XHJcbiAgICovXHJcbiAgcHVibGljIHJlZ2lzdGVyRmlsdGVyVGFyZ2V0KC4uLnRhcmdldHM6IG9iamVjdFtdKTogdm9pZCB7XHJcbiAgICB0aGlzLmZpbHRlcnNTZXJ2aWNlLnJlZ2lzdGVyRmlsdGVyVGFyZ2V0KC4uLnRhcmdldHMpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAc2VlIHtAbGluayBGaWx0ZXJzU2VydmljZS5yZW1vdmVGaWx0ZXJUYXJnZXR9XHJcbiAgICovXHJcbiAgcHVibGljIHJlbW92ZUZpbHRlclRhcmdldCguLi50YXJnZXRzOiBvYmplY3RbXSk6IHZvaWQge1xyXG4gICAgdGhpcy5maWx0ZXJzU2VydmljZS5yZW1vdmVGaWx0ZXJUYXJnZXQoLi4udGFyZ2V0cyk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBzZWUge0BsaW5rIEZpbHRlcnNTZXJ2aWNlLmdldFJlcXVlc3RTdGF0ZX1cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0UmVxdWVzdFN0YXRlKGZpbHRlckZuPzogKGNvbmZpZzogRmlsdGVyQ29uZmlnLCBwcm9wb3NlZFZhbHVlOiBhbnksIHRhcmdldE9iamVjdDogb2JqZWN0KSA9PiBib29sZWFuKTogYW55IHtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlcnNTZXJ2aWNlLmdldFJlcXVlc3RTdGF0ZShmaWx0ZXJGbik7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFJlc2V0cyB0aGUgbGlzdCBwYXJhbWV0ZXJzIChzb3J0aW5ncywgcGFnaW5nLCBmaWx0ZXJzKSB0byB0aGVpciBkZWZhdWx0IHZhbHVlcy5cclxuICAgKi9cclxuICBwdWJsaWMgcmVzZXRTZXR0aW5ncygpOiB2b2lkIHtcclxuICAgIHRoaXMuYXN5bmNTdWJzY3JpYmVyLmRldGFjaCgpO1xyXG4gICAgdGhpcy5maWx0ZXJzU2VydmljZS5yZXNldFZhbHVlcygpO1xyXG4gICAgdGhpcy5wYWdlci5yZXNldCgpO1xyXG4gICAgdGhpcy5jbGVhckRhdGEoKTtcclxuICAgICh0aGlzLnN0YXR1cyQgYXMgQmVoYXZpb3JTdWJqZWN0PE9wZXJhdGlvblN0YXR1cz4pLm5leHQoT3BlcmF0aW9uU3RhdHVzLkluaXRpYWwpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDYW5jZWxzIHRoZSByZXF1ZXN0IGV4ZWN1dGVkIGF0IHRoZSBtb21lbnQuXHJcbiAgICovXHJcbiAgcHVibGljIGNhbmNlbFJlcXVlc3RzKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYnVzeSB8fCB0aGlzLmFwcGVuZFN0cmVhbWVkRGF0YSAhPT0gbnVsbCkge1xyXG4gICAgICB0aGlzLmFzeW5jU3Vic2NyaWJlci5kZXRhY2goKTtcclxuICAgICAgKHRoaXMuc3RhdHVzJCBhcyBCZWhhdmlvclN1YmplY3Q8T3BlcmF0aW9uU3RhdHVzPikubmV4dChPcGVyYXRpb25TdGF0dXMuQ2FuY2VsbGVkKTtcclxuICAgICAgdGhpcy5jbGVhckRhdGEoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENsZWFycyB7QGxpbmsgaXRlbXN9IGFycmF5LiBDYWxscyB7QGxpbmsgZGVzdHJveUFsbH0gbWV0aG9kIGZvciB7QGxpbmsgaXRlbXN9IGFycmF5IHRvIHBlcmZvcm0gb3B0aW9uYWwgZGVzdHJveSBsb2dpYyBvZiB0aGUgZWxlbWVudHMuXHJcbiAgICoge0BzZWUgZGVzdHJveUFsbH1cclxuICAgKi9cclxuICBwdWJsaWMgY2xlYXJEYXRhKCk6IHZvaWQge1xyXG4gICAgZGVzdHJveUFsbCh0aGlzLml0ZW1zKTtcclxuICAgICh0aGlzLml0ZW1zJCBhcyBCZWhhdmlvclN1YmplY3Q8YW55W10+KS5uZXh0KFtdKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcmZvcm1zIGRhdGEgbG9hZGluZyBieSBjYWxsaW5nIHNwZWNpZmllZCB7QGxpbmsgZmV0Y2hNZXRob2R9IGRlbGVnYXRlLlxyXG4gICAqIEByZXR1cm4gcmVzdWx0IG9mIHtAbGluayBmZXRjaE1ldGhvZH0gZXhlY3V0aW9uLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBsb2FkRGF0YSgpOiBPYnNlcnZhYmxlPGFueT4gfCBQcm9taXNlPGFueT4gfCBFdmVudEVtaXR0ZXI8YW55PiB7XHJcbiAgICBpZiAodGhpcy5idXN5KSB7XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG4gICAgdGhpcy5sb2FkU3RhcnRlZC5lbWl0KCk7XHJcbiAgICBjb25zdCBzdWJzY3JpYmFibGUgPSB0aGlzLmJlZ2luUmVxdWVzdCgpO1xyXG4gICAgdGhpcy50cnlDbGVhbkl0ZW1zT25Mb2FkKGZhbHNlKTtcclxuICAgIHRoaXMuYXN5bmNTdWJzY3JpYmVyLmF0dGFjaChzdWJzY3JpYmFibGUsIHRoaXMubG9hZERhdGFTdWNjZXNzQ2FsbGJhY2ssIHRoaXMubG9hZERhdGFGYWlsQ2FsbGJhY2spO1xyXG4gICAgdGhpcy5zdGF0ZVNlcnZpY2VzLmZvckVhY2goKHNlcnZpY2U6IFJUU3RhdGVTZXJ2aWNlKSA9PiB7XHJcbiAgICAgIHNlcnZpY2UucGVyc2lzdFN0YXRlKHRoaXMuZmlsdGVyc1NlcnZpY2UpO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gc3Vic2NyaWJhYmxlO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXNldHMgcGFnaW5nIHBhcmFtZXRlcnMgYW5kIHBlcmZvcm1zIGRhdGEgbG9hZGluZyBieSBjYWxsaW5nIHtAbGluayBsb2FkRGF0YX0gaWYgbGlzdCBub3QgaW4ge0BsaW5rIE9wZXJhdGlvblN0YXR1cy5Qcm9ncmVzc30gc3RhdGUuXHJcbiAgICogQHJldHVybiByZXN1bHQgb2Yge0BsaW5rIGZldGNoTWV0aG9kfSBpZiBpdCB3YXMgY2FsbGVkLiBgbnVsbGAgb3RoZXJ3aXNlLlxyXG4gICAqL1xyXG4gIHB1YmxpYyByZWxvYWREYXRhKCk6IE9ic2VydmFibGU8YW55PiB8IFByb21pc2U8YW55PiB8IEV2ZW50RW1pdHRlcjxhbnk+IHtcclxuICAgIGlmICh0aGlzLmJ1c3kpIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICB0aGlzLmxvYWRTdGFydGVkLmVtaXQoKTtcclxuICAgIHRoaXMucGFnZXIucmVzZXQoKTtcclxuICAgIGNvbnN0IHN1YnNjcmliYWJsZSA9IHRoaXMuYmVnaW5SZXF1ZXN0KCk7XHJcbiAgICB0aGlzLnRyeUNsZWFuSXRlbXNPblJlbG9hZChmYWxzZSk7XHJcbiAgICB0aGlzLmFzeW5jU3Vic2NyaWJlci5hdHRhY2goc3Vic2NyaWJhYmxlLCB0aGlzLnJlbG9hZERhdGFTdWNjZXNzQ2FsbGJhY2ssIHRoaXMucmVsb2FkRGF0YUZhaWxDYWxsYmFjayk7XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZXMuZm9yRWFjaCgoc2VydmljZTogUlRTdGF0ZVNlcnZpY2UpID0+IHtcclxuICAgICAgc2VydmljZS5wZXJzaXN0U3RhdGUodGhpcy5maWx0ZXJzU2VydmljZSk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBzdWJzY3JpYmFibGU7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIENhbGxiYWNrIHdoaWNoIGlzIGV4ZWN1dGVkIGlmIHtAbGluayBmZXRjaE1ldGhvZH0gZXhlY3V0aW9uIGZpbmlzaGVkIHN1Y2Nlc3NmdWxseS5cclxuICAgKi9cclxuICBwdWJsaWMgbG9hZFN1Y2Nlc3NDYWxsYmFjayhyZXNwb25zZTogTGlzdFJlc3BvbnNlPGFueT4gfCBhbnlbXSk6IExpc3RSZXNwb25zZTxhbnk+IHwgYW55W10ge1xyXG4gICAgY29uc3QgaXRlbXMgPSBBcnJheS5pc0FycmF5KHJlc3BvbnNlKSA/IHJlc3BvbnNlIDogcmVzcG9uc2UuaXRlbXM7XHJcbiAgICAodGhpcy5pdGVtcyQgYXMgQmVoYXZpb3JTdWJqZWN0PGFueVtdPikubmV4dCh0aGlzLml0ZW1zLmNvbmNhdChpdGVtcykpO1xyXG4gICAgdGhpcy5wYWdlci5wcm9jZXNzUmVzcG9uc2UocmVzcG9uc2UpO1xyXG4gICAgLy8gSW4gY2FzZSB3aGVuIGZpbHRlciBjaGFuZ2VkIGZyb20gbGFzdCByZXF1ZXN0IGFuZCB0aGVyZSdzIG5vIGRhdGEgbm93XHJcbiAgICAvLyBEb24ndCBkbyB0aGlzIGZvciBmbGF0IHJlc3BvbnNlcyBzaW5jZSB3ZSBkb24ndCBrbm93IHJlYWwgY291bnQgaXRlbXNcclxuICAgIGlmICghQXJyYXkuaXNBcnJheShyZXNwb25zZSkgJiYgdGhpcy5wYWdlci50b3RhbENvdW50ID09PSAwKSB7XHJcbiAgICAgIHRoaXMuY2xlYXJEYXRhKCk7XHJcbiAgICAgIHRoaXMucGFnZXIucmVzZXQoKTtcclxuICAgIH1cclxuICAgICh0aGlzLnN0YXR1cyQgYXMgQmVoYXZpb3JTdWJqZWN0PE9wZXJhdGlvblN0YXR1cz4pLm5leHQoXHJcbiAgICAgIHRoaXMucGFnZXIudG90YWxDb3VudCA9PT0gMCAmJiB0aGlzLml0ZW1zLmxlbmd0aCA9PT0gMCA/IE9wZXJhdGlvblN0YXR1cy5Ob0RhdGEgOiBPcGVyYXRpb25TdGF0dXMuRG9uZVxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLmxvYWRTdWNjZWVkLmVtaXQocmVzcG9uc2UpO1xyXG4gICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDYWxsYmFjayB3aGljaCBpcyBleGVjdXRlZCBpZiB7QGxpbmsgZmV0Y2hNZXRob2R9IGV4ZWN1dGlvbiBmaW5pc2hlZCB3aXRoIGVycm9yLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBsb2FkRmFpbENhbGxiYWNrKCk6IHZvaWQge1xyXG4gICAgdGhpcy50cnlDbGVhbkl0ZW1zT25Mb2FkKHRydWUpO1xyXG4gICAgKHRoaXMuc3RhdHVzJCBhcyBCZWhhdmlvclN1YmplY3Q8T3BlcmF0aW9uU3RhdHVzPikubmV4dChPcGVyYXRpb25TdGF0dXMuRmFpbCk7XHJcbiAgICB0aGlzLmxvYWRGYWlsZWQuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBsb2FkRGF0YVN1Y2Nlc3NDYWxsYmFjayA9IChyZXNwb25zZTogTGlzdFJlc3BvbnNlPGFueT4gfCBhbnlbXSk6IExpc3RSZXNwb25zZTxhbnk+IHwgYW55W10gPT4ge1xyXG4gICAgaWYgKHRoaXMudHJ5SW50ZXJjZXB0U3RhdHVzUmVzcG9uc2UocmVzcG9uc2UpKSB7XHJcbiAgICAgIHJldHVybiByZXNwb25zZTtcclxuICAgIH1cclxuICAgIHRoaXMudHJ5Q2xlYW5JdGVtc09uTG9hZCh0cnVlKTtcclxuICAgIHJldHVybiB0aGlzLmxvYWRTdWNjZXNzQ2FsbGJhY2socmVzcG9uc2UpO1xyXG4gIH07XHJcbiAgcHJpdmF0ZSByZWxvYWREYXRhU3VjY2Vzc0NhbGxiYWNrID0gKHJlc3BvbnNlOiBMaXN0UmVzcG9uc2U8YW55PiB8IGFueVtdKTogTGlzdFJlc3BvbnNlPGFueT4gfCBhbnlbXSA9PiB7XHJcbiAgICBpZiAodGhpcy50cnlJbnRlcmNlcHRTdGF0dXNSZXNwb25zZShyZXNwb25zZSkpIHtcclxuICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgfVxyXG4gICAgdGhpcy50cnlDbGVhbkl0ZW1zT25SZWxvYWQodHJ1ZSk7XHJcbiAgICByZXR1cm4gdGhpcy5sb2FkU3VjY2Vzc0NhbGxiYWNrKHJlc3BvbnNlKTtcclxuICB9O1xyXG4gIHByaXZhdGUgbG9hZERhdGFGYWlsQ2FsbGJhY2sgPSAoKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLnRyeUNsZWFuSXRlbXNPbkxvYWQodHJ1ZSk7XHJcbiAgICB0aGlzLmxvYWRGYWlsQ2FsbGJhY2soKTtcclxuICB9O1xyXG4gIHByaXZhdGUgdHJ5SW50ZXJjZXB0U3RhdHVzUmVzcG9uc2UocmVzcG9uc2U6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMucmVzcG9uc2VIYXNTdGF0dXMocmVzcG9uc2UpKSB7XHJcbiAgICAgIHN3aXRjaCAocmVzcG9uc2Uuc3RhdHVzKSB7XHJcbiAgICAgICAgY2FzZSBPcGVyYXRpb25TdGF0dXMuRmFpbDpcclxuICAgICAgICAgIHRoaXMucmVsb2FkRGF0YUZhaWxDYWxsYmFjaygpO1xyXG4gICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgY2FzZSBPcGVyYXRpb25TdGF0dXMuQ2FuY2VsbGVkOlxyXG4gICAgICAgICAgdGhpcy5jYW5jZWxSZXF1ZXN0cygpO1xyXG4gICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgY2FzZSBPcGVyYXRpb25TdGF0dXMuUHJvZ3Jlc3M6XHJcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuICBwcml2YXRlIHJlbG9hZERhdGFGYWlsQ2FsbGJhY2sgPSAoKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLnRyeUNsZWFuSXRlbXNPblJlbG9hZCh0cnVlKTtcclxuICAgIHRoaXMubG9hZEZhaWxDYWxsYmFjaygpO1xyXG4gIH07XHJcbiAgcHJpdmF0ZSB0cnlDbGVhbkl0ZW1zT25Mb2FkKHJlcXVlc3RDb21wbGV0ZWQ6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmtlZXBSZWNvcmRzT25Mb2FkID09PSByZXF1ZXN0Q29tcGxldGVkICYmIHRoaXMucGFnZXIuYXBwZW5kZWRPbkxvYWQgPT09IGZhbHNlKSB7XHJcbiAgICAgIHRoaXMuY2xlYXJEYXRhKCk7XHJcbiAgICB9XHJcbiAgICBpZiAocmVxdWVzdENvbXBsZXRlZCAmJiB0aGlzLmFwcGVuZFN0cmVhbWVkRGF0YSA9PT0gZmFsc2UpIHtcclxuICAgICAgdGhpcy5jbGVhckRhdGEoKTtcclxuICAgIH1cclxuICB9XHJcbiAgcHJpdmF0ZSB0cnlDbGVhbkl0ZW1zT25SZWxvYWQocmVxdWVzdENvbXBsZXRlZDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMua2VlcFJlY29yZHNPbkxvYWQgPT09IHJlcXVlc3RDb21wbGV0ZWQpIHtcclxuICAgICAgdGhpcy5jbGVhckRhdGEoKTtcclxuICAgIH1cclxuICAgIGlmIChyZXF1ZXN0Q29tcGxldGVkICYmIHRoaXMuYXBwZW5kU3RyZWFtZWREYXRhID09PSBmYWxzZSkge1xyXG4gICAgICB0aGlzLmNsZWFyRGF0YSgpO1xyXG4gICAgfVxyXG4gIH1cclxuICBwcml2YXRlIGJlZ2luUmVxdWVzdCgpOiBhbnkge1xyXG4gICAgKHRoaXMuc3RhdHVzJCBhcyBCZWhhdmlvclN1YmplY3Q8T3BlcmF0aW9uU3RhdHVzPikubmV4dChPcGVyYXRpb25TdGF0dXMuUHJvZ3Jlc3MpO1xyXG4gICAgY29uc3QgcmVxdWVzdFN0YXRlID0gdGhpcy5maWx0ZXJzU2VydmljZS5nZXRSZXF1ZXN0U3RhdGUoKTtcclxuICAgIHJldHVybiB0aGlzLmZldGNoTWV0aG9kKHJlcXVlc3RTdGF0ZSk7XHJcbiAgfVxyXG4gIHByaXZhdGUgcmVzcG9uc2VIYXNTdGF0dXMocmVzcG9uc2U6IExpc3RSZXNwb25zZTxhbnk+IHwgYW55W10pOiBib29sZWFuIHtcclxuICAgIHJldHVybiAocmVzcG9uc2UgYXMgTGlzdFJlc3BvbnNlPGFueT4pLnN0YXR1cyAhPT0gbnVsbCAmJiB0eXBlb2YgKHJlc3BvbnNlIGFzIExpc3RSZXNwb25zZTxhbnk+KS5zdGF0dXMgIT09ICd1bmRlZmluZWQnO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IExJU1RfUFJPVklERVJTOiBhbnlbXSA9IFtBc3luY1N1YnNjcmliZXIsIFJUTGlzdCwgUlRGaWx0ZXJzU2VydmljZSwgUlRTb3J0aW5nc1NlcnZpY2UsIHsgcHJvdmlkZTogT3BlcmF0aW9uU3RhdHVzU3RyZWFtLCB1c2VFeGlzdGluZzogUlRMaXN0IH1dO1xyXG4iXX0=