@netgrif/components-core
Version:
Netgrif Application engine frontend core Angular library
331 lines • 53.8 kB
JavaScript
import { Inject, Injectable, Optional } from '@angular/core';
import { BehaviorSubject, of, ReplaySubject, Subject, timer } from 'rxjs';
import { catchError, concatMap, filter, map, mergeMap, scan, switchMap, take, tap } from 'rxjs/operators';
import { HttpParams } from '@angular/common/http';
import { TaskEndpoint } from '../models/task-endpoint';
import { NAE_PREFERRED_TASK_ENDPOINT } from '../models/injection-token-task-endpoint';
import { PageLoadRequestContext } from '../../abstract/page-load-request-context';
import { LoadingWithFilterEmitter } from '../../../utility/loading-with-filter-emitter';
import { arrayToObservable } from '../../../utility/array-to-observable';
import { AbstractSortableViewComponent } from '../../abstract/sortable-view';
import { NAE_TASK_VIEW_CONFIGURATION } from '../models/task-view-configuration-injection-token';
import { PaginationParams } from '../../../utility/pagination/pagination-params';
import { createSortParam, PaginationSort } from '../../../utility/pagination/pagination-sort';
import * as i0 from "@angular/core";
import * as i1 from "../../../resources/engine-endpoint/task-resource.service";
import * as i2 from "../../../user/services/user.service";
import * as i3 from "../../../snack-bar/services/snack-bar.service";
import * as i4 from "@ngx-translate/core";
import * as i5 from "../../../search/search-service/search.service";
import * as i6 from "../../../logger/services/logger.service";
import * as i7 from "../../../user/services/user-comparator.service";
import * as i8 from "../../../search/search-keyword-resolver-service/search-index-resolver.service";
import * as i9 from "../models/task-endpoint";
export class TaskViewService extends AbstractSortableViewComponent {
_taskService;
_userService;
_snackBarService;
_translate;
_searchService;
_log;
_userComparator;
_preferredEndpoint;
_tasks$;
_changedFields$;
_requestedPage$;
_loading$;
_endOfData;
_pagination;
_initiallyOpenOneTask;
_closeTaskTabOnNoTasks;
_panelUpdate$;
_closeTab$;
_subInitiallyOpen;
_subCloseTask;
_subSearch;
// Serializing assign after cancel
_allowMultiOpen;
_initializing = true;
_paginationView = false;
constructor(_taskService, _userService, _snackBarService, _translate, _searchService, _log, _userComparator, resolver, _preferredEndpoint = null, taskViewConfig = null) {
super(resolver);
this._taskService = _taskService;
this._userService = _userService;
this._snackBarService = _snackBarService;
this._translate = _translate;
this._searchService = _searchService;
this._log = _log;
this._userComparator = _userComparator;
this._preferredEndpoint = _preferredEndpoint;
this._tasks$ = new Subject();
this._loading$ = new LoadingWithFilterEmitter();
this._changedFields$ = new Subject();
this._allowMultiOpen = true;
this._endOfData = false;
this._pagination = {
size: 50,
totalElements: undefined,
totalPages: undefined,
number: -1
};
this._requestedPage$ = new BehaviorSubject(new PageLoadRequestContext(this.activeFilter, Object.assign({}, this._pagination, { number: 0 })));
this._panelUpdate$ = new BehaviorSubject([]);
this._closeTab$ = new ReplaySubject(1);
this._preferredEndpoint = taskViewConfig?.preferredEndpoint ?? (this._preferredEndpoint ?? TaskEndpoint.MONGO);
this._initializing = false;
this._subSearch = this._searchService.activeFilter$.subscribe(() => {
this.reload();
});
const tasksMap$ = this._requestedPage$.pipe(mergeMap(p => this.loadPage(p)), map(pageLoadResult => {
if (pageLoadResult.requestContext && pageLoadResult.requestContext.clearLoaded) {
// we set an empty value to the virtual scroll and then replace it by the real value forcing it to redraw its content
const results = [{ tasks: {}, requestContext: null }, pageLoadResult];
return arrayToObservable(results);
}
else {
return of(pageLoadResult);
}
}), concatMap(o => o), scan((acc, pageLoadResult) => {
let result;
if (pageLoadResult.requestContext === null) {
return pageLoadResult.tasks;
}
if (pageLoadResult.requestContext.reloadCurrentTaskPage) {
Object.keys(acc).forEach(taskId => {
if (!pageLoadResult.tasks[taskId]) {
delete acc[taskId];
}
else {
pageLoadResult.tasks[taskId].task.dataGroups = acc[taskId].task.dataGroups;
pageLoadResult.tasks[taskId].initiallyExpanded = acc[taskId].initiallyExpanded;
this.updateTask(acc[taskId].task, pageLoadResult.tasks[taskId].task);
this.blockTaskFields(acc[taskId].task, !(acc[taskId].task.userId
&& this._userComparator.compareUsers(acc[taskId].task.userId)));
if (!this._paginationView) {
delete pageLoadResult.tasks[taskId];
}
}
});
result = Object.assign(acc, pageLoadResult.tasks);
}
else {
result = { ...acc, ...pageLoadResult.tasks };
}
Object.assign(this._pagination, pageLoadResult.requestContext.pagination);
if (pageLoadResult.requestContext !== null) {
this._loading$.off(pageLoadResult.requestContext.filter);
}
if (this._paginationView) {
return pageLoadResult.tasks;
}
return result;
}, {}));
this._tasks$ = tasksMap$.pipe(map(v => Object.values(v)), map(taskArray => {
if (taskArray.length === 1 && this._initiallyOpenOneTask) {
taskArray[0].task.finishDate === undefined ?
taskArray[0].initiallyExpanded = true :
taskArray[0].initiallyExpanded = false;
}
return taskArray;
}), tap(v => this._panelUpdate$.next(v)));
this._subInitiallyOpen = (taskViewConfig?.initiallyOpenOneTask ?? of(true)).subscribe(bool => {
this._initiallyOpenOneTask = bool;
});
this._subCloseTask = (taskViewConfig?.closeTaskTabOnNoTasks ?? of(true)).subscribe(bool => {
this._closeTaskTabOnNoTasks = bool;
});
}
ngOnDestroy() {
super.ngOnDestroy();
this._changedFields$.complete();
this._requestedPage$.complete();
this._panelUpdate$.complete();
this._closeTab$.complete();
this._subInitiallyOpen.unsubscribe();
this._subCloseTask.unsubscribe();
this._subSearch.unsubscribe();
}
get tasks$() {
return this._tasks$;
}
get changedFields$() {
return this._changedFields$;
}
get loading$() {
return this._loading$.asObservable();
}
get loading() {
return this._loading$.isActive;
}
get panelUpdate() {
return this._panelUpdate$.asObservable();
}
get closeTab() {
return this._closeTab$.asObservable();
}
get pagination() {
return this._pagination;
}
get activeFilter() {
return this._searchService.activeFilter;
}
set allowMultiOpen(bool) {
this._allowMultiOpen = bool;
}
get allowMultiOpen() {
return this._allowMultiOpen;
}
set paginationView(value) {
this._paginationView = value;
}
loadPage(requestContext) {
if (requestContext === null || requestContext.pageNumber < 0) {
return of({ tasks: {}, requestContext });
}
let params = new HttpParams();
params = this.addSortParams(params);
params = this.addPageParams(params, requestContext.pagination);
this._loading$.on(requestContext.filter);
let request;
if (requestContext.filter.bodyContainsQuery() || this._preferredEndpoint === TaskEndpoint.ELASTIC) {
request = timer(200).pipe(switchMap(() => this._taskService.searchTask(requestContext.filter, params).pipe(take(1))));
}
else {
request = this._taskService.getTasks(requestContext.filter, params).pipe(take(1));
}
return request.pipe(catchError(err => {
this._log.error('Loading tasks has failed!', err);
this._loading$.off(requestContext.filter);
return of({ content: [], pagination: { ...this._pagination } });
}), filter(() => {
const r = requestContext.filter === this._searchService.activeFilter;
if (!r) {
this._loading$.off(requestContext.filter);
this._log.debug('Received tasks page is no longer relevant since the active filter has changed before it could arrive.'
+ ' Discarding...');
}
return r;
}), tap(t => {
Object.assign(requestContext.pagination, t.pagination);
}), tap(t => {
if (this._pagination.totalElements && this._pagination.totalElements > 0
&& t.pagination.totalElements === 0 && !Array.isArray(t.content) && this._closeTaskTabOnNoTasks) {
this._closeTab$.next();
}
}), tap(t => {
this._endOfData = !Array.isArray(t.content)
|| t.content.length === 0
|| t.pagination.number === t.pagination.totalPages;
}), map(tasks => Array.isArray(tasks.content) ? tasks : { ...tasks, content: [] }), map(tasks => {
return tasks.content.reduce((acc, curr) => {
this.blockTaskFields(curr, !(curr.userId && this._userComparator.compareUsers(curr.userId)));
return {
...acc, [curr.stringId]: {
task: curr,
changedFields: this._changedFields$,
initiallyExpanded: false
}
};
}, {});
}), map(tasks => ({ tasks, requestContext })));
}
updateTask(old, neww) {
Object.keys(old).forEach(key => {
if (!neww.hasOwnProperty(key)) {
delete old[key];
}
});
Object.keys(neww).forEach(key => {
if (neww[key] !== undefined && neww[key] !== null) {
old[key] = neww[key];
}
});
this.blockTaskFields(old, !(old.userId && this._userComparator.compareUsers(old.userId)));
}
blockTaskFields(task, block) {
if (!task.dataGroups) {
return;
}
task.dataGroups.forEach(g => g.fields.forEach(f => f.block = block));
}
nextPage(renderedRange, totalLoaded, requestContext) {
if (requestContext === undefined) {
requestContext = new PageLoadRequestContext(this.activeFilter, this._pagination);
requestContext.pagination.number += 1;
}
if (this.isLoadingRelevantFilter(requestContext) || this._endOfData) {
return;
}
if (renderedRange.end === totalLoaded) {
this._requestedPage$.next(requestContext);
}
}
nextPagePagination(length, pageIndex, requestContext) {
if (requestContext === undefined) {
requestContext = new PageLoadRequestContext(this.activeFilter, this._pagination);
requestContext.pagination.size = length;
requestContext.pagination.number = pageIndex;
}
if (this.isLoadingRelevantFilter(requestContext) || this._endOfData) {
return;
}
this._requestedPage$.next(requestContext);
}
isLoadingRelevantFilter(requestContext) {
return requestContext === undefined || (this._loading$.isActiveWithFilter(requestContext.filter) && !requestContext.force);
}
reload() {
if (!this._tasks$ || !this._pagination) {
return;
}
this._endOfData = false;
const requestContext = new PageLoadRequestContext(this.activeFilter, this._pagination, true);
requestContext.pagination.number = 0;
const range = {
start: -1,
end: 0
};
this.nextPage(range, 0, requestContext);
}
reloadCurrentPage(force) {
if (!this._tasks$ || !this._pagination) {
return;
}
this._endOfData = false;
const requestContext = new PageLoadRequestContext(this.activeFilter, this._pagination, false, true, force);
requestContext.pagination.number = 0; // TODO [BUG] - Reloading only first page
const range = {
start: -1,
end: 0
};
this.nextPage(range, 0, requestContext);
}
getMetaFieldSortId() {
// TODO Tasks were not sortable on old frontend sorting might require elastic mapping changes on backend
return this._lastHeaderSearchState.fieldIdentifier;
}
getDefaultSortParam() {
return createSortParam('priority', PaginationSort.DESCENDING);
}
addPageParams(params, pagination) {
params = params.set(PaginationParams.PAGE_SIZE, `${pagination.size}`);
params = params.set(PaginationParams.PAGE_NUMBER, `${pagination.number}`);
return params;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TaskViewService, deps: [{ token: i1.TaskResourceService }, { token: i2.UserService }, { token: i3.SnackBarService }, { token: i4.TranslateService }, { token: i5.SearchService }, { token: i6.LoggerService }, { token: i7.UserComparatorService }, { token: i8.SearchIndexResolverService }, { token: NAE_PREFERRED_TASK_ENDPOINT, optional: true }, { token: NAE_TASK_VIEW_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TaskViewService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TaskViewService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.TaskResourceService }, { type: i2.UserService }, { type: i3.SnackBarService }, { type: i4.TranslateService }, { type: i5.SearchService }, { type: i6.LoggerService }, { type: i7.UserComparatorService }, { type: i8.SearchIndexResolverService }, { type: i9.TaskEndpoint, decorators: [{
type: Optional
}, {
type: Inject,
args: [NAE_PREFERRED_TASK_ENDPOINT]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [NAE_TASK_VIEW_CONFIGURATION]
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay12aWV3LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZXRncmlmLWNvbXBvbmVudHMtY29yZS9zcmMvbGliL3ZpZXcvdGFzay12aWV3L3NlcnZpY2UvdGFzay12aWV3LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQWEsUUFBUSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3RFLE9BQU8sRUFBQyxlQUFlLEVBQWMsRUFBRSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQWdCLEtBQUssRUFBQyxNQUFNLE1BQU0sQ0FBQztBQU1sRyxPQUFPLEVBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFPaEQsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBRXJELE9BQU8sRUFBQywyQkFBMkIsRUFBQyxNQUFNLHlDQUF5QyxDQUFDO0FBQ3BGLE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLDBDQUEwQyxDQUFDO0FBR2hGLE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLDhDQUE4QyxDQUFDO0FBQ3RGLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHNDQUFzQyxDQUFDO0FBRXZFLE9BQU8sRUFBQyw2QkFBNkIsRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBQzNFLE9BQU8sRUFBQywyQkFBMkIsRUFBQyxNQUFNLG1EQUFtRCxDQUFDO0FBRzlGLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLCtDQUErQyxDQUFDO0FBQy9FLE9BQU8sRUFBQyxlQUFlLEVBQUUsY0FBYyxF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R0FBRyxFQUFFLENBQUM7U0FDVCxDQUFDO1FBQ0YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFUyxrQkFBa0I7UUFDeEIsd0dBQXdHO1FBQ3hHLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLGVBQWUsQ0FBQztJQUN2RCxDQUFDO0lBRVMsbUJBQW1CO1FBQ3pCLE9BQU8sZUFBZSxDQUFDLFVBQVUsRUFBRSxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVTLGFBQWEsQ0FBQyxNQUFrQixFQUFFLFVBQXNCO1FBQzlELE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxHQUFHLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3RFLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7d0dBclZRLGVBQWUsd1JBOEJRLDJCQUEyQiw2QkFDM0IsMkJBQTJCOzRHQS9CbEQsZUFBZTs7NEZBQWYsZUFBZTtrQkFEM0IsVUFBVTs7MEJBK0JNLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsMkJBQTJCOzswQkFDOUMsUUFBUTs7MEJBQUksTUFBTTsyQkFBQywyQkFBMkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdCwgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBPcHRpb25hbH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgb2YsIFJlcGxheVN1YmplY3QsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiwgdGltZXJ9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtUYXNrUGFuZWxEYXRhfSBmcm9tICcuLi8uLi8uLi9wYW5lbC90YXNrLXBhbmVsLWRhdGEvdGFzay1wYW5lbC1kYXRhJztcbmltcG9ydCB7VGFza1Jlc291cmNlU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vcmVzb3VyY2VzL2VuZ2luZS1lbmRwb2ludC90YXNrLXJlc291cmNlLnNlcnZpY2UnO1xuaW1wb3J0IHtVc2VyU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdXNlci9zZXJ2aWNlcy91c2VyLnNlcnZpY2UnO1xuaW1wb3J0IHtTbmFja0JhclNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3NuYWNrLWJhci9zZXJ2aWNlcy9zbmFjay1iYXIuc2VydmljZSc7XG5pbXBvcnQge1RyYW5zbGF0ZVNlcnZpY2V9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHtjYXRjaEVycm9yLCBjb25jYXRNYXAsIGZpbHRlciwgbWFwLCBtZXJnZU1hcCwgc2Nhbiwgc3dpdGNoTWFwLCB0YWtlLCB0YXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7SHR0cFBhcmFtc30gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHtQYWdpbmF0aW9ufSBmcm9tICcuLi8uLi8uLi9yZXNvdXJjZXMvaW50ZXJmYWNlL3BhZ2luYXRpb24nO1xuaW1wb3J0IHtUYXNrfSBmcm9tICcuLi8uLi8uLi9yZXNvdXJjZXMvaW50ZXJmYWNlL3Rhc2snO1xuaW1wb3J0IHtTZWFyY2hTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi9zZWFyY2gvc2VhcmNoLXNlcnZpY2Uvc2VhcmNoLnNlcnZpY2UnO1xuaW1wb3J0IHtMb2dnZXJTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi9sb2dnZXIvc2VydmljZXMvbG9nZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHtMaXN0UmFuZ2V9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQge1VzZXJDb21wYXJhdG9yU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdXNlci9zZXJ2aWNlcy91c2VyLWNvbXBhcmF0b3Iuc2VydmljZSc7XG5pbXBvcnQge1Rhc2tFbmRwb2ludH0gZnJvbSAnLi4vbW9kZWxzL3Rhc2stZW5kcG9pbnQnO1xuaW1wb3J0IHtQYWdlfSBmcm9tICcuLi8uLi8uLi9yZXNvdXJjZXMvaW50ZXJmYWNlL3BhZ2UnO1xuaW1wb3J0IHtOQUVfUFJFRkVSUkVEX1RBU0tfRU5EUE9JTlR9IGZyb20gJy4uL21vZGVscy9pbmplY3Rpb24tdG9rZW4tdGFzay1lbmRwb2ludCc7XG5pbXBvcnQge1BhZ2VMb2FkUmVxdWVzdENvbnRleHR9IGZyb20gJy4uLy4uL2Fic3RyYWN0L3BhZ2UtbG9hZC1yZXF1ZXN0LWNvbnRleHQnO1xuaW1wb3J0IHtGaWx0ZXJ9IGZyb20gJy4uLy4uLy4uL2ZpbHRlci9tb2RlbHMvZmlsdGVyJztcbmltcG9ydCB7VGFza1BhZ2VMb2FkUmVxdWVzdFJlc3VsdH0gZnJvbSAnLi4vbW9kZWxzL3Rhc2stcGFnZS1sb2FkLXJlcXVlc3QtcmVzdWx0JztcbmltcG9ydCB7TG9hZGluZ1dpdGhGaWx0ZXJFbWl0dGVyfSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L2xvYWRpbmctd2l0aC1maWx0ZXItZW1pdHRlcic7XG5pbXBvcnQge2FycmF5VG9PYnNlcnZhYmxlfSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L2FycmF5LXRvLW9ic2VydmFibGUnO1xuaW1wb3J0IHtTZWFyY2hJbmRleFJlc29sdmVyU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vc2VhcmNoL3NlYXJjaC1rZXl3b3JkLXJlc29sdmVyLXNlcnZpY2Uvc2VhcmNoLWluZGV4LXJlc29sdmVyLnNlcnZpY2UnO1xuaW1wb3J0IHtBYnN0cmFjdFNvcnRhYmxlVmlld0NvbXBvbmVudH0gZnJvbSAnLi4vLi4vYWJzdHJhY3Qvc29ydGFibGUtdmlldyc7XG5pbXBvcnQge05BRV9UQVNLX1ZJRVdfQ09ORklHVVJBVElPTn0gZnJvbSAnLi4vbW9kZWxzL3Rhc2stdmlldy1jb25maWd1cmF0aW9uLWluamVjdGlvbi10b2tlbic7XG5pbXBvcnQge1Rhc2tWaWV3Q29uZmlndXJhdGlvbn0gZnJvbSAnLi4vbW9kZWxzL3Rhc2stdmlldy1jb25maWd1cmF0aW9uJztcbmltcG9ydCB7Q2hhbmdlZEZpZWxkc01hcH0gZnJvbSAnLi4vLi4vLi4vZXZlbnQvc2VydmljZXMvaW50ZXJmYWNlcy9jaGFuZ2VkLWZpZWxkcy1tYXAnO1xuaW1wb3J0IHtQYWdpbmF0aW9uUGFyYW1zfSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L3BhZ2luYXRpb24vcGFnaW5hdGlvbi1wYXJhbXMnO1xuaW1wb3J0IHtjcmVhdGVTb3J0UGFyYW0sIFBhZ2luYXRpb25Tb3J0fSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L3BhZ2luYXRpb24vcGFnaW5hdGlvbi1zb3J0JztcblxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVGFza1ZpZXdTZXJ2aWNlIGV4dGVuZHMgQWJzdHJhY3RTb3J0YWJsZVZpZXdDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHJvdGVjdGVkIF90YXNrcyQ6IE9ic2VydmFibGU8QXJyYXk8VGFza1BhbmVsRGF0YT4+O1xuICAgIHByb3RlY3RlZCBfY2hhbmdlZEZpZWxkcyQ6IFN1YmplY3Q8Q2hhbmdlZEZpZWxkc01hcD47XG4gICAgcHJvdGVjdGVkIF9yZXF1ZXN0ZWRQYWdlJDogQmVoYXZpb3JTdWJqZWN0PFBhZ2VMb2FkUmVxdWVzdENvbnRleHQ+O1xuICAgIHByb3RlY3RlZCBfbG9hZGluZyQ6IExvYWRpbmdXaXRoRmlsdGVyRW1pdHRlcjtcbiAgICBwcm90ZWN0ZWQgX2VuZE9mRGF0YTogYm9vbGVhbjtcbiAgICBwcm90ZWN0ZWQgX3BhZ2luYXRpb246IFBhZ2luYXRpb247XG4gICAgcHJvdGVjdGVkIF9pbml0aWFsbHlPcGVuT25lVGFzazogYm9vbGVhbjtcbiAgICBwcm90ZWN0ZWQgX2Nsb3NlVGFza1RhYk9uTm9UYXNrczogYm9vbGVhbjtcbiAgICBwcm90ZWN0ZWQgX3BhbmVsVXBkYXRlJDogQmVoYXZpb3JTdWJqZWN0PEFycmF5PFRhc2tQYW5lbERhdGE+PjtcbiAgICBwcm90ZWN0ZWQgX2Nsb3NlVGFiJDogUmVwbGF5U3ViamVjdDx2b2lkPjtcbiAgICBwcm90ZWN0ZWQgX3N1YkluaXRpYWxseU9wZW46IFN1YnNjcmlwdGlvbjtcbiAgICBwcm90ZWN0ZWQgX3N1YkNsb3NlVGFzazogU3Vic2NyaXB0aW9uO1xuICAgIHByb3RlY3RlZCBfc3ViU2VhcmNoOiBTdWJzY3JpcHRpb247XG5cbiAgICAvLyBTZXJpYWxpemluZyBhc3NpZ24gYWZ0ZXIgY2FuY2VsXG4gICAgcHJvdGVjdGVkIF9hbGxvd011bHRpT3BlbjogYm9vbGVhbjtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2luaXRpYWxpemluZzogYm9vbGVhbiA9IHRydWU7XG4gICAgcHJvdGVjdGVkIF9wYWdpbmF0aW9uVmlldzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IocHJvdGVjdGVkIF90YXNrU2VydmljZTogVGFza1Jlc291cmNlU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcml2YXRlIF91c2VyU2VydmljZTogVXNlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBfc25hY2tCYXJTZXJ2aWNlOiBTbmFja0JhclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBfdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfc2VhcmNoU2VydmljZTogU2VhcmNoU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcml2YXRlIF9sb2c6IExvZ2dlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBfdXNlckNvbXBhcmF0b3I6IFVzZXJDb21wYXJhdG9yU2VydmljZSxcbiAgICAgICAgICAgICAgICByZXNvbHZlcjogU2VhcmNoSW5kZXhSZXNvbHZlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChOQUVfUFJFRkVSUkVEX1RBU0tfRU5EUE9JTlQpIHByb3RlY3RlZCByZWFkb25seSBfcHJlZmVycmVkRW5kcG9pbnQ6IFRhc2tFbmRwb2ludCA9IG51bGwsXG4gICAgICAgICAgICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChOQUVfVEFTS19WSUVXX0NPTkZJR1VSQVRJT04pIHRhc2tWaWV3Q29uZmlnOiBUYXNrVmlld0NvbmZpZ3VyYXRpb24gPSBudWxsKSB7XG4gICAgICAgIHN1cGVyKHJlc29sdmVyKTtcbiAgICAgICAgdGhpcy5fdGFza3MkID0gbmV3IFN1YmplY3Q8QXJyYXk8VGFza1BhbmVsRGF0YT4+KCk7XG4gICAgICAgIHRoaXMuX2xvYWRpbmckID0gbmV3IExvYWRpbmdXaXRoRmlsdGVyRW1pdHRlcigpO1xuICAgICAgICB0aGlzLl9jaGFuZ2VkRmllbGRzJCA9IG5ldyBTdWJqZWN0PENoYW5nZWRGaWVsZHNNYXA+KCk7XG4gICAgICAgIHRoaXMuX2FsbG93TXVsdGlPcGVuID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fZW5kT2ZEYXRhID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX3BhZ2luYXRpb24gPSB7XG4gICAgICAgICAgICBzaXplOiA1MCxcbiAgICAgICAgICAgIHRvdGFsRWxlbWVudHM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHRvdGFsUGFnZXM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG51bWJlcjogLTFcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5fcmVxdWVzdGVkUGFnZSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFBhZ2VMb2FkUmVxdWVzdENvbnRleHQ+KFxuICAgICAgICAgICAgbmV3IFBhZ2VMb2FkUmVxdWVzdENvbnRleHQodGhpcy5hY3RpdmVGaWx0ZXIsIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX3BhZ2luYXRpb24sIHtudW1iZXI6IDB9KSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5fcGFuZWxVcGRhdGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBcnJheTxUYXNrUGFuZWxEYXRhPj4oW10pO1xuICAgICAgICB0aGlzLl9jbG9zZVRhYiQgPSBuZXcgUmVwbGF5U3ViamVjdDx2b2lkPigxKTtcbiAgICAgICAgdGhpcy5fcHJlZmVycmVkRW5kcG9pbnQgPSB0YXNrVmlld0NvbmZpZz8ucHJlZmVycmVkRW5kcG9pbnQgPz8gKHRoaXMuX3ByZWZlcnJlZEVuZHBvaW50ID8/IFRhc2tFbmRwb2ludC5NT05HTyk7XG5cbiAgICAgICAgdGhpcy5faW5pdGlhbGl6aW5nID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5fc3ViU2VhcmNoID0gdGhpcy5fc2VhcmNoU2VydmljZS5hY3RpdmVGaWx0ZXIkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbG9hZCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0YXNrc01hcCQgPSB0aGlzLl9yZXF1ZXN0ZWRQYWdlJC5waXBlKFxuICAgICAgICAgICAgbWVyZ2VNYXAocCA9PiB0aGlzLmxvYWRQYWdlKHApKSxcbiAgICAgICAgICAgIG1hcChwYWdlTG9hZFJlc3VsdCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHBhZ2VMb2FkUmVzdWx0LnJlcXVlc3RDb250ZXh0ICYmIHBhZ2VMb2FkUmVzdWx0LnJlcXVlc3RDb250ZXh0LmNsZWFyTG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHdlIHNldCBhbiBlbXB0eSB2YWx1ZSB0byB0aGUgdmlydHVhbCBzY3JvbGwgYW5kIHRoZW4gcmVwbGFjZSBpdCBieSB0aGUgcmVhbCB2YWx1ZSBmb3JjaW5nIGl0IHRvIHJlZHJhdyBpdHMgY29udGVudFxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHRzID0gW3t0YXNrczoge30sIHJlcXVlc3RDb250ZXh0OiBudWxsfSwgcGFnZUxvYWRSZXN1bHRdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlUb09ic2VydmFibGUocmVzdWx0cyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKHBhZ2VMb2FkUmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNvbmNhdE1hcChvID0+IG8pLFxuICAgICAgICAgICAgc2NhbigoYWNjLCBwYWdlTG9hZFJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCByZXN1bHQ6IHsgW2s6IHN0cmluZ106IFRhc2tQYW5lbERhdGEgfTtcbiAgICAgICAgICAgICAgICBpZiAocGFnZUxvYWRSZXN1bHQucmVxdWVzdENvbnRleHQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhZ2VMb2FkUmVzdWx0LnRhc2tzO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwYWdlTG9hZFJlc3VsdC5yZXF1ZXN0Q29udGV4dC5yZWxvYWRDdXJyZW50VGFza1BhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoYWNjKS5mb3JFYWNoKHRhc2tJZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXBhZ2VMb2FkUmVzdWx0LnRhc2tzW3Rhc2tJZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgYWNjW3Rhc2tJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMb2FkUmVzdWx0LnRhc2tzW3Rhc2tJZF0udGFzay5kYXRhR3JvdXBzID0gYWNjW3Rhc2tJZF0udGFzay5kYXRhR3JvdXBzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMb2FkUmVzdWx0LnRhc2tzW3Rhc2tJZF0uaW5pdGlhbGx5RXhwYW5kZWQgPSBhY2NbdGFza0lkXS5pbml0aWFsbHlFeHBhbmRlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVRhc2soYWNjW3Rhc2tJZF0udGFzaywgcGFnZUxvYWRSZXN1bHQudGFza3NbdGFza0lkXS50YXNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJsb2NrVGFza0ZpZWxkcyhhY2NbdGFza0lkXS50YXNrLCAhKGFjY1t0YXNrSWRdLnRhc2sudXNlcklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYmIHRoaXMuX3VzZXJDb21wYXJhdG9yLmNvbXBhcmVVc2VycyhhY2NbdGFza0lkXS50YXNrLnVzZXJJZCkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3BhZ2luYXRpb25WaWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBwYWdlTG9hZFJlc3VsdC50YXNrc1t0YXNrSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IE9iamVjdC5hc3NpZ24oYWNjLCBwYWdlTG9hZFJlc3VsdC50YXNrcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gey4uLmFjYywgLi4ucGFnZUxvYWRSZXN1bHQudGFza3N9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5fcGFnaW5hdGlvbiwgcGFnZUxvYWRSZXN1bHQucmVxdWVzdENvbnRleHQucGFnaW5hdGlvbik7XG4gICAgICAgICAgICAgICAgaWYgKHBhZ2VMb2FkUmVzdWx0LnJlcXVlc3RDb250ZXh0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRpbmckLm9mZihwYWdlTG9hZFJlc3VsdC5yZXF1ZXN0Q29udGV4dC5maWx0ZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fcGFnaW5hdGlvblZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhZ2VMb2FkUmVzdWx0LnRhc2tzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfSwge30pXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuX3Rhc2tzJCA9IHRhc2tzTWFwJC5waXBlKFxuICAgICAgICAgICAgbWFwKHYgPT4gT2JqZWN0LnZhbHVlcyh2KSBhcyBBcnJheTxUYXNrUGFuZWxEYXRhPiksXG4gICAgICAgICAgICBtYXAodGFza0FycmF5ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGFza0FycmF5Lmxlbmd0aCA9PT0gMSAmJiB0aGlzLl9pbml0aWFsbHlPcGVuT25lVGFzaykge1xuICAgICAgICAgICAgICAgICAgICB0YXNrQXJyYXlbMF0udGFzay5maW5pc2hEYXRlID09PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFza0FycmF5WzBdLmluaXRpYWxseUV4cGFuZGVkID0gdHJ1ZSA6XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXNrQXJyYXlbMF0uaW5pdGlhbGx5RXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRhc2tBcnJheTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgdGFwKHYgPT4gdGhpcy5fcGFuZWxVcGRhdGUkLm5leHQodikpKTtcblxuICAgICAgICB0aGlzLl9zdWJJbml0aWFsbHlPcGVuID0gKHRhc2tWaWV3Q29uZmlnPy5pbml0aWFsbHlPcGVuT25lVGFzayA/PyBvZih0cnVlKSkuc3Vic2NyaWJlKGJvb2wgPT4ge1xuICAgICAgICAgICAgdGhpcy5faW5pdGlhbGx5T3Blbk9uZVRhc2sgPSBib29sO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLl9zdWJDbG9zZVRhc2sgPSAodGFza1ZpZXdDb25maWc/LmNsb3NlVGFza1RhYk9uTm9UYXNrcyA/PyBvZih0cnVlKSkuc3Vic2NyaWJlKGJvb2wgPT4ge1xuICAgICAgICAgICAgdGhpcy5fY2xvc2VUYXNrVGFiT25Ob1Rhc2tzID0gYm9vbDtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLm5nT25EZXN0cm95KCk7XG4gICAgICAgIHRoaXMuX2NoYW5nZWRGaWVsZHMkLmNvbXBsZXRlKCk7XG4gICAgICAgIHRoaXMuX3JlcXVlc3RlZFBhZ2UkLmNvbXBsZXRlKCk7XG4gICAgICAgIHRoaXMuX3BhbmVsVXBkYXRlJC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLl9jbG9zZVRhYiQuY29tcGxldGUoKTtcbiAgICAgICAgdGhpcy5fc3ViSW5pdGlhbGx5T3Blbi51bnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLl9zdWJDbG9zZVRhc2sudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgdGhpcy5fc3ViU2VhcmNoLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCB0YXNrcyQoKTogT2JzZXJ2YWJsZTxBcnJheTxUYXNrUGFuZWxEYXRhPj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fdGFza3MkO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY2hhbmdlZEZpZWxkcyQoKTogU3ViamVjdDxDaGFuZ2VkRmllbGRzTWFwPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaGFuZ2VkRmllbGRzJDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGxvYWRpbmckKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGluZyQuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBsb2FkaW5nKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGluZyQuaXNBY3RpdmU7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBwYW5lbFVwZGF0ZSgpOiBPYnNlcnZhYmxlPEFycmF5PFRhc2tQYW5lbERhdGE+PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wYW5lbFVwZGF0ZSQuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBjbG9zZVRhYigpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Nsb3NlVGFiJC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHBhZ2luYXRpb24oKTogUGFnaW5hdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wYWdpbmF0aW9uO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgYWN0aXZlRmlsdGVyKCk6IEZpbHRlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZWFyY2hTZXJ2aWNlLmFjdGl2ZUZpbHRlcjtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0IGFsbG93TXVsdGlPcGVuKGJvb2w6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fYWxsb3dNdWx0aU9wZW4gPSBib29sO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgYWxsb3dNdWx0aU9wZW4oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hbGxvd011bHRpT3BlbjtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0IHBhZ2luYXRpb25WaWV3KHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX3BhZ2luYXRpb25WaWV3ID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcHVibGljIGxvYWRQYWdlKHJlcXVlc3RDb250ZXh0OiBQYWdlTG9hZFJlcXVlc3RDb250ZXh0KTogT2JzZXJ2YWJsZTxUYXNrUGFnZUxvYWRSZXF1ZXN0UmVzdWx0PiB7XG4gICAgICAgIGlmIChyZXF1ZXN0Q29udGV4dCA9PT0gbnVsbCB8fCByZXF1ZXN0Q29udGV4dC5wYWdlTnVtYmVyIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIG9mKHt0YXNrczoge30sIHJlcXVlc3RDb250ZXh0fSk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHBhcmFtczogSHR0cFBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKCk7XG4gICAgICAgIHBhcmFtcyA9IHRoaXMuYWRkU29ydFBhcmFtcyhwYXJhbXMpO1xuICAgICAgICBwYXJhbXMgPSB0aGlzLmFkZFBhZ2VQYXJhbXMocGFyYW1zLCByZXF1ZXN0Q29udGV4dC5wYWdpbmF0aW9uKTtcbiAgICAgICAgdGhpcy5fbG9hZGluZyQub24ocmVxdWVzdENvbnRleHQuZmlsdGVyKTtcblxuICAgICAgICBsZXQgcmVxdWVzdDogT2JzZXJ2YWJsZTxQYWdlPFRhc2s+PjtcbiAgICAgICAgaWYgKHJlcXVlc3RDb250ZXh0LmZpbHRlci5ib2R5Q29udGFpbnNRdWVyeSgpIHx8IHRoaXMuX3ByZWZlcnJlZEVuZHBvaW50ID09PSBUYXNrRW5kcG9pbnQuRUxBU1RJQykge1xuICAgICAgICAgICAgcmVxdWVzdCA9IHRpbWVyKDIwMCkucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5fdGFza1NlcnZpY2Uuc2VhcmNoVGFzayhyZXF1ZXN0Q29udGV4dC5maWx0ZXIsIHBhcmFtcykucGlwZSh0YWtlKDEpKSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXF1ZXN0ID0gdGhpcy5fdGFza1NlcnZpY2UuZ2V0VGFza3MocmVxdWVzdENvbnRleHQuZmlsdGVyLCBwYXJhbXMpLnBpcGUodGFrZSgxKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcXVlc3QucGlwZShcbiAgICAgICAgICAgIGNhdGNoRXJyb3IoZXJyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2cuZXJyb3IoJ0xvYWRpbmcgdGFza3MgaGFzIGZhaWxlZCEnLCBlcnIpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRpbmckLm9mZihyZXF1ZXN0Q29udGV4dC5maWx0ZXIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBvZih7Y29udGVudDogW10sIHBhZ2luYXRpb246IHsuLi50aGlzLl9wYWdpbmF0aW9ufX0pO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBmaWx0ZXIoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHIgPSByZXF1ZXN0Q29udGV4dC5maWx0ZXIgPT09IHRoaXMuX3NlYXJjaFNlcnZpY2UuYWN0aXZlRmlsdGVyO1xuICAgICAgICAgICAgICAgIGlmICghcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkaW5nJC5vZmYocmVxdWVzdENvbnRleHQuZmlsdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9nLmRlYnVnKCdSZWNlaXZlZCB0YXNrcyBwYWdlIGlzIG5vIGxvbmdlciByZWxldmFudCBzaW5jZSB0aGUgYWN0aXZlIGZpbHRlciBoYXMgY2hhbmdlZCBiZWZvcmUgaXQgY291bGQgYXJyaXZlLidcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJyBEaXNjYXJkaW5nLi4uJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihyZXF1ZXN0Q29udGV4dC5wYWdpbmF0aW9uLCB0LnBhZ2luYXRpb24pO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3BhZ2luYXRpb24udG90YWxFbGVtZW50cyAmJiB0aGlzLl9wYWdpbmF0aW9uLnRvdGFsRWxlbWVudHMgPiAwXG4gICAgICAgICAgICAgICAgICAgICYmIHQucGFnaW5hdGlvbi50b3RhbEVsZW1lbnRzID09PSAwICYmICFBcnJheS5pc0FycmF5KHQuY29udGVudCkgJiYgdGhpcy5fY2xvc2VUYXNrVGFiT25Ob1Rhc2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2Nsb3NlVGFiJC5uZXh0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZW5kT2ZEYXRhID0gIUFycmF5LmlzQXJyYXkodC5jb250ZW50KVxuICAgICAgICAgICAgICAgICAgICB8fCB0LmNvbnRlbnQubGVuZ3RoID09PSAwXG4gICAgICAgICAgICAgICAgICAgIHx8IHQucGFnaW5hdGlvbi5udW1iZXIgPT09IHQucGFnaW5hdGlvbi50b3RhbFBhZ2VzO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBtYXAodGFza3MgPT4gQXJyYXkuaXNBcnJheSh0YXNrcy5jb250ZW50KSA/IHRhc2tzIDogey4uLnRhc2tzLCBjb250ZW50OiBbXX0pLFxuICAgICAgICAgICAgbWFwKHRhc2tzID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGFza3MuY29udGVudC5yZWR1Y2UoKGFjYywgY3VycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJsb2NrVGFza0ZpZWxkcyhjdXJyLCAhKGN1cnIudXNlcklkICYmIHRoaXMuX3VzZXJDb21wYXJhdG9yLmNvbXBhcmVVc2VycyhjdXJyLnVzZXJJZCkpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmFjYywgW2N1cnIuc3RyaW5nSWRdOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzazogY3VycixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFuZ2VkRmllbGRzOiB0aGlzLl9jaGFuZ2VkRmllbGRzJCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsbHlFeHBhbmRlZDogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9LCB7fSk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIG1hcCh0YXNrcyA9PiAoe3Rhc2tzLCByZXF1ZXN0Q29udGV4dH0pKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlVGFzayhvbGQ6IFRhc2ssIG5ld3c6IFRhc2spIHtcbiAgICAgICAgT2JqZWN0LmtleXMob2xkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICBpZiAoIW5ld3cuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvbGRba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5rZXlzKG5ld3cpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgIGlmIChuZXd3W2tleV0gIT09IHVuZGVmaW5lZCAmJiBuZXd3W2tleV0gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBvbGRba2V5XSA9IG5ld3dba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYmxvY2tUYXNrRmllbGRzKG9sZCwgIShvbGQudXNlcklkICYmIHRoaXMuX3VzZXJDb21wYXJhdG9yLmNvbXBhcmVVc2VycyhvbGQudXNlcklkKSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYmxvY2tUYXNrRmllbGRzKHRhc2s6IFRhc2ssIGJsb2NrOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICghdGFzay5kYXRhR3JvdXBzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGFzay5kYXRhR3JvdXBzLmZvckVhY2goZyA9PiBnLmZpZWxkcy5mb3JFYWNoKGYgPT4gZi5ibG9jayA9IGJsb2NrKSk7XG4gICAgfVxuXG4gICAgcHVibGljIG5leHRQYWdlKHJlbmRlcmVkUmFuZ2U6IExpc3RSYW5nZSwgdG90YWxMb2FkZWQ6IG51bWJlciwgcmVxdWVzdENvbnRleHQ/OiBQYWdlTG9hZFJlcX