@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
390 lines • 55 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Component, ElementRef, Injector, Input, ViewChild } from '@angular/core';
import { Validators } from '@angular/forms';
import { KeyCode } from '@microsoft/windows-admin-center-sdk/core/data/accessibility-manager';
import { SmeSchemaProperty } from '../../../schema/schema-decorator';
import { SimplePropertySchemaFieldLoaderComponent } from '../../../schema/schema-field-host.component';
import { SchemaPrimitiveType } from '../../../schema/schema-models';
import { ValidationAlertSeverity } from '../../validation-alert/validation-alert';
import { SmeInternalFormFieldComponent } from '../form-field.component';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "../form-field-accessor.directive";
import * as i3 from "../form-field-validator.directive";
import * as i4 from "../form-field-async-validator.directive";
import * as i5 from "@angular/common";
import * as i6 from "../../validation-alert/validation-alert.component";
import * as i7 from "../../form-field-layout/form-field-layout.component";
const _c0 = ["input"];
const _c1 = ["container"];
const _c2 = ["incrementButton"];
const _c3 = ["decrementButton"];
const _c4 = ["type", "number"];
function NumberFormFieldComponent_span_2_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "span");
i0.ɵɵtext(1);
i0.ɵɵelementEnd();
} if (rf & 2) {
const ctx_r0 = i0.ɵɵnextContext();
i0.ɵɵadvance(1);
i0.ɵɵtextInterpolate(ctx_r0.value);
} }
function NumberFormFieldComponent_div_3_span_4_Template(rf, ctx) { if (rf & 1) {
const _r8 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "span", 10)(1, "button", 11, 12);
i0.ɵɵlistener("click", function NumberFormFieldComponent_div_3_span_4_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r8); const ctx_r7 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r7.increment()); });
i0.ɵɵelement(3, "span", 13);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(4, "button", 11, 14);
i0.ɵɵlistener("click", function NumberFormFieldComponent_div_3_span_4_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r8); const ctx_r9 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r9.decrement()); });
i0.ɵɵelement(6, "span", 15);
i0.ɵɵelementEnd()();
} if (rf & 2) {
const ctx_r4 = i0.ɵɵnextContext(2);
i0.ɵɵadvance(1);
i0.ɵɵattribute("aria-label", ctx_r4.ariaLabelIncrease);
i0.ɵɵadvance(3);
i0.ɵɵattribute("aria-label", ctx_r4.ariaLabelDecrease);
} }
function NumberFormFieldComponent_div_3_Template(rf, ctx) { if (rf & 1) {
const _r11 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 5, 6)(2, "input", 7, 8);
i0.ɵɵlistener("ngModelChange", function NumberFormFieldComponent_div_3_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r10 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r10.value = $event); })("focus", function NumberFormFieldComponent_div_3_Template_input_focus_2_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r12 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r12.onInputFocus($event)); })("focusout", function NumberFormFieldComponent_div_3_Template_input_focusout_2_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r13 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r13.onInputFocusOut($event)); })("keydown", function NumberFormFieldComponent_div_3_Template_input_keydown_2_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r14 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r14.onInputKeydown($event)); });
i0.ɵɵelementEnd();
i0.ɵɵtemplate(4, NumberFormFieldComponent_div_3_span_4_Template, 7, 2, "span", 9);
i0.ɵɵelementEnd();
} if (rf & 2) {
const ctx_r1 = i0.ɵɵnextContext();
i0.ɵɵadvance(2);
i0.ɵɵproperty("ngModel", ctx_r1.value)("required", ctx_r1.required)("disabled", ctx_r1.loadingOrDisabled)("max", ctx_r1.max)("min", ctx_r1.min)("step", ctx_r1.step)("placeholder", ctx_r1.placeholder);
i0.ɵɵattribute("role", ctx_r1.showSpinButton ? "spinbutton" : null)("aria-valuemax", ctx_r1.max)("aria-valuemin", ctx_r1.min)("aria-label", ctx_r1.label)("aria-required", ctx_r1.required);
i0.ɵɵadvance(2);
i0.ɵɵproperty("ngIf", ctx_r1.showSpinButton);
} }
/* eslint-disable max-len */
/* eslint-enable max-len */
export class NumberFormFieldLoaderComponent extends SimplePropertySchemaFieldLoaderComponent {
}
/** @nocollapse */ NumberFormFieldLoaderComponent.ɵfac = /** @pureOrBreakMyCode */ function () { let ɵNumberFormFieldLoaderComponent_BaseFactory; return function NumberFormFieldLoaderComponent_Factory(t) { return (ɵNumberFormFieldLoaderComponent_BaseFactory || (ɵNumberFormFieldLoaderComponent_BaseFactory = i0.ɵɵgetInheritedFactory(NumberFormFieldLoaderComponent)))(t || NumberFormFieldLoaderComponent); }; }();
/** @nocollapse */ NumberFormFieldLoaderComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: NumberFormFieldLoaderComponent, selectors: [["ng-component"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 14, consts: [["type", "number", 3, "ngModel", "name", "label", "required", "description", "readonly", "disabled", "min", "max", "step", "showSpinButton", "pendingMessage", "customAsyncValidateDisabled", "customAsyncValidateDebounceTime", "ngModelChange", "customValidate", "customAsyncValidate"], ["field", ""]], template: function NumberFormFieldLoaderComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "sme-form-field", 0, 1);
i0.ɵɵlistener("ngModelChange", function NumberFormFieldLoaderComponent_Template_sme_form_field_ngModelChange_0_listener($event) { return ctx.data = $event; })("customValidate", function NumberFormFieldLoaderComponent_Template_sme_form_field_customValidate_0_listener($event) { return ctx.resolveFunction(ctx.propertySchema.customValidation)($event); })("customAsyncValidate", function NumberFormFieldLoaderComponent_Template_sme_form_field_customAsyncValidate_0_listener($event) { return ctx.propertySchema.customAsyncValidation && ctx.resolveFunction(ctx.propertySchema.customAsyncValidation.handler)($event); });
i0.ɵɵelementEnd();
} if (rf & 2) {
i0.ɵɵproperty("ngModel", ctx.data)("name", ctx.propertySchema.name)("label", ctx.localize(ctx.propertySchema.label))("required", ctx.propertySchema.required)("description", ctx.localize(ctx.propertySchema.description))("readonly", !!ctx.evalExpression(ctx.propertySchema.readonlyCondition))("disabled", !!(ctx.propertySchema.disabledCondition && ctx.evalExpression(ctx.propertySchema.disabledCondition)))("min", ctx.propertySchema.options && ctx.propertySchema.options.min)("max", ctx.propertySchema.options && ctx.propertySchema.options.max)("step", ctx.propertySchema.options && ctx.propertySchema.options.step)("showSpinButton", ctx.propertySchema.options && ctx.propertySchema.options.showSpinButton)("pendingMessage", ctx.propertySchema.customAsyncValidation && ctx.localize(ctx.propertySchema.customAsyncValidation.pendingMessage))("customAsyncValidateDisabled", ctx.shouldCustomAsyncValidationBeDisabled())("customAsyncValidateDebounceTime", ctx.propertySchema.customAsyncValidation && +ctx.propertySchema.customAsyncValidation.handler);
} }, dependencies: function () { return [i1.NgControlStatus, i1.RequiredValidator, i1.NgModel, NumberFormFieldComponent, i2.FormFieldAccessorDirective, i3.FormFieldValidatorDirective, i4.FormFieldAsyncValidatorDirective]; }, encapsulation: 2 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NumberFormFieldLoaderComponent, [{
type: Component,
args: [{ template: "<sme-form-field #field type=\"number\" [(ngModel)]=\"data\"\r\n [name]=\"propertySchema.name\"\r\n [label]=\"localize(propertySchema.label)\"\r\n [required]=\"propertySchema.required\"\r\n [description]=\"localize(propertySchema.description)\"\r\n [readonly]=\"!!evalExpression(propertySchema.readonlyCondition)\"\r\n [disabled]=\"!!(propertySchema.disabledCondition && evalExpression(propertySchema.disabledCondition))\"\r\n [min]=\"propertySchema.options && propertySchema.options.min\"\r\n [max]=\"propertySchema.options && propertySchema.options.max\"\r\n [step]=\"propertySchema.options && propertySchema.options.step\"\r\n [showSpinButton]=\"propertySchema.options && propertySchema.options.showSpinButton\"\r\n [pendingMessage]=\"propertySchema.customAsyncValidation && localize(propertySchema.customAsyncValidation.pendingMessage)\"\r\n [customAsyncValidateDisabled]=\"shouldCustomAsyncValidationBeDisabled()\"\r\n [customAsyncValidateDebounceTime]=\"propertySchema.customAsyncValidation && +propertySchema.customAsyncValidation.handler\"\r\n (customValidate)=\"resolveFunction(propertySchema.customValidation)($event)\"\r\n (customAsyncValidate)=\"propertySchema.customAsyncValidation && resolveFunction(propertySchema.customAsyncValidation.handler)($event)\">\r\n</sme-form-field>\r\n" }]
}], null, null); })();
/**
* Accessible number field implementation
*/
let NumberFormFieldComponent = class NumberFormFieldComponent extends SmeInternalFormFieldComponent {
/**
* Initializes a new instance of the SliderFormFieldComponent
*/
constructor(injector) {
super(injector);
/**
* It determine whether to show the spin button.
*/
this.showSpinButton = false;
this.min = 0;
// No default maximum/step
}
/**
* The source name to use for logging
*/
get logSourceName() {
return 'NumberFormFieldComponent';
}
ngOnInit() {
super.ngOnInit();
// If incrementBy is not set, use step. If step is not set default to 1 (one)
this.incrementBy = MsftSme.isNullOrUndefined(this.incrementBy)
? MsftSme.isNullOrUndefined(this.step) ? 1 : this.step
: this.incrementBy;
}
/**
* Getter aria label increase for spin button increase.
*/
get ariaLabelIncrease() {
return this.strings.MsftSmeShell.Angular.Form.SpinButton.increase.format(this.incrementBy);
}
/**
* Getter aria label increase for spin button decrease.
*/
get ariaLabelDecrease() {
return this.strings.MsftSmeShell.Angular.Form.SpinButton.decrease.format(this.incrementBy);
}
/**
* Handle keydown events on the number input
*/
onInputKeydown($event) {
// In Microsoft Edge and IE, numeric inputs will scroll the page while incrementing/decrementing the number.
switch ($event.keyCode) {
case KeyCode.UpArrow: {
$event.preventDefault();
// firing the click event to trigger the click style to render
this.increment();
this.toggleFocusEvent(this.incrementButton, true);
setTimeout(() => {
this.toggleFocusEvent(this.incrementButton, false);
});
break;
}
case KeyCode.DownArrow: {
$event.preventDefault();
// firing the click event to trigger the click style to render
this.decrement();
this.toggleFocusEvent(this.decrementButton, true);
setTimeout(() => {
this.toggleFocusEvent(this.decrementButton, false);
});
break;
}
default: {
return;
}
}
}
/**
* Increments the controls value by 1 "step"
*/
increment() {
let value = MsftSme.isNumber(this.value) ? this.value : this.min - 1;
value += this.incrementBy;
if (value > this.max) {
value = this.max;
}
this.value = value;
}
/**
* Decrements the controls value by 1 "step"
*/
decrement() {
let value = MsftSme.isNumber(this.value) ? this.value : this.min + 1;
value -= this.incrementBy;
if (value < this.min) {
value = this.min;
}
this.value = value;
}
/**
* The functionality to focus on the input field
*/
onInputFocus($event) {
if ($event) {
$event.preventDefault();
}
this.toggleFocusEvent(this.container, true);
}
/**
* The functionality to focus out on the input field
*
* @param $event the focus event object
*/
onInputFocusOut($event) {
if ($event) {
$event.preventDefault();
}
this.toggleFocusEvent(this.container, false);
}
/**
* Creates the idBag used by this component to store unique element ids.
* id values will be assigned be the @see BaseComponent super class.
*/
createIdBag() {
return {
detailsSpan: ''
};
}
/**
* Determines the value to use when clearing the field based on the initial value type
*/
getClearValue() {
return MsftSme.isNullOrUndefined(this.min) ? 0 : this.min;
}
/**
* Performs validation that is internal to this control
* @param c The form control attached to this instance
*/
validate(c) {
// if not required, don't process null or empty values for further validation
if (!this.required && (MsftSme.isNullOrWhiteSpace(c.value))) {
return super.validate(c);
}
if (!MsftSme.isNumber(this.value)) {
return {
notANumber: {
valid: false,
message: this.strings.MsftSmeShell.Angular.Common.Form.Validation.isNumber.format.format(this.fieldName),
severity: ValidationAlertSeverity.Error
}
};
}
// angular's min and max validator only work via code. So we implement them here.
if (!MsftSme.isNullOrUndefined(this.min) && this.value < this.min) {
const errors = Validators.min(this.min)(c);
if (errors) {
return errors;
}
}
if (!MsftSme.isNullOrUndefined(this.max) && this.value > this.max) {
const errors = Validators.max(this.max)(c);
if (errors) {
return errors;
}
}
if (!MsftSme.isNullOrUndefined(this.step)) {
// If step is used check if the current value falls within the range of the legal values
const safeRem = this.getSafeRemainder((this.value - this.min), this.step);
// Round off to the nearest integer, handle any floating precision errors that may occur
const rem = Math.round((safeRem + Number.EPSILON) * 100) / 100;
if (rem !== 0) {
return {
notAMultipleOfStep: {
valid: false,
message: this.strings.MsftSmeShell.Angular.Common.Form.Validation.IllegalNumber
.format(this.fieldName, this.step, this.min),
severity: ValidationAlertSeverity.Error
}
};
}
}
return super.validate(c);
}
/**
* Gets the remainder of a division operation by converting any decimals to integers first
* @param value The number to be divided
* @param divisor The dividing number
*/
getSafeRemainder(value, divisor) {
const valueDecimals = (value.toString().split('.')[1] || '').length;
const divisorDecimals = (divisor.toString().split('.')[1] || '').length;
const maxDecimals = Math.max(valueDecimals, divisorDecimals);
const valueInt = parseInt(value.toFixed(maxDecimals).replace('.', ''), 10);
const divisorInt = parseInt(divisor.toFixed(maxDecimals).replace('.', ''), 10);
return (valueInt % divisorInt) / Math.pow(10, maxDecimals);
}
/**
* It toggles the focus state for passed in UI element
*
* @param element the element for focusing
* @param addClass it determines whether to add or remove class state
* @returns void
*/
toggleFocusEvent(element, addClass = true) {
if (!element?.nativeElement) {
return;
}
if (addClass && !element.nativeElement.className.includes('sme-focused')) {
element.nativeElement.classList.add('sme-focused');
}
if (!addClass && element.nativeElement.className.includes('sme-focused')) {
element.nativeElement.classList.remove('sme-focused');
}
}
};
/** @nocollapse */ NumberFormFieldComponent.ɵfac = function NumberFormFieldComponent_Factory(t) { return new (t || NumberFormFieldComponent)(i0.ɵɵdirectiveInject(i0.Injector)); };
/** @nocollapse */ NumberFormFieldComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: NumberFormFieldComponent, selectors: [["sme-form-field", "type", "number"]], viewQuery: function NumberFormFieldComponent_Query(rf, ctx) { if (rf & 1) {
i0.ɵɵviewQuery(_c0, 5);
i0.ɵɵviewQuery(_c1, 5);
i0.ɵɵviewQuery(_c2, 5);
i0.ɵɵviewQuery(_c3, 5);
} if (rf & 2) {
let _t;
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.input = _t.first);
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.container = _t.first);
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.incrementButton = _t.first);
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.decrementButton = _t.first);
} }, inputs: { showSpinButton: "showSpinButton", step: "step", incrementBy: "incrementBy", min: "min", max: "max" }, features: [i0.ɵɵInheritDefinitionFeature], attrs: _c4, decls: 5, vars: 4, consts: [[3, "formField"], [1, "sme-form-field-editor"], [4, "ngIf"], ["class", "sme-number-form-field-container", 4, "ngIf"], [3, "alert"], [1, "sme-number-form-field-container"], ["container", ""], ["type", "number", "autocomplete", "off", 1, "sme-hidden-focus", 3, "ngModel", "required", "disabled", "max", "min", "step", "placeholder", "ngModelChange", "focus", "focusout", "keydown"], ["input", ""], ["class", "sme-arrange-stack-v sme-form-field-number-button-group", 4, "ngIf"], [1, "sme-arrange-stack-v", "sme-form-field-number-button-group"], ["type", "button", "tabindex", "-1", 1, "sme-button-auto-width", 3, "click"], ["incrementButton", ""], [1, "sme-icon", "sme-icon-chevronUpSmall"], ["decrementButton", ""], [1, "sme-icon", "sme-icon-chevronDownSmall"]], template: function NumberFormFieldComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "sme-form-field-layout", 0)(1, "div", 1);
i0.ɵɵtemplate(2, NumberFormFieldComponent_span_2_Template, 2, 1, "span", 2);
i0.ɵɵtemplate(3, NumberFormFieldComponent_div_3_Template, 5, 13, "div", 3);
i0.ɵɵelementEnd();
i0.ɵɵelement(4, "sme-validation-alert", 4);
i0.ɵɵelementEnd();
} if (rf & 2) {
i0.ɵɵproperty("formField", ctx);
i0.ɵɵadvance(2);
i0.ɵɵproperty("ngIf", ctx.readonly);
i0.ɵɵadvance(1);
i0.ɵɵproperty("ngIf", !ctx.readonly);
i0.ɵɵadvance(1);
i0.ɵɵproperty("alert", ctx.alert);
} }, dependencies: [i5.NgIf, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.NgControlStatus, i1.RequiredValidator, i1.MinValidator, i1.MaxValidator, i1.NgModel, i6.ValidationAlertComponent, i7.FormFieldLayoutComponent], encapsulation: 2 });
NumberFormFieldComponent = __decorate([
SmeSchemaProperty({
type: SchemaPrimitiveType.Number,
format: 'textbox',
isDefaultFormat: true,
description: 'A single line textbox binding to number data.',
loaderComponent: NumberFormFieldLoaderComponent,
optionProperties: [
{
type: SchemaPrimitiveType.Number,
format: 'textbox',
name: 'min',
label: 'actual_string:Min',
defaultValue: 0,
required: false,
options: {
multipleline: false
}
},
{
type: SchemaPrimitiveType.Number,
format: 'textbox',
name: 'max',
label: 'actual_string:Max',
defaultValue: 100,
required: false,
options: {
multipleline: false
}
},
{
type: SchemaPrimitiveType.Number,
format: 'textbox',
name: 'step',
label: 'actual_string:Step',
defaultValue: 1,
required: false,
options: {
multipleline: false
}
}
]
}),
__metadata("design:paramtypes", [Injector])
], NumberFormFieldComponent);
export { NumberFormFieldComponent };
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NumberFormFieldComponent, [{
type: Component,
args: [{ selector: 'sme-form-field[type="number"]', template: "<sme-form-field-layout [formField]=\"this\">\r\n <div class=\"sme-form-field-editor\">\r\n <span *ngIf=\"readonly\">{{ value }}</span>\r\n <div #container *ngIf=\"!readonly\" class=\"sme-number-form-field-container\">\r\n <input #input type=\"number\" autocomplete=\"off\" [(ngModel)]=\"value\" class=\"sme-hidden-focus\" [attr.role]=\"showSpinButton ? 'spinbutton': null\"\r\n [required]=\"required\" [disabled]=\"loadingOrDisabled\" [max]=\"max\" [min]=\"min\" [step]=\"step\" [placeholder]=\"placeholder\"\r\n [attr.aria-valuemax]=\"max\" [attr.aria-valuemin]=\"min\" [attr.aria-label]=\"label\" [attr.aria-required]=\"required\"\r\n (focus)=\"onInputFocus($event)\" (focusout)=\"onInputFocusOut($event)\" (keydown)=\"onInputKeydown($event)\">\r\n <span *ngIf=\"showSpinButton\" class=\"sme-arrange-stack-v sme-form-field-number-button-group\">\r\n <button #incrementButton type=\"button\" class=\"sme-button-auto-width\" tabindex=\"-1\" (click)=\"increment()\" [attr.aria-label]=\"ariaLabelIncrease\">\r\n <span class=\"sme-icon sme-icon-chevronUpSmall\"></span>\r\n </button>\r\n <button #decrementButton type=\"button\" class=\"sme-button-auto-width\" tabindex=\"-1\" (click)=\"decrement()\" [attr.aria-label]=\"ariaLabelDecrease\">\r\n <span class=\"sme-icon sme-icon-chevronDownSmall\"></span>\r\n </button>\r\n </span>\r\n </div>\r\n </div>\r\n <sme-validation-alert [alert]=\"alert\"></sme-validation-alert>\r\n</sme-form-field-layout>\r\n" }]
}], function () { return [{ type: i0.Injector }]; }, { input: [{
type: ViewChild,
args: ['input']
}], container: [{
type: ViewChild,
args: ['container']
}], incrementButton: [{
type: ViewChild,
args: ['incrementButton']
}], decrementButton: [{
type: ViewChild,
args: ['decrementButton']
}], showSpinButton: [{
type: Input
}], step: [{
type: Input
}], incrementBy: [{
type: Input
}], min: [{
type: Input
}], max: [{
type: Input
}] }); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtYmVyLWZvcm0tZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvZm9ybS9mb3JtLWZpZWxkL251bWJlci9udW1iZXItZm9ybS1maWVsZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9mb3JtL2Zvcm0tZmllbGQvbnVtYmVyL251bWJlci1mb3JtLWZpZWxkLmNvbXBvbmVudC5odG1sIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvZm9ybS9mb3JtLWZpZWxkL251bWJlci9udW1iZXItc2NoZW1hLWRyaXZlbi1mb3JtLXRlbXBsYXRlLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQVUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFGLE9BQU8sRUFBaUMsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0UsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFFQUFxRSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSx3Q0FBd0MsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ3ZHLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHlCQUF5QixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7SUNMcEUsNEJBQXVCO0lBQUEsWUFBVztJQUFBLGlCQUFPOzs7SUFBbEIsZUFBVztJQUFYLGtDQUFX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QUFLLEVBQUUsb0JBQW9CO2dCQUMzQixZQUFZLEVBQUUsQ0FBQztnQkFDZixRQUFRLEVBQUUsS0FBSztnQkFDZixPQUFPLEVBQUU7b0JBQ0wsWUFBWSxFQUFFLEtBQUs7aUJBQ3RCO2FBQ0o7U0FDSjtLQUNKLENBQUM7cUNBd0VnQixRQUFRO0dBbkViLHdCQUF3QixDQXFScEM7U0FyUlksd0JBQXdCO3VGQUF4Qix3QkFBd0I7Y0FKcEMsU0FBUzsyQkFDSSwrQkFBK0I7MkRBZ0JsQyxLQUFLO2tCQURYLFNBQVM7bUJBQUMsT0FBTztZQU9YLFNBQVM7a0JBRGYsU0FBUzttQkFBQyxXQUFXO1lBT2YsZUFBZTtrQkFEckIsU0FBUzttQkFBQyxpQkFBaUI7WUFPckIsZUFBZTtrQkFEckIsU0FBUzttQkFBQyxpQkFBaUI7WUFPckIsY0FBYztrQkFEcEIsS0FBSztZQU9DLElBQUk7a0JBRFYsS0FBSztZQU9DLFdBQVc7a0JBRGpCLEtBQUs7WUFPQyxHQUFHO2tCQURULEtBQUs7WUFPQyxHQUFHO2tCQURULEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEluamVjdG9yLCBJbnB1dCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIFZhbGlkYXRpb25FcnJvcnMsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IEtleUNvZGUgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RhdGEvYWNjZXNzaWJpbGl0eS1tYW5hZ2VyJztcclxuaW1wb3J0IHsgU21lU2NoZW1hUHJvcGVydHkgfSBmcm9tICcuLi8uLi8uLi9zY2hlbWEvc2NoZW1hLWRlY29yYXRvcic7XHJcbmltcG9ydCB7IFNpbXBsZVByb3BlcnR5U2NoZW1hRmllbGRMb2FkZXJDb21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9zY2hlbWEvc2NoZW1hLWZpZWxkLWhvc3QuY29tcG9uZW50JztcclxuaW1wb3J0IHsgU2NoZW1hUHJpbWl0aXZlVHlwZSB9IGZyb20gJy4uLy4uLy4uL3NjaGVtYS9zY2hlbWEtbW9kZWxzJztcclxuaW1wb3J0IHsgVmFsaWRhdGlvbkFsZXJ0U2V2ZXJpdHkgfSBmcm9tICcuLi8uLi92YWxpZGF0aW9uLWFsZXJ0L3ZhbGlkYXRpb24tYWxlcnQnO1xyXG5pbXBvcnQgeyBTbWVJbnRlcm5hbEZvcm1GaWVsZENvbXBvbmVudCB9IGZyb20gJy4uL2Zvcm0tZmllbGQuY29tcG9uZW50JztcclxuXHJcbi8qIGVzbGludC1kaXNhYmxlIG1heC1sZW4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vbnVtYmVyLXNjaGVtYS1kcml2ZW4tZm9ybS10ZW1wbGF0ZS5odG1sJ1xyXG59KVxyXG4vKiBlc2xpbnQtZW5hYmxlIG1heC1sZW4gKi9cclxuZXhwb3J0IGNsYXNzIE51bWJlckZvcm1GaWVsZExvYWRlckNvbXBvbmVudCBleHRlbmRzIFNpbXBsZVByb3BlcnR5U2NoZW1hRmllbGRMb2FkZXJDb21wb25lbnQge1xyXG59XHJcblxyXG4vKipcclxuICogQWNjZXNzaWJsZSBudW1iZXIgZmllbGQgaW1wbGVtZW50YXRpb25cclxuICovXHJcbkBTbWVTY2hlbWFQcm9wZXJ0eSh7XHJcbiAgICB0eXBlOiBTY2hlbWFQcmltaXRpdmVUeXBlLk51bWJlcixcclxuICAgIGZvcm1hdDogJ3RleHRib3gnLFxyXG4gICAgaXNEZWZhdWx0Rm9ybWF0OiB0cnVlLFxyXG4gICAgZGVzY3JpcHRpb246ICdBIHNpbmdsZSBsaW5lIHRleHRib3ggYmluZGluZyB0byBudW1iZXIgZGF0YS4nLFxyXG4gICAgbG9hZGVyQ29tcG9uZW50OiBOdW1iZXJGb3JtRmllbGRMb2FkZXJDb21wb25lbnQsXHJcbiAgICBvcHRpb25Qcm9wZXJ0aWVzOiBbXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICB0eXBlOiBTY2hlbWFQcmltaXRpdmVUeXBlLk51bWJlcixcclxuICAgICAgICAgICAgZm9ybWF0OiAndGV4dGJveCcsXHJcbiAgICAgICAgICAgIG5hbWU6ICdtaW4nLFxyXG4gICAgICAgICAgICBsYWJlbDogJ2FjdHVhbF9zdHJpbmc6TWluJyxcclxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAwLFxyXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXHJcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcclxuICAgICAgICAgICAgICAgIG11bHRpcGxlbGluZTogZmFsc2VcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICB0eXBlOiBTY2hlbWFQcmltaXRpdmVUeXBlLk51bWJlcixcclxuICAgICAgICAgICAgZm9ybWF0OiAndGV4dGJveCcsXHJcbiAgICAgICAgICAgIG5hbWU6ICdtYXgnLFxyXG4gICAgICAgICAgICBsYWJlbDogJ2FjdHVhbF9zdHJpbmc6TWF4JyxcclxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxMDAsXHJcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcclxuICAgICAgICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgICAgICAgICAgbXVsdGlwbGVsaW5lOiBmYWxzZVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIHR5cGU6IFNjaGVtYVByaW1pdGl2ZVR5cGUuTnVtYmVyLFxyXG4gICAgICAgICAgICBmb3JtYXQ6ICd0ZXh0Ym94JyxcclxuICAgICAgICAgICAgbmFtZTogJ3N0ZXAnLFxyXG4gICAgICAgICAgICBsYWJlbDogJ2FjdHVhbF9zdHJpbmc6U3RlcCcsXHJcbiAgICAgICAgICAgIGRlZmF1bHRWYWx1ZTogMSxcclxuICAgICAgICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgICBvcHRpb25zOiB7XHJcbiAgICAgICAgICAgICAgICBtdWx0aXBsZWxpbmU6IGZhbHNlXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICBdXHJcbn0pXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdzbWUtZm9ybS1maWVsZFt0eXBlPVwibnVtYmVyXCJdJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9udW1iZXItZm9ybS1maWVsZC5jb21wb25lbnQuaHRtbCdcclxufSlcclxuZXhwb3J0IGNsYXNzIE51bWJlckZvcm1GaWVsZENvbXBvbmVudCBleHRlbmRzIFNtZUludGVybmFsRm9ybUZpZWxkQ29tcG9uZW50PG51bWJlcj4gaW1wbGVtZW50cyBPbkluaXQge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIHNvdXJjZSBuYW1lIHRvIHVzZSBmb3IgbG9nZ2luZ1xyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgZ2V0IGxvZ1NvdXJjZU5hbWUoKSB7XHJcbiAgICAgICAgcmV0dXJuICdOdW1iZXJGb3JtRmllbGRDb21wb25lbnQnO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGlucHV0IGZyb20gbnVtYmVyIGZvcm0gZmllbGRcclxuICAgICAqL1xyXG4gICAgQFZpZXdDaGlsZCgnaW5wdXQnKVxyXG4gICAgcHVibGljIGlucHV0OiBFbGVtZW50UmVmO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGNvbnRhaW5lciBmb3IgdGhlIGlucHV0IGJveCBhbmQgc3BpbiBidXR0b25zXHJcbiAgICAgKi9cclxuICAgIEBWaWV3Q2hpbGQoJ2NvbnRhaW5lcicpXHJcbiAgICBwdWJsaWMgY29udGFpbmVyOiBFbGVtZW50UmVmO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGluY3JlbWVudCBidXR0b24gVUkgZWxlbWVudFxyXG4gICAgICovXHJcbiAgICBAVmlld0NoaWxkKCdpbmNyZW1lbnRCdXR0b24nKVxyXG4gICAgcHVibGljIGluY3JlbWVudEJ1dHRvbjogRWxlbWVudFJlZjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBkZWNyZW1lbnQgYnV0dG9uIFVJIGVsZW1lbnRcclxuICAgICAqL1xyXG4gICAgQFZpZXdDaGlsZCgnZGVjcmVtZW50QnV0dG9uJylcclxuICAgIHB1YmxpYyBkZWNyZW1lbnRCdXR0b246IEVsZW1lbnRSZWY7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJdCBkZXRlcm1pbmUgd2hldGhlciB0byBzaG93IHRoZSBzcGluIGJ1dHRvbi5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzaG93U3BpbkJ1dHRvbiA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIHNpemUgb2YgZWFjaCBtb3ZlbWVudCBvZiB0aGUgc2xpZGVyLlxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHN0ZXA6IG51bWJlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBzaXplIG9mIGVhY2ggaW5jcmVtZW50L2RlY3JlbWVudCB2YWx1ZSBvZiB0aGUgc2xpZGVyLlxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIGluY3JlbWVudEJ5OiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbWluaW11bSB2YWx1ZSBvZiB0aGUgc2xpZGVyXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgbWluOiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbWF4aW11bSB2YWx1ZSBvZiB0aGUgc2xpZGVyXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgbWF4OiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgU2xpZGVyRm9ybUZpZWxkQ29tcG9uZW50XHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIGluamVjdG9yOiBJbmplY3RvclxyXG4gICAgKSB7XHJcbiAgICAgICAgc3VwZXIoaW5qZWN0b3IpO1xyXG4gICAgICAgIHRoaXMubWluID0gMDtcclxuICAgICAgICAvLyBObyBkZWZhdWx0IG1heGltdW0vc3RlcFxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBuZ09uSW5pdCgpIHtcclxuICAgICAgICBzdXBlci5uZ09uSW5pdCgpO1xyXG5cclxuICAgICAgICAvLyBJZiBpbmNyZW1lbnRCeSBpcyBub3Qgc2V0LCB1c2Ugc3RlcC4gSWYgc3RlcCBpcyBub3Qgc2V0IGRlZmF1bHQgdG8gMSAob25lKVxyXG4gICAgICAgIHRoaXMuaW5jcmVtZW50QnkgPSBNc2Z0U21lLmlzTnVsbE9yVW5kZWZpbmVkKHRoaXMuaW5jcmVtZW50QnkpXHJcbiAgICAgICAgICAgID8gTXNmdFNtZS5pc051bGxPclVuZGVmaW5lZCh0aGlzLnN0ZXApID8gMSA6IHRoaXMuc3RlcFxyXG4gICAgICAgICAgICA6IHRoaXMuaW5jcmVtZW50Qnk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXR0ZXIgYXJpYSBsYWJlbCBpbmNyZWFzZSBmb3Igc3BpbiBidXR0b24gaW5jcmVhc2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgYXJpYUxhYmVsSW5jcmVhc2UoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkZvcm0uU3BpbkJ1dHRvbi5pbmNyZWFzZS5mb3JtYXQodGhpcy5pbmNyZW1lbnRCeSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXR0ZXIgYXJpYSBsYWJlbCBpbmNyZWFzZSBmb3Igc3BpbiBidXR0b24gZGVjcmVhc2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgYXJpYUxhYmVsRGVjcmVhc2UoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkZvcm0uU3BpbkJ1dHRvbi5kZWNyZWFzZS5mb3JtYXQodGhpcy5pbmNyZW1lbnRCeSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIYW5kbGUga2V5ZG93biBldmVudHMgb24gdGhlIG51bWJlciBpbnB1dFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25JbnB1dEtleWRvd24oJGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICAgICAgLy8gSW4gTWljcm9zb2Z0IEVkZ2UgYW5kIElFLCBudW1lcmljIGlucHV0cyB3aWxsIHNjcm9sbCB0aGUgcGFnZSB3aGlsZSBpbmNyZW1lbnRpbmcvZGVjcmVtZW50aW5nIHRoZSBudW1iZXIuXHJcbiAgICAgICAgc3dpdGNoICgkZXZlbnQua2V5Q29kZSkge1xyXG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuVXBBcnJvdzoge1xyXG4gICAgICAgICAgICAgICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICAvLyBmaXJpbmcgdGhlIGNsaWNrIGV2ZW50IHRvIHRyaWdnZXIgdGhlIGNsaWNrIHN0eWxlIHRvIHJlbmRlclxyXG4gICAgICAgICAgICAgICAgdGhpcy5pbmNyZW1lbnQoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMudG9nZ2xlRm9jdXNFdmVudCh0aGlzLmluY3JlbWVudEJ1dHRvbiwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvZ2dsZUZvY3VzRXZlbnQodGhpcy5pbmNyZW1lbnRCdXR0b24sIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRvd25BcnJvdzoge1xyXG4gICAgICAgICAgICAgICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICAvLyBmaXJpbmcgdGhlIGNsaWNrIGV2ZW50IHRvIHRyaWdnZXIgdGhlIGNsaWNrIHN0eWxlIHRvIHJlbmRlclxyXG4gICAgICAgICAgICAgICAgdGhpcy5kZWNyZW1lbnQoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMudG9nZ2xlRm9jdXNFdmVudCh0aGlzLmRlY3JlbWVudEJ1dHRvbiwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvZ2dsZUZvY3VzRXZlbnQodGhpcy5kZWNyZW1lbnRCdXR0b24sIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZGVmYXVsdDogeyByZXR1cm47IH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmNyZW1lbnRzIHRoZSBjb250cm9scyB2YWx1ZSBieSAxIFwic3RlcFwiXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBpbmNyZW1lbnQoKSB7XHJcbiAgICAgICAgbGV0IHZhbHVlID0gTXNmdFNtZS5pc051bWJlcih0aGlzLnZhbHVlKSA/IHRoaXMudmFsdWUgOiB0aGlzLm1pbiAtIDE7XHJcbiAgICAgICAgdmFsdWUgKz0gdGhpcy5pbmNyZW1lbnRCeTtcclxuICAgICAgICBpZiAodmFsdWUgPiB0aGlzLm1heCkge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMubWF4O1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWNyZW1lbnRzIHRoZSBjb250cm9scyB2YWx1ZSBieSAxIFwic3RlcFwiXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkZWNyZW1lbnQoKSB7XHJcbiAgICAgICAgbGV0IHZhbHVlID0gTXNmdFNtZS5pc051bWJlcih0aGlzLnZhbHVlKSA/IHRoaXMudmFsdWUgOiB0aGlzLm1pbiArIDE7XHJcbiAgICAgICAgdmFsdWUgLT0gdGhpcy5pbmNyZW1lbnRCeTtcclxuICAgICAgICBpZiAodmFsdWUgPCB0aGlzLm1pbikge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMubWluO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgZnVuY3Rpb25hbGl0eSB0byBmb2N1cyBvbiB0aGUgaW5wdXQgZmllbGRcclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uSW5wdXRGb2N1cygkZXZlbnQpIHtcclxuICAgICAgICBpZiAoJGV2ZW50KSB7XHJcbiAgICAgICAgICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50b2dnbGVGb2N1c0V2ZW50KHRoaXMuY29udGFpbmVyLCB0cnVlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBmdW5jdGlvbmFsaXR5IHRvIGZvY3VzIG91dCBvbiB0aGUgaW5wdXQgZmllbGRcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gJGV2ZW50IHRoZSBmb2N1cyBldmVudCBvYmplY3RcclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uSW5wdXRGb2N1c091dCgkZXZlbnQpIHtcclxuICAgICAgICBpZiAoJGV2ZW50KSB7XHJcbiAgICAgICAgICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50b2dnbGVGb2N1c0V2ZW50KHRoaXMuY29udGFpbmVyLCBmYWxzZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIHRoZSBpZEJhZyB1c2VkIGJ5IHRoaXMgY29tcG9uZW50IHRvIHN0b3JlIHVuaXF1ZSBlbGVtZW50IGlkcy5cclxuICAgICAqIGlkIHZhbHVlcyB3aWxsIGJlIGFzc2lnbmVkIGJlIHRoZSBAc2VlIEJhc2VDb21wb25lbnQgc3VwZXIgY2xhc3MuXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVJZEJhZygpOiBNc2Z0U21lLlN0cmluZ01hcDxzdHJpbmc+IHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBkZXRhaWxzU3BhbjogJydcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGV0ZXJtaW5lcyB0aGUgdmFsdWUgdG8gdXNlIHdoZW4gY2xlYXJpbmcgdGhlIGZpZWxkIGJhc2VkIG9uIHRoZSBpbml0aWFsIHZhbHVlIHR5cGVcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGdldENsZWFyVmFsdWUoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gTXNmdFNtZS5pc051bGxPclVuZGVmaW5lZCh0aGlzLm1pbikgPyAwIDogdGhpcy5taW47XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQZXJmb3JtcyB2YWxpZGF0aW9uIHRoYXQgaXMgaW50ZXJuYWwgdG8gdGhpcyBjb250cm9sXHJcbiAgICAgKiBAcGFyYW0gYyBUaGUgZm9ybSBjb250cm9sIGF0dGFjaGVkIHRvIHRoaXMgaW5zdGFuY2VcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIHZhbGlkYXRlKGM6IEZvcm1Db250cm9sKTogVmFsaWRhdGlvbkVycm9ycyB7XHJcbiAgICAgICAgLy8gaWYgbm90IHJlcXVpcmVkLCBkb24ndCBwcm9jZXNzIG51bGwgb3IgZW1wdHkgdmFsdWVzIGZvciBmdXJ0aGVyIHZhbGlkYXRpb25cclxuICAgICAgICBpZiAoIXRoaXMucmVxdWlyZWQgJiYgKE1zZnRTbWUuaXNOdWxsT3JXaGl0ZVNwYWNlKGMudmFsdWUpKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gc3VwZXIudmFsaWRhdGUoYyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIU1zZnRTbWUuaXNOdW1iZXIodGhpcy52YWx1ZSkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIG5vdEFOdW1iZXI6IHtcclxuICAgICAgICAgICAgICAgICAgICB2YWxpZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkNvbW1vbi5Gb3JtLlZhbGlkYXRpb24uaXNOdW1iZXIuZm9ybWF0LmZvcm1hdCh0aGlzLmZpZWxkTmFtZSksXHJcbiAgICAgICAgICAgICAgICAgICAgc2V2ZXJpdHk6IFZhbGlkYXRpb25BbGVydFNldmVyaXR5LkVycm9yXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIGFuZ3VsYXIncyBtaW4gYW5kIG1heCB2YWxpZGF0b3Igb25seSB3b3JrIHZpYSBjb2RlLiBTbyB3ZSBpbXBsZW1lbnQgdGhlbSBoZXJlLlxyXG4gICAgICAgIGlmICghTXNmdFNtZS5pc051bGxPclVuZGVmaW5lZCh0aGlzLm1pbikgJiYgdGhpcy52YWx1ZSA8IHRoaXMubWluKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVycm9ycyA9IFZhbGlkYXRvcnMubWluKHRoaXMubWluKShjKTtcclxuICAgICAgICAgICAgaWYgKGVycm9ycykgeyByZXR1cm4gZXJyb3JzOyB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIU1zZnRTbWUuaXNOdWxsT3JVbmRlZmluZWQodGhpcy5tYXgpICYmIHRoaXMudmFsdWUgPiB0aGlzLm1heCkge1xyXG4gICAgICAgICAgICBjb25zdCBlcnJvcnMgPSBWYWxpZGF0b3JzLm1heCh0aGlzLm1heCkoYyk7XHJcbiAgICAgICAgICAgIGlmIChlcnJvcnMpIHsgcmV0dXJuIGVycm9yczsgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCFNc2Z0U21lLmlzTnVsbE9yVW5kZWZpbmVkKHRoaXMuc3RlcCkpIHtcclxuICAgICAgICAgICAgLy8gSWYgc3RlcCBpcyB1c2VkIGNoZWNrIGlmIHRoZSBjdXJyZW50IHZhbHVlIGZhbGxzIHdpdGhpbiB0aGUgcmFuZ2Ugb2YgdGhlIGxlZ2FsIHZhbHVlc1xyXG4gICAgICAgICAgICBjb25zdCBzYWZlUmVtID0gdGhpcy5nZXRTYWZlUmVtYWluZGVyKCh0aGlzLnZhbHVlIC0gdGhpcy5taW4pLCB0aGlzLnN0ZXApO1xyXG4gICAgICAgICAgICAvLyBSb3VuZCBvZmYgdG8gdGhlIG5lYXJlc3QgaW50ZWdlciwgaGFuZGxlIGFueSBmbG9hdGluZyBwcmVjaXNpb24gZXJyb3JzIHRoYXQgbWF5IG9jY3VyXHJcbiAgICAgICAgICAgIGNvbnN0IHJlbSA9IE1hdGgucm91bmQoKHNhZmVSZW0gKyBOdW1iZXIuRVBTSUxPTikgKiAxMDApIC8gMTAwO1xyXG5cclxuICAgICAgICAgICAgaWYgKHJlbSAhPT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICBub3RBTXVsdGlwbGVPZlN0ZXA6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWQ6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiB0aGlzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuQ29tbW9uLkZvcm0uVmFsaWRhdGlvbi5JbGxlZ2FsTnVtYmVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZm9ybWF0KHRoaXMuZmllbGROYW1lLCB0aGlzLnN0ZXAsIHRoaXMubWluKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2V2ZXJpdHk6IFZhbGlkYXRpb25BbGVydFNldmVyaXR5LkVycm9yXHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHN1cGVyLnZhbGlkYXRlKGMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgcmVtYWluZGVyIG9mIGEgZGl2aXNpb24gb3BlcmF0aW9uIGJ5IGNvbnZlcnRpbmcgYW55IGRlY2ltYWxzIHRvIGludGVnZXJzIGZpcnN0XHJcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIG51bWJlciB0byBiZSBkaXZpZGVkXHJcbiAgICAgKiBAcGFyYW0gZGl2aXNvciBUaGUgZGl2aWRpbmcgbnVtYmVyXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBnZXRTYWZlUmVtYWluZGVyKHZhbHVlOiBudW1iZXIsIGRpdmlzb3I6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgdmFsdWVEZWNpbWFscyA9ICh2YWx1ZS50b1N0cmluZygpLnNwbGl0KCcuJylbMV0gfHwgJycpLmxlbmd0aDtcclxuICAgICAgICBjb25zdCBkaXZpc29yRGVjaW1hbHMgPSAoZGl2aXNvci50b1N0cmluZygpLnNwbGl0KCcuJylbMV0gfHwgJycpLmxlbmd0aDtcclxuICAgICAgICBjb25zdCBtYXhEZWNpbWFscyA9IE1hdGgubWF4KHZhbHVlRGVjaW1hbHMsIGRpdmlzb3JEZWNpbWFscyk7XHJcbiAgICAgICAgY29uc3QgdmFsdWVJbnQgPSBwYXJzZUludCh2YWx1ZS50b0ZpeGVkKG1heERlY2ltYWxzKS5yZXBsYWNlKCcuJywgJycpLCAxMCk7XHJcbiAgICAgICAgY29uc3QgZGl2aXNvckludCA9IHBhcnNlSW50KGRpdmlzb3IudG9GaXhlZChtYXhEZWNpbWFscykucmVwbGFjZSgnLicsICcnKSwgMTApO1xyXG4gICAgICAgIHJldHVybiAodmFsdWVJbnQgJSBkaXZpc29ySW50KSAvIE1hdGgucG93KDEwLCBtYXhEZW