UNPKG

@netgrif/components-core

Version:

Netgrif Application engine frontend core Angular library

287 lines 42.8 kB
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.assignee === undefined || !this._userComparator.compareUsers(this._taskContentService.task.assignee?.id); 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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QUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVc7UUFDUCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ3pCO1FBQ0QsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ3RCLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDbEM7SUFDTCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNPLHVCQUF1QjtRQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFlBQVksRUFBRTtZQUN6QyxPQUFPLFNBQVMsQ0FBQztTQUNwQjtRQUNELE9BQU8sR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsWUFBWSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO0lBQ2hJLENBQUM7d0dBclFRLHNCQUFzQiwyY0F3QlgsbUJBQW1COzRHQXhCOUIsc0JBQXNCOzs0RkFBdEIsc0JBQXNCO2tCQURsQyxVQUFVOzswQkF5Qk0sTUFBTTsyQkFBQyxtQkFBbUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdCwgSW5qZWN0YWJsZSwgT25EZXN0cm95fSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7VGFza0NvbnRlbnRTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi90YXNrLWNvbnRlbnQvc2VydmljZXMvdGFzay1jb250ZW50LnNlcnZpY2UnO1xuaW1wb3J0IHtUYXNrRGF0YVNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3Rhc2svc2VydmljZXMvdGFzay1kYXRhLnNlcnZpY2UnO1xuaW1wb3J0IHtDYW5jZWxUYXNrU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdGFzay9zZXJ2aWNlcy9jYW5jZWwtdGFzay5zZXJ2aWNlJztcbmltcG9ydCB7VGFza0V2ZW50U2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdGFzay1jb250ZW50L3NlcnZpY2VzL3Rhc2stZXZlbnQuc2VydmljZSc7XG5pbXBvcnQge1Rhc2tSZXNvdXJjZVNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3Jlc291cmNlcy9lbmdpbmUtZW5kcG9pbnQvdGFzay1yZXNvdXJjZS5zZXJ2aWNlJztcbmltcG9ydCB7VHJlZUNhc2VWaWV3U2VydmljZX0gZnJvbSAnLi4vdHJlZS1jYXNlLXZpZXcuc2VydmljZSc7XG5pbXBvcnQge0Nhc2V9IGZyb20gJy4uLy4uLy4uL3Jlc291cmNlcy9pbnRlcmZhY2UvY2FzZSc7XG5pbXBvcnQge1Rhc2t9IGZyb20gJy4uLy4uLy4uL3Jlc291cmNlcy9pbnRlcmZhY2UvdGFzayc7XG5pbXBvcnQge0Fzc2lnblBvbGljeVNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3Rhc2svc2VydmljZXMvYXNzaWduLXBvbGljeS5zZXJ2aWNlJztcbmltcG9ydCB7QXNzaWduUG9saWN5fSBmcm9tICcuLi8uLi8uLi90YXNrLWNvbnRlbnQvbW9kZWwvcG9saWN5JztcbmltcG9ydCB7TkFFX1RBU0tfT1BFUkFUSU9OU30gZnJvbSAnLi4vLi4vLi4vdGFzay9tb2RlbHMvdGFzay1vcGVyYXRpb25zLWluamVjdGlvbi10b2tlbic7XG5pbXBvcnQge1N1YmplY3RUYXNrT3BlcmF0aW9uc30gZnJvbSAnLi4vLi4vLi4vdGFzay9tb2RlbHMvc3ViamVjdC10YXNrLW9wZXJhdGlvbnMnO1xuaW1wb3J0IHtVc2VyQ29tcGFyYXRvclNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3VzZXIvc2VydmljZXMvdXNlci1jb21wYXJhdG9yLnNlcnZpY2UnO1xuaW1wb3J0IHtUcmVlUGV0cmlmbG93SWRlbnRpZmllcnN9IGZyb20gJy4uL21vZGVsL3RyZWUtcGV0cmlmbG93LWlkZW50aWZpZXJzJztcbmltcG9ydCB7Q2FsbENoYWluU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vdXRpbGl0eS9jYWxsLWNoYWluL2NhbGwtY2hhaW4uc2VydmljZSc7XG5pbXBvcnQge0xvYWRpbmdFbWl0dGVyfSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L2xvYWRpbmctZW1pdHRlcic7XG5pbXBvcnQge09ic2VydmFibGUsIFJlcGxheVN1YmplY3QsIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtoYXNDb250ZW50fSBmcm9tICcuLi8uLi8uLi91dGlsaXR5L3BhZ2luYXRpb24vcGFnZS1oYXMtY29udGVudCc7XG5pbXBvcnQge2dldEltbWVkaWF0ZURhdGF9IGZyb20gJy4uLy4uLy4uL3V0aWxpdHkvZ2V0LWltbWVkaWF0ZS1kYXRhJztcbmltcG9ydCB7ZmlsdGVyfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge0xvZ2dlclNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL2xvZ2dlci9zZXJ2aWNlcy9sb2dnZXIuc2VydmljZSc7XG5pbXBvcnQge1NlbGVjdGVkQ2FzZVNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL3Rhc2svc2VydmljZXMvc2VsZWN0ZWQtY2FzZS5zZXJ2aWNlJztcbmltcG9ydCB7RmlsdGVyfSBmcm9tICcuLi8uLi8uLi9maWx0ZXIvbW9kZWxzL2ZpbHRlcic7XG5pbXBvcnQge1NpbXBsZUZpbHRlcn0gZnJvbSAnLi4vLi4vLi4vZmlsdGVyL21vZGVscy9zaW1wbGUtZmlsdGVyJztcbmltcG9ydCB7UGVybWlzc2lvblNlcnZpY2V9IGZyb20gJy4uLy4uLy4uL2F1dGhvcml6YXRpb24vcGVybWlzc2lvbi9wZXJtaXNzaW9uLnNlcnZpY2UnO1xuaW1wb3J0IHtDaGFuZ2VkRmllbGRzU2VydmljZX0gZnJvbSAnLi4vLi4vLi4vY2hhbmdlZC1maWVsZHMvc2VydmljZXMvY2hhbmdlZC1maWVsZHMuc2VydmljZSc7XG5pbXBvcnQge0NoYW5nZWRGaWVsZHN9IGZyb20gJy4uLy4uLy4uL2RhdGEtZmllbGRzL21vZGVscy9jaGFuZ2VkLWZpZWxkcyc7XG5pbXBvcnQge0NoYW5nZWRGaWVsZHNNYXB9IGZyb20gJy4uLy4uLy4uL2V2ZW50L3NlcnZpY2VzL2ludGVyZmFjZXMvY2hhbmdlZC1maWVsZHMtbWFwJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFRyZWVUYXNrQ29udGVudFNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHJpdmF0ZSBfcHJvY2Vzc2luZ1Rhc2tDaGFuZ2U6IExvYWRpbmdFbWl0dGVyO1xuICAgIHByaXZhdGUgX2Rpc3BsYXllZFRhc2tUZXh0JDogUmVwbGF5U3ViamVjdDxzdHJpbmc+O1xuICAgIC8qKlxuICAgICAqIGEgdW5pcXVlIGlkZW50aWZpZXIgY29uc2lzdGluZyBvZiBjYXNlSWQgYW5kIHRyYW5zaXRpb24gSURcbiAgICAgKlxuICAgICAqIElzIHNldCBpZiBhIHJlbG9hZCBvZiB0aGUgZ2l2ZW4gdGFzayBpcyBjdXJyZW50bHkgdGFraW5nIHBsYWNlLCBgdW5kZWZpbmVkYCBvdGhlcndpc2UuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfcmVsb2FkZWRUYXNrVW5pcXVlSWRlbnRpZmllcjogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IocHJvdGVjdGVkIF90cmVlQ2FzZVNlcnZpY2U6IFRyZWVDYXNlVmlld1NlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF90YXNrRGF0YVNlcnZpY2U6IFRhc2tEYXRhU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX3Rhc2tDb250ZW50U2VydmljZTogVGFza0NvbnRlbnRTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfdGFza1Jlc291cmNlU2VydmljZTogVGFza1Jlc291cmNlU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX3Rhc2tFdmVudFNlcnZpY2U6IFRhc2tFdmVudFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9hc3NpZ25Qb2xpY3k6IEFzc2lnblBvbGljeVNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9jYW5jZWw6IENhbmNlbFRhc2tTZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfdXNlckNvbXBhcmF0b3I6IFVzZXJDb21wYXJhdG9yU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX2NhbGxjaGFpbjogQ2FsbENoYWluU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX2xvZ2dlcjogTG9nZ2VyU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX3NlbGVjdGVkQ2FzZVNlcnZpY2U6IFNlbGVjdGVkQ2FzZVNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9jaGFuZ2VkRmllbGRzU2VydmljZTogQ2hhbmdlZEZpZWxkc1NlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9wZXJtaXNzaW9uU2VydmljZTogUGVybWlzc2lvblNlcnZpY2UsXG4gICAgICAgICAgICAgICAgQEluamVjdChOQUVfVEFTS19PUEVSQVRJT05TKSBwcm90ZWN0ZWQgX3Rhc2tPcGVyYXRpb25zOiBTdWJqZWN0VGFza09wZXJhdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fcHJvY2Vzc2luZ1Rhc2tDaGFuZ2UgPSBuZXcgTG9hZGluZ0VtaXR0ZXIoKTtcbiAgICAgICAgdGhpcy5fZGlzcGxheWVkVGFza1RleHQkID0gbmV3IFJlcGxheVN1YmplY3Q8c3RyaW5nPigpO1xuXG4gICAgICAgIHRoaXMuX2NoYW5nZWRGaWVsZHNTZXJ2aWNlLmNoYW5nZWRGaWVsZHMkLnN1YnNjcmliZSgoY2hhbmdlZEZpZWxkc01hcDogQ2hhbmdlZEZpZWxkc01hcCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZmlsdGVyZWRDYXNlSWRzOiBBcnJheTxzdHJpbmc+ID0gT2JqZWN0LmtleXMoY2hhbmdlZEZpZWxkc01hcCkuZmlsdGVyKFxuICAgICAgICAgICAgICAgIGNhc2VJZCA9PiBPYmplY3Qua2V5cyh0aGlzLl90YXNrQ29udGVudFNlcnZpY2UucmVmZXJlbmNlZFRhc2tBbmRDYXNlSWRzKS5pbmNsdWRlcyhjYXNlSWQpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgY2hhbmdlZEZpZWxkczogQXJyYXk8Q2hhbmdlZEZpZWxkcz4gPSBbXTtcbiAgICAgICAgICAgIGZpbHRlcmVkQ2FzZUlkcy5mb3JFYWNoKGNhc2VJZCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGFza0lkczogQXJyYXk8c3RyaW5nPiA9IHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS5yZWZlcmVuY2VkVGFza0FuZENhc2VJZHNbY2FzZUlkXTtcbiAgICAgICAgICAgICAgICBjaGFuZ2VkRmllbGRzLnB1c2goLi4udGhpcy5fY2hhbmdlZEZpZWxkc1NlcnZpY2UucGFyc2VDaGFuZ2VkRmllbGRzQnlDYXNlQW5kVGFza0lkcyhjYXNlSWQsIHRhc2tJZHMsIGNoYW5nZWRGaWVsZHNNYXApKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY2hhbmdlZEZpZWxkcy5maWx0ZXIoZmllbGRzID0+IGZpZWxkcyAhPT0gdW5kZWZpbmVkKS5mb3JFYWNoKGZpZWxkcyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnVwZGF0ZUZyb21DaGFuZ2VkRmllbGRzKGZpZWxkcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIF90YXNrRGF0YVNlcnZpY2UudXBkYXRlU3VjY2VzcyQuc3Vic2NyaWJlKHJlc3VsdCA9PiB7XG4gICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdHJlZUNhc2VTZXJ2aWNlLnJlbG9hZENhc2UkLm5leHQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc29sdmVUYXNrQmxvY2tTdGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBfdHJlZUNhc2VTZXJ2aWNlLmxvYWRUYXNrJC5hc09ic2VydmFibGUoKS5waXBlKGZpbHRlcihzZWxlY3RlZENhc2UgPT4gdGhpcy50YXNrQ2hhbmdlZChzZWxlY3RlZENhc2UpKSkuc3Vic2NyaWJlKHNlbGVjdGVkQ2FzZSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNhbmNlbEFuZExvYWRGZWF0dXJlZFRhc2soc2VsZWN0ZWRDYXNlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgX3Rhc2tPcGVyYXRpb25zLnJlbG9hZCQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVGFza1N0YXRlKCk7XG4gICAgICAgICAgICB0aGlzLl90cmVlQ2FzZVNlcnZpY2UucmVsb2FkQ2FzZSQubmV4dCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgX3Rhc2tPcGVyYXRpb25zLm9wZW4kLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuYmxvY2tGaWVsZHMoZmFsc2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgX3Rhc2tPcGVyYXRpb25zLmNsb3NlJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLmJsb2NrRmllbGRzKHRydWUpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHRhc2tDb250ZW50VGV4dCQoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Rpc3BsYXllZFRhc2tUZXh0JC5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHByb2Nlc3NpbmdUYXNrQ2hhbmdlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcHJvY2Vzc2luZ1Rhc2tDaGFuZ2UuaXNBY3RpdmU7XG4gICAgfVxuXG4gICAgcHVibGljIGRpc3BsYXlFbXB0eVRhc2tDb250ZW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuJHNob3VsZENyZWF0ZS5uZXh0KFtdKTtcbiAgICAgICAgdGhpcy5fZGlzcGxheWVkVGFza1RleHQkLm5leHQoJ2Nhc2VUcmVlLm5vVGFza1NlbGVjdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FuY2VscyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHtAbGluayBUYXNrfSBpZiBhbnkuIEFuZCB0aGVuIGxvYWRzIGFuZCBhc3NpZ25zIHRoZSBuZXcgVGFzay5cbiAgICAgKiBAcGFyYW0gc2VsZWN0ZWRDYXNlIHRoZSBDYXNlIHdobydzIHRhc2sgc2hvdWxkIGJlIG5vdyBkaXNwbGF5ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY2FuY2VsQW5kTG9hZEZlYXR1cmVkVGFzayhzZWxlY3RlZENhc2U6IENhc2UgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fcHJvY2Vzc2luZ1Rhc2tDaGFuZ2Uub24oKTtcbiAgICAgICAgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLmJsb2NrRmllbGRzKHRydWUpO1xuICAgICAgICBpZiAodGhpcy5zaG91bGRDYW5jZWxUYXNrKSB7XG4gICAgICAgICAgICB0aGlzLl9jYW5jZWwuY2FuY2VsKHRoaXMuX2NhbGxjaGFpbi5jcmVhdGUoc3VjY2VzcyA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKCdPbGQgdHJlZSB0YXNrIHN1Y2Nlc3NmdWxseSBjYW5jZWxlZCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvZ2dlci53YXJuKCdPbGQgdHJlZSB0YXNrIGNvdWxkIG5vdCBiZSBjYW5jZWxlZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxvYWRGZWF0dXJlZFRhc2soc2VsZWN0ZWRDYXNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIHRoZSBjdXJyZW50bHkgZGlzcGxheWVkIHtAbGluayBUYXNrfSBiYXNlZCBvbiB0aGUgc2VsZWN0ZWQge0BsaW5rIENhc2V9IGZyb20gdGhlIFRyZWUuXG4gICAgICogQHBhcmFtIHNlbGVjdGVkQ2FzZSB0aGUgQ2FzZSB3aG8ncyB0YXNrIHNob3VsZCBiZSBub3cgZGlzcGxheWVkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGxvYWRGZWF0dXJlZFRhc2soc2VsZWN0ZWRDYXNlOiBDYXNlIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3NlbGVjdGVkQ2FzZVNlcnZpY2Uuc2VsZWN0ZWRDYXNlID0gc2VsZWN0ZWRDYXNlO1xuXG4gICAgICAgIGNvbnN0IHJlcXVlc3RCb2R5ID0gdGhpcy5nZXRUYXNrRmlsdGVyKCk7XG4gICAgICAgIGlmIChyZXF1ZXN0Qm9keSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyQ3VycmVudFRhc2soKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3Rhc2tSZXNvdXJjZVNlcnZpY2UuZ2V0VGFza3MocmVxdWVzdEJvZHkpLnN1YnNjcmliZShwYWdlID0+IHtcbiAgICAgICAgICAgIGlmIChoYXNDb250ZW50KHBhZ2UpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGFuZGFyZFRhc2tUZXh0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zd2l0Y2hUb1Rhc2socGFnZS5jb250ZW50WzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhckN1cnJlbnRUYXNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIHRoZSBjdXJyZW50bHkgZGlzcGxheWVkIHRhc2sgZGlmZmVycyBmcm9tIHRoZSBuZXcgb25lXG4gICAgICogQHBhcmFtIG5ld0Nhc2UgW0Nhc2Vde0BsaW5rIENhc2V9IG9iamVjdCB0aGF0IGhvbGRzIHRoZSBuZXdseSBzZWxlY3RlZCB7QGxpbmsgVGFza31cbiAgICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBDYXNlIGhhcyBhIGRpZmZlcmVudCBJRCBmcm9tIHRoZSBuZXdseSBzZWxlY3RlZCBDYXNlLlxuICAgICAqIElmIHRoZSBJRHMgYXJlIHRoZSBzYW1lIHJldHVybnMgYHRydWVgIGlmIHRoZSB0cmFuc2l0aW9uIElEcyBhcmUgZGlmZmVyZW50LlxuICAgICAqIFJldHVybnMgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICovXG4gICAgcHJpdmF0ZSB0YXNrQ2hhbmdlZChuZXdDYXNlOiBDYXNlIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRDYXNlSWQgPSB0aGlzLl9zZWxlY3RlZENhc2VTZXJ2aWNlLnNlbGVjdGVkQ2FzZSA/IHRoaXMuX3NlbGVjdGVkQ2FzZVNlcnZpY2Uuc2VsZWN0ZWRDYXNlLnN0cmluZ0lkIDogdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBuZXdDYXNlSWQgPSBuZXdDYXNlID8gbmV3Q2FzZS5zdHJpbmdJZCA6IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGN1cnJlbnRDYXNlSWQgIT09IG5ld0Nhc2VJZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjdXJyZW50VHJhbnNpdGlvbklkID0gdGhpcy5nZXRUcmFuc2l0aW9uSWQodGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2UpO1xuICAgICAgICBjb25zdCBuZXdUcmFuc2l0aW9uSWQgPSB0aGlzLmdldFRyYW5zaXRpb25JZChuZXdDYXNlKTtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRUcmFuc2l0aW9uSWQgIT09IG5ld1RyYW5zaXRpb25JZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3Mgd2hldGhlciBhIFRhc2sgb2JqZWN0IGlzIGN1cnJlbnRseSBzZWxlY3RlZCBhbmQgaWYgaXQgY2FuIGJlIGNhbmNlbGxlZCBieSB0aGUgdXNlclxuICAgICAqL1xuICAgIHByaXZhdGUgZ2V0IHNob3VsZENhbmNlbFRhc2soKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzayAmJiB0aGlzLl9wZXJtaXNzaW9uU2VydmljZS5jYW5DYW5jZWwodGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnRhc2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSB7QGxpbmsgRmlsdGVyfSBvYmplY3QgdGhhdCBmaW5kcyB0aGUgc3BlY2lmaWVkIFRhc2sgZm9yIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgQ2FzZSBpbiBhIFRyZWUgQ2FzZSBWaWV3XG4gICAgICogQHJldHVybnMgYSByZXF1ZXN0IGJvZHkgdGhhdCBmaW5kcyB0YXNrcyBvZiB0aGUgZ2l2ZW4gY2FzZSB3aXRoIHRhc2sgaWQgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgdmFsdWUgaW4gdGhlIGB0cmVlVGFza1RyYW5zaXRpb25JZGBcbiAgICAgKiBpbW1lZGlhdGUgZGF0YSBmaWVsZC4gUmV0dXJucyBgdW5kZWZpbmVkYCBpZiB0aGUgcmVxdWVzdCBib2R5IGNhbm5vdCBiZSBjcmVhdGVkLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBnZXRUYXNrRmlsdGVyKCk6IEZpbHRlciB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGNvbnN0IHRyYW5zaXRpb25JZCA9IHRoaXMuZ2V0VHJhbnNpdGlvbklkKHRoaXMuX3NlbGVjdGVkQ2FzZVNlcnZpY2Uuc2VsZWN0ZWRDYXNlKTtcbiAgICAgICAgaWYgKHRyYW5zaXRpb25JZCkge1xuICAgICAgICAgICAgcmV0dXJuIFNpbXBsZUZpbHRlci5mcm9tVGFza1F1ZXJ5KHtcbiAgICAgICAgICAgICAgICBjYXNlOiB7aWQ6IHRoaXMuX3NlbGVjdGVkQ2FzZVNlcnZpY2Uuc2VsZWN0ZWRDYXNlLnN0cmluZ0lkfSxcbiAgICAgICAgICAgICAgICB0cmFuc2l0aW9uSWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGV4YW1pbmVkQ2FzZSB0aGUge0BsaW5rIENhc2V9IG9iamVjdCBmcm9tIHdoaWNoIHdlIHdhbnQgdG8gZXh0cmFjdCB0aGUgdHJhbnNpdGlvbiBJRFxuICAgICAqIEByZXR1cm5zIHRoZSBJRCBvZiB0aGUgdHJhbnNpdGlvbiB0aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQgaW4gdGhlIHtAbGluayBBYnN0cmFjdFRhc2tDb250ZW50Q29tcG9uZW50fSxcbiAgICAgKiBvciBgdW5kZWZpbmVkYCBpZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGNhc2UgZG9lc24ndCBkZWZpbmUgaXRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0VHJhbnNpdGlvbklkKGV4YW1pbmVkQ2FzZTogQ2FzZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGlmIChleGFtaW5lZENhc2UgJiYgZXhhbWluZWRDYXNlLmltbWVkaWF0ZURhdGEpIHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zaXRpb25JZCA9IGdldEltbWVkaWF0ZURhdGEoZXhhbWluZWRDYXNlLCBUcmVlUGV0cmlmbG93SWRlbnRpZmllcnMuRkVBVFVSRURfVFJBTlNJVElPTik7XG4gICAgICAgICAgICByZXR1cm4gdHJhbnNpdGlvbklkID8gdHJhbnNpdGlvbklkLnZhbHVlIDogdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHtAbGluayBUYXNrfS5cbiAgICAgKiBAcGFyYW0gdGFzayB0aGUgVGFzayB0aGF0IHNob3VsZCBub3cgYmUgc2VsZWN0ZWRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc3dpdGNoVG9UYXNrKHRhc2s6IFRhc2spOiB2b2lkIHtcbiAgICAgICAgaWYgKHRhc2suY2FzZUlkICE9PSB0aGlzLl9zZWxlY3RlZENhc2VTZXJ2aWNlLnNlbGVjdGVkQ2FzZS5zdHJpbmdJZCkge1xuICAgICAgICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKCdUcmVlIGZlYXR1cmVkIHRhc2sgaGFzIGJlZW4gbG9hZGVkLCBidXQgdGhlIHNlbGVjdGVkIGNhc2UgaGFzIGNoYW5nZWQgc2luY2UuIERpc2NhcmRpbmcuLi4nKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhc2suYXNzaWduUG9saWN5ID0gQXNzaWduUG9saWN5LmF1dG87XG4gICAgICAgIHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS50YXNrID0gdGFzaztcbiAgICAgICAgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLmJsb2NrRmllbGRzKHRydWUpO1xuICAgICAgICB0aGlzLl9hc3NpZ25Qb2xpY3kucGVyZm9ybUFzc2lnblBvbGljeSh0cnVlLCB0aGlzLl9jYWxsY2hhaW4uY3JlYXRlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NpbmdUYXNrQ2hhbmdlLm9mZigpO1xuICAgICAgICB9KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTm90aWZpZXMgYWxsIGNvbm5lY3RlZCBTZXJ2aWNlcyB0aGF0IG5vIFRhc2sgaXMgY3VycmVudGx5IHNlbGVjdGVkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGNsZWFyQ3VycmVudFRhc2soKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3Rhc2tDb250ZW50U2VydmljZS50YXNrID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmRpc3BsYXlFbXB0eVRhc2tDb250ZW50KCk7XG4gICAgICAgIHRoaXMuX3Byb2Nlc3NpbmdUYXNrQ2hhbmdlLm9mZigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIHN0YXRlIG9mIHRoZSBjdXJyZW50IFRhc2sgZnJvbSBiYWNrZW5kXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZVRhc2tTdGF0ZSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdW5pcXVlVGFza0lkZW50aWZpZXIgPSB0aGlzLmdldFVuaXF1ZVRhc2tJZGVudGlmaWVyKCk7XG4gICAgICAgIGlmICh1bmlxdWVUYXNrSWRlbnRpZmllciA9PT0gdGhpcy5fcmVsb2FkZWRUYXNrVW5pcXVlSWRlbnRpZmllcikge1xuICAgICAgICAgICAgdGhpcy5fbG9nZ2VyLmRlYnVnKCdUaGUgY3VycmVudGx5IHNlbGVjdGVkIHRhc2sgaXMgYWxyZWFkeSBiZWluZyByZWxvYWRlZC4gSWdub3JpbmcgcmVsb2FkIHJlcXVlc3QuJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVsb2FkZWRUYXNrVW5pcXVlSWRlbnRpZmllciA9IHVuaXF1ZVRhc2tJZGVudGlmaWVyO1xuICAgICAgICB0aGlzLl90YXNrUmVzb3VyY2VTZXJ2aWNlLmdldFRhc2tzKHRoaXMuZ2V0VGFza0ZpbHRlcigpKS5zdWJzY3JpYmUocGFnZSA9PiB7XG4gICAgICAgICAgICBpZiAoaGFzQ29udGVudChwYWdlKSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzayAmJiB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzay5zdHJpbmdJZCA9PT0gcGFnZS5jb250ZW50WzBdLnN0cmluZ0lkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZGVkVGFza1VuaXF1ZUlkZW50aWZpZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnRhc2ssIHBhZ2UuY29udGVudFswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucmVzb2x2ZVRhc2tCbG9ja1N0YXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHRoZSBjdXJyZW50IHtAbGluayBUYXNrfSBpcyBhc3NpZ25lZCB0byB0aGUgY3VycmVudCB1c2VyIGl0IGlzIHVuYmxvY2tlZC4gT3RoZXJ3aXNlIGl0IGlzIGJsb2NrZWQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlc29sdmVUYXNrQmxvY2tTdGF0ZSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdGFza1Nob3VsZEJlQmxvY2tlZCA9ICF0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFza1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgdGhpcy5fdGFza0NvbnRlbnRTZXJ2aWNlLnRhc2suYXNzaWduZWUgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgIXRoaXMuX3VzZXJDb21wYXJhdG9yLmNvbXBhcmVVc2Vycyh0aGlzLl90YXNrQ29udGVudFNlcnZpY2UudGFzay5hc3NpZ25lZT8uaWQpO1xuICAgICAgICB0aGlzLl90YXNrQ29udGVudFNlcnZpY2UuYmxvY2tGaWVsZHModGFza1Nob3VsZEJlQmxvY2tlZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbm9EYXRhIHRleHQgaW4gdGhlIHRhc2sgY29udGVudCB0byBpdCdzIGRlZmF1bHQgdmFsdWVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc2V0U3RhbmRhcmRUYXNrVGV4dCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fZGlzcGxheWVkVGFza1RleHQkLm5leHQodW5kZWZpbmVkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRlbXB0cyB0byBjYW5jZWwgdGhlIGN1cnJlbnRseSBvcGVuZWQgVGFzayBpZiB0aGUgVGFzayBpcyBpbiBzdWNoIHN0YXRlIHRoYXQgYWxsb3dzIGNhbmNlbGxhdGlvbi5cbiAgICAgKi9cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc2hvdWxkQ2FuY2VsVGFzaykge1xuICAgICAgICAgICAgdGhpcy5fY2FuY2VsLmNhbmNlbCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl90YXNrT3BlcmF0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5fdGFza09wZXJhdGlvbnMuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgYSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCB0YXNrLCB0aGF0IGNvbnNpc3RzIG9mIGl0J3MgY2FzZSdzIGlkIGFuZCBpdCdzIHRyYW5zaXRpb24gaWQuXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGB1bmRlZmluZWRgLCBpZiBubyB0YXNrIGlzIGN1cnJlbnRseSBzZWxlY3RlZC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0VW5pcXVlVGFza0lkZW50aWZpZXIoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zZWxlY3RlZENhc2VTZXJ2aWNlLnNlbGVjdGVkQ2FzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYCR7dGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2Uuc3RyaW5nSWR9IyR7dGhpcy5nZXRUcmFuc2l0aW9uSWQodGhpcy5fc2VsZWN0ZWRDYXNlU2VydmljZS5zZWxlY3RlZENhc2UpfWA7XG4gICAgfVxufVxuIl19