com.phloxui
Version:
PhloxUI Ng2+ Framework
629 lines (628 loc) • 48.6 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, ElementRef, Input, Output, Type, EventEmitter } from '@angular/core';
import { AbstractSelectOneItem } from './AbstractSelectOneItem';
import { CLICK_EVENT, BEFORE_CLICK_EVENT } from '../../../share/CustomEventType';
import { UUIDUtils } from '../../../share/utils/UUIDUtils';
import { Option } from '../../../decorator/Option.decorator';
import { NeedFocusService } from '../../../service/NeedFocusService.service';
import { EventUtils } from '../../../share/utils/EventUtils';
import { I18N } from '../../../decorator/decorators';
const /** @type {?} */ TYPE_NAME = "phx-component-radio-btns";
export class ComponentRadioButtons extends AbstractSelectOneItem {
/**
* @param {?} elementRef
* @param {?} needFocusService
*/
constructor(elementRef, needFocusService) {
super(elementRef, needFocusService);
this.DEFAULT_GROUP_NAME = "DEFAULT_RADIO";
this.beforeClickEvent = new EventEmitter();
this.clickEvent = new EventEmitter();
this.changeEvent = new EventEmitter();
}
/**
* @return {?}
*/
ngOnInit() {
super.ngOnInit();
if (this.name === null || typeof this.name === 'undefined') {
this.name = this.DEFAULT_GROUP_NAME + "_" + UUIDUtils.generateUUID();
}
}
/**
* @param {?} item
* @return {?}
*/
isChecked(item) {
if (item !== null && typeof item !== 'undefined') {
let /** @type {?} */ sItem = this.getSelectedItem();
return (sItem === item);
}
return false;
}
/**
* @param {?} index
* @param {?=} $event
* @param {?=} fireEvent
* @return {?}
*/
_onRadioBtnClicked(index, $event, fireEvent) {
if (fireEvent === null || fireEvent === undefined) {
fireEvent = true;
}
$event.preventDefault();
if (this.isReadOnly()) {
return;
}
if (this.isDisabled()) {
return;
}
let /** @type {?} */ oldIndex = this.getSelectedIndex();
let /** @type {?} */ newIndex = index;
EventUtils.handleBrowserEvent(this, 'beforeClickEvent', $event, fireEvent, ($event) => {
// doEvent
this.setSelectedIndex(newIndex);
}, ($event) => {
// emitBeforeEvent
this.emitBeforeClickEvent(oldIndex, newIndex, $event);
}, ($event, result) => {
// emitAfterEvent
this.emitClickEvent(oldIndex, newIndex, $event);
}, ($event) => {
// doPrevented
});
}
/**
* @param {?} oldIdx
* @param {?} newIdx
* @param {?=} $event
* @return {?}
*/
emitBeforeClickEvent(oldIdx, newIdx, $event) {
let /** @type {?} */ eventData = {
item: this.getItemAtIndex(newIdx).getValue(),
index: newIdx,
oldItem: this.getItemAtIndex(oldIdx).getValue(),
oldIndex: oldIdx
};
// emit event
let /** @type {?} */ data = eventData;
let /** @type {?} */ ev = EventUtils.newCustomEvent(BEFORE_CLICK_EVENT, this, data, $event);
if (this.beforeClickEvent !== null && this.beforeClickEvent !== undefined) {
this.beforeClickEvent.emit(ev);
}
}
/**
* @param {?} oldIdx
* @param {?} newIdx
* @param {?=} $event
* @return {?}
*/
emitClickEvent(oldIdx, newIdx, $event) {
let /** @type {?} */ eventData;
if (oldIdx !== -1) {
eventData = {
item: this.getItemAtIndex(newIdx).getValue(),
index: newIdx,
oldItem: this.getItemAtIndex(oldIdx).getValue(),
oldIndex: oldIdx
};
}
else {
eventData = {
item: this.getItemAtIndex(newIdx).getValue(),
index: newIdx,
oldItem: null,
oldIndex: oldIdx
};
}
// emit event
let /** @type {?} */ data = eventData;
let /** @type {?} */ ev = EventUtils.newCustomEvent(CLICK_EVENT, this, data, $event);
if (this.clickEvent !== null && this.clickEvent !== undefined) {
this.clickEvent.emit(ev);
}
}
/**
* @param {?} selectedItems
* @param {?=} $event
* @param {?=} fireEvent
* @param {?=} fireChangeEvent
* @return {?}
*/
setSelectedItems(selectedItems, $event, fireEvent, fireChangeEvent) {
if (selectedItems === null || selectedItems === undefined || !Array.isArray(selectedItems)) {
selectedItems = [];
}
if (fireEvent === null || fireEvent === undefined) {
fireEvent = true;
}
let /** @type {?} */ sItems = [];
let /** @type {?} */ newIndices = [];
for (let /** @type {?} */ item of selectedItems) {
let /** @type {?} */ idx = this.getItemIndex(item);
if (idx >= 0) {
newIndices.push(idx);
sItems.push(item);
}
}
// Only allow "item" which actually exists.
selectedItems = sItems;
let /** @type {?} */ oldIndex = this.getSelectedIndexes();
EventUtils.handleBrowserEvent(this, 'beforeSelectEvent', $event, fireEvent, ($event) => {
// doEvent
this._setSelectedItemsSaveData(selectedItems, true, $event, fireChangeEvent);
}, ($event) => {
// emitBeforeEvent
this.emitBeforeSelectEvent(oldIndex, newIndices, $event);
}, ($event, result) => {
// emitAfterEvent
this.emitSelectEvent(oldIndex, newIndices, $event);
}, ($event) => {
// doPrevented
});
}
/**
* @return {?}
*/
getDescription() {
return this.description;
}
/**
* @param {?} description
* @return {?}
*/
setDescription(description) {
this.description = description;
}
/**
* @return {?}
*/
hasDescription() {
if (this.description !== null && typeof this.description === 'string' && this.description !== '') {
return true;
}
return false;
}
/**
* @return {?}
*/
getClickedEvent() {
return this.clickEvent;
}
/**
* @param {?} event
* @return {?}
*/
setClickedEvent(event) {
this.clickEvent = event;
}
/**
* @return {?}
*/
getBeforeClickedEvent() {
return this.beforeClickEvent;
}
/**
* @param {?} event
* @return {?}
*/
setBeforeClickedEvent(event) {
this.beforeClickEvent = event;
}
/**
* @param {?} inputValue
* @param {?} results
* @return {?}
*/
onValidationEnd(inputValue, results) {
//! do sthing
}
/**
* @param {?} data
* @param {?} inputVal
* @return {?}
*/
onDataChange(data, inputVal) {
}
/**
* @param {?} $event
* @return {?}
*/
doFocus($event) {
}
/**
* @param {?} $event
* @return {?}
*/
doLostFocus($event) {
}
/**
* @param {?} data
* @return {?}
*/
selfSaveData(data) {
}
/**
* @return {?}
*/
selfResetData() {
}
/**
* @return {?}
*/
getClickEvent() {
return this.clickEvent;
}
/**
* @param {?} event
* @return {?}
*/
setClickEvent(event) {
this.clickEvent = event;
}
/**
* @return {?}
*/
getName() {
return this.name;
}
/**
* @return {?}
*/
getComponentType() {
return this.componentType;
}
/**
* @return {?}
*/
getComponentModel() {
return this.componentModel;
}
/**
* @return {?}
*/
getComponentHandler() {
return this.componentHandler;
}
/**
* @return {?}
*/
getItems() {
return this.items;
}
/**
* @return {?}
*/
getBeforeClickEvent() {
return this.beforeClickEvent;
}
/**
* @param {?} beforeClickEvent
* @return {?}
*/
setBeforeClickEvent(beforeClickEvent) {
this.beforeClickEvent = beforeClickEvent;
}
}
ComponentRadioButtons.TYPE_NAME = TYPE_NAME;
ComponentRadioButtons.decorators = [
{ type: Component, args: [{
moduleId: module.id,
selector: TYPE_NAME,
template: `<div class="phx-component-radio-btns">
<div class="radio-group">
<div class="radio" *ngFor="let item of getItems(); let i = index;" (click)="_onRadioBtnClicked(i, $event)">
<!-- <input type="radio" name="{{getName()}}" [checked]="isChecked(item)" [disabled]="isDisabled()"> -->
<input type="button" name="{{getName()}}" [class._selected]="getSelectedIndex() === i" [disabled]="isDisabled()">
<label>
<div class="content"><phx-component-wrapper [type]="getComponentType()" [model]="getComponentModel()" [handler]="getComponentHandler()" [data]="item"></phx-component-wrapper></div>
</label>
</div>
</div>
<br />
<br />
<div class="validation" [style.display]="getValidationResultMessage() ? undefined : 'none'" [class.normal]="isNormal() && !isDisabled()" [class.success]="isSuccess() && !isDisabled()" [class.warning]="isWarning() && !isDisabled()" [class.error]="isError() && !isDisabled()">
<ng-template [ngIf]="getValidationResultMessage()" [ngIfElse]="validation_else">
{{getValidationResultMessage() | phx_text}}
</ng-template>
<ng-template #validation_else>
<!-- We've to put whitespace if there is no validation msg to prevent empty dom -->
<!-- since if validate msg's <div> dom is empty, the component positioning -->
<!-- will be misplaced. -->
{{ ' ' }}
</ng-template>
</div>
<div class="description" [style.display]="getValidationResultMessage() ? 'none' : undefined" [class.normal]="isNormal() && !isDisabled()" [class.success]="isSuccess() && !isDisabled()" [class.warning]="isWarning() && !isDisabled()" [class.error]="isError() && !isDisabled()">
<ng-template [ngIf]="getDescription()" [ngIfElse]="description_else">
{{ getDescription() | phx_text }}
</ng-template>
<ng-template #description_else>
<!-- We've to put whitespace if there is no description to prevent empty dom -->
<!-- since if description's <div> dom is empty, the component positioning -->
<!-- will be misplaced. -->
{{ ' ' }}
</ng-template>
</div>
</div>
`
},] },
];
/** @nocollapse */
ComponentRadioButtons.ctorParameters = () => [
{ type: ElementRef, },
{ type: NeedFocusService, },
];
ComponentRadioButtons.propDecorators = {
"dataParent": [{ type: Input },],
"ignoreParentData": [{ type: Input },],
"data": [{ type: Input },],
"ignoreParentDisabled": [{ type: Input },],
"delegateHistory": [{ type: Input },],
"onDisabled": [{ type: Input },],
"onEnabled": [{ type: Input },],
"loadingEnabled": [{ type: Input },],
"i18nKey": [{ type: Input },],
"bypass": [{ type: Input, args: ['i18nBypass',] },],
"options": [{ type: Input },],
"disabled": [{ type: Input },],
"field": [{ type: Input },],
"name": [{ type: Input },],
"typeOfData": [{ type: Input },],
"readOnly": [{ type: Input },],
"help": [{ type: Input },],
"dataComparator": [{ type: Input, args: ['comparator',] },],
"items": [{ type: Input },],
"componentType": [{ type: Input, args: ["type",] },],
"componentModel": [{ type: Input, args: ["model",] },],
"componentHandler": [{ type: Input, args: ["handler",] },],
"description": [{ type: Input },],
"loadEvent": [{ type: Output, args: ['phxLoad',] },],
"startValidateEvent": [{ type: Output, args: ['phxStartValidate',] },],
"endValidateEvent": [{ type: Output, args: ['phxEndValidate',] },],
"beforeFocusEvent": [{ type: Output, args: ['phxBeforeFocus',] },],
"focusEvent": [{ type: Output, args: ['phxFocus',] },],
"beforeLostFocusEvent": [{ type: Output, args: ['phxBeforeLostFocus',] },],
"lostFocusEvent": [{ type: Output, args: ['phxLostFocus',] },],
"beforeChangeEvent": [{ type: Output, args: ['phxBeforeChange',] },],
"changeEvent": [{ type: Output, args: ['phxChange',] },],
"beforeSelectEvent": [{ type: Output, args: ['phxBeforeSelect',] },],
"selectEvent": [{ type: Output, args: ['phxSelect',] },],
"beforeClickEvent": [{ type: Output, args: ['phxBeforeClick',] },],
"clickEvent": [{ type: Output, args: ['phxClick',] },],
};
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Object)
], ComponentRadioButtons.prototype, "dataParent", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "ignoreParentData", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Object)
], ComponentRadioButtons.prototype, "data", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "ignoreParentDisabled", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "delegateHistory", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Function)
], ComponentRadioButtons.prototype, "onDisabled", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Function)
], ComponentRadioButtons.prototype, "onEnabled", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "loadingEnabled", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", String)
], ComponentRadioButtons.prototype, "i18nKey", void 0);
tslib_1.__decorate([
Option('i18nBypass'),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "bypass", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "disabled", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", String)
], ComponentRadioButtons.prototype, "field", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", String)
], ComponentRadioButtons.prototype, "name", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", String)
], ComponentRadioButtons.prototype, "typeOfData", void 0);
tslib_1.__decorate([
Option(),
tslib_1.__metadata("design:type", Boolean)
], ComponentRadioButtons.prototype, "readOnly", void 0);
tslib_1.__decorate([
I18N(),
Option(),
tslib_1.__metadata("design:type", Object)
], ComponentRadioButtons.prototype, "help", void 0);
tslib_1.__decorate([
Option('comparator'),
tslib_1.__metadata("design:type", Object)
], ComponentRadioButtons.prototype, "dataComparator", void 0);
tslib_1.__decorate([
I18N(),
Option(),
tslib_1.__metadata("design:type", Array)
], ComponentRadioButtons.prototype, "items", void 0);
tslib_1.__decorate([
Option("type"),
tslib_1.__metadata("design:type", Type)
], ComponentRadioButtons.prototype, "componentType", void 0);
tslib_1.__decorate([
Option("model"),
tslib_1.__metadata("design:type", Object)
], ComponentRadioButtons.prototype, "componentModel", void 0);
tslib_1.__decorate([
Option("handler"),
tslib_1.__metadata("design:type", Function)
], ComponentRadioButtons.prototype, "componentHandler", void 0);
tslib_1.__decorate([
I18N(),
Option(),
tslib_1.__metadata("design:type", String)
], ComponentRadioButtons.prototype, "description", void 0);
tslib_1.__decorate([
Option('load'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "loadEvent", void 0);
tslib_1.__decorate([
Option('startValidate'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "startValidateEvent", void 0);
tslib_1.__decorate([
Option('endValidate'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "endValidateEvent", void 0);
tslib_1.__decorate([
Option('beforeFocus'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "beforeFocusEvent", void 0);
tslib_1.__decorate([
Option('focus'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "focusEvent", void 0);
tslib_1.__decorate([
Option('beforeLostFocus'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "beforeLostFocusEvent", void 0);
tslib_1.__decorate([
Option('lostFocus'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "lostFocusEvent", void 0);
tslib_1.__decorate([
Option('beforeChange'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "beforeChangeEvent", void 0);
tslib_1.__decorate([
Option('change'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "changeEvent", void 0);
tslib_1.__decorate([
Option('beforeSelect'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "beforeSelectEvent", void 0);
tslib_1.__decorate([
Option('select'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "selectEvent", void 0);
tslib_1.__decorate([
Option('beforeClick'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "beforeClickEvent", void 0);
tslib_1.__decorate([
Option('click'),
tslib_1.__metadata("design:type", EventEmitter)
], ComponentRadioButtons.prototype, "clickEvent", void 0);
function ComponentRadioButtons_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
ComponentRadioButtons.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
ComponentRadioButtons.ctorParameters;
/** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
ComponentRadioButtons.propDecorators;
/** @type {?} */
ComponentRadioButtons.TYPE_NAME;
/** @type {?} */
ComponentRadioButtons.prototype.DEFAULT_GROUP_NAME;
/** @type {?} */
ComponentRadioButtons.prototype.dataParent;
/** @type {?} */
ComponentRadioButtons.prototype.ignoreParentData;
/** @type {?} */
ComponentRadioButtons.prototype.data;
/** @type {?} */
ComponentRadioButtons.prototype.ignoreParentDisabled;
/** @type {?} */
ComponentRadioButtons.prototype.delegateHistory;
/** @type {?} */
ComponentRadioButtons.prototype.onDisabled;
/** @type {?} */
ComponentRadioButtons.prototype.onEnabled;
/** @type {?} */
ComponentRadioButtons.prototype.loadingEnabled;
/** @type {?} */
ComponentRadioButtons.prototype.i18nKey;
/** @type {?} */
ComponentRadioButtons.prototype.bypass;
/** @type {?} */
ComponentRadioButtons.prototype.options;
/** @type {?} */
ComponentRadioButtons.prototype.disabled;
/** @type {?} */
ComponentRadioButtons.prototype.field;
/** @type {?} */
ComponentRadioButtons.prototype.name;
/** @type {?} */
ComponentRadioButtons.prototype.typeOfData;
/** @type {?} */
ComponentRadioButtons.prototype.readOnly;
/** @type {?} */
ComponentRadioButtons.prototype.help;
/** @type {?} */
ComponentRadioButtons.prototype.dataComparator;
/** @type {?} */
ComponentRadioButtons.prototype.items;
/** @type {?} */
ComponentRadioButtons.prototype.componentType;
/** @type {?} */
ComponentRadioButtons.prototype.componentModel;
/** @type {?} */
ComponentRadioButtons.prototype.componentHandler;
/** @type {?} */
ComponentRadioButtons.prototype.description;
/** @type {?} */
ComponentRadioButtons.prototype.loadEvent;
/** @type {?} */
ComponentRadioButtons.prototype.startValidateEvent;
/** @type {?} */
ComponentRadioButtons.prototype.endValidateEvent;
/** @type {?} */
ComponentRadioButtons.prototype.beforeFocusEvent;
/** @type {?} */
ComponentRadioButtons.prototype.focusEvent;
/** @type {?} */
ComponentRadioButtons.prototype.beforeLostFocusEvent;
/** @type {?} */
ComponentRadioButtons.prototype.lostFocusEvent;
/** @type {?} */
ComponentRadioButtons.prototype.beforeChangeEvent;
/** @type {?} */
ComponentRadioButtons.prototype.changeEvent;
/** @type {?} */
ComponentRadioButtons.prototype.beforeSelectEvent;
/** @type {?} */
ComponentRadioButtons.prototype.selectEvent;
/** @type {?} */
ComponentRadioButtons.prototype.beforeClickEvent;
/** @type {?} */
ComponentRadioButtons.prototype.clickEvent;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcG9uZW50UmFkaW9CdXR0b25zLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2NvbS5waGxveHVpLyIsInNvdXJjZXMiOlsibGliL2NvbXBvbmVudC9kYXRhdmlldy9pbnB1dC9Db21wb25lbnRSYWRpb0J1dHRvbnMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pHLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxXQUFXLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUlqRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFM0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDJDQUEyQyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU3RCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFLckQsdUJBQU0sU0FBUyxHQUFXLDBCQUEwQixDQUFDO0FBMENyRCxNQUFNLDRCQUE2QixTQUFRLHFCQUFxQjs7Ozs7SUF1STlELFlBQVksVUFBc0IsRUFBRSxnQkFBa0M7UUFDcEUsS0FBSyxDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO2tDQXBJRCxlQUFlO1FBcUlsRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUMzQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0tB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TUFBTSxDQUFDLGFBQWEsQ0FBQztzQ0FDTSxZQUFZOzs7SUFFdkMsTUFBTSxDQUFDLGFBQWEsQ0FBQztzQ0FDTSxZQUFZOzs7SUFFdkMsTUFBTSxDQUFDLE9BQU8sQ0FBQztzQ0FDTSxZQUFZOzs7SUFFakMsTUFBTSxDQUFDLGlCQUFpQixDQUFDO3NDQUNNLFlBQVk7OztJQUUzQyxNQUFNLENBQUMsV0FBVyxDQUFDO3NDQUNNLFlBQVk7OztJQUVyQyxNQUFNLENBQUMsY0FBYyxDQUFDO3NDQUNNLFlBQVk7OztJQUV4QyxNQUFNLENBQUMsUUFBUSxDQUFDO3NDQUNNLFlBQVk7OztJQUlsQyxNQUFNLENBQUMsY0FBYyxDQUFDO3NDQUNNLFlBQVk7OztJQUV4QyxNQUFNLENBQUMsUUFBUSxDQUFDO3NDQUNNLFlBQVk7OztJQUlsQyxNQUFNLENBQUMsYUFBYSxDQUFDO3NDQUNNLFlBQVk7OztJQUV2QyxNQUFNLENBQUMsT0FBTyxDQUFDO3NDQUNNLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgRWxlbWVudFJlZiwgSW5wdXQsIE91dHB1dCwgVHlwZSwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBYnN0cmFjdFNlbGVjdE9uZUl0ZW0gfSBmcm9tICcuL0Fic3RyYWN0U2VsZWN0T25lSXRlbSc7XG5pbXBvcnQgeyBDTElDS19FVkVOVCwgQkVGT1JFX0NMSUNLX0VWRU5UIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmUvQ3VzdG9tRXZlbnRUeXBlJztcbmltcG9ydCB7IElEYXRhQ29tcGFyYXRvciB9IGZyb20gJy4uLy4uL0lEYXRhQ29tcGFyYXRvcic7XG5pbXBvcnQgeyBJSGFzRGF0YSB9IGZyb20gJy4uLy4uL0lIYXNEYXRhJztcbmltcG9ydCB7IElTZWxlY3RJdGVtTW9kZWwgfSBmcm9tICcuLi8uLi9tb2RlbC9JU2VsZWN0SXRlbU1vZGVsJztcbmltcG9ydCB7IFVVSURVdGlscyB9IGZyb20gJy4uLy4uLy4uL3NoYXJlL3V0aWxzL1VVSURVdGlscyc7XG5pbXBvcnQgeyBWYWxpZGF0aW9uUmVzdWx0IH0gZnJvbSAnLi4vLi4vbW9kZWwvVmFsaWRhdGlvblJlc3VsdCc7XG5pbXBvcnQgeyBPcHRpb24gfSBmcm9tICcuLi8uLi8uLi9kZWNvcmF0b3IvT3B0aW9uLmRlY29yYXRvcic7XG5pbXBvcnQgeyBOZWVkRm9jdXNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZS9OZWVkRm9jdXNTZXJ2aWNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRXZlbnRVdGlscyB9IGZyb20gJy4uLy4uLy4uL3NoYXJlL3V0aWxzL0V2ZW50VXRpbHMnO1xuLy8gaW1wb3J0IHsgRGVmYXVsdFNlbGVjdEl0ZW1Nb2RlbCB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL2Rpc3QvbGliL2xpYi9tb2RlbC9EZWZhdWx0U2VsZWN0SXRlbU1vZGVsJztcbmltcG9ydCB7IEkxOE4gfSBmcm9tICcuLi8uLi8uLi9kZWNvcmF0b3IvZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBEZWZhdWx0U2VsZWN0SXRlbU1vZGVsIH0gZnJvbSAnLi4vLi4vbW9kZWwvbW9kZWxzJztcblxuZGVjbGFyZSB2YXIgJDogYW55O1xuXG5jb25zdCBUWVBFX05BTUU6IHN0cmluZyA9IFwicGh4LWNvbXBvbmVudC1yYWRpby1idG5zXCI7XG5cbkBDb21wb25lbnQoe1xuICBtb2R1bGVJZDogbW9kdWxlLmlkLFxuICBzZWxlY3RvcjogVFlQRV9OQU1FLFxuICB0ZW1wbGF0ZTogYDxkaXYgY2xhc3M9XCJwaHgtY29tcG9uZW50LXJhZGlvLWJ0bnNcIj5cblx0PGRpdiBjbGFzcz1cInJhZGlvLWdyb3VwXCI+XG5cdFx0PGRpdiBjbGFzcz1cInJhZGlvXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZ2V0SXRlbXMoKTsgbGV0IGkgPSBpbmRleDtcIiAoY2xpY2spPVwiX29uUmFkaW9CdG5DbGlja2VkKGksICRldmVudClcIj5cblx0XHQgIDwhLS0gPGlucHV0IHR5cGU9XCJyYWRpb1wiIG5hbWU9XCJ7e2dldE5hbWUoKX19XCIgW2NoZWNrZWRdPVwiaXNDaGVja2VkKGl0ZW0pXCIgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWQoKVwiPiAtLT5cblx0XHQgIDxpbnB1dCB0eXBlPVwiYnV0dG9uXCIgbmFtZT1cInt7Z2V0TmFtZSgpfX1cIiBbY2xhc3MuX3NlbGVjdGVkXT1cImdldFNlbGVjdGVkSW5kZXgoKSA9PT0gaVwiIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkKClcIj5cblx0XHRcdDxsYWJlbD5cblx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY29udGVudFwiPjxwaHgtY29tcG9uZW50LXdyYXBwZXIgW3R5cGVdPVwiZ2V0Q29tcG9uZW50VHlwZSgpXCIgW21vZGVsXT1cImdldENvbXBvbmVudE1vZGVsKClcIiBbaGFuZGxlcl09XCJnZXRDb21wb25lbnRIYW5kbGVyKClcIiBbZGF0YV09XCJpdGVtXCI+PC9waHgtY29tcG9uZW50LXdyYXBwZXI+PC9kaXY+XG5cdFx0XHQ8L2xhYmVsPlxuXHRcdDwvZGl2PlxuXHQ8L2Rpdj5cblx0PGJyIC8+XG5cdDxiciAvPlxuXHQ8ZGl2IGNsYXNzPVwidmFsaWRhdGlvblwiIFtzdHlsZS5kaXNwbGF5XT1cImdldFZhbGlkYXRpb25SZXN1bHRNZXNzYWdlKCkgPyB1bmRlZmluZWQgOiAnbm9uZSdcIiBbY2xhc3Mubm9ybWFsXT1cImlzTm9ybWFsKCkgJiYgIWlzRGlzYWJsZWQoKVwiIFtjbGFzcy5zdWNjZXNzXT1cImlzU3VjY2VzcygpICYmICFpc0Rpc2FibGVkKClcIiBbY2xhc3Mud2FybmluZ109XCJpc1dhcm5pbmcoKSAmJiAhaXNEaXNhYmxlZCgpXCIgW2NsYXNzLmVycm9yXT1cImlzRXJyb3IoKSAmJiAhaXNEaXNhYmxlZCgpXCI+XG5cdFx0PG5nLXRlbXBsYXRlIFtuZ0lmXT1cImdldFZhbGlkYXRpb25SZXN1bHRNZXNzYWdlKClcIiBbbmdJZkVsc2VdPVwidmFsaWRhdGlvbl9lbHNlXCI+XG5cdFx0XHR7e2dldFZhbGlkYXRpb25SZXN1bHRNZXNzYWdlKCkgfCBwaHhfdGV4dH19XG5cdFx0PC9uZy10ZW1wbGF0ZT5cblx0XHQ8bmctdGVtcGxhdGUgI3ZhbGlkYXRpb25fZWxzZT5cblx0XHRcdDwhLS0gV2UndmUgdG8gcHV0IHdoaXRlc3BhY2UgaWYgdGhlcmUgaXMgbm8gdmFsaWRhdGlvbiBtc2cgdG8gcHJldmVudCBlbXB0eSBkb20gLS0+XG5cdFx0XHQ8IS0tIHNpbmNlIGlmIHZhbGlkYXRlIG1zZydzIDxkaXY+IGRvbSBpcyBlbXB0eSwgdGhlIGNvbXBvbmVudCBwb3NpdGlvbmluZyAtLT5cblx0XHRcdDwhLS0gd2lsbCBiZSBtaXNwbGFjZWQuIC0tPlxuXHRcdFx0e3sgJyZuYnNwOycgfX1cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHQ8L2Rpdj5cblx0PGRpdiBjbGFzcz1cImRlc2NyaXB0aW9uXCIgW3N0eWxlLmRpc3BsYXldPVwiZ2V0VmFsaWRhdGlvblJlc3VsdE1lc3NhZ2UoKSA/ICdub25lJyA6IHVuZGVmaW5lZFwiIFtjbGFzcy5ub3JtYWxdPVwiaXNOb3JtYWwoKSAmJiAhaXNEaXNhYmxlZCgpXCIgW2NsYXNzLnN1Y2Nlc3NdPVwiaXNTdWNjZXNzKCkgJiYgIWlzRGlzYWJsZWQoKVwiIFtjbGFzcy53YXJuaW5nXT1cImlzV2FybmluZygpICYmICFpc0Rpc2FibGVkKClcIiBbY2xhc3MuZXJyb3JdPVwiaXNFcnJvcigpICYmICFpc0Rpc2FibGVkKClcIj5cblx0XHQ8bmctdGVtcGxhdGUgW25nSWZdPVwiZ2V0RGVzY3JpcHRpb24oKVwiIFtuZ0lmRWxzZV09XCJkZXNjcmlwdGlvbl9lbHNlXCI+XG5cdFx0XHR7eyBnZXREZXNjcmlwdGlvbigpIHwgcGh4X3RleHQgfX1cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRcdDxuZy10ZW1wbGF0ZSAjZGVzY3JpcHRpb25fZWxzZT5cblx0XHRcdDwhLS0gV2UndmUgdG8gcHV0IHdoaXRlc3BhY2UgaWYgdGhlcmUgaXMgbm8gZGVzY3JpcHRpb24gdG8gcHJldmVudCBlbXB0eSBkb20gLS0+XG5cdFx0XHQ8IS0tIHNpbmNlIGlmIGRlc2NyaXB0aW9uJ3MgPGRpdj4gZG9tIGlzIGVtcHR5LCB0aGUgY29tcG9uZW50IHBvc2l0aW9uaW5nIC0tPlxuXHRcdFx0PCEtLSB3aWxsIGJlIG1pc3BsYWNlZC4gLS0+XG5cdFx0XHR7eyAnJm5ic3A7JyB9fVxuXHRcdDwvbmctdGVtcGxhdGU+XG5cdDwvZGl2PlxuPC9kaXY+XG5gXG59KVxuZXhwb3J0IGNsYXNzIENvbXBvbmVudFJhZGlvQnV0dG9ucyBleHRlbmRzIEFic3RyYWN0U2VsZWN0T25lSXRlbSBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBUWVBFX05BTUU6IHN0cmluZyA9IFRZUEVfTkFNRTtcblxuICBwcml2YXRlIERFRkFVTFRfR1JPVVBfTkFNRTogc3RyaW5nID0gXCJERUZBVUxUX1JBRElPXCI7XG5cbiAgLy8gUmUtZGVjbGFyZSBmaWVsZCB0byBkZWNsYXJlIG5nIEBJbnB1dC5cbiAgLy8gLS0tIGZyb20gQWJzdHJhY3RIYXNEYXRhXG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgZGF0YVBhcmVudDogSUhhc0RhdGE7XG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgaWdub3JlUGFyZW50RGF0YTogYm9vbGVhbjtcbiAgQElucHV0KClcbiAgQE9wdGlvbigpXG4gIHByb3RlY3RlZCBkYXRhOiBhbnk7XG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgaWdub3JlUGFyZW50RGlzYWJsZWQ6IGJvb2xlYW47XG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgZGVsZWdhdGVIaXN0b3J5OiBib29sZWFuO1xuICBASW5wdXQoKVxuICBAT3B0aW9uKClcbiAgcHJvdGVjdGVkIG9uRGlzYWJsZWQ6IEZ1bmN0aW9uO1xuICBASW5wdXQoKVxuICBAT3B0aW9uKClcbiAgcHJvdGVjdGVkIG9uRW5hYmxlZDogRnVuY3Rpb247XG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgbG9hZGluZ0VuYWJsZWQ6IGJvb2xlYW47XG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgaTE4bktleTogc3RyaW5nO1xuICBASW5wdXQoJ2kxOG5CeXBhc3MnKVxuICBAT3B0aW9uKCdpMThuQnlwYXNzJylcbiAgcHJvdGVjdGVkIGJ5cGFzczogYm9vbGVhbjtcbiAgQElucHV0KClcbiAgcHJvdGVjdGVkIG9wdGlvbnM6IGFueTtcbiAgQElucHV0KClcbiAgQE9wdGlvbigpXG4gIHByb3RlY3RlZCBkaXNhYmxlZDogYm9vbGVhbjtcbiAgLy8gLS0tIGZyb20gQWJzdHJhY3REYXRhVmlld1xuICBASW5wdXQoKVxuICBAT3B0aW9uKClcbiAgcHJvdGVjdGVkIGZpZWxkOiBzdHJpbmc7XG4gIC8vIC0tLSBmcm9tIEFic3RyYWN0SW5wdXREYXRhVmlld1xuICBASW5wdXQoKVxuICBAT3B0aW9uKClcbiAgcHJvdGVjdGVkIG5hbWU6IHN0cmluZztcbiAgQElucHV0KClcbiAgQE9wdGlvbigpXG4gIHByb3RlY3RlZCB0eXBlT2ZEYXRhOiBzdHJpbmc7XG4gIEBJbnB1dCgpXG4gIEBPcHRpb24oKVxuICBwcm90ZWN0ZWQgcmVhZE9ubHk6IGJvb2xlYW47XG4gIEBJbnB1dCgpXG4gIEBJMThOKClcbiAgQE9wdGlvbigpXG4gIHByb3RlY3RlZCBoZWxwOiBhbnk7XG4gIC8vIC0tLSBmcm9tIEFic3RyYWN0U2VsZWN0SXRlbXNcbiAgQElucHV0KCdjb21wYXJhdG9yJylcbiAgQE9wdGlvbignY29tcGFyYXRvcicpXG4gIHByb3RlY3RlZCBkYXRhQ29tcGFyYXRvcjogSURhdGFDb21wYXJhdG9yPGFueT47XG4gIEBJMThOKClcbiAgQElucHV0KClcbiAgQE9wdGlvbigpXG4gIHByb3RlY3RlZCBpdGVtczogRGVmYXVsdFNlbGVjdEl0ZW1Nb2RlbFtdO1xuICAvLyAtLS0gZnJvbSBzZWxmXG4gIEBJbnB1dChcInR5cGVcIilcbiAgQE9wdGlvbihcInR5cGVcIilcbiAgcHJvdGVjdGVkIGNvbXBvbmVudFR5cGU6IFR5cGU8YW55PjtcbiAgQElucHV0KFwibW9kZWxcIilcbiAgQE9wdGlvbihcIm1vZGVsXCIpXG4gIHByb3RlY3RlZCBjb21wb25lbnRNb2RlbDogYW55O1xuICBASW5wdXQoXCJoYW5kbGVyXCIpXG4gIEBPcHRpb24oXCJoYW5kbGVyXCIpXG4gIHByb3RlY3RlZCBjb21wb25lbnRIYW5kbGVyOiBGdW5jdGlvbjtcblxuICAvLyAtLS0gU2VsZlxuICBASTE4TigpXG4gIEBPcHRpb24oKVxuICBASW5wdXQoKVxuICBwcml2YXRlIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG5cbiAgLy8gUmUtZGVjbGFyZSBmaWVsZCB0byBkZWNsYXJlIG5nIEBPdXRwdXQuXG4gIC8vIC0tLSBmcm9tIEFic3RyYWN0SGFzRGF0YVxuICBAT3V0cHV0KCdwaHhMb2FkJylcbiAgQE9wdGlvbignbG9hZCcpXG4gIHByb3RlY3RlZCBsb2FkRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICAvLyAtLS0gZnJvbSBBYnN0cmFjdERhdGFWaWV3XG4gIC8vIC0tLSBmcm9tIEFic3RyYWN0SW5wdXREYXRhVmlld1xuICBAT3V0cHV0KCdwaHhTdGFydFZhbGlkYXRlJylcbiAgQE9wdGlvbignc3RhcnRWYWxpZGF0ZScpXG4gIHByb3RlY3RlZCBzdGFydFZhbGlkYXRlRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhFbmRWYWxpZGF0ZScpXG4gIEBPcHRpb24oJ2VuZFZhbGlkYXRlJylcbiAgcHJvdGVjdGVkIGVuZFZhbGlkYXRlRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhCZWZvcmVGb2N1cycpXG4gIEBPcHRpb24oJ2JlZm9yZUZvY3VzJylcbiAgcHJvdGVjdGVkIGJlZm9yZUZvY3VzRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhGb2N1cycpXG4gIEBPcHRpb24oJ2ZvY3VzJylcbiAgcHJvdGVjdGVkIGZvY3VzRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhCZWZvcmVMb3N0Rm9jdXMnKVxuICBAT3B0aW9uKCdiZWZvcmVMb3N0Rm9jdXMnKVxuICBwcm90ZWN0ZWQgYmVmb3JlTG9zdEZvY3VzRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhMb3N0Rm9jdXMnKVxuICBAT3B0aW9uKCdsb3N0Rm9jdXMnKVxuICBwcm90ZWN0ZWQgbG9zdEZvY3VzRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhCZWZvcmVDaGFuZ2UnKVxuICBAT3B0aW9uKCdiZWZvcmVDaGFuZ2UnKVxuICBwcm90ZWN0ZWQgYmVmb3JlQ2hhbmdlRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhDaGFuZ2UnKVxuICBAT3B0aW9uKCdjaGFuZ2UnKVxuICBwcm90ZWN0ZWQgY2hhbmdlRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICAvLyAtLS0gZnJvbSBBYnN0cmFjdFNlbGVjdEl0ZW1zXG4gIC8vIC0tLSBmcm9tIEFic3RyYWN0U2VsZWN0T25lSXRlbVxuICBAT3V0cHV0KCdwaHhCZWZvcmVTZWxlY3QnKVxuICBAT3B0aW9uKCdiZWZvcmVTZWxlY3QnKVxuICBwcm90ZWN0ZWQgYmVmb3JlU2VsZWN0RXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuICBAT3V0cHV0KCdwaHhTZWxlY3QnKVxuICBAT3B0aW9uKCdzZWxlY3QnKVxuICBwcm90ZWN0ZWQgc2VsZWN0RXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+O1xuXG4gIC8vIC0tLSBmcm9tIFNlbGZcbiAgQE91dHB1dCgncGh4QmVmb3JlQ2xpY2snKVxuICBAT3B0aW9uKCdiZWZvcmVDbGljaycpXG4gIHByb3RlY3RlZCBiZWZvcmVDbGlja0V2ZW50OiBFdmVudEVtaXR0ZXI8YW55PjtcbiAgQE91dHB1dCgncGh4Q2xpY2snKVxuICBAT3B0aW9uKCdjbGljaycpXG4gIHByb3RlY3RlZCBjbGlja0V2ZW50OiBFdmVudEVtaXR0ZXI8YW55PjtcblxuXG4gIGNvbnN0cnVjdG9yKGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsIG5lZWRGb2N1c1NlcnZpY2U6IE5lZWRGb2N1c1NlcnZpY2UpIHtcbiAgICBzdXBlcihlbGVtZW50UmVmLCBuZWVkRm9jdXNTZXJ2aWNlKTtcbiAgICB0aGlzLmJlZm9yZUNsaWNrRXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5jbGlja0V2ZW50ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgIHRoaXMuY2hhbmdlRXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcblxuICAgIGlmICh0aGlzLm5hbWUgPT09IG51bGwgfHwgdHlwZW9mIHRoaXMubmFtZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuREVGQVVMVF9HUk9VUF9OQU1FICsgXCJfXCIgKyBVVUlEVXRpbHMuZ2VuZXJhdGVVVUlEKCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGlzQ2hlY2tlZChpdGVtOiBJU2VsZWN0SXRlbU1vZGVsKTogYm9vbGVhbiB7XG4gICAgaWYgKGl0ZW0gIT09IG51bGwgJiYgdHlwZW9mIGl0ZW0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsZXQgc0l0ZW0gPSB0aGlzLmdldFNlbGVjdGVkSXRlbSgpO1xuXG4gICAgICByZXR1cm4gKHNJdGVtID09PSBpdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcHVibGljIF9vblJhZGlvQnRuQ2xpY2tlZChpbmRleDogbnVtYmVyLCAkZXZlbnQ/OiBFdmVudCwgZmlyZUV2ZW50PzogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChmaXJlRXZlbnQgPT09IG51bGwgfHwgZmlyZUV2ZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGZpcmVFdmVudCA9IHRydWU7XG4gICAgfVxuXG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBpZiAodGhpcy5pc1JlYWRPbmx5KCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgb2xkSW5kZXggPSB0aGlzLmdldFNlbGVjdGVkSW5kZXgoKTtcbiAgICBsZXQgbmV3SW5kZXggPSBpbmRleDtcblxuICAgIEV2ZW50VXRpbHMuaGFuZGxlQnJvd3NlckV2ZW50KHRoaXMsICdiZWZvcmVDbGlja0V2ZW50JywgJGV2ZW50LCBmaXJlRXZlbnQsICgkZXZlbnQ6IEV2ZW50KSA9PiB7XG4gICAgICAvLyBkb0V2ZW50XG4gICAgICB0aGlzLnNldFNlbGVjdGVkSW5kZXgobmV3SW5kZXgpO1xuICAgIH0sICgkZXZlbnQ6IEV2ZW50KSA9PiB7XG4gICAgICAvLyBlbWl0QmVmb3JlRXZlbnRcbiAgICAgIHRoaXMuZW1pdEJlZm9yZUNsaWNrRXZlbnQob2xkSW5kZXgsIG5ld0luZGV4LCAkZXZlbnQpO1xuICAgIH0sICgkZXZlbnQ6IEV2ZW50LCByZXN1bHQ6IGFueSkgPT4ge1xuICAgICAgLy8gZW1pdEFmdGVyRXZlbnRcbiAgICAgIHRoaXMuZW1pdENsaWNrRXZlbnQob2xkSW5kZXgsIG5ld0luZGV4LCAkZXZlbnQpO1xuICAgIH0sICgkZXZlbnQ6IEV2ZW50KSA9PiB7XG4gICAgICAvLyBkb1ByZXZlbnRlZFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGVtaXRCZWZvcmVDbGlja0V2ZW50KG9sZElkeDogbnVtYmVyLCBuZXdJZHg6IG51bWJlciwgJGV2ZW50PzogYW55KTogdm9pZCB7XG4gICAgbGV0IGV2ZW50RGF0YTogYW55ID0ge1xuICAgICAgaXRlbTogdGhpcy5nZXRJdGVtQXRJbmRleChuZXdJZHgpLmdldFZhbHVlKCksXG4gICAgICBpbmRleDogbmV3SWR4LFxuICAgICAgb2xkSXRlbTogdGhpcy5nZXRJdGVtQXRJbmRleChvbGRJZHgpLmdldFZhbHVlKCksXG4gICAgICBvbGRJbmRleDogb2xkSWR4XG4gICAgfTtcblxuICAgIC8vIGVtaXQgZXZlbnRcbiAgICBsZXQgZGF0YTogYW55ID0gZXZlbnREYXRhO1xuICAgIGxldCBldiA9IEV2ZW50VXRpbHMubmV3Q3VzdG9tRXZlbnQoQkVGT1JFX0NMSUNLX0VWRU5ULCB0aGlzLCBkYXRhLCAkZXZlbnQpO1xuXG4gICAgaWYgKHRoaXMuYmVmb3JlQ2xpY2tFdmVudCAhPT0gbnVsbCAmJiB0aGlzLmJlZm9yZUNsaWNrRXZlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5iZWZvcmVDbGlja0V2ZW50LmVtaXQoZXYpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBlbWl0Q2xpY2tFdmVudChvbGRJZHg6IG51bWJlciwgbmV3SWR4OiBudW1iZXIsICRldmVudD86IGFueSk6IHZvaWQge1xuICAgIGxldCBldmVudERhdGE6IGFueTtcblxuICAgIGlmKG9sZElkeCAhPT0gLTEpIHtcbiAgICAgIGV2ZW50RGF0YSA9IHtcbiAgICAgICAgaXRlbTogdGhpcy5nZXRJdGVtQXRJbmRleChuZXdJZHgpLmdldFZhbHVlKCksXG4gICAgICAgIGluZGV4OiBuZXdJZHgsXG4gICAgICAgIG9sZEl0ZW06IHRoaXMuZ2V0SXRlbUF0SW5kZXgob2xkSWR4KS5nZXRWYWx1ZSgpLFxuICAgICAgICBvbGRJbmRleDogb2xkSWR4XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBldmVudERhdGEgPSB7XG4gICAgICAgIGl0ZW06IHRoaXMuZ2V0SXRlbUF0SW5kZXgobmV3SWR4KS5nZXRWYWx1ZSgpLFxuICAgICAgICBpbmRleDogbmV3SWR4LFxuICAgICAgICBvbGRJdGVtOiBudWxsLFxuICAgICAgICBvbGRJbmRleDogb2xkSWR4XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIGVtaXQgZXZlbnRcbiAgICBsZXQgZGF0YTogYW55ID0gZXZlbnREYXRhO1xuICAgIGxldCBldiA9IEV2ZW50VXRpbHMubmV3Q3VzdG9tRXZlbnQoQ0xJQ0tfRVZFTlQsIHRoaXMsIGRhdGEsICRldmVudCk7XG5cbiAgICBpZiAodGhpcy5jbGlja0V2ZW50ICE9PSBudWxsICYmIHRoaXMuY2xpY2tFdmVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmNsaWNrRXZlbnQuZW1pdChldik7XG4gICAgfVxuICB9XG5cbiAgLy8gdXNlIGZvciBwcmV2ZW50RXZlbnQgb2YgRm9ybUNvbnRyb2xcbiAgcHJvdGVjdGVkIHNldFNlbGVjdGVkSXRlbXMoc2VsZWN0ZWRJdGVtczogSVNlbGVjdEl0ZW1Nb2RlbFtdLCAkZXZlbnQ/OiBFdmVudCwgZmlyZUV2ZW50PzogYm9vbGVhbiwgZmlyZUNoYW5nZUV2ZW50PzogYm9vbGVhbikge1xuICAgIGlmIChzZWxlY3RlZEl0ZW1zID09PSBudWxsIHx8IHNlbGVjdGVkSXRlbXMgPT09IHVuZGVmaW5lZCB8fCAhQXJyYXkuaXNBcnJheShzZWxlY3RlZEl0ZW1zKSkge1xuICAgICAgc2VsZWN0ZWRJdGVtcyA9IFtdO1xuICAgIH1cblxuICAgIGlmIChmaXJlRXZlbnQgPT09IG51bGwgfHwgZmlyZUV2ZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGZpcmVFdmVudCA9IHRydWU7XG4gICAgfVxuXG4gICAgbGV0IHNJdGVtczogSVNlbGVjdEl0ZW1Nb2RlbFtdID0gW107XG4gICAgbGV0IG5ld0luZGljZXM6IG51bWJlcltdID0gW107XG5cbiAgICBmb3IgKGxldCBpdGVtIG9mIHNlbGVjdGVkSXRlbXMpIHtcbiAgICAgIGxldCBpZHg6IG51bWJlciA9IHRoaXMuZ2V0SXRlbUluZGV4KGl0ZW0pO1xuXG4gICAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgICAgbmV3SW5kaWNlcy5wdXNoKGlkeCk7XG4gICAgICAgIHNJdGVtcy5wdXNoKGl0ZW0pO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBPbmx5IGFsbG93IFwiaXRlbVwiIHdoaWNoIGFjdHVhbGx5IGV4aXN0cy5cbiAgICBzZWxlY3RlZEl0ZW1zID0gc0l0ZW1zO1xuXG4gICAgbGV0IG9sZEluZGV4ID0gdGhpcy5nZXRTZWxlY3RlZEluZGV4ZXMoKTtcblxuICAgIEV2ZW50VXRpbHMuaGFuZGxlQnJvd3NlckV2ZW50KHRoaXMsICdiZWZvcmVTZWxlY3RFdmVudCcsICRldmVudCwgZmlyZUV2ZW50LCAoJGV2ZW50OiBFdmVudCkgPT4ge1xuICAgICAgLy8gZG9FdmVudFxuICAgICAgdGhpcy5fc2V0U2VsZWN0ZWRJdGVtc1NhdmVEYXRhKHNlbGVjdGVkSXRlbXMsIHRydWUsICRldmVudCwgZmlyZUNoYW5nZUV2ZW50KTtcbiAgICB9LCAoJGV2ZW50OiBFdmVudCkgPT4ge1xuICAgICAgLy8gZW1pdEJlZm9yZUV2ZW50XG4gICAgICB0aGlzLmVtaXRCZWZvcmVTZWxlY3RFdmVudChvbGRJbmRleCwgbmV3SW5kaWNlcywgJGV2ZW50KTtcbiAgICB9LCAoJGV2ZW50OiBFdmVudCwgcmVzdWx0OiBhbnkpID0+IHtcbiAgICAgIC8vIGVtaXRBZnRlckV2ZW50XG4gICAgICB0aGlzLmVtaXRTZWxlY3RFdmVudChvbGRJbmRleCwgbmV3SW5kaWNlcywgJGV2ZW50KTtcbiAgICB9LCAoJGV2ZW50OiBFdmVudCkgPT4ge1xuICAgICAgLy8gZG9QcmV2ZW50ZWRcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXREZXNjcmlwdGlvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmRlc2NyaXB0aW9uO1xuICB9XG5cbiAgcHVibGljIHNldERlc2NyaXB0aW9uKGRlc2NyaXB0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb247XG4gIH1cblxuICBwdWJsaWMgaGFzRGVzY3JpcHRpb24oKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuZGVzY3JpcHRpb24gIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuZGVzY3JpcHRpb24gPT09ICdzdHJpbmcnICYmIHRoaXMuZGVzY3JpcHRpb24gIT09ICcnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwdWJsaWMgZ2V0Q2xpY2tlZEV2ZW50KCk6IEV2ZW50RW1pdHRlcjxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5jbGlja0V2ZW50O1xuICB9XG5cbiAgcHVibGljIHNldENsaWNrZWRFdmVudChldmVudDogYW55KSB7XG4gICAgdGhpcy5jbGlja0V2ZW50ID0gZXZlbnQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0QmVmb3JlQ2xpY2tlZEV2ZW50KCk6IEV2ZW50RW1pdHRlcjxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5iZWZvcmVDbGlja0V2ZW50O1xuICB9XG5cbiAgcHVibGljIHNldEJlZm9yZUNsaWNrZWRFdmVudChldmVudDogYW55KSB7XG4gICAgdGhpcy5iZWZvcmVDbGlja0V2ZW50ID0gZXZlbnQ7XG4gIH1cbiAgcHJvdGVjdGVkIG9uVmFsaWRhdGlvbkVuZChpbnB1dFZhbHVlOiBhbnksIHJlc3VsdHM6IFZhbGlkYXRpb25SZXN1bHRbXSk6IHZvaWQge1xuICAgIC8vISBkbyBzdGhpbmdcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkRhdGFDaGFuZ2UoZGF0YTogYW55LCBpbnB1dFZhbDogYW55KTogdm9pZCB7XG4gIH1cblxuICBwcm90ZWN0ZWQgZG9Gb2N1cygkZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gIH1cblxuICBwcm90ZWN0ZWQgZG9Mb3N0Rm9jdXMoJGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICB9XG5cbiAgcHVibGljIHNlbGZTYXZlRGF0YShkYXRhOiBhbnkpOiB2b2lkIHtcblxuICB9XG5cbiAgcHVibGljIHNlbGZSZXNldERhdGEoKTogdm9pZCB7XG5cbiAgfVxuXG4gIHB1YmxpYyBnZXRDbGlja0V2ZW50KCk6IEV2ZW50RW1pdHRlcjxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5jbGlja0V2ZW50O1xuICB9XG5cbiAgcHVibGljIHNldENsaWNrRXZlbnQoZXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+KSB7XG4gICAgdGhpcy5jbGlja0V2ZW50ID0gZXZlbnQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0TmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm5hbWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0Q29tcG9uZW50VHlwZSgpOiBUeXBlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudFR5cGU7XG4gIH1cblxuICBwdWJsaWMgZ2V0Q29tcG9uZW50TW9kZWwoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnRNb2RlbDtcbiAgfVxuXG4gIHB1YmxpYyBnZXRDb21wb25lbnRIYW5kbGVyKCk6IEZ1bmN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnRIYW5kbGVyO1xuICB9XG5cbiAgcHVibGljIGdldEl0ZW1zKCk6IElTZWxlY3RJdGVtTW9kZWxbXSB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbXM7XG4gIH1cblxuICBwdWJsaWMgZ2V0QmVmb3JlQ2xpY2tFdmVudCgpOiBFdmVudEVtaXR0ZXI8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuYmVmb3JlQ2xpY2tFdmVudDtcbiAgfVxuXG4gIHB1YmxpYyBzZXRCZWZvcmVDbGlja0V2ZW50KGJlZm9yZUNsaWNrRXZlbnQ6IEV2ZW50RW1pdHRlcjxhbnk+KSB7XG4gICAgdGhpcy5iZWZvcmVDbGlja0V2ZW50ID0gYmVmb3JlQ2xpY2tFdmVudDtcbiAgfVxufVxuIl19