UNPKG

ontimize-web-ngx

Version:
313 lines 56.3 kB
import { Component, ElementRef, EventEmitter, forwardRef, Inject, Injector, Input, Optional, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import * as lpn from 'google-libphonenumber'; import { Codes } from '../../../util/codes'; import { Util } from '../../../util/util'; import { OValidators } from '../../../validators/o-validators'; import { OFormValue } from '../../form/o-form-value'; import { OFormComponent } from '../../form/o-form.component'; import { OFormDataComponent } from '../../o-form-data-component.class'; import { CountryCode } from './data/country-code'; import { CountryISO } from './enums/country-iso.enum'; import { PhoneNumberFormat } from './enums/phone-number-format.enum'; import * as i0 from "@angular/core"; import * as i1 from "./data/country-code"; import * as i2 from "@angular/common"; import * as i3 from "@angular/flex-layout/flex"; import * as i4 from "@angular/forms"; import * as i5 from "../../../directives/o-mat-error.directive"; import * as i6 from "@angular/material/core"; import * as i7 from "@angular/material/button"; import * as i8 from "@angular/material/icon"; import * as i9 from "@angular/material/input"; import * as i10 from "@angular/material/form-field"; import * as i11 from "@angular/material/select"; import * as i12 from "../../../pipes/o-translate.pipe"; import * as i13 from "../../form/o-form.component"; export const DEFAULT_INPUTS_O_PHONE_INPUT = [ 'gap' ]; const PHONE_PREFIX = '+'; export class OPhoneInputComponent extends OFormDataComponent { set selectedCountry(value) { this._selectedCountry = value; this.placeHolder = this.resolvePlaceholder(); } get selectedCountry() { return this._selectedCountry; } constructor(countryCodeData, form, elRef, injector) { super(form, elRef, injector); this.countryCodeData = countryCodeData; this.countries = []; this.countryChange = new EventEmitter(); this.onPhoneDataChange = new EventEmitter(); this.gap = '14px'; this._selectedCountry = { areaCodes: undefined, dialCode: '', htmlId: '', flagClass: '', iso2: '', name: '', placeHolder: '', priority: 0, }; this.allCountries = []; this.states = CountryISO; this.selectedStates = this.states; this.phoneUtil = lpn.PhoneNumberUtil.getInstance(); this.separateDialCode = true; this.numberFormat = PhoneNumberFormat.International; this.fetchCountryData(); } initialize() { this.initializeCountryData(); super.initialize(); const formControl = this.getFormControl(); if (formControl) { const self = this; formControl.getValue = function () { if (this.value && this.value.length > 0 && self.selectedCountry && self.selectedCountry.dialCode) { return `+${self.selectedCountry.dialCode} ${this.value}`; } return undefined; }; } } ngAfterViewInit() { super.ngAfterViewInit(); if (this.oInputsOptions.iconColor === Codes.O_INPUTS_OPTIONS_COLOR_ACCENT) { const matFormFieldEL = this.elRef.nativeElement.getElementsByTagName('mat-form-field')[1]; if (Util.isDefined(matFormFieldEL)) { matFormFieldEL.classList.add('accent'); } } } addOntimizeCustomAppearanceClass() { try { if (this.elRef) { const matFormFieldEl = this.elRef.nativeElement.querySelectorAll('mat-form-field'); matFormFieldEl.forEach(matForm => { matForm.classList.add('mat-form-field-appearance-ontimize'); }); } } catch (e) { } } getValue() { const formControl = this.getFormControl(); if (formControl) { return formControl.getValue(); } return super.getValue(); } resolveValidators() { const validators = super.resolveValidators(); const createPhoneValidator = (() => { return OValidators.phoneValidator(this.getFormControl(), this.getSelectedCountryIso2()); }); validators.push(createPhoneValidator); return validators; } onFormControlChange(value) { if (!this.value) { this.value = new OFormValue(); } this.ensureOFormValue(value); this.ensurePhoneValue(value); this.onChange.emit(value); } setFormValue(val, options, setDirty = false) { let { countryDialCode, number } = this.getSeparatedValues(val); let country = this.getCountryByDialCode(countryDialCode); const parsed = this.getParsedNumber(number, country ? country.iso2 : undefined); if (!Util.isDefined(parsed)) { number = undefined; country = undefined; } this.selectedCountry = country; this.ensureOFormValue(number); if (this._fControl) { this._fControl.setValue(this.value.value, options); if (setDirty) { this._fControl.markAsDirty(); } if (this._fControl.invalid && !this.form.isInInsertMode()) { this._fControl.markAsTouched(); } } this.oldValue = this.value.value; } onCountrySelect(value) { const country = value.value; this.countryChange.emit(country); this.setValue(undefined); this.selectedCountry = country; if (this.matInputRef && this.matInputRef.nativeElement) { setTimeout(() => { this.matInputRef.nativeElement.focus(); }, 0); } } innerOnBlur(event) { super.innerOnBlur(event); if (this._fControl) { this._fControl.updateValueAndValidity({ emitEvent: false }); } } getSelectedCountryIso2() { return this.selectedCountry ? this.selectedCountry.iso2 : undefined; } initializeCountryData() { if (this.countries.length) { this.allCountries = this.allCountries.filter((c) => this.countries.includes(c.iso2)); } } ensurePhoneValue(value) { const number = this.getParsedNumber(value, this.getSelectedCountryIso2()); if (number) { const intlNo = number ? this.phoneUtil.format(number, lpn.PhoneNumberFormat.INTERNATIONAL) : ''; if (intlNo) { this.value.value = this.removeDialCode(intlNo); this.emitPhoneInputData(intlNo, number); } } } getCountryByDialCode(countryDialCode) { if (countryDialCode) { return this.sortCountries().find((c) => c.dialCode === countryDialCode); } return undefined; } sortCountries() { return this.allCountries .sort((a, b) => { return a.priority - b.priority; }); } getSeparatedValues(value) { let countryDialCode = ''; let number = (value instanceof OFormValue ? value.value : value) || undefined; if (Util.isDefined(number) && number.startsWith(PHONE_PREFIX)) { countryDialCode = number.substr(1, number.indexOf(' ') - 1); number = number.substr(countryDialCode.length + 2); } return { countryDialCode, number }; } emitPhoneInputData(intlNo, number) { let phoneInputData = undefined; const iso2 = this.getSelectedCountryIso2(); if (intlNo && number && iso2) { phoneInputData = { number: this.value.value, internationalNumber: intlNo, nationalNumber: number ? this.phoneUtil.format(number, lpn.PhoneNumberFormat.NATIONAL) : '', e164Number: number ? this.phoneUtil.format(number, lpn.PhoneNumberFormat.E164) : '', countryCode: iso2.toUpperCase(), dialCode: PHONE_PREFIX + this.selectedCountry.dialCode, }; } this.onPhoneDataChange.emit(phoneInputData); } getParsedNumber(phoneNumber, countryCode) { let number; try { number = this.phoneUtil.parse(phoneNumber, countryCode.toUpperCase()); } catch (e) { } return number; } removeDialCode(phoneNumber) { const number = this.getParsedNumber(phoneNumber, this.getSelectedCountryIso2()); phoneNumber = this.phoneUtil.format(number, lpn.PhoneNumberFormat[this.numberFormat]); if (phoneNumber.startsWith(PHONE_PREFIX) && this.separateDialCode) { phoneNumber = phoneNumber.substring(phoneNumber.indexOf(' ') + 1); } return phoneNumber; } getCountryIsoCode(countryCode, number) { const rawNumber = number['values_']['2'].toString(); const countries = this.allCountries.filter((c) => c.dialCode === countryCode.toString()); const mainCountry = countries.find((c) => c.areaCodes === undefined); const secondaryCountries = countries.filter((c) => c.areaCodes !== undefined); let matchedCountry = mainCountry ? mainCountry.iso2 : undefined; secondaryCountries.forEach((country) => { country.areaCodes.forEach((areaCode) => { if (rawNumber.startsWith(areaCode)) { matchedCountry = country.iso2; } }); }); return matchedCountry; } getPhoneNumberPlaceHolder(countryCode) { try { return this.phoneUtil.format(this.phoneUtil.getExampleNumber(countryCode), lpn.PhoneNumberFormat[this.numberFormat]); } catch (e) { return e; } } fetchCountryData() { this.allCountries = []; this.countryCodeData.allCountries.forEach((c) => { const country = { name: c[0].toString(), iso2: c[1].toString(), dialCode: c[2].toString(), priority: +c[3] || 0, areaCodes: c[4] || undefined, htmlId: `iti-0__item-${c[1].toString()}`, flagClass: `iti__${c[1].toString().toLocaleLowerCase()}`, placeHolder: '', }; if (!this.oplaceholder) { country.placeHolder = this.getPhoneNumberPlaceHolder(country.iso2.toUpperCase()); } this.allCountries.push(country); }); } resolvePlaceholder() { let placeholder = ''; if (this.selectedCountry && this.selectedCountry.placeHolder && this.selectedCountry.placeHolder.length > 0) { placeholder = this.selectedCountry.placeHolder; if (this.separateDialCode) { placeholder = this.removeDialCode(placeholder); } } return placeholder; } } OPhoneInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OPhoneInputComponent, deps: [{ token: i1.CountryCode }, { token: forwardRef(() => OFormComponent), optional: true }, { token: i0.ElementRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); OPhoneInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OPhoneInputComponent, selector: "o-phone-input", inputs: { gap: "gap", countries: "countries" }, outputs: { countryChange: "countryChange", onPhoneDataChange: "onPhoneDataChange" }, host: { properties: { "class.o-phone-input": "true" } }, providers: [CountryCode], viewQueries: [{ propertyName: "countryList", first: true, predicate: ["countryList"], descendants: true }, { propertyName: "matInputRef", first: true, predicate: ["matInputRef"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, ngImport: i0, template: "<div [formGroup]=\"getFormGroup()\" fxLayout=\"row wrap\" [fxLayoutGap]=\"gap +' grid'\">\n <mat-form-field class=\"mat-form-phone\" [floatLabel]=\"floatLabel\" [appearance]=\"appearance\" [class.read-only]=\"isReadOnly\" fxFlex.xs\n [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <mat-select [value]=\"selectedCountry\" (selectionChange)=\"onCountrySelect($event)\" [disabled]=\"!enabled\">\n <mat-option *ngFor=\"let country of allCountries\" [value]=\"country\"> {{country.name}} +{{country.dialCode}}</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field [hideRequiredMarker]=\"hideRequiredMarker\" [class.custom-width]=\"hasCustomWidth\" class=\"icon-field\" [appearance]=\"appearance\"\n [subscriptSizing]=\"subscriptSizing\" fxFlex>\n <input #matInputRef matInput type=\"tel\" [id]=\"getAttribute()\" [formControlName]=\"getAttribute()\" [placeholder]=\"placeHolder\"\n (focus)=\"innerOnFocus($event)\" (blur)=\"innerOnBlur($event)\" [readonly]=\"isReadOnly\" (change)=\"onChangeEvent($event)\" [required]=\"isRequired\">\n <button type=\"button\" *ngIf=\"showClearButton\" matSuffix mat-icon-button (click)=\"onClickClearValue($event)\">\n <mat-icon svgIcon=\"ontimize:close\"></mat-icon>\n </button>\n <mat-icon matSuffix [class.mat-disabled]=\"!enabled\" class=\"svg-icon\" svgIcon=\"ontimize:phone_outline\"></mat-icon>\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('validatePhoneNumber')\">\n {{ 'FORM_VALIDATION.PHONE_FORMAT' | oTranslate }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n</div>\n", styles: [".o-phone-input{overflow:hidden}.o-phone-input .read-only{pointer-events:none}.o-phone-input .read-only .mat-mdc-select-arrow-wrapper{visibility:hidden}.o-phone-input .read-only .mdc-line-ripple:after{background-image:none}.o-phone-input .mat-mdc-form-field.icon-field{height:100%}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i3.DefaultLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i3.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5.OMatErrorDirective, selector: "[oMatError]", inputs: ["oMatError"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i11.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "pipe", type: i12.OTranslatePipe, name: "oTranslate" }], encapsulation: i0.ViewEncapsulation.None }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OPhoneInputComponent, decorators: [{ type: Component, args: [{ selector: 'o-phone-input', inputs: DEFAULT_INPUTS_O_PHONE_INPUT, encapsulation: ViewEncapsulation.None, providers: [CountryCode], host: { '[class.o-phone-input]': 'true' }, template: "<div [formGroup]=\"getFormGroup()\" fxLayout=\"row wrap\" [fxLayoutGap]=\"gap +' grid'\">\n <mat-form-field class=\"mat-form-phone\" [floatLabel]=\"floatLabel\" [appearance]=\"appearance\" [class.read-only]=\"isReadOnly\" fxFlex.xs\n [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <mat-select [value]=\"selectedCountry\" (selectionChange)=\"onCountrySelect($event)\" [disabled]=\"!enabled\">\n <mat-option *ngFor=\"let country of allCountries\" [value]=\"country\"> {{country.name}} +{{country.dialCode}}</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field [hideRequiredMarker]=\"hideRequiredMarker\" [class.custom-width]=\"hasCustomWidth\" class=\"icon-field\" [appearance]=\"appearance\"\n [subscriptSizing]=\"subscriptSizing\" fxFlex>\n <input #matInputRef matInput type=\"tel\" [id]=\"getAttribute()\" [formControlName]=\"getAttribute()\" [placeholder]=\"placeHolder\"\n (focus)=\"innerOnFocus($event)\" (blur)=\"innerOnBlur($event)\" [readonly]=\"isReadOnly\" (change)=\"onChangeEvent($event)\" [required]=\"isRequired\">\n <button type=\"button\" *ngIf=\"showClearButton\" matSuffix mat-icon-button (click)=\"onClickClearValue($event)\">\n <mat-icon svgIcon=\"ontimize:close\"></mat-icon>\n </button>\n <mat-icon matSuffix [class.mat-disabled]=\"!enabled\" class=\"svg-icon\" svgIcon=\"ontimize:phone_outline\"></mat-icon>\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *oMatError=\"hasError('validatePhoneNumber')\">\n {{ 'FORM_VALIDATION.PHONE_FORMAT' | oTranslate }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n</div>\n", styles: [".o-phone-input{overflow:hidden}.o-phone-input .read-only{pointer-events:none}.o-phone-input .read-only .mat-mdc-select-arrow-wrapper{visibility:hidden}.o-phone-input .read-only .mdc-line-ripple:after{background-image:none}.o-phone-input .mat-mdc-form-field.icon-field{height:100%}\n"] }] }], ctorParameters: function () { return [{ type: i1.CountryCode }, { type: i13.OFormComponent, decorators: [{ type: Optional }, { type: Inject, args: [forwardRef(() => OFormComponent)] }] }, { type: i0.ElementRef }, { type: i0.Injector }]; }, propDecorators: { countries: [{ type: Input }], countryChange: [{ type: Output }], onPhoneDataChange: [{ type: Output }], countryList: [{ type: ViewChild, args: ['countryList'] }], matInputRef: [{ type: ViewChild, args: ['matInputRef', { read: ElementRef, static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiby1waG9uZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9vbnRpbWl6ZS13ZWItbmd4L3NyYy9saWIvY29tcG9uZW50cy9pbnB1dC9waG9uZS1pbnB1dC9vLXBob25lLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L3Bob25lLWlucHV0L28tcGhvbmUtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixNQUFNLEVBQ04sUUFBUSxFQUNSLEtBQUssRUFFTCxRQUFRLEVBQ1IsTUFBTSxFQUNOLFNBQVMsRUFDVCxpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxLQUFLLEdBQUcsTUFBTSx1QkFBdUIsQ0FBQztBQUc3QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDNUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUMvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFHTCxrQkFBa0IsRUFDbkIsTUFBTSxtQ0FBbUMsQ0FBQztBQUUzQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDOzs7Ozs7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TUFBTSxHQUFHLENBQUMsRUFBRTtZQUMzRyxXQUFXLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUM7WUFDL0MsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3pCLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO2FBQ2hEO1NBQ0Y7UUFDRCxPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDOztrSEFwVlUsb0JBQW9CLDZDQXlDVCxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFDO3NHQXpDM0Msb0JBQW9CLHNPQUxwQixDQUFDLFdBQVcsQ0FBQyw4TUFXVSxVQUFVLGtFQzdEOUMsNjBEQTJCQTs0RkQ0QmEsb0JBQW9CO2tCQVhoQyxTQUFTOytCQUNFLGVBQWUsVUFHakIsNEJBQTRCLGlCQUNyQixpQkFBaUIsQ0FBQyxJQUFJLGFBQzFCLENBQUMsV0FBVyxDQUFDLFFBQ2xCO3dCQUNKLHVCQUF1QixFQUFFLE1BQU07cUJBQ2hDOzswQkEyQ0UsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFDOzRGQXhDN0MsU0FBUztzQkFBakIsS0FBSztnQkFDYSxhQUFhO3NCQUEvQixNQUFNO2dCQUNZLGlCQUFpQjtzQkFBbkMsTUFBTTtnQkFFbUIsV0FBVztzQkFBcEMsU0FBUzt1QkFBQyxhQUFhO2dCQUM4QyxXQUFXO3NCQUFoRixTQUFTO3VCQUFDLGFBQWEsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBJbmplY3QsXG4gIEluamVjdG9yLFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPcHRpb25hbCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVmFsaWRhdG9yRm4gfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBNYXRTZWxlY3RDaGFuZ2UgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xuaW1wb3J0ICogYXMgbHBuIGZyb20gJ2dvb2dsZS1saWJwaG9uZW51bWJlcic7XG5cbmltcG9ydCB7IEZvcm1WYWx1ZU9wdGlvbnMgfSBmcm9tICcuLi8uLi8uLi90eXBlcy9mb3JtLXZhbHVlLW9wdGlvbnMudHlwZSc7XG5pbXBvcnQgeyBDb2RlcyB9IGZyb20gJy4uLy4uLy4uL3V0aWwvY29kZXMnO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwvdXRpbCc7XG5pbXBvcnQgeyBPVmFsaWRhdG9ycyB9IGZyb20gJy4uLy4uLy4uL3ZhbGlkYXRvcnMvby12YWxpZGF0b3JzJztcbmltcG9ydCB7IE9Gb3JtVmFsdWUgfSBmcm9tICcuLi8uLi9mb3JtL28tZm9ybS12YWx1ZSc7XG5pbXBvcnQgeyBPRm9ybUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2Zvcm0vby1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQge1xuICBERUZBVUxUX0lOUFVUU19PX0ZPUk1fREFUQV9DT01QT05FTlQsXG4gIERFRkFVTFRfT1VUUFVUU19PX0ZPUk1fREFUQV9DT01QT05FTlQsXG4gIE9Gb3JtRGF0YUNvbXBvbmVudFxufSBmcm9tICcuLi8uLi9vLWZvcm0tZGF0YS1jb21wb25lbnQuY2xhc3MnO1xuaW1wb3J0IHsgT0Zvcm1Db250cm9sIH0gZnJvbSAnLi4vby1mb3JtLWNvbnRyb2wuY2xhc3MnO1xuaW1wb3J0IHsgQ291bnRyeUNvZGUgfSBmcm9tICcuL2RhdGEvY291bnRyeS1jb2RlJztcbmltcG9ydCB7IENvdW50cnlJU08gfSBmcm9tICcuL2VudW1zL2NvdW50cnktaXNvLmVudW0nO1xuaW1wb3J0IHsgUGhvbmVOdW1iZXJGb3JtYXQgfSBmcm9tICcuL2VudW1zL3Bob25lLW51bWJlci1mb3JtYXQuZW51bSc7XG5pbXBvcnQgeyBPUGhvbmVJbnB1dERhdGEgfSBmcm9tICcuL2ludGVyZmFjZXMvY2hhbmdlLWRhdGEnO1xuaW1wb3J0IHsgQ291bnRyeSB9IGZyb20gJy4vbW9kZWwvY291bnRyeS5tb2RlbCc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0lOUFVUU19PX1BIT05FX0lOUFVUID0gW1xuICAvL2dhcDogU3BlY2lmeSBnYXAgYmV0d2VlbiBmaWVsZHMgaW4gcHhcbiAgJ2dhcCdcbl07XG5cbmNvbnN0IFBIT05FX1BSRUZJWCA9ICcrJ1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdvLXBob25lLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL28tcGhvbmUtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9vLXBob25lLWlucHV0LmNvbXBvbmVudC5zY3NzJ10sXG4gIGlucHV0czogREVGQVVMVF9JTlBVVFNfT19QSE9ORV9JTlBVVCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgcHJvdmlkZXJzOiBbQ291bnRyeUNvZGVdLFxuICBob3N0OiB7XG4gICAgJ1tjbGFzcy5vLXBob25lLWlucHV0XSc6ICd0cnVlJ1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIE9QaG9uZUlucHV0Q29tcG9uZW50IGV4dGVuZHMgT0Zvcm1EYXRhQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcbiAgQElucHV0KCkgY291bnRyaWVzOiBBcnJheTxzdHJpbmc+ID0gW107XG4gIEBPdXRwdXQoKSByZWFkb25seSBjb3VudHJ5Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxDb3VudHJ5PigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgb25QaG9uZURhdGFDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPE9QaG9uZUlucHV0RGF0YT4oKTtcblxuICBAVmlld0NoaWxkKCdjb3VudHJ5TGlzdCcpIGNvdW50cnlMaXN0OiBFbGVtZW50UmVmO1xuICBAVmlld0NoaWxkKCdtYXRJbnB1dFJlZicsIHsgcmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgbWF0SW5wdXRSZWYhOiBFbGVtZW50UmVmO1xuICBwdWJsaWMgZ2FwID0gJzE0cHgnO1xuXG4gIF9zZWxlY3RlZENvdW50cnk6IENvdW50cnkgPSB7XG4gICAgYXJlYUNvZGVzOiB1bmRlZmluZWQsXG4gICAgZGlhbENvZGU6ICcnLFxuICAgIGh0bWxJZDogJycsXG4gICAgZmxhZ0NsYXNzOiAnJyxcbiAgICBpc28yOiAnJyxcbiAgICBuYW1lOiAnJyxcbiAgICBwbGFjZUhvbGRlcjogJycsXG4gICAgcHJpb3JpdHk6IDAsXG4gIH07XG5cbiAgc2V0IHNlbGVjdGVkQ291bnRyeSh2YWx1ZTogQ291bnRyeSkge1xuICAgIHRoaXMuX3NlbGVjdGVkQ291bnRyeSA9IHZhbHVlO1xuICAgIHRoaXMucGxhY2VIb2xkZXIgPSB0aGlzLnJlc29sdmVQbGFjZWhvbGRlcigpO1xuICB9XG5cbiAgZ2V0IHNlbGVjdGVkQ291bnRyeSgpOiBDb3VudHJ5IHtcbiAgICByZXR1cm4gdGhpcy5fc2VsZWN0ZWRDb3VudHJ5O1xuICB9XG5cbiAgYWxsQ291bnRyaWVzOiBBcnJheTxDb3VudHJ5PiA9IFtdO1xuXG4gIHN0YXRlcyA9IENvdW50cnlJU087XG4gIHNlbGVjdGVkU3RhdGVzID0gdGhpcy5zdGF0ZXM7XG5cbiAgLy8gSGFzIHRvIGJlICdhbnknIHRvIHByZXZlbnQgYSBuZWVkIHRvIGluc3RhbGwgQHR5cGVzL2dvb2dsZS1saWJwaG9uZW51bWJlciBieSB0aGUgcGFja2FnZSB1c2VyLi4uXG4gIHByb3RlY3RlZCBwaG9uZVV0aWw6IGFueSA9IGxwbi5QaG9uZU51bWJlclV0aWwuZ2V0SW5zdGFuY2UoKTtcbiAgcHJvdGVjdGVkIHNlcGFyYXRlRGlhbENvZGUgPSB0cnVlO1xuICBwcm90ZWN0ZWQgbnVtYmVyRm9ybWF0OiBQaG9uZU51bWJlckZvcm1hdCA9IFBob25lTnVtYmVyRm9ybWF0LkludGVybmF0aW9uYWw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBjb3VudHJ5Q29kZURhdGE6IENvdW50cnlDb2RlLFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBPRm9ybUNvbXBvbmVudCkpIGZvcm06IE9Gb3JtQ29tcG9uZW50LFxuICAgIGVsUmVmOiBFbGVtZW50UmVmLFxuICAgIGluamVjdG9yOiBJbmplY3RvclxuICApIHtcbiAgICBzdXBlcihmb3JtLCBlbFJlZiwgaW5qZWN0b3IpO1xuICAgIHRoaXMuZmV0Y2hDb3VudHJ5RGF0YSgpO1xuICB9XG5cbiAgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICB0aGlzLmluaXRpYWxpemVDb3VudHJ5RGF0YSgpO1xuICAgIHN1cGVyLmluaXRpYWxpemUoKTtcbiAgICBjb25zdCBmb3JtQ29udHJvbCA9IHRoaXMuZ2V0Rm9ybUNvbnRyb2woKSBhcyBPRm9ybUNvbnRyb2w7XG4gICAgaWYgKGZvcm1Db250cm9sKSB7XG4gICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgIGZvcm1Db250cm9sLmdldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy52YWx1ZSAmJiB0aGlzLnZhbHVlLmxlbmd0aCA+IDAgJiYgc2VsZi5zZWxlY3RlZENvdW50cnkgJiYgc2VsZi5zZWxlY3RlZENvdW50cnkuZGlhbENvZGUpIHtcbiAgICAgICAgICByZXR1cm4gYCske3NlbGYuc2VsZWN0ZWRDb3VudHJ5LmRpYWxDb2RlfSAke3RoaXMudmFsdWV9YDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHN1cGVyLm5nQWZ0ZXJWaWV3SW5pdCgpO1xuICAgIGlmICh0aGlzLm9JbnB1dHNPcHRpb25zLmljb25Db2xvciA9PT0gQ29kZXMuT19JTlBVVFNfT1BUSU9OU19DT0xPUl9BQ0NFTlQpIHtcbiAgICAgIGNvbnN0IG1hdEZvcm1GaWVsZEVMID0gdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdtYXQtZm9ybS1maWVsZCcpWzFdO1xuICAgICAgaWYgKFV0aWwuaXNEZWZpbmVkKG1hdEZvcm1GaWVsZEVMKSkge1xuICAgICAgICBtYXRGb3JtRmllbGRFTC5jbGFzc0xpc3QuYWRkKCdhY2NlbnQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYWRkT250aW1pemVDdXN0b21BcHBlYXJhbmNlQ2xhc3MoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmVsUmVmKSB7XG4gICAgICAgIGNvbnN0IG1hdEZvcm1GaWVsZEVsID0gdGhpcy5lbFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ21hdC1mb3JtLWZpZWxkJyk7XG4gICAgICAgIG1hdEZvcm1GaWVsZEVsLmZvckVhY2gobWF0Rm9ybSA9PiB7XG4gICAgICAgICAgbWF0Rm9ybS5jbGFzc0xpc3QuYWRkKCdtYXQtZm9ybS1maWVsZC1hcHBlYXJhbmNlLW9udGltaXplJyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vXG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldFZhbHVlKCk6IGFueSB7XG4gICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmdldEZvcm1Db250cm9sKCkgYXMgT0Zvcm1Db250cm9sO1xuICAgIGlmIChmb3JtQ29udHJvbCkge1xuICAgICAgcmV0dXJuIGZvcm1Db250cm9sLmdldFZhbHVlKCk7XG4gICAgfVxuICAgIHJldHVybiBzdXBlci5nZXRWYWx1ZSgpO1xuICB9XG5cbiAgcmVzb2x2ZVZhbGlkYXRvcnMoKTogVmFsaWRhdG9yRm5bXSB7XG4gICAgY29uc3QgdmFsaWRhdG9yczogVmFsaWRhdG9yRm5bXSA9IHN1cGVyLnJlc29sdmVWYWxpZGF0b3JzKCk7XG4gICAgY29uc3QgY3JlYXRlUGhvbmVWYWxpZGF0b3IgPSAoKCkgPT4ge1xuICAgICAgcmV0dXJuIE9WYWxpZGF0b3JzLnBob25lVmFsaWRhdG9yKHRoaXMuZ2V0Rm9ybUNvbnRyb2woKSwgdGhpcy5nZXRTZWxlY3RlZENvdW50cnlJc28yKCkpO1xuICAgIH0pO1xuICAgIHZhbGlkYXRvcnMucHVzaChjcmVhdGVQaG9uZVZhbGlkYXRvcik7XG4gICAgcmV0dXJuIHZhbGlkYXRvcnM7XG4gIH1cblxuICBvbkZvcm1Db250cm9sQ2hhbmdlKHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudmFsdWUpIHtcbiAgICAgIHRoaXMudmFsdWUgPSBuZXcgT0Zvcm1WYWx1ZSgpO1xuICAgIH1cbiAgICB0aGlzLmVuc3VyZU9Gb3JtVmFsdWUodmFsdWUpO1xuICAgIHRoaXMuZW5zdXJlUGhvbmVWYWx1ZSh2YWx1ZSk7XG4gICAgdGhpcy5vbkNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRGb3JtVmFsdWUodmFsOiBhbnksIG9wdGlvbnM/OiBGb3JtVmFsdWVPcHRpb25zLCBzZXREaXJ0eTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgbGV0IHsgY291bnRyeURpYWxDb2RlLCBudW1iZXIgfSA9IHRoaXMuZ2V0U2VwYXJhdGVkVmFsdWVzKHZhbCk7XG4gICAgbGV0IGNvdW50cnkgPSB0aGlzLmdldENvdW50cnlCeURpYWxDb2RlKGNvdW50cnlEaWFsQ29kZSk7XG4gICAgY29uc3QgcGFyc2VkID0gdGhpcy5nZXRQYXJzZWROdW1iZXIobnVtYmVyLCBjb3VudHJ5ID8gY291bnRyeS5pc28yIDogdW5kZWZpbmVkKTtcbiAgICBpZiAoIVV0aWwuaXNEZWZpbmVkKHBhcnNlZCkpIHtcbiAgICAgIG51bWJlciA9IHVuZGVmaW5lZDtcbiAgICAgIGNvdW50cnkgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuc2VsZWN0ZWRDb3VudHJ5ID0gY291bnRyeTtcbiAgICB0aGlzLmVuc3VyZU9Gb3JtVmFsdWUobnVtYmVyKTtcbiAgICBpZiAodGhpcy5fZkNvbnRyb2wpIHtcbiAgICAgIHRoaXMuX2ZDb250cm9sLnNldFZhbHVlKHRoaXMudmFsdWUudmFsdWUsIG9wdGlvbnMpO1xuICAgICAgaWYgKHNldERpcnR5KSB7XG4gICAgICAgIHRoaXMuX2ZDb250cm9sLm1hcmtBc0RpcnR5KCk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5fZkNvbnRyb2wuaW52YWxpZCAmJiAhdGhpcy5mb3JtLmlzSW5JbnNlcnRNb2RlKCkpIHtcbiAgICAgICAgdGhpcy5fZkNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLm9sZFZhbHVlID0gdGhpcy52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIG9uQ291bnRyeVNlbGVjdCh2YWx1ZTogTWF0U2VsZWN0Q2hhbmdlKSB7XG4gICAgY29uc3QgY291bnRyeTogQ291bnRyeSA9IHZhbHVlLnZhbHVlXG4gICAgdGhpcy5jb3VudHJ5Q2hhbmdlLmVtaXQoY291bnRyeSk7XG4gICAgdGhpcy5zZXRWYWx1ZSh1bmRlZmluZWQpO1xuICAgIHRoaXMuc2VsZWN0ZWRDb3VudHJ5ID0gY291bnRyeTtcbiAgICBpZiAodGhpcy5tYXRJbnB1dFJlZiAmJiB0aGlzLm1hdElucHV0UmVmLm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLm1hdElucHV0UmVmLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH0sIDApXG4gICAgfVxuICB9XG5cbiAgcHVibGljIGlubmVyT25CbHVyKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBzdXBlci5pbm5lck9uQmx1cihldmVudCk7XG4gICAgaWYgKHRoaXMuX2ZDb250cm9sKSB7XG4gICAgICB0aGlzLl9mQ29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0U2VsZWN0ZWRDb3VudHJ5SXNvMigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkQ291bnRyeSA/IHRoaXMuc2VsZWN0ZWRDb3VudHJ5LmlzbzIgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcm90ZWN0ZWQgaW5pdGlhbGl6ZUNvdW50cnlEYXRhKCkge1xuICAgIGlmICh0aGlzLmNvdW50cmllcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuYWxsQ291bnRyaWVzID0gdGhpcy5hbGxDb3VudHJpZXMuZmlsdGVyKChjKSA9PiB0aGlzLmNvdW50cmllcy5pbmNsdWRlcyhjLmlzbzIpKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZW5zdXJlUGhvbmVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgY29uc3QgbnVtYmVyID0gdGhpcy5nZXRQYXJzZWROdW1iZXIodmFsdWUsIHRoaXMuZ2V0U2VsZWN0ZWRDb3VudHJ5SXNvMigpKTtcbiAgICBpZiAobnVtYmVyKSB7XG4gICAgICBjb25zdCBpbnRsTm8gPSBudW1iZXJcbiAgICAgICAgPyB0aGlzLnBob25lVXRpbC5mb3JtYXQobnVtYmVyLCBscG4uUGhvbmVOdW1iZXJGb3JtYXQuSU5URVJOQVRJT05BTClcbiAgICAgICAgOiAnJztcbiAgICAgIGlmIChpbnRsTm8pIHtcbiAgICAgICAgdGhpcy52YWx1ZS52YWx1ZSA9IHRoaXMucmVtb3ZlRGlhbENvZGUoaW50bE5vKTtcbiAgICAgICAgdGhpcy5lbWl0UGhvbmVJbnB1dERhdGEoaW50bE5vLCBudW1iZXIpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRDb3VudHJ5QnlEaWFsQ29kZShjb3VudHJ5RGlhbENvZGU6IGFueSk6IENvdW50cnkge1xuICAgIGlmIChjb3VudHJ5RGlhbENvZGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnNvcnRDb3VudHJpZXMoKS5maW5kKChjKSA9PiBjLmRpYWxDb2RlID09PSBjb3VudHJ5RGlhbENvZGUpO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHByb3RlY3RlZCBzb3J0Q291bnRyaWVzKCk6IENvdW50cnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuYWxsQ291bnRyaWVzXG4gICAgICAuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICByZXR1cm4gYS5wcmlvcml0eSAtIGIucHJpb3JpdHk7XG4gICAgICB9KVxuICB9XG4gIHByb3RlY3RlZCBnZXRTZXBhcmF0ZWRWYWx1ZXModmFsdWU6IGFueSk6IHsgY291bnRyeURpYWxDb2RlOiBzdHJpbmcsIG51bWJlcjogc3RyaW5nIH0ge1xuICAgIGxldCBjb3VudHJ5RGlhbENvZGUgPSAnJ1xuICAgIGxldCBudW1iZXIgPSAodmFsdWUgaW5zdGFuY2VvZiBPRm9ybVZhbHVlID8gdmFsdWUudmFsdWUgOiB2YWx1ZSkgfHwgdW5kZWZpbmVkXG4gICAgaWYgKFV0aWwuaXNEZWZpbmVkKG51bWJlcikgJiYgbnVtYmVyLnN0YXJ0c1dpdGgoUEhPTkVfUFJFRklYKSkge1xuICAgICAgY291bnRyeURpYWxDb2RlID0gbnVtYmVyLnN1YnN0cigxLCBudW1iZXIuaW5kZXhPZignICcpIC0gMSk7XG4gICAgICBudW1iZXIgPSBudW1iZXIuc3Vic3RyKGNvdW50cnlEaWFsQ29kZS5sZW5ndGggKyAyKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgY291bnRyeURpYWxDb2RlLCBudW1iZXIgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGVtaXRQaG9uZUlucHV0RGF0YShpbnRsTm8/OiBzdHJpbmcsIG51bWJlcj86IHN0cmluZyk6IHZvaWQge1xuICAgIGxldCBwaG9uZUlucHV0RGF0YTogT1Bob25lSW5wdXREYXRhID0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGlzbzIgPSB0aGlzLmdldFNlbGVjdGVkQ291bnRyeUlzbzIoKTtcbiAgICBpZiAoaW50bE5vICYmIG51bWJlciAmJiBpc28yKSB7XG4gICAgICBwaG9uZUlucHV0RGF0YSA9IHtcbiAgICAgICAgbnVtYmVyOiB0aGlzLnZhbHVlLnZhbHVlLFxuICAgICAgICBpbnRlcm5hdGlvbmFsTnVtYmVyOiBpbnRsTm8sXG4gICAgICAgIG5hdGlvbmFsTnVtYmVyOiBudW1iZXJcbiAgICAgICAgICA/IHRoaXMucGhvbmVVdGlsLmZvcm1hdChudW1iZXIsIGxwbi5QaG9uZU51bWJlckZvcm1hdC5OQVRJT05BTClcbiAgICAgICAgICA6ICcnLFxuICAgICAgICBlMTY0TnVtYmVyOiBudW1iZXJcbiAgICAgICAgICA/IHRoaXMucGhvbmVVdGlsLmZvcm1hdChudW1iZXIsIGxwbi5QaG9uZU51bWJlckZvcm1hdC5FMTY0KVxuICAgICAgICAgIDogJycsXG4gICAgICAgIGNvdW50cnlDb2RlOiBpc28yLnRvVXBwZXJDYXNlKCksXG4gICAgICAgIGRpYWxDb2RlOiBQSE9ORV9QUkVGSVggKyB0aGlzLnNlbGVjdGVkQ291bnRyeS5kaWFsQ29kZSxcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5vblBob25lRGF0YUNoYW5nZS5lbWl0KHBob25lSW5wdXREYXRhKTtcbiAgfVxuXG4gIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBIZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG4gIC8qKlxuICAgKiBSZXR1cm5zIHBhcnNlIFBob25lTnVtYmVyIG9iamVjdC5cbiAgICogQHBhcmFtIHBob25lTnVtYmVyIHN0cmluZ1xuICAgKiBAcGFyYW0gY291bnRyeUNvZGUgc3RyaW5nXG4gICAqL1xuICBwcml2YXRlIGdldFBhcnNlZE51bWJlcihcbiAgICBwaG9uZU51bWJlcjogc3RyaW5nLFxuICAgIGNvdW50cnlDb2RlOiBzdHJpbmdcbiAgKTogbHBuLlBob25lTnVtYmVyIHtcbiAgICBsZXQgbnVtYmVyOiBscG4uUGhvbmVOdW1iZXI7XG4gICAgdHJ5IHtcbiAgICAgIG51bWJlciA9IHRoaXMucGhvbmVVdGlsLnBhcnNlKHBob25lTnVtYmVyLCBjb3VudHJ5Q29kZS50b1VwcGVyQ2FzZSgpKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbiAgICByZXR1cm4gbnVtYmVyO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFucyBkaWFsY29kZSBmcm9tIHBob25lIG51bWJlciBzdHJpbmcuXG4gICAqIEBwYXJhbSBwaG9uZU51bWJlciBzdHJpbmdcbiAgICovXG4gIHByaXZhdGUgcmVtb3ZlRGlhbENvZGUocGhvbmVOdW1iZXI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgbnVtYmVyID0gdGhpcy5nZXRQYXJzZWROdW1iZXIocGhvbmVOdW1iZXIsIHRoaXMuZ2V0U2VsZWN0ZWRDb3VudHJ5SXNvMigpKTtcbiAgICBwaG9uZU51bWJlciA9IHRoaXMucGhvbmVVdGlsLmZvcm1hdChcbiAgICAgIG51bWJlcixcbiAgICAgIGxwbi5QaG9uZU51bWJlckZvcm1hdFt0aGlzLm51bWJlckZvcm1hdF1cbiAgICApO1xuICAgIGlmIChwaG9uZU51bWJlci5zdGFydHNXaXRoKFBIT05FX1BSRUZJWCkgJiYgdGhpcy5zZXBhcmF0ZURpYWxDb2RlKSB7XG4gICAgICBwaG9uZU51bWJlciA9IHBob25lTnVtYmVyLnN1YnN0cmluZyhwaG9uZU51bWJlci5pbmRleE9mKCcgJykgKyAxKTtcbiAgICB9XG4gICAgcmV0dXJuIHBob25lTnVtYmVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFNpZnRzIHRocm91Z2ggYWxsIGNvdW50cmllcyBhbmQgcmV0dXJucyBpc28gY29kZSBvZiB0aGUgcHJpbWFyeSBjb3VudHJ5XG4gICAqIGJhc2VkIG9uIHRoZSBudW1iZXIgcHJvdmlkZWQuXG4gICAqIEBwYXJhbSBjb3VudHJ5Q29kZSBjb3VudHJ5IGNvZGUgaW4gbnVtYmVyIGZvcm1hdFxuICAgKiBAcGFyYW0gbnVtYmVyIFBob25lTnVtYmVyIG9iamVjdFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRDb3VudHJ5SXNvQ29kZShcbiAgICBjb3VudHJ5Q29kZTogbnVtYmVyLFxuICAgIG51bWJlcjogbHBuLlBob25lTnVtYmVyXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgLy8gV2lsbCB1c2UgdGhpcyB0byBtYXRjaCBhcmVhIGNvZGU