UNPKG

ontimize-web-ngx

Version:
319 lines 52.6 kB
import { __decorate, __metadata } from "tslib"; import { Component, ElementRef, forwardRef, Inject, Injector, Optional, ViewChild, ViewEncapsulation } from '@angular/core'; import { UntypedFormControl } from '@angular/forms'; import { MatSelect } from '@angular/material/select'; import { Subscription } from 'rxjs'; import { BooleanInputConverter } from '../../../decorators/input-converter'; import { OntimizeServiceProvider } from '../../../services/factories'; import { Codes } from '../../../util/codes'; import { Util } from '../../../util/util'; import { OFormValue } from '../../form/o-form-value'; import { OFormComponent } from '../../form/o-form.component'; import { OValueChangeEvent } from '../../o-value-change-event.class'; import { OFormServiceComponent } from '../o-form-service-component.class'; import { OComboSearchComponent } from './combo-search/o-combo-search.component'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/flex-layout/flex"; import * as i3 from "@angular/forms"; import * as i4 from "../../../directives/o-mat-error.directive"; import * as i5 from "@angular/material/core"; import * as i6 from "@angular/material/button"; import * as i7 from "@angular/material/icon"; import * as i8 from "@angular/material/form-field"; import * as i9 from "@angular/material/select"; import * as i10 from "@angular/material/tooltip"; import * as i11 from "../../contextmenu/o-context-menu.directive"; import * as i12 from "../../contextmenu/o-context-menu.component"; import * as i13 from "../../contextmenu/context-menu-item/o-context-menu-item.component"; import * as i14 from "./combo-search/o-combo-search.component"; import * as i15 from "../../../pipes/o-translate.pipe"; import * as i16 from "../../form/o-form.component"; export const DEFAULT_INPUTS_O_COMBO = [ 'multiple', 'nullSelection: null-selection', 'multipleTriggerLabel: multiple-trigger-label', 'searchable', 'nullSelectionLabel: null-selection-label' ]; export class OComboComponent extends OFormServiceComponent { set filteredDataArray(data) { if (Util.isArray(data)) { this._filteredDataArray = data; } else if (Util.isObject(data) && Object.keys(data).length > 0) { this._filteredDataArray = [data]; } else { console.warn('Component has received not supported service data. Supported data are Array or not empty Object'); this._filteredDataArray = []; } } get filteredDataArray() { return this._filteredDataArray; } constructor(form, elRef, injector) { super(form, elRef, injector); this.searchControl = new UntypedFormControl(); this.multipleTriggerLabel = false; this.searchable = false; this.nullSelection = true; this._filteredDataArray = []; this.subscription = new Subscription(); this.defaultValue = ''; } ngOnInit() { super.ngOnInit(); this.subscription.add(this.searchControl.valueChanges.subscribe(() => this.searchFilter())); } ngAfterViewInit() { super.ngAfterViewInit(); if (this.queryOnInit) { this.queryData(); } else if (this.queryOnBind) { this.syncDataIndex(); } } ngOnDestroy() { this.subscription.unsubscribe(); this.destroy(); } initialize() { super.initialize(); if (this.multiple) { this.nullSelection = false; this.defaultValue = []; } } ensureOFormValue(value) { if (value instanceof OFormValue) { this.value = new OFormValue(value.value); } else if (Util.isDefined(value) && !(value instanceof OFormValue)) { this.value = new OFormValue(value); } else if (!Util.isDefined(value) && this.nullSelection) { this.value = new OFormValue(undefined); } else { this.value = new OFormValue(this.defaultValue); } } setDataArray(data) { super.setDataArray(data); this.filteredDataArray = data; } getDataArray() { return this.dataArray; } getFilteredDataArray() { return this._filteredDataArray; } hasNullSelection() { return this.nullSelection; } syncDataIndex(queryIfNotFound = true) { super.syncDataIndex(queryIfNotFound); if (this._currentIndex !== undefined && this.nullSelection) { this._currentIndex += 1; } } getValue() { if (this.value instanceof OFormValue) { if (this.value.value !== undefined) { return this.value.value; } else if (this.value.value === undefined) { return this.getEmptyValue(); } } return ''; } getEmptyValue() { if (this.multiple) { return []; } else { if (this.nullSelection) { return undefined; } else { return ''; } } } isEmpty() { if (!(this.value instanceof OFormValue)) { return true; } return this.value.value === undefined || (this.multiple && this.value.value.length === 0); } clearValue(options, setDirty = false) { if (this.multiple) { this.setValue(this.defaultValue, options, setDirty); this.value.value = []; if (Util.isDefined(this.comboSearch)) { this.comboSearch.resetSelectedValues(); } } else { super.clearValue(options, setDirty); } } get showClearButton() { return this.clearButton && !this.isReadOnly && this.enabled && !this.isEmpty(); } getMultiple() { return this.multiple; } onSelectionChange(event) { if (!this.selectModel.panelOpen) { return; } const newValue = event.value; this.setValue(newValue, { changeType: OValueChangeEvent.USER_CHANGE, emitEvent: false, emitModelToViewChange: false }); } getValueColumn(item) { if (item && item.hasOwnProperty(this.valueColumn)) { let option = item[this.valueColumn]; if (option === 'undefined') { option = null; } return option; } return ''; } isSelected(item, rowIndex) { let selected = false; if (item && item.hasOwnProperty(this.valueColumn) && this.value) { const val = item[this.valueColumn]; if (val === this.value.value) { selected = true; this._currentIndex = rowIndex; } } return selected; } setValue(val, options, setDirty = false) { if (!this.dataArray) { return; } const isDefinedVal = Util.isDefined(val); if (this.multiple && !isDefinedVal) { return; } if (!isDefinedVal && !this.nullSelection) { console.warn('`o-combo` with attr ' + this.oattr + ' cannot be set. `null-selection` attribute is false.'); return; } super.setValue(val, options); } getSelectedItems() { return this.getValue(); } setSelectedItems(values) { this.setValue(values); } getFirstSelectedValue() { return this.selectModel.selected[0].viewValue; } setIsReadOnly(value) { super.setIsReadOnly(value); const readOnly = Util.isDefined(this.readOnly) ? this.readOnly : value; if (this.enabled) { if (this._fControl && readOnly) { this._fControl.disable({ emitEvent: false }); } else if (this._fControl) { this._fControl.enable({ emitEvent: false }); } } } parseByValueColumnType(val) { if (!Util.isDefined(this.multiple)) { return val; } const valueArr = this.multiple ? val : [val]; if (this.valueColumnType === Codes.TYPE_INT) { valueArr.forEach((item, index) => { const parsed = parseInt(item, 10); if (!isNaN(parsed)) { valueArr[index] = parsed; } }); } return this.multiple ? valueArr : valueArr[0]; } searchFilter() { if (this.dataArray || this.dataArray.length) { let search = this.searchControl.value; if (!search) { this.filteredDataArray = this.dataArray.slice(); return; } else { search = search.toLowerCase(); } if (this.renderer) { this.filteredDataArray = this.dataArray.filter(item => this.renderer.getComboData(item).toLowerCase().indexOf(search) > -1); } else { this.filteredDataArray = this.dataArray.filter(item => this.getOptionDescriptionValue(item).toLowerCase().indexOf(search) > -1); } } } registerRenderer(renderer) { this.renderer = renderer; this.renderer.initialize(); } } OComboComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OComboComponent, deps: [{ token: forwardRef(() => OFormComponent), optional: true }, { token: i0.ElementRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); OComboComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OComboComponent, selector: "o-combo", inputs: { multiple: "multiple", nullSelection: ["null-selection", "nullSelection"], multipleTriggerLabel: ["multiple-trigger-label", "multipleTriggerLabel"], searchable: "searchable", nullSelectionLabel: ["null-selection-label", "nullSelectionLabel"] }, host: { properties: { "class.o-combo": "true" } }, providers: [ OntimizeServiceProvider, { provide: OFormServiceComponent, useExisting: forwardRef(() => OComboComponent) } ], viewQueries: [{ propertyName: "inputModel", first: true, predicate: ["inputModel"], descendants: true }, { propertyName: "selectModel", first: true, predicate: ["selectModel"], descendants: true }, { propertyName: "comboSearch", first: true, predicate: ["comboSearch"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div [formGroup]=\"getFormGroup()\" [matTooltip]=\"tooltip\" [matTooltipClass]=\"tooltipClass\" [matTooltipPosition]=\"tooltipPosition\"\n [matTooltipShowDelay]=\"tooltipShowDelay\" [matTooltipHideDelay]=\"tooltipHideDelay\" [oContextMenu]=\"oContextMenu\">\n\n <mat-form-field [appearance]=\"appearance\" [floatLabel]=\"floatLabel\" [class.read-only]=\"isReadOnly\" [class.custom-width]=\"hasCustomWidth\"\n [hideRequiredMarker]=\"hideRequiredMarker\" fxFill [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <mat-select [value]=\"getValue()\" #selectModel [id]=\"getAttribute()\" fxFill [formControlName]=\"getAttribute()\" [placeholder]=\"placeHolder\"\n [multiple]=\"getMultiple()\" [required]=\"isRequired\" [panelClass]=\"{ 'o-combo-panel': true, 'o-combo-panel-search': searchable }\"\n (selectionChange)=\"onSelectionChange($event)\" (closed)=\"innerOnBlur($event)\">\n <o-combo-search #comboSearch *ngIf=\"searchable\" [formControl]=\"searchControl\"></o-combo-search>\n\n <mat-select-trigger *ngIf=\"multiple && multipleTriggerLabel\">\n {{ selectModel.selected[0] ? getFirstSelectedValue(): '' }}\n <span *ngIf=\"!isEmpty()\">\n {{ 'INPUT.COMBO.MESSAGE_TRIGGER' | oTranslate: { values: [getFormControl().value.length -1] } }}\n </span>\n </mat-select-trigger>\n\n <mat-select-trigger *ngIf=\"!multiple && !multipleTriggerLabel\">\n <ng-container *ngFor=\"let item of filteredDataArray\">\n <ng-container *ngIf=\"renderer && item[valueColumn] == getValue()\">\n <ng-template *ngTemplateOutlet=\"renderer?.templateref; context:{ value: item }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!renderer && item[valueColumn] == getValue()\">\n {{ getOptionDescriptionValue(item) }}\n </ng-container>\n </ng-container>\n </mat-select-trigger>\n\n <div class=\"o-combo-options-container\">\n <mat-option *ngIf=\"hasNullSelection()\" [value]=\"null\">{{translate ?\n (nullSelectionLabel|oTranslate): nullSelectionLabel}}\n </mat-option>\n <mat-option *ngFor=\"let item of filteredDataArray\" [value]=\"getValueColumn(item)\">\n <ng-container *ngIf=\"renderer\">\n <ng-template *ngTemplateOutlet=\"renderer?.templateref; context:{ value: item }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!renderer\">\n {{ getOptionDescriptionValue(item) }}\n </ng-container>\n </mat-option>\n </div>\n </mat-select>\n\n <button type=\"button\" *ngIf=\"showClearButton\" matSuffix mat-icon-button (click)=\"onClickClearValue($event)\">\n <mat-icon svgIcon=\"ontimize:close\"></mat-icon>\n </button>\n\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n\n <o-context-menu *ngIf=\"!this.isReadOnly && this.enabled\">\n <o-context-menu-item attr=\"refresh\" label=\"FORM_SERVICE_COMPONENT.REFRESH\" svg-icon=\"ontimize:autorenew\" (execute)=\"refresh()\">\n </o-context-menu-item>\n </o-context-menu>\n</div>\n", styles: [".o-combo .read-only .mat-mdc-select-arrow-wrapper{visibility:hidden}.o-combo-panel.o-combo-panel-search{height:100%}.o-combo-panel.o-combo-panel-search .o-combo-options-container{height:calc(100% - 3em);overflow:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.FlexFillDirective, selector: "[fxFill], [fxFlexFill]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i4.OMatErrorDirective, selector: "[oMatError]", inputs: ["oMatError"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "directive", type: i8.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i9.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "directive", type: i9.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i11.OContextMenuDirective, selector: "[oContextMenu]", inputs: ["oContextMenu", "oContextMenuData"] }, { kind: "component", type: i12.OContextMenuComponent, selector: "o-context-menu", outputs: ["onShow", "onClose"] }, { kind: "component", type: i13.OContextMenuItemComponent, selector: "o-context-menu-item", outputs: ["execute"] }, { kind: "component", type: i14.OComboSearchComponent, selector: "o-combo-search" }, { kind: "pipe", type: i15.OTranslatePipe, name: "oTranslate" }], encapsulation: i0.ViewEncapsulation.None }); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], OComboComponent.prototype, "multiple", void 0); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], OComboComponent.prototype, "multipleTriggerLabel", void 0); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], OComboComponent.prototype, "searchable", void 0); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], OComboComponent.prototype, "nullSelection", void 0); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OComboComponent, decorators: [{ type: Component, args: [{ selector: 'o-combo', providers: [ OntimizeServiceProvider, { provide: OFormServiceComponent, useExisting: forwardRef(() => OComboComponent) } ], inputs: DEFAULT_INPUTS_O_COMBO, encapsulation: ViewEncapsulation.None, host: { '[class.o-combo]': 'true' }, template: "<div [formGroup]=\"getFormGroup()\" [matTooltip]=\"tooltip\" [matTooltipClass]=\"tooltipClass\" [matTooltipPosition]=\"tooltipPosition\"\n [matTooltipShowDelay]=\"tooltipShowDelay\" [matTooltipHideDelay]=\"tooltipHideDelay\" [oContextMenu]=\"oContextMenu\">\n\n <mat-form-field [appearance]=\"appearance\" [floatLabel]=\"floatLabel\" [class.read-only]=\"isReadOnly\" [class.custom-width]=\"hasCustomWidth\"\n [hideRequiredMarker]=\"hideRequiredMarker\" fxFill [subscriptSizing]=\"subscriptSizing\">\n <mat-label *ngIf=\"labelVisible\">{{ olabel | oTranslate }}</mat-label>\n <mat-select [value]=\"getValue()\" #selectModel [id]=\"getAttribute()\" fxFill [formControlName]=\"getAttribute()\" [placeholder]=\"placeHolder\"\n [multiple]=\"getMultiple()\" [required]=\"isRequired\" [panelClass]=\"{ 'o-combo-panel': true, 'o-combo-panel-search': searchable }\"\n (selectionChange)=\"onSelectionChange($event)\" (closed)=\"innerOnBlur($event)\">\n <o-combo-search #comboSearch *ngIf=\"searchable\" [formControl]=\"searchControl\"></o-combo-search>\n\n <mat-select-trigger *ngIf=\"multiple && multipleTriggerLabel\">\n {{ selectModel.selected[0] ? getFirstSelectedValue(): '' }}\n <span *ngIf=\"!isEmpty()\">\n {{ 'INPUT.COMBO.MESSAGE_TRIGGER' | oTranslate: { values: [getFormControl().value.length -1] } }}\n </span>\n </mat-select-trigger>\n\n <mat-select-trigger *ngIf=\"!multiple && !multipleTriggerLabel\">\n <ng-container *ngFor=\"let item of filteredDataArray\">\n <ng-container *ngIf=\"renderer && item[valueColumn] == getValue()\">\n <ng-template *ngTemplateOutlet=\"renderer?.templateref; context:{ value: item }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!renderer && item[valueColumn] == getValue()\">\n {{ getOptionDescriptionValue(item) }}\n </ng-container>\n </ng-container>\n </mat-select-trigger>\n\n <div class=\"o-combo-options-container\">\n <mat-option *ngIf=\"hasNullSelection()\" [value]=\"null\">{{translate ?\n (nullSelectionLabel|oTranslate): nullSelectionLabel}}\n </mat-option>\n <mat-option *ngFor=\"let item of filteredDataArray\" [value]=\"getValueColumn(item)\">\n <ng-container *ngIf=\"renderer\">\n <ng-template *ngTemplateOutlet=\"renderer?.templateref; context:{ value: item }\">\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!renderer\">\n {{ getOptionDescriptionValue(item) }}\n </ng-container>\n </mat-option>\n </div>\n </mat-select>\n\n <button type=\"button\" *ngIf=\"showClearButton\" matSuffix mat-icon-button (click)=\"onClickClearValue($event)\">\n <mat-icon svgIcon=\"ontimize:close\"></mat-icon>\n </button>\n\n <mat-error *oMatError=\"hasError('required')\">\n {{ 'FORM_VALIDATION.REQUIRED' | oTranslate }}\n </mat-error>\n <mat-error *ngFor=\"let oError of getActiveOErrors()\">\n {{ oError.text | oTranslate }}\n </mat-error>\n </mat-form-field>\n\n <o-context-menu *ngIf=\"!this.isReadOnly && this.enabled\">\n <o-context-menu-item attr=\"refresh\" label=\"FORM_SERVICE_COMPONENT.REFRESH\" svg-icon=\"ontimize:autorenew\" (execute)=\"refresh()\">\n </o-context-menu-item>\n </o-context-menu>\n</div>\n", styles: [".o-combo .read-only .mat-mdc-select-arrow-wrapper{visibility:hidden}.o-combo-panel.o-combo-panel-search{height:100%}.o-combo-panel.o-combo-panel-search .o-combo-options-container{height:calc(100% - 3em);overflow:auto}\n"] }] }], ctorParameters: function () { return [{ type: i16.OFormComponent, decorators: [{ type: Optional }, { type: Inject, args: [forwardRef(() => OFormComponent)] }] }, { type: i0.ElementRef }, { type: i0.Injector }]; }, propDecorators: { multiple: [], multipleTriggerLabel: [], searchable: [], nullSelection: [], inputModel: [{ type: ViewChild, args: ['inputModel'] }], selectModel: [{ type: ViewChild, args: ['selectModel'] }], comboSearch: [{ type: ViewChild, args: ['comboSearch', { static: false }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiby1jb21iby5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9vbnRpbWl6ZS13ZWItbmd4L3NyYy9saWIvY29tcG9uZW50cy9pbnB1dC9jb21iby9vLWNvbWJvLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9jb21wb25lbnRzL2lucHV0L2NvbWJvL28tY29tYm8uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBaUIsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBcUIsUUFBUSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5SixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsU0FBUyxFQUFtQixNQUFNLDBCQUEwQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFcEMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDNUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFdEUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRTFFLE9BQU8s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QUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUU7S0FDbkYscVZDaENILHkwR0ErREE7QURmRTtJQUFDLHFCQUFxQixFQUFFOztpREFDQztBQUN6QjtJQUFDLHFCQUFxQixFQUFFOzs2REFDcUI7QUFDN0M7SUFBQyxxQkFBcUIsRUFBRTs7bURBQ1c7QUFDbkM7SUFBQyxxQkFBcUIsRUFBRTs7c0RBQ2dCOzRGQWQ3QixlQUFlO2tCQWQzQixTQUFTOytCQUNFLFNBQVMsYUFDUjt3QkFDVCx1QkFBdUI7d0JBQ3ZCLEVBQUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLGdCQUFnQixDQUFDLEVBQUU7cUJBQ25GLFVBQ08sc0JBQXNCLGlCQUdmLGlCQUFpQixDQUFDLElBQUksUUFDL0I7d0JBQ0osaUJBQWlCLEVBQUUsTUFBTTtxQkFDMUI7OzBCQWlERSxRQUFROzswQkFBSSxNQUFNOzJCQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxjQUFjLENBQUM7NEZBdkMvQyxRQUFRLE1BRVIsb0JBQW9CLE1BRXBCLFVBQVUsTUFFUCxhQUFhLE1BS2IsVUFBVTtzQkFEbkIsU0FBUzt1QkFBQyxZQUFZO2dCQUliLFdBQVc7c0JBRHBCLFNBQVM7dUJBQUMsYUFBYTtnQkFJZCxXQUFXO3NCQURwQixTQUFTO3VCQUFDLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZnRlclZpZXdJbml0LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIGZvcndhcmRSZWYsIEluamVjdCwgSW5qZWN0b3IsIE9uRGVzdHJveSwgT25Jbml0LCBPcHRpb25hbCwgVmlld0NoaWxkLCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVW50eXBlZEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTWF0U2VsZWN0LCBNYXRTZWxlY3RDaGFuZ2UgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IEJvb2xlYW5JbnB1dENvbnZlcnRlciB9IGZyb20gJy4uLy4uLy4uL2RlY29yYXRvcnMvaW5wdXQtY29udmVydGVyJztcbmltcG9ydCB7IE9udGltaXplU2VydmljZVByb3ZpZGVyIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvZmFjdG9yaWVzJztcbmltcG9ydCB7IEZvcm1WYWx1ZU9wdGlvbnMgfSBmcm9tICcuLi8uLi8uLi90eXBlcy9mb3JtLXZhbHVlLW9wdGlvbnMudHlwZSc7XG5pbXBvcnQgeyBDb2RlcyB9IGZyb20gJy4uLy4uLy4uL3V0aWwvY29kZXMnO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwvdXRpbCc7XG5pbXBvcnQgeyBPRm9ybVZhbHVlIH0gZnJvbSAnLi4vLi4vZm9ybS9vLWZvcm0tdmFsdWUnO1xuaW1wb3J0IHsgT0Zvcm1Db21wb25lbnQgfSBmcm9tICcuLi8uLi9mb3JtL28tZm9ybS5jb21wb25lbnQnO1xuaW1wb3J0IHsgT1ZhbHVlQ2hhbmdlRXZlbnQgfSBmcm9tICcuLi8uLi9vLXZhbHVlLWNoYW5nZS1ldmVudC5jbGFzcyc7XG5pbXBvcnQgeyBPRm9ybVNlcnZpY2VDb21wb25lbnQgfSBmcm9tICcuLi9vLWZvcm0tc2VydmljZS1jb21wb25lbnQuY2xhc3MnO1xuaW1wb3J0IHsgT0NvbWJvQ3VzdG9tUmVuZGVyZXIgfSBmcm9tICcuL2NvbWJvLXJlbmRlcmVyL28tY29tYm8tcmVuZGVyZXIuY2xhc3MnO1xuaW1wb3J0IHsgT0NvbWJvU2VhcmNoQ29tcG9uZW50IH0gZnJvbSAnLi9jb21iby1zZWFyY2gvby1jb21iby1zZWFyY2guY29tcG9uZW50JztcblxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9JTlBVVFNfT19DT01CTyA9IFtcbiAgJ211bHRpcGxlJyxcbiAgJ251bGxTZWxlY3Rpb246IG51bGwtc2VsZWN0aW9uJyxcbiAgJ211bHRpcGxlVHJpZ2dlckxhYmVsOiBtdWx0aXBsZS10cmlnZ2VyLWxhYmVsJyxcbiAgJ3NlYXJjaGFibGUnLFxuICAvLyB0ZXh0IHRvIG5vbmUgc2VsZWN0aW9uIGluIGEgY29tYm9cbiAgJ251bGxTZWxlY3Rpb25MYWJlbDogbnVsbC1zZWxlY3Rpb24tbGFiZWwnXG5dO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdvLWNvbWJvJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAgT250aW1pemVTZXJ2aWNlUHJvdmlkZXIsXG4gICAgeyBwcm92aWRlOiBPRm9ybVNlcnZpY2VDb21wb25lbnQsIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE9Db21ib0NvbXBvbmVudCkgfVxuICBdLFxuICBpbnB1dHM6IERFRkFVTFRfSU5QVVRTX09fQ09NQk8sXG4gIHRlbXBsYXRlVXJsOiAnLi9vLWNvbWJvLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vby1jb21iby5jb21wb25lbnQuc2NzcyddLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBob3N0OiB7XG4gICAgJ1tjbGFzcy5vLWNvbWJvXSc6ICd0cnVlJ1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIE9Db21ib0NvbXBvbmVudCBleHRlbmRzIE9Gb3JtU2VydmljZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICBwdWJsaWMgdmFsdWU6IE9Gb3JtVmFsdWU7XG4gIHB1YmxpYyBzZWFyY2hDb250cm9sOiBVbnR5cGVkRm9ybUNvbnRyb2wgPSBuZXcgVW50eXBlZEZvcm1Db250cm9sKCk7XG4gIHB1YmxpYyByZW5kZXJlcjogT0NvbWJvQ3VzdG9tUmVuZGVyZXI7XG5cbiAgLyogSW5wdXRzICovXG4gIEBCb29sZWFuSW5wdXRDb252ZXJ0ZXIoKVxuICBwdWJsaWMgbXVsdGlwbGU6IGJvb2xlYW47XG4gIEBCb29sZWFuSW5wdXRDb252ZXJ0ZXIoKVxuICBwdWJsaWMgbXVsdGlwbGVUcmlnZ2VyTGFiZWw6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQEJvb2xlYW5JbnB1dENvbnZlcnRlcigpXG4gIHB1YmxpYyBzZWFyY2hhYmxlOiBib29sZWFuID0gZmFsc2U7XG4gIEBCb29sZWFuSW5wdXRDb252ZXJ0ZXIoKVxuICBwcm90ZWN0ZWQgbnVsbFNlbGVjdGlvbjogYm9vbGVhbiA9IHRydWU7XG4gIHB1YmxpYyBudWxsU2VsZWN0aW9uTGFiZWw6IHN0cmluZztcbiAgLyogRW5kIGlucHV0cyovXG5cbiAgQFZpZXdDaGlsZCgnaW5wdXRNb2RlbCcpXG4gIHByb3RlY3RlZCBpbnB1dE1vZGVsOiBFbGVtZW50UmVmO1xuXG4gIEBWaWV3Q2hpbGQoJ3NlbGVjdE1vZGVsJylcbiAgcHJvdGVjdGVkIHNlbGVjdE1vZGVsOiBNYXRTZWxlY3Q7XG5cbiAgQFZpZXdDaGlsZCgnY29tYm9TZWFyY2gnLCB7IHN0YXRpYzogZmFsc2UgfSlcbiAgcHJvdGVjdGVkIGNvbWJvU2VhcmNoOiBPQ29tYm9TZWFyY2hDb21wb25lbnQ7XG5cbiAgcHJvdGVjdGVkIF9maWx0ZXJlZERhdGFBcnJheTogYW55W10gPSBbXTtcblxuICBzZXQgZmlsdGVyZWREYXRhQXJyYXkoZGF0YTogYW55KSB7XG4gICAgaWYgKFV0aWwuaXNBcnJheShkYXRhKSkge1xuICAgICAgdGhpcy5fZmlsdGVyZWREYXRhQXJyYXkgPSBkYXRhO1xuICAgIH0gZWxzZSBpZiAoVXRpbC5pc09iamVjdChkYXRhKSAmJiBPYmplY3Qua2V5cyhkYXRhKS5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLl9maWx0ZXJlZERhdGFBcnJheSA9IFtkYXRhXTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdDb21wb25lbnQgaGFzIHJlY2VpdmVkIG5vdCBzdXBwb3J0ZWQgc2VydmljZSBkYXRhLiBTdXBwb3J0ZWQgZGF0YSBhcmUgQXJyYXkgb3Igbm90IGVtcHR5IE9iamVjdCcpO1xuICAgICAgdGhpcy5fZmlsdGVyZWREYXRhQXJyYXkgPSBbXTtcbiAgICB9XG4gIH1cblxuICBnZXQgZmlsdGVyZWREYXRhQXJyYXkoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5fZmlsdGVyZWREYXRhQXJyYXk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChmb3J3YXJkUmVmKCgpID0+IE9Gb3JtQ29tcG9uZW50KSkgZm9ybTogT0Zvcm1Db21wb25lbnQsXG4gICAgZWxSZWY6IEVsZW1lbnRSZWYsXG4gICAgaW5qZWN0b3I6IEluamVjdG9yXG4gICkge1xuICAgIHN1cGVyKGZvcm0sIGVsUmVmLCBpbmplY3Rvcik7XG4gICAgdGhpcy5kZWZhdWx0VmFsdWUgPSAnJztcbiAgfVxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZCh0aGlzLnNlYXJjaENvbnRyb2wudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLnNlYXJjaEZpbHRlcigpKSk7XG4gIH1cblxuICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHN1cGVyLm5nQWZ0ZXJWaWV3SW5pdCgpO1xuICAgIGlmICh0aGlzLnF1ZXJ5T25Jbml0KSB7XG4gICAgICB0aGlzLnF1ZXJ5RGF0YSgpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5xdWVyeU9uQmluZCkge1xuICAgICAgLy8gVE9ETyBkbyBpdCBiZXR0ZXIuIFdoZW4gY2hhbmdpbmcgdGFicyBpdCBpcyBuZWNlc3NhcnkgdG8gaW52b2tlIG5ldyBxdWVyeVxuICAgICAgdGhpcy5zeW5jRGF0YUluZGV4KCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5kZXN0cm95KCk7XG4gIH1cblxuICBwdWJsaWMgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgaWYgKHRoaXMubXVsdGlwbGUpIHtcbiAgICAgIHRoaXMubnVsbFNlbGVjdGlvbiA9IGZhbHNlO1xuICAgICAgdGhpcy5kZWZhdWx0VmFsdWUgPSBbXTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZW5zdXJlT0Zvcm1WYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgT0Zvcm1WYWx1ZSkge1xuICAgICAgdGhpcy52YWx1ZSA9IG5ldyBPRm9ybVZhbHVlKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKFV0aWwuaXNEZWZpbmVkKHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgT0Zvcm1WYWx1ZSkpIHtcbiAgICAgIHRoaXMudmFsdWUgPSBuZXcgT0Zvcm1WYWx1ZSh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmICghVXRpbC5pc0RlZmluZWQodmFsdWUpICYmIHRoaXMubnVsbFNlbGVjdGlvbikge1xuICAgICAgdGhpcy52YWx1ZSA9IG5ldyBPRm9ybVZhbHVlKHVuZGVmaW5lZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudmFsdWUgPSBuZXcgT0Zvcm1WYWx1ZSh0aGlzLmRlZmF1bHRWYWx1ZSk7XG4gICAgfVxuICAgIC8vIFRoaXMgY2FsbCBtYWtlIHRoZSBjb21wb25lbnQgcXVlcnlpbmcgaXRzIGRhdGEgbXVsdGlwbGUgdGltZXNcbiAgICAvLyB0aGlzLnN5bmNEYXRhSW5kZXgoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXREYXRhQXJyYXkoZGF0YTogYW55KTogdm9pZCB7XG4gICAgc3VwZXIuc2V0RGF0YUFycmF5KGRhdGEpO1xuICAgIHRoaXMuZmlsdGVyZWREYXRhQXJyYXkgPSBkYXRhO1xuICB9XG5cbiAgcHVibGljIGdldERhdGFBcnJheSgpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YUFycmF5O1xuICB9XG5cbiAgcHVibGljIGdldEZpbHRlcmVkRGF0YUFycmF5KCk6IGFueVtdIHtcbiAgICByZXR1cm4gdGhpcy5fZmlsdGVyZWREYXRhQXJyYXk7XG4gIH1cblxuICBwdWJsaWMgaGFzTnVsbFNlbGVjdGlvbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5udWxsU2VsZWN0aW9uO1xuICB9XG5cbiAgcHVibGljIHN5bmNEYXRhSW5kZXgocXVlcnlJZk5vdEZvdW5kOiBib29sZWFuID0gdHJ1ZSk6IHZvaWQge1xuICAgIHN1cGVyLnN5bmNEYXRhSW5kZXgocXVlcnlJZk5vdEZvdW5kKTtcbiAgICBpZiAodGhpcy5fY3VycmVudEluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5udWxsU2VsZWN0aW9uKSB7XG4gICAgICAvLyBmaXJzdCBwb3NpdGlvbiBpcyBmb3IgbnVsbCBzZWxlY3Rpb24gdGhhdCBpdCBpcyBub3QgaW5jbHVkZWQgaW50byBkYXRhQXJyYXlcbiAgICAgIHRoaXMuX2N1cnJlbnRJbmRleCArPSAxO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRWYWx1ZSgpOiBhbnkge1xuICAgIGlmICh0aGlzLnZhbHVlIGluc3RhbmNlb2YgT0Zvcm1WYWx1ZSkge1xuICAgICAgaWYgKHRoaXMudmFsdWUudmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZS52YWx1ZTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy52YWx1ZS52YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEVtcHR5VmFsdWUoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgcHVibGljIGdldEVtcHR5VmFsdWUoKTogYW55IHtcbiAgICBpZiAodGhpcy5tdWx0aXBsZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGhpcy5udWxsU2VsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGlzRW1wdHkoKTogYm9vbGVhbiB7XG4gICAgaWYgKCEodGhpcy52YWx1ZSBpbnN0YW5jZW9mIE9Gb3JtVmFsdWUpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWUudmFsdWUgPT09IHVuZGVmaW5lZCB8fCAodGhpcy5tdWx0aXBsZSAmJiB0aGlzLnZhbHVlLnZhbHVlLmxlbmd0aCA9PT0gMCk7XG4gIH1cblxuICBwdWJsaWMgY2xlYXJWYWx1ZShvcHRpb25zPzogRm9ybVZhbHVlT3B0aW9ucywgc2V0RGlydHk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGlmICh0aGlzLm11bHRpcGxlKSB7XG4gICAgICB0aGlzLnNldFZhbHVlKHRoaXMuZGVmYXVsdFZhbHVlLCBvcHRpb25zLCBzZXREaXJ0eSk7XG4gICAgICB0aGlzLnZhbHVlLnZhbHVlID0gW107XG4gICAgICBpZiAoVXRpbC5pc0RlZmluZWQodGhpcy5jb21ib1NlYXJjaCkpIHtcbiAgICAgICAgdGhpcy5jb21ib1NlYXJjaC5yZXNldFNlbGVjdGVkVmFsdWVzKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHN1cGVyLmNsZWFyVmFsdWUob3B0aW9ucywgc2V0RGlydHkpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBzaG93Q2xlYXJCdXR0b24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY2xlYXJCdXR0b24gJiYgIXRoaXMuaXNSZWFkT25seSAmJiB0aGlzLmVuYWJsZWQgJiYgIXRoaXMuaXNFbXB0eSgpO1xuICB9XG5cbiAgcHVibGljIGdldE11bHRpcGxlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm11bHRpcGxlO1xuICB9XG5cbiAgcHVibGljIG9uU2VsZWN0aW9uQ2hhbmdlKGV2ZW50OiBNYXRTZWxlY3RDaGFuZ2UpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2VsZWN0TW9kZWwucGFuZWxPcGVuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG5ld1ZhbHVlID0gZXZlbnQudmFsdWU7XG4gICAgdGhpcy5zZXRWYWx1ZShuZXdWYWx1ZSwge1xuICAgICAgY2hhbmdlVHlwZTogT1ZhbHVlQ2hhbmdlRXZlbnQuVVNFUl9DSEFOR0UsXG4gICAgICBlbWl0RXZlbnQ6IGZhbHNlLFxuICAgICAgZW1pdE1vZGVsVG9WaWV3Q2hhbmdlOiBmYWxzZVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldFZhbHVlQ29sdW1uKGl0ZW06IGFueSk6IGFueSB7XG4gICAgaWYgKGl0ZW0gJiYgaXRlbS5oYXNPd25Qcm9wZXJ0eSh0aGlzLnZhbHVlQ29sdW1uKSkge1xuICAgICAgbGV0IG9wdGlvbiA9IGl0ZW1bdGhpcy52YWx1ZUNvbHVtbl07XG4gICAgICBpZiAob3B0aW9uID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICBvcHRpb24gPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9wdGlvbjtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgcHVibGljIGlzU2VsZWN0ZWQoaXRlbTogYW55LCByb3dJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgbGV0IHNlbGVjdGVkID0gZmFsc2U7XG4gICAgaWYgKGl0ZW0gJiYgaXRlbS5oYXNPd25Qcm9wZXJ0eSh0aGlzLnZhbHVlQ29sdW1uKSAmJiB0aGlzLnZhbHVlKSB7XG4gICAgICBjb25zdCB2YWwgPSBpdGVtW3RoaXMudmFsdWVDb2x1bW5dO1xuICAgICAgaWYgKHZhbCA9PT0gdGhpcy52YWx1ZS52YWx1ZSkge1xuICAgICAgICBzZWxlY3RlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuX2N1cnJlbnRJbmRleCA9IHJvd0luZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc2VsZWN0ZWQ7XG4gIH1cblxuICBwdWJsaWMgc2V0VmFsdWUodmFsOiBhbnksIG9wdGlvbnM/OiBGb3JtVmFsdWVPcHRpb25zLCBzZXREaXJ0eTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmRhdGFBcnJheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpc0RlZmluZWRWYWwgPSBVdGlsLmlzRGVmaW5lZCh2YWwpO1xuICAgIGlmICh0aGlzLm11bHRpcGxlICYmICFpc0RlZmluZWRWYWwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlzRGVmaW5lZFZhbCAmJiAhdGhpcy5udWxsU2VsZWN0aW9uKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ2BvLWNvbWJvYCB3aXRoIGF0dHIgJyArIHRoaXMub2F0dHIgKyAnIGNhbm5vdCBiZSBzZXQuIGBudWxsLXNlbGVjdGlvbmAgYXR0cmlidXRlIGlzIGZhbHNlLicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN1cGVyLnNldFZhbHVlKHZhbCwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0U2VsZWN0ZWRJdGVtcygpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VmFsdWUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRTZWxlY3RlZEl0ZW1zKHZhbHVlczogYW55W10pOiB2b2lkIHtcbiAgICB0aGlzLnNldFZhbHVlKHZhbHVlcyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0Rmlyc3RTZWxlY3RlZFZhbHVlKCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdE1vZGVsLnNlbGVjdGVkWzBdLnZpZXdWYWx1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRJc1JlYWRPbmx5KHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgc3VwZXIuc2V0SXNSZWFkT25seSh2YWx1ZSk7XG4gICAgY29uc3QgcmVhZE9ubHkgPSBVdGlsLmlzRGVmaW5lZCh0aGlzLnJlYWRPbmx5KSA/IHRoaXMucmVhZE9ubHkgOiB2YWx1ZTtcbiAgICBpZiAodGhpcy5lbmFibGVkKSB7XG4gICAgICBpZiAodGhpcy5fZkNvbnRyb2wgJiYgcmVhZE9ubHkpIHtcbiAgICAgICAgdGhpcy5fZkNvbnRyb2wuZGlzYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2ZDb250cm9sKSB7XG4gICAgICAgIHRoaXMuX2ZDb250cm9sLmVuYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHByb3RlY3RlZCBwYXJzZUJ5VmFsdWVDb2x1bW5UeXBlKHZhbDogYW55KTogYW55IHtcbiAgICBpZiAoIVV0aWwuaXNEZWZpbmVkKHRoaXMubXVsdGlwbGUpKSB7XG4gICAgICByZXR1cm4gdmFsO1xuICAgIH1cbiAgICBjb25zdCB2YWx1ZUFycjogYW55W10gPSB0aGlzLm11bHRpcGxlID8gdmFsIDogW3ZhbF07XG4gICAgaWYgKHRoaXMudmFsdWVDb2x1bW5UeXBlID09PSBDb2Rlcy5UWVBFX0lOVCkge1xuICAgICAgdmFsdWVBcnIuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnQoaXRlbSwgMTApO1xuICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICB2YWx1ZUFycltpbmRleF0gPSBwYXJzZWQ7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tdWx0aXBsZSA/IHZhbHVlQXJyIDogdmFsdWVBcnJbMF07XG4gIH1cblxuICBwcm90ZWN0ZWQgc2VhcmNoRmlsdGVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRhdGFBcnJheSB8fCB0aGlzLmRhdGFBcnJheS5sZW5ndGgpIHtcblxuICAgICAgLy8gZ2V0IHRoZSBzZWFyY2gga2V5d29yZFxuICAgICAgbGV0IHNlYXJjaCA9IHRoaXMuc2VhcmNoQ29udHJvbC52YWx1ZTtcbiAgICAgIGlmICghc2VhcmNoKSB7XG4gICAgICAgIHRoaXMuZmlsdGVyZWREYXRhQXJyYXkgPSB0aGlzLmRhdGFBcnJheS5zbGljZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWFyY2ggPSBzZWFyY2gudG9Mb3dlckNhc2UoKTtcbiAgICAgIH1cblxuICAgICAgLy8gZmlsdGVyXG4gICAgICBpZiAodGhpcy5yZW5kZXJlcikge1xuICAgICAgICB0aGlzLmZpbHRlcmVkRGF0YUFycmF5ID0gdGhpcy5kYXRhQXJyYXkuZmlsdGVyKGl0ZW0gPT4gdGhpcy5yZW5kZXJlci5nZXRDb21ib0RhdGEoaXRlbSkudG9Mb3dlckNhc2UoKS5pbmRleE9mKHNlYXJjaCkgPiAtMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmZpbHRlcmVkRGF0YUFycmF5ID0gdGhpcy5kYXRhQXJyYXkuZmlsdGVyKGl0ZW0gPT4gdGhpcy5nZXRPcHRpb25EZXNjcmlwdGlvblZhbHVlKGl0ZW0pLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihzZWFyY2gpID4gLTEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlclJlbmRlcmVyKHJlbmRlcmVyOiBhbnkpIHtcbiAgICB0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXI7XG4gICAgdGhpcy5yZW5kZXJlci5pbml0aWFsaXplKCk7XG4gIH1cblxufVxuIiwiPGRpdiBbZm9ybUdyb3VwXT1cImdldEZvcm1Hcm91cCgpXCIgW21hdFRvb2x0aXBdPVwidG9vbHRpcFwiIFttYXRUb29sdGlwQ2xhc3NdPVwidG9vbHRpcENsYXNzXCIgW21hdFRvb2x0aXBQb3NpdGlvbl09XCJ0b29sdGlwUG9zaXRpb25cIlxuICBbbWF0VG9vbHRpcFNob3dEZWxheV09XCJ0b29sdGlwU2hvd0RlbGF5XCIgW21hdFRvb2x0aXBIaWRlRGVsYXldPVwidG9vbHRpcEhpZGVEZWxheVwiIFtvQ29udGV4dE1lbnVdPVwib0NvbnRleHRNZW51XCI+XG5cbiAgPG1hdC1mb3JtLWZpZWxkIFthcHBlYXJhbmNlXT1cImFwcGVhcmFuY2VcIiBbZmxvYXRMYWJlbF09XCJmbG9hdExhYmVsXCIgW2NsYXNzLnJlYWQtb25seV09XCJpc1JlYWRPbmx5XCIgW2NsYXNzLmN1c3RvbS13aWR0aF09XCJoYXNDdXN0b21XaWR0aFwiXG4gICAgW2hpZGVSZXF1aXJlZE1hcmtlcl09XCJoaWRlUmVxdWlyZWRNYXJrZXJcIiBmeEZpbGwgW3N1YnNjcmlwdFNpemluZ109XCJzdWJzY3JpcHRTaXppbmdcIj5cbiAgICA8bWF0LWxhYmVsICpuZ0lmPVwibGFiZWxWaXNpYmxlXCI+e3sgb2xhYmVsIHwgb1RyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgIDxtYXQtc2VsZWN0IFt2YWx1ZV09XCJnZXRWYWx1ZSgpXCIgI3NlbGVjdE1vZGVsIFtpZF09XCJnZXRBdHRyaWJ1dGUoKVwiIGZ4RmlsbCBbZm9ybUNvbnRyb2xOYW1lXT1cImdldEF0dHJpYnV0ZSgpXCIgW3BsYWNlaG9sZGVyXT1cInBsYWNlSG9sZGVyXCJcbiAgICAgIFttdWx0aXBsZV09XCJnZXRNdWx0aXBsZSgpXCIgW3JlcXVpcmVkXT1cImlzUmVxdWlyZWRcIiBbcGFuZWxDbGFzc109XCJ7ICdvLWNvbWJvLXBhbmVsJzogdHJ1ZSwgJ28tY29tYm8tcGFuZWwtc2VhcmNoJzogc2VhcmNoYWJsZSB9XCJcbiAgICAgIChzZWxlY3Rpb25DaGFuZ2UpPVwib25TZWxlY3Rpb25DaGFuZ2UoJGV2ZW50KVwiIChjbG9zZWQpPVwiaW5uZXJPbkJsdXIoJGV2ZW50KVwiPlxuICAgICAgPG8tY29tYm8tc2VhcmNoICNjb21ib1NlYXJjaCAqbmdJZj1cInNlYXJjaGFibGVcIiBbZm9ybUNvbnRyb2xdPVwic2VhcmNoQ29udHJvbFwiPjwvby1jb21iby1zZWFyY2g+XG5cbiAgICAgIDxtYXQtc2VsZWN0LXRyaWdnZXIgKm5nSWY9XCJtdWx0aXBsZSAmJiBtdWx0aXBsZVRyaWdnZXJMYWJlbFwiPlxuICAgICAgICB7eyBzZWxlY3RNb2RlbC5zZWxlY3RlZFswXSA/IGdldEZpcnN0U2VsZWN0ZWRWYWx1ZSgpOiAnJyB9fVxuICAgICAgICA8c3BhbiAqbmdJZj1cIiFpc0VtcHR5KClcIj5cbiAgICAgICAgICB7eyAnSU5QVVQuQ09NQk8uTUVTU0FHRV9UUklHR0VSJyB8IG9UcmFuc2xhdGU6IHsgdmFsdWVzOiBbZ2V0Rm9ybUNvbnRyb2woKS52YWx1ZS5sZW5ndGggLTFdIH0gfX1cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9tYXQtc2VsZWN0LXRyaWdnZXI+XG5cbiAgICAgIDxtYXQtc2VsZWN0LXRyaWdnZXIgKm5nSWY9XCIhbXVsdGlwbGUgJiYgIW11bHRp