fundamental-ngx
Version:
SAP Fiori Fundamentals, implemented in Angular
628 lines • 50.6 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ElementRef, EventEmitter, forwardRef, HostListener, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { TimeComponent } from '../time/time.component';
import { DateTimeFormatParser } from './format/datetime-parser';
/**
* The datetime picker component is an opinionated composition of the fd-popover,
* fd-calendar and fd-time components to accomplish the UI pattern for picking a date and time.
*/
export class DatetimePickerComponent {
/**
* @hidden
* @param {?} elRef
* @param {?} dateTimeAdapter
*/
constructor(elRef, dateTimeAdapter) {
this.elRef = elRef;
this.dateTimeAdapter = dateTimeAdapter;
/**
* Placeholder for the inner input element.
*/
this.placeholder = 'mm/dd/yyyy, hh:mm:ss am';
/**
* Whether the component should be in compact mode.
*/
this.compact = false;
/**
* 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';
/**
* Whether the time component should be meridian (am/pm).
*/
this.meridian = true;
/**
* Whether the time component shows spinners for changing the time.
*/
this.spinners = true;
/**
* Whether the time component shows seconds.
*/
this.displaySeconds = true;
/**
* Whether to perform visual validation on the picker input.
*/
this.validate = true;
/**
* Current selected date. Two-way binding is supported.
*/
this.date = new Date();
/**
* Whether the popover is open. Two-way binding is supported.
*/
this.isOpen = false;
/**
* The disableFunction for the calendar.
*/
this.startingDayOfWeek = 0;
/**
* Aria label for the datetime picker input.
*/
this.datetimeInputLabel = 'Datetime input';
/**
* Aria label for the button to show/hide the calendar.
*/
this.displayDatetimeToggleLabel = 'Display calendar toggle';
/**
* Whether a null input is considered valid.
*/
this.allowNull = true;
/**
* Event emitted when the date changes. This can be a time or day change.
*/
this.dateChange = new EventEmitter();
/**
* Event emitted when the day changes from the calendar.
*/
this.calendarChange = new EventEmitter();
/**
* Event emitted when the time changes from the time component.
*/
this.timeChange = new EventEmitter();
/**
* Event emitted when popover closes.
*/
this.onClose = new EventEmitter();
/**
* @hidden Date of the input field. Internal use.
* For programmatic selection, use two-way binding on the date input.
*/
this.inputFieldDate = null;
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
*/
this.isInvalidDateInput = false;
/**
* @hidden Observable used internally.
*/
this.dateFromInput = new Subject();
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
*/
this.time = { hour: 0, minute: 0, second: 0 };
/**
* @hidden The CalendarDay object which interacts with the inner Calendar component. Internal use.
*/
this.selectedDay = {
date: null
};
this.disableFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* The blockFunction for the calendar.
*/
this.blockFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.disableRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.disableRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.blockRangeStartFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
this.blockRangeEndFunction = (/**
* @param {?} d
* @return {?}
*/
function (d) {
return false;
});
/**
* @hidden
*/
this.onChange = (/**
* @return {?}
*/
() => { });
/**
* @hidden
*/
this.onTouched = (/**
* @return {?}
*/
() => { });
}
/**
* Toggles the popover.
* @return {?}
*/
togglePopover() {
this.onTouched(this.selectedDay.date);
if (this.isOpen) {
this.closePopover();
}
else {
this.openPopover();
}
}
/**
* Opens the popover.
* @param {?=} inputFieldDate
* @return {?}
*/
openPopover(inputFieldDate) {
if (!this.isOpen && !this.disabled) {
this.onTouched(this.selectedDay.date);
this.isOpen = true;
if (inputFieldDate !== null && inputFieldDate !== '' && !this.isInvalidDateInput) {
this.inputValueChange(this.date);
}
}
}
/**
* Closes the popover
* @return {?}
*/
closePopover() {
if (this.isOpen) {
this.onClose.emit(this.date);
this.isOpen = false;
}
}
/**
* @param {?} d
* @return {?}
*/
updatePickerInputHandler(d) {
if (d.selectedDay && d.selectedDay.date) {
d.selectedDay.date.setHours(this.date.getHours());
d.selectedDay.date.setMinutes(this.date.getMinutes());
d.selectedDay.date.setSeconds(this.date.getSeconds());
d.selectedDay.date.setMilliseconds(this.date.getMilliseconds());
/** @type {?} */
const previous = this.date.getTime();
this.selectedDay = d.selectedDay;
this.date = d.selectedDay.date;
this.inputFieldDate = this.dateTimeAdapter.format(this.date);
this.time = { hour: this.date.getHours(), minute: this.date.getMinutes(), second: this.date.getSeconds() };
if (this.date.getTime() !== previous) {
this.calendarChange.emit(this.date);
this.dateChange.emit(this.date);
this.onChange(this.date);
}
}
else if (d === '') {
this.selectedDay.date = null;
this.selectedDay.selected = null;
this.time.second = null;
this.time.minute = null;
this.time.hour = null;
this.timeComponent.displayedHour = null;
this.timeComponent.period = 'am';
this.timeComponent.oldPeriod = 'am';
this.calendarChange.emit(null);
this.timeChange.emit(null);
this.dateChange.emit(null);
this.onChange(this.selectedDay.date);
}
}
/**
* @hidden
* @param {?} e
* @return {?}
*/
isInvalidDateInputHandler(e) {
this.isInvalidDateInput = e;
}
/**
* @hidden
* @param {?} e
* @return {?}
*/
inputValueChange(e) {
/** @type {?} */
let temp;
if (typeof e === 'string') {
temp = this.dateTimeAdapter.parse(e);
}
else {
temp = new Date(e);
}
/*
Need to check if current locale toDateString contains AM or PM. If the current locale has it and it is absent
from the user's input, the meridian should be considered invalid
*/
/** @type {?} */
const localeMeridian = new Date().toLocaleTimeString().slice(-2);
/** @type {?} */
let meridianValid = true;
if ((localeMeridian === 'AM' || localeMeridian === 'PM') &&
(typeof e === 'string' && e.slice(-2) !== 'AM' && e.slice(-2) !== 'PM')) {
meridianValid = false;
}
if (meridianValid && temp && temp.toLocaleDateString() !== 'Invalid Date') {
/** @type {?} */
const newValue = { hour: temp.getHours(), minute: temp.getMinutes(), second: temp.getSeconds() };
if (newValue.hour !== this.time.hour || newValue.minute !== this.time.minute || newValue.second !== this.time.second) {
this.time = newValue;
this.setTime(true);
}
this.dateFromInput.next(temp.toLocaleDateString());
}
else if (e === '' && this.allowNull) {
this.isInvalidDateInput = false;
this.dateFromInput.next('');
}
else {
this.isInvalidDateInput = true;
}
}
/**
* @hidden
* @return {?}
*/
onEscapeKeydownHandler() {
this.closePopover();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onGlobalClick(event) {
if (!this.elRef.nativeElement.contains(event.target)) {
this.closePopover();
}
}
/**
* @hidden
* @return {?}
*/
ngOnInit() {
if (this.date && this.inputFieldDate !== null) {
this.selectedDay.date = this.date;
this.time = { hour: this.date.getHours(), minute: this.date.getMinutes(), second: this.date.getSeconds() };
}
if (this.dateFromInput) {
this.dateFromInputSubscription = this.dateFromInput.subscribe((/**
* @param {?} date
* @return {?}
*/
date => {
this.updatePickerInputHandler(date);
}));
}
}
/**
* @hidden
* @return {?}
*/
ngOnDestroy() {
if (this.dateFromInputSubscription) {
this.dateFromInputSubscription.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;
}
this.selectedDay.date = selected;
this.time = { hour: selected.getHours(), minute: selected.getMinutes(), second: selected.getSeconds() };
this.date = this.selectedDay.date;
this.setTime();
}
/**
* @hidden
* @param {?=} fireEvents
* @return {?}
*/
setTime(fireEvents = false) {
this.date.setHours(this.time.hour);
this.date.setMinutes(this.time.minute);
this.date.setSeconds(this.time.second);
this.inputFieldDate = this.dateTimeAdapter.format(this.date);
if (fireEvents) {
this.timeChange.emit(this.date);
this.dateChange.emit(this.date);
this.onChange(this.date);
}
}
/**
* @hidden
* @return {?}
*/
focusArrowLeft() {
this.elRef.nativeElement.querySelector('#arrowLeft').focus();
}
}
DatetimePickerComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-datetime-picker',
template: "<div class=\"fd-datetime\">\n <fd-popover [(isOpen)]=\"isOpen\"\n [closeOnOutsideClick]=\"false\"\n [closeOnEscapeKey]=\"false\"\n [triggers]=\"[]\"\n [disabled]=\"disabled\"\n [placement]=\"placement\">\n <fd-popover-control>\n <div class=\"fd-input-group fd-input-group--after\"\n [ngClass]=\"{'fd-input-group--compact' : compact}\">\n <input type=\"text\"\n [attr.aria-label]=\"datetimeInputLabel\"\n [(ngModel)]=\"inputFieldDate\"\n [placeholder]=\"placeholder\"\n (keyup.enter)=\"inputValueChange(inputFieldDate)\"\n (blur)=\"inputValueChange(inputFieldDate)\"\n (click)=\"openPopover(inputFieldDate)\"\n [ngClass]=\"{ 'fd-input--compact': compact, 'is-invalid': isInvalidDateInput && validate }\"\n [disabled]=\"disabled\">\n <span class=\"fd-input-group__addon fd-input-group__addon--after fd-input-group__addon--button\">\n <button class=\"fd-popover__control fd-button--icon fd-button--light sap-icon--date-time\"\n (click)=\"togglePopover()\" [attr.aria-label]=\"displayDatetimeToggleLabel\"\n [attr.aria-expanded]=\"isOpen\" type=\"button\" [disabled]=\"disabled\"></button>\n </span>\n </div>\n </fd-popover-control>\n <fd-popover-body\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-hidden]=\"!isOpen\"\n [style.display]=\"'block'\">\n <div class=\"fd-datetime__container\">\n <fd-calendar calType=\"single\"\n (closeCalendar)=\"closePopover()\"\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 (isInvalidDateInput)=\"isInvalidDateInputHandler($event)\"\n [dateFromDatePicker]=\"dateFromInput\"\n [allowFocusEscape]=\"true\"\n [startingDayOfWeek]=\"startingDayOfWeek\"></fd-calendar>\n <div class=\"fd-datetime__separator\"></div>\n <fd-time [disabled]=\"disabled\"\n [meridian]=\"meridian\"\n [(ngModel)]=\"time\"\n (ngModelChange)=\"setTime(true)\"\n [spinners]=\"spinners\"\n [displaySeconds]=\"displaySeconds\"\n (focusArrowLeft)=\"focusArrowLeft()\"></fd-time>\n </div>\n </fd-popover-body>\n </fd-popover>\n</div>\n",
host: {
'(blur)': 'onTouched()',
'[class.fd-datetime-host]': 'true'
},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef((/**
* @return {?}
*/
() => DatetimePickerComponent)),
multi: true
}
],
encapsulation: ViewEncapsulation.None,
styles: [".fd-datetime-host{display:inline-block;width:230px}.fd-datetime-host .fd-datetime{display:block}.fd-datetime-host .fd-datetime__container{display:flex;align-items:center;margin:0 16px}.fd-datetime-host .fd-datetime__separator{background-color:#d3d3d3;width:1px;margin:42px 28px;-ms-grid-row-align:stretch;align-self:stretch}.fd-datetime-host .fd-datetime fd-popover{display:block}.fd-datetime-host .fd-datetime fd-time{width:auto}"]
}] }
];
/** @nocollapse */
DatetimePickerComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: DateTimeFormatParser }
];
DatetimePickerComponent.propDecorators = {
timeComponent: [{ type: ViewChild, args: [TimeComponent,] }],
placeholder: [{ type: Input }],
compact: [{ type: Input }],
placement: [{ type: Input }],
meridian: [{ type: Input }],
disabled: [{ type: Input }],
spinners: [{ type: Input }],
displaySeconds: [{ type: Input }],
validate: [{ type: Input }],
date: [{ type: Input }],
isOpen: [{ type: Input }],
startingDayOfWeek: [{ type: Input }],
datetimeInputLabel: [{ type: Input }],
displayDatetimeToggleLabel: [{ type: Input }],
allowNull: [{ type: Input }],
dateChange: [{ type: Output }],
calendarChange: [{ type: Output }],
timeChange: [{ type: Output }],
onClose: [{ type: Output }],
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 Reference to the inner time component.
* @type {?}
*/
DatetimePickerComponent.prototype.timeComponent;
/**
* Placeholder for the inner input element.
* @type {?}
*/
DatetimePickerComponent.prototype.placeholder;
/**
* Whether the component should be in compact mode.
* @type {?}
*/
DatetimePickerComponent.prototype.compact;
/**
* 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 {?}
*/
DatetimePickerComponent.prototype.placement;
/**
* Whether the time component should be meridian (am/pm).
* @type {?}
*/
DatetimePickerComponent.prototype.meridian;
/**
* Whether the component is disabled.
* @type {?}
*/
DatetimePickerComponent.prototype.disabled;
/**
* Whether the time component shows spinners for changing the time.
* @type {?}
*/
DatetimePickerComponent.prototype.spinners;
/**
* Whether the time component shows seconds.
* @type {?}
*/
DatetimePickerComponent.prototype.displaySeconds;
/**
* Whether to perform visual validation on the picker input.
* @type {?}
*/
DatetimePickerComponent.prototype.validate;
/**
* Current selected date. Two-way binding is supported.
* @type {?}
*/
DatetimePickerComponent.prototype.date;
/**
* Whether the popover is open. Two-way binding is supported.
* @type {?}
*/
DatetimePickerComponent.prototype.isOpen;
/**
* The disableFunction for the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.startingDayOfWeek;
/**
* Aria label for the datetime picker input.
* @type {?}
*/
DatetimePickerComponent.prototype.datetimeInputLabel;
/**
* Aria label for the button to show/hide the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.displayDatetimeToggleLabel;
/**
* Whether a null input is considered valid.
* @type {?}
*/
DatetimePickerComponent.prototype.allowNull;
/**
* Event emitted when the date changes. This can be a time or day change.
* @type {?}
*/
DatetimePickerComponent.prototype.dateChange;
/**
* Event emitted when the day changes from the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.calendarChange;
/**
* Event emitted when the time changes from the time component.
* @type {?}
*/
DatetimePickerComponent.prototype.timeChange;
/**
* Event emitted when popover closes.
* @type {?}
*/
DatetimePickerComponent.prototype.onClose;
/**
* @hidden Date of the input field. Internal use.
* For programmatic selection, use two-way binding on the date input.
* @type {?}
*/
DatetimePickerComponent.prototype.inputFieldDate;
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
* @type {?}
*/
DatetimePickerComponent.prototype.isInvalidDateInput;
/**
* @hidden Observable used internally.
* @type {?}
*/
DatetimePickerComponent.prototype.dateFromInput;
/**
* @hidden The Time object which interacts with the inner Time component. Internal use.
* @type {?}
*/
DatetimePickerComponent.prototype.time;
/**
* @hidden The CalendarDay object which interacts with the inner Calendar component. Internal use.
* @type {?}
*/
DatetimePickerComponent.prototype.selectedDay;
/**
* Subscription of the dateFromInput.
* @type {?}
* @private
*/
DatetimePickerComponent.prototype.dateFromInputSubscription;
/** @type {?} */
DatetimePickerComponent.prototype.disableFunction;
/**
* The blockFunction for the calendar.
* @type {?}
*/
DatetimePickerComponent.prototype.blockFunction;
/** @type {?} */
DatetimePickerComponent.prototype.disableRangeStartFunction;
/** @type {?} */
DatetimePickerComponent.prototype.disableRangeEndFunction;
/** @type {?} */
DatetimePickerComponent.prototype.blockRangeStartFunction;
/** @type {?} */
DatetimePickerComponent.prototype.blockRangeEndFunction;
/**
* @hidden
* @type {?}
*/
DatetimePickerComponent.prototype.onChange;
/**
* @hidden
* @type {?}
*/
DatetimePickerComponent.prototype.onTouched;
/**
* @type {?}
* @private
*/
DatetimePickerComponent.prototype.elRef;
/**
* @type {?}
* @private
*/
DatetimePickerComponent.prototype.dateTimeAdapter;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXRpbWUtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2Z1bmRhbWVudGFsLW5neC8iLCJzb3VyY2VzIjpbImxpYi9kYXRldGltZS1waWNrZXIvZGF0ZXRpbWUtcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sRUFDTixTQUFTLEVBQ1QsaUJBQWlCLEVBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUU3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFdkQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7Ozs7O0FBdUJoRSxNQUFNLE9BQU8sdUJBQXVCOzs7Ozs7SUE4UWhDLFlBQW9CLEtBQWlCLEVBQ2pCLGVBQXFDO1FBRHJDLFVBQUssR0FBTCxLQUFLLENBQVk7UUFDakIsb0JBQWUsR0FBZixlQUFlLENBQXNCOzs7O1FBdlF6RCxnQkFBVyxHQUFXLHlCQUF5QixDQUFDOzs7O1FBSWhELFlBQU8sR0FBWSxLQUFLLENBQUM7Ozs7O1FBS3pCLGNBQVMsR0FBYyxjQUFjLENBQUM7Ozs7UUFJdEMsYUFBUSxHQUFZLElBQUksQ0FBQzs7OztRQVF6QixhQUFRLEdBQVksSUFBSSxDQUFDOzs7O1FBSXpCLG1CQUFjLEdBQVksSUFBSSxDQUFDOzs7O1FBSS9CLGFBQVEsR0FBWSxJQUFJLENBQUM7Ozs7UUFJekIsU0FBSSxHQUFTLElBQUksSUFBSSxFQUFFLENBQUM7Ozs7UUFJeEIsV0FBTSxHQUFZLEtBQUssQ0FBQzs7OztRQUl4QixzQkFBaUIsR0FBVyxDQUFDLENB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TCxLQUFLO2dDQUlMLEtBQUs7aUNBSUwsS0FBSzt5Q0FJTCxLQUFLO3dCQUlMLEtBQUs7eUJBSUwsTUFBTTs2QkFJTixNQUFNO3lCQUlOLE1BQU07c0JBSU4sTUFBTTs4QkEwQk4sS0FBSzs0QkFNTCxLQUFLO3dDQUlMLEtBQUs7c0NBSUwsS0FBSztzQ0FJTCxLQUFLO29DQUlMLEtBQUs7cUNBZ0hMLFlBQVksU0FBQyx5QkFBeUIsRUFBRSxFQUFFOzRCQU0xQyxZQUFZLFNBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Ozs7Ozs7SUEvTzFDLGdEQUM2Qjs7Ozs7SUFHN0IsOENBQ2dEOzs7OztJQUdoRCwwQ0FDeUI7Ozs7OztJQUl6Qiw0Q0FDc0M7Ozs7O0lBR3RDLDJDQUN5Qjs7Ozs7SUFHekIsMkNBQ2tCOzs7OztJQUdsQiwyQ0FDeUI7Ozs7O0lBR3pCLGlEQUMrQjs7Ozs7SUFHL0IsMkNBQ3lCOzs7OztJQUd6Qix1Q0FDd0I7Ozs7O0lBR3hCLHlDQUN3Qjs7Ozs7SUFHeEIsb0RBQzhCOzs7OztJQUc5QixxREFDOEM7Ozs7O0lBRzlDLDZEQUMrRDs7Ozs7SUFHL0QsNENBQzBCOzs7OztJQUcxQiw2Q0FDbUU7Ozs7O0lBR25FLGlEQUN1RTs7Ozs7SUFHdkUsNkNBQ21FOzs7OztJQUduRSwwQ0FDZ0U7Ozs7OztJQU1oRSxpREFBc0I7Ozs7O0lBR3RCLHFEQUFvQzs7Ozs7SUFHcEMsZ0RBQStDOzs7OztJQUcvQyx1Q0FBcUQ7Ozs7O0lBR3JELDhDQUVFOzs7Ozs7SUFHRiw0REFBZ0Q7O0lBRWhELGtEQUdFOzs7OztJQUdGLGdEQUdFOztJQUNGLDREQUdFOztJQUNGLDBEQUdFOztJQUNGLDBEQUdFOztJQUNGLHdEQUdFOzs7OztJQUdGLDJDQUF5Qjs7Ozs7SUFHekIsNENBQTBCOzs7OztJQXlJZCx3Q0FBeUI7Ozs7O0lBQ3pCLGtEQUE2QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIGZvcndhcmRSZWYsIEhvc3RCaW5kaW5nLFxuICAgIEhvc3RMaXN0ZW5lcixcbiAgICBJbnB1dCxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT25Jbml0LFxuICAgIE91dHB1dCxcbiAgICBWaWV3Q2hpbGQsXG4gICAgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDYWxlbmRhckRheSB9IGZyb20gJy4uL2NhbGVuZGFyL2NhbGVuZGFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRpbWVPYmplY3QgfSBmcm9tICcuLi90aW1lL3RpbWUtb2JqZWN0JztcbmltcG9ydCB7IFRpbWVDb21wb25lbnQgfSBmcm9tICcuLi90aW1lL3RpbWUuY29tcG9uZW50JztcbmltcG9ydCB7IFBsYWNlbWVudCB9IGZyb20gJ3BvcHBlci5qcyc7XG5pbXBvcnQgeyBEYXRlVGltZUZvcm1hdFBhcnNlciB9IGZyb20gJy4vZm9ybWF0L2RhdGV0aW1lLXBhcnNlcic7XG5cbi8qKlxuICogVGhlIGRhdGV0aW1lIHBpY2tlciBjb21wb25lbnQgaXMgYW4gb3BpbmlvbmF0ZWQgY29tcG9zaXRpb24gb2YgdGhlIGZkLXBvcG92ZXIsXG4gKiBmZC1jYWxlbmRhciBhbmQgZmQtdGltZSBjb21wb25lbnRzIHRvIGFjY29tcGxpc2ggdGhlIFVJIHBhdHRlcm4gZm9yIHBpY2tpbmcgYSBkYXRlIGFuZCB0aW1lLlxuICovXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2ZkLWRhdGV0aW1lLXBpY2tlcicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2RhdGV0aW1lLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZGF0ZXRpbWUtcGlja2VyLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgaG9zdDoge1xuICAgICAgICAnKGJsdXIpJzogJ29uVG91Y2hlZCgpJyxcbiAgICAgICAgJ1tjbGFzcy5mZC1kYXRldGltZS1ob3N0XSc6ICd0cnVlJ1xuICAgIH0sXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZXRpbWVQaWNrZXJDb21wb25lbnQpLFxuICAgICAgICAgICAgbXVsdGk6IHRydWVcbiAgICAgICAgfVxuICAgIF0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxufSlcbmV4cG9ydCBjbGFzcyBEYXRldGltZVBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cbiAgICAvKiogQGhpZGRlbiBSZWZlcmVuY2UgdG8gdGhlIGlubmVyIHRpbWUgY29tcG9uZW50LiAqL1xuICAgIEBWaWV3Q2hpbGQoVGltZUNvbXBvbmVudClcbiAgICB0aW1lQ29tcG9uZW50OiBUaW1lQ29tcG9uZW50O1xuXG4gICAgLyoqIFBsYWNlaG9sZGVyIGZvciB0aGUgaW5uZXIgaW5wdXQgZWxlbWVudC4gKi9cbiAgICBASW5wdXQoKVxuICAgIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnbW0vZGQveXl5eSwgaGg6bW06c3MgYW0nO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGNvbXBvbmVudCBzaG91bGQgYmUgaW4gY29tcGFjdCBtb2RlLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgY29tcGFjdDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIFRoZSBwbGFjZW1lbnQgb2YgdGhlIHBvcG92ZXIuIEl0IGNhbiBiZSBvbmUgb2Y6IHRvcCwgdG9wLXN0YXJ0LCB0b3AtZW5kLCBib3R0b20sXG4gICAgICogIGJvdHRvbS1zdGFydCwgYm90dG9tLWVuZCwgcmlnaHQsIHJpZ2h0LXN0YXJ0LCByaWdodC1lbmQsIGxlZnQsIGxlZnQtc3RhcnQsIGxlZnQtZW5kLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgcGxhY2VtZW50OiBQbGFjZW1lbnQgPSAnYm90dG9tLXN0YXJ0JztcblxuICAgIC8qKiBXaGV0aGVyIHRoZSB0aW1lIGNvbXBvbmVudCBzaG91bGQgYmUgbWVyaWRpYW4gKGFtL3BtKS4gKi9cbiAgICBASW5wdXQoKVxuICAgIG1lcmlkaWFuOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBjb21wb25lbnQgaXMgZGlzYWJsZWQuICovXG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlZDogYm9vbGVhbjtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSB0aW1lIGNvbXBvbmVudCBzaG93cyBzcGlubmVycyBmb3IgY2hhbmdpbmcgdGhlIHRpbWUuICovXG4gICAgQElucHV0KClcbiAgICBzcGlubmVyczogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogV2hldGhlciB0aGUgdGltZSBjb21wb25lbnQgc2hvd3Mgc2Vjb25kcy4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc3BsYXlTZWNvbmRzOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBXaGV0aGVyIHRvIHBlcmZvcm0gdmlzdWFsIHZhbGlkYXRpb24gb24gdGhlIHBpY2tlciBpbnB1dC4gKi9cbiAgICBASW5wdXQoKVxuICAgIHZhbGlkYXRlOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKiBDdXJyZW50IHNlbGVjdGVkIGRhdGUuIFR3by13YXkgYmluZGluZyBpcyBzdXBwb3J0ZWQuICovXG4gICAgQElucHV0KClcbiAgICBkYXRlOiBEYXRlID0gbmV3IERhdGUoKTtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBwb3BvdmVyIGlzIG9wZW4uIFR3by13YXkgYmluZGluZyBpcyBzdXBwb3J0ZWQuICovXG4gICAgQElucHV0KClcbiAgICBpc09wZW46IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBUaGUgZGlzYWJsZUZ1bmN0aW9uIGZvciB0aGUgY2FsZW5kYXIuICovXG4gICAgQElucHV0KClcbiAgICBzdGFydGluZ0RheU9mV2VlazogbnVtYmVyID0gMDtcblxuICAgIC8qKiBBcmlhIGxhYmVsIGZvciB0aGUgZGF0ZXRpbWUgcGlja2VyIGlucHV0LiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZGF0ZXRpbWVJbnB1dExhYmVsOiBzdHJpbmcgPSAnRGF0ZXRpbWUgaW5wdXQnO1xuXG4gICAgLyoqIEFyaWEgbGFiZWwgZm9yIHRoZSBidXR0b24gdG8gc2hvdy9oaWRlIHRoZSBjYWxlbmRhci4gKi9cbiAgICBASW5wdXQoKVxuICAgIGRpc3BsYXlEYXRldGltZVRvZ2dsZUxhYmVsOiBzdHJpbmcgPSAnRGlzcGxheSBjYWxlbmRhciB0b2dnbGUnO1xuXG4gICAgLyoqIFdoZXRoZXIgYSBudWxsIGlucHV0IGlzIGNvbnNpZGVyZWQgdmFsaWQuICovXG4gICAgQElucHV0KClcbiAgICBhbGxvd051bGw6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgZGF0ZSBjaGFuZ2VzLiBUaGlzIGNhbiBiZSBhIHRpbWUgb3IgZGF5IGNoYW5nZS4gKi9cbiAgICBAT3V0cHV0KClcbiAgICByZWFkb25seSBkYXRlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8RGF0ZT4gPSBuZXcgRXZlbnRFbWl0dGVyPERhdGU+KCk7XG5cbiAgICAvKiogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBkYXkgY2hhbmdlcyBmcm9tIHRoZSBjYWxlbmRhci4gKi9cbiAgICBAT3V0cHV0KClcbiAgICByZWFkb25seSBjYWxlbmRhckNoYW5nZTogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xuXG4gICAgLyoqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgdGltZSBjaGFuZ2VzIGZyb20gdGhlIHRpbWUgY29tcG9uZW50LiAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHJlYWRvbmx5IHRpbWVDaGFuZ2U6IEV2ZW50RW1pdHRlcjxEYXRlPiA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZT4oKTtcblxuICAgIC8qKiBFdmVudCBlbWl0dGVkIHdoZW4gcG9wb3ZlciBjbG9zZXMuICovXG4gICAgQE91dHB1dCgpXG4gICAgcmVhZG9ubHkgb25DbG9zZTogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlbiBEYXRlIG9mIHRoZSBpbnB1dCBmaWVsZC4gSW50ZXJuYWwgdXNlLlxuICAgICAqIEZvciBwcm9ncmFtbWF0aWMgc2VsZWN0aW9uLCB1c2UgdHdvLXdheSBiaW5kaW5nIG9uIHRoZSBkYXRlIGlucHV0LlxuICAgICAqL1xuICAgIGlucHV0RmllbGREYXRlID0gbnVsbDtcblxuICAgIC8qKiBAaGlkZGVuIFRoZSBUaW1lIG9iamVjdCB3aGljaCBpbnRlcmFjdHMgd2l0aCB0aGUgaW5uZXIgVGltZSBjb21wb25lbnQuIEludGVybmFsIHVzZS4gKi9cbiAgICBpc0ludmFsaWREYXRlSW5wdXQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBAaGlkZGVuIE9ic2VydmFibGUgdXNlZCBpbnRlcm5hbGx5LiAqL1xuICAgIGRhdGVGcm9tSW5wdXQ6IFN1YmplY3Q8c3RyaW5nPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgICAvKiogQGhpZGRlbiBUaGUgVGltZSBvYmplY3Qgd2hpY2ggaW50ZXJhY3RzIHdpdGggdGhlIGlubmVyIFRpbWUgY29tcG9uZW50LiBJbnRlcm5hbCB1c2UuICovXG4gICAgdGltZTogVGltZU9iamVjdCA9IHsgaG91cjogMCwgbWludXRlOiAwLCBzZWNvbmQ6IDAgfTtcblxuICAgIC8qKiBAaGlkZGVuIFRoZSBDYWxlbmRhckRheSBvYmplY3Qgd2hpY2ggaW50ZXJhY3RzIHdpdGggdGhlIGlubmVyIENhbGVuZGFyIGNvbXBvbmVudC4gSW50ZXJuYWwgdXNlLiAqL1xuICAgIHNlbGVjdGVkRGF5OiBDYWxlbmRhckRheSA9IHtcbiAgICAgICAgZGF0ZTogbnVsbFxuICAgIH07XG5cbiAgICAvKiogU3Vic2NyaXB0aW9uIG9mIHRoZSBkYXRlRnJvbUlucHV0LiAqL1xuICAgIHByaXZhdGUgZGF0ZUZyb21JbnB1dFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG4gICAgQElucHV0KClcbiAgICBkaXNhYmxlRnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqIFRoZSBibG9ja0Z1bmN0aW9uIGZvciB0aGUgY2FsZW5kYXIuICovXG4gICAgQElucHV0KClcbiAgICBibG9ja0Z1bmN0aW9uID0gZnVuY3Rpb24oZCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBASW5wdXQoKVxuICAgIGRpc2FibGVSYW5nZVN0YXJ0RnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEBJbnB1dCgpXG4gICAgZGlzYWJsZVJhbmdlRW5kRnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEBJbnB1dCgpXG4gICAgYmxvY2tSYW5nZVN0YXJ0RnVuY3Rpb24gPSBmdW5jdGlvbihkKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEBJbnB1dCgpXG4gICAgYmxvY2tSYW5nZUVuZEZ1bmN0aW9uID0gZnVuY3Rpb24oZCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgb25DaGFuZ2U6IGFueSA9ICgpID0+IHt9O1xuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBvblRvdWNoZWQ6IGFueSA9ICgpID0+IHt9O1xuXG4gICAgLyoqIFRvZ2dsZXMgdGhlIHBvcG92ZXIuICovXG4gICAgdG9nZ2xlUG9wb3ZlcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQodGhpcy5zZWxlY3RlZERheS5kYXRlKTtcbiAgICAgICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlUG9wb3ZlcigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vcGVuUG9wb3ZlcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIE9wZW5zIHRoZSBwb3BvdmVyLiAqL1xuICAgIG9wZW5Qb3BvdmVyKGlucHV0RmllbGREYXRlPzogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5pc09wZW4gJiYgIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkKHRoaXMuc2VsZWN0ZWREYXkuZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG4gICAgICAgICAgICBpZiAoaW5wdXRGaWVsZERhdGUgIT09IG51bGwgJiYgaW5wdXRGaWVsZERhdGUgIT09ICcnICYmICF0aGlzLmlzSW52YWxpZERhdGVJbnB1dCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRWYWx1ZUNoYW5nZSh0aGlzLmRhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIENsb3NlcyB0aGUgcG9wb3ZlciAqL1xuICAgIGNsb3NlUG9wb3ZlcigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLm9uQ2xvc2UuZW1pdCh0aGlzLmRhdGUpO1xuICAgICAgICAgICAgdGhpcy5pc09wZW4gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVwZGF0ZVBpY2tlcklucHV0SGFuZGxlcihkKTogdm9pZCB7XG4gICAgICAgIGlmIChkLnNlbGVjdGVkRGF5ICYmIGQuc2VsZWN0ZWREYXkuZGF0ZSkge1xuICAgICAgICAgICAgZC5zZWxlY3RlZERheS5kYXRlLnNldEhvdXJzKHRoaXMuZGF0ZS5nZXRIb3VycygpKTtcbiAgICAgICAgICAgIGQuc2VsZWN0ZWREYXkuZGF0ZS5zZXRNaW51dGVzKHRoaXMuZGF0ZS5nZXRNaW51dGVzKCkpO1xuICAgICAgICAgICAgZC5zZWxlY3RlZERheS5kYXRlLnNldFNlY29uZHModGhpcy5kYXRlLmdldFNlY29uZHMoKSk7XG4gICAgICAgICAgICBkLnNlbGVjdGVkRGF5LmRhdGUuc2V0TWlsbGlzZWNvbmRzKHRoaXMuZGF0ZS5nZXRNaWxsaXNlY29uZHMoKSk7XG4gICAgICAgICAgICBjb25zdCBwcmV2aW91cyA9IHRoaXMuZGF0ZS5nZXRUaW1lKCk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF5ID0gZC5zZWxlY3RlZERheTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZSA9IGQuc2VsZWN0ZWREYXkuZGF0ZTtcbiAgICAgICAgICAgIHRoaXMuaW5wdXRGaWVsZERhdGUgPSB0aGlzLmRhdGVUaW1lQWRhcHRlci5mb3JtYXQodGhpcy5kYXRlKTtcbiAgICAgICAgICAgIHRoaXMudGltZSA9IHtob3VyOiB0aGlzLmRhdGUuZ2V0SG91cnMoKSwgbWludXRlOiB0aGlzLmRhdGUuZ2V0TWludXRlcygpLCBzZWNvbmQ6IHRoaXMuZGF0ZS5nZXRTZWNvbmRzKCl9O1xuICAgICAgICAgICAgaWYgKHRoaXMuZGF0ZS5nZXRUaW1lKCkgIT09IHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxlbmRhckNoYW5nZS5lbWl0KHRoaXMuZGF0ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlQ2hhbmdlLmVtaXQodGhpcy5kYXRlKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMuZGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZCA9PT0gJycpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWREYXkuZGF0ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF5LnNlbGVjdGVkID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudGltZS5zZWNvbmQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy50aW1lLm1pbnV0ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRpbWUuaG91ciA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRpbWVDb21wb25lbnQuZGlzcGxheWVkSG91ciA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRpbWVDb21wb25lbnQucGVyaW9kID0gJ2FtJztcbiAgICAgICAgICAgIHRoaXMudGltZUNvbXBvbmVudC5vbGRQZXJpb2QgPSAnYW0nO1xuICAgICAgICAgICAgdGhpcy5jYWxlbmRhckNoYW5nZS5lbWl0KG51bGwpO1xuICAgICAgICAgICAgdGhpcy50aW1lQ2hhbmdlLmVtaXQobnVsbCk7XG4gICAgICAgICAgICB0aGlzLmRhdGVDaGFuZ2UuZW1pdChudWxsKTtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UodGhpcy5zZWxlY3RlZERheS5kYXRlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgaXNJbnZhbGlkRGF0ZUlucHV0SGFuZGxlcihlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXNJbnZhbGlkRGF0ZUlucHV0ID0gZTtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIGlucHV0VmFsdWVDaGFuZ2UoZSk6IHZvaWQge1xuICAgICAgICBsZXQgdGVtcDtcbiAgICAgICAgaWYgKHR5cGVvZiBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGVtcCA9IHRoaXMuZGF0ZVRpbWVBZGFwdGVyLnBhcnNlKGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGVtcCA9IG5ldyBEYXRlKGUpO1xuICAgICAgICB9XG4gICAgICAgIC8qXG4gICAgICAgICBOZWVkIHRvIGNoZWNrIGlmIGN1cnJlbnQgbG9jYWxlIHRvRGF0ZVN0cmluZyBjb250YWlucyBBTSBvciBQTS4gSWYgdGhlIGN1cnJlbnQgbG9jYWxlIGhhcyBpdCBhbmQgaXQgaXMgYWJzZW50XG4gICAgICAgICBmcm9tIHRoZSB1c2VyJ3MgaW5wdXQsIHRoZSBtZXJpZGlhbiBzaG91bGQgYmUgY29uc2lkZXJlZCBpbnZhbGlkXG4gICAgICAgICAqL1xuICAgICAgICBjb25zdCBsb2NhbGVNZXJpZGlhbiA9IG5ldyBEYXRlKCkudG9Mb2NhbGVUaW1lU3RyaW5nKCkuc2xpY2UoLTIpO1xuICAgICAgICBsZXQgbWVyaWRpYW5WYWxpZCA9IHRydWU7XG4gICAgICAgIGlmICgobG9jYWxlTWVyaWRpYW4gPT09ICdBTScgfHwgbG9jYWxlTWVyaWRpYW4gPT09ICdQTScpICYmXG4gICAgICAgICAgICAodHlwZW9mIGUgPT09ICdzdHJpbmcnICYmIGUuc2xpY2UoLTIpICE9PSAnQU0nICYmIGUuc2xpY2UoLTIpICE9PSAnUE0nKSkge1xuICAgICAgICAgICAgbWVyaWRpYW5WYWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1lcmlkaWFuVmFsaWQgJiYgdGVtcCAmJiB0ZW1wLnRvTG9jYWxlRGF0ZVN0cmluZygpICE9PSAnSW52YWxpZCBEYXRlJykge1xuICAgICAgICAgICAgY29uc3QgbmV3VmFsdWUgPSB7aG91cjogdGVtcC5nZXRIb3VycygpLCBtaW51dGU6IHRlbXAuZ2V0TWludXRlcygpLCBzZWNvbmQ6IHRlbXAuZ2V0U2Vjb25kcygpfTtcbiAgICAgICAgICAgIGlmIChuZXdWYWx1ZS5ob3VyICE9PSB0aGlzLnRpbWUuaG91ciB8fCBuZXdWYWx1ZS5taW51dGUgIT09IHRoaXMudGltZS5taW51dGUgfHwgbmV3VmFsdWUuc2Vjb25kICE9PSB0aGlzLnRpbWUuc2Vjb25kKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lID0gbmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRUaW1lKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5kYXRlRnJvbUlucHV0Lm5leHQodGVtcC50b0xvY2FsZURhdGVTdHJpbmcoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZSA9PT0gJycgJiYgdGhpcy5hbGxvd051bGwpIHtcbiAgICAgICAgICAgIHRoaXMuaXNJbnZhbGlkRGF0ZUlucHV0ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmRhdGVGcm9tSW5wdXQubmV4dCgnJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmlzSW52YWxpZERhdGVJbnB1dCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleWRvd24uZXNjYXBlJywgW10pXG4gICAgb25Fc2NhcGVLZXlkb3duSGFuZGxlcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jbG9zZVBvcG92ZXIoKTtcbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcbiAgICBwdWJsaWMgb25HbG9iYWxDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMuZWxSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQpKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlUG9wb3ZlcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZGF0ZSAmJiB0aGlzLmlucHV0RmllbGREYXRlICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRGF5LmRhdGUgPSB0aGlzLmRhdGU7XG4gICAgICAgICAgICB0aGlzLnRpbWUgPSB7aG91cjogdGhpcy5kYXRlLmdldEhvdXJzKCksIG1pbnV0ZTogdGhpcy5kYXRlLmdldE1pbnV0ZXMoKSwgc2Vjb25kOiB0aGlzLmRhdGUuZ2V0U2Vjb25kcygpfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5kYXRlRnJvbUlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVGcm9tSW5wdXRTdWJzY3JpcHRpb24gPSB0aGlzLmRhdGVGcm9tSW5wdXQuc3Vic2NyaWJlKGRhdGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUGlja2VySW5wdXRIYW5kbGVyKGRhdGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5kYXRlRnJvbUlucHV0U3Vic2NyaXB0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGVGcm9tSW5wdXRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBlbFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgICAgICAgICBwcml2YXRlIGRhdGVUaW1lQWRhcHRlcjogRGF0ZVRpbWVGb3JtYXRQYXJzZXJcbiAgICApIHt9XG5cbiAgICAvKiogQGhpZGRlbiAqL1xuICAgIHJlZ2lzdGVyT25DaGFuZ2UoZm46IChzZWxlY3RlZDogYW55KSA9PiB7dm9pZH0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgd3JpdGVWYWx1ZShzZWxlY3RlZDogRGF0ZSk6IHZvaWQge1xuICAgICAgICBpZiAoIXNlbGVjdGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWxlY3RlZERheS5kYXRlID0gc2VsZWN0ZWQ7XG4gICAgICAgIHRoaXMudGltZSA9IHtob3VyOiBzZWxlY3RlZC5nZXRIb3VycygpLCBtaW51dGU6IHNlbGVjdGVkLmdldE1pbnV0ZXMoKSwgc2Vjb25kOiBzZWxlY3RlZC5nZXRTZWNvbmRzKCl9XG4gICAgICAgIHRoaXMuZGF0ZSA9IHRoaXMuc2VsZWN0ZWREYXkuZGF0ZTtcbiAgICAgICAgdGhpcy5zZXRUaW1lKCk7XG4gICAgfVxuXG4gICAgLyoqIEBoaWRkZW4gKi9cbiAgICBzZXRUaW1lKGZpcmVFdmVudHMgPSBmYWxzZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmRhdGUuc2V0SG91cnModGhpcy50aW1lLmhvdXIpO1xuI