fundamental-ngx
Version:
SAP Fiori Fundamentals, implemented in Angular
587 lines • 43.2 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ElementRef, EventEmitter, forwardRef, HostListener, Input, Output, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { DateFormatParser } from '../calendar/format/date-parser';
export class DatePickerComponent {
/**
* @param {?} eRef
* @param {?} dateAdapter
*/
constructor(eRef, dateAdapter) {
this.eRef = eRef;
this.dateAdapter = dateAdapter;
/**
* @hidden The value of the input
*/
this.inputFieldDate = null;
/**
* @hidden Whether the date input is invalid
*/
this.isInvalidDateInput = false;
/**
* @hidden Whether the date picker is open
*/
this.isOpen = false;
/**
* @hidden Subject the calendar subscribes to when the date value from the datePicker component changes. For internal use.
*/
this.dateFromDatePicker = new Subject();
/**
* The type of calendar, 'single' for single date selection or 'range' for a range of dates.
*/
this.type = 'single';
/**
* Date picker input placeholder string
*/
this.placeholder = 'mm/dd/yyyy';
/**
* Whether this is the compact input date picker
*/
this.compact = false;
/**
* The currently selected CalendarDay model
*/
this.selectedDay = {
date: null
};
/**
* Fired when a new date is selected.
*/
this.selectedDayChange = new EventEmitter();
/**
* The currently selected first CalendarDay in a range type calendar.
*/
this.selectedRangeFirst = {
date: null
};
/**
* Fired when the user selects a new first date in a range of dates is selected.
*/
this.selectedRangeFirstChange = new EventEmitter();
/**
* The currently selected last CalendarDay in a range type calendar.
*/
this.selectedRangeLast = {
date: null
};
/**
* Fired when the user selects a new last date in a range of dates is selected.
*/
this.selectedRangeLastChange = new EventEmitter();
/**
* The day of the week the calendar should start on. 0 represents Sunday, 1 is Monday, 2 is Tuesday, and so on.
*/
this.startingDayOfWeek = 0;
/**
* Whether to validate the date picker input.
*/
this.validate = true;
/**
* Aria label for the datepicker input.
*/
this.dateInputLabel = 'Date input';
/**
* Aria label for the button to show/hide the calendar.
*/
this.displayCalendarToggleLabel = 'Display calendar toggle';
/**
* Whether a null input is considered valid.
*/
this.allowNull = true;
/**
* The placement of the popover. It can be one of: top, top-start, top-end, bottom,
* bottom-start, bottom-end, right, right-start, right-end, left, left-start, left-end.
*/
this.placement = 'bottom-start';
/**
* Function used to disable certain dates in the calendar.
* @param d Date
*/
this.disableFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to block certain dates in the calendar.
* @param d Date
*/
this.blockFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to disable certain dates in the calendar for the range start selection.
* @param d Date
*/
this.disableRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to disable certain dates in the calendar for the range end selection.
* @param d Date
*/
this.disableRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to block certain dates in the calendar for the range start selection.
* @param d Date
*/
this.blockRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* Function used to block certain dates in the calendar for the range end selection.
* @param d Date
*/
this.blockRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* @hidden
*/
this.onChange = (/**
* @param {?} selected
* @return {?}
*/
(selected) => { });
/**
* @hidden
*/
this.onTouched = (/**
* @return {?}
*/
() => { });
}
/**
* Opens the calendar
* @param {?} e
* @return {?}
*/
openCalendar(e) {
if (!this.disabled) {
this.onTouched({ date: this.selectedDay.date });
this.isOpen = true;
this.getInputValue(e);
}
}
/**
* Toggles the calendar open or closed
* @param {?} e
* @return {?}
*/
toggleCalendar(e) {
this.onTouched({ date: this.selectedDay.date });
this.isOpen = !this.isOpen;
this.getInputValue(e);
}
/**
* Closes the calendar if it is open
* @return {?}
*/
closeCalendar() {
if (this.isOpen) {
this.isOpen = false;
}
}
/**
* @hidden
* @param {?} d
* @return {?}
*/
updateDatePickerInputHandler(d) {
if (this.type === 'single') {
if (d.selectedDay.date) {
/** @type {?} */
const newInputDate = this.dateAdapter.format(d.selectedDay.date);
if (this.inputFieldDate !== newInputDate) {
this.inputFieldDate = newInputDate;
this.selectedDay = d.selectedDay;
this.selectedDayChange.emit(this.selectedDay);
this.onChange({ date: this.selectedDay.date });
}
}
}
else {
if (d.selectedFirstDay.date) {
/** @type {?} */
const newInputDates = this.dateAdapter.format(d.selectedFirstDay.date) + this.dateAdapter.rangeDelimiter
+ this.dateAdapter.format(d.selectedLastDay.date);
if (this.inputFieldDate !== newInputDates) {
this.inputFieldDate = newInputDates;
this.selectedRangeFirst = d.selectedFirstDay;
this.selectedRangeLast = d.selectedLastDay;
this.selectedRangeFirstChange.emit(this.selectedRangeFirst);
this.selectedRangeLastChange.emit(this.selectedRangeLast);
this.onChange({ date: this.selectedRangeFirst.date, rangeEnd: this.selectedRangeLast.date });
}
}
}
}
/**
* @hidden
* @param {?} e
* @return {?}
*/
isInvalidDateInputHandler(e) {
this.isInvalidDateInput = e;
}
/**
* @hidden
* @param {?} e
* @return {?}
*/
getInputValue(e) {
this.dateFromDatePicker.next(e);
}
/**
* @hidden
* @return {?}
*/
onEscapeKeydownHandler() {
this.closeCalendar();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onGlobalClick(event) {
if (!this.eRef.nativeElement.contains(event.target)) {
this.closeCalendar();
}
}
/**
* @hidden
* @return {?}
*/
ngOnInit() {
if (this.dateFromDatePicker) {
this.dateFromDatePicker.subscribe((/**
* @param {?} date
* @return {?}
*/
date => {
if (date && typeof date === 'object') {
this.updateDatePickerInputHandler(date);
}
else if (date === '' && this.allowNull) {
this.isInvalidDateInput = false;
if (this.type === 'single') {
this.selectedDay.date = null;
this.selectedDay.selected = null;
}
else {
this.selectedRangeFirst.date = null;
this.selectedRangeFirst.selected = null;
this.selectedRangeLast.date = null;
this.selectedRangeLast.selected = null;
}
}
else {
this.isInvalidDateInput = true;
}
}));
}
}
/**
* @hidden
* @return {?}
*/
ngOnDestroy() {
if (this.dateFromDatePicker) {
this.dateFromDatePicker.unsubscribe();
}
}
/**
* @hidden
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.onChange = fn;
}
/**
* @hidden
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* @hidden
* @param {?} isDisabled
* @return {?}
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
/**
* @hidden
* @param {?} selected
* @return {?}
*/
writeValue(selected) {
if (!selected) {
return;
}
if (this.type.toLocaleLowerCase() === 'single') {
this.selectedDay.date = selected.date;
if (selected.date !== null) {
this.inputFieldDate = this.dateAdapter.format(selected.date);
}
else {
this.inputFieldDate = '';
}
}
else {
this.selectedRangeFirst.date = selected.date;
this.selectedRangeLast.date = selected.rangeEnd;
if (selected.date !== null) {
this.inputFieldDate = this.dateAdapter.format(selected.date) +
this.dateAdapter.rangeDelimiter + this.dateAdapter.format(selected.rangeEnd);
}
else {
this.inputFieldDate = '';
}
}
}
}
DatePickerComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-date-picker',
template: "<fd-popover [(isOpen)]=\"isOpen\"\n [triggers]=\"[]\"\n [placement]=\"placement\"\n [disabled]=\"disabled\">\n <fd-popover-control>\n <div class=\"fd-input-group fd-input-group--after\"\n [ngClass]=\"{'fd-input-group--compact' : compact}\">\n <input #datePicker\n type=\"text\"\n [attr.aria-label]=\"dateInputLabel\"\n [value]=\"inputFieldDate\"\n [placeholder]=\"placeholder\"\n (keyup.enter)=\"getInputValue(datePicker.value)\"\n (blur)=\"getInputValue(datePicker.value)\"\n (click)=\"openCalendar(datePicker.value)\"\n [disabled]=\"disabled\"\n [ngClass]=\"{ 'fd-input--compact': compact, 'is-invalid': isInvalidDateInput && validate }\">\n <span class=\"fd-input-group__addon fd-input-group__addon--after fd-input-group__addon--button\">\n <button [disabled]=\"disabled\" class=\"fd-popover__control fd-button--icon fd-button--light sap-icon--calendar\"\n (click)=\"toggleCalendar(datePicker.value)\" [attr.aria-label]=\"displayCalendarToggleLabel\"\n [attr.aria-expanded]=\"isOpen\" type=\"button\"></button>\n </span>\n </div>\n </fd-popover-control>\n <fd-popover-body\n [style.display]=\"'block'\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-hidden]=\"!isOpen\">\n <fd-calendar (closeCalendar)=\"isOpen = false;\" [calType]=\"type\"\n [disableFunction]=\"disableFunction ? disableFunction : null\"\n [blockFunction]=\"blockFunction ? blockFunction : null\"\n [disableRangeStartFunction]=\"disableRangeStartFunction ? disableRangeStartFunction : null\"\n [disableRangeEndFunction]=\"disableRangeEndFunction ? disableRangeEndFunction : null\"\n [blockRangeStartFunction]=\"blockRangeStartFunction ? blockRangeStartFunction : null\"\n [blockRangeEndFunction]=\"blockRangeEndFunction ? blockRangeEndFunction : null\"\n [(selectedDay)]=\"selectedDay\"\n [(selectedRangeFirst)]=\"selectedRangeFirst\"\n [(selectedRangeLast)]=\"selectedRangeLast\"\n (isInvalidDateInput)=\"isInvalidDateInputHandler($event)\"\n [dateFromDatePicker]=\"dateFromDatePicker\"\n [startingDayOfWeek]=\"startingDayOfWeek\"></fd-calendar>\n </fd-popover-body>\n</fd-popover>\n",
host: {
'(blur)': 'onTouched()',
'[class.fd-date-picker]': 'true',
'[class.fd-date-picker-custom]': 'true'
},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((/**
* @return {?}
*/
() => DatePickerComponent)),
multi: true
}
],
encapsulation: ViewEncapsulation.None,
styles: [".fd-date-picker-custom{display:inline-block}.fd-date-picker-custom fd-popover{display:block}"]
}] }
];
/** @nocollapse */
DatePickerComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: DateFormatParser }
];
DatePickerComponent.propDecorators = {
type: [{ type: Input }],
placeholder: [{ type: Input }],
compact: [{ type: Input }],
selectedDay: [{ type: Input }],
selectedDayChange: [{ type: Output }],
selectedRangeFirst: [{ type: Input }],
selectedRangeFirstChange: [{ type: Output }],
selectedRangeLast: [{ type: Input }],
selectedRangeLastChange: [{ type: Output }],
startingDayOfWeek: [{ type: Input }],
validate: [{ type: Input }],
dateInputLabel: [{ type: Input }],
displayCalendarToggleLabel: [{ type: Input }],
allowNull: [{ type: Input }],
placement: [{ type: Input }],
disabled: [{ type: Input }],
disableFunction: [{ type: Input }],
blockFunction: [{ type: Input }],
disableRangeStartFunction: [{ type: Input }],
disableRangeEndFunction: [{ type: Input }],
blockRangeStartFunction: [{ type: Input }],
blockRangeEndFunction: [{ type: Input }],
onEscapeKeydownHandler: [{ type: HostListener, args: ['document:keydown.escape', [],] }],
onGlobalClick: [{ type: HostListener, args: ['document:click', ['$event'],] }]
};
if (false) {
/**
* @hidden The value of the input
* @type {?}
*/
DatePickerComponent.prototype.inputFieldDate;
/**
* @hidden Whether the date input is invalid
* @type {?}
*/
DatePickerComponent.prototype.isInvalidDateInput;
/**
* @hidden Whether the date picker is open
* @type {?}
*/
DatePickerComponent.prototype.isOpen;
/**
* @hidden Subject the calendar subscribes to when the date value from the datePicker component changes. For internal use.
* @type {?}
*/
DatePickerComponent.prototype.dateFromDatePicker;
/**
* The type of calendar, 'single' for single date selection or 'range' for a range of dates.
* @type {?}
*/
DatePickerComponent.prototype.type;
/**
* Date picker input placeholder string
* @type {?}
*/
DatePickerComponent.prototype.placeholder;
/**
* Whether this is the compact input date picker
* @type {?}
*/
DatePickerComponent.prototype.compact;
/**
* The currently selected CalendarDay model
* @type {?}
*/
DatePickerComponent.prototype.selectedDay;
/**
* Fired when a new date is selected.
* @type {?}
*/
DatePickerComponent.prototype.selectedDayChange;
/**
* The currently selected first CalendarDay in a range type calendar.
* @type {?}
*/
DatePickerComponent.prototype.selectedRangeFirst;
/**
* Fired when the user selects a new first date in a range of dates is selected.
* @type {?}
*/
DatePickerComponent.prototype.selectedRangeFirstChange;
/**
* The currently selected last CalendarDay in a range type calendar.
* @type {?}
*/
DatePickerComponent.prototype.selectedRangeLast;
/**
* Fired when the user selects a new last date in a range of dates is selected.
* @type {?}
*/
DatePickerComponent.prototype.selectedRangeLastChange;
/**
* The day of the week the calendar should start on. 0 represents Sunday, 1 is Monday, 2 is Tuesday, and so on.
* @type {?}
*/
DatePickerComponent.prototype.startingDayOfWeek;
/**
* Whether to validate the date picker input.
* @type {?}
*/
DatePickerComponent.prototype.validate;
/**
* Aria label for the datepicker input.
* @type {?}
*/
DatePickerComponent.prototype.dateInputLabel;
/**
* Aria label for the button to show/hide the calendar.
* @type {?}
*/
DatePickerComponent.prototype.displayCalendarToggleLabel;
/**
* Whether a null input is considered valid.
* @type {?}
*/
DatePickerComponent.prototype.allowNull;
/**
* The placement of the popover. It can be one of: top, top-start, top-end, bottom,
* bottom-start, bottom-end, right, right-start, right-end, left, left-start, left-end.
* @type {?}
*/
DatePickerComponent.prototype.placement;
/**
* Whether the date picker is disabled.
* @type {?}
*/
DatePickerComponent.prototype.disabled;
/**
* Function used to disable certain dates in the calendar.
* \@param d Date
* @type {?}
*/
DatePickerComponent.prototype.disableFunction;
/**
* Function used to block certain dates in the calendar.
* \@param d Date
* @type {?}
*/
DatePickerComponent.prototype.blockFunction;
/**
* Function used to disable certain dates in the calendar for the range start selection.
* \@param d Date
* @type {?}
*/
DatePickerComponent.prototype.disableRangeStartFunction;
/**
* Function used to disable certain dates in the calendar for the range end selection.
* \@param d Date
* @type {?}
*/
DatePickerComponent.prototype.disableRangeEndFunction;
/**
* Function used to block certain dates in the calendar for the range start selection.
* \@param d Date
* @type {?}
*/
DatePickerComponent.prototype.blockRangeStartFunction;
/**
* Function used to block certain dates in the calendar for the range end selection.
* \@param d Date
* @type {?}
*/
DatePickerComponent.prototype.blockRangeEndFunction;
/**
* @hidden
* @type {?}
*/
DatePickerComponent.prototype.onChange;
/**
* @hidden
* @type {?}
*/
DatePickerComponent.prototype.onTouched;
/**
* @type {?}
* @private
*/
DatePickerComponent.prototype.eRef;
/** @type {?} */
DatePickerComponent.prototype.dateAdapter;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vZnVuZGFtZW50YWwtbmd4LyIsInNvdXJjZXMiOlsibGliL2RhdGUtcGlja2VyL2RhdGUtcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFFVixZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sRUFDTixpQkFBaUIsRUFDcEIsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFxQmxFLE1BQU0sT0FBTyxtQkFBbUI7Ozs7O0lBZ1A1QixZQUFvQixJQUFnQixFQUFTLFdBQTZCO1FBQXRELFNBQUksR0FBSixJQUFJLENBQVk7UUFBUyxnQkFBVyxHQUFYLFdBQVcsQ0FBa0I7Ozs7UUE5TzFFLG1CQUFjLEdBQUcsSUFBSSxDQUFDOzs7O1FBRXRCLHVCQUFrQixHQUFZLEtBQUssQ0FBQzs7OztRQUVwQyxXQUFNLEdBQVksS0FBSyxDQUFDOzs7O1FBRXhCLHVCQUFrQixHQUFvQixJQUFJLE9BQU8sRUFBRSxDQUFDOzs7O1FBSXBELFNBQUksR0FBaUIsUUFBUSxDQUFDOzs7O1FBSTlCLGdCQUFXLEdBQVcsWUFBWSxDQUFDOzs7O1FBSW5DLFlBQU8sR0FBWSxLQUFLLENBQUM7Ozs7UUFJekIsZ0JBQVcsR0FBZ0I7WUFDdkIsSUFBSSxFQUFFLElBQUk7U0FDYixDQUFDOzs7O1FBSUYsc0JBQWlCLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQzs7OztRQUl2Qyx1QkFBa0IsR0FBZ0I7WUFDOUIsSUFBSSxFQUFFLElBQUk7U0FDYixDQUFDOzs7O1FBSUYsNkJB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QUFFLENBQUMsUUFBUSxDQUFDOzs7Ozs7O0lBeE0xQyw2Q0FBc0I7Ozs7O0lBRXRCLGlEQUFvQzs7Ozs7SUFFcEMscUNBQXdCOzs7OztJQUV4QixpREFBb0Q7Ozs7O0lBR3BELG1DQUM4Qjs7Ozs7SUFHOUIsMENBQ21DOzs7OztJQUduQyxzQ0FDeUI7Ozs7O0lBR3pCLDBDQUdFOzs7OztJQUdGLGdEQUN1Qzs7Ozs7SUFHdkMsaURBR0U7Ozs7O0lBR0YsdURBQzhDOzs7OztJQUc5QyxnREFHRTs7Ozs7SUFHRixzREFDNkM7Ozs7O0lBRzdDLGdEQUM4Qjs7Ozs7SUFHOUIsdUNBQWtDOzs7OztJQUdsQyw2Q0FDc0M7Ozs7O0lBR3RDLHlEQUMrRDs7Ozs7SUFHL0Qsd0NBQzBCOzs7Ozs7SUFJMUIsd0NBQ3NDOzs7OztJQUd0Qyx1Q0FDa0I7Ozs7OztJQU1sQiw4Q0FHRTs7Ozs7O0lBS0YsNENBR0U7Ozs7OztJQUtGLHdEQUdFOzs7Ozs7SUFLRixzREFHRTs7Ozs7O0lBS0Ysc0RBR0U7Ozs7OztJQUtGLG9EQUdFOzs7OztJQUdGLHVDQUFzQzs7Ozs7SUFFdEMsd0NBQTBCOzs7OztJQTRHZCxtQ0FBd0I7O0lBQUUsMENBQW9DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgZm9yd2FyZFJlZixcbiAgICBIb3N0QmluZGluZyxcbiAgICBIb3N0TGlzdGVuZXIsXG4gICAgSW5wdXQsXG4gICAgT25EZXN0cm95LFxuICAgIE9uSW5pdCxcbiAgICBPdXRwdXQsXG4gICAgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDYWxlbmRhckRheSwgQ2FsZW5kYXJUeXBlIH0gZnJvbSAnLi4vY2FsZW5kYXIvY2FsZW5kYXIuY29tcG9uZW50JztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERhdGVGb3JtYXRQYXJzZXIgfSBmcm9tICcuLi9jYWxlbmRhci9mb3JtYXQvZGF0ZS1wYXJzZXInO1xuaW1wb3J0IHsgUGxhY2VtZW50IH0gZnJvbSAncG9wcGVyLmpzJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdmZC1kYXRlLXBpY2tlcicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2RhdGUtcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9kYXRlLXBpY2tlci5jb21wb25lbnQuc2NzcyddLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgJyhibHVyKSc6ICdvblRvdWNoZWQoKScsXG4gICAgICAgICdbY2xhc3MuZmQtZGF0ZS1waWNrZXJdJzogJ3RydWUnLFxuICAgICAgICAnW2NsYXNzLmZkLWRhdGUtcGlja2VyLWN1c3RvbV0nOiAndHJ1ZSdcbiAgICB9LFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgICAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVQaWNrZXJDb21wb25lbnQpLFxuICAgICAgICAgICAgbXVsdGk6IHRydWVcbiAgICAgICAgfVxuICAgIF0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxufSlcbmV4cG9ydCBjbGFzcyBEYXRlUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgICAvKiogQGhpZGRlbiBUaGUgdmFsdWUgb2YgdGhlIGlucHV0ICovXG4gICAgaW5wdXRGaWVsZERhdGUgPSBudWxsO1xuICAgIC8qKiBAaGlkZGVuIFdoZXRoZXIgdGhlIGRhdGUgaW5wdXQgaXMgaW52YWxpZCAqL1xuICAgIGlzSW52YWxpZERhdGVJbnB1dDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIC8qKiBAaGlkZGVuIFdoZXRoZXIgdGhlIGRhdGUgcGlja2VyIGlzIG9wZW4gKi9cbiAgICBpc09wZW46IGJvb2xlYW4gPSBmYWxzZTtcbiAgICAvKiogQGhpZGRlbiBTdWJqZWN0IHRoZSBjYWxlbmRhciBzdWJzY3JpYmVzIHRvIHdoZW4gdGhlIGRhdGUgdmFsdWUgZnJvbSB0aGUgZGF0ZVBpY2tlciBjb21wb25lbnQgY2hhbmdlcy4gRm9yIGludGVybmFsIHVzZS4gKi9cbiAgICBkYXRlRnJvbURhdGVQaWNrZXI6IFN1YmplY3Q8c3RyaW5nPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgICAvKiogVGhlIHR5cGUgb2YgY2FsZW5kYXIsICdzaW5nbGUnIGZvciBzaW5nbGUgZGF0ZSBzZWxlY3Rpb24gb3IgJ3JhbmdlJyBmb3IgYSByYW5nZSBvZiBkYXRlcy4gKi9cbiAgICBASW5wdXQoKVxuICAgIHR5cGU6IENhbGVuZGFyVHlwZSA9ICdzaW5nbGUnO1xuXG4gICAgLyoqIERhdGUgcGlja2VyIGlucHV0IHBsYWNlaG9sZGVyIHN0cmluZyAqL1xuICAgIEBJbnB1dCgpXG4gICAgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICdtbS9kZC95eXl5JztcblxuICAgIC8qKiBXaGV0aGVyIHRoaXMgaXMgdGhlIGNvbXBhY3QgaW5wdXQgZGF0ZSBwaWNrZXIgKi9cbiAgICBASW5wdXQoKVxuICAgIGNvbXBhY3Q6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBUaGUgY3VycmVudGx5IHNlbGVjdGVkIENhbGVuZGFyRGF5IG1vZGVsICovXG4gICAgQElucHV0KClcbiAgICBzZWxlY3RlZERheTogQ2FsZW5kYXJEYXkgPSB7XG4gICAgICAgIGRhdGU6IG51bGxcbiAgICB9O1xuXG4gICAgLyoqIEZpcmVkIHdoZW4gYSBuZXcgZGF0ZSBpcyBzZWxlY3RlZC4gKi9cbiAgICBAT3V0cHV0KClcbiAgICBzZWxlY3RlZERheUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKiBUaGUgY3VycmVudGx5IHNlbGVjdGVkIGZpcnN0IENhbGVuZGFyRGF5IGluIGEgcmFuZ2UgdHlwZSBjYWxlbmRhci4gKi9cbiAgICBASW5wdXQoKVxuICAgIHNlbGVjdGVkUmFuZ2VGaXJzdDogQ2FsZW5kYXJEYXkgPSB7XG4gICAgICAgIGRhdGU6IG51bGxcbiAgICB9O1xuXG4gICAgLyoqIEZpcmVkIHdoZW4gdGhlIHVzZXIgc2VsZWN0cyBhIG5ldyBmaXJzdCBkYXRlIGluIGEgcmFuZ2Ugb2YgZGF0ZXMgaXMgc2VsZWN0ZWQuICovXG4gICAgQE91dHB1dCgpXG4gICAgc2VsZWN0ZWRSYW5nZUZpcnN0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgLyoqIFRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgbGFzdCBDYWxlbmRhckRheSBpbiBhIHJhbmdlIHR5cGUgY2FsZW5kYXIuICovXG4gICAgQElucHV0KClcbiAgICBzZWxlY3RlZFJhbmdlTGFzdDogQ2FsZW5kYXJEYXkgPSB7XG4gICAgICAgIGRhdGU6IG51bGxcbiAgICB9O1xuXG4gICAgLyoqIEZpcmVkIHdoZW4gdGhlIHVzZXIgc2VsZWN0cyBhIG5ldyBsYXN0IGRhdGUgaW4gYSByYW5nZSBvZiBkYXRlcyBpcyBzZWxlY3RlZC4gKi9cbiAgICBAT3V0cHV0KClcbiAgICBzZWxlY3RlZFJhbmdlTGFzdENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKiBUaGUgZGF5IG9mIHRoZSB3ZWVrIHRoZSBjYWxlbmRhciBzaG91bGQgc3RhcnQgb24uIDAgcmVwcmVzZW50cyBTdW5kYXksIDEgaXMgTW9uZGF5LCAyIGlzIFR1ZXNkYXksIGFuZCBzbyBvbi4gKi9cbiAgICBASW5wdXQoKVxuICAgIHN0YXJ0aW5nRGF5T2ZXZWVrOiBudW1iZXIgPSAwO1xuXG4gICAgLyoqIFdoZXRoZXIgdG8gdmFsaWRhdGUgdGhlIGRhdGUgcGlja2VyIGlucHV0LiAqL1xuICAgIEBJbnB1dCgpIHZhbGlkYXRlOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBBcmlhIGxhYmVsIGZvciB0aGUgZGF0ZXBpY2tlciBpbnB1dC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRhdGVJbnB1dExhYmVsOiBzdHJpbmcgPSAnRGF0ZSBpbnB1dCc7XG5cbiAgICAvKiogQXJpYSBsYWJlbCBmb3IgdGhlIGJ1dHRvbiB0byBzaG93L2hpZGUgdGhlIGNhbGVuZGFyLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzcGxheUNhbGVuZGFyVG9nZ2xlTGFiZWw6IHN0cmluZyA9ICdEaXNwbGF5IGNhbGVuZGFyIHRvZ2dsZSc7XG5cbiAgICAvKiogV2hldGhlciBhIG51bGwgaW5wdXQgaXMgY29uc2lkZXJlZCB2YWxpZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGFsbG93TnVsbDogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogVGhlIHBsYWNlbWVudCBvZiB0aGUgcG9wb3Zlci4gSXQgY2FuIGJlIG9uZSBvZjogdG9wLCB0b3Atc3RhcnQsIHRvcC1lbmQsIGJvdHRvbSxcbiAgICAgKiAgYm90dG9tLXN0YXJ0LCBib3R0b20tZW5kLCByaWdodCwgcmlnaHQtc3RhcnQsIHJpZ2h0LWVuZCwgbGVmdCwgbGVmdC1zdGFydCwgbGVmdC1lbmQuICovXG4gICAgQElucHV0KClcbiAgICBwbGFjZW1lbnQ6IFBsYWNlbWVudCA9ICdib3R0b20tc3RhcnQnO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGRhdGUgcGlja2VyIGlzIGRpc2FibGVkLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzYWJsZWQ6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGRpc2FibGUgY2VydGFpbiBkYXRlcyBpbiB0aGUgY2FsZW5kYXIuXG4gICAgICogQHBhcmFtIGQgRGF0ZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGlzYWJsZUZ1bmN0aW9uID0gZnVuY3Rpb24oZCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGJsb2NrIGNlcnRhaW4gZGF0ZXMgaW4gdGhlIGNhbGVuZGFyLlxuICAgICAqIEBwYXJhbSBkIERhdGVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGJsb2NrRnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHVzZWQgdG8gZGlzYWJsZSBjZXJ0YWluIGRhdGVzIGluIHRoZSBjYWxlbmRhciBmb3IgdGhlIHJhbmdlIHN0YXJ0IHNlbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0gZCBEYXRlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlUmFuZ2VTdGFydEZ1bmN0aW9uID0gZnVuY3Rpb24oZCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGRpc2FibGUgY2VydGFpbiBkYXRlcyBpbiB0aGUgY2FsZW5kYXIgZm9yIHRoZSByYW5nZSBlbmQgc2VsZWN0aW9uLlxuICAgICAqIEBwYXJhbSBkIERhdGVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc2FibGVSYW5nZUVuZEZ1bmN0aW9uID0gZnVuY3Rpb24oZCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGJsb2NrIGNlcnRhaW4gZGF0ZXMgaW4gdGhlIGNhbGVuZGFyIGZvciB0aGUgcmFuZ2Ugc3RhcnQgc2VsZWN0aW9uLlxuICAgICAqIEBwYXJhbSBkIERhdGVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGJsb2NrUmFuZ2VTdGFydEZ1bmN0aW9uID0gZnVuY3Rpb24oZCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGJsb2NrIGNlcnRhaW4gZGF0ZXMgaW4gdGhlIGNhbGVuZGFyIGZvciB0aGUgcmFuZ2UgZW5kIHNlbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0gZCBEYXRlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBibG9ja1JhbmdlRW5kRnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvbkNoYW5nZTogYW55ID0gKHNlbGVjdGVkOiBhbnkpID0+IHt9O1xuICAgIC8qKiBAaGlkZGVuICovXG4gICAgb25Ub3VjaGVkOiBhbnkgPSAoKSA9PiB7fTtcblxuICAgIC8qKiBPcGVucyB0aGUgY2FsZW5kYXIgKi9cbiAgICBvcGVuQ2FsZW5kYXIoZSkge1xuICAgICAgICBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkKHtkYXRlOiB0aGlzLnNlbGVjdGVkRGF5LmRhdGV9KTtcbiAgICAgICAgICAgIHRoaXMuaXNPcGVuID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuZ2V0SW5wdXRWYWx1ZShlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBUb2dnbGVzIHRoZSBjYWxlbmRhciBvcGVuIG9yIGNsb3NlZCAqL1xuICAgIHRvZ2dsZUNhbGVuZGFyKGUpIHtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQoe2RhdGU6IHRoaXMuc2VsZWN0ZWREYXkuZGF0ZX0pO1xuICAgICAgICB0aGlzLmlzT3BlbiA9ICF0aGlzLmlzT3BlbjtcbiAgICAgICAgdGhpcy5nZXRJbnB1dFZhbHVlKGUpO1xuICAgIH1cblxuICAgIC8qKiBDbG9zZXMgdGhlIGNhbGVuZGFyIGlmIGl0IGlzIG9wZW4gKi9cbiAgICBjbG9zZUNhbGVuZGFyKCkge1xuICAgICAgICBpZiAodGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHVwZGF0ZURhdGVQaWNrZXJJbnB1dEhhbmRsZXIoZCkge1xuICAgICAgICBpZiAodGhpcy50eXBlID09PSAnc2luZ2xlJykge1xuICAgICAgICAgICAgaWYgKGQuc2VsZWN0ZWREYXkuZGF0ZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0lucHV0RGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIuZm9ybWF0KGQuc2VsZWN0ZWREYXkuZGF0ZSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRGaWVsZERhdGUgIT09IG5ld0lucHV0RGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0RmllbGREYXRlID0gbmV3SW5wdXREYXRlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF5ID0gZC5zZWxlY3RlZERheTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERheUNoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWREYXkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHtkYXRlOiB0aGlzLnNlbGVjdGVkRGF5LmRhdGV9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZC5zZWxlY3RlZEZpcnN0RGF5LmRhdGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdJbnB1dERhdGVzID0gdGhpcy5kYXRlQWRhcHRlci5mb3JtYXQoZC5zZWxlY3RlZEZpcnN0RGF5LmRhdGUpICsgdGhpcy5kYXRlQWRhcHRlci5yYW5nZURlbGltaXRlclxuICAgICAgICAgICAgICAgICAgICArIHRoaXMuZGF0ZUFkYXB0ZXIuZm9ybWF0KGQuc2VsZWN0ZWRMYXN0RGF5LmRhdGUpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0RmllbGREYXRlICE9PSBuZXdJbnB1dERhdGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRGaWVsZERhdGUgPSBuZXdJbnB1dERhdGVzO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFuZ2VGaXJzdCA9IGQuc2VsZWN0ZWRGaXJzdERheTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlTGFzdCA9IGQuc2VsZWN0ZWRMYXN0RGF5O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFuZ2VGaXJzdENoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWRSYW5nZUZpcnN0KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlTGFzdENoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWRSYW5nZUxhc3QpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHtkYXRlOiB0aGlzLnNlbGVjdGVkUmFuZ2VGaXJzdC5kYXRlLCByYW5nZUVuZDogdGhpcy5zZWxlY3RlZFJhbmdlTGFzdC5kYXRlfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBpc0ludmFsaWREYXRlSW5wdXRIYW5kbGVyKGUpIHtcbiAgICAgICAgdGhpcy5pc0ludmFsaWREYXRlSW5wdXQgPSBlO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgZ2V0SW5wdXRWYWx1ZShlKSB7XG4gICAgICAgIHRoaXMuZGF0ZUZyb21EYXRlUGlja2VyLm5leHQoZSk7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXlkb3duLmVzY2FwZScsIFtdKVxuICAgIG9uRXNjYXBlS2V5ZG93bkhhbmRsZXIoKSB7XG4gICAgICAgIHRoaXMuY2xvc2VDYWxlbmRhcigpO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxuICAgIHB1YmxpYyBvbkdsb2JhbENsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5lUmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KSkge1xuICAgICAgICAgICAgdGhpcy5jbG9zZUNhbGVuZGFyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG5nT25Jbml0KCkge1xuICAgICAgICBpZiAodGhpcy5kYXRlRnJvbURhdGVQaWNrZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUZyb21EYXRlUGlja2VyLnN1YnNjcmliZShkYXRlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0ZSAmJiB0eXBlb2YgZGF0ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVEYXRlUGlja2VySW5wdXRIYW5kbGVyKGRhdGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0ZSA9PT0gJycgJiYgdGhpcy5hbGxvd051bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0ludmFsaWREYXRlSW5wdXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3NpbmdsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXkuZGF0ZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF5LnNlbGVjdGVkID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRSYW5nZUZpcnN0LmRhdGUgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlRmlyc3Quc2VsZWN0ZWQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlTGFzdC5kYXRlID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRSYW5nZUxhc3Quc2VsZWN0ZWQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0ludmFsaWREYXRlSW5wdXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5kYXRlRnJvbURhdGVQaWNrZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUZyb21EYXRlUGlja2VyLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVSZWY6IEVsZW1lbnRSZWYsIHB1YmxpYyBkYXRlQWRhcHRlcjogRGF0ZUZvcm1hdFBhcnNlcikge31cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHNlbGVjdGVkOiBhbnkpID0+IHt2b2lkfSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICB3cml0ZVZhbHVlKHNlbGVjdGVkOiB7ZGF0ZTogRGF0ZSwgcmFuZ2VFbmQ/OiBEYXRlfSk6IHZvaWQge1xuICAgICAgICBpZiAoIXNlbGVjdGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudHlwZS50b0xvY2FsZUxvd2VyQ2FzZSgpID09PSAnc2luZ2xlJykge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERheS5kYXRlID0gc2VsZWN0ZWQuZGF0ZTtcbiAgICAgICAgICAgIGlmIChzZWxlY3RlZC5kYXRlICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dEZpZWxkRGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIuZm9ybWF0KHNlbGVjdGVkLmRhdGUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0RmllbGREYXRlID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFuZ2VGaXJzdC5kYXRlID0gc2VsZWN0ZWQuZGF0ZTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRSYW5nZUxhc3QuZGF0ZSA9IHNlbGVjdGVkLnJhbmdlRW5kO1xuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLmRhdGUgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0RmllbGREYXRlID0gdGhpcy5kYXRlQWRhcHRlci5mb3JtYXQoc2VsZWN0ZWQuZGF0ZSkgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGVBZGFwdGVyLnJhbmdlRGVsaW1pdGVyICsgdGhpcy5kYXRlQWRhcHRlci5mb3JtYXQoc2VsZWN0ZWQucmFuZ2VFbmQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0RmllbGREYXRlID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=