fundamental-ngx
Version:
SAP Fundamentals, implemented in Angular
628 lines • 53.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, EventEmitter, forwardRef, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
import { FdDate } from '../calendar/models/fd-date';
import { CalendarService } from '../calendar/calendar.service';
import { CalendarComponent } from '../calendar/calendar.component';
import { DateFormatParser } from './format/date-parser';
export class DatePickerComponent {
/**
* @hidden
* @param {?} dateAdapter
*/
constructor(dateAdapter) {
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;
/**
* 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 FdDates model start and end in range mode.
*/
this.selectedRangeDate = { start: null, end: null };
/**
* 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.useValidation = 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;
/**
* Actually shown active view one of 'day' | 'month' | 'year' in calendar component
*/
this.activeView = 'day';
/**
* 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';
/**
* Fired when a new date is selected.
*/
this.selectedDateChange = new EventEmitter();
/**
* Event thrown every time selected first or last date in range mode is changed
*/
this.selectedRangeDateChange = new EventEmitter();
/**
* Event thrown every time calendar active view is changed
*/
this.activeViewChange = new EventEmitter();
/**
* @hidden
*/
this.onChange = (/**
* @param {?} selected
* @return {?}
*/
(selected) => {
});
/**
* @hidden
*/
this.onTouched = (/**
* @return {?}
*/
() => {
});
/**
* Function used to disable certain dates in the calendar.
* @param fdDate FdDate
*/
this.disableFunction = (/**
* @param {?} fdDate
* @return {?}
*/
function (fdDate) {
return false;
});
/**
* Function used to disable certain dates in the calendar for the range start selection.
* @param fdDate FdDate
*/
this.disableRangeStartFunction = (/**
* @param {?} fdDate
* @return {?}
*/
function (fdDate) {
return false;
});
/**
* Function used to disable certain dates in the calendar for the range end selection.
* @param fdDate FdDate
*/
this.disableRangeEndFunction = (/**
* @param {?} fdDate
* @return {?}
*/
function (fdDate) {
return false;
});
/**
* Function used to block certain dates in the calendar for the range start selection.
* @param fdDate FdDate
*/
this.blockRangeStartFunction = (/**
* @param {?} fdDate
* @return {?}
*/
function (fdDate) {
return false;
});
/**
* Function used to block certain dates in the calendar for the range end selection.
* @param fdDate FdDate
*/
this.blockRangeEndFunction = (/**
* @param {?} fdDate
* @return {?}
*/
function (fdDate) {
return false;
});
/**
* Function used to block certain dates in the calendar.
* @param fdDate FdDate
*/
this.blockFunction = (/**
* @param {?} fdDate
* @return {?}
*/
function (fdDate) {
return false;
});
}
/**
* Method that handle calendar active view change and throws event.
* @param {?} activeView
* @return {?}
*/
handleCalendarActiveViewChange(activeView) {
this.activeViewChange.emit(activeView);
}
/**
* @hidden
* @return {?}
*/
closeFromCalendar() {
if (this.type === 'single') {
this.closeCalendar();
}
}
/**
* Opens the calendar
* @return {?}
*/
openCalendar() {
if (!this.disabled) {
this.onTouched();
this.isOpen = true;
}
}
/**
* Toggles the calendar open or closed
* @return {?}
*/
toggleCalendar() {
this.onTouched();
this.isOpen = !this.isOpen;
}
/**
* Closes the calendar if it is open
* @return {?}
*/
closeCalendar() {
if (this.isOpen) {
this.isOpen = false;
}
}
/**
* @hidden
* Method that is triggered by events from calendar component, when there is selected single date changed
* @param {?} date
* @return {?}
*/
handleSingleDateChange(date) {
if (date) {
this.inputFieldDate = this.dateAdapter.format(date);
this.selectedDate = date;
this.selectedDateChange.emit(date);
this.onChange(date);
}
}
/**
* @hidden
* Method that is triggered by events from calendar component, when there is selected range date changed
* @param {?} dates
* @return {?}
*/
handleRangeDateChange(dates) {
if (dates &&
(!CalendarService.datesEqual(this.selectedRangeDate.start, dates.start) ||
!CalendarService.datesEqual(this.selectedRangeDate.end, dates.end))) {
this.inputFieldDate = this.dateAdapter.format(dates.start) + this.dateAdapter.rangeDelimiter
+ this.dateAdapter.format(dates.end);
this.selectedRangeDate = { start: dates.start, end: dates.end };
this.selectedRangeDateChange.emit(this.selectedRangeDate);
this.onChange(this.selectedRangeDate);
}
}
/**
* @hidden
* Method that is triggered when the text input is confirmed to ba changed, by clicking enter, or blur
* @param {?} strDate
* @return {?}
*/
handleInputChange(strDate) {
this.dateStringUpdate(strDate);
}
/**
* @hidden
* Function that implements Validator Interface, adds validation support for forms
* @param {?} control
* @return {?}
*/
validate(control) {
return this.isModelValid() ? null : {
dateValidation: {
valid: false
}
};
}
/**
* @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
* Function that provides support for ControlValueAccessor that allows to use [(ngModel)] or forms
* @param {?} selected
* @return {?}
*/
writeValue(selected) {
/** If written value is not defined, null, empty string */
if (!selected) {
this.inputFieldDate = '';
return;
}
if (this.type === 'single') {
/**
* For single mode, if the date is invalid, model is changed, it refresh currently
* input field text, but it does not refresh currently displayed day
*/
selected = (/** @type {?} */ (selected));
this.selectedDate = selected;
this.inputFieldDate = this.dateAdapter.format(selected);
if (this.isModelValid()) {
this.calendarComponent.setCurrentlyDisplayed(this.selectedDate);
}
}
else {
/**
* For range mode, if the date is invalid, model is changed, but it does not refresh currently
* displayed day view, or input field text
*/
selected = (/** @type {?} */ (selected));
if (selected.start) {
this.selectedRangeDate = { start: selected.start, end: selected.end };
if (this.isModelValid()) {
this.calendarComponent.setCurrentlyDisplayed(this.selectedRangeDate.start);
this.inputFieldDate = this.dateAdapter.format(selected.start) +
this.dateAdapter.rangeDelimiter + this.dateAdapter.format(selected.end);
}
}
else {
this.inputFieldDate = '';
}
}
this.isInvalidDateInput = !this.isModelValid();
}
/**
* @hidden
* Method, which is responsible for transforming string to date, depending on type or
* validation the results are different. It also changes to state of isInvalidDateInput
* @param {?} date
* @return {?}
*/
dateStringUpdate(date) {
/** Case when there is single mode */
if (this.type === 'single') {
/** @type {?} */
const fdDate = this.dateAdapter.parse(date);
/**
* Check if dates are equal, if dates are the same there is no need to make any changes
* Date in model is changed no matter if the parsed date fro string is valid or not.
*/
if (!CalendarService.datesEqual(fdDate, this.selectedDate)) {
this.isInvalidDateInput = !fdDate.isDateValid();
this.selectedDate = fdDate;
this.onChange(this.selectedDate);
this.selectedDateChange.emit(this.selectedDate);
/** Check if date is valid, if it's not, there is no need to refresh calendar */
if (!this.isInvalidDateInput) {
this.calendarComponent.setCurrentlyDisplayed(fdDate);
}
}
/** Case when there is range mode */
}
else {
/** @type {?} */
const currentDates = date.split(this.dateAdapter.rangeDelimiter);
/** @type {?} */
const firstDate = this.dateAdapter.parse(currentDates[0]);
/** @type {?} */
const secondDate = this.dateAdapter.parse(currentDates[1]);
/**
* Check if dates are equal, if dates are the same there is no need to make any changes
* Date in model is changed no matter if the parsed dates from string are valid or not.
*/
if (!CalendarService.datesEqual(firstDate, this.selectedRangeDate.start) ||
!CalendarService.datesEqual(secondDate, this.selectedRangeDate.end)) {
this.isInvalidDateInput = !firstDate.isDateValid() || !secondDate.isDateValid();
/** If the end date is before the start date, there is need to replace them */
if ((firstDate.getTimeStamp() > secondDate.getTimeStamp()) && secondDate.isDateValid()) {
this.selectedRangeDate = { start: secondDate, end: firstDate };
}
else {
this.selectedRangeDate = { start: firstDate, end: secondDate };
}
this.selectedRangeDateChange.emit(this.selectedRangeDate);
this.onChange({ start: this.selectedRangeDate.start, end: this.selectedRangeDate.end });
/** Check if dates are valid, if it's not, there is no need o refresh calendar */
if (!this.isInvalidDateInput) {
this.calendarComponent.setCurrentlyDisplayed(this.selectedRangeDate.start);
}
}
}
if (!date && this.allowNull) {
this.isInvalidDateInput = false;
}
}
/**
* Method that provides information if model selected date/dates have properly types and are valid
* @return {?}
*/
isModelValid() {
if (this.type === 'single') {
return this.selectedDate &&
this.selectedDate instanceof FdDate &&
this.selectedDate.isDateValid();
}
else {
return this.selectedRangeDate &&
(this.selectedRangeDate.start &&
this.selectedRangeDate.start instanceof FdDate &&
this.selectedRangeDate.start.isDateValid()) && (this.selectedRangeDate.end &&
this.selectedRangeDate.end instanceof FdDate &&
this.selectedRangeDate.end.isDateValid());
}
}
}
DatePickerComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-date-picker',
template: "<fd-popover [(isOpen)]=\"isOpen\"\n (isOpenChange)=\"handleInputChange(datePicker.value)\"\n [triggers]=\"[]\"\n [placement]=\"placement\"\n [closeOnEscapeKey]=\"true\"\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)=\"handleInputChange(datePicker.value)\"\n (click)=\"openCalendar()\"\n [disabled]=\"disabled\"\n [ngClass]=\"{ 'fd-input--compact': compact, 'is-invalid': isInvalidDateInput && useValidation }\">\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()\" [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)=\"closeFromCalendar()\"\n [activeView]=\"activeView\"\n (activeViewChange)=\"handleCalendarActiveViewChange($event)\"\n [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 [selectedDate]=\"selectedDate\"\n [selectedRangeDate]=\"selectedRangeDate\"\n (selectedRangeDateChange)=\"handleRangeDateChange($event)\"\n (selectedDateChange)=\"handleSingleDateChange($event)\"\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
},
{
provide: NG_VALIDATORS,
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: DateFormatParser }
];
DatePickerComponent.propDecorators = {
calendarComponent: [{ type: ViewChild, args: [CalendarComponent,] }],
type: [{ type: Input }],
placeholder: [{ type: Input }],
compact: [{ type: Input }],
selectedDate: [{ type: Input }],
selectedRangeDate: [{ type: Input }],
startingDayOfWeek: [{ type: Input }],
useValidation: [{ type: Input }],
dateInputLabel: [{ type: Input }],
displayCalendarToggleLabel: [{ type: Input }],
allowNull: [{ type: Input }],
activeView: [{ type: Input }],
placement: [{ type: Input }],
disabled: [{ type: Input }],
selectedDateChange: [{ type: Output }],
selectedRangeDateChange: [{ type: Output }],
activeViewChange: [{ type: Output }],
disableFunction: [{ type: Input }],
disableRangeStartFunction: [{ type: Input }],
disableRangeEndFunction: [{ type: Input }],
blockRangeStartFunction: [{ type: Input }],
blockRangeEndFunction: [{ type: Input }],
blockFunction: [{ type: Input }]
};
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
* @type {?}
*/
DatePickerComponent.prototype.calendarComponent;
/**
* 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.selectedDate;
/**
* The currently selected FdDates model start and end in range mode.
* @type {?}
*/
DatePickerComponent.prototype.selectedRangeDate;
/**
* 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.useValidation;
/**
* 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;
/**
* Actually shown active view one of 'day' | 'month' | 'year' in calendar component
* @type {?}
*/
DatePickerComponent.prototype.activeView;
/**
* 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;
/**
* Fired when a new date is selected.
* @type {?}
*/
DatePickerComponent.prototype.selectedDateChange;
/**
* Event thrown every time selected first or last date in range mode is changed
* @type {?}
*/
DatePickerComponent.prototype.selectedRangeDateChange;
/**
* Event thrown every time calendar active view is changed
* @type {?}
*/
DatePickerComponent.prototype.activeViewChange;
/**
* @hidden
* @type {?}
*/
DatePickerComponent.prototype.onChange;
/**
* @hidden
* @type {?}
*/
DatePickerComponent.prototype.onTouched;
/**
* Function used to disable certain dates in the calendar.
* \@param fdDate FdDate
* @type {?}
*/
DatePickerComponent.prototype.disableFunction;
/**
* Function used to disable certain dates in the calendar for the range start selection.
* \@param fdDate FdDate
* @type {?}
*/
DatePickerComponent.prototype.disableRangeStartFunction;
/**
* Function used to disable certain dates in the calendar for the range end selection.
* \@param fdDate FdDate
* @type {?}
*/
DatePickerComponent.prototype.disableRangeEndFunction;
/**
* Function used to block certain dates in the calendar for the range start selection.
* \@param fdDate FdDate
* @type {?}
*/
DatePickerComponent.prototype.blockRangeStartFunction;
/**
* Function used to block certain dates in the calendar for the range end selection.
* \@param fdDate FdDate
* @type {?}
*/
DatePickerComponent.prototype.blockRangeEndFunction;
/**
* Function used to block certain dates in the calendar.
* \@param fdDate FdDate
* @type {?}
*/
DatePickerComponent.prototype.blockFunction;
/** @type {?} */
DatePickerComponent.prototype.dateAdapter;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vZnVuZGFtZW50YWwtbmd4LyIsInNvdXJjZXMiOlsibGliL2RhdGUtcGlja2VyL2RhdGUtcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNILFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLEtBQUssRUFDTCxNQUFNLEVBQUUsU0FBUyxFQUNqQixpQkFBaUIsRUFDcEIsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUF5QyxhQUFhLEVBQUUsaUJBQWlCLEVBQWEsTUFBTSxnQkFBZ0IsQ0FBQztBQUVwSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBeUJ4RCxNQUFNLE9BQU8sbUJBQW1COzs7OztJQTBONUIsWUFDVyxXQUE2QjtRQUE3QixnQkFBVyxHQUFYLFdBQVcsQ0FBa0I7Ozs7UUF4TnhDLG1CQUFjLEdBQUcsSUFBSSxDQUFDOzs7O1FBR3RCLHVCQUFrQixHQUFZLEtBQUssQ0FBQzs7OztRQUdwQyxXQUFNLEdBQVksS0FBSyxDQUFDOzs7O1FBT3hCLFNBQUksR0FBaUIsUUFBUSxDQUFDOzs7O1FBSTlCLGdCQUFXLEdBQVcsWUFBWSxDQUFDOzs7O1FBSW5DLFlBQU8sR0FBWSxLQUFLLENBQUM7Ozs7UUFRbEIsc0JBQWlCLEdBQWdCLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUM7Ozs7UUFJbkUsc0JBQWlCLEdBQVcsQ0FBQyxDQUFDOzs7O1FBSTlCLGtCQUFhLEdBQVksSUFBSSxDQUFDOzs7O1FBSTlCLG1CQUFjLEdBQVcsWUFBWSxDQUFDOzs7O1FBSXRDLCtCQUEwQixHQUFXLHlCQUF5QixDQUFDOzs7O1FBSS9ELGNBQVMsR0FBWSxJQUFJLENBQUM7Ozs7UUFJbkIsZUFBVSxHQUFtQixLQUFLLENBQUM7Ozs7O1FBTzFDLGNBQVMsR0FBYyxjQUFjLENBQUM7Ozs7UUFRdEIsdUJBQWtCLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7Ozs7UUFJdEUsNEJBQXVCLEdBQThCLElBQUksWUFBWSxFQUFlLENBQUM7Ozs7UUFJckYscUJBQWdCLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDOzs7O1FBR3BHLGFBQVE7Ozs7UUFBUSxDQUFDLFFBQWEsRUFBRSxFQUFFO1FBQ2xDLENBQUMsRUFBQzs7OztRQUdGLGNBQVM7OztRQUFRLEdBQUcsRUFBRTtRQUN0QixDQUFDLEVBQUM7Ozs7O1FBT0Ysb0JBQWU7Ozs7UUFBRyxVQUFTLE1BQWM7WUFDckMsT0FBTyxLQUFLLENBQUM7UUFDakIsQ0FBQyxFQUFDOzs7OztRQU9GLDhCQUF5Qjs7OztRQUFHLFVBQVMsTUFBYztZQUMvQyxPQUFPLEtBQUssQ0FBQztRQUNqQixDQUFDLEVBQUM7Ozs7O1FBT0YsNEJBQXVCOzs7O1FBQUcsVUFBUyxNQUFjO1lBQzdDLE9BQU8sS0FBSyxDQUFDO1FBQ2pCLENBQUMsRUFBQzs7Ozs7UUFPRiw0QkFBdUI7Ozs7UUFBRyxVQUFTLE1BQWM7WUFDN0MsT0FBTyxLQUFLLENBQUM7UUFDakIsQ0FBQyxFQUFDOzs7OztRQU9GLDBCQUFxQjs7OztRQUFHLFVBQVMsTUFBYztZQUMzQyxPQUFPLEtBQUssQ0FBQztRQUNqQixDQUFDLEVBQUM7Ozs7O1FBT0Ysa0JBQWE7Ozs7UUFBRyxVQUFTLE1BQWM7WUFDbkMsT0FBTyxLQUFLLENBQUM7UUFDakIsQ0FBQyxFQUFDO0lBZ0ZGLENBQUM7Ozs7OztJQTNFTSw4QkFBOEIsQ0FBQyxVQUEwQjtRQUM1RCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7Ozs7O0lBR00saUJBQWlCO1FBQ3BCLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUU7WUFDeEIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1NBQ3hCO0lBQ0wsQ0FBQzs7Ozs7SUFHRCxZQUFZO1FBQ1IsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDaEIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1NBQ3RCO0lBQ0wsQ0FBQzs7Ozs7SUFHTSxjQUFjO1FBQ2pCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUMvQixDQUFDOzs7OztJQUdNLGFBQWE7UUFDaEIsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2IsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7U0FDdkI7SUFDTCxDQUFDOzs7Ozs7O0lBTU0sc0JBQXNCLENBQUMsSUFBWTtRQUN0QyxJQUFJLElBQUksRUFBRTtZQUNOLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7WUFDekIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO0lBQ0wsQ0FBQzs7Ozs7OztJQU1NLHFCQUFxQixDQUFDLEtBQWtCO1FBQzNDLElBQUksS0FBSztZQUNMLENBQUMsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQztnQkFDbkUsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQ3pFO1lBQ0UsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjO2tCQUN0RixJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQ3ZDO1lBQ0QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNoRSxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzFELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7U0FDekM7SUFDTCxDQUFDOzs7Ozs7O0lBTU0saUJBQWlCLENBQUMsT0FBZTtRQUNwQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsQ0FBQzs7Ozs7OztJQVlELFFBQVEsQ0FBQyxPQUF3QjtRQUc3QixPQUFPLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNoQyxjQUFjLEVBQUU7Z0JBQ1osS0FBSyxFQUFFLEtBQUs7YUFDZjtTQUNKLENBQUE7SUFDTCxDQUFDOzs7Ozs7SUFHRCxnQkFBZ0IsQ0FBQyxFQUErQjtRQUM1QyxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUN2QixDQUFDOzs7Ozs7SUFHRCxpQkFBaUIsQ0FBQyxFQUFPO1FBQ3JCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLENBQUM7Ozs7OztJQUdELGdCQUFnQixDQUFDLFVBQW1CO1FBQ2hDLElBQUksQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO0lBQy9CLENBQUM7Ozs7Ozs7SUFNRCxVQUFVLENBQUMsUUFBOEI7UUFDckMsMERBQTBEO1FBQzFELElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDWCxJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztZQUN6QixPQUFPO1NBQ1Y7UUFDRCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO1lBQ3hCOzs7ZUFHRztZQUNILFFBQVEsR0FBRyxtQkFBUSxRQUFRLEVBQUEsQ0FBQztZQUM1QixJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQztZQUM3QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3hELElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFO2dCQUNyQixJQUFJLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQ25FO1NBRUo7YUFBTTtZQUNIOzs7ZUFHRztZQUNILFFBQVEsR0FBRyxtQkFBYSxRQUFRLEVBQUEsQ0FBQztZQUVqQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLEVBQUU7Z0JBQ2hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBRXRFLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFO29CQUNyQixJQUFJLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUMzRSxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7d0JBQ3pELElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDL0U7YUFDSjtpQkFBTTtnQkFDSCxJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQzthQUM1QjtTQUNKO1FBQ0QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ25ELENBQUM7Ozs7Ozs7O0lBT0QsZ0JBQWdCLENBQUMsSUFBWTtRQUN6QixxQ0FBcUM7UUFDckMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRTs7a0JBRWxCLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7WUFFM0M7OztlQUdHO1lBQ0gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRTtnQkFDeEQsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNoRCxJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQztnQkFDM0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUVoRCxnRkFBZ0Y7Z0JBQ2hGLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7b0JBQzFCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDeEQ7YUFDSjtZQUdELG9DQUFvQztTQUN2QzthQUFNOztrQkFDRyxZQUFZLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQzs7a0JBQzFELFNBQVMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7O2tCQUNuRCxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTFEOzs7ZUFHRztZQUNILElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDO2dCQUNwRSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFFckUsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUVoRiwrRUFBK0U7Z0JBQy9FLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLEdBQUcsVUFBVSxDQUFDLFlBQVksRUFBRSxDQUFDLElBQUksVUFBVSxDQUFDLFdBQVcsRUFBRSxFQUFFO29CQUNwRixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQztpQkFDbEU7cUJBQU07b0JBQ0gsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUM7aUJBQ2xFO2dCQUVELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7Z0JBQzFELElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7Z0JBRXhGLGlGQUFpRjtnQkFDakYsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtvQkFDMUIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDOUU7YUFDSjtTQUNKO1FBRUQsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ3pCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUM7U0FDbkM7SUFDTCxDQUFDOzs7OztJQUdNLFlBQVk7UUFDZixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO1lBQ3hCLE9BQU8sSUFBSSxDQUFDLFlBQVk7Z0JBQ3BCLElBQUksQ0FBQyxZQUFZLFlBQVksTUFBTTtnQkFDbkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztTQUN2QzthQUFNO1lBQ0gsT0FBTyxJQUFJLENBQUMsaUJBQWlCO2dCQUN6QixDQUNJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLO29CQUM1QixJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxZQUFZLE1BQU07b0JBQzlDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQzdDLElBQUksQ0FDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRztnQkFDMUIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsWUFBWSxNQUFNO2dCQUM1QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUMzQyxDQUFDO1NBQ1Q7SUFDTCxDQUFDOzs7WUFsWkosU0FBUyxTQUFDO2dCQUNQLFFBQVEsRUFBRSxnQkFBZ0I7Z0JBQzFCLGd2RkFBMkM7Z0JBRTNDLElBQUksRUFBRTtvQkFDRixRQUFRLEVBQUUsYUFBYTtvQkFDdkIsd0JBQXdCLEVBQUUsTUFBTTtvQkFDaEMsK0JBQStCLEVBQUUsTUFBTTtpQkFDMUM7Z0JBQ0QsU0FBUyxFQUFFO29CQUNQO3dCQUNJLE9BQU8sRUFBRSxpQkFBaUI7d0JBQzFCLFdBQVcsRUFBRSxVQUFVOzs7d0JBQUMsR0FBRyxFQUFFLENBQUMsbUJBQW1CLEVBQUM7d0JBQ2xELEtBQUssRUFBRSxJQUFJO3FCQUNkO29CQUNEO3dCQUNJLE9BQU8sRUFBRSxhQUFhO3dCQUN0QixXQUFXLEVBQUUsVUFBVTs7O3dCQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixFQUFDO3dCQUNsRCxLQUFLLEVBQUUsSUFBSTtxQkFDZDtpQkFDSjtnQkFDRCxhQUFhLEVBQUUsaUJBQWlCLENBQUMsSUFBSTs7YUFDeEM7Ozs7WUF4QlEsZ0JBQWdCOzs7Z0NBcUNwQixTQUFTLFNBQUMsaUJBQWlCO21CQUczQixLQUFLOzBCQUlMLEtBQUs7c0JBSUwsS0FBSzsyQkFJTCxLQUFLO2dDQUlMLEtBQUs7Z0NBSUwsS0FBSzs0QkFJTCxLQUFLOzZCQUlMLEtBQUs7eUNBSUwsS0FBSzt3QkFJTCxLQUFLO3lCQUlMLEtBQUs7d0JBT0wsS0FBSzt1QkFJTCxLQUFLO2lDQUlMLE1BQU07c0NBSU4sTUFBTTsrQkFJTixNQUFNOzhCQWVOLEtBQUs7d0NBU0wsS0FBSztzQ0FTTCxLQUFLO3NDQVNMLEtBQUs7b0NBU0wsS0FBSzs0QkFTTCxLQUFLOzs7Ozs7O0lBdklOLDZDQUFzQjs7Ozs7SUFHdEIsaURBQW9DOzs7OztJQUdwQyxxQ0FBd0I7Ozs7O0lBR3hCLGdEQUFtRTs7Ozs7SUFHbkUsbUNBQzhCOzs7OztJQUc5QiwwQ0FDbUM7Ozs7O0lBR25DLHNDQUN5Qjs7Ozs7SUFHekIsMkNBQ3FCOzs7OztJQUdyQixnREFDbUU7Ozs7O0lBR25FLGdEQUM4Qjs7Ozs7SUFHOUIsNENBQzhCOzs7OztJQUc5Qiw2Q0FDc0M7Ozs7O0lBR3RDLHlEQUMrRDs7Ozs7SUFHL0Qsd0NBQzBCOzs7OztJQUcxQix5Q0FDMEM7Ozs7OztJQU0xQyx3Q0FDc0M7Ozs7O0lBR3RDLHVDQUNrQjs7Ozs7SUFHbEIsaURBQ3NGOzs7OztJQUd0RixzREFDcUc7Ozs7O0lBR3JHLCtDQUNvRzs7Ozs7SUFHcEcsdUNBQ0U7Ozs7O0lBR0Ysd0NBQ0U7Ozs7OztJQU1GLDhDQUdFOzs7Ozs7SUFNRix3REFHRTs7Ozs7O0lBTUYsc0RBR0U7Ozs7OztJQU1GLHNEQUdFOzs7Ozs7SUFNRixvREFHRTs7Ozs7O0lBTUYsNENBR0U7O0lBOEVFLDBDQUFvQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBmb3J3YXJkUmVmLFxuICAgIElucHV0LFxuICAgIE91dHB1dCwgVmlld0NoaWxkLFxuICAgIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ2FsZW5kYXJUeXBlLCBGZENhbGVuZGFyVmlldyB9IGZyb20gJy4uL2NhbGVuZGFyL2NhbGVuZGFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxJREFUT1JTLCBOR19WQUxVRV9BQ0NFU1NPUiwgVmFsaWRhdG9yIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgUGxhY2VtZW50IH0gZnJvbSAncG9wcGVyLmpzJztcbmltcG9ydCB7IEZkRGF0ZSB9IGZyb20gJy4uL2NhbGVuZGFyL21vZGVscy9mZC1kYXRlJztcbmltcG9ydCB7IENhbGVuZGFyU2VydmljZSB9IGZyb20gJy4uL2NhbGVuZGFyL2NhbGVuZGFyLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2FsZW5kYXJDb21wb25lbnQgfSBmcm9tICcuLi9jYWxlbmRhci9jYWxlbmRhci5jb21wb25lbnQnO1xuaW1wb3J0IHsgRmRSYW5nZURhdGUgfSBmcm9tICcuLi9jYWxlbmRhci9tb2RlbHMvZmQtcmFuZ2UtZGF0ZSc7XG5pbXBvcnQgeyBEYXRlRm9ybWF0UGFyc2VyIH0gZnJvbSAnLi9mb3JtYXQvZGF0ZS1wYXJzZXInO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2ZkLWRhdGUtcGlja2VyJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZGF0ZS1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlVXJsczogWycuL2RhdGUtcGlja2VyLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgaG9zdDoge1xuICAgICAgICAnKGJsdXIpJzogJ29uVG91Y2hlZCgpJyxcbiAgICAgICAgJ1tjbGFzcy5mZC1kYXRlLXBpY2tlcl0nOiAndHJ1ZScsXG4gICAgICAgICdbY2xhc3MuZmQtZGF0ZS1waWNrZXItY3VzdG9tXSc6ICd0cnVlJ1xuICAgIH0sXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZVBpY2tlckNvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZVBpY2tlckNvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZVxuICAgICAgICB9XG4gICAgXSxcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuZXhwb3J0IGNsYXNzIERhdGVQaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yIHtcblxuICAgIC8qKiBAaGlkZGVuIFRoZSB2YWx1ZSBvZiB0aGUgaW5wdXQgKi9cbiAgICBpbnB1dEZpZWxkRGF0ZSA9IG51bGw7XG5cbiAgICAvKiogQGhpZGRlbiBXaGV0aGVyIHRoZSBkYXRlIGlucHV0IGlzIGludmFsaWQgKi9cbiAgICBpc0ludmFsaWREYXRlSW5wdXQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBAaGlkZGVuIFdoZXRoZXIgdGhlIGRhdGUgcGlja2VyIGlzIG9wZW4gKi9cbiAgICBpc09wZW46IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgQFZpZXdDaGlsZChDYWxlbmRhckNvbXBvbmVudCkgY2FsZW5kYXJDb21wb25lbnQ6IENhbGVuZGFyQ29tcG9uZW50O1xuXG4gICAgLyoqIFRoZSB0eXBlIG9mIGNhbGVuZGFyLCAnc2luZ2xlJyBmb3Igc2luZ2xlIGRhdGUgc2VsZWN0aW9uIG9yICdyYW5nZScgZm9yIGEgcmFuZ2Ugb2YgZGF0ZXMuICovXG4gICAgQElucHV0KClcbiAgICB0eXBlOiBDYWxlbmRhclR5cGUgPSAnc2luZ2xlJztcblxuICAgIC8qKiBEYXRlIHBpY2tlciBpbnB1dCBwbGFjZWhvbGRlciBzdHJpbmcgKi9cbiAgICBASW5wdXQoKVxuICAgIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnbW0vZGQveXl5eSc7XG5cbiAgICAvKiogV2hldGhlciB0aGlzIGlzIHRoZSBjb21wYWN0IGlucHV0IGRhdGUgcGlja2VyICovXG4gICAgQElucHV0KClcbiAgICBjb21wYWN0OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogVGhlIGN1cnJlbnRseSBzZWxlY3RlZCBDYWxlbmRhckRheSBtb2RlbCAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2VsZWN0ZWREYXRlOiBGZERhdGU7XG5cbiAgICAvKiogVGhlIGN1cnJlbnRseSBzZWxlY3RlZCBGZERhdGVzIG1vZGVsIHN0YXJ0IGFuZCBlbmQgaW4gcmFuZ2UgbW9kZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZWxlY3RlZFJhbmdlRGF0ZTogRmRSYW5nZURhdGUgPSB7IHN0YXJ0OiBudWxsLCBlbmQ6IG51bGwgfTtcblxuICAgIC8qKiBUaGUgZGF5IG9mIHRoZSB3ZWVrIHRoZSBjYWxlbmRhciBzaG91bGQgc3RhcnQgb24uIDAgcmVwcmVzZW50cyBTdW5kYXksIDEgaXMgTW9uZGF5LCAyIGlzIFR1ZXNkYXksIGFuZCBzbyBvbi4gKi9cbiAgICBASW5wdXQoKVxuICAgIHN0YXJ0aW5nRGF5T2ZXZWVrOiBudW1iZXIgPSAwO1xuXG4gICAgLyoqIFdoZXRoZXIgdG8gdmFsaWRhdGUgdGhlIGRhdGUgcGlja2VyIGlucHV0LiAqL1xuICAgIEBJbnB1dCgpXG4gICAgdXNlVmFsaWRhdGlvbjogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogQXJpYSBsYWJlbCBmb3IgdGhlIGRhdGVwaWNrZXIgaW5wdXQuICovXG4gICAgQElucHV0KClcbiAgICBkYXRlSW5wdXRMYWJlbDogc3RyaW5nID0gJ0RhdGUgaW5wdXQnO1xuXG4gICAgLyoqIEFyaWEgbGFiZWwgZm9yIHRoZSBidXR0b24gdG8gc2hvdy9oaWRlIHRoZSBjYWxlbmRhci4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc3BsYXlDYWxlbmRhclRvZ2dsZUxhYmVsOiBzdHJpbmcgPSAnRGlzcGxheSBjYWxlbmRhciB0b2dnbGUnO1xuXG4gICAgLyoqIFdoZXRoZXIgYSBudWxsIGlucHV0IGlzIGNvbnNpZGVyZWQgdmFsaWQuICovXG4gICAgQElucHV0KClcbiAgICBhbGxvd051bGw6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIEFjdHVhbGx5IHNob3duIGFjdGl2ZSB2aWV3IG9uZSBvZiAnZGF5JyB8ICdtb250aCcgfCAneWVhcicgaW4gY2FsZW5kYXIgY29tcG9uZW50Ki9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBhY3RpdmVWaWV3OiBGZENhbGVuZGFyVmlldyA9ICdkYXknO1xuXG4gICAgLyoqXG4gICAgICogIFRoZSBwbGFjZW1lbnQgb2YgdGhlIHBvcG92ZXIuIEl0IGNhbiBiZSBvbmUgb2Y6IHRvcCwgdG9wLXN0YXJ0LCB0b3AtZW5kLCBib3R0b20sXG4gICAgICogIGJvdHRvbS1zdGFydCwgYm90dG9tLWVuZCwgcmlnaHQsIHJpZ2h0LXN0YXJ0LCByaWdodC1lbmQsIGxlZnQsIGxlZnQtc3RhcnQsIGxlZnQtZW5kLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcGxhY2VtZW50OiBQbGFjZW1lbnQgPSAnYm90dG9tLXN0YXJ0JztcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBkYXRlIHBpY2tlciBpcyBkaXNhYmxlZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc2FibGVkOiBib29sZWFuO1xuXG4gICAgLyoqIEZpcmVkIHdoZW4gYSBuZXcgZGF0ZSBpcyBzZWxlY3RlZC4gKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgcmVhZG9ubHkgc2VsZWN0ZWREYXRlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8RmREYXRlPiA9IG5ldyBFdmVudEVtaXR0ZXI8RmREYXRlPigpO1xuXG4gICAgLyoqIEV2ZW50IHRocm93biBldmVyeSB0aW1lIHNlbGVjdGVkIGZpcnN0IG9yIGxhc3QgZGF0ZSBpbiByYW5nZSBtb2RlIGlzIGNoYW5nZWQgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgcmVhZG9ubHkgc2VsZWN0ZWRSYW5nZURhdGVDaGFuZ2U6IEV2ZW50RW1pdHRlcjxGZFJhbmdlRGF0ZT4gPSBuZXcgRXZlbnRFbWl0dGVyPEZkUmFuZ2VEYXRlPigpO1xuXG4gICAgLyoqIEV2ZW50IHRocm93biBldmVyeSB0aW1lIGNhbGVuZGFyIGFjdGl2ZSB2aWV3IGlzIGNoYW5nZWQgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgcmVhZG9ubHkgYWN0aXZlVmlld0NoYW5nZTogRXZlbnRFbWl0dGVyPEZkQ2FsZW5kYXJWaWV3PiA9IG5ldyBFdmVudEVtaXR0ZXI8RmRDYWxlbmRhclZpZXc+KCk7XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uQ2hhbmdlOiBhbnkgPSAoc2VsZWN0ZWQ6IGFueSkgPT4ge1xuICAgIH07XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG9uVG91Y2hlZDogYW55ID0gKCkgPT4ge1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGRpc2FibGUgY2VydGFpbiBkYXRlcyBpbiB0aGUgY2FsZW5kYXIuXG4gICAgICogQHBhcmFtIGZkRGF0ZSBGZERhdGVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc2FibGVGdW5jdGlvbiA9IGZ1bmN0aW9uKGZkRGF0ZTogRmREYXRlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdXNlZCB0byBkaXNhYmxlIGNlcnRhaW4gZGF0ZXMgaW4gdGhlIGNhbGVuZGFyIGZvciB0aGUgcmFuZ2Ugc3RhcnQgc2VsZWN0aW9uLlxuICAgICAqIEBwYXJhbSBmZERhdGUgRmREYXRlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlUmFuZ2VTdGFydEZ1bmN0aW9uID0gZnVuY3Rpb24oZmREYXRlOiBGZERhdGUpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB1c2VkIHRvIGRpc2FibGUgY2VydGFpbiBkYXRlcyBpbiB0aGUgY2FsZW5kYXIgZm9yIHRoZSByYW5nZSBlbmQgc2VsZWN0aW9uLlxuICAgICAqIEBwYXJhbSBmZERhdGUgRmREYXRlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlUmFuZ2VFbmRGdW5jdGlvbiA9IGZ1bmN0aW9uKGZkRGF0ZTogRmREYXRlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdXNlZCB0byBibG9jayBjZXJ0YWluIGRhdGVzIGluIHRoZSBjYWxlbmRhciBmb3IgdGhlIHJhbmdlIHN0YXJ0IHNlbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0gZmREYXRlIEZkRGF0ZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgYmxvY2tSYW5nZVN0YXJ0RnVuY3Rpb24gPSBmdW5jdGlvbihmZERhdGU6IEZkRGF0ZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHVzZWQgdG8gYmxvY2sgY2VydGFpbiBkYXRlcyBpbiB0aGUgY2FsZW5kYXIgZm9yIHRoZSByYW5nZSBlbmQgc2VsZWN0aW9uLlxuICAgICAqIEBwYXJhbSBmZERhdGUgRmREYXRlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBibG9ja1JhbmdlRW5kRnVuY3Rpb24gPSBmdW5jdGlvbihmZERhdGU6IEZkRGF0ZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHVzZWQgdG8gYmxvY2sgY2VydGFpbiBkYXRlcyBpbiB0aGUgY2FsZW5kYXIuXG4gICAgICogQHBhcmFtIGZkRGF0ZSBGZERhdGVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGJsb2NrRnVuY3Rpb24gPSBmdW5jdGlvbihmZERhdGU6IEZkRGF0ZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0aGF0IGhhbmRsZSBjYWxlbmRhciBhY3RpdmUgdmlldyBjaGFuZ2UgYW5kIHRocm93cyBldmVudC5cbiAgICAgKi9cbiAgICBwdWJsaWMgaGFuZGxlQ2FsZW5kYXJBY3RpdmVWaWV3Q2hhbmdlKGFjdGl2ZVZpZXc6IEZkQ2FsZW5kYXJWaWV3KTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWN0aXZlVmlld0NoYW5nZS5lbWl0KGFjdGl2ZVZpZXcpO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgcHVibGljIGNsb3NlRnJvbUNhbGVuZGFyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy50eXBlID09PSAnc2luZ2xlJykge1xuICAgICAgICAgICAgdGhpcy5jbG9zZUNhbGVuZGFyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogT3BlbnMgdGhlIGNhbGVuZGFyICovXG4gICAgb3BlbkNhbGVuZGFyKCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogVG9nZ2xlcyB0aGUgY2FsZW5kYXIgb3BlbiBvciBjbG9zZWQgKi9cbiAgICBwdWJsaWMgdG9nZ2xlQ2FsZW5kYXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgICAgIHRoaXMuaXNPcGVuID0gIXRoaXMuaXNPcGVuO1xuICAgIH1cblxuICAgIC8qKiBDbG9zZXMgdGhlIGNhbGVuZGFyIGlmIGl0IGlzIG9wZW4gKi9cbiAgICBwdWJsaWMgY2xvc2VDYWxlbmRhcigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIE1ldGhvZCB0aGF0IGlzIHRyaWdnZXJlZCBieSBldmVudHMgZnJvbSBjYWxlbmRhciBjb21wb25lbnQsIHdoZW4gdGhlcmUgaXMgc2VsZWN0ZWQgc2luZ2xlIGRhdGUgY2hhbmdlZFxuICAgICAqL1xuICAgIHB1YmxpYyBoYW5kbGVTaW5nbGVEYXRlQ2hhbmdlKGRhdGU6IEZkRGF0ZSk6IHZvaWQge1xuICAgICAgICBpZiAoZGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5pbnB1dEZpZWxkRGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIuZm9ybWF0KGRhdGUpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUgPSBkYXRlO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGVDaGFuZ2UuZW1pdChkYXRlKTtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UoZGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogTWV0aG9kIHRoYXQgaXMgdHJpZ2dlcmVkIGJ5IGV2ZW50cyBmcm9tIGNhbGVuZGFyIGNvbXBvbmVudCwgd2hlbiB0aGVyZSBpcyBzZWxlY3RlZCByYW5nZSBkYXRlIGNoYW5nZWRcbiAgICAgKi9cbiAgICBwdWJsaWMgaGFuZGxlUmFuZ2VEYXRlQ2hhbmdlKGRhdGVzOiBGZFJhbmdlRGF0ZSk6IHZvaWQge1xuICAgICAgICBpZiAoZGF0ZXMgJiZcbiAgICAgICAgICAgICghQ2FsZW5kYXJTZXJ2aWNlLmRhdGVzRXF1YWwodGhpcy5zZWxlY3RlZFJhbmdlRGF0ZS5zdGFydCwgZGF0ZXMuc3RhcnQpIHx8XG4gICAgICAgICAgICAgICAgIUNhbGVuZGFyU2VydmljZS5kYXRlc0VxdWFsKHRoaXMuc2VsZWN0ZWRSYW5nZURhdGUuZW5kLCBkYXRlcy5lbmQpKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuaW5wdXRGaWVsZERhdGUgPSB0aGlzLmRhdGVBZGFwdGVyLmZvcm1hdChkYXRlcy5zdGFydCkgKyB0aGlzLmRhdGVBZGFwdGVyLnJhbmdlRGVsaW1pdGVyXG4gICAgICAgICAgICAgICAgKyB0aGlzLmRhdGVBZGFwdGVyLmZvcm1hdChkYXRlcy5lbmQpXG4gICAgICAgICAgICA7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFuZ2VEYXRlID0geyBzdGFydDogZGF0ZXMuc3RhcnQsIGVuZDogZGF0ZXMuZW5kIH07XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkUmFuZ2VEYXRlQ2hhbmdlLmVtaXQodGhpcy5zZWxlY3RlZFJhbmdlRGF0ZSk7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMuc2VsZWN0ZWRSYW5nZURhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIE1ldGhvZCB0aGF0IGlzIHRyaWdnZXJlZCB3aGVuIHRoZSB0ZXh0IGlucHV0IGlzIGNvbmZpcm1lZCB0byBiYSBjaGFuZ2VkLCBieSBjbGlja2luZyBlbnRlciwgb3IgYmx1clxuICAgICAqL1xuICAgIHB1YmxpYyBoYW5kbGVJbnB1dENoYW5nZShzdHJEYXRlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYXRlU3RyaW5nVXBkYXRlKHN0ckRhdGUpO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHB1YmxpYyBkYXRlQWRhcHRlcjogRGF0ZUZvcm1hdFBhcnNlclxuICAgICkge1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBGdW5jdGlvbiB0aGF0IGltcGxlbWVudHMgVmFsaWRhdG9yIEludGVyZmFjZSwgYWRkcyB2YWxpZGF0aW9uIHN1cHBvcnQgZm9yIGZvcm1zXG4gICAgICovXG4gICAgdmFsaWRhdGUoY29udHJvbDogQWJzdHJhY3RDb250cm9sKToge1xuICAgICAgICBba2V5OiBzdHJpbmddOiBhbnlcbiAgICB9IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNNb2RlbFZhbGlkKCkgPyBudWxsIDoge1xuICAgICAgICAgICAgZGF0ZVZhbGlkYXRpb246IHtcbiAgICAgICAgICAgICAgICB2YWxpZDogZmFsc2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHNlbGVjdGVkOiBhbnkpID0+IHsgdm9pZCB9KTogdm9pZCB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogRnVuY3Rpb24gdGhhdCBwcm92aWRlcyBzdXBwb3J0IGZvciBDb250cm9sVmFsdWVBY2Nlc3NvciB0aGF0IGFsbG93cyB0byB1c2UgWyhuZ01vZGVsKV0gb3IgZm9ybXNcbiAgICAgKi9cbiAgICB3cml0ZVZhbHVlKHNlbGVjdGVkOiBGZFJhbmdlRGF0ZSB8IEZkRGF0ZSk6IHZvaWQge1xuICAgICAgICAvKiogSWYgd3JpdHRlbiB2YWx1ZSBpcyBub3QgZGVmaW5lZCwgbnVsbCwgZW1wdHkgc3RyaW5nICovXG4gICAgICAgIGlmICghc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5wdXRGaWVsZERhdGUgPSAnJztcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy50eXBlID09PSAnc2luZ2xlJykge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBGb3Igc2luZ2xlIG1vZGUsIGlmIHRoZSBkYXRlIGlzIGludmFsaWQsIG1vZGVsIGlzIGNoYW5nZWQsIGl0IHJlZnJlc2ggY3VycmVudGx5XG4gICAgICAgICAgICAgKiBpbnB1dCBmaWVsZCB0ZXh0LCBidXQgaXQgZG9lcyBub3QgcmVmcmVzaCBjdXJyZW50bHkgZGlzcGxheWVkIGRheVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZWxlY3RlZCA9IDxGZERhdGU+c2VsZWN0ZWQ7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IHNlbGVjdGVkO1xuICAgICAgICAgICAgdGhpcy5pbnB1dEZpZWxkRGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIuZm9ybWF0KHNlbGVjdGVkKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzTW9kZWxWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxlbmRhckNvbXBvbmVudC5zZXRDdXJyZW50bHlEaXNwbGF5ZWQodGhpcy5zZWxlY3RlZERhdGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEZvciByYW5nZSBtb2RlLCBpZiB0aGUgZGF0ZSBpcyBpbnZhbGlkLCBtb2RlbCBpcyBjaGFuZ2VkLCBidXQgaXQgZG9lcyBub3QgcmVmcmVzaCBjdXJyZW50bHlcbiAgICAgICAgICAgICAqIGRpc3BsYXllZCBkYXkgdmlldywgb3IgaW5wdXQgZmllbGQgdGV4dFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZWxlY3RlZCA9IDxGZFJhbmdlRGF0ZT5zZWxlY3RlZDtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdGVkLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlRGF0ZSA9IHsgc3RhcnQ6IHNlbGVjdGVkLnN0YXJ0LCBlbmQ6IHNlbGVjdGVkLmVuZCB9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNNb2RlbFZhbGlkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxlbmRhckNvbXBvbmVudC5zZXRDdXJyZW50bHlEaXNwbGF5ZWQodGhpcy5zZWxlY3RlZFJhbmdlRGF0ZS5zdGFydCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRGaWVsZERhdGUgPSB0aGlzLmRhdGVBZGFwdGVyLmZvcm1hdChzZWxlY3RlZC5zdGFydCkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlQWRhcHRlci5yYW5nZURlbGltaXRlciArIHRoaXMuZGF0ZUFkYXB0ZXIuZm9ybWF0KHNlbGVjdGVkLmVuZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0RmllbGREYXRlID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc0ludmFsaWREYXRlSW5wdXQgPSAhdGhpcy5pc01vZGVsVmFsaWQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogTWV0aG9kLCB3aGljaCBpcyByZXNwb25zaWJsZSBmb3IgdHJhbnNmb3JtaW5nIHN0cmluZyB0byBkYXRlLCBkZXBlbmRpbmcgb24gdHlwZSBvclxuICAgICAqIHZhbGlkYXRpb24gdGhlIHJlc3VsdHMgYXJlIGRpZmZlcmVudC4gSXQgYWxzbyBjaGFuZ2VzIHRvIHN0YXRlIG9mIGlzSW52YWxpZERhdGVJbnB1dFxuICAgICAqL1xuICAgIGRhdGVTdHJpbmdVcGRhdGUoZGF0ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIC8qKiBDYXNlIHdoZW4gdGhlcmUgaXMgc2luZ2xlIG1vZGUgKi9cbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3NpbmdsZScpIHtcblxuICAgICAgICAgICAgY29uc3QgZmREYXRlID0gdGhpcy5kYXRlQWRhcHRlci5wYXJzZShkYXRlKTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDaGVjayBpZiBkYXRlcyBhcmUgZXF1YWwsIGlmIGRhdGVzIGFyZSB0aGUgc2FtZSB0aGVyZSBpcyBubyBuZWVkIHRvIG1ha2UgYW55IGNoYW5nZXNcbiAgICAgICAgICAgICAqIERhdGUgaW4gbW9kZWwgaXMgY2hhbmdlZCBubyBtYXR0ZXIgaWYgdGhlIHBhcnNlZCBkYXRlIGZybyBzdHJpbmcgaXMgdmFsaWQgb3Igbm90LlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAoIUNhbGVuZGFyU2VydmljZS5kYXRlc0VxdWFsKGZkRGF0ZSwgdGhpcy5zZWxlY3RlZERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc0ludmFsaWREYXRlSW5wdXQgPSAhZmREYXRlLmlzRGF0ZVZhbGlkKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGUgPSBmZERhdGU7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLnNlbGVjdGVkRGF0ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZERhdGVDaGFuZ2UuZW1pdCh0aGlzLnNlbGVjdGVkRGF0ZSk7XG5cbiA