@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
273 lines • 41.4 kB
JavaScript
import { FormArray, FormGroup } from '@angular/forms';
import { LogLevel } from '@microsoft/windows-admin-center-sdk/core/diagnostics/log-level';
import { Logging } from '@microsoft/windows-admin-center-sdk/core/diagnostics/logging';
import { debounceTime, map, mergeMap, take } from 'rxjs/operators';
/**
* A base class for an Angular component containing a form.
*
* @classdesc A base class for an Angular component containing a form that is pre-populated with fetched data.
* The deriving class should call init() when setup is complete (sometime after calling super()) to begin the fetch
* and initialize the form.
*
* @version 1.0.0
*/
export class BasePropertiesForm {
/**
* Initializes a new instance of the BasePropertiesForm class.
*
* @param [loggingSource] - The source of log messages.
*/
constructor(loggingSource = 'BasePropertiesForm', appContextService) {
this.loggingSource = loggingSource;
this.appContextService = appContextService;
this.confirmationStrings = MsftSme.getStrings().MsftSmeShell.Angular.Form.ConfirmationDialog;
/**
* Indicates data is being fetched.
*/
this.loading = true;
}
/**
* Gets the current value of the form.
*/
get formCurrentValue() {
return this.form.value;
}
/**
* Discards the current form edits.
*/
onDiscard() {
// TODO: The empty form should be created synchronously so angular
// can bind to it. The values can be updated once the real data is available
this.formData = this.createFormDataFromDataModel();
this.resetForm();
}
/**
* Saves the content of the form. The newest version of data for the form
* will be fetched before performing the save operation.
*/
onSave() {
if (this.saving) {
return;
}
this.saving = true;
MsftSme.deepAssign(this.formData, this.form.value);
// Move disable after deepAssign since once disable form.value becomes empty
this.form.disable();
let updatedModel;
this.fetchData()
.pipe(mergeMap((freshModel) => {
this.formData.applyUpdatesToModel(freshModel);
updatedModel = freshModel;
return this.saveForm(freshModel);
}), take(1)).subscribe({
next: (freshModel) => {
this.form.enable();
this.saving = false;
if (freshModel) {
this.dataModel = freshModel;
}
else {
this.dataModel = updatedModel;
}
this.formData = this.createFormDataFromDataModel();
this.resetForm();
this.onSaveSuccess();
},
error: (error) => {
this.saving = false;
this.form.enable();
this.onSaveError(error);
}
});
}
canDeactivate(component, route, state) {
if (this.appContextService && this.form && this.form.dirty) {
return this.appContextService.frame.showDialogConfirmation(this.confirmContinueEditingDialogOptions(this.form, null))
.pipe(map((result) => {
// The default is to continue editing
const continueNavigation = !result.confirmed;
if (continueNavigation) {
this.form.reset();
}
return continueNavigation;
}));
}
return true;
}
confirmContinueEditingDialogOptions(dirtyForm, allForms) {
return {
cancelButtonText: this.confirmationStrings.unsavedChangesCancelText,
confirmButtonText: this.confirmationStrings.unsavedChangesConfirmText,
message: this.confirmationStrings.unsavedChangesMessage,
title: this.confirmationStrings.unsavedChangesTitle
};
}
/**
* The method to initialize the form with data.
*/
init() {
this.loading = true;
this.fetchData().pipe(take(1)).subscribe({
next: (data) => {
this.dataModel = data;
this.resetFormData();
this.initializeValidation();
},
error: (error) => {
this.onFetchError(error);
this.form.disable();
// TODO: Have a mechanism to refresh the data
},
complete: () => {
this.loading = false;
}
});
}
/**
* Resets the form and displays the original values while marking the form as pristine and untouched.
*/
resetForm() {
this.form.reset(this.formData);
}
/**
* Processes a control for validation.
*
* @param control - The control to validate.
* @param formErrors - The errors of the form.
* @param validationMessages - The validation messages of the form.
* @param formErrorsIndex - The form errors index.
*/
processControlForValidation(control, formErrors, validationMessages, formErrorsIndex) {
const isFormGroup = control instanceof FormGroup;
let isFormArray = false;
if (!isFormGroup) {
isFormArray = control instanceof FormArray;
}
if (isFormGroup) {
// iterate
this.updateFormErrors(control, formErrors[formErrorsIndex], (validationMessages));
}
else if (isFormArray) {
this.updateFormErrorsForArray(control, formErrors[formErrorsIndex], (validationMessages));
}
else {
// for controls, clear the previous error messages
formErrors[formErrorsIndex] = '';
}
if (!control.valid && control.dirty) {
if (isFormGroup || isFormArray) {
// form groups and arrays are processed outside this for loop once all children have been processed
return;
}
const messages = validationMessages;
if (!messages) {
return;
}
for (const key in control.errors) {
if (control.errors.hasOwnProperty(key)) {
let message = messages[key];
if (MsftSme.isFunction(message)) {
message = message();
}
formErrors[formErrorsIndex] = message;
// Only one error message per control
break;
}
}
}
}
/**
* Updates the form errors.
*
* @param form - The form to update.
* @param formErrors - The form errors to apply.
* @param validationMessages - The validation messages to apply.
*/
updateFormErrors(form, formErrors, validationMessages) {
for (const field in formErrors) {
if (formErrors.hasOwnProperty(field)) {
const control = form.get(field);
if (control) {
this.processControlForValidation(control, formErrors, validationMessages.controls[field], field);
}
}
}
if (!form.valid && validationMessages.formGroup) {
validationMessages.formGroup(form.errors);
}
}
/**
* Updates the form array errors.
*
* @param formArray - The form array to update.
* @param formErrors - The form errors to apply.
* @param validationMessages - The validation messages to apply.
*/
updateFormErrorsForArray(formArray, formErrors, validationMessages) {
let processItems = true;
if (!Array.isArray(formErrors)) {
// form errors for form arrays should be an array of logSource
processItems = false;
Logging.log({
source: this.loggingSource,
level: LogLevel.Warning,
message: `Unexpected form errors type for form array. ` +
`It should be an array but it is ${typeof formErrors}. Skipping validation`
});
}
const errorsArray = formErrors;
if (errorsArray.length !== formArray.length) {
processItems = false;
Logging.log({
source: this.loggingSource,
level: LogLevel.Warning,
message: `Unexpected count of errors type for form array. ` +
`It should be ${formArray.length} but it is ${errorsArray.length}. Skipping validation`
});
}
if (processItems) {
for (let i = 0; i < formArray.length; i++) {
const stringIndex = '' + i;
const control = formArray.get(stringIndex);
if (control) {
this.processControlForValidation(control, formErrors, validationMessages, stringIndex);
}
}
}
if (!formArray.valid && validationMessages.formArray) {
validationMessages.formArray(formArray.errors);
}
}
/**
* Initializes the form validation.
*/
initializeValidation() {
this.form.valueChanges
.pipe(debounceTime(500))
.subscribe((data) => {
this.onValueChanged(data);
});
this.onValueChanged();
}
/**
* The method to call when the form value changes.
*/
onValueChanged(data) {
// TODO: Validate that the data? paramter was not needed
if (!this.form) {
return;
}
const form = this.form;
this.updateFormErrors(form, this.formErrors, this.validationMessages);
}
/**
* Resets the data backing the form without updating the display.
*
* @param existingForm - The existing form group of the display.
*/
resetFormData(existingForm) {
this.formData = this.createFormDataFromDataModel();
this.form = this.createForm();
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1wcm9wZXJ0aWVzLWZvcm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9kYXRhL2Zvcm1zL2Jhc2UtcHJvcGVydGllcy1mb3JtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBbUIsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXZFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQztBQUMxRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sOERBQThELENBQUM7QUFFdkYsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBbUVuRTs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sT0FBZ0Isa0JBQWtCO0lBNEJwQzs7OztPQUlHO0lBQ0gsWUFBc0IsZ0JBQXdCLG9CQUFvQixFQUFZLGlCQUFxQztRQUE3RixrQkFBYSxHQUFiLGFBQWEsQ0FBK0I7UUFBWSxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW9CO1FBaEMzRyx3QkFBbUIsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFXLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUM7UUFPekc7O1dBRUc7UUFDSSxZQUFPLEdBQUcsSUFBSSxDQUFDO0lBc0JpRyxDQUFDO0lBNER4SDs7T0FFRztJQUNILElBQWMsZ0JBQWdCO1FBQzFCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDM0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksU0FBUztRQUNaLGtFQUFrRTtRQUNsRSw0RUFBNEU7UUFFNUUsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztRQUNuRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7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QUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGFBQWEsQ0FBQyxZQUF3QjtRQUMxQyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ2xDLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUFycmF5LCBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIFJvdXRlclN0YXRlU25hcHNob3QgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xyXG5pbXBvcnQgeyBMb2dMZXZlbCB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvZGlhZ25vc3RpY3MvbG9nLWxldmVsJztcclxuaW1wb3J0IHsgTG9nZ2luZyB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvZGlhZ25vc3RpY3MvbG9nZ2luZyc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBtYXAsIG1lcmdlTWFwLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBDb25maXJtYXRpb25EaWFsb2dPcHRpb25zIH0gZnJvbSAnLi4vLi4vY29udHJvbHMvZGlhbG9nL2NvbmZpcm1hdGlvbi1kaWFsb2cvY29uZmlybWF0aW9uLWRpYWxvZy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBDYW5Db21wb25lbnREZWFjdGl2YXRlIH0gZnJvbSAnLi4vLi4vY29udHJvbHMvc2V0dGluZ3Mvc2V0dGluZ3MtY2FuLWRlYWN0aXZhdGUtZ3VhcmQuc2VydmljZSc7XHJcbmltcG9ydCB7IFN0cmluZ3MgfSBmcm9tICcuLi8uLi9nZW5lcmF0ZWQvc3RyaW5ncyc7XHJcbmltcG9ydCB7IEFwcENvbnRleHRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZS9hcHAtY29udGV4dC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQmFzZUZvcm1EYXRhIH0gZnJvbSAnLi9iYXNlLWZvcm0tZGF0YSc7XHJcblxyXG4vKipcclxuICogVGhlIGludGVyZmFjZSBmb3IgZXhwb3NpbmcgZm9ybSBjb250cm9sIHZhbGlkYXRpb24gbWVzc2FnZXMuXHJcbiAqXHJcbiAqIEV4YW1wbGU6XHJcbiAqIHtcclxuICogICAgICBmb3JtQ29udHJvbEE6IHtcclxuICogICAgICAgICAgcmVxdWlyZWQ6ICdOYW1lIGZpZWxkIGNhbm5vdCBiZSBlbXB0eS4nLFxyXG4gKiAgICAgICAgICBtYXhMZW5ndGg6ICdOYW1lIGNhbm5vdCBiZSBncmVhdGVyIHRoYW4gMTAwIGNoYXJhY3RlcnMgbG9uZy4nXHJcbiAqICAgICAgICAgIC4uLlxyXG4gKiAgICAgIH0sXHJcbiAqICAgICAgZnJvbUdyb3VwQToge1xyXG4gKiAgICAgICAgICBmb3JtQ29udHJvbEFBOiB7XHJcbiAqICAgICAgICAgICAgICByZXF1aXJlZDogJ2NpdHkgcmVxdWlyZWQnLFxyXG4gKiAgICAgICAgICB9LFxyXG4gKiAgICAgICAgICBmb3JtQ29udHJvbEFCOiB7XHJcbiAqICAgICAgICAgICAgICB6aXBWYWxpZGF0b3I6ICdaSVAgY29kZSBzaG91bGQgYmUgNSBudW1iZXJzJ1xyXG4gKiAgICAgICAgICB9LFxyXG4gKiAgICAgICAgICBmb3JtR3JvdXA6IChlcnJvcjogYW55KSA9PiB7XHJcbiAqICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NGb3JtR3JvdXBBRXJyb3JzKGVycm9yKTsgLy8gWW91IG5lZWQgdG8gaW1wbGVtZW50IHRoaXMgZnVuY3Rpb24gaW4geW91ciBzdXBlciBjbGFzcy5cclxuICogICAgICAgICAgfVxyXG4gKiAgICAgIH0sXHJcbiAqICAgICAgZm9ybUFycmF5QToge1xyXG4gKiAgICAgICAgICBmb3JtQ29udHJvbEFBOiB7XHJcbiAqICAgICAgICAgICAgICAuLi5cclxuICogICAgICAgICAgfSxcclxuICogICAgICAgICAgZm9ybUNvbnRyb2xBQjoge1xyXG4gKiAgICAgICAgICAgICAgLi4uXHJcbiAqICAgICAgICAgIH0sXHJcbiAqICAgICAgICAgIGZvcm1BcnJheTogKGVycm9yOiBhbnkpID0+IHtcclxuICogICAgICAgICAgICAgIGlmIChlcnJvci5kdXBsaWNhdGVOYW1lKSB7XHJcbiAqICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzRHVwbGljYXRlTmFtZUVycm9yKGVycm9yKTtcclxuICogICAgICAgICAgICAgIH1cclxuICogICAgICAgICAgfVxyXG4gKiAgICAgIH1cclxuICogfVxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBGb3JtQ29udHJvbENvbnRhaW5lclZhbGlkYXRpb25NZXNzYWdlcyB7XHJcbiAgICBjb250cm9sczogeyBba2V5OiBzdHJpbmddOiAoeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCAoKCkgPT4gc3RyaW5nKSB9IHwgRm9ybUdyb3VwVmFsaWRhdGlvbk1lc3NhZ2VzIHwgRm9ybUFycmF5VmFsaWRhdGlvbk1lc3NhZ2VzKSB9O1xyXG59XHJcblxyXG4vKipcclxuICogVGhlIGludGVyZmFjZSBmb3IgZXhwb3NpbmcgdmFsaWRhdGlvbiBtZXNzYWdlcyBmb3IgZm9ybSBhcnJheXMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEZvcm1BcnJheVZhbGlkYXRpb25NZXNzYWdlcyBleHRlbmRzIEZvcm1Db250cm9sQ29udGFpbmVyVmFsaWRhdGlvbk1lc3NhZ2VzIHtcclxuICAgIC8qKlxyXG4gICAgICogQSBjYWxsYmFjayB0aGF0IHRha2VzIHRoZSBmb3JtIGFycmF5IHZhbGlkYXRpb24gZXJyb3JzIGFuZCBwcm9jZXNzZXMgdGhlbSBhY2NvcmRpbmdseS5cclxuICAgICAqL1xyXG4gICAgZm9ybUFycmF5PzogKGVycm9yOiBhbnkpID0+IHZvaWQ7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBUaGUgaW50ZXJmYWNlIGZvciBleHBvc2luZyB2YWxpZGF0aW9uIG1lc3NhZ2VzIGZvciBmb3JtIGdyb3Vwcy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRm9ybUdyb3VwVmFsaWRhdGlvbk1lc3NhZ2VzIGV4dGVuZHMgRm9ybUNvbnRyb2xDb250YWluZXJWYWxpZGF0aW9uTWVzc2FnZXMge1xyXG4gICAgLyoqXHJcbiAgICAgKiBBIGNhbGxiYWNrIHRoYXQgdGFrZXMgdGhlIGZvcm0gZ3JvdXAgdmFsaWRhdGlvbiBlcnJvcnMgYW5kIHByb2Nlc3NlcyB0aGVtIGFjY29yZGluZ2x5LlxyXG4gICAgICovXHJcbiAgICBmb3JtR3JvdXA/OiAoZXJyb3I6IGFueSkgPT4gdm9pZDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEEgYmFzZSBjbGFzcyBmb3IgYW4gQW5ndWxhciBjb21wb25lbnQgY29udGFpbmluZyBhIGZvcm0uXHJcbiAqXHJcbiAqIEBjbGFzc2Rlc2MgQSBiYXNlIGNsYXNzIGZvciBhbiBBbmd1bGFyIGNvbXBvbmVudCBjb250YWluaW5nIGEgZm9ybSB0aGF0IGlzIHByZS1wb3B1bGF0ZWQgd2l0aCBmZXRjaGVkIGRhdGEuXHJcbiAqIFRoZSBkZXJpdmluZyBjbGFzcyBzaG91bGQgY2FsbCBpbml0KCkgd2hlbiBzZXR1cCBpcyBjb21wbGV0ZSAoc29tZXRpbWUgYWZ0ZXIgY2FsbGluZyBzdXBlcigpKSB0byBiZWdpbiB0aGUgZmV0Y2hcclxuICogYW5kIGluaXRpYWxpemUgdGhlIGZvcm0uXHJcbiAqXHJcbiAqIEB2ZXJzaW9uIDEuMC4wXHJcbiAqL1xyXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZVByb3BlcnRpZXNGb3JtPFREYXRhTW9kZWwsIFRGb3JtRGF0YSBleHRlbmRzIEJhc2VGb3JtRGF0YTxURGF0YU1vZGVsPj4ge1xyXG4gICAgcHJpdmF0ZSBjb25maXJtYXRpb25TdHJpbmdzID0gTXNmdFNtZS5nZXRTdHJpbmdzPFN0cmluZ3M+KCkuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuRm9ybS5Db25maXJtYXRpb25EaWFsb2c7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgcmVhY3RpdmUgZm9ybSBjb250YWluaW5nIGFsbCBmb3JtIGNvbnRyb2xzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZm9ybTogRm9ybUdyb3VwO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhdGVzIGRhdGEgaXMgYmVpbmcgZmV0Y2hlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRpbmcgPSB0cnVlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhdGVkIGRhdGEgaXMgYmVpbmcgc2F2ZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzYXZpbmc6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgZGF0YSBtb2RlbCB0aGF0IGNvbnRhaW5zIGRhdGEgZnJvbSB0aGUgc2VydmljZS5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGRhdGFNb2RlbDogVERhdGFNb2RlbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBkYXRhIG1vZGVsIHN1cHBseWluZyB0aGUgZm9ybSBmaWVsZCB2YWx1ZXMuXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBmb3JtRGF0YTogVEZvcm1EYXRhO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIEJhc2VQcm9wZXJ0aWVzRm9ybSBjbGFzcy5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gW2xvZ2dpbmdTb3VyY2VdIC0gVGhlIHNvdXJjZSBvZiBsb2cgbWVzc2FnZXMuXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBsb2dnaW5nU291cmNlOiBzdHJpbmcgPSAnQmFzZVByb3BlcnRpZXNGb3JtJywgcHJvdGVjdGVkIGFwcENvbnRleHRTZXJ2aWNlPzogQXBwQ29udGV4dFNlcnZpY2UpIHsgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgZm9ybSBlcnJvcnMuXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBnZXQgZm9ybUVycm9ycygpOiBhbnk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSB2YWxpZGF0aW9uIG1lc3NhZ2VzLlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgZ2V0IHZhbGlkYXRpb25NZXNzYWdlcygpOiBGb3JtR3JvdXBWYWxpZGF0aW9uTWVzc2FnZXM7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGZXRjaGVzIGRhdGEgZm9yIHRoZSBmb3JtLlxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIFRoZSBsYXRlc3QgdmVyc2lvbiBvZiB0aGUgZm9ybSBkYXRhLlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgZmV0Y2hEYXRhKCk6IE9ic2VydmFibGU8VERhdGFNb2RlbD47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIHRoZSBmb3JtLlxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIFRoZSBmb3JtIGdyb3VwIG9iamVjdC5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNyZWF0ZUZvcm0oKTogRm9ybUdyb3VwO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBmb3JtIGRhdGEgZnJvbSB0aGUgYmFja2luZyBkYXRhIG1vZGVsLlxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIFRoZSBmb3JtIGRhdGEgb2JqZWN0LlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgY3JlYXRlRm9ybURhdGFGcm9tRGF0YU1vZGVsKCk6IFRGb3JtRGF0YTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBtZXRob2QgdG8gcnVuIHdoZW4gdGhlIGRhdGEgZmV0Y2ggZmFpbHMuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGVycm9yIC0gVGhlIGVycm9yIG9iamVjdC5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IG9uRmV0Y2hFcnJvcihlcnJvcjogYW55KTogdm9pZDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBtZXRob2QgdG8gcnVuIHdoZW4gdGhlIGZvcm0gc2F2ZSBmYWlscy5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gZXJyb3IgLSBUaGUgZXJyb3Igb2JqZWN0LlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3Qgb25TYXZlRXJyb3IoZXJyb3I6IGFueSk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbWV0aG9kIHRvIHJ1biB3aGVuIHRoZSBmb3JtIHNhdmUgc3VjY2VlZHMuXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBvblNhdmVTdWNjZXNzKCk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTYXZlcyB0aGUgZm9ybSBhY2NvcmRpbmcgdG8gdGhlIG5ldyBkYXRhIG1vZGVsLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBuZXdEYXRhTW9kZWwgLSBUaGUgbmV3IGRhdGEgbW9kZWwgdG8gc2F2ZS5cclxuICAgICAqIEByZXR1cm5zIFRoZSBuZXdlc3QgdmVyc2lvbiBvZiB0aGUgZGF0YSBtb2RlbC5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHNhdmVGb3JtKG5ld0RhdGFNb2RlbDogVERhdGFNb2RlbCk6IE9ic2VydmFibGU8VERhdGFNb2RlbD47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBmb3JtLlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgZ2V0IGZvcm1DdXJyZW50VmFsdWUoKTogVEZvcm1EYXRhIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5mb3JtLnZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGlzY2FyZHMgdGhlIGN1cnJlbnQgZm9ybSBlZGl0cy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uRGlzY2FyZCgpOiB2b2lkIHtcclxuICAgICAgICAvLyBUT0RPOiBUaGUgZW1wdHkgZm9ybSBzaG91bGQgYmUgY3JlYXRlZCBzeW5jaHJvbm91c2x5IHNvIGFuZ3VsYXJcclxuICAgICAgICAvLyBjYW4gYmluZCB0byBpdC4gVGhlIHZhbHVlcyBjYW4gYmUgdXBkYXRlZCBvbmNlIHRoZSByZWFsIGRhdGEgaXMgYXZhaWxhYmxlXHJcblxyXG4gICAgICAgIHRoaXMuZm9ybURhdGEgPSB0aGlzLmNyZWF0ZUZvcm1EYXRhRnJvbURhdGFNb2RlbCgpO1xyXG4gICAgICAgIHRoaXMucmVzZXRGb3JtKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTYXZlcyB0aGUgY29udGVudCBvZiB0aGUgZm9ybS4gVGhlIG5ld2VzdCB2ZXJzaW9uIG9mIGRhdGEgZm9yIHRoZSBmb3JtXHJcbiAgICAgKiB3aWxsIGJlIGZldGNoZWQgYmVmb3JlIHBlcmZvcm1pbmcgdGhlIHNhdmUgb3BlcmF0aW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25TYXZlKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLnNhdmluZykge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnNhdmluZyA9IHRydWU7XHJcblxyXG4gICAgICAgIE1zZnRTbWUuZGVlcEFzc2lnbih0aGlzLmZvcm1EYXRhLCB0aGlzLmZvcm0udmFsdWUpO1xyXG5cclxuICAgICAgICAvLyBNb3ZlIGRpc2FibGUgYWZ0ZXIgZGVlcEFzc2lnbiBzaW5jZSBvbmNlIGRpc2FibGUgZm9ybS52YWx1ZSBiZWNvbWVzIGVtcHR5XHJcbiAgICAgICAgdGhpcy5mb3JtLmRpc2FibGUoKTtcclxuXHJcbiAgICAgICAgbGV0IHVwZGF0ZWRNb2RlbDtcclxuXHJcbiAgICAgICAgdGhpcy5mZXRjaERhdGEoKVxyXG4gICAgICAgICAgICAucGlwZShcclxuICAgICAgICAgICAgICAgIG1lcmdlTWFwKChmcmVzaE1vZGVsKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtRGF0YS5hcHBseVVwZGF0ZXNUb01vZGVsKGZyZXNoTW9kZWwpO1xyXG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZWRNb2RlbCA9IGZyZXNoTW9kZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2F2ZUZvcm0oZnJlc2hNb2RlbCk7XHJcbiAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgIHRha2UoMSlcclxuICAgICAgICAgICAgKS5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgICAgICAgbmV4dDogKGZyZXNoTW9kZWwpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uZW5hYmxlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zYXZpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZnJlc2hNb2RlbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFNb2RlbCA9IGZyZXNoTW9kZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhTW9kZWwgPSB1cGRhdGVkTW9kZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm1EYXRhID0gdGhpcy5jcmVhdGVGb3JtRGF0YUZyb21EYXRhTW9kZWwoKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2V0Rm9ybSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TYXZlU3VjY2VzcygpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zYXZpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmVuYWJsZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU2F2ZUVycm9yKGVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBjYW5EZWFjdGl2YXRlKFxyXG4gICAgICAgIGNvbXBvbmVudDogQ2FuQ29tcG9uZW50RGVhY3RpdmF0ZSxcclxuICAgICAgICByb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCxcclxuICAgICAgICBzdGF0ZTogUm91dGVyU3RhdGVTbmFwc2hvdCk6IE9ic2VydmFibGU8Ym9vbGVhbj4gfCBQcm9taXNlPGJvb2xlYW4+IHwgYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKHRoaXMuYXBwQ29udGV4dFNlcnZpY2UgJiYgdGhpcy5mb3JtICYmIHRoaXMuZm9ybS5kaXJ0eSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hcHBDb250ZXh0U2VydmljZS5mcmFtZS5zaG93RGlhbG9nQ29uZmlybWF0aW9uKHRoaXMuY29uZmlybUNvbnRpbnVlRWRpdGluZ0RpYWxvZ09wdGlvbnModGhpcy5mb3JtLCBudWxsKSlcclxuICAgICAgICAgICAgICAgIC5waXBlKG1hcCgocmVzdWx0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgaXMgdG8gY29udGludWUgZWRpdGluZ1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRpbnVlTmF2aWdhdGlvbiA9ICFyZXN1bHQuY29uZmlybWVkO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb250aW51ZU5hdmlnYXRpb24pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLnJlc2V0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb250aW51ZU5hdmlnYXRpb247XHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgY29uZmlybUNvbnRpbnVlRWRpdGluZ0RpYWxvZ09wdGlvbnMoXHJcbiAgICAgICAgZGlydHlGb3JtOiBGb3JtR3JvdXAsXHJcbiAgICAgICAgYWxsRm9ybXM6IEZvcm1Hcm91cFtdKTogQ29uZmlybWF0aW9uRGlhbG9nT3B0aW9ucyB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgY2FuY2VsQnV0dG9uVGV4dDogdGhpcy5jb25maXJtYXRpb25TdHJpbmdzLnVuc2F2ZWRDaGFuZ2VzQ2FuY2VsVGV4dCxcclxuICAgICAgICAgICAgY29uZmlybUJ1dHRvblRleHQ6IHRoaXMuY29uZmlybWF0aW9uU3RyaW5ncy51bnNhdmVkQ2hhbmdlc0NvbmZpcm1UZXh0LFxyXG4gICAgICAgICAgICBtZXNzYWdlOiB0aGlzLmNvbmZpcm1hdGlvblN0cmluZ3MudW5zYXZlZENoYW5nZXNNZXNzYWdlLFxyXG4gICAgICAgICAgICB0aXRsZTogdGhpcy5jb25maXJtYXRpb25TdHJpbmdzLnVuc2F2ZWRDaGFuZ2VzVGl0bGVcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIG1ldGhvZCB0byBpbml0aWFsaXplIHRoZSBmb3JtIHdpdGggZGF0YS5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGluaXQoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmZldGNoRGF0YSgpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgbmV4dDogKGRhdGEpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YU1vZGVsID0gZGF0YTtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVzZXRGb3JtRGF0YSgpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplVmFsaWRhdGlvbigpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uRmV0Y2hFcnJvcihlcnJvcik7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm0uZGlzYWJsZSgpO1xyXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogSGF2ZSBhIG1lY2hhbmlzbSB0byByZWZyZXNoIHRoZSBkYXRhXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVzZXRzIHRoZSBmb3JtIGFuZCBkaXNwbGF5cyB0aGUgb3JpZ2luYWwgdmFsdWVzIHdoaWxlIG1hcmtpbmcgdGhlIGZvcm0gYXMgcHJpc3RpbmUgYW5kIHVudG91Y2hlZC5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHJlc2V0Rm9ybSgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmZvcm0ucmVzZXQodGhpcy5mb3JtRGF0YSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQcm9jZXNzZXMgYSBjb250cm9sIGZvciB2YWxpZGF0aW9uLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBjb250cm9sIC0gVGhlIGNvbnRyb2wgdG8gdmFsaWRhdGUuXHJcbiAgICAgKiBAcGFyYW0gZm9ybUVycm9ycyAtIFRoZSBlcnJvcnMgb2YgdGhlIGZvcm0uXHJcbiAgICAgKiBAcGFyYW0gdmFsaWRhdGlvbk1lc3NhZ2VzIC0gVGhlIHZhbGlkYXRpb24gbWVzc2FnZXMgb2YgdGhlIGZvcm0uXHJcbiAgICAgKiBAcGFyYW0gZm9ybUVycm9yc0luZGV4IC0gVGhlIGZvcm0gZXJyb3JzIGluZGV4LlxyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgcHJvY2Vzc0NvbnRyb2xGb3JWYWxpZGF0aW9uKFxyXG4gICAgICAgIGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCxcclxuICAgICAgICBmb3JtRXJyb3JzOiBhbnksXHJcbiAgICAgICAgdmFsaWRhdGlvbk1lc3NhZ2VzOiBGb3JtQ29udHJvbENvbnRhaW5lclZhbGlkYXRpb25NZXNzYWdlcyB8IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIHwgKCgpID0+IHN0cmluZykgfSxcclxuICAgICAgICBmb3JtRXJyb3JzSW5kZXg6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IGlzRm9ybUdyb3VwID0gY29udHJvbCBpbnN0YW5jZW9mIEZvcm1Hcm91cDtcclxuICAgICAgICBsZXQgaXNGb3JtQXJyYXkgPSBmYWxzZTtcclxuICAgICAgICBpZiAoIWlzRm9ybUdyb3VwKSB7XHJcbiAgICAgICAgICAgIGlzRm9ybUFycmF5ID0gY29udHJvbCBpbnN0YW5jZW9mIEZvcm1BcnJheTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChpc0Zvcm1Hcm91cCkge1xyXG4gICAgICAgICAgICAvLyBpdGVyYXRlXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRm9ybUVycm9ycyhcclxuICAgICAgICAgICAgICAgIGNvbnRyb2wgYXMgRm9ybUdyb3VwLFxyXG4gICAgICAgICAgICAgICAgZm9ybUVycm9yc1tmb3JtRXJyb3JzSW5kZXhdLFxyXG4gICAgICAgICAgICAgICAgPEZvcm1Hcm91cFZhbGlkYXRpb25NZXNzYWdlcz4odmFsaWRhdGlvbk1lc3NhZ2VzKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChpc0Zvcm1BcnJheSkge1xyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUZvcm1FcnJvcnNGb3JBcnJheShcclxuICAgICAgICAgICAgICAgIGNvbnRyb2wgYXMgRm9ybUFycmF5LFxyXG4gICAgICAgICAgICAgICAgZm9ybUVycm9yc1tmb3JtRXJyb3JzSW5kZXhdLFxyXG4gICAgICAgICAgICAgICAgPEZvcm1BcnJheVZhbGlkYXRpb25NZXNzYWdlcz4odmFsaWRhdGlvbk1lc3NhZ2VzKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gZm9yIGNvbnRyb2xzLCBjbGVhciB0aGUgcHJldmlvdXMgZXJyb3IgbWVzc2FnZXNcclxuICAgICAgICAgICAgZm9ybUVycm9yc1tmb3JtRXJyb3JzSW5kZXhdID0gJyc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIWNvbnRyb2wudmFsaWQgJiYgY29udHJvbC5kaXJ0eSkge1xyXG4gICAgICAgICAgICBpZiAoaXNGb3JtR3JvdXAgfHwgaXNGb3JtQXJyYXkpIHtcclxuICAgICAgICAgICAgICAgIC8vIGZvcm0gZ3JvdXBzIGFuZCBhcnJheXMgYXJlIHByb2Nlc3NlZCBvdXRzaWRlIHRoaXMgZm9yIGxvb3Agb25jZSBhbGwgY2hpbGRyZW4gaGF2ZSBiZWVuIHByb2Nlc3NlZFxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlcyA9IHZhbGlkYXRpb25NZXNzYWdlcztcclxuICAgICAgICAgICAgaWYgKCFtZXNzYWdlcykge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBjb250cm9sLmVycm9ycykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2wuZXJyb3JzLmhhc093blByb3BlcnR5KGtleSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbWVzc2FnZSA9IG1lc3NhZ2VzW2tleV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1zZnRTbWUuaXNGdW5jdGlvbihtZXNzYWdlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gbWVzc2FnZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgZm9ybUVycm9yc1tmb3JtRXJyb3JzSW5kZXhdID0gbWVzc2FnZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gT25seSBvbmUgZXJyb3IgbWVzc2FnZSBwZXIgY29udHJvbFxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVXBkYXRlcyB0aGUgZm9ybSBlcnJvcnMuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGZvcm0gLSBUaGUgZm9ybSB0byB1cGRhdGUuXHJcbiAgICAgKiBAcGFyYW0gZm9ybUVycm9ycyAtIFRoZSBmb3JtIGVycm9ycyB0byBhcHBseS5cclxuICAgICAqIEBwYXJhbSB2YWxpZGF0aW9uTWVzc2FnZXMgLSBUaGUgdmFsaWRhdGlvbiBtZXNzYWdlcyB0byBhcHBseS5cclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUZvcm1FcnJvcnMoZm9ybTogRm9ybUdyb3VwLCBmb3JtRXJyb3JzOiBhbnksIHZhbGlkYXRpb25NZXNzYWdlczogRm9ybUdyb3VwVmFsaWRhdGlvbk1lc3NhZ2VzKTogdm9pZCB7XHJcbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBmb3JtRXJyb3JzKSB7XHJcbiAgICAgICAgICAgIGlmIChmb3JtRXJyb3JzLmhhc093blByb3BlcnR5KGZpZWxkKSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgY29udHJvbCA9IGZvcm0uZ2V0KGZpZWxkKTtcclxuICAgICAgICAgICAgICAgIGlmIChjb250cm9sKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ29udHJvbEZvclZhbGlkYXRpb24oY29udHJvbCwgZm9ybUVycm9ycywgdmFsaWRhdGlvbk1lc3NhZ2VzLmNvbnRyb2xzW2ZpZWxkXSwgZmllbGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIWZvcm0udmFsaWQgJiYgdmFsaWRhdGlvbk1lc3NhZ2VzLmZvcm1Hcm91cCkge1xyXG4gICAgICAgICAgICB2YWxpZGF0aW9uTWVzc2FnZXMuZm9ybUdyb3VwKGZvcm0uZXJyb3JzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGVzIHRoZSBmb3JtIGFycmF5IGVycm9ycy5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gZm9ybUFycmF5IC0gVGhlIGZvcm0gYXJyYXkgdG8gdXBkYXRlLlxyXG4gICAgICogQHBhcmFtIGZvcm1FcnJvcnMgLSBUaGUgZm9ybSBlcnJvcnMgdG8gYXBwbHkuXHJcbiAgICAgKiBAcGFyYW0gdmFsaWRhdGlvbk1lc3NhZ2VzIC0gVGhlIHZhbGlkYXRpb24gbWVzc2FnZXMgdG8gYXBwbHkuXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCB1cGRhdGVGb3JtRXJyb3JzRm9yQXJyYXkoZm9ybUFycmF5OiBGb3JtQXJyYXksIGZvcm1FcnJvcnM6IGFueSwgdmFsaWRhdGlvbk1lc3NhZ2VzOiBGb3JtQXJyYXlWYWxpZGF0aW9uTWVzc2FnZXMpOiB2b2lkIHtcclxuICAgICAgICBsZXQgcHJvY2Vzc0l0ZW1zID0gdHJ1ZTtcclxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZm9ybUVycm9ycykpIHtcclxuICAgICAgICAgICAgLy8gZm9ybSBlcnJvcnMgZm9yIGZvcm0gYXJyYXlzIHNob3VsZCBiZSBhbiBhcnJheSBvZiBsb2dTb3VyY2VcclxuICAgICAgICAgICAgcHJvY2Vzc0l0ZW1zID0gZmFsc2U7XHJcbiAgICAgICAgICAgIExvZ2dpbmcubG9nKHtcclxuICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcy5sb2dnaW5nU291cmNlLFxyXG4gICAgICAgICAgICAgICAgbGV2ZWw6IExvZ0xldmVsLldhcm5pbmcsXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBgVW5leHBlY3RlZCBmb3JtIGVycm9ycyB0eXBlIGZvciBmb3JtIGFycmF5LiBgICtcclxuICAgICAgICAgICAgICAgICAgICBgSXQgc2hvdWxkIGJlIGFuIGFycmF5IGJ1dCBpdCBpcyAke3R5cGVvZiBmb3JtRXJyb3JzfS4gU2tpcHBpbmcgdmFsaWRhdGlvbmBcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBlcnJvcnNBcnJheSA9IGZvcm1FcnJvcnMgYXMgQXJyYXk8YW55PjtcclxuXHJcbiAgICAgICAgaWYgKGVycm9yc0FycmF5Lmxlbmd0aCAhPT0gZm9ybUFycmF5Lmxlbmd0aCkge1xyXG4gICAgICAgICAgICBwcm9jZXNzSXRlbXMgPSBmYWxzZTtcclxuICAgICAgICAgICAgTG9nZ2luZy5sb2coe1xyXG4gICAgICAgICAgICAgICAgc291cmNlOiB0aGlzLmxvZ2dpbmdTb3VyY2UsXHJcbiAgICAgICAgICAgICAgICBsZXZlbDogTG9nTGV2ZWwuV2FybmluZyxcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBVbmV4cGVjdGVkIGNvdW50IG9mIGVycm9ycyB0eXBlIGZvciBmb3JtIGFycmF5LiBgICtcclxuICAgICAgICAgICAgICAgICAgICBgSXQgc2hvdWxkIGJlICR7Zm9ybUFycmF5Lmxlbmd0aH0gYnV0IGl0IGlzICR7ZXJyb3JzQXJyYXkubGVuZ3RofS4gU2tpcHBpbmcgdmFsaWRhdGlvbmBcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJvY2Vzc0l0ZW1zKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZm9ybUFycmF5Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJpbmdJbmRleCA9ICcnICsgaTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRyb2wgPSBmb3JtQXJyYXkuZ2V0KHN0cmluZ0luZGV4KTtcclxuICAgICAgICAgICAgICAgIGlmIChjb250cm9sKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ29udHJvbEZvclZhbGlkYXRpb24oY29udHJvbCwgZm9ybUVycm9ycywgdmFsaWRhdGlvbk1lc3NhZ2VzLCBzdHJpbmdJbmRleCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghZm9ybUFycmF5LnZhbGlkICYmIHZhbGlkYXRpb25NZXNzYWdlcy5mb3JtQXJyYXkpIHtcclxuICAgICAgICAgICAgdmFsaWRhdGlvbk1lc3NhZ2VzLmZvcm1BcnJheShmb3JtQXJyYXkuZXJyb3JzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgZm9ybSB2YWxpZGF0aW9uLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGluaXRpYWxpemVWYWxpZGF0aW9uKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuZm9ybS52YWx1ZUNoYW5nZXNcclxuICAgICAgICAgICAgLnBpcGUoZGVib3VuY2VUaW1lKDUwMCkpXHJcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKGRhdGEpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMub25WYWx1ZUNoYW5nZWQoZGF0YSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0aGlzLm9uVmFsdWVDaGFuZ2VkKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbWV0aG9kIHRvIGNhbGwgd2hlbiB0aGUgZm9ybSB2YWx1ZSBjaGFuZ2VzLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG9uVmFsdWVDaGFuZ2VkKGRhdGE/OiBhbnkpOiB2b2lkIHtcclxuICAgICAgICAvLyBUT0RPOiBWYWxpZGF0ZSB0aGF0IHRoZSBkYXRhPyBwYXJhbXRlciB3YXMgbm90IG5lZWRlZFxyXG4gICAgICAgIGlmICghdGhpcy5mb3JtKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGZvcm0gPSB0aGlzLmZvcm07XHJcbiAgICAgICAgdGhpcy51cGRhdGVGb3JtRXJyb3JzKGZvcm0sIHRoaXMuZm9ybUVycm9ycywgdGhpcy52YWxpZGF0aW9uTWVzc2FnZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVzZXRzIHRoZSBkYXRhIGJhY2tpbmcgdGhlIGZvcm0gd2l0aG91dCB1cGRhdGluZyB0aGUgZGlzcGxheS5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gZXhpc3RpbmdGb3JtIC0gVGhlIGV4aXN0aW5nIGZvcm0gZ3JvdXAgb2YgdGhlIGRpc3BsYXkuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVzZXRGb3JtRGF0YShleGlzdGluZ0Zvcm0/OiBGb3JtR3JvdXApOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmZvcm1EYXRhID0gdGhpcy5jcmVhdGVGb3JtRGF0YUZyb21EYXRhTW9kZWwoKTtcclxuICAgICAgICB0aGlzLmZvcm0gPSB0aGlzLmNyZWF0ZUZvcm0oKTtcclxuICAgIH1cclxufVxyXG4iXX0=