right-angled
Version:
Lightweight and easy to use angular data grids. Integrates with your markup and styles rather than generating its own.
316 lines • 42.7 kB
JavaScript
import { Injectable } from '@angular/core';
import * as i0 from "@angular/core";
/**
* Represents possible operations with selection model.
*/
export class RTSelectionService {
constructor() {
this.eventEmitters = new Array();
this.childSelectionServices = new Array();
/**
* Collection of elements for selection.
*/
this.items = [];
/**
* Collection of {@link SelectionTuple} elements which represents currently selected items in {@link items} collection.
*/
this.selectionsList = new Array();
/**
* Default tracking function that will be used if nothing was specified for {@link trackByFn}.
* Implements comparison by reference equality of objects.
*/
this.trackByIdentity = (index, item) => item;
this.trackByFn = this.trackByIdentity;
}
/**
* Performs application-defined logic for service destroy.
*/
destroy() {
this.areaEventsEmitter = null;
this.eventEmitters.length = 0;
this.selectionsList.length = 0;
this.lastProcessedIndex = null;
this.items = null;
}
/**
* Performs check that every selected element is actually selected.
*
*/
checkSelection() {
if (this.items !== null && typeof this.items !== 'undefined') {
for (let i = this.selectionsList.length - 1; i >= 0; i--) {
const tuple = this.selectionsList[i];
const trackFn = this.trackByFn || this.trackByIdentity;
if (this.isIndexAcceptable(tuple.index) && trackFn(tuple.index, this.items[tuple.index]) === trackFn(tuple.index, tuple.item)) {
tuple.item = this.items[tuple.index];
this.selectItem(tuple, true);
}
else {
this.deselectItem(tuple);
}
}
}
else {
this.deselectAll();
}
}
/**
* Checks that applied index is valid number and it's value is inside {@link items} boundaries.
* @param index index to check.
* @returns `true` if index is valid.
*/
isIndexAcceptable(index) {
return index !== null && typeof index !== 'undefined' && index >= 0 && this.items && this.items.length > index;
}
/**
* Selects range of elements in {@link items} collection.
* @param fromIndex index of element from which selection range begins.
* @param toIndex index of element on which selection range ends.
*/
selectRange(fromIndex, toIndex) {
if (toIndex < 0 || this.items.length <= toIndex || fromIndex < 0 || this.items.length <= fromIndex) {
return;
}
const startIndex = Math.min(fromIndex, toIndex);
const endIndex = Math.max(fromIndex, toIndex);
if (this.isRangeSelected(startIndex, endIndex)) {
return;
}
this.deselectAll();
const tempData = new Array();
for (let i = startIndex; i <= endIndex; i++) {
const tuple = this.getSelectionTuple(i);
tempData.push(tuple);
this.processSelection(tuple, true);
}
this.selectionsList.splice(0, this.selectionsList.length, ...tempData);
this.lastProcessedIndex = endIndex;
}
/**
* Checks that at least one element selected in {@link items} collection.
* @returns `true` if anything is selected.
*/
hasSelections() {
return this.selectionsList.length !== 0;
}
/**
* Checks that all elements inside specified range are selected in {@link items} collection.
* @param fromIndex index of element from which check must be performed.
* @param toIndex index of element to which check must be performed.
* @returns `true` if all elements inside specified range are selected.
*/
isRangeSelected(from, to) {
// nothing selected
if (this.selectionsList.length === 0) {
return false;
}
// entire list selected
if (from === 0 && to === this.items.length - 1 && this.selectionsList.length === this.items.length) {
return true;
}
const orderedIndexes = this.selectionsList.map((tuple) => tuple.index).sort();
return 1 + to - from === orderedIndexes.length && orderedIndexes[0] === from && orderedIndexes[orderedIndexes.length - 1] === to;
}
/**
* Checks that element at specified index is selected.
* @param index index of element in {@link items} collection to check.
* @returns `true` if element is selected.
*/
isIndexSelected(index) {
if (this.selectionsList.length > 0 && this.isIndexAcceptable(index)) {
return this.selectionsList.findIndex((st) => st.index === index) !== -1;
}
return false;
}
/**
* Returns index of specified element in {@link items} collection.
* @param item element to find.
* @returns index of specified element in {@link items} collection. -1 if element not found.
* @see {@link trackByFn}
*/
getItemIndex(item) {
return this.items.findIndex((value) => value === item);
}
/**
* Returns index of first selected element from {@link items} collection.
* @returns index of first selected element. -1 if nothing is selected.
*/
getMinSelectedIndex() {
let minIndex = -1;
this.selectionsList.forEach((item) => {
minIndex = minIndex === -1 || item.index < minIndex ? item.index : minIndex;
});
return minIndex;
}
/**
* Returns index of last selected element from {@link items} collection.
* @returns index of last selected element. -1 if nothing is selected.
*/
getMaxSelectedIndex() {
let maxIndex = -1;
this.selectionsList.forEach((item) => {
maxIndex = maxIndex === -1 || item.index > maxIndex ? item.index : maxIndex;
});
return maxIndex;
}
/**
* Selects first element in {@link items} collection.
*/
selectFirst() {
if (this.items.length > 0) {
this.selectItem(this.getSelectionTuple(0));
}
}
/**
* Selects last element in {@link items} collection.
*/
selectLast() {
if (this.items.length > 0) {
this.selectItem(this.getSelectionTuple(this.items.length - 1));
}
}
/**
* Selects element at specified index in {@link items} collection.
* @param index index of element in {@link items} collection.
* @param savePrevious `true` if previously selected elements must stay selected after current selection.
*/
selectIndex(index, savePrevious = false) {
if (this.isIndexAcceptable(index)) {
this.selectItem(this.getSelectionTuple(index), savePrevious);
}
}
/**
* Deselects element at specified index in {@link items} collection.
* @param index index of element in {@link items} collection.
*/
deselectIndex(index) {
if (this.isIndexAcceptable(index)) {
this.deselectItem(this.getSelectionTuple(index));
}
}
/**
* Toggles selection of element at the specified index.
* @param index index of element in {@link items} collection.
* @param savePrevious `true` if previously selected elements must stay selected after current selection.
*/
toggleSelection(index, savePrevious = false) {
if (!this.isIndexAcceptable(index)) {
return;
}
const tuple = this.getSelectionTuple(index);
if (this.isIndexSelected(index) && (this.selectionsList.length === 1 || (this.selectionsList.length > 1 && savePrevious))) {
this.deselectItem(tuple);
return;
}
this.selectItem(tuple, savePrevious);
}
/**
* Returns all elements from {@link items} collection which are marked as selected.
* @returns collection of selected elements.
*/
getSelectedElements() {
return this.selectionsList.map((selectionTuple) => selectionTuple.item);
}
/**
* Returns indexes of all elements from {@link items} collection which are marked as selected.
* @returns collection of selected elements indexes in {@link items} collection.
*/
getSelectedIndexes() {
return this.selectionsList.map((selectionTuple) => selectionTuple.index);
}
/**
* Performs final processing of selection/deselection of element.
*/
processSelection(tuple, selected) {
if (Object.prototype.hasOwnProperty.call(tuple.item, 'selected')) {
tuple.item.selected = selected;
}
const initialSelectState = this.eventEmitters[tuple.index] ? this.eventEmitters[tuple.index].selected || null : null;
if (initialSelectState === null || initialSelectState !== selected) {
if (this.eventEmitters.length > tuple.index && this.eventEmitters[tuple.index]) {
this.emitEvents(this.eventEmitters[tuple.index], selected, tuple);
this.eventEmitters[tuple.index].postProcessSelection(selected);
}
if (this.areaEventsEmitter) {
this.emitEvents(this.areaEventsEmitter, selected, tuple);
}
}
}
deselectItem(selectionTuple) {
const index = this.selectionsList.findIndex((selectedItem) => selectedItem.item === selectionTuple.item);
if (index !== -1) {
this.selectionsList.splice(index, 1);
}
this.processSelection(selectionTuple, false);
this.lastProcessedIndex = selectionTuple.index;
}
selectItem(selectionTuple, savePrevious = false) {
if (savePrevious) {
const index = this.selectionsList.findIndex((selectedItem) => selectedItem.item === selectionTuple.item);
if (index !== -1) {
this.selectionsList.splice(index, 1);
}
this.selectionsList.push(selectionTuple);
this.processSelection(selectionTuple, true);
}
else {
const list = this.selectionsList.splice(0, this.selectionsList.length);
list.forEach((selectedItem) => {
this.processSelection(selectedItem, false);
});
this.selectionsList.push(selectionTuple);
this.processSelection(selectionTuple, true);
}
this.lastProcessedIndex = selectionTuple.index;
}
getSelectionTuple(index) {
return {
index,
item: this.items[index]
};
}
/**
* Selects all elements in {@link items} collection.
*/
selectAll(recursive = true) {
this.selectRange(0, this.items.length - 1);
// run this directly after render to give child selectionAreas ability to render
setTimeout(() => {
if (recursive && this.childSelectionServices) {
this.childSelectionServices.forEach(service => {
service.selectAll(recursive);
});
}
}, 0);
}
/**
* Deselects all elements in {@link items} collection.
*/
deselectAll(recursive = true) {
if (recursive && this.childSelectionServices) {
this.childSelectionServices.forEach(service => {
service.deselectAll(recursive);
});
}
const list = this.selectionsList.splice(0, this.selectionsList.length);
for (const item of list) {
this.processSelection(item, false);
}
this.lastProcessedIndex = null;
}
emitEvents(emitter, selected, tuple) {
if (selected) {
emitter.itemSelected.emit({ index: tuple.index, item: tuple.item });
}
else {
emitter.itemDeselected.emit({ index: tuple.index, item: tuple.item });
}
emitter.selectionChanged.emit({ index: tuple.index, item: tuple.item });
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RTSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RTSelectionService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RTSelectionService, decorators: [{
type: Injectable
}], ctorParameters: function () { return []; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yaWdodC1hbmdsZWQvc3JjL2xpYi9zZWxlY3Rpb24vcHJvdmlkZXJzL3NlbGVjdGlvbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBSzNDOztHQUVHO0FBRUgsTUFBTSxPQUFPLGtCQUFrQjtJQTZCN0I7UUE1Qk8sa0JBQWEsR0FBb0MsSUFBSSxLQUFLLEVBQWlDLENBQUM7UUFDNUYsMkJBQXNCLEdBQXlCLElBQUksS0FBSyxFQUFzQixDQUFDO1FBaUJ0Rjs7V0FFRztRQUNJLFVBQUssR0FBVSxFQUFFLENBQUM7UUFFekI7O1dBRUc7UUFDSyxtQkFBYyxHQUFxQixJQUFJLEtBQUssRUFBa0IsQ0FBQztRQXlOdkU7OztXQUdHO1FBQ0ssb0JBQWUsR0FBc0MsQ0FBQyxLQUFhLEVBQUUsSUFBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUM7UUExTjlGLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUN4QyxDQUFDO0lBQ0Q7O09BRUc7SUFDSSxPQUFPO1FBQ1osSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztRQUM5QixJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUM7UUFDL0IsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7SUFDcEIsQ0FBQztJQUNEOzs7T0FHRztJQUNJLGNBQWM7UUFDbkIsSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLElBQUksSUFBSSxPQUFPLElBQUksQ0FBQyxLQUFLLEtBQUssV0FBVyxFQUFFO1lBQzVELEtBQUssSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3hELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3JDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQztnQkFDdkQsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFO29CQUM3SCxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNyQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztpQkFDOUI7cUJBQU07b0JBQ0wsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDMUI7YUFDRjtTQUNGO2FBQU07WUFDTCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDcEI7SUFDSCxDQUFDO0lBQ0Q7Ozs7T0FJRztJQUNJLGlCQUFpQixDQUFDLEtBQWE7UUFDcEMsT0FBTyxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFdBQVcsSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ2pILENBQUM7SUFDRDs7OztPQUlHO0lBQ0ksV0FBVyxDQUFDLFNBQWlCLEVBQUUsT0FBZTtRQUNuRCxJQUFJLE9BQU8sR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLElBQUksT0FBTyxJQUFJLFNBQVMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLElBQUksU0FBUyxFQUFFO1lBQ2xHLE9BQU87U0FDUjtRQUNELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2hELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUU7WUFDOUMsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25CLE1BQU0sUUFBUSxHQUFHLElBQUksS0FBSyxFQUFrQixDQUFDO1FBQzdDLEtBQUssSUFBSSxDQUFDLEdBQUcsVUFBVSxFQUFFLENBQUMsSUFBSSxRQUFRLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDM0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUNwQztRQUNELElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxRQUFRLENBQUM7SUFDckMsQ0FBQztJQUNEOzs7T0FHRztJQUNJLGFBQWE7UUFDbEIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUNEOzs7OztPQUtHO0lBQ0ksZUFBZSxDQUFDLElBQVksRUFBRSxFQUFVO1FBQzdDLG1CQUFtQjtRQUNuQixJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNwQyxPQUFPLEtBQUssQ0FBQztTQUNkO1FBQ0QsdUJBQXVCO1FBQ3ZCLElBQUksSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFO1lBQ2xHLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQXFCLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5RixPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxLQUFLLGNBQWMsQ0FBQyxNQUFNLElBQUksY0FBYyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksSUFBSSxjQUFjLENBQUMsY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDbkksQ0FBQztJQUNEOzs7O09BSUc7SUFDSSxlQUFlLENBQUMsS0FBYTtRQUNsQyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDbkUsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQWtCLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDekY7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRDs7Ozs7T0FLRztJQUNJLFlBQVksQ0FBQyxJQUFTO1FBQzNCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFVLEVBQUUsRUFBRSxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBQ0Q7OztPQUdHO0lBQ0ksbUJBQW1CO1FBQ3hCLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBb0IsRUFBRSxFQUFFO1lBQ25ELFFBQVEsR0FBRyxRQUFRLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUM5RSxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFDRDs7O09BR0c7SUFDSSxtQkFBbUI7UUFDeEIsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFvQixFQUFFLEVBQUU7WUFDbkQsUUFBUSxHQUFHLFFBQVEsS0FBSyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBQzlFLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUNEOztPQUVHO0lBQ0ksV0FBVztRQUNoQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzVDO0lBQ0gsQ0FBQztJQUNEOztPQUVHO0lBQ0ksVUFBVTtRQUNmLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ3pCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEU7SUFDSCxDQUFDO0lBQ0Q7Ozs7T0FJRztJQUNJLFdBQVcsQ0FBQyxLQUFhLEVBQUUsWUFBWSxHQUFHLEtBQUs7UUFDcEQsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDakMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7U0FDOUQ7SUFDSCxDQUFDO0lBQ0Q7OztPQUdHO0lBQ0ksYUFBYSxDQUFDLEtBQWE7UUFDaEMsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDakMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUNsRDtJQUNILENBQUM7SUFDRDs7OztPQUlHO0lBQ0ksZUFBZSxDQUFDLEtBQWEsRUFBRSxZQUFZLEdBQUcsS0FBSztRQUN4RCxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ2xDLE9BQU87U0FDUjtRQUNELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksWUFBWSxDQUFDLENBQUMsRUFBRTtZQUN6SCxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pCLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFDRDs7O09BR0c7SUFDSSxtQkFBbUI7UUFDeEIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQThCLEVBQUUsRUFBRSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxRixDQUFDO0lBQ0Q7OztPQUdHO0lBQ0ksa0JBQWtCO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxjQUE4QixFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUNEOztPQUVHO0lBQ0ksZ0JBQWdCLENBQUMsS0FBcUIsRUFBRSxRQUFpQjtRQUM5RCxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxFQUFFO1lBQ2hFLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztTQUNoQztRQUNELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNySCxJQUFJLGtCQUFrQixLQUFLLElBQUksSUFBSSxrQkFBa0IsS0FBSyxRQUFRLEVBQUU7WUFDbEUsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUM5RSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDbEUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDaEU7WUFDRCxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDMUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQzFEO1NBQ0Y7SUFDSCxDQUFDO0lBT08sWUFBWSxDQUFDLGNBQThCO1FBQ2pELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsWUFBNEIsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekgsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFDaEIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ3RDO1FBQ0QsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQztJQUNqRCxDQUFDO0lBQ08sVUFBVSxDQUFDLGNBQThCLEVBQUUsWUFBWSxHQUFHLEtBQUs7UUFDckUsSUFBSSxZQUFZLEVBQUU7WUFDaEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxZQUE0QixFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxLQUFLLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN6SCxJQUFJLEtBQUssS0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDaEIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQ3RDO1lBQ0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsQ0FBQztTQUM3QzthQUFNO1lBQ0wsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFlBQTRCLEVBQUUsRUFBRTtnQkFDNUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM3QyxDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDN0M7UUFDRCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQztJQUNqRCxDQUFDO0lBQ08saUJBQWlCLENBQUMsS0FBYTtRQUNyQyxPQUFPO1lBQ0wsS0FBSztZQUNMLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztTQUN4QixDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksU0FBUyxDQUFDLFNBQVMsR0FBRyxJQUFJO1FBQy9CLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzNDLGdGQUFnRjtRQUNoRixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDLHNCQUFzQixFQUFFO2dCQUM1QyxJQUFJLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUM1QyxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUMvQixDQUFDLENBQUMsQ0FBQzthQUNKO1FBQ0gsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQztJQUNEOztPQUVHO0lBQ0ksV0FBVyxDQUFDLFNBQVMsR0FBRyxJQUFJO1FBQ2pDLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRTtZQUM1QyxJQUFJLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUM1QyxPQUFPLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2pDLENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFDRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2RSxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksRUFBRTtZQUN2QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ3BDO1FBQ0QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztJQUNqQyxDQUFDO0lBQ00sVUFBVSxDQUFDLE9BQStCLEVBQUUsUUFBaUIsRUFBRSxLQUFxQjtRQUN6RixJQUFJLFFBQVEsRUFBRTtZQUNaLE9BQU8sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1NBQ3JFO2FBQU07WUFDTCxPQUFPLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUN2RTtRQUNELE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDMUUsQ0FBQzsrR0EvVFUsa0JBQWtCO21IQUFsQixrQkFBa0I7OzRGQUFsQixrQkFBa0I7a0JBRDlCLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTZWxlY3Rpb25FdmVudHNFbWl0dGVyLCBTZWxlY3Rpb25FbGVtZW50RXZlbnRzRW1pdHRlciB9IGZyb20gJy4vc2VsZWN0aW9uLWV2ZW50cy1lbWl0dGVyJztcclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5leHBvcnQgaW50ZXJmYWNlIFNlbGVjdGlvblR1cGxlIHtcclxuICBpbmRleDogbnVtYmVyO1xyXG4gIGl0ZW06IGFueTtcclxufVxyXG4vKipcclxuICogUmVwcmVzZW50cyBwb3NzaWJsZSBvcGVyYXRpb25zIHdpdGggc2VsZWN0aW9uIG1vZGVsLlxyXG4gKi9cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgUlRTZWxlY3Rpb25TZXJ2aWNlIHtcclxuICBwdWJsaWMgZXZlbnRFbWl0dGVyczogU2VsZWN0aW9uRWxlbWVudEV2ZW50c0VtaXR0ZXJbXSA9IG5ldyBBcnJheTxTZWxlY3Rpb25FbGVtZW50RXZlbnRzRW1pdHRlcj4oKTtcclxuICBwdWJsaWMgY2hpbGRTZWxlY3Rpb25TZXJ2aWNlczogUlRTZWxlY3Rpb25TZXJ2aWNlW10gPSBuZXcgQXJyYXk8UlRTZWxlY3Rpb25TZXJ2aWNlPigpO1xyXG4gIHB1YmxpYyBhcmVhRXZlbnRzRW1pdHRlcjogU2VsZWN0aW9uRXZlbnRzRW1pdHRlcjtcclxuICAvKipcclxuICAgKiBJbmRleCBvZiBsYXN0IHNlbGVjdGVkL2Rlc2VsZWN0ZWQgZWxlbWVudCBpbiB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24uXHJcbiAgICovXHJcblxyXG4gIHB1YmxpYyBsYXN0UHJvY2Vzc2VkSW5kZXg6IG51bWJlcjtcclxuICAvKipcclxuICAgKiBPcHRpb25hbCBmdW5jdGlvbiB3aGljaCBjYW4gYmUgdXNlZCB0byBjb21wYXJlIHtAbGluayBpdGVtc30gZWxlbWVudHMuXHJcbiAgICpcclxuICAgKiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIGJ5IHtAbGluayBjaGVja1NlbGVjdGlvbn0uXHJcbiAgICpcclxuICAgKiBBbHNvIGl0J3MgcmVhc29uYWJsZSB0byB1c2UgdGhpcyBmdW5jdGlvbiBmb3Ige0BsaW5rIGdldEl0ZW1JbmRleH0uXHJcbiAgICogQHBhcmFtIGluZGV4IGluZGV4IG9mIGVsZW1lbnQgaW4ge0BsaW5rIGl0ZW1zfSBjb2xsZWN0aW9uLlxyXG4gICAqIEBwYXJhbSBhY3R1YWwgZWxlbWVudCBmcm9tIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgdHJhY2tCeUZuOiAoaW5kZXg6IG51bWJlciwgaXRlbTogYW55KSA9PiBhbnk7XHJcbiAgLyoqXHJcbiAgICogQ29sbGVjdGlvbiBvZiBlbGVtZW50cyBmb3Igc2VsZWN0aW9uLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBpdGVtczogYW55W10gPSBbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ29sbGVjdGlvbiBvZiB7QGxpbmsgU2VsZWN0aW9uVHVwbGV9IGVsZW1lbnRzIHdoaWNoIHJlcHJlc2VudHMgY3VycmVudGx5IHNlbGVjdGVkIGl0ZW1zIGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKi9cclxuICBwcml2YXRlIHNlbGVjdGlvbnNMaXN0OiBTZWxlY3Rpb25UdXBsZVtdID0gbmV3IEFycmF5PFNlbGVjdGlvblR1cGxlPigpO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICAgIHRoaXMudHJhY2tCeUZuID0gdGhpcy50cmFja0J5SWRlbnRpdHk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFBlcmZvcm1zIGFwcGxpY2F0aW9uLWRlZmluZWQgbG9naWMgZm9yIHNlcnZpY2UgZGVzdHJveS5cclxuICAgKi9cclxuICBwdWJsaWMgZGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuYXJlYUV2ZW50c0VtaXR0ZXIgPSBudWxsO1xyXG4gICAgdGhpcy5ldmVudEVtaXR0ZXJzLmxlbmd0aCA9IDA7XHJcbiAgICB0aGlzLnNlbGVjdGlvbnNMaXN0Lmxlbmd0aCA9IDA7XHJcbiAgICB0aGlzLmxhc3RQcm9jZXNzZWRJbmRleCA9IG51bGw7XHJcbiAgICB0aGlzLml0ZW1zID0gbnVsbDtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgY2hlY2sgdGhhdCBldmVyeSBzZWxlY3RlZCBlbGVtZW50IGlzIGFjdHVhbGx5IHNlbGVjdGVkLlxyXG4gICAqXHJcbiAgICovXHJcbiAgcHVibGljIGNoZWNrU2VsZWN0aW9uKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXRlbXMgIT09IG51bGwgJiYgdHlwZW9mIHRoaXMuaXRlbXMgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgIGZvciAobGV0IGkgPSB0aGlzLnNlbGVjdGlvbnNMaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgY29uc3QgdHVwbGUgPSB0aGlzLnNlbGVjdGlvbnNMaXN0W2ldO1xyXG4gICAgICAgIGNvbnN0IHRyYWNrRm4gPSB0aGlzLnRyYWNrQnlGbiB8fCB0aGlzLnRyYWNrQnlJZGVudGl0eTtcclxuICAgICAgICBpZiAodGhpcy5pc0luZGV4QWNjZXB0YWJsZSh0dXBsZS5pbmRleCkgJiYgdHJhY2tGbih0dXBsZS5pbmRleCwgdGhpcy5pdGVtc1t0dXBsZS5pbmRleF0pID09PSB0cmFja0ZuKHR1cGxlLmluZGV4LCB0dXBsZS5pdGVtKSkge1xyXG4gICAgICAgICAgdHVwbGUuaXRlbSA9IHRoaXMuaXRlbXNbdHVwbGUuaW5kZXhdO1xyXG4gICAgICAgICAgdGhpcy5zZWxlY3RJdGVtKHR1cGxlLCB0cnVlKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdGhpcy5kZXNlbGVjdEl0ZW0odHVwbGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5kZXNlbGVjdEFsbCgpO1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBDaGVja3MgdGhhdCBhcHBsaWVkIGluZGV4IGlzIHZhbGlkIG51bWJlciBhbmQgaXQncyB2YWx1ZSBpcyBpbnNpZGUge0BsaW5rIGl0ZW1zfSBib3VuZGFyaWVzLlxyXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCB0byBjaGVjay5cclxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgaW5kZXggaXMgdmFsaWQuXHJcbiAgICovXHJcbiAgcHVibGljIGlzSW5kZXhBY2NlcHRhYmxlKGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBpbmRleCAhPT0gbnVsbCAmJiB0eXBlb2YgaW5kZXggIT09ICd1bmRlZmluZWQnICYmIGluZGV4ID49IDAgJiYgdGhpcy5pdGVtcyAmJiB0aGlzLml0ZW1zLmxlbmd0aCA+IGluZGV4O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBTZWxlY3RzIHJhbmdlIG9mIGVsZW1lbnRzIGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKiBAcGFyYW0gZnJvbUluZGV4IGluZGV4IG9mIGVsZW1lbnQgZnJvbSB3aGljaCBzZWxlY3Rpb24gcmFuZ2UgYmVnaW5zLlxyXG4gICAqIEBwYXJhbSB0b0luZGV4IGluZGV4IG9mIGVsZW1lbnQgb24gd2hpY2ggc2VsZWN0aW9uIHJhbmdlIGVuZHMuXHJcbiAgICovXHJcbiAgcHVibGljIHNlbGVjdFJhbmdlKGZyb21JbmRleDogbnVtYmVyLCB0b0luZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICh0b0luZGV4IDwgMCB8fCB0aGlzLml0ZW1zLmxlbmd0aCA8PSB0b0luZGV4IHx8IGZyb21JbmRleCA8IDAgfHwgdGhpcy5pdGVtcy5sZW5ndGggPD0gZnJvbUluZGV4KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBNYXRoLm1pbihmcm9tSW5kZXgsIHRvSW5kZXgpO1xyXG4gICAgY29uc3QgZW5kSW5kZXggPSBNYXRoLm1heChmcm9tSW5kZXgsIHRvSW5kZXgpO1xyXG4gICAgaWYgKHRoaXMuaXNSYW5nZVNlbGVjdGVkKHN0YXJ0SW5kZXgsIGVuZEluZGV4KSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmRlc2VsZWN0QWxsKCk7XHJcbiAgICBjb25zdCB0ZW1wRGF0YSA9IG5ldyBBcnJheTxTZWxlY3Rpb25UdXBsZT4oKTtcclxuICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDw9IGVuZEluZGV4OyBpKyspIHtcclxuICAgICAgY29uc3QgdHVwbGUgPSB0aGlzLmdldFNlbGVjdGlvblR1cGxlKGkpO1xyXG4gICAgICB0ZW1wRGF0YS5wdXNoKHR1cGxlKTtcclxuICAgICAgdGhpcy5wcm9jZXNzU2VsZWN0aW9uKHR1cGxlLCB0cnVlKTtcclxuICAgIH1cclxuICAgIHRoaXMuc2VsZWN0aW9uc0xpc3Quc3BsaWNlKDAsIHRoaXMuc2VsZWN0aW9uc0xpc3QubGVuZ3RoLCAuLi50ZW1wRGF0YSk7XHJcbiAgICB0aGlzLmxhc3RQcm9jZXNzZWRJbmRleCA9IGVuZEluZGV4O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDaGVja3MgdGhhdCBhdCBsZWFzdCBvbmUgZWxlbWVudCBzZWxlY3RlZCBpbiB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24uXHJcbiAgICogQHJldHVybnMgYHRydWVgIGlmIGFueXRoaW5nIGlzIHNlbGVjdGVkLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBoYXNTZWxlY3Rpb25zKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uc0xpc3QubGVuZ3RoICE9PSAwO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDaGVja3MgdGhhdCBhbGwgZWxlbWVudHMgaW5zaWRlIHNwZWNpZmllZCByYW5nZSBhcmUgc2VsZWN0ZWQgaW4ge0BsaW5rIGl0ZW1zfSBjb2xsZWN0aW9uLlxyXG4gICAqIEBwYXJhbSBmcm9tSW5kZXggaW5kZXggb2YgZWxlbWVudCBmcm9tIHdoaWNoIGNoZWNrIG11c3QgYmUgcGVyZm9ybWVkLlxyXG4gICAqIEBwYXJhbSB0b0luZGV4IGluZGV4IG9mIGVsZW1lbnQgdG8gd2hpY2ggY2hlY2sgbXVzdCBiZSBwZXJmb3JtZWQuXHJcbiAgICogQHJldHVybnMgYHRydWVgIGlmIGFsbCBlbGVtZW50cyBpbnNpZGUgc3BlY2lmaWVkIHJhbmdlIGFyZSBzZWxlY3RlZC5cclxuICAgKi9cclxuICBwdWJsaWMgaXNSYW5nZVNlbGVjdGVkKGZyb206IG51bWJlciwgdG86IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gICAgLy8gbm90aGluZyBzZWxlY3RlZFxyXG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uc0xpc3QubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIC8vIGVudGlyZSBsaXN0IHNlbGVjdGVkXHJcbiAgICBpZiAoZnJvbSA9PT0gMCAmJiB0byA9PT0gdGhpcy5pdGVtcy5sZW5ndGggLSAxICYmIHRoaXMuc2VsZWN0aW9uc0xpc3QubGVuZ3RoID09PSB0aGlzLml0ZW1zLmxlbmd0aCkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICAgIGNvbnN0IG9yZGVyZWRJbmRleGVzID0gdGhpcy5zZWxlY3Rpb25zTGlzdC5tYXAoKHR1cGxlOiBTZWxlY3Rpb25UdXBsZSkgPT4gdHVwbGUuaW5kZXgpLnNvcnQoKTtcclxuICAgIHJldHVybiAxICsgdG8gLSBmcm9tID09PSBvcmRlcmVkSW5kZXhlcy5sZW5ndGggJiYgb3JkZXJlZEluZGV4ZXNbMF0gPT09IGZyb20gJiYgb3JkZXJlZEluZGV4ZXNbb3JkZXJlZEluZGV4ZXMubGVuZ3RoIC0gMV0gPT09IHRvO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDaGVja3MgdGhhdCBlbGVtZW50IGF0IHNwZWNpZmllZCBpbmRleCBpcyBzZWxlY3RlZC5cclxuICAgKiBAcGFyYW0gaW5kZXggaW5kZXggb2YgZWxlbWVudCBpbiB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24gdG8gY2hlY2suXHJcbiAgICogQHJldHVybnMgYHRydWVgIGlmIGVsZW1lbnQgaXMgc2VsZWN0ZWQuXHJcbiAgICovXHJcbiAgcHVibGljIGlzSW5kZXhTZWxlY3RlZChpbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5zZWxlY3Rpb25zTGlzdC5sZW5ndGggPiAwICYmIHRoaXMuaXNJbmRleEFjY2VwdGFibGUoaW5kZXgpKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnNlbGVjdGlvbnNMaXN0LmZpbmRJbmRleCgoc3Q6IFNlbGVjdGlvblR1cGxlKSA9PiBzdC5pbmRleCA9PT0gaW5kZXgpICE9PSAtMTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBpbmRleCBvZiBzcGVjaWZpZWQgZWxlbWVudCBpbiB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24uXHJcbiAgICogQHBhcmFtIGl0ZW0gZWxlbWVudCB0byBmaW5kLlxyXG4gICAqIEByZXR1cm5zIGluZGV4IG9mIHNwZWNpZmllZCBlbGVtZW50IGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi4gLTEgaWYgZWxlbWVudCBub3QgZm91bmQuXHJcbiAgICogQHNlZSB7QGxpbmsgdHJhY2tCeUZufVxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXRJdGVtSW5kZXgoaXRlbTogYW55KTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLml0ZW1zLmZpbmRJbmRleCgodmFsdWU6IGFueSkgPT4gdmFsdWUgPT09IGl0ZW0pO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGluZGV4IG9mIGZpcnN0IHNlbGVjdGVkIGVsZW1lbnQgZnJvbSB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24uXHJcbiAgICogQHJldHVybnMgaW5kZXggb2YgZmlyc3Qgc2VsZWN0ZWQgZWxlbWVudC4gLTEgaWYgbm90aGluZyBpcyBzZWxlY3RlZC5cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0TWluU2VsZWN0ZWRJbmRleCgpOiBudW1iZXIge1xyXG4gICAgbGV0IG1pbkluZGV4ID0gLTE7XHJcbiAgICB0aGlzLnNlbGVjdGlvbnNMaXN0LmZvckVhY2goKGl0ZW06IFNlbGVjdGlvblR1cGxlKSA9PiB7XHJcbiAgICAgIG1pbkluZGV4ID0gbWluSW5kZXggPT09IC0xIHx8IGl0ZW0uaW5kZXggPCBtaW5JbmRleCA/IGl0ZW0uaW5kZXggOiBtaW5JbmRleDtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG1pbkluZGV4O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGluZGV4IG9mIGxhc3Qgc2VsZWN0ZWQgZWxlbWVudCBmcm9tIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKiBAcmV0dXJucyBpbmRleCBvZiBsYXN0IHNlbGVjdGVkIGVsZW1lbnQuIC0xIGlmIG5vdGhpbmcgaXMgc2VsZWN0ZWQuXHJcbiAgICovXHJcbiAgcHVibGljIGdldE1heFNlbGVjdGVkSW5kZXgoKTogbnVtYmVyIHtcclxuICAgIGxldCBtYXhJbmRleCA9IC0xO1xyXG4gICAgdGhpcy5zZWxlY3Rpb25zTGlzdC5mb3JFYWNoKChpdGVtOiBTZWxlY3Rpb25UdXBsZSkgPT4ge1xyXG4gICAgICBtYXhJbmRleCA9IG1heEluZGV4ID09PSAtMSB8fCBpdGVtLmluZGV4ID4gbWF4SW5kZXggPyBpdGVtLmluZGV4IDogbWF4SW5kZXg7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBtYXhJbmRleDtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogU2VsZWN0cyBmaXJzdCBlbGVtZW50IGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgc2VsZWN0Rmlyc3QoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5pdGVtcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0SXRlbSh0aGlzLmdldFNlbGVjdGlvblR1cGxlKDApKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogU2VsZWN0cyBsYXN0IGVsZW1lbnQgaW4ge0BsaW5rIGl0ZW1zfSBjb2xsZWN0aW9uLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBzZWxlY3RMYXN0KCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXRlbXMubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLnNlbGVjdEl0ZW0odGhpcy5nZXRTZWxlY3Rpb25UdXBsZSh0aGlzLml0ZW1zLmxlbmd0aCAtIDEpKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogU2VsZWN0cyBlbGVtZW50IGF0IHNwZWNpZmllZCBpbmRleCBpbiB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24uXHJcbiAgICogQHBhcmFtIGluZGV4IGluZGV4IG9mIGVsZW1lbnQgaW4ge0BsaW5rIGl0ZW1zfSBjb2xsZWN0aW9uLlxyXG4gICAqIEBwYXJhbSBzYXZlUHJldmlvdXMgYHRydWVgIGlmIHByZXZpb3VzbHkgc2VsZWN0ZWQgZWxlbWVudHMgbXVzdCBzdGF5IHNlbGVjdGVkIGFmdGVyIGN1cnJlbnQgc2VsZWN0aW9uLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBzZWxlY3RJbmRleChpbmRleDogbnVtYmVyLCBzYXZlUHJldmlvdXMgPSBmYWxzZSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXNJbmRleEFjY2VwdGFibGUoaW5kZXgpKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0SXRlbSh0aGlzLmdldFNlbGVjdGlvblR1cGxlKGluZGV4KSwgc2F2ZVByZXZpb3VzKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogRGVzZWxlY3RzIGVsZW1lbnQgYXQgc3BlY2lmaWVkIGluZGV4IGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKiBAcGFyYW0gaW5kZXggaW5kZXggb2YgZWxlbWVudCBpbiB7QGxpbmsgaXRlbXN9IGNvbGxlY3Rpb24uXHJcbiAgICovXHJcbiAgcHVibGljIGRlc2VsZWN0SW5kZXgoaW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXNJbmRleEFjY2VwdGFibGUoaW5kZXgpKSB7XHJcbiAgICAgIHRoaXMuZGVzZWxlY3RJdGVtKHRoaXMuZ2V0U2VsZWN0aW9uVHVwbGUoaW5kZXgpKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogVG9nZ2xlcyBzZWxlY3Rpb24gb2YgZWxlbWVudCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LlxyXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiBlbGVtZW50IGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKiBAcGFyYW0gc2F2ZVByZXZpb3VzIGB0cnVlYCBpZiBwcmV2aW91c2x5IHNlbGVjdGVkIGVsZW1lbnRzIG11c3Qgc3RheSBzZWxlY3RlZCBhZnRlciBjdXJyZW50IHNlbGVjdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgdG9nZ2xlU2VsZWN0aW9uKGluZGV4OiBudW1iZXIsIHNhdmVQcmV2aW91cyA9IGZhbHNlKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuaXNJbmRleEFjY2VwdGFibGUoaW5kZXgpKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGNvbnN0IHR1cGxlID0gdGhpcy5nZXRTZWxlY3Rpb25UdXBsZShpbmRleCk7XHJcbiAgICBpZiAodGhpcy5pc0luZGV4U2VsZWN0ZWQoaW5kZXgpICYmICh0aGlzLnNlbGVjdGlvbnNMaXN0Lmxlbmd0aCA9PT0gMSB8fCAodGhpcy5zZWxlY3Rpb25zTGlzdC5sZW5ndGggPiAxICYmIHNhdmVQcmV2aW91cykpKSB7XHJcbiAgICAgIHRoaXMuZGVzZWxlY3RJdGVtKHR1cGxlKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5zZWxlY3RJdGVtKHR1cGxlLCBzYXZlUHJldmlvdXMpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGFsbCBlbGVtZW50cyBmcm9tIHtAbGluayBpdGVtc30gY29sbGVjdGlvbiB3aGljaCBhcmUgbWFya2VkIGFzIHNlbGVjdGVkLlxyXG4gICAqIEByZXR1cm5zIGNvbGxlY3Rpb24gb2Ygc2VsZWN0ZWQgZWxlbWVudHMuXHJcbiAgICovXHJcbiAgcHVibGljIGdldFNlbGVjdGVkRWxlbWVudHMoKTogYW55W10ge1xyXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uc0xpc3QubWFwKChzZWxlY3Rpb25UdXBsZTogU2VsZWN0aW9uVHVwbGUpID0+IHNlbGVjdGlvblR1cGxlLml0ZW0pO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGluZGV4ZXMgb2YgYWxsIGVsZW1lbnRzIGZyb20ge0BsaW5rIGl0ZW1zfSBjb2xsZWN0aW9uIHdoaWNoIGFyZSBtYXJrZWQgYXMgc2VsZWN0ZWQuXHJcbiAgICogQHJldHVybnMgY29sbGVjdGlvbiBvZiBzZWxlY3RlZCBlbGVtZW50cyBpbmRleGVzIGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0U2VsZWN0ZWRJbmRleGVzKCk6IG51bWJlcltdIHtcclxuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvbnNMaXN0Lm1hcCgoc2VsZWN0aW9uVHVwbGU6IFNlbGVjdGlvblR1cGxlKSA9PiBzZWxlY3Rpb25UdXBsZS5pbmRleCk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFBlcmZvcm1zIGZpbmFsIHByb2Nlc3Npbmcgb2Ygc2VsZWN0aW9uL2Rlc2VsZWN0aW9uIG9mIGVsZW1lbnQuXHJcbiAgICovXHJcbiAgcHVibGljIHByb2Nlc3NTZWxlY3Rpb24odHVwbGU6IFNlbGVjdGlvblR1cGxlLCBzZWxlY3RlZDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0dXBsZS5pdGVtLCAnc2VsZWN0ZWQnKSkge1xyXG4gICAgICB0dXBsZS5pdGVtLnNlbGVjdGVkID0gc2VsZWN0ZWQ7XHJcbiAgICB9XHJcbiAgICBjb25zdCBpbml0aWFsU2VsZWN0U3RhdGUgPSB0aGlzLmV2ZW50RW1pdHRlcnNbdHVwbGUuaW5kZXhdID8gdGhpcy5ldmVudEVtaXR0ZXJzW3R1cGxlLmluZGV4XS5zZWxlY3RlZCB8fCBudWxsIDogbnVsbDtcclxuICAgIGlmIChpbml0aWFsU2VsZWN0U3RhdGUgPT09IG51bGwgfHwgaW5pdGlhbFNlbGVjdFN0YXRlICE9PSBzZWxlY3RlZCkge1xyXG4gICAgICBpZiAodGhpcy5ldmVudEVtaXR0ZXJzLmxlbmd0aCA+IHR1cGxlLmluZGV4ICYmIHRoaXMuZXZlbnRFbWl0dGVyc1t0dXBsZS5pbmRleF0pIHtcclxuICAgICAgICB0aGlzLmVtaXRFdmVudHModGhpcy5ldmVudEVtaXR0ZXJzW3R1cGxlLmluZGV4XSwgc2VsZWN0ZWQsIHR1cGxlKTtcclxuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlcnNbdHVwbGUuaW5kZXhdLnBvc3RQcm9jZXNzU2VsZWN0aW9uKHNlbGVjdGVkKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodGhpcy5hcmVhRXZlbnRzRW1pdHRlcikge1xyXG4gICAgICAgIHRoaXMuZW1pdEV2ZW50cyh0aGlzLmFyZWFFdmVudHNFbWl0dGVyLCBzZWxlY3RlZCwgdHVwbGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIERlZmF1bHQgdHJhY2tpbmcgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIHVzZWQgaWYgbm90aGluZyB3YXMgc3BlY2lmaWVkIGZvciB7QGxpbmsgdHJhY2tCeUZufS5cclxuICAgKiBJbXBsZW1lbnRzIGNvbXBhcmlzb24gYnkgcmVmZXJlbmNlIGVxdWFsaXR5IG9mIG9iamVjdHMuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSB0cmFja0J5SWRlbnRpdHk6IChpbmRleDogbnVtYmVyLCBpdGVtOiBhbnkpID0+IGFueSA9IChpbmRleDogbnVtYmVyLCBpdGVtOiBhbnkpID0+IGl0ZW07XHJcblxyXG4gIHByaXZhdGUgZGVzZWxlY3RJdGVtKHNlbGVjdGlvblR1cGxlOiBTZWxlY3Rpb25UdXBsZSk6IHZvaWQge1xyXG4gICAgY29uc3QgaW5kZXggPSB0aGlzLnNlbGVjdGlvbnNMaXN0LmZpbmRJbmRleCgoc2VsZWN0ZWRJdGVtOiBTZWxlY3Rpb25UdXBsZSkgPT4gc2VsZWN0ZWRJdGVtLml0ZW0gPT09IHNlbGVjdGlvblR1cGxlLml0ZW0pO1xyXG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICB0aGlzLnNlbGVjdGlvbnNMaXN0LnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnByb2Nlc3NTZWxlY3Rpb24oc2VsZWN0aW9uVHVwbGUsIGZhbHNlKTtcclxuICAgIHRoaXMubGFzdFByb2Nlc3NlZEluZGV4ID0gc2VsZWN0aW9uVHVwbGUuaW5kZXg7XHJcbiAgfVxyXG4gIHByaXZhdGUgc2VsZWN0SXRlbShzZWxlY3Rpb25UdXBsZTogU2VsZWN0aW9uVHVwbGUsIHNhdmVQcmV2aW91cyA9IGZhbHNlKTogdm9pZCB7XHJcbiAgICBpZiAoc2F2ZVByZXZpb3VzKSB7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5zZWxlY3Rpb25zTGlzdC5maW5kSW5kZXgoKHNlbGVjdGVkSXRlbTogU2VsZWN0aW9uVHVwbGUpID0+IHNlbGVjdGVkSXRlbS5pdGVtID09PSBzZWxlY3Rpb25UdXBsZS5pdGVtKTtcclxuICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uc0xpc3Quc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNlbGVjdGlvbnNMaXN0LnB1c2goc2VsZWN0aW9uVHVwbGUpO1xyXG4gICAgICB0aGlzLnByb2Nlc3NTZWxlY3Rpb24oc2VsZWN0aW9uVHVwbGUsIHRydWUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3QgbGlzdCA9IHRoaXMuc2VsZWN0aW9uc0xpc3Quc3BsaWNlKDAsIHRoaXMuc2VsZWN0aW9uc0xpc3QubGVuZ3RoKTtcclxuICAgICAgbGlzdC5mb3JFYWNoKChzZWxlY3RlZEl0ZW06IFNlbGVjdGlvblR1cGxlKSA9PiB7XHJcbiAgICAgICAgdGhpcy5wcm9jZXNzU2VsZWN0aW9uKHNlbGVjdGVkSXRlbSwgZmFsc2UpO1xyXG4gICAgICB9KTtcclxuICAgICAgdGhpcy5zZWxlY3Rpb25zTGlzdC5wdXNoKHNlbGVjdGlvblR1cGxlKTtcclxuICAgICAgdGhpcy5wcm9jZXNzU2VsZWN0aW9uKHNlbGVjdGlvblR1cGxlLCB0cnVlKTtcclxuICAgIH1cclxuICAgIHRoaXMubGFzdFByb2Nlc3NlZEluZGV4ID0gc2VsZWN0aW9uVHVwbGUuaW5kZXg7XHJcbiAgfVxyXG4gIHByaXZhdGUgZ2V0U2VsZWN0aW9uVHVwbGUoaW5kZXg6IG51bWJlcik6IFNlbGVjdGlvblR1cGxlIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGluZGV4LFxyXG4gICAgICBpdGVtOiB0aGlzLml0ZW1zW2luZGV4XVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlbGVjdHMgYWxsIGVsZW1lbnRzIGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgc2VsZWN0QWxsKHJlY3Vyc2l2ZSA9IHRydWUpOiB2b2lkIHtcclxuICAgIHRoaXMuc2VsZWN0UmFuZ2UoMCwgdGhpcy5pdGVtcy5sZW5ndGggLSAxKTtcclxuICAgIC8vIHJ1biB0aGlzIGRpcmVjdGx5IGFmdGVyIHJlbmRlciB0byBnaXZlIGNoaWxkIHNlbGVjdGlvbkFyZWFzIGFiaWxpdHkgdG8gcmVuZGVyXHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgaWYgKHJlY3Vyc2l2ZSAmJiB0aGlzLmNoaWxkU2VsZWN0aW9uU2VydmljZXMpIHtcclxuICAgICAgICB0aGlzLmNoaWxkU2VsZWN0aW9uU2VydmljZXMuZm9yRWFjaChzZXJ2aWNlID0+IHtcclxuICAgICAgICAgIHNlcnZpY2Uuc2VsZWN0QWxsKHJlY3Vyc2l2ZSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH0sIDApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBEZXNlbGVjdHMgYWxsIGVsZW1lbnRzIGluIHtAbGluayBpdGVtc30gY29sbGVjdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgZGVzZWxlY3RBbGwocmVjdXJzaXZlID0gdHJ1ZSk6IHZvaWQge1xyXG4gICAgaWYgKHJlY3Vyc2l2ZSAmJiB0aGlzLmNoaWxkU2VsZWN0aW9uU2VydmljZXMpIHtcclxuICAgICAgdGhpcy5jaGlsZFNlbGVjdGlvblNlcnZpY2VzLmZvckVhY2goc2VydmljZSA9PiB7XHJcbiAgICAgICAgc2VydmljZS5kZXNlbGVjdEFsbChyZWN1cnNpdmUpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIGNvbnN0IGxpc3QgPSB0aGlzLnNlbGVjdGlvbnNMaXN0LnNwbGljZSgwLCB0aGlzLnNlbGVjdGlvbnNMaXN0Lmxlbmd0aCk7XHJcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgbGlzdCkge1xyXG4gICAgICB0aGlzLnByb2Nlc3NTZWxlY3Rpb24oaXRlbSwgZmFsc2UpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5sYXN0UHJvY2Vzc2VkSW5kZXggPSBudWxsO1xyXG4gIH1cclxuICBwdWJsaWMgZW1pdEV2ZW50cyhlbWl0dGVyOiBTZWxlY3Rpb25FdmVudHNFbWl0dGVyLCBzZWxlY3RlZDogYm9vbGVhbiwgdHVwbGU6IFNlbGVjdGlvblR1cGxlKTogdm9pZCB7XHJcbiAgICBpZiAoc2VsZWN0ZWQpIHtcclxuICAgICAgZW1pdHRlci5pdGVtU2VsZWN0ZWQuZW1pdCh7IGluZGV4OiB0dXBsZS5pbmRleCwgaXRlbTogdHVwbGUuaXRlbSB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGVtaXR0ZXIuaXRlbURlc2VsZWN0ZWQuZW1pdCh7IGluZGV4OiB0dXBsZS5pbmRleCwgaXRlbTogdHVwbGUuaXRlbSB9KTtcclxuICAgIH1cclxuICAgIGVtaXR0ZXIuc2VsZWN0aW9uQ2hhbmdlZC5lbWl0KHsgaW5kZXg6IHR1cGxlLmluZGV4LCBpdGVtOiB0dXBsZS5pdGVtIH0pO1xyXG4gIH1cclxufVxyXG4iXX0=