@ng-dynamic-forms/core
Version:
A rapid form development library for Angular
278 lines • 51.2 kB
JavaScript
import { Injectable } from "@angular/core";
import { UntypedFormArray, UntypedFormControl, UntypedFormGroup } from "@angular/forms";
import { DynamicFormArrayModel, DYNAMIC_FORM_CONTROL_TYPE_ARRAY, DynamicFormArrayGroupModel } from "../model/form-array/dynamic-form-array.model";
import { DYNAMIC_FORM_CONTROL_TYPE_GROUP, DynamicFormGroupModel } from "../model/form-group/dynamic-form-group.model";
import { DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP, DynamicCheckboxGroupModel } from "../model/checkbox/dynamic-checkbox-group.model";
import { DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX, DynamicCheckboxModel } from "../model/checkbox/dynamic-checkbox.model";
import { DYNAMIC_FORM_CONTROL_TYPE_COLORPICKER, DynamicColorPickerModel } from "../model/colorpicker/dynamic-colorpicker.model";
import { DYNAMIC_FORM_CONTROL_TYPE_DATEPICKER, DynamicDatePickerModel } from "../model/datepicker/dynamic-datepicker.model";
import { DYNAMIC_FORM_CONTROL_TYPE_EDITOR, DynamicEditorModel } from "../model/editor/dynamic-editor.model";
import { DYNAMIC_FORM_CONTROL_TYPE_FILE_UPLOAD, DynamicFileUploadModel } from "../model/file-upload/dynamic-file-upload.model";
import { DYNAMIC_FORM_CONTROL_TYPE_INPUT, DynamicInputModel } from "../model/input/dynamic-input.model";
import { DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP, DynamicRadioGroupModel } from "../model/radio/dynamic-radio-group.model";
import { DYNAMIC_FORM_CONTROL_TYPE_RATING, DynamicRatingModel } from "../model/rating/dynamic-rating.model";
import { DYNAMIC_FORM_CONTROL_TYPE_SELECT, DynamicSelectModel } from "../model/select/dynamic-select.model";
import { DYNAMIC_FORM_CONTROL_TYPE_SLIDER, DynamicSliderModel } from "../model/slider/dynamic-slider.model";
import { DYNAMIC_FORM_CONTROL_TYPE_SWITCH, DynamicSwitchModel } from "../model/switch/dynamic-switch.model";
import { DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA, DynamicTextAreaModel } from "../model/textarea/dynamic-textarea.model";
import { DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER, DynamicTimePickerModel } from "../model/timepicker/dynamic-timepicker.model";
import { DynamicFormHook } from "../model/misc/dynamic-form-control-validation.model";
import { parseReviver } from "../utils/json.utils";
import { isString } from "../utils/core.utils";
import { DynamicFormComponent } from "../component/dynamic-form.component";
import * as i0 from "@angular/core";
import * as i1 from "./dynamic-form-component.service";
import * as i2 from "./dynamic-form-validation.service";
export class DynamicFormService {
constructor(componentService, validationService) {
this.componentService = componentService;
this.validationService = validationService;
}
createAbstractControlOptions(validatorsConfig = null, asyncValidatorsConfig = null, updateOn = null) {
return {
asyncValidators: asyncValidatorsConfig !== null ? this.validationService.getAsyncValidators(asyncValidatorsConfig) : null,
validators: validatorsConfig !== null ? this.validationService.getValidators(validatorsConfig) : null,
updateOn: updateOn !== null && this.validationService.isFormHook(updateOn) ? updateOn : DynamicFormHook.Change
};
}
createFormArray(formArrayModel) {
const controls = [];
const options = this.createAbstractControlOptions(formArrayModel.validators, formArrayModel.asyncValidators, formArrayModel.updateOn);
for (let index = 0; index < formArrayModel.size; index++) {
const groupModel = formArrayModel.get(index);
const groupOptions = this.createAbstractControlOptions(formArrayModel.groupValidators, formArrayModel.groupAsyncValidators, formArrayModel.updateOn);
controls.push(this.createFormGroup(groupModel.group, groupOptions, groupModel));
}
return new UntypedFormArray(controls, options);
}
createFormGroup(formModel, options = null, parent = null) {
const controls = {};
formModel.forEach(model => {
model.parent = parent;
switch (model.type) {
case DYNAMIC_FORM_CONTROL_TYPE_ARRAY:
controls[model.id] = this.createFormArray(model);
break;
case DYNAMIC_FORM_CONTROL_TYPE_GROUP:
case DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP:
const groupModel = model;
const groupOptions = this.createAbstractControlOptions(groupModel.validators, groupModel.asyncValidators, groupModel.updateOn);
controls[model.id] = this.createFormGroup(groupModel.group, groupOptions, groupModel);
break;
default:
const controlModel = model;
const controlState = { value: controlModel.value, disabled: controlModel.disabled };
const controlOptions = this.createAbstractControlOptions(controlModel.validators, controlModel.asyncValidators, controlModel.updateOn);
controls[model.id] = new UntypedFormControl(controlState, controlOptions);
}
});
return new UntypedFormGroup(controls, options);
}
getPathSegment(model) {
return model instanceof DynamicFormArrayGroupModel ? model.index.toString() : model.id;
}
getPath(model, join = false) {
const path = [this.getPathSegment(model)];
let parent = model.parent;
while (parent) {
path.unshift(this.getPathSegment(parent));
parent = parent.parent;
}
return join ? path.join(".") : path;
}
addFormGroupControl(formGroup, formModel, ...models) {
if (formModel instanceof DynamicFormGroupModel) {
this.insertFormGroupControl(formModel.size(), formGroup, formModel, ...models);
}
else {
const model = formModel;
this.insertFormGroupControl(model.length, formGroup, model, ...models);
}
}
moveFormGroupControl(index, step, formModel) {
if (formModel instanceof DynamicFormGroupModel) {
formModel.move(index, step);
}
else {
const model = formModel;
model.splice(index + step, 0, ...model.splice(index, 1));
}
}
insertFormGroupControl(index, formGroup, formModel, ...models) {
const parent = formModel instanceof DynamicFormGroupModel ? formModel : null;
const controls = this.createFormGroup(models, null, parent).controls;
Object.keys(controls).forEach((controlName, idx) => {
const controlModel = models[idx];
if (formModel instanceof DynamicFormGroupModel) {
formModel.insert(index, controlModel);
}
else {
formModel.splice(index, 0, controlModel);
}
formGroup.addControl(controlName, controls[controlName]);
});
}
removeFormGroupControl(index, formGroup, formModel) {
if (formModel instanceof DynamicFormGroupModel) {
formGroup.removeControl(formModel.get(index).id);
formModel.remove(index);
}
else {
formGroup.removeControl(formModel[index].id);
formModel.splice(index, 1);
}
}
addFormArrayGroup(formArray, formArrayModel) {
const groupModel = formArrayModel.addGroup();
formArray.push(this.createFormGroup(groupModel.group, null, groupModel));
}
insertFormArrayGroup(index, formArray, formArrayModel) {
const groupModel = formArrayModel.insertGroup(index);
formArray.insert(index, this.createFormGroup(groupModel.group, null, groupModel));
}
moveFormArrayGroup(index, step, formArray, formArrayModel) {
const newIndex = index + step;
const moveUp = step >= 0;
if ((index >= 0 && index < formArrayModel.size) && (newIndex >= 0 && newIndex < formArrayModel.size)) {
const movingGroups = [];
for (let i = moveUp ? index : newIndex; i <= (moveUp ? newIndex : index); i++) {
movingGroups.push(formArray.at(i));
}
movingGroups.forEach((formControl, idx) => {
let position;
if (moveUp) {
position = idx === 0 ? newIndex : index + idx - 1;
}
else {
position = idx === movingGroups.length - 1 ? newIndex : newIndex + idx + 1;
}
formArray.setControl(position, formControl);
});
formArrayModel.moveGroup(index, step);
}
else {
throw new Error(`form array group cannot be moved due to index or new index being out of bounds`);
}
}
removeFormArrayGroup(index, formArray, formArrayModel) {
formArray.removeAt(index);
formArrayModel.removeGroup(index);
}
clearFormArray(formArray, formArrayModel) {
formArray.clear();
formArrayModel.clear();
}
findById(id, formModel) {
const findByIdFn = (modelId, groupModel) => {
for (const controlModel of groupModel) {
if (controlModel.id === modelId) {
result = controlModel;
break;
}
if (controlModel instanceof DynamicFormGroupModel) {
findByIdFn(modelId, controlModel.group);
}
}
};
let result = null;
findByIdFn(id, formModel);
return result;
}
findModelById(id, formModel) {
return this.findById(id, formModel);
}
findControlByModel(model, group) {
return group.root.get(this.getPath(model, true));
}
detectChanges(formComponent) {
if (formComponent instanceof DynamicFormComponent) {
formComponent.markForCheck();
formComponent.detectChanges();
}
else {
for (const form of this.componentService.getForms()) {
form.markForCheck();
form.detectChanges();
}
}
}
fromJSON(json) {
const formModelJSON = isString(json) ? JSON.parse(json, parseReviver) : json;
const formModel = [];
formModelJSON.forEach((model) => {
const layout = model.layout ?? null;
switch (model.type) {
case DYNAMIC_FORM_CONTROL_TYPE_ARRAY:
const formArrayModel = model;
if (Array.isArray(formArrayModel.groups)) {
formArrayModel.groups.forEach((groupModel) => {
groupModel.group = this.fromJSON(groupModel.group);
});
}
formArrayModel.groupFactory = () => this.fromJSON(formArrayModel.groupPrototype);
formModel.push(new DynamicFormArrayModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX:
formModel.push(new DynamicCheckboxModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP:
model.group = this.fromJSON(model.group);
formModel.push(new DynamicCheckboxGroupModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_COLORPICKER:
formModel.push(new DynamicColorPickerModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_DATEPICKER:
formModel.push(new DynamicDatePickerModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_EDITOR:
formModel.push(new DynamicEditorModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_FILE_UPLOAD:
model.value = null;
formModel.push(new DynamicFileUploadModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_GROUP:
model.group = this.fromJSON(model.group);
formModel.push(new DynamicFormGroupModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_INPUT:
formModel.push(new DynamicInputModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP:
formModel.push(new DynamicRadioGroupModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_RATING:
formModel.push(new DynamicRatingModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_SELECT:
formModel.push(new DynamicSelectModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_SLIDER:
formModel.push(new DynamicSliderModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_SWITCH:
formModel.push(new DynamicSwitchModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_TEXTAREA:
formModel.push(new DynamicTextAreaModel(model, layout));
break;
case DYNAMIC_FORM_CONTROL_TYPE_TIMEPICKER:
formModel.push(new DynamicTimePickerModel(model, layout));
break;
default:
throw new Error(`unknown form control model type defined on JSON object with id "${model.id}"`);
}
});
return formModel;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: DynamicFormService, deps: [{ token: i1.DynamicFormComponentService }, { token: i2.DynamicFormValidationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: DynamicFormService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: DynamicFormService, decorators: [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], ctorParameters: function () { return [{ type: i1.DynamicFormComponentService }, { type: i2.DynamicFormValidationService }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3JtLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1keW5hbWljLWZvcm1zL2NvcmUvc3JjL2xpYi9zZXJ2aWNlL2R5bmFtaWMtZm9ybS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFtQixnQkFBZ0IsRUFBRSxrQkFBa0IsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSXpHLE9BQU8sRUFDSCxxQkFBcUIsRUFDckIsK0JBQStCLEVBQy9CLDBCQUEwQixFQUM3QixNQUFNLDhDQUE4QyxDQUFDO0FBQ3RELE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQ3RILE9BQU8sRUFDSCx3Q0FBd0MsRUFDeEMseUJBQXlCLEVBQzVCLE1BQU0sZ0RBQWdELENBQUM7QUFDeEQsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDcEgsT0FBTyxFQUNILHFDQUFxQyxFQUNyQyx1QkFBdUIsRUFDMUIsTUFBTSxnREFBZ0QsQ0FBQztBQUN4RCxPQUFPLEVBQ0gsb0NBQW9DLEVBQ3BDLHNCQUFzQixFQUN6QixNQUFNLDhDQUE4QyxDQUFDO0FBQ3RELE9BQU8sRUFBRSxnQ0FBZ0MsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzVHLE9BQU8sRUFDSCxxQ0FBcUMsRUFDckMsc0JBQXNCLEVBQ3pCLE1BQU0sZ0RBQWdELENBQUM7QUFDeEQsT0FBTyxFQUFFLCtCQUErQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDeEcsT0FBTyxFQUNILHFDQUFxQyxFQUNyQyxzQkFBc0IsRUFDekIsTUFBTSwwQ0FBMEMsQ0FBQztBQUNsRCxP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TSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsS0FBSyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7YUFDdkc7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7OEdBNVRRLGtCQUFrQjtrSEFBbEIsa0JBQWtCLGNBRmYsTUFBTTs7MkZBRVQsa0JBQWtCO2tCQUg5QixVQUFVO21CQUFDO29CQUNSLFVBQVUsRUFBRSxNQUFNO2lCQUNyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBVbnR5cGVkRm9ybUFycmF5LCBVbnR5cGVkRm9ybUNvbnRyb2wsIFVudHlwZWRGb3JtR3JvdXAgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbE9wdGlvbnMgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IER5bmFtaWNGb3JtQ29udHJvbE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL2R5bmFtaWMtZm9ybS1jb250cm9sLm1vZGVsXCI7XG5pbXBvcnQgeyBEeW5hbWljRm9ybVZhbHVlQ29udHJvbE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL2R5bmFtaWMtZm9ybS12YWx1ZS1jb250cm9sLm1vZGVsXCI7XG5pbXBvcnQge1xuICAgIER5bmFtaWNGb3JtQXJyYXlNb2RlbCxcbiAgICBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX0FSUkFZLFxuICAgIER5bmFtaWNGb3JtQXJyYXlHcm91cE1vZGVsXG59IGZyb20gXCIuLi9tb2RlbC9mb3JtLWFycmF5L2R5bmFtaWMtZm9ybS1hcnJheS5tb2RlbFwiO1xuaW1wb3J0IHsgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9HUk9VUCwgRHluYW1pY0Zvcm1Hcm91cE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL2Zvcm0tZ3JvdXAvZHluYW1pYy1mb3JtLWdyb3VwLm1vZGVsXCI7XG5pbXBvcnQge1xuICAgIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfQ0hFQ0tCT1hfR1JPVVAsXG4gICAgRHluYW1pY0NoZWNrYm94R3JvdXBNb2RlbFxufSBmcm9tIFwiLi4vbW9kZWwvY2hlY2tib3gvZHluYW1pYy1jaGVja2JveC1ncm91cC5tb2RlbFwiO1xuaW1wb3J0IHsgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9DSEVDS0JPWCwgRHluYW1pY0NoZWNrYm94TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvY2hlY2tib3gvZHluYW1pYy1jaGVja2JveC5tb2RlbFwiO1xuaW1wb3J0IHtcbiAgICBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX0NPTE9SUElDS0VSLFxuICAgIER5bmFtaWNDb2xvclBpY2tlck1vZGVsXG59IGZyb20gXCIuLi9tb2RlbC9jb2xvcnBpY2tlci9keW5hbWljLWNvbG9ycGlja2VyLm1vZGVsXCI7XG5pbXBvcnQge1xuICAgIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfREFURVBJQ0tFUixcbiAgICBEeW5hbWljRGF0ZVBpY2tlck1vZGVsXG59IGZyb20gXCIuLi9tb2RlbC9kYXRlcGlja2VyL2R5bmFtaWMtZGF0ZXBpY2tlci5tb2RlbFwiO1xuaW1wb3J0IHsgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9FRElUT1IsIER5bmFtaWNFZGl0b3JNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9lZGl0b3IvZHluYW1pYy1lZGl0b3IubW9kZWxcIjtcbmltcG9ydCB7XG4gICAgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9GSUxFX1VQTE9BRCxcbiAgICBEeW5hbWljRmlsZVVwbG9hZE1vZGVsXG59IGZyb20gXCIuLi9tb2RlbC9maWxlLXVwbG9hZC9keW5hbWljLWZpbGUtdXBsb2FkLm1vZGVsXCI7XG5pbXBvcnQgeyBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX0lOUFVULCBEeW5hbWljSW5wdXRNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9pbnB1dC9keW5hbWljLWlucHV0Lm1vZGVsXCI7XG5pbXBvcnQge1xuICAgIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfUkFESU9fR1JPVVAsXG4gICAgRHluYW1pY1JhZGlvR3JvdXBNb2RlbFxufSBmcm9tIFwiLi4vbW9kZWwvcmFkaW8vZHluYW1pYy1yYWRpby1ncm91cC5tb2RlbFwiO1xuaW1wb3J0IHsgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9SQVRJTkcsIER5bmFtaWNSYXRpbmdNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9yYXRpbmcvZHluYW1pYy1yYXRpbmcubW9kZWxcIjtcbmltcG9ydCB7IERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfU0VMRUNULCBEeW5hbWljU2VsZWN0TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvc2VsZWN0L2R5bmFtaWMtc2VsZWN0Lm1vZGVsXCI7XG5pbXBvcnQgeyBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX1NMSURFUiwgRHluYW1pY1NsaWRlck1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL3NsaWRlci9keW5hbWljLXNsaWRlci5tb2RlbFwiO1xuaW1wb3J0IHsgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9TV0lUQ0gsIER5bmFtaWNTd2l0Y2hNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9zd2l0Y2gvZHluYW1pYy1zd2l0Y2gubW9kZWxcIjtcbmltcG9ydCB7IERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfVEVYVEFSRUEsIER5bmFtaWNUZXh0QXJlYU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL3RleHRhcmVhL2R5bmFtaWMtdGV4dGFyZWEubW9kZWxcIjtcbmltcG9ydCB7XG4gICAgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9USU1FUElDS0VSLFxuICAgIER5bmFtaWNUaW1lUGlja2VyTW9kZWxcbn0gZnJvbSBcIi4uL21vZGVsL3RpbWVwaWNrZXIvZHluYW1pYy10aW1lcGlja2VyLm1vZGVsXCI7XG5pbXBvcnQgeyBEeW5hbWljRm9ybVZhbGlkYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vZHluYW1pYy1mb3JtLXZhbGlkYXRpb24uc2VydmljZVwiO1xuaW1wb3J0IHsgRHluYW1pY0Zvcm1Nb2RlbCwgRHluYW1pY1VuaW9uRm9ybU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL2R5bmFtaWMtZm9ybS5tb2RlbFwiO1xuaW1wb3J0IHsgRHluYW1pY1BhdGhhYmxlIH0gZnJvbSBcIi4uL21vZGVsL21pc2MvZHluYW1pYy1mb3JtLWNvbnRyb2wtcGF0aC5tb2RlbFwiO1xuaW1wb3J0IHsgRHluYW1pY0Zvcm1Ib29rLCBEeW5hbWljVmFsaWRhdG9yc0NvbmZpZyB9IGZyb20gXCIuLi9tb2RlbC9taXNjL2R5bmFtaWMtZm9ybS1jb250cm9sLXZhbGlkYXRpb24ubW9kZWxcIjtcbmltcG9ydCB7IHBhcnNlUmV2aXZlciB9IGZyb20gXCIuLi91dGlscy9qc29uLnV0aWxzXCI7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gXCIuLi91dGlscy9jb3JlLnV0aWxzXCI7XG5pbXBvcnQgeyBEeW5hbWljRm9ybUNvbXBvbmVudCB9IGZyb20gXCIuLi9jb21wb25lbnQvZHluYW1pYy1mb3JtLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgRHluYW1pY0Zvcm1Db21wb25lbnRTZXJ2aWNlIH0gZnJvbSBcIi4vZHluYW1pYy1mb3JtLWNvbXBvbmVudC5zZXJ2aWNlXCI7XG5cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiBcInJvb3RcIlxufSlcbmV4cG9ydCBjbGFzcyBEeW5hbWljRm9ybVNlcnZpY2Uge1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb21wb25lbnRTZXJ2aWNlOiBEeW5hbWljRm9ybUNvbXBvbmVudFNlcnZpY2UsIHByaXZhdGUgdmFsaWRhdGlvblNlcnZpY2U6IER5bmFtaWNGb3JtVmFsaWRhdGlvblNlcnZpY2UpIHtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZUFic3RyYWN0Q29udHJvbE9wdGlvbnModmFsaWRhdG9yc0NvbmZpZzogRHluYW1pY1ZhbGlkYXRvcnNDb25maWcgfCBudWxsID0gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXN5bmNWYWxpZGF0b3JzQ29uZmlnOiBEeW5hbWljVmFsaWRhdG9yc0NvbmZpZyB8IG51bGwgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVPbjogRHluYW1pY0Zvcm1Ib29rIHwgbnVsbCA9IG51bGwpOiBBYnN0cmFjdENvbnRyb2xPcHRpb25zIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGFzeW5jVmFsaWRhdG9yczogYXN5bmNWYWxpZGF0b3JzQ29uZmlnICE9PSBudWxsID8gdGhpcy52YWxpZGF0aW9uU2VydmljZS5nZXRBc3luY1ZhbGlkYXRvcnMoYXN5bmNWYWxpZGF0b3JzQ29uZmlnKSA6IG51bGwsXG4gICAgICAgICAgICB2YWxpZGF0b3JzOiB2YWxpZGF0b3JzQ29uZmlnICE9PSBudWxsID8gdGhpcy52YWxpZGF0aW9uU2VydmljZS5nZXRWYWxpZGF0b3JzKHZhbGlkYXRvcnNDb25maWcpIDogbnVsbCxcbiAgICAgICAgICAgIHVwZGF0ZU9uOiB1cGRhdGVPbiAhPT0gbnVsbCAmJiB0aGlzLnZhbGlkYXRpb25TZXJ2aWNlLmlzRm9ybUhvb2sodXBkYXRlT24pID8gdXBkYXRlT24gOiBEeW5hbWljRm9ybUhvb2suQ2hhbmdlXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgY3JlYXRlRm9ybUFycmF5KGZvcm1BcnJheU1vZGVsOiBEeW5hbWljRm9ybUFycmF5TW9kZWwpOiBVbnR5cGVkRm9ybUFycmF5IHtcbiAgICAgICAgY29uc3QgY29udHJvbHM6IEFic3RyYWN0Q29udHJvbFtdID0gW107XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmNyZWF0ZUFic3RyYWN0Q29udHJvbE9wdGlvbnMoZm9ybUFycmF5TW9kZWwudmFsaWRhdG9ycywgZm9ybUFycmF5TW9kZWwuYXN5bmNWYWxpZGF0b3JzLFxuICAgICAgICAgICAgZm9ybUFycmF5TW9kZWwudXBkYXRlT24pO1xuXG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBmb3JtQXJyYXlNb2RlbC5zaXplOyBpbmRleCsrKSB7XG4gICAgICAgICAgICBjb25zdCBncm91cE1vZGVsID0gZm9ybUFycmF5TW9kZWwuZ2V0KGluZGV4KTtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwT3B0aW9ucyA9IHRoaXMuY3JlYXRlQWJzdHJhY3RDb250cm9sT3B0aW9ucyhmb3JtQXJyYXlNb2RlbC5ncm91cFZhbGlkYXRvcnMsXG4gICAgICAgICAgICAgICAgZm9ybUFycmF5TW9kZWwuZ3JvdXBBc3luY1ZhbGlkYXRvcnMsIGZvcm1BcnJheU1vZGVsLnVwZGF0ZU9uKTtcblxuICAgICAgICAgICAgY29udHJvbHMucHVzaCh0aGlzLmNyZWF0ZUZvcm1Hcm91cChncm91cE1vZGVsLmdyb3VwLCBncm91cE9wdGlvbnMsIGdyb3VwTW9kZWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgVW50eXBlZEZvcm1BcnJheShjb250cm9scywgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgY3JlYXRlRm9ybUdyb3VwKGZvcm1Nb2RlbDogRHluYW1pY0Zvcm1Nb2RlbCwgb3B0aW9uczogQWJzdHJhY3RDb250cm9sT3B0aW9ucyB8IG51bGwgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQ6IER5bmFtaWNQYXRoYWJsZSB8IG51bGwgPSBudWxsKTogVW50eXBlZEZvcm1Hcm91cCB7XG4gICAgICAgIGNvbnN0IGNvbnRyb2xzOiB7IFtjb250cm9sSWQ6IHN0cmluZ106IEFic3RyYWN0Q29udHJvbDsgfSA9IHt9O1xuXG4gICAgICAgIGZvcm1Nb2RlbC5mb3JFYWNoKG1vZGVsID0+IHtcbiAgICAgICAgICAgIG1vZGVsLnBhcmVudCA9IHBhcmVudDtcblxuICAgICAgICAgICAgc3dpdGNoIChtb2RlbC50eXBlKSB7XG5cbiAgICAgICAgICAgICAgICBjYXNlIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfQVJSQVk6XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzW21vZGVsLmlkXSA9IHRoaXMuY3JlYXRlRm9ybUFycmF5KG1vZGVsIGFzIER5bmFtaWNGb3JtQXJyYXlNb2RlbCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX0dST1VQOlxuICAgICAgICAgICAgICAgIGNhc2UgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9DSEVDS0JPWF9HUk9VUDpcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBNb2RlbCA9IG1vZGVsIGFzIER5bmFtaWNGb3JtR3JvdXBNb2RlbDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBPcHRpb25zID0gdGhpcy5jcmVhdGVBYnN0cmFjdENvbnRyb2xPcHRpb25zKGdyb3VwTW9kZWwudmFsaWRhdG9ycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwTW9kZWwuYXN5bmNWYWxpZGF0b3JzLCBncm91cE1vZGVsLnVwZGF0ZU9uKTtcblxuICAgICAgICAgICAgICAgICAgICBjb250cm9sc1ttb2RlbC5pZF0gPSB0aGlzLmNyZWF0ZUZvcm1Hcm91cChncm91cE1vZGVsLmdyb3VwLCBncm91cE9wdGlvbnMsIGdyb3VwTW9kZWwpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRyb2xNb2RlbCA9IG1vZGVsIGFzIER5bmFtaWNGb3JtVmFsdWVDb250cm9sTW9kZWw8YW55PjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udHJvbFN0YXRlID0ge3ZhbHVlOiBjb250cm9sTW9kZWwudmFsdWUsIGRpc2FibGVkOiBjb250cm9sTW9kZWwuZGlzYWJsZWR9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250cm9sT3B0aW9ucyA9IHRoaXMuY3JlYXRlQWJzdHJhY3RDb250cm9sT3B0aW9ucyhjb250cm9sTW9kZWwudmFsaWRhdG9ycyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xNb2RlbC5hc3luY1ZhbGlkYXRvcnMsIGNvbnRyb2xNb2RlbC51cGRhdGVPbik7XG5cbiAgICAgICAgICAgICAgICAgICAgY29udHJvbHNbbW9kZWwuaWRdID0gbmV3IFVudHlwZWRGb3JtQ29udHJvbChjb250cm9sU3RhdGUsIGNvbnRyb2xPcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBVbnR5cGVkRm9ybUdyb3VwKGNvbnRyb2xzLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBnZXRQYXRoU2VnbWVudChtb2RlbDogRHluYW1pY1BhdGhhYmxlKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIG1vZGVsIGluc3RhbmNlb2YgRHluYW1pY0Zvcm1BcnJheUdyb3VwTW9kZWwgPyBtb2RlbC5pbmRleC50b1N0cmluZygpIDogKG1vZGVsIGFzIER5bmFtaWNGb3JtQ29udHJvbE1vZGVsKS5pZDtcbiAgICB9XG5cbiAgICBnZXRQYXRoKG1vZGVsOiBEeW5hbWljUGF0aGFibGUsIGpvaW46IGJvb2xlYW4gPSBmYWxzZSk6IHN0cmluZ1tdIHwgc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcGF0aCA9IFt0aGlzLmdldFBhdGhTZWdtZW50KG1vZGVsKV07XG4gICAgICAgIGxldCBwYXJlbnQgPSBtb2RlbC5wYXJlbnQ7XG5cbiAgICAgICAgd2hpbGUgKHBhcmVudCkge1xuICAgICAgICAgICAgcGF0aC51bnNoaWZ0KHRoaXMuZ2V0UGF0aFNlZ21lbnQocGFyZW50KSk7XG4gICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGpvaW4gPyBwYXRoLmpvaW4oXCIuXCIpIDogcGF0aDtcbiAgICB9XG5cbiAgICBhZGRGb3JtR3JvdXBDb250cm9sKGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cCwgZm9ybU1vZGVsOiBEeW5hbWljVW5pb25Gb3JtTW9kZWwsIC4uLm1vZGVsczogRHluYW1pY0Zvcm1Nb2RlbCk6IHZvaWQge1xuICAgICAgICBpZiAoZm9ybU1vZGVsIGluc3RhbmNlb2YgRHluYW1pY0Zvcm1Hcm91cE1vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLmluc2VydEZvcm1Hcm91cENvbnRyb2woZm9ybU1vZGVsLnNpemUoKSwgZm9ybUdyb3VwLCBmb3JtTW9kZWwsIC4uLm1vZGVscyk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG1vZGVsID0gZm9ybU1vZGVsIGFzIER5bmFtaWNGb3JtTW9kZWw7XG4gICAgICAgICAgICB0aGlzLmluc2VydEZvcm1Hcm91cENvbnRyb2wobW9kZWwubGVuZ3RoLCBmb3JtR3JvdXAsIG1vZGVsLCAuLi5tb2RlbHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbW92ZUZvcm1Hcm91cENvbnRyb2woaW5kZXg6IG51bWJlciwgc3RlcDogbnVtYmVyLCBmb3JtTW9kZWw6IER5bmFtaWNVbmlvbkZvcm1Nb2RlbCk6IHZvaWQge1xuICAgICAgICBpZiAoZm9ybU1vZGVsIGluc3RhbmNlb2YgRHluYW1pY0Zvcm1Hcm91cE1vZGVsKSB7XG4gICAgICAgICAgICBmb3JtTW9kZWwubW92ZShpbmRleCwgc3RlcCk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG1vZGVsID0gZm9ybU1vZGVsIGFzIER5bmFtaWNGb3JtTW9kZWw7XG4gICAgICAgICAgICBtb2RlbC5zcGxpY2UoaW5kZXggKyBzdGVwLCAwLCAuLi5tb2RlbC5zcGxpY2UoaW5kZXgsIDEpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGluc2VydEZvcm1Hcm91cENvbnRyb2woaW5kZXg6IG51bWJlciwgZm9ybUdyb3VwOiBVbnR5cGVkRm9ybUdyb3VwLCBmb3JtTW9kZWw6IER5bmFtaWNVbmlvbkZvcm1Nb2RlbCwgLi4ubW9kZWxzOiBEeW5hbWljRm9ybU1vZGVsKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHBhcmVudCA9IGZvcm1Nb2RlbCBpbnN0YW5jZW9mIER5bmFtaWNGb3JtR3JvdXBNb2RlbCA/IGZvcm1Nb2RlbCA6IG51bGw7XG4gICAgICAgIGNvbnN0IGNvbnRyb2xzID0gdGhpcy5jcmVhdGVGb3JtR3JvdXAobW9kZWxzLCBudWxsLCBwYXJlbnQpLmNvbnRyb2xzO1xuXG4gICAgICAgIE9iamVjdC5rZXlzKGNvbnRyb2xzKS5mb3JFYWNoKChjb250cm9sTmFtZSwgaWR4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb250cm9sTW9kZWwgPSBtb2RlbHNbaWR4XTtcblxuICAgICAgICAgICAgaWYgKGZvcm1Nb2RlbCBpbnN0YW5jZW9mIER5bmFtaWNGb3JtR3JvdXBNb2RlbCkge1xuICAgICAgICAgICAgICAgIGZvcm1Nb2RlbC5pbnNlcnQoaW5kZXgsIGNvbnRyb2xNb2RlbCk7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgKGZvcm1Nb2RlbCBhcyBEeW5hbWljRm9ybU1vZGVsKS5zcGxpY2UoaW5kZXgsIDAsIGNvbnRyb2xNb2RlbCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcm1Hcm91cC5hZGRDb250cm9sKGNvbnRyb2xOYW1lLCBjb250cm9sc1tjb250cm9sTmFtZV0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICByZW1vdmVGb3JtR3JvdXBDb250cm9sKGluZGV4OiBudW1iZXIsIGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cCwgZm9ybU1vZGVsOiBEeW5hbWljVW5pb25Gb3JtTW9kZWwpOiB2b2lkIHtcbiAgICAgICAgaWYgKGZvcm1Nb2RlbCBpbnN0YW5jZW9mIER5bmFtaWNGb3JtR3JvdXBNb2RlbCkge1xuICAgICAgICAgICAgZm9ybUdyb3VwLnJlbW92ZUNvbnRyb2woZm9ybU1vZGVsLmdldChpbmRleCkuaWQpO1xuICAgICAgICAgICAgZm9ybU1vZGVsLnJlbW92ZShpbmRleCk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1Hcm91cC5yZW1vdmVDb250cm9sKGZvcm1Nb2RlbFtpbmRleF0uaWQpO1xuICAgICAgICAgICAgKGZvcm1Nb2RlbCBhcyBEeW5hbWljRm9ybU1vZGVsKS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYWRkRm9ybUFycmF5R3JvdXAoZm9ybUFycmF5OiBVbnR5cGVkRm9ybUFycmF5LCBmb3JtQXJyYXlNb2RlbDogRHluYW1pY0Zvcm1BcnJheU1vZGVsKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGdyb3VwTW9kZWwgPSBmb3JtQXJyYXlNb2RlbC5hZGRHcm91cCgpO1xuICAgICAgICBmb3JtQXJyYXkucHVzaCh0aGlzLmNyZWF0ZUZvcm1Hcm91cChncm91cE1vZGVsLmdyb3VwLCBudWxsLCBncm91cE1vZGVsKSk7XG4gICAgfVxuXG4gICAgaW5zZXJ0Rm9ybUFycmF5R3JvdXAoaW5kZXg6IG51bWJlciwgZm9ybUFycmF5OiBVbnR5cGVkRm9ybUFycmF5LCBmb3JtQXJyYXlNb2RlbDogRHluYW1pY0Zvcm1BcnJheU1vZGVsKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGdyb3VwTW9kZWwgPSBmb3JtQXJyYXlNb2RlbC5pbnNlcnRHcm91cChpbmRleCk7XG4gICAgICAgIGZvcm1BcnJheS5pbnNlcnQoaW5kZXgsIHRoaXMuY3JlYXRlRm9ybUdyb3VwKGdyb3VwTW9kZWwuZ3JvdXAsIG51bGwsIGdyb3VwTW9kZWwpKTtcbiAgICB9XG5cbiAgICBtb3ZlRm9ybUFycmF5R3JvdXAoaW5kZXg6IG51bWJlciwgc3RlcDogbnVtYmVyLCBmb3JtQXJyYXk6IFVudHlwZWRGb3JtQXJyYXksIGZvcm1BcnJheU1vZGVsOiBEeW5hbWljRm9ybUFycmF5TW9kZWwpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbmV3SW5kZXggPSBpbmRleCArIHN0ZXA7XG4gICAgICAgIGNvbnN0IG1vdmVVcCA9IHN0ZXAgPj0gMDtcblxuICAgICAgICBpZiAoKGluZGV4ID49IDAgJiYgaW5kZXggPCBmb3JtQXJyYXlNb2RlbC5zaXplKSAmJiAobmV3SW5kZXggPj0gMCAmJiBuZXdJbmRleCA8IGZvcm1BcnJheU1vZGVsLnNpemUpKSB7XG4gICAgICAgICAgICBjb25zdCBtb3ZpbmdHcm91cHM6IEFic3RyYWN0Q29udHJvbFtdID0gW107XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBtb3ZlVXAgPyBpbmRleCA6IG5ld0luZGV4OyBpIDw9IChtb3ZlVXAgPyBuZXdJbmRleCA6IGluZGV4KTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbW92aW5nR3JvdXBzLnB1c2goZm9ybUFycmF5LmF0KGkpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbW92aW5nR3JvdXBzLmZvckVhY2goKGZvcm1Db250cm9sLCBpZHgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgcG9zaXRpb247XG5cbiAgICAgICAgICAgICAgICBpZiAobW92ZVVwKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gaWR4ID09PSAwID8gbmV3SW5kZXggOiBpbmRleCArIGlkeCAtIDE7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IGlkeCA9PT0gbW92aW5nR3JvdXBzLmxlbmd0aCAtIDEgPyBuZXdJbmRleCA6IG5ld0luZGV4ICsgaWR4ICsgMTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3JtQXJyYXkuc2V0Q29udHJvbChwb3NpdGlvbiwgZm9ybUNvbnRyb2wpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGZvcm1BcnJheU1vZGVsLm1vdmVHcm91cChpbmRleCwgc3RlcCk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZm9ybSBhcnJheSBncm91cCBjYW5ub3QgYmUgbW92ZWQgZHVlIHRvIGluZGV4IG9yIG5ldyBpbmRleCBiZWluZyBvdXQgb2YgYm91bmRzYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZW1vdmVGb3JtQXJyYXlHcm91cChpbmRleDogbnVtYmVyLCBmb3JtQXJyYXk6IFVudHlwZWRGb3JtQXJyYXksIGZvcm1BcnJheU1vZGVsOiBEeW5hbWljRm9ybUFycmF5TW9kZWwpOiB2b2lkIHtcbiAgICAgICAgZm9ybUFycmF5LnJlbW92ZUF0KGluZGV4KTtcbiAgICAgICAgZm9ybUFycmF5TW9kZWwucmVtb3ZlR3JvdXAoaW5kZXgpO1xuICAgIH1cblxuICAgIGNsZWFyRm9ybUFycmF5KGZvcm1BcnJheTogVW50eXBlZEZvcm1BcnJheSwgZm9ybUFycmF5TW9kZWw6IER5bmFtaWNGb3JtQXJyYXlNb2RlbCk6IHZvaWQge1xuICAgICAgICBmb3JtQXJyYXkuY2xlYXIoKTtcbiAgICAgICAgZm9ybUFycmF5TW9kZWwuY2xlYXIoKTtcbiAgICB9XG5cbiAgICBmaW5kQnlJZChpZDogc3RyaW5nLCBmb3JtTW9kZWw6IER5bmFtaWNGb3JtTW9kZWwpOiBEeW5hbWljRm9ybUNvbnRyb2xNb2RlbCB8IG51bGwge1xuICAgICAgICBjb25zdCBmaW5kQnlJZEZuID0gKG1vZGVsSWQ6IHN0cmluZywgZ3JvdXBNb2RlbDogRHluYW1pY0Zvcm1Nb2RlbCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBjb250cm9sTW9kZWwgb2YgZ3JvdXBNb2RlbCkge1xuXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2xNb2RlbC5pZCA9PT0gbW9kZWxJZCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBjb250cm9sTW9kZWw7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjb250cm9sTW9kZWwgaW5zdGFuY2VvZiBEeW5hbWljRm9ybUdyb3VwTW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZmluZEJ5SWRGbihtb2RlbElkLCAoY29udHJvbE1vZGVsIGFzIER5bmFtaWNGb3JtR3JvdXBNb2RlbCkuZ3JvdXApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICAgICAgZmluZEJ5SWRGbihpZCwgZm9ybU1vZGVsKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGZpbmRNb2RlbEJ5SWQ8VCBleHRlbmRzIER5bmFtaWNGb3JtQ29udHJvbE1vZGVsPihpZDogc3RyaW5nLCBmb3JtTW9kZWw6IER5bmFtaWNGb3JtTW9kZWwpOiBUIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpbmRCeUlkKGlkLCBmb3JtTW9kZWwpIGFzIFQ7XG4gICAgfVxuXG4gICAgZmluZENvbnRyb2xCeU1vZGVsPFQgZXh0ZW5kcyBBYnN0cmFjdENvbnRyb2w+KG1vZGVsOiBEeW5hbWljRm9ybUNvbnRyb2xNb2RlbCwgZ3JvdXA6IFVudHlwZWRGb3JtR3JvdXApOiBUIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiBncm91cC5yb290LmdldCh0aGlzLmdldFBhdGgobW9kZWwsIHRydWUpKSBhcyBUO1xuICAgIH1cblxuICAgIGRldGVjdENoYW5nZXMoZm9ybUNvbXBvbmVudD86IER5bmFtaWNGb3JtQ29tcG9uZW50KTogdm9pZCB7XG4gICAgICAgIGlmIChmb3JtQ29tcG9uZW50IGluc3RhbmNlb2YgRHluYW1pY0Zvcm1Db21wb25lbnQpIHtcbiAgICAgICAgICAgIGZvcm1Db21wb25lbnQubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICBmb3JtQ29tcG9uZW50LmRldGVjdENoYW5nZXMoKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yIChjb25zdCBmb3JtIG9mIHRoaXMuY29tcG9uZW50U2VydmljZS5nZXRGb3JtcygpKSB7XG4gICAgICAgICAgICAgICAgZm9ybS5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICAgICAgICBmb3JtLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZyb21KU09OKGpzb246IHN0cmluZyB8IG9iamVjdFtdKTogRHluYW1pY0Zvcm1Nb2RlbCB8IG5ldmVyIHtcbiAgICAgICAgY29uc3QgZm9ybU1vZGVsSlNPTiA9IGlzU3RyaW5nKGpzb24pID8gSlNPTi5wYXJzZShqc29uLCBwYXJzZVJldml2ZXIpIDoganNvbjtcbiAgICAgICAgY29uc3QgZm9ybU1vZGVsOiBEeW5hbWljRm9ybU1vZGVsID0gW107XG5cbiAgICAgICAgZm9ybU1vZGVsSlNPTi5mb3JFYWNoKChtb2RlbDogYW55KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBsYXlvdXQgPSBtb2RlbC5sYXlvdXQgPz8gbnVsbDtcblxuICAgICAgICAgICAgc3dpdGNoIChtb2RlbC50eXBlKSB7XG5cbiAgICAgICAgICAgICAgICBjYXNlIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfQVJSQVk6XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvcm1BcnJheU1vZGVsID0gbW9kZWwgYXMgRHluYW1pY0Zvcm1BcnJheU1vZGVsO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZvcm1BcnJheU1vZGVsLmdyb3VwcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1BcnJheU1vZGVsLmdyb3Vwcy5mb3JFYWNoKChncm91cE1vZGVsOiBEeW5hbWljRm9ybUFycmF5R3JvdXBNb2RlbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwTW9kZWwuZ3JvdXAgPSB0aGlzLmZyb21KU09OKGdyb3VwTW9kZWwuZ3JvdXApIGFzIER5bmFtaWNGb3JtTW9kZWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGZvcm1BcnJheU1vZGVsLmdyb3VwRmFjdG9yeSA9ICgpID0+IHRoaXMuZnJvbUpTT04oZm9ybUFycmF5TW9kZWwuZ3JvdXBQcm90b3R5cGUpO1xuXG4gICAgICAgICAgICAgICAgICAgIGZvcm1Nb2RlbC5wdXNoKG5ldyBEeW5hbWljRm9ybUFycmF5TW9kZWwobW9kZWwsIGxheW91dCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9DSEVDS0JPWDpcbiAgICAgICAgICAgICAgICAgICAgZm9ybU1vZGVsLnB1c2gobmV3IER5bmFtaWNDaGVja2JveE1vZGVsKG1vZGVsLCBsYXlvdXQpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfQ0hFQ0tCT1hfR1JPVVA6XG4gICAgICAgICAgICAgICAgICAgIG1vZGVsLmdyb3VwID0gdGhpcy5mcm9tSlNPTihtb2RlbC5ncm91cCkgYXMgRHluYW1pY0NoZWNrYm94TW9kZWxbXTtcbiAgICAgICAgICAgICAgICAgICAgZm9ybU1vZGVsLnB1c2gobmV3IER5bmFtaWNDaGVja2JveEdyb3VwTW9kZWwobW9kZWwsIGxheW91dCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9DT0xPUlBJQ0tFUjpcbiAgICAgICAgICAgICAgICAgICAgZm9ybU1vZGVsLnB1c2gobmV3IER5bmFtaWNDb2xvclBpY2tlck1vZGVsKG1vZGVsLCBsYXlvdXQpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfREFURVBJQ0tFUjpcbiAgICAgICAgICAgICAgICAgICAgZm9ybU1vZGVsLnB1c2gobmV3IER5bmFtaWNEYXRlUGlja2VyTW9kZWwobW9kZWwsIGxheW91dCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9FRElUT1I6XG4gICAgICAgICAgICAgICAgICAgIGZvcm1Nb2RlbC5wdXNoKG5ldyBEeW5hbWljRWRpdG9yTW9kZWwobW9kZWwsIGxheW91dCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgRFlOQU1JQ19GT1JNX0NPTlRST0xfVFlQRV9GSUxFX1VQTE9BRDpcbiAgICAgICAgICAgICAgICAgICAgbW9kZWwudmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBmb3JtTW9kZWwucHVzaChuZXcgRHluYW1pY0ZpbGVVcGxvYWRNb2RlbChtb2RlbCwgbGF5b3V0KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX0dST1VQOlxuICAgICAgICAgICAgICAgICAgICBtb2RlbC5ncm91cCA9IHRoaXMuZnJvbUpTT04obW9kZWwuZ3JvdXApO1xuICAgICAgICAgICAgICAgICAgICBmb3JtTW9kZWwucHVzaChuZXcgRHluYW1pY0Zvcm1Hcm91cE1vZGVsKG1vZGVsLCBsYXlvdXQpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlIERZTkFNSUNfRk9STV9DT05UUk9MX1RZUEVfSU5QVVQ6XG4gICAgICAgICAgICAgICAgICAgIGZvcm1Nb2RlbC5wdXNoKG5ldyBEeW5hbWljSW5wdXRNb2RlbChtb2RlbCwgbGF5b3V0KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX1JBRElPX0dST1VQOlxuICAgICAgICAgICAgICAgICAgICBmb3JtTW9kZWwucHVzaChuZXcgRHluYW1pY1JhZGlvR3JvdXBNb2RlbChtb2RlbCwgbGF5b3V0KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX1JBVElORzpcbiAgICAgICAgICAgICAgICAgICAgZm9ybU1vZGVsLnB1c2gobmV3IER5bmFtaWNSYXRpbmdNb2RlbChtb2RlbCwgbGF5b3V0KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBEWU5BTUlDX0ZPUk1fQ09OVFJPTF9UWVBFX1NFTEVDVDpcbiAgICAgICAgICAgICAgICAgICAgZm9ybU1vZGVsLnB1c2gobmV3IER5bmFtaWNTZWxlY3RNb2RlbChtb2RlbCwgbGF5b3V