UNPKG

@netgrif/components-core

Version:

Netgrif Application engine frontend core Angular library

282 lines 47 kB
import { Injectable } from '@angular/core'; import { BehaviorSubject, ReplaySubject, Subject } from 'rxjs'; import { FieldTypeResource } from '../model/field-type-resource'; import { DynamicEnumerationField } from '../../data-fields/enumeration-field/models/dynamic-enumeration-field'; import { TaskRefField } from "../../data-fields/task-ref-field/model/task-ref-field"; import * as i0 from "@angular/core"; import * as i1 from "./field-converter.service"; import * as i2 from "../../snack-bar/services/snack-bar.service"; import * as i3 from "@ngx-translate/core"; import * as i4 from "../../logger/services/logger.service"; /** * Acts as a communication interface between the Component that renders Task content and it's parent Component. * Also provides some general functionality that is needed when working with task content. * * Notable example of a parent Component is the {@link AbstractTaskPanelComponent}. * * Notable example of a task content renderer is the {@link AbstractTaskContentComponent}. */ export class TaskContentService { _fieldConverterService; _snackBarService; _translate; _logger; static FRONTEND_ACTIONS_KEY = '_frontend_actions'; static ACTION = 'action'; $shouldCreate; $shouldCreateCounter; _task; _taskDataReloadRequest$; _isExpanding$; _taskFieldsIndex = {}; _referencedTaskAndCaseIds = {}; constructor(_fieldConverterService, _snackBarService, _translate, _logger) { this._fieldConverterService = _fieldConverterService; this._snackBarService = _snackBarService; this._translate = _translate; this._logger = _logger; this.$shouldCreate = new ReplaySubject(1); this.$shouldCreateCounter = new BehaviorSubject(0); this._isExpanding$ = new BehaviorSubject(false); this._task = undefined; this._taskDataReloadRequest$ = new Subject(); } ngOnDestroy() { if (!this.$shouldCreate.closed) { this.$shouldCreate.complete(); } this._taskDataReloadRequest$.complete(); this._isExpanding$.complete(); } /** * Stream that emits every time a data reload is requested. */ get taskDataReloadRequest$() { return this._taskDataReloadRequest$.asObservable(); } get taskFieldsIndex() { return this._taskFieldsIndex; } set taskFieldsIndex(value) { this._taskFieldsIndex = value; } get referencedTaskAndCaseIds() { return this._referencedTaskAndCaseIds; } set referencedTaskAndCaseIds(value) { this._referencedTaskAndCaseIds = value; } /** * Whether the panel that the task content is contained in is currently expanding. * * If the task content is not contained in a panel, `isExpanding` will be always `false`. */ get isExpanding() { return this._isExpanding$.value; } /** * Changes the state of the task content to `expanding`. */ expansionStarted() { this._isExpanding$.next(true); } /** * Changes the state of the task content to `not expanding`. */ expansionFinished() { this._isExpanding$.next(false); } /** * Checks the validity of all data fields in the managed {@link Task}. * * If some of the fields are invalid touches them so their validation errors will appear (if set). * A snackbar will also be displayed to the user, informing them of the fact that the fields are invalid. * @returns whether the task is valid or not */ validateTaskData(taskId) { if (!this._task || !this._task.dataGroups) { return false; } const valid = !this._task.dataGroups.filter(group => !!group.parentTaskId && !!taskId ? group.parentTaskId === taskId : true).some(group => group.fields.some(field => !field.valid && !field.disabled)); const validDisabled = !this._task.dataGroups.filter(group => !!group.parentTaskId && !!taskId ? group.parentTaskId === taskId : true).some(group => group.fields.some(field => !field.validRequired && field.disabled)); if (!valid) { this._snackBarService.openErrorSnackBar(this._translate.instant('tasks.snackbar.invalidData')); this._task.dataGroups.forEach(group => group.fields.forEach(field => field.touch = true)); } if (!validDisabled) { this._snackBarService.openErrorSnackBar(this._translate.instant('tasks.snackbar.missingRequired')); } return valid && validDisabled; } /** * Finds invalid data of task * * @returns array of invalid datafields */ getInvalidTaskData() { const invalidFields = []; this._task.dataGroups.forEach(group => invalidFields.push(...group.fields.filter(field => (!field.valid && !field.disabled) || (!field.validRequired && !field.disabled)))); return invalidFields; } validateDynamicEnumField() { if (!this._task || !this._task.dataGroups) { return false; } const exists = this._task.dataGroups.some(group => group.fields.some(field => field instanceof DynamicEnumerationField)); if (!exists) { return true; } let valid = true; for (const group of this._task.dataGroups) { for (const field of group.fields) { if (field instanceof DynamicEnumerationField) { if (field.choices !== undefined && field.choices.length !== 0 && field.value !== '' && field.value !== undefined) { if (!field.choices.some(choice => choice.key === field.value)) { field.value = ''; if (field.behavior.required) { valid = false; } } } } } } if (!valid) { this._snackBarService.openErrorSnackBar(this._translate.instant('tasks.snackbar.missingRequired')); } return valid; } /** * Changes the blocking state of all fields in the managed Task. * @param blockingState whether the field should be blocked or not */ blockFields(blockingState) { if (this._task && this._task.dataGroups) { this._task.dataGroups.forEach(group => { group.fields.forEach(field => { field.block = blockingState; }); }); } } /** * Clears the assignee, start date and finish date from the managed Task. */ updateStateData(eventOutcome) { if (this._task) { this._task.assignee = eventOutcome.task.assignee; this._task.startDate = eventOutcome.task.startDate; this._task.finishDate = eventOutcome.task.finishDate; } } /** * Updates the properties of fields in the managed task based on a delta of changes from previous state. * @param chFields object containing the delta of the changes from the previous state */ updateFromChangedFields(chFields) { if (!this._task || !this._task.dataGroups) { return; } const frontendActions = chFields.taskId === this.task.stringId && chFields[TaskContentService.FRONTEND_ACTIONS_KEY]; Object.keys(chFields).forEach(changedField => { if (chFields.taskId === this._task.stringId && this.isFieldInTask(chFields.taskId, changedField)) { this.updateField(chFields, this.taskFieldsIndex[chFields.taskId].fields[changedField], frontendActions); } else if (!!this.getReferencedTaskId(changedField, chFields)) { this.updateField(chFields, this.taskFieldsIndex[this.getReferencedTaskId(changedField, chFields)].fields[changedField], frontendActions, true); } }); this.$shouldCreate.next(this._task.dataGroups); } updateField(chFields, field, frontendActions, referenced = false) { if (this._fieldConverterService.resolveType(field) === FieldTypeResource.TASK_REF) { this._taskDataReloadRequest$.next(frontendActions ? frontendActions : undefined); return; } const updatedField = chFields[field.stringId]; Object.keys(updatedField).forEach(key => { switch (key) { case 'type': // type is just an information, not an update. A field cannot change its type return; // continue - the field does not need updating, since nothing changed case 'value': field.valueWithoutChange(this._fieldConverterService.formatValueFromBackend(field, updatedField[key])); break; case 'behavior': if (!referenced && updatedField.behavior[this._task.transitionId]) { field.behavior = updatedField.behavior[this._task.transitionId]; } else if (referenced) { const taskId = this.getReferencedTaskId(field.stringId, chFields); const taskRef = this.findTaskRefId(taskId, this.taskFieldsIndex[this._task.stringId].fields); const transitionId = this.taskFieldsIndex[taskId].transitionId; if (!!transitionId && transitionId !== '' && updatedField.behavior[transitionId]) field.behavior = taskRef.behavior.editable ? updatedField.behavior[transitionId] : taskRef.behavior; } break; case 'choices': const newChoices = []; if (updatedField.choices instanceof Array) { updatedField.choices.forEach(it => { newChoices.push({ key: it, value: it }); }); } else { Object.keys(updatedField.choices).forEach(choiceKey => { newChoices.push({ key: choiceKey, value: updatedField.choices[choiceKey] }); }); } field.choices = newChoices; field.updateChoice(); break; case 'options': const newOptions = []; Object.keys(updatedField.options).forEach(optionKey => { newOptions.push({ key: optionKey, value: updatedField.options[optionKey] }); }); field.choices = newOptions; field.updateChoice(); break; case 'validations': field.replaceValidations(updatedField.validations.map(it => it)); break; default: field[key] = updatedField[key]; } field.update(); }); } isFieldInTask(taskId, changedField) { return !!taskId && !!this.taskFieldsIndex[taskId] && !!this.taskFieldsIndex[taskId].fields && !!this.taskFieldsIndex[taskId].fields[changedField]; } getReferencedTaskId(changedField, chFields) { return !!this.taskFieldsIndex ? (Object.keys(this.taskFieldsIndex).find(taskId => taskId !== this.task.stringId && taskId === chFields.taskId && Object.keys(this.taskFieldsIndex[taskId].fields)?.includes(changedField)) || Object.keys(this.taskFieldsIndex).find(taskId => taskId !== this.task.stringId && Object.keys(this.taskFieldsIndex[taskId].fields)?.includes(changedField))) : undefined; } findTaskRefId(taskId, fields) { let taskRefId = Object.values(fields).find(f => f instanceof TaskRefField && f.value?.includes(taskId)); if (!taskRefId) { const referencedTaskIds = Object.values(fields).filter(f => f instanceof TaskRefField).map(tr => tr.value); referencedTaskIds.forEach(id => { taskRefId = this.findTaskRefId(taskId, this.taskFieldsIndex[id].fields); if (!!taskRefId) { return taskRefId; } }); } return taskRefId; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TaskContentService, deps: [{ token: i1.FieldConverterService }, { token: i2.SnackBarService }, { token: i3.TranslateService }, { token: i4.LoggerService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TaskContentService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TaskContentService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.FieldConverterService }, { type: i2.SnackBarService }, { type: i3.TranslateService }, { type: i4.LoggerService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1jb250ZW50LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZXRncmlmLWNvbXBvbmVudHMtY29yZS9zcmMvbGliL3Rhc2stY29udGVudC9zZXJ2aWNlcy90YXNrLWNvbnRlbnQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBRXBELE9BQU8sRUFBQyxlQUFlLEVBQWMsYUFBYSxFQUFFLE9BQU8sRUFBUSxNQUFNLE1BQU0sQ0FBQztBQVNoRixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEVBQUMsdUJBQXVCLEVBQUMsTUFBTSxzRUFBc0UsQ0FBQztBQUs3RyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sdURBQXVELENBQUM7Ozs7OztBQUVuRjs7Ozs7OztHQU9HO0FBRUgsTUFBTSxPQUFnQixrQkFBa0I7SUFlSjtJQUNBO0lBQ0E7SUFDQTtJQWhCekIsTUFBTSxDQUFVLG9CQUFvQixHQUFHLG1CQUFtQixDQUFDO0lBQzNELE1BQU0sQ0FBVSxNQUFNLEdBQUcsUUFBUSxDQUFDO0lBRXpDLGFBQWEsQ0FBa0M7SUFDL0Msb0JBQW9CLENBQTBCO0lBQ3BDLEtBQUssQ0FBTztJQUNaLHVCQUF1QixDQUFrQjtJQUN6QyxhQUFhLENBQTJCO0lBQ3hDLGdCQUFnQixHQUV0QixFQUFFLENBQUM7SUFDRyx5QkFBeUIsR0FBd0MsRUFBRSxDQUFDO0lBRTlFLFlBQWdDLHNCQUE2QyxFQUM3QyxnQkFBaUMsRUFDakMsVUFBNEIsRUFDNUIsT0FBc0I7UUFIdEIsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF1QjtRQUM3QyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWlCO1FBQ2pDLGVBQVUsR0FBVixVQUFVLENBQWtCO1FBQzVCLFlBQU8sR0FBUCxPQUFPLENBQWU7UUFD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LE9BQU8sU0FBUyxDQUFDO2lCQUNwQjtZQUNMLENBQUMsQ0FBQyxDQUFDO1NBQ047UUFDRCxPQUFPLFNBQVMsQ0FBQTtJQUNwQixDQUFDO3dHQXZTaUIsa0JBQWtCOzRHQUFsQixrQkFBa0I7OzRGQUFsQixrQkFBa0I7a0JBRHZDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIE9uRGVzdHJveX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0RhdGFHcm91cH0gZnJvbSAnLi4vLi4vcmVzb3VyY2VzL2ludGVyZmFjZS9kYXRhLWdyb3Vwcyc7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3ViamVjdCwgdGltZXJ9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtUYXNrfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvaW50ZXJmYWNlL3Rhc2snO1xuaW1wb3J0IHtMb2dnZXJTZXJ2aWNlfSBmcm9tICcuLi8uLi9sb2dnZXIvc2VydmljZXMvbG9nZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHtTbmFja0JhclNlcnZpY2V9IGZyb20gJy4uLy4uL3NuYWNrLWJhci9zZXJ2aWNlcy9zbmFjay1iYXIuc2VydmljZSc7XG5pbXBvcnQge1RyYW5zbGF0ZVNlcnZpY2V9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHtFbnVtZXJhdGlvbkZpZWxkLCBFbnVtZXJhdGlvbkZpZWxkVmFsdWV9IGZyb20gJy4uLy4uL2RhdGEtZmllbGRzL2VudW1lcmF0aW9uLWZpZWxkL21vZGVscy9lbnVtZXJhdGlvbi1maWVsZCc7XG5pbXBvcnQge011bHRpY2hvaWNlRmllbGR9IGZyb20gJy4uLy4uL2RhdGEtZmllbGRzL211bHRpY2hvaWNlLWZpZWxkL21vZGVscy9tdWx0aWNob2ljZS1maWVsZCc7XG5pbXBvcnQge0NoYW5nZSwgQ2hhbmdlZEZpZWxkc30gZnJvbSAnLi4vLi4vZGF0YS1maWVsZHMvbW9kZWxzL2NoYW5nZWQtZmllbGRzJztcbmltcG9ydCB7RmllbGRDb252ZXJ0ZXJTZXJ2aWNlfSBmcm9tICcuL2ZpZWxkLWNvbnZlcnRlci5zZXJ2aWNlJztcbmltcG9ydCB7RmllbGRUeXBlUmVzb3VyY2V9IGZyb20gJy4uL21vZGVsL2ZpZWxkLXR5cGUtcmVzb3VyY2UnO1xuaW1wb3J0IHtEeW5hbWljRW51bWVyYXRpb25GaWVsZH0gZnJvbSAnLi4vLi4vZGF0YS1maWVsZHMvZW51bWVyYXRpb24tZmllbGQvbW9kZWxzL2R5bmFtaWMtZW51bWVyYXRpb24tZmllbGQnO1xuaW1wb3J0IHtWYWxpZGF0aW9ufSBmcm9tICcuLi8uLi9kYXRhLWZpZWxkcy9tb2RlbHMvdmFsaWRhdGlvbic7XG5pbXBvcnQge1Rhc2tFdmVudE91dGNvbWV9IGZyb20gJy4uLy4uL2V2ZW50L21vZGVsL2V2ZW50LW91dGNvbWVzL3Rhc2stb3V0Y29tZXMvdGFzay1ldmVudC1vdXRjb21lJztcbmltcG9ydCB7RGF0YUZpZWxkfSBmcm9tICcuLi8uLi9kYXRhLWZpZWxkcy9tb2RlbHMvYWJzdHJhY3QtZGF0YS1maWVsZCc7XG5pbXBvcnQge1Rhc2tGaWVsZHN9IGZyb20gJy4uL21vZGVsL3Rhc2stZmllbGRzJztcbmltcG9ydCB7VGFza1JlZkZpZWxkfSBmcm9tIFwiLi4vLi4vZGF0YS1maWVsZHMvdGFzay1yZWYtZmllbGQvbW9kZWwvdGFzay1yZWYtZmllbGRcIjtcblxuLyoqXG4gKiBBY3RzIGFzIGEgY29tbXVuaWNhdGlvbiBpbnRlcmZhY2UgYmV0d2VlbiB0aGUgQ29tcG9uZW50IHRoYXQgcmVuZGVycyBUYXNrIGNvbnRlbnQgYW5kIGl0J3MgcGFyZW50IENvbXBvbmVudC5cbiAqIEFsc28gcHJvdmlkZXMgc29tZSBnZW5lcmFsIGZ1bmN0aW9uYWxpdHkgdGhhdCBpcyBuZWVkZWQgd2hlbiB3b3JraW5nIHdpdGggdGFzayBjb250ZW50LlxuICpcbiAqIE5vdGFibGUgZXhhbXBsZSBvZiBhIHBhcmVudCBDb21wb25lbnQgaXMgdGhlIHtAbGluayBBYnN0cmFjdFRhc2tQYW5lbENvbXBvbmVudH0uXG4gKlxuICogTm90YWJsZSBleGFtcGxlIG9mIGEgdGFzayBjb250ZW50IHJlbmRlcmVyIGlzIHRoZSB7QGxpbmsgQWJzdHJhY3RUYXNrQ29udGVudENvbXBvbmVudH0uXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBUYXNrQ29udGVudFNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBGUk9OVEVORF9BQ1RJT05TX0tFWSA9ICdfZnJvbnRlbmRfYWN0aW9ucyc7XG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBBQ1RJT04gPSAnYWN0aW9uJztcblxuICAgICRzaG91bGRDcmVhdGU6IFJlcGxheVN1YmplY3Q8QXJyYXk8RGF0YUdyb3VwPj47XG4gICAgJHNob3VsZENyZWF0ZUNvdW50ZXI6IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+O1xuICAgIHByb3RlY3RlZCBfdGFzazogVGFzaztcbiAgICBwcm90ZWN0ZWQgX3Rhc2tEYXRhUmVsb2FkUmVxdWVzdCQ6IFN1YmplY3Q8Q2hhbmdlPjtcbiAgICBwcm90ZWN0ZWQgX2lzRXhwYW5kaW5nJDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+O1xuICAgIHByb3RlY3RlZCBfdGFza0ZpZWxkc0luZGV4OiB7XG4gICAgICAgIFt0YXNrSWQ6IHN0cmluZ106IFRhc2tGaWVsZHNcbiAgICB9ID0ge307XG4gICAgcHJvdGVjdGVkIF9yZWZlcmVuY2VkVGFza0FuZENhc2VJZHM6IHsgW2Nhc2VJZDogc3RyaW5nXTogQXJyYXk8c3RyaW5nPiB9ID0ge307XG5cbiAgICBwcm90ZWN0ZWQgY29uc3RydWN0b3IocHJvdGVjdGVkIF9maWVsZENvbnZlcnRlclNlcnZpY2U6IEZpZWxkQ29udmVydGVyU2VydmljZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9zbmFja0JhclNlcnZpY2U6IFNuYWNrQmFyU2VydmljZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVjdGVkIF90cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlY3RlZCBfbG9nZ2VyOiBMb2dnZXJTZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMuJHNob3VsZENyZWF0ZSA9IG5ldyBSZXBsYXlTdWJqZWN0PEFycmF5PERhdGFHcm91cD4+KDEpO1xuICAgICAgICB0aGlzLiRzaG91bGRDcmVhdGVDb3VudGVyID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KDApO1xuICAgICAgICB0aGlzLl9pc0V4cGFuZGluZyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgICAgICAgdGhpcy5fdGFzayA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fdGFza0RhdGFSZWxvYWRSZXF1ZXN0JCA9IG5ldyBTdWJqZWN0PENoYW5nZT4oKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLiRzaG91bGRDcmVhdGUuY2xvc2VkKSB7XG4gICAgICAgICAgICB0aGlzLiRzaG91bGRDcmVhdGUuY29tcGxldGUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl90YXNrRGF0YVJlbG9hZFJlcXVlc3QkLmNvbXBsZXRlKCk7XG4gICAgICAgIHRoaXMuX2lzRXhwYW5kaW5nJC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIHRoZSBUYXNrIG9iamVjdCBpZiBzZXQgYW5kIGB1bmRlZmluZWRgIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBnZXQgdGFzaygpOiBUYXNrIHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogU2V0dGluZyBhIFRhc2sgYWxzbyBlbWl0cyBpdCBpbnRvIHRoZSBzdHJlYW0gYWNjZXNzaWJsZSBieSB0aGUgW3Rhc2skXXtAbGluayBUYXNrQ29udGVudFNlcnZpY2UjdGFzayR9IGdldHRlciBtZXRob2QuXG4gICAgICogQHBhcmFtIHRhc2sgdGhlIFRhc2sgdGhhdCBvd25zIHRoZSBjb250ZW50IG1hbmFnZWQgYnkgdGhpcyBzZXJ2aWNlXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IHNldCB0YXNrKHRhc2s6IFRhc2spO1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIHJldHVybnMgYSB7QGxpbmsgVGFza30gb2JqZWN0IGV2ZXJ5IHRpbWUgdGhpcyBvYmplY3QgaXMgc2V0LlxuICAgICAqXG4gICAgICogVXNlIFt0YXNrXXtAbGluayBUYXNrQ29udGVudFNlcnZpY2UjdGFza30gc2V0dGVyIG1ldGhvZCB0byBzZXQgdGhlIFRhc2suXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IGdldCB0YXNrJCgpOiBPYnNlcnZhYmxlPFRhc2s+O1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIHRoYXQgZW1pdHMgZXZlcnkgdGltZSBhIGRhdGEgcmVsb2FkIGlzIHJlcXVlc3RlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHRhc2tEYXRhUmVsb2FkUmVxdWVzdCQoKTogT2JzZXJ2YWJsZTxDaGFuZ2U+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Rhc2tEYXRhUmVsb2FkUmVxdWVzdCQuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG5cbiAgICBnZXQgdGFza0ZpZWxkc0luZGV4KCk6IHsgW3A6IHN0cmluZ106IFRhc2tGaWVsZHMgfSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90YXNrRmllbGRzSW5kZXg7XG4gICAgfVxuXG4gICAgc2V0IHRhc2tGaWVsZHNJbmRleCh2YWx1ZTogeyBbcDogc3RyaW5nXTogVGFza0ZpZWxkcyB9KSB7XG4gICAgICAgIHRoaXMuX3Rhc2tGaWVsZHNJbmRleCA9IHZhbHVlO1xuICAgIH1cblxuICAgIGdldCByZWZlcmVuY2VkVGFza0FuZENhc2VJZHMoKTogeyBbcDogc3RyaW5nXTogQXJyYXk8c3RyaW5nPiB9IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlZmVyZW5jZWRUYXNrQW5kQ2FzZUlkcztcbiAgICB9XG5cbiAgICBzZXQgcmVmZXJlbmNlZFRhc2tBbmRDYXNlSWRzKHZhbHVlOiB7IFtwOiBzdHJpbmddOiBBcnJheTxzdHJpbmc+IH0pIHtcbiAgICAgICAgdGhpcy5fcmVmZXJlbmNlZFRhc2tBbmRDYXNlSWRzID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgcGFuZWwgdGhhdCB0aGUgdGFzayBjb250ZW50IGlzIGNvbnRhaW5lZCBpbiBpcyBjdXJyZW50bHkgZXhwYW5kaW5nLlxuICAgICAqXG4gICAgICogSWYgdGhlIHRhc2sgY29udGVudCBpcyBub3QgY29udGFpbmVkIGluIGEgcGFuZWwsIGBpc0V4cGFuZGluZ2Agd2lsbCBiZSBhbHdheXMgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGlzRXhwYW5kaW5nKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNFeHBhbmRpbmckLnZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIHN0YXRlIG9mIHRoZSB0YXNrIGNvbnRlbnQgdG8gYGV4cGFuZGluZ2AuXG4gICAgICovXG4gICAgcHVibGljIGV4cGFuc2lvblN0YXJ0ZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2lzRXhwYW5kaW5nJC5uZXh0KHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIHN0YXRlIG9mIHRoZSB0YXNrIGNvbnRlbnQgdG8gYG5vdCBleHBhbmRpbmdgLlxuICAgICAqL1xuICAgIHB1YmxpYyBleHBhbnNpb25GaW5pc2hlZCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5faXNFeHBhbmRpbmckLm5leHQoZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB0aGUgdmFsaWRpdHkgb2YgYWxsIGRhdGEgZmllbGRzIGluIHRoZSBtYW5hZ2VkIHtAbGluayBUYXNrfS5cbiAgICAgKlxuICAgICAqIElmIHNvbWUgb2YgdGhlIGZpZWxkcyBhcmUgaW52YWxpZCB0b3VjaGVzIHRoZW0gc28gdGhlaXIgdmFsaWRhdGlvbiBlcnJvcnMgd2lsbCBhcHBlYXIgKGlmIHNldCkuXG4gICAgICogQSBzbmFja2JhciB3aWxsIGFsc28gYmUgZGlzcGxheWVkIHRvIHRoZSB1c2VyLCBpbmZvcm1pbmcgdGhlbSBvZiB0aGUgZmFjdCB0aGF0IHRoZSBmaWVsZHMgYXJlIGludmFsaWQuXG4gICAgICogQHJldHVybnMgd2hldGhlciB0aGUgdGFzayBpcyB2YWxpZCBvciBub3RcbiAgICAgKi9cbiAgICBwdWJsaWMgdmFsaWRhdGVUYXNrRGF0YSh0YXNrSWQ/OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCF0aGlzLl90YXNrIHx8ICF0aGlzLl90YXNrLmRhdGFHcm91cHMpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWxpZCA9ICF0aGlzLl90YXNrLmRhdGFHcm91cHMuZmlsdGVyKGdyb3VwID0+ICEhZ3JvdXAucGFyZW50VGFza0lkICYmICEhdGFza0lkID8gZ3JvdXAucGFyZW50VGFza0lkID09PSB0YXNrSWQgOiB0cnVlKS5zb21lKGdyb3VwID0+IGdyb3VwLmZpZWxkcy5zb21lKGZpZWxkID0+ICFmaWVsZC52YWxpZCAmJiAhZmllbGQuZGlzYWJsZWQpKTtcbiAgICAgICAgY29uc3QgdmFsaWREaXNhYmxlZCA9ICF0aGlzLl90YXNrLmRhdGFHcm91cHMuZmlsdGVyKGdyb3VwID0+ICEhZ3JvdXAucGFyZW50VGFza0lkICYmICEhdGFza0lkID8gZ3JvdXAucGFyZW50VGFza0lkID09PSB0YXNrSWQgOiB0cnVlKS5zb21lKGdyb3VwID0+IGdyb3VwLmZpZWxkcy5zb21lKGZpZWxkID0+ICFmaWVsZC52YWxpZFJlcXVpcmVkICYmIGZpZWxkLmRpc2FibGVkKSk7XG4gICAgICAgIGlmICghdmFsaWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3NuYWNrQmFyU2VydmljZS5vcGVuRXJyb3JTbmFja0Jhcih0aGlzLl90cmFuc2xhdGUuaW5zdGFudCgndGFza3Muc25hY2tiYXIuaW52YWxpZERhdGEnKSk7XG4gICAgICAgICAgICB0aGlzLl90YXNrLmRhdGFHcm91cHMuZm9yRWFjaChncm91cCA9PiBncm91cC5maWVsZHMuZm9yRWFjaChmaWVsZCA9PiBmaWVsZC50b3VjaCA9IHRydWUpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXZhbGlkRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3NuYWNrQmFyU2VydmljZS5vcGVuRXJyb3JTbmFja0Jhcih0aGlzLl90cmFuc2xhdGUuaW5zdGFudCgndGFza3Muc25hY2tiYXIubWlzc2luZ1JlcXVpcmVkJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWxpZCAmJiB2YWxpZERpc2FibGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmRzIGludmFsaWQgZGF0YSBvZiB0YXNrXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBhcnJheSBvZiBpbnZhbGlkIGRhdGFmaWVsZHNcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0SW52YWxpZFRhc2tEYXRhKCk6IEFycmF5PERhdGFGaWVsZDxhbnk+PiB7XG4gICAgICAgIGNvbnN0IGludmFsaWRGaWVsZHMgPSBbXTtcbiAgICAgICAgdGhpcy5fdGFzay5kYXRhR3JvdXBzLmZvckVhY2goZ3JvdXAgPT4gaW52YWxpZEZpZWxkcy5wdXNoKC4uLmdyb3VwLmZpZWxkcy5maWx0ZXIoZmllbGQgPT5cbiAgICAgICAgICAgICghZmllbGQudmFsaWQgJiYgIWZpZWxkLmRpc2FibGVkKSB8fCAoIWZpZWxkLnZhbGlkUmVxdWlyZWQgJiYgIWZpZWxkLmRpc2FibGVkKSkpKTtcbiAgICAgICAgcmV0dXJuIGludmFsaWRGaWVsZHM7XG4gICAgfVxuXG4gICAgcHVibGljIHZhbGlkYXRlRHluYW1pY0VudW1GaWVsZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCF0aGlzLl90YXNrIHx8ICF0aGlzLl90YXNrLmRhdGFHcm91cHMpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBleGlzdHMgPSB0aGlzLl90YXNrLmRhdGFHcm91cHMuc29tZShncm91cCA9PiBncm91cC5maWVsZHMuc29tZShmaWVsZCA9PiBmaWVsZCBpbnN0YW5jZW9mIER5bmFtaWNFbnVtZXJhdGlvbkZpZWxkKSk7XG4gICAgICAgIGlmICghZXhpc3RzKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgdmFsaWQgPSB0cnVlO1xuICAgICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIHRoaXMuX3Rhc2suZGF0YUdyb3Vwcykge1xuICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiBncm91cC5maWVsZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZmllbGQgaW5zdGFuY2VvZiBEeW5hbWljRW51bWVyYXRpb25GaWVsZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmllbGQuY2hvaWNlcyAhPT0gdW5kZWZpbmVkICYmIGZpZWxkLmNob2ljZXMubGVuZ3RoICE9PSAwICYmIGZpZWxkLnZhbHVlICE9PSAnJyAmJiBmaWVsZC52YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWZpZWxkLmNob2ljZXMuc29tZShjaG9pY2UgPT4gY2hvaWNlLmtleSA9PT0gZmllbGQudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmllbGQudmFsdWUgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmllbGQuYmVoYXZpb3IucmVxdWlyZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF2YWxpZCkge1xuICAgICAgICAgICAgdGhpcy5fc25hY2tCYXJTZXJ2aWNlLm9wZW5FcnJvclNuYWNrQmFyKHRoaXMuX3RyYW5zbGF0ZS5pbnN0YW50KCd0YXNrcy5zbmFja2Jhci5taXNzaW5nUmVxdWlyZWQnKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbGlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIGJsb2NraW5nIHN0YXRlIG9mIGFsbCBmaWVsZHMgaW4gdGhlIG1hbmFnZWQgVGFzay5cbiAgICAgKiBAcGFyYW0gYmxvY2tpbmdTdGF0ZSB3aGV0aGVyIHRoZSBmaWVsZCBzaG91bGQgYmUgYmxvY2tlZCBvciBub3RcbiAgICAgKi9cbiAgICBwdWJsaWMgYmxvY2tGaWVsZHMoYmxvY2tpbmdTdGF0ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5fdGFzayAmJiB0aGlzLl90YXNrLmRhdGFHcm91cHMpIHtcbiAgICAgICAgICAgIHRoaXMuX3Rhc2suZGF0YUdyb3Vwcy5mb3JFYWNoKGdyb3VwID0+IHtcbiAgICAgICAgICAgICAgICBncm91cC5maWVsZHMuZm9yRWFjaChmaWVsZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkLmJsb2NrID0gYmxvY2tpbmdTdGF0ZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXJzIHRoZSBhc3NpZ25lZSwgc3RhcnQgZGF0ZSBhbmQgZmluaXNoIGRhdGUgZnJvbSB0aGUgbWFuYWdlZCBUYXNrLlxuICAgICAqL1xuICAgIHB1YmxpYyB1cGRhdGVTdGF0ZURhdGEoZXZlbnRPdXRjb21lOiBUYXNrRXZlbnRPdXRjb21lKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl90YXNrKSB7XG4gICAgICAgICAgICB0aGlzLl90YXNrLmFzc2lnbmVlID0gZXZlbnRPdXRjb21lLnRhc2suYXNzaWduZWU7XG4gICAgICAgICAgICB0aGlzLl90YXNrLnN0YXJ0RGF0ZSA9IGV2ZW50T3V0Y29tZS50YXNrLnN0YXJ0RGF0ZTtcbiAgICAgICAgICAgIHRoaXMuX3Rhc2suZmluaXNoRGF0ZSA9IGV2ZW50T3V0Y29tZS50YXNrLmZpbmlzaERhdGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBwcm9wZXJ0aWVzIG9mIGZpZWxkcyBpbiB0aGUgbWFuYWdlZCB0YXNrIGJhc2VkIG9uIGEgZGVsdGEgb2YgY2hhbmdlcyBmcm9tIHByZXZpb3VzIHN0YXRlLlxuICAgICAqIEBwYXJhbSBjaEZpZWxkcyBvYmplY3QgY29udGFpbmluZyB0aGUgZGVsdGEgb2YgdGhlIGNoYW5nZXMgZnJvbSB0aGUgcHJldmlvdXMgc3RhdGVcbiAgICAgKi9cbiAgICBwdWJsaWMgdXBkYXRlRnJvbUNoYW5nZWRGaWVsZHMoY2hGaWVsZHM6IENoYW5nZWRGaWVsZHMpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLl90YXNrIHx8ICF0aGlzLl90YXNrLmRhdGFHcm91cHMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmcm9udGVuZEFjdGlvbnMgPSBjaEZpZWxkcy50YXNrSWQgPT09IHRoaXMudGFzay5zdHJpbmdJZCAmJiBjaEZpZWxkc1tUYXNrQ29udGVudFNlcnZpY2UuRlJPTlRFTkRfQUNUSU9OU19LRVldO1xuICAgICAgICBPYmplY3Qua2V5cyhjaEZpZWxkcykuZm9yRWFjaChjaGFuZ2VkRmllbGQgPT4ge1xuICAgICAgICAgICAgaWYgKGNoRmllbGRzLnRhc2tJZCA9PT0gdGhpcy5fdGFzay5zdHJpbmdJZCAmJiB0aGlzLmlzRmllbGRJblRhc2soY2hGaWVsZHMudGFza0lkLCBjaGFuZ2VkRmllbGQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVGaWVsZChjaEZpZWxkcywgdGhpcy50YXNrRmllbGRzSW5kZXhbY2hGaWVsZHMudGFza0lkXS5maWVsZHNbY2hhbmdlZEZpZWxkXSwgZnJvbnRlbmRBY3Rpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoISF0aGlzLmdldFJlZmVyZW5jZWRUYXNrSWQoY2hhbmdlZEZpZWxkLCBjaEZpZWxkcykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUZpZWxkKGNoRmllbGRzLCB0aGlzLnRhc2tGaWVsZHNJbmRleFt0aGlzLmdldFJlZmVyZW5jZWRUYXNrSWQoY2hhbmdlZEZpZWxkLCBjaEZpZWxkcyldLmZpZWxkc1tjaGFuZ2VkRmllbGRdLCBmcm9udGVuZEFjdGlvbnMsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLiRzaG91bGRDcmVhdGUubmV4dCh0aGlzLl90YXNrLmRhdGFHcm91cHMpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCB1cGRhdGVGaWVsZChjaEZpZWxkczogQ2hhbmdlZEZpZWxkcywgZmllbGQ6IERhdGFGaWVsZDxhbnk+LCBmcm9udGVuZEFjdGlvbnM6IENoYW5nZSwgcmVmZXJlbmNlZDogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl9maWVsZENvbnZlcnRlclNlcnZpY2UucmVzb2x2ZVR5cGUoZmllbGQpID09PSBGaWVsZFR5cGVSZXNvdXJjZS5UQVNLX1JFRikge1xuICAgICAgICAgICAgdGhpcy5fdGFza0RhdGFSZWxvYWRSZXF1ZXN0JC5uZXh0KGZyb250ZW5kQWN0aW9ucyA/IGZyb250ZW5kQWN0aW9ucyA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGQgPSBjaEZpZWxkc1tmaWVsZC5zdHJpbmdJZF07XG4gICAgICAgIE9iamVjdC5rZXlzKHVwZGF0ZWRGaWVsZCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgICAgICBjYXNlICd0eXBlJzpcbiAgICAgICAgICAgICAgICAgICAgLy8gdHlwZSBpcyBqdXN0IGFuIGluZm9ybWF0aW9uLCBub3QgYW4gdXBkYXRlLiBBIGZpZWxkIGNhbm5vdCBjaGFuZ2UgaXRzIHR5cGVcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBjb250aW51ZSAtIHRoZSBmaWVsZCBkb2VzIG5vdCBuZWVkIHVwZGF0aW5nLCBzaW5jZSBub3RoaW5nIGNoYW5nZWRcbiAgICAgICAgICAgICAgICBjYXNlICd2YWx1ZSc6XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkLnZhbHVlV2l0aG91dENoYW5nZSh0aGlzLl9maWVsZENvbnZlcnRlclNlcnZpY2UuZm9ybWF0VmFsdWVGcm9tQmFja2VuZChmaWVsZCwgdXBkYXRlZEZpZWxkW2tleV0pKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYmVoYXZpb3InOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXJlZmVyZW5jZWQgJiYgdXBkYXRlZEZpZWxkLmJlaGF2aW9yW3RoaXMuX3Rhc2sudHJhbnNpdGlvbklkXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmllbGQuYmVoYXZpb3IgPSB1cGRhdGVkRmllbGQuYmVoYXZpb3JbdGhpcy5fdGFzay50cmFuc2l0aW9uSWRdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJlZmVyZW5jZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhc2tJZCA9IHRoaXMuZ2V0UmVmZXJlbmNlZFRhc2tJZChmaWVsZC5zdHJpbmdJZCwgY2hGaWVsZHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFza1JlZiA9IHRoaXMuZmluZFRhc2tSZWZJZCh0YXNrSWQsIHRoaXMudGFza0ZpZWxkc0luZGV4W3RoaXMuX3Rhc2suc3RyaW5nSWRdLmZpZWxkcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2l0aW9uSWQgPSB0aGlzLnRhc2tGaWVsZHNJbmRleFt0YXNrSWRdLnRyYW5zaXRpb25JZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXRyYW5zaXRpb25JZCAmJiB0cmFuc2l0aW9uSWQgIT09ICcnICYmIHVwZGF0ZWRGaWVsZC5iZWhhdmlvclt0cmFuc2l0aW9uSWRdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkLmJlaGF2aW9yID0gdGFza1JlZi5iZWhhdmlvci5lZGl0YWJsZSA/IHVwZGF0ZWRGaWVsZC5iZWhhdmlvclt0cmFuc2l0aW9uSWRdIDogdGFza1JlZi5iZWhhdmlvcjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjaG9pY2VzJzpcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3Q2hvaWNlczogQXJyYXk8RW51bWVyYXRpb25GaWVsZFZhbHVlPiA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAodXBkYXRlZEZpZWxkLmNob2ljZXMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEZpZWxkLmNob2ljZXMuZm9yRWFjaChpdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hvaWNlcy5wdXNoKHtrZXk6IGl0LCB2YWx1ZTogaXR9IGFzIEVudW1lcmF0aW9uRmllbGRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHVwZGF0ZWRGaWVsZC5jaG9pY2VzKS5mb3JFYWNoKGNob2ljZUtleSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hvaWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5OiBjaG9pY2VLZXksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1cGRhdGVkRmllbGQuY2hvaWNlc1tjaG9pY2VLZXldXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBhcyBFbnVtZXJhdGlvbkZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKGZpZWxkIGFzIEVudW1lcmF0aW9uRmllbGQgfCBNdWx0aWNob2ljZUZpZWxkKS5jaG9pY2VzID0gbmV3Q2hvaWNlcztcbiAgICAgICAgICAgICAgICAgICAgKGZpZWxkIGFzIEVudW1lcmF0aW9uRmllbGQgfCBNdWx0aWNob2ljZUZpZWxkKS51cGRhdGVDaG9pY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnb3B0aW9ucyc6XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld09wdGlvbnMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXModXBkYXRlZEZpZWxkLm9wdGlvbnMpLmZvckVhY2gob3B0aW9uS2V5ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09wdGlvbnMucHVzaCh7a2V5OiBvcHRpb25LZXksIHZhbHVlOiB1cGRhdGVkRmllbGQub3B0aW9uc1tvcHRpb25LZXldfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAoZmllbGQgYXMgRW51bWVyYXRpb25GaWVsZCB8IE11bHRpY2hvaWNlRmllbGQpLmNob2ljZXMgPSBuZXdPcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICAoZmllbGQgYXMgRW51bWVyYXRpb25GaWVsZCB8IE11bHRpY2hvaWNlRmllbGQpLnVwZGF0ZUNob2ljZSgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd2YWxpZGF0aW9ucyc6XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkLnJlcGxhY2VWYWxpZGF0aW9ucyh1cGRhdGVkRmllbGQudmFsaWRhdGlvbnMubWFwKGl0ID0+IChpdCBhcyBWYWxpZGF0aW9uKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBmaWVsZFtrZXldID0gdXBkYXRlZEZpZWxkW2tleV07XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpZWxkLnVwZGF0ZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaXNGaWVsZEluVGFzayh0YXNrSWQ6IHN0cmluZywgY2hhbmdlZEZpZWxkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdGFza0lkXG4gICAgICAgICAgICAmJiAhIXRoaXMudGFza0ZpZWxkc0luZGV4W3Rhc2tJZF1cbiAgICAgICAgICAgICYmICEhdGhpcy50YXNrRmllbGRzSW5kZXhbdGFza0lkXS5maWVsZHNcbiAgICAgICAgICAgICYmICEhdGhpcy50YXNrRmllbGRzSW5kZXhbdGFza0lkXS5maWVsZHNbY2hhbmdlZEZpZWxkXVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRSZWZlcmVuY2VkVGFza0lkKGNoYW5nZWRGaWVsZDogc3RyaW5nLCBjaEZpZWxkczogQ2hhbmdlZEZpZWxkcyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiAhIXRoaXMudGFza0ZpZWxkc0luZGV4ID9cbiAgICAgICAgICAgIChPYmplY3Qua2V5cyh0aGlzLnRhc2tGaWVsZHNJbmRleCkuZmluZCh0YXNrSWQgPT4gdGFza0lkICE9PSB0aGlzLnRhc2suc3RyaW5nSWQgJiYgdGFza0lkID09PSBjaEZpZWxkcy50YXNrSWQgJiYgT2JqZWN0LmtleXModGhpcy50YXNrRmllbGRzSW5kZXhbdGFza0lkXS5maWVsZHMpPy5pbmNsdWRlcyhjaGFuZ2VkRmllbGQpKVxuICAgICAgICAgICAgfHwgT2JqZWN0LmtleXModGhpcy50YXNrRmllbGRzSW5kZXgpLmZpbmQodGFza0lkID0+IHRhc2tJZCAhPT0gdGhpcy50YXNrLnN0cmluZ0lkICYmIE9iamVjdC5rZXlzKHRoaXMudGFza0ZpZWxkc0luZGV4W3Rhc2tJZF0uZmllbGRzKT8uaW5jbHVkZXMoY2hhbmdlZEZpZWxkKSkpIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBmaW5kVGFza1JlZklkKHRhc2tJZDogc3RyaW5nLCBmaWVsZHM6IHsgW2ZpZWxkSWQ6IHN0cmluZ106IERhdGFGaWVsZDxhbnk+fSk6IERhdGFGaWVsZDxhbnk+IHtcbiAgICAgICAgbGV0IHRhc2tSZWZJZCA9IE9iamVjdC52YWx1ZXMoZmllbGRzKS5maW5kKGYgPT4gZiBpbnN0YW5jZW9mIFRhc2tSZWZGaWVsZCAmJiBmLnZhbHVlPy5pbmNsdWRlcyh0YXNrSWQpKTtcbiAgICAgICAgaWYgKCF0YXNrUmVmSWQpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlZmVyZW5jZWRUYXNrSWRzID0gT2JqZWN0LnZhbHVlcyhmaWVsZHMpLmZpbHRlcihmID0+IGYgaW5zdGFuY2VvZiBUYXNrUmVmRmllbGQpLm1hcCh0ciA9PiB0ci52YWx1ZSk7XG4gICAgICAgICAgICByZWZlcmVuY2VkVGFza0lkcy5mb3JFYWNoKGlkID0+IHtcbiAgICAgICAgICAgICAgICB0YXNrUmVmSWQgPSB0aGlzLmZpbmRUYXNrUmVmSWQodGFza0lkLCB0aGlzLnRhc2tGaWVsZHNJbmRleFtpZF0uZmllbGRzKTtcbiAgICAgICAgICAgICAgICBpZiAoISF0YXNrUmVmSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRhc2tSZWZJZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGFza1JlZklkXG4gICAgfVxufVxuIl19