@netgrif/components-core
Version:
Netgrif Application engine frontend core Angular library
287 lines • 42.7 kB
JavaScript
import { Inject, Injectable } from '@angular/core';
import { AssignPolicy } from '../../../task-content/model/policy';
import { NAE_TASK_OPERATIONS } from '../../../task/models/task-operations-injection-token';
import { TreePetriflowIdentifiers } from '../model/tree-petriflow-identifiers';
import { LoadingEmitter } from '../../../utility/loading-emitter';
import { ReplaySubject } from 'rxjs';
import { hasContent } from '../../../utility/pagination/page-has-content';
import { getImmediateData } from '../../../utility/get-immediate-data';
import { filter } from 'rxjs/operators';
import { SimpleFilter } from '../../../filter/models/simple-filter';
import * as i0 from "@angular/core";
import * as i1 from "../tree-case-view.service";
import * as i2 from "../../../task/services/task-data.service";
import * as i3 from "../../../task-content/services/task-content.service";
import * as i4 from "../../../resources/engine-endpoint/task-resource.service";
import * as i5 from "../../../task-content/services/task-event.service";
import * as i6 from "../../../task/services/assign-policy.service";
import * as i7 from "../../../task/services/cancel-task.service";
import * as i8 from "../../../user/services/user-comparator.service";
import * as i9 from "../../../utility/call-chain/call-chain.service";
import * as i10 from "../../../logger/services/logger.service";
import * as i11 from "../../../task/services/selected-case.service";
import * as i12 from "../../../changed-fields/services/changed-fields.service";
import * as i13 from "../../../authorization/permission/permission.service";
import * as i14 from "../../../task/models/subject-task-operations";
export class TreeTaskContentService {
_treeCaseService;
_taskDataService;
_taskContentService;
_taskResourceService;
_taskEventService;
_assignPolicy;
_cancel;
_userComparator;
_callchain;
_logger;
_selectedCaseService;
_changedFieldsService;
_permissionService;
_taskOperations;
_processingTaskChange;
_displayedTaskText$;
/**
* a unique identifier consisting of caseId and transition ID
*
* Is set if a reload of the given task is currently taking place, `undefined` otherwise.
*/
_reloadedTaskUniqueIdentifier;
constructor(_treeCaseService, _taskDataService, _taskContentService, _taskResourceService, _taskEventService, _assignPolicy, _cancel, _userComparator, _callchain, _logger, _selectedCaseService, _changedFieldsService, _permissionService, _taskOperations) {
this._treeCaseService = _treeCaseService;
this._taskDataService = _taskDataService;
this._taskContentService = _taskContentService;
this._taskResourceService = _taskResourceService;
this._taskEventService = _taskEventService;
this._assignPolicy = _assignPolicy;
this._cancel = _cancel;
this._userComparator = _userComparator;
this._callchain = _callchain;
this._logger = _logger;
this._selectedCaseService = _selectedCaseService;
this._changedFieldsService = _changedFieldsService;
this._permissionService = _permissionService;
this._taskOperations = _taskOperations;
this._processingTaskChange = new LoadingEmitter();
this._displayedTaskText$ = new ReplaySubject();
this._changedFieldsService.changedFields$.subscribe((changedFieldsMap) => {
const filteredCaseIds = Object.keys(changedFieldsMap).filter(caseId => Object.keys(this._taskContentService.referencedTaskAndCaseIds).includes(caseId));
const changedFields = [];
filteredCaseIds.forEach(caseId => {
const taskIds = this._taskContentService.referencedTaskAndCaseIds[caseId];
changedFields.push(...this._changedFieldsService.parseChangedFieldsByCaseAndTaskIds(caseId, taskIds, changedFieldsMap));
});
changedFields.filter(fields => fields !== undefined).forEach(fields => {
this._taskContentService.updateFromChangedFields(fields);
});
});
_taskDataService.updateSuccess$.subscribe(result => {
if (result) {
this._treeCaseService.reloadCase$.next();
this.resolveTaskBlockState();
}
});
_treeCaseService.loadTask$.asObservable().pipe(filter(selectedCase => this.taskChanged(selectedCase))).subscribe(selectedCase => {
this.cancelAndLoadFeaturedTask(selectedCase);
});
_taskOperations.reload$.subscribe(() => {
this.updateTaskState();
this._treeCaseService.reloadCase$.next();
});
_taskOperations.open$.subscribe(() => {
this._taskContentService.blockFields(false);
});
_taskOperations.close$.subscribe(() => {
this._taskContentService.blockFields(true);
});
}
get taskContentText$() {
return this._displayedTaskText$.asObservable();
}
get processingTaskChange() {
return this._processingTaskChange.isActive;
}
displayEmptyTaskContent() {
this._taskContentService.$shouldCreate.next([]);
this._displayedTaskText$.next('caseTree.noTaskSelected');
}
/**
* Cancels the currently selected {@link Task} if any. And then loads and assigns the new Task.
* @param selectedCase the Case who's task should be now displayed
*/
cancelAndLoadFeaturedTask(selectedCase) {
this._processingTaskChange.on();
this._taskContentService.blockFields(true);
if (this.shouldCancelTask) {
this._cancel.cancel(this._callchain.create(success => {
if (success) {
this._logger.debug('Old tree task successfully canceled');
}
else {
this._logger.warn('Old tree task could not be canceled');
}
}));
}
this.loadFeaturedTask(selectedCase);
}
/**
* Changes the currently displayed {@link Task} based on the selected {@link Case} from the Tree.
* @param selectedCase the Case who's task should be now displayed
*/
loadFeaturedTask(selectedCase) {
this._selectedCaseService.selectedCase = selectedCase;
const requestBody = this.getTaskFilter();
if (requestBody === undefined) {
this.clearCurrentTask();
return;
}
this._taskResourceService.getTasks(requestBody).subscribe(page => {
if (hasContent(page)) {
this.setStandardTaskText();
this.switchToTask(page.content[0]);
}
else {
this.clearCurrentTask();
}
});
}
/**
* Checks whether the currently displayed task differs from the new one
* @param newCase [Case]{@link Case} object that holds the newly selected {@link Task}
* @returns `true` if the currently selected Case has a different ID from the newly selected Case.
* If the IDs are the same returns `true` if the transition IDs are different.
* Returns `false` otherwise.
*/
taskChanged(newCase) {
const currentCaseId = this._selectedCaseService.selectedCase ? this._selectedCaseService.selectedCase.stringId : undefined;
const newCaseId = newCase ? newCase.stringId : undefined;
if (currentCaseId !== newCaseId) {
return true;
}
const currentTransitionId = this.getTransitionId(this._selectedCaseService.selectedCase);
const newTransitionId = this.getTransitionId(newCase);
return currentTransitionId !== newTransitionId;
}
/**
* Checks whether a Task object is currently selected and if it can be cancelled by the user
*/
get shouldCancelTask() {
return this._taskContentService.task && this._permissionService.canCancel(this._taskContentService.task);
}
/**
* Creates a {@link Filter} object that finds the specified Task for the currently selected Case in a Tree Case View
* @returns a request body that finds tasks of the given case with task id that corresponds to the value in the `treeTaskTransitionId`
* immediate data field. Returns `undefined` if the request body cannot be created.
*/
getTaskFilter() {
const transitionId = this.getTransitionId(this._selectedCaseService.selectedCase);
if (transitionId) {
return SimpleFilter.fromTaskQuery({
case: { id: this._selectedCaseService.selectedCase.stringId },
transitionId
});
}
return undefined;
}
/**
* @param examinedCase the {@link Case} object from which we want to extract the transition ID
* @returns the ID of the transition that should be displayed in the {@link AbstractTaskContentComponent},
* or `undefined` if the currently selected case doesn't define it
*/
getTransitionId(examinedCase) {
if (examinedCase && examinedCase.immediateData) {
const transitionId = getImmediateData(examinedCase, TreePetriflowIdentifiers.FEATURED_TRANSITION);
return transitionId ? transitionId.value : undefined;
}
return undefined;
}
/**
* Changes the currently selected {@link Task}.
* @param task the Task that should now be selected
*/
switchToTask(task) {
if (task.caseId !== this._selectedCaseService.selectedCase.stringId) {
this._logger.debug('Tree featured task has been loaded, but the selected case has changed since. Discarding...');
return;
}
task.assignPolicy = AssignPolicy.auto;
this._taskContentService.task = task;
this._taskContentService.blockFields(true);
this._assignPolicy.performAssignPolicy(true, this._callchain.create(() => {
this._processingTaskChange.off();
}));
}
/**
* Notifies all connected Services that no Task is currently selected
*/
clearCurrentTask() {
this._taskContentService.task = undefined;
this.displayEmptyTaskContent();
this._processingTaskChange.off();
}
/**
* Updates the state of the current Task from backend
*/
updateTaskState() {
const uniqueTaskIdentifier = this.getUniqueTaskIdentifier();
if (uniqueTaskIdentifier === this._reloadedTaskUniqueIdentifier) {
this._logger.debug('The currently selected task is already being reloaded. Ignoring reload request.');
return;
}
this._reloadedTaskUniqueIdentifier = uniqueTaskIdentifier;
this._taskResourceService.getTasks(this.getTaskFilter()).subscribe(page => {
if (hasContent(page)) {
if (this._taskContentService.task && this._taskContentService.task.stringId === page.content[0].stringId) {
this._reloadedTaskUniqueIdentifier = undefined;
Object.assign(this._taskContentService.task, page.content[0]);
}
this.resolveTaskBlockState();
}
});
}
/**
* If the current {@link Task} is assigned to the current user it is unblocked. Otherwise it is blocked.
*/
resolveTaskBlockState() {
const taskShouldBeBlocked = !this._taskContentService.task
|| this._taskContentService.task.userId === undefined
|| !this._userComparator.compareUsers(this._taskContentService.task.userId);
this._taskContentService.blockFields(taskShouldBeBlocked);
}
/**
* Sets the noData text in the task content to it's default value
*/
setStandardTaskText() {
this._displayedTaskText$.next(undefined);
}
/**
* Attempts to cancel the currently opened Task if the Task is in such state that allows cancellation.
*/
ngOnDestroy() {
if (this.shouldCancelTask) {
this._cancel.cancel();
}
if (this._taskOperations) {
this._taskOperations.destroy();
}
}
/**
* @returns a unique identifier for the currently selected task, that consists of it's case's id and it's transition id.
*
* Returns `undefined`, if no task is currently selected.
*/
getUniqueTaskIdentifier() {
if (!this._selectedCaseService.selectedCase) {
return undefined;
}
return `${this._selectedCaseService.selectedCase.stringId}#${this.getTransitionId(this._selectedCaseService.selectedCase)}`;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TreeTaskContentService, deps: [{ token: i1.TreeCaseViewService }, { token: i2.TaskDataService }, { token: i3.TaskContentService }, { token: i4.TaskResourceService }, { token: i5.TaskEventService }, { token: i6.AssignPolicyService }, { token: i7.CancelTaskService }, { token: i8.UserComparatorService }, { token: i9.CallChainService }, { token: i10.LoggerService }, { token: i11.SelectedCaseService }, { token: i12.ChangedFieldsService }, { token: i13.PermissionService }, { token: NAE_TASK_OPERATIONS }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TreeTaskContentService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TreeTaskContentService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.TreeCaseViewService }, { type: i2.TaskDataService }, { type: i3.TaskContentService }, { type: i4.TaskResourceService }, { type: i5.TaskEventService }, { type: i6.AssignPolicyService }, { type: i7.CancelTaskService }, { type: i8.UserComparatorService }, { type: i9.CallChainService }, { type: i10.LoggerService }, { type: i11.SelectedCaseService }, { type: i12.ChangedFieldsService }, { type: i13.PermissionService }, { type: i14.SubjectTaskOperations, decorators: [{
type: Inject,
args: [NAE_TASK_OPERATIONS]
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS10YXNrLWNvbnRlbnQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25ldGdyaWYtY29tcG9uZW50cy1jb3JlL3NyYy9saWIvdmlldy90cmVlLWNhc2Utdmlldy90cmVlLXRhc2stY29udGVudC90cmVlLXRhc2stY29udGVudC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBVTVELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxvQ0FBb0MsQ0FBQztBQUNoRSxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSxzREFBc0QsQ0FBQztBQUd6RixPQUFPLEVBQUMsd0JBQXdCLEVBQUMsTUFBTSxxQ0FBcUMsQ0FBQztBQUU3RSxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sa0NBQWtDLENBQUM7QUFDaEUsT0FBTyxFQUFhLGFBQWEsRUFBVSxNQUFNLE1BQU0sQ0FBQztBQUN4RCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sOENBQThDLENBQUM7QUFDeEUsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0scUNBQXFDLENBQUM7QUFDckUsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBSXRDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxzQ0FBc0MsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7OztBQU9sRSxNQUFNLE9BQU8sc0JBQXNCO0lBV1Q7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDNkI7SUF0QjNDLHFCQUFxQixDQUFpQjtJQUN0QyxtQkFBbUIsQ0FBd0I7SUFDbkQ7Ozs7T0FJRztJQUNLLDZCQUE2QixDQUFTO0lBRTlDLFlBQXNCLGdCQUFxQyxFQUNyQyxnQkFBaUMsRUFDakMsbUJBQXVDLEVB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QUFDLENBQUM7SUFDN0MsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNQLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFO1lBQ3ZCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDekI7UUFDRCxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDdEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNsQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ08sdUJBQXVCO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsWUFBWSxFQUFFO1lBQ3pDLE9BQU8sU0FBUyxDQUFDO1NBQ3BCO1FBQ0QsT0FBTyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7SUFDaEksQ0FBQzt3R0FyUVEsc0JBQXNCLDJjQXdCWCxtQkFBbUI7NEdBeEI5QixzQkFBc0I7OzRGQUF0QixzQkFBc0I7a0JBRGxDLFVBQVU7OzBCQXlCTSxNQUFNOzJCQUFDLG1CQUFtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0LCBJbmplY3RhYmxlLCBPbkRlc3Ryb3l9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtUYXNrQ29udGVudFNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3Rhc2stY29udGVudC9zZXJ2aWNlcy90YXNrLWNvbnRlbnQuc2VydmljZSc7XG5pbXBvcnQge1Rhc2tEYXRhU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdGFzay9zZXJ2aWNlcy90YXNrLWRhdGEuc2VydmljZSc7XG5pbXBvcnQge0NhbmNlbFRhc2tTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi90YXNrL3NlcnZpY2VzL2NhbmNlbC10YXNrLnNlcnZpY2UnO1xuaW1wb3J0IHtUYXNrRXZlbnRTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi90YXNrLWNvbnRlbnQvc2VydmljZXMvdGFzay1ldmVudC5zZXJ2aWNlJztcbmltcG9ydCB7VGFza1Jlc291cmNlU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vcmVzb3VyY2VzL2VuZ2luZS1lbmRwb2ludC90YXNrLXJlc291cmNlLnNlcnZpY2UnO1xuaW1wb3J0IHtUcmVlQ2FzZVZpZXdTZXJ2aWNlfSBmcm9tICcuLi90cmVlLWNhc2Utdmlldy5zZXJ2aWNlJztcbmltcG9ydCB7Q2FzZX0gZnJvbSAnLi4vLi4vLi4vcmVzb3VyY2VzL2ludGVyZmFjZS9jYXNlJztcbmltcG9ydCB7VGFza30gZnJvbSAnLi4vLi4vLi4vcmVzb3VyY2VzL2ludGVyZmFjZS90YXNrJztcbmltcG9ydCB7QXNzaWduUG9saWN5U2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdGFzay9zZXJ2aWNlcy9hc3NpZ24tcG9saWN5LnNlcnZpY2UnO1xuaW1wb3J0IHtBc3NpZ25Qb2xpY3l9IGZyb20gJy4uLy4uLy4uL3Rhc2stY29udGVudC9tb2RlbC9wb2xpY3knO1xuaW1wb3J0IHtOQUVfVEFTS19PUEVSQVRJT05TfSBmcm9tICcuLi8uLi8uLi90YXNrL21vZGVscy90YXNrLW9wZXJhdGlvbnMtaW5qZWN0aW9uLXRva2VuJztcbmltcG9ydCB7U3ViamVjdFRhc2tPcGVyYXRpb25zfSBmcm9tICcuLi8uLi8uLi90YXNrL21vZGVscy9zdWJqZWN0LXRhc2stb3BlcmF0aW9ucyc7XG5pbXBvcnQge1VzZXJDb21wYXJhdG9yU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdXNlci9zZXJ2aWNlcy91c2VyLWNvbXBhcmF0b3Iuc2VydmljZSc7XG5pbXBvcnQge1RyZWVQZXRyaWZsb3dJZGVudGlmaWVyc30gZnJvbSAnLi4vbW9kZWwvdHJlZS1wZXRyaWZsb3ctaWRlbnRpZmllcnMnO1xuaW1wb3J0IHtDYWxsQ2hhaW5TZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L2NhbGwtY2hhaW4vY2FsbC1jaGFpbi5zZXJ2aWNlJztcbmltcG9ydCB7TG9hZGluZ0VtaXR0ZXJ9IGZyb20gJy4uLy4uLy4uL3V0aWxpdHkvbG9hZGluZy1lbWl0dGVyJztcbmltcG9ydCB7T2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2hhc0NvbnRlbnR9IGZyb20gJy4uLy4uLy4uL3V0aWxpdHkvcGFnaW5hdGlvbi9wYWdlLWhhcy1jb250ZW50JztcbmltcG9ydCB7Z2V0SW1tZWRpYXRlRGF0YX0gZnJvbSAnLi4vLi4vLi4vdXRpbGl0eS9nZXQtaW1tZWRpYXRlLWRhdGEnO1xuaW1wb3J0IHtmaWx0ZXJ9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7TG9nZ2VyU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vbG9nZ2VyL3NlcnZpY2VzL2xvZ2dlci5zZXJ2aWNlJztcbmltcG9ydCB7U2VsZWN0ZWRDYXNlU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdGFzay9zZXJ2aWNlcy9zZWxlY3RlZC1jYXNlLnNlcnZpY2UnO1xuaW1wb3J0IHtGaWx0ZXJ9IGZyb20gJy4uLy4uLy4uL2ZpbHRlci9tb2RlbHMvZmlsdGVyJztcbmltcG9ydCB7U2ltcGxlRmlsdGVyfSBmcm9tICcuLi8uLi8uLi9maWx0ZXIvbW9kZWxzL3NpbXBsZS1maWx0ZXInO1xuaW1wb3J0IHtQZXJtaXNzaW9uU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vYXV0aG9yaXphdGlvbi9wZXJtaXNzaW9uL3Blcm1pc3Npb24uc2VydmljZSc7XG5pbXBvcnQge0NoYW5nZWRGaWVsZHNTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi9jaGFuZ2VkLWZpZWxkcy9zZXJ2aWNlcy9jaGFuZ2VkLWZpZWxkcy5zZXJ2aWNlJztcbmltcG9ydCB7Q2hhbmdlZEZpZWxkc30gZnJvbSAnLi4vLi4vLi4vZGF0YS1maWVsZHMvbW9kZWxzL2NoYW5nZWQtZmllbGRzJztcbmltcG9ydCB7Q2hhbmdlZEZpZWxkc01hcH0gZnJvbSAnLi4vLi4vLi4vZXZlbnQvc2VydmljZXMvaW50ZXJmYWNlcy9jaGFuZ2VkLWZpZWxkcy1tYXAnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVHJlZVRhc2tDb250ZW50U2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG5cbiAgICBwcml2YXRlIF9wcm9jZXNzaW5nVGFza0NoYW5nZTogTG9hZGluZ0VtaXR0ZXI7XG4gICAgcHJpdmF0ZSBfZGlzcGxheWVkVGFza1RleHQkOiBSZXBsYXlTdWJqZWN0PHN0cmluZz47XG4gICAgLyoqXG4gICAgICogYSB1bmlxdWUgaWRlbnRpZmllciBjb25zaXN0aW5nIG9mIGNhc2VJZCBhbmQgdHJhbnNpdGlvbiBJRFxuICAgICAqXG4gICAgICogSXMgc2V0IGlmIGEgcmVsb2FkIG9mIHRoZSBnaXZlbiB0YXNrIGlzIGN1cnJlbnRseSB0YWtpbmcgcGxhY2UsIGB1bmRlZmluZWRgIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9yZWxvYWRlZFRhc2tVbmlxdWVJZGVudGlmaWVyOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX3RyZWVDYXNlU2VydmljZTogVHJlZUNhc2VWaWV3U2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX3Rhc2tEYXRhU2VydmljZTogVGFza0RhdGFTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfdGFza0NvbnRlbnRTZXJ2aWNlOiBUYXNrQ29udGVudFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF90YXNrUmVzb3VyY2VTZXJ2aWNlOiBUYXNrUmVzb3VyY2VTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfdGFza0V2ZW50U2VydmljZTogVGFza0V2ZW50U2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX2Fzc2lnblBvbGljeTogQXNzaWduUG9saWN5U2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX2NhbmNlbDogQ2FuY2VsVGFza1NlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF91c2VyQ29tcGFyYXRvcjogVXNlckNvbXBhcmF0b3JTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfY2FsbGNoYWluOiBDYWxsQ2hhaW5TZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfbG9nZ2VyOiBMb2dnZXJTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfc2VsZWN0ZWRDYXNlU2VydmljZTogU2VsZWN0ZWRDYXNlU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX2NoYW5nZWRGaWVsZHNTZXJ2aWNlOiBDaGFuZ2VkRmllbGRzU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX3Blcm1pc3Npb25TZXJ2aWNlOiBQZXJtaXNzaW9uU2VydmljZSxcbiAgICAgICAgICAgICAgICBASW5qZWN0KE5BRV9UQVNLX09QRVJBVElPTlMpIHByb3RlY3RlZCBfdGFza09wZXJhdGlvbnM6IFN1YmplY3RUYXNrT3BlcmF0aW9ucykge1xuICAgICAgICB0aGlzLl9wcm9jZXNzaW5nVGFza0NoYW5nZSA9IG5ldyBMb2FkaW5nRW1pdHRlcigpO1xuICAgICAgICB0aGlzLl9kaXNwbGF5ZWRUYXNrVGV4dCQgPSBuZXcgUmVwbGF5U3ViamVjdDxzdHJpbmc+KCk7XG5cbiAgICAgICAgdGhpcy5fY2hhbmdlZEZpZWxkc1NlcnZpY2UuY2hhbmdlZEZpZWxkcyQuc3Vic2NyaWJlKChjaGFuZ2VkRmllbGRzTWFwOiBDaGFuZ2VkRmllbGRzTWFwKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJlZENhc2VJZHM6IEFycmF5PHN0cmluZz4gPSBPYmplY3Qua2V5cyhjaGFuZ2VkRmllbGRzTWFwKS5maWx0ZXIoXG4gICAgICAgICAgICAgICAgY2FzZUlkID0+IE9iamVjdC5rZXlzKHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS5yZWZlcmVuY2VkVGFza0FuZENhc2VJZHMpLmluY2x1ZGVzKGNhc2VJZClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBjaGFuZ2VkRmllbGRzOiBBcnJheTxDaGFuZ2VkRmllbGRzPiA9IFtdO1xuICAgICAgICAgICAgZmlsdGVyZWRDYXNlSWRzLmZvckVhY2goY2FzZUlkID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXNrSWRzOiBBcnJheTxzdHJpbmc+ID0gdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnJlZmVyZW5jZWRUYXNrQW5kQ2FzZUlkc1tjYXNlSWRdO1xuICAgICAgICAgICAgICAgIGNoYW5nZWRGaWVsZHMucHVzaCguLi50aGlzLl9jaGFuZ2VkRmllbGRzU2VydmljZS5wYXJzZUNoYW5nZWRGaWVsZHNCeUNhc2VBbmRUYXNrSWRzKGNhc2VJZCwgdGFza0lkcywgY2hhbmdlZEZpZWxkc01hcCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjaGFuZ2VkRmllbGRzLmZpbHRlcihmaWVsZHMgPT4gZmllbGRzICE9PSB1bmRlZmluZWQpLmZvckVhY2goZmllbGRzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudXBkYXRlRnJvbUNoYW5nZWRGaWVsZHMoZmllbGRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgX3Rhc2tEYXRhU2VydmljZS51cGRhdGVTdWNjZXNzJC5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl90cmVlQ2FzZVNlcnZpY2UucmVsb2FkQ2FzZSQubmV4dCgpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzb2x2ZVRhc2tCbG9ja1N0YXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIF90cmVlQ2FzZVNlcnZpY2UubG9hZFRhc2skLmFzT2JzZXJ2YWJsZSgpLnBpcGUoZmlsdGVyKHNlbGVjdGVkQ2FzZSA9PiB0aGlzLnRhc2tDaGFuZ2VkKHNlbGVjdGVkQ2FzZSkpKS5zdWJzY3JpYmUoc2VsZWN0ZWRDYXNlID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2FuY2VsQW5kTG9hZEZlYXR1cmVkVGFzayhzZWxlY3RlZENhc2UpO1xuICAgICAgICB9KTtcblxuICAgICAgICBfdGFza09wZXJhdGlvbnMucmVsb2FkJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVUYXNrU3RhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuX3RyZWVDYXNlU2VydmljZS5yZWxvYWRDYXNlJC5uZXh0KCk7XG4gICAgICAgIH0pO1xuICAgICAgICBfdGFza09wZXJhdGlvbnMub3BlbiQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS5ibG9ja0ZpZWxkcyhmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBfdGFza09wZXJhdGlvbnMuY2xvc2UkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuYmxvY2tGaWVsZHModHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgdGFza0NvbnRlbnRUZXh0JCgpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGlzcGxheWVkVGFza1RleHQkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgcHJvY2Vzc2luZ1Rhc2tDaGFuZ2UoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wcm9jZXNzaW5nVGFza0NoYW5nZS5pc0FjdGl2ZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGlzcGxheUVtcHR5VGFza0NvbnRlbnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS4kc2hvdWxkQ3JlYXRlLm5leHQoW10pO1xuICAgICAgICB0aGlzLl9kaXNwbGF5ZWRUYXNrVGV4dCQubmV4dCgnY2FzZVRyZWUubm9UYXNrU2VsZWN0ZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYW5jZWxzIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQge0BsaW5rIFRhc2t9IGlmIGFueS4gQW5kIHRoZW4gbG9hZHMgYW5kIGFzc2lnbnMgdGhlIG5ldyBUYXNrLlxuICAgICAqIEBwYXJhbSBzZWxlY3RlZENhc2UgdGhlIENhc2Ugd2hvJ3MgdGFzayBzaG91bGQgYmUgbm93IGRpc3BsYXllZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5jZWxBbmRMb2FkRmVhdHVyZWRUYXNrKHNlbGVjdGVkQ2FzZTogQ2FzZSB8IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLl9wcm9jZXNzaW5nVGFza0NoYW5nZS5vbigpO1xuICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuYmxvY2tGaWVsZHModHJ1ZSk7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZENhbmNlbFRhc2spIHtcbiAgICAgICAgICAgIHRoaXMuX2NhbmNlbC5jYW5jZWwodGhpcy5fY2FsbGNoYWluLmNyZWF0ZShzdWNjZXNzID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2dnZXIuZGVidWcoJ09sZCB0cmVlIHRhc2sgc3VjY2Vzc2Z1bGx5IGNhbmNlbGVkJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9nZ2VyLndhcm4oJ09sZCB0cmVlIHRhc2sgY291bGQgbm90IGJlIGNhbmNlbGVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubG9hZEZlYXR1cmVkVGFzayhzZWxlY3RlZENhc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIGN1cnJlbnRseSBkaXNwbGF5ZWQge0BsaW5rIFRhc2t9IGJhc2VkIG9uIHRoZSBzZWxlY3RlZCB7QGxpbmsgQ2FzZX0gZnJvbSB0aGUgVHJlZS5cbiAgICAgKiBAcGFyYW0gc2VsZWN0ZWRDYXNlIHRoZSBDYXNlIHdobydzIHRhc2sgc2hvdWxkIGJlIG5vdyBkaXNwbGF5ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgbG9hZEZlYXR1cmVkVGFzayhzZWxlY3RlZENhc2U6IENhc2UgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2UgPSBzZWxlY3RlZENhc2U7XG5cbiAgICAgICAgY29uc3QgcmVxdWVzdEJvZHkgPSB0aGlzLmdldFRhc2tGaWx0ZXIoKTtcbiAgICAgICAgaWYgKHJlcXVlc3RCb2R5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJDdXJyZW50VGFzaygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdGFza1Jlc291cmNlU2VydmljZS5nZXRUYXNrcyhyZXF1ZXN0Qm9keSkuc3Vic2NyaWJlKHBhZ2UgPT4ge1xuICAgICAgICAgICAgaWYgKGhhc0NvbnRlbnQocGFnZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YW5kYXJkVGFza1RleHQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN3aXRjaFRvVGFzayhwYWdlLmNvbnRlbnRbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFyQ3VycmVudFRhc2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIGN1cnJlbnRseSBkaXNwbGF5ZWQgdGFzayBkaWZmZXJzIGZyb20gdGhlIG5ldyBvbmVcbiAgICAgKiBAcGFyYW0gbmV3Q2FzZSBbQ2FzZV17QGxpbmsgQ2FzZX0gb2JqZWN0IHRoYXQgaG9sZHMgdGhlIG5ld2x5IHNlbGVjdGVkIHtAbGluayBUYXNrfVxuICAgICAqIEByZXR1cm5zIGB0cnVlYCBpZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIENhc2UgaGFzIGEgZGlmZmVyZW50IElEIGZyb20gdGhlIG5ld2x5IHNlbGVjdGVkIENhc2UuXG4gICAgICogSWYgdGhlIElEcyBhcmUgdGhlIHNhbWUgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHRyYW5zaXRpb24gSURzIGFyZSBkaWZmZXJlbnQuXG4gICAgICogUmV0dXJucyBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHRhc2tDaGFuZ2VkKG5ld0Nhc2U6IENhc2UgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgY3VycmVudENhc2VJZCA9IHRoaXMuX3NlbGVjdGVkQ2FzZVNlcnZpY2Uuc2VsZWN0ZWRDYXNlID8gdGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2Uuc3RyaW5nSWQgOiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IG5ld0Nhc2VJZCA9IG5ld0Nhc2UgPyBuZXdDYXNlLnN0cmluZ0lkIDogdW5kZWZpbmVkO1xuICAgICAgICBpZiAoY3VycmVudENhc2VJZCAhPT0gbmV3Q2FzZUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnRUcmFuc2l0aW9uSWQgPSB0aGlzLmdldFRyYW5zaXRpb25JZCh0aGlzLl9zZWxlY3RlZENhc2VTZXJ2aWNlLnNlbGVjdGVkQ2FzZSk7XG4gICAgICAgIGNvbnN0IG5ld1RyYW5zaXRpb25JZCA9IHRoaXMuZ2V0VHJhbnNpdGlvbklkKG5ld0Nhc2UpO1xuICAgICAgICByZXR1cm4gY3VycmVudFRyYW5zaXRpb25JZCAhPT0gbmV3VHJhbnNpdGlvbklkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIGEgVGFzayBvYmplY3QgaXMgY3VycmVudGx5IHNlbGVjdGVkIGFuZCBpZiBpdCBjYW4gYmUgY2FuY2VsbGVkIGJ5IHRoZSB1c2VyXG4gICAgICovXG4gICAgcHJpdmF0ZSBnZXQgc2hvdWxkQ2FuY2VsVGFzaygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS50YXNrICYmIHRoaXMuX3Blcm1pc3Npb25TZXJ2aWNlLmNhbkNhbmNlbCh0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHtAbGluayBGaWx0ZXJ9IG9iamVjdCB0aGF0IGZpbmRzIHRoZSBzcGVjaWZpZWQgVGFzayBmb3IgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBDYXNlIGluIGEgVHJlZSBDYXNlIFZpZXdcbiAgICAgKiBAcmV0dXJucyBhIHJlcXVlc3QgYm9keSB0aGF0IGZpbmRzIHRhc2tzIG9mIHRoZSBnaXZlbiBjYXNlIHdpdGggdGFzayBpZCB0aGF0IGNvcnJlc3BvbmRzIHRvIHRoZSB2YWx1ZSBpbiB0aGUgYHRyZWVUYXNrVHJhbnNpdGlvbklkYFxuICAgICAqIGltbWVkaWF0ZSBkYXRhIGZpZWxkLiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSByZXF1ZXN0IGJvZHkgY2Fubm90IGJlIGNyZWF0ZWQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGdldFRhc2tGaWx0ZXIoKTogRmlsdGVyIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgY29uc3QgdHJhbnNpdGlvbklkID0gdGhpcy5nZXRUcmFuc2l0aW9uSWQodGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2UpO1xuICAgICAgICBpZiAodHJhbnNpdGlvbklkKSB7XG4gICAgICAgICAgICByZXR1cm4gU2ltcGxlRmlsdGVyLmZyb21UYXNrUXVlcnkoe1xuICAgICAgICAgICAgICAgIGNhc2U6IHtpZDogdGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2Uuc3RyaW5nSWR9LFxuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25JZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZXhhbWluZWRDYXNlIHRoZSB7QGxpbmsgQ2FzZX0gb2JqZWN0IGZyb20gd2hpY2ggd2Ugd2FudCB0byBleHRyYWN0IHRoZSB0cmFuc2l0aW9uIElEXG4gICAgICogQHJldHVybnMgdGhlIElEIG9mIHRoZSB0cmFuc2l0aW9uIHRoYXQgc2hvdWxkIGJlIGRpc3BsYXllZCBpbiB0aGUge0BsaW5rIEFic3RyYWN0VGFza0NvbnRlbnRDb21wb25lbnR9LFxuICAgICAqIG9yIGB1bmRlZmluZWRgIGlmIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgY2FzZSBkb2Vzbid0IGRlZmluZSBpdFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBnZXRUcmFuc2l0aW9uSWQoZXhhbWluZWRDYXNlOiBDYXNlKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKGV4YW1pbmVkQ2FzZSAmJiBleGFtaW5lZENhc2UuaW1tZWRpYXRlRGF0YSkge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNpdGlvbklkID0gZ2V0SW1tZWRpYXRlRGF0YShleGFtaW5lZENhc2UsIFRyZWVQZXRyaWZsb3dJZGVudGlmaWVycy5GRUFUVVJFRF9UUkFOU0lUSU9OKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2l0aW9uSWQgPyB0cmFuc2l0aW9uSWQudmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQge0BsaW5rIFRhc2t9LlxuICAgICAqIEBwYXJhbSB0YXNrIHRoZSBUYXNrIHRoYXQgc2hvdWxkIG5vdyBiZSBzZWxlY3RlZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzd2l0Y2hUb1Rhc2sodGFzazogVGFzayk6IHZvaWQge1xuICAgICAgICBpZiAodGFzay5jYXNlSWQgIT09IHRoaXMuX3NlbGVjdGVkQ2FzZVNlcnZpY2Uuc2VsZWN0ZWRDYXNlLnN0cmluZ0lkKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2dnZXIuZGVidWcoJ1RyZWUgZmVhdHVyZWQgdGFzayBoYXMgYmVlbiBsb2FkZWQsIGJ1dCB0aGUgc2VsZWN0ZWQgY2FzZSBoYXMgY2hhbmdlZCBzaW5jZS4gRGlzY2FyZGluZy4uLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGFzay5hc3NpZ25Qb2xpY3kgPSBBc3NpZ25Qb2xpY3kuYXV0bztcbiAgICAgICAgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnRhc2sgPSB0YXNrO1xuICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuYmxvY2tGaWVsZHModHJ1ZSk7XG4gICAgICAgIHRoaXMuX2Fzc2lnblBvbGljeS5wZXJmb3JtQXNzaWduUG9saWN5KHRydWUsIHRoaXMuX2NhbGxjaGFpbi5jcmVhdGUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcHJvY2Vzc2luZ1Rhc2tDaGFuZ2Uub2ZmKCk7XG4gICAgICAgIH0pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOb3RpZmllcyBhbGwgY29ubmVjdGVkIFNlcnZpY2VzIHRoYXQgbm8gVGFzayBpcyBjdXJyZW50bHkgc2VsZWN0ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY2xlYXJDdXJyZW50VGFzaygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnRhc2sgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuZGlzcGxheUVtcHR5VGFza0NvbnRlbnQoKTtcbiAgICAgICAgdGhpcy5fcHJvY2Vzc2luZ1Rhc2tDaGFuZ2Uub2ZmKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgc3RhdGUgb2YgdGhlIGN1cnJlbnQgVGFzayBmcm9tIGJhY2tlbmRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgdXBkYXRlVGFza1N0YXRlKCk6IHZvaWQge1xuICAgICAgICBjb25zdCB1bmlxdWVUYXNrSWRlbnRpZmllciA9IHRoaXMuZ2V0VW5pcXVlVGFza0lkZW50aWZpZXIoKTtcbiAgICAgICAgaWYgKHVuaXF1ZVRhc2tJZGVudGlmaWVyID09PSB0aGlzLl9yZWxvYWRlZFRhc2tVbmlxdWVJZGVudGlmaWVyKSB7XG4gICAgICAgICAgICB0aGlzLl9sb2dnZXIuZGVidWcoJ1RoZSBjdXJyZW50bHkgc2VsZWN0ZWQgdGFzayBpcyBhbHJlYWR5IGJlaW5nIHJlbG9hZGVkLiBJZ25vcmluZyByZWxvYWQgcmVxdWVzdC4nKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9yZWxvYWRlZFRhc2tVbmlxdWVJZGVudGlmaWVyID0gdW5pcXVlVGFza0lkZW50aWZpZXI7XG4gICAgICAgIHRoaXMuX3Rhc2tSZXNvdXJjZVNlcnZpY2UuZ2V0VGFza3ModGhpcy5nZXRUYXNrRmlsdGVyKCkpLnN1YnNjcmliZShwYWdlID0+IHtcbiAgICAgICAgICAgIGlmIChoYXNDb250ZW50KHBhZ2UpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS50YXNrICYmIHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS50YXNrLnN0cmluZ0lkID09PSBwYWdlLmNvbnRlbnRbMF0uc3RyaW5nSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkZWRUYXNrVW5pcXVlSWRlbnRpZmllciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzaywgcGFnZS5jb250ZW50WzBdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvbHZlVGFza0Jsb2NrU3RhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSWYgdGhlIGN1cnJlbnQge0BsaW5rIFRhc2t9IGlzIGFzc2lnbmVkIHRvIHRoZSBjdXJyZW50IHVzZXIgaXQgaXMgdW5ibG9ja2VkLiBPdGhlcndpc2UgaXQgaXMgYmxvY2tlZC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVzb2x2ZVRhc2tCbG9ja1N0YXRlKCk6IHZvaWQge1xuICAgICAgICBjb25zdCB0YXNrU2hvdWxkQmVCbG9ja2VkID0gIXRoaXMuX3Rhc2tDb250ZW50U2VydmljZS50YXNrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzay51c2VySWQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgIXRoaXMuX3VzZXJDb21wYXJhdG9yLmNvbXBhcmVVc2Vycyh0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzay51c2VySWQpO1xuICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuYmxvY2tGaWVsZHModGFza1Nob3VsZEJlQmxvY2tlZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbm9EYXRhIHRleHQgaW4gdGhlIHRhc2sgY29udGVudCB0byBpdCdzIGRlZmF1bHQgdmFsdWVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc2V0U3RhbmRhcmRUYXNrVGV4dCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fZGlzcGxheWVkVGFza1RleHQkLm5leHQodW5kZWZpbmVkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRlbXB0cyB0byBjYW5jZWwgdGhlIGN1cnJlbnRseSBvcGVuZWQgVGFzayBpZiB0aGUgVGFzayBpcyBpbiBzdWNoIHN0YXRlIHRoYXQgYWxsb3dzIGNhbmNlbGxhdGlvbi5cbiAgICAgKi9cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc2hvdWxkQ2FuY2VsVGFzaykge1xuICAgICAgICAgICAgdGhpcy5fY2FuY2VsLmNhbmNlbCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl90YXNrT3BlcmF0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5fdGFza09wZXJhdGlvbnMuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgYSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCB0YXNrLCB0aGF0IGNvbnNpc3RzIG9mIGl0J3MgY2FzZSdzIGlkIGFuZCBpdCdzIHRyYW5zaXRpb24gaWQuXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGB1bmRlZmluZWRgLCBpZiBubyB0YXNrIGlzIGN1cnJlbnRseSBzZWxlY3RlZC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0VW5pcXVlVGFza0lkZW50aWZpZXIoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zZWxlY3RlZENhc2VTZXJ2aWNlLnNlbGVjdGVkQ2FzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYCR7dGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2Uuc3RyaW5nSWR9IyR7dGhpcy5nZXRUcmFuc2l0aW9uSWQodGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2UpfWA7XG4gICAgfVxufVxuIl19