@nova-ui/bits
Version:
SolarWinds Nova Framework
291 lines • 42.8 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { Injectable, Optional } from "@angular/core";
import _differenceWith from "lodash/differenceWith";
import _intersectionWith from "lodash/intersectionWith";
import _isEqual from "lodash/isEqual";
import _isUndefined from "lodash/isUndefined";
import _reject from "lodash/reject";
import _unionWith from "lodash/unionWith";
import { CheckboxStatus, SelectionType } from "./public-api";
import { LoggerService } from "../../services/log-service";
import { SelectionModel, } from "../../services/public-api";
import { RepeatSelectionMode } from "../repeat/types";
import * as i0 from "@angular/core";
import * as i1 from "../../services/log-service";
/**
* @ignore
*/
export class SelectorService {
constructor(logger) {
this.logger = logger;
/**
* Map if SelectionType to internationalized selector options
*/
this.i18nTitleMap = {};
this.i18nTitleMap[SelectionType.All] = $localize `Select all items on this page`;
this.i18nTitleMap[SelectionType.AllPages] = $localize `Select all items on all pages`;
this.i18nTitleMap[SelectionType.None] = $localize `Unselect all items`;
this.i18nTitleMap[SelectionType.UnselectAll] = $localize `Unselect all items on this page`;
}
// TODO: think about an ability to provide isEqual function from outside
/**
* Allows to react on changes of a selector component.
* If user has selected one of the options in a selector (Select all items pages, Select all items on all pages),
* the new selection object should be created.
* @param {ISelection} currentSelection
* @param {any[]} currentItems Items on current page
* @param {SelectionType} selectorValue
* @param {number} totalItems
* @param trackBy
* @param {boolean} virtualScroll Enables virtual scroll selection behavior
* @returns {ISelection} New selection object
*/
applySelector(currentSelection, currentItems, selectorValue, totalItems, trackBy = (i, d) => d, virtualScroll) {
if (virtualScroll) {
if (selectorValue === SelectionType.AllPages ||
selectorValue === SelectionType.All) {
return new SelectionModel({ isAllPages: true });
}
return new SelectionModel();
}
if (selectorValue === SelectionType.AllPages) {
return new SelectionModel({ isAllPages: true });
}
const trackedItems = currentItems.map((value, index) => trackBy(index, value));
if (currentSelection.isAllPages) {
if (selectorValue === SelectionType.All) {
return new SelectionModel({
isAllPages: true,
exclude: _differenceWith(currentSelection.exclude, trackedItems, _isEqual),
});
}
if (selectorValue === SelectionType.UnselectAll) {
return new SelectionModel({
isAllPages: true,
exclude: _unionWith(currentSelection.exclude, trackedItems, _isEqual),
});
}
}
else {
if (selectorValue === SelectionType.All) {
return new SelectionModel({
include: _unionWith(currentSelection.include, trackedItems, _isEqual),
});
}
if (selectorValue === SelectionType.UnselectAll) {
return new SelectionModel({
include: _differenceWith(currentSelection.include, trackedItems, _isEqual),
});
}
}
return new SelectionModel();
}
/**
* You may need to obtain the set of items that are selected given selection object and some set of items.
* @param {ISelection} selection
* @param {any[]} items
* @param comparator
* @returns {any[]} Set of items
*/
getSelectedItems(selection, items, comparator = _isEqual) {
if (selection.isAllPages) {
return _differenceWith(items, selection.exclude, comparator);
}
else {
return _intersectionWith(items, selection.include, comparator);
}
}
/**
* Allows to react on changes of selected items (for selector).
* If user selects some items directly in a list, selector state may change
* @param {ISelection} currentSelection
* @param {number} totalOnCurrentPage
* @param {number} selectedOnCurrentPage
* @param totalItems
* @param selectedOnAllPages
* @param {boolean} virtualScroll Enables virtual scroll selection behavior
* @returns {ISelectorState}
*/
getSelectorState(currentSelection, totalOnCurrentPage, selectedOnCurrentPage, totalItems, selectedOnAllPages, virtualScroll) {
// Note: short cutting the flow in case we're preforming the selection in
// virtual scroll mode where we can't have options for selection, just select all and unselect all
if (virtualScroll) {
// Note: In case user manually selected all the items we should set the Checked state
if (selectedOnAllPages === totalItems) {
return {
checkboxStatus: CheckboxStatus.Checked,
selectorItems: [],
};
}
if (currentSelection.isAllPages) {
return {
// Note: In case master checkbox is in the checked state we should ensure
// that we don't have any excluded items to prevent displaying Checked state
checkboxStatus: currentSelection.exclude.length
? CheckboxStatus.Indeterminate
: CheckboxStatus.Checked,
selectorItems: [],
};
}
else {
return {
// Note: In case master checkbox is in the unchecked state we should ensure
// that we don't have any included items to prevent displaying Unchecked state
checkboxStatus: currentSelection.include.length
? CheckboxStatus.Indeterminate
: CheckboxStatus.Unchecked,
selectorItems: [],
};
}
}
if (selectedOnCurrentPage === 0) {
if (totalOnCurrentPage === totalItems) {
return {
checkboxStatus: CheckboxStatus.Unchecked,
selectorItems: this.getFlatSelectorItems([
SelectionType.All,
]),
};
}
if (selectedOnAllPages && selectedOnAllPages > 0) {
return {
checkboxStatus: CheckboxStatus.Unchecked,
selectorItems: this.getFlatSelectorItems([
SelectionType.All,
SelectionType.AllPages,
SelectionType.None,
]),
};
}
return {
checkboxStatus: CheckboxStatus.Unchecked,
selectorItems: this.getFlatSelectorItems([
SelectionType.AllPages,
SelectionType.All,
]),
};
}
// case when we have only one page. Clarified with UX team that when we have one page we need to have SelectionType.All
if (selectedOnCurrentPage < totalOnCurrentPage &&
totalOnCurrentPage === totalItems) {
return {
checkboxStatus: CheckboxStatus.Indeterminate,
selectorItems: this.getFlatSelectorItems([
SelectionType.All,
SelectionType.None,
]),
};
}
if (selectedOnCurrentPage === totalOnCurrentPage) {
return {
checkboxStatus: CheckboxStatus.Checked,
selectorItems: currentSelection.isAllPages &&
currentSelection.exclude.length === 0
? this.getFlatSelectorItems([SelectionType.None])
: this.getFlatSelectorItems([
SelectionType.AllPages,
SelectionType.None,
]),
};
}
return {
checkboxStatus: CheckboxStatus.Indeterminate,
selectorItems: this.getFlatSelectorItems([
SelectionType.All,
SelectionType.AllPages,
SelectionType.None,
]),
};
}
/**
* Allows to react on selection.
* @param {ISelection} prevSelection Previous selection
* @param {any[]} selectedItems Selected items on the current page
* @param {any[]} items Items on the current page
* @param {RepeatSelectionMode} selectionMode One of possible repeater selection modes
* @param {number} totalItems Deprecated in v9 - Unused - Removal: NUI-5809
* @returns {ISelection} New selection
*/
selectItems(prevSelection, selectedItems, items, selectionMode, totalItems) {
if (!_isUndefined(totalItems)) {
this.logger?.warn("'totalItems' parameter of SelectorService.selectItems is unused and deprecated. As of Nova v9, this \
argument may be omitted. Removal: NUI-5896");
}
if (selectionMode === RepeatSelectionMode.radio ||
selectionMode === RepeatSelectionMode.single ||
selectionMode ===
RepeatSelectionMode.radioWithNonRequiredSelection ||
selectionMode === RepeatSelectionMode.singleWithRequiredSelection) {
return new SelectionModel({ include: selectedItems });
}
// This is just common sense: if selection mode can be dynamically changed this may be useful
if (selectionMode === RepeatSelectionMode.none) {
return new SelectionModel();
}
const includedItems = this.getIncludedItems(prevSelection, items, selectedItems);
if (prevSelection.isAllPages) {
return new SelectionModel({
isAllPages: prevSelection.isAllPages,
exclude: this.getExcludedItems(prevSelection, items, selectedItems),
});
}
return new SelectionModel({
isAllPages: prevSelection.isAllPages,
include: includedItems,
});
}
// items are all items in current repeater
getIncludedItems(prevSelection, items, selectedItems) {
const unselectedItems = _differenceWith(items, selectedItems, _isEqual);
const includedItems = _reject(prevSelection.include, (includedItem) => unselectedItems.some((unselectedItem) => _isEqual(includedItem, unselectedItem)));
return _unionWith(includedItems, selectedItems, _isEqual);
}
getExcludedItems(prevSelection, items, selectedItems) {
const excludedItems = _reject(prevSelection.exclude, (excludedItem) => selectedItems.some((item) => _isEqual(excludedItem, item)));
const unselectedItemsOnPage = _differenceWith(items, selectedItems, _isEqual);
return unselectedItemsOnPage.reduce((memo, item) => {
const isItemExcluded = excludedItems.some((excludedItem) => _isEqual(excludedItem, item));
if (!isItemExcluded) {
memo.push(item);
}
return memo;
}, excludedItems);
}
getFlatSelectorItems(arr) {
return [
{
itemsSource: arr.map((element) => ({
value: element,
title: this.i18nTitleMap[element],
})),
},
];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectorService, deps: [{ token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectorService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectorService, decorators: [{
type: Injectable,
args: [{ providedIn: "root" }]
}], ctorParameters: () => [{ type: i1.LoggerService, decorators: [{
type: Optional
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0b3Iuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc2VsZWN0b3Ivc2VsZWN0b3Iuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQW1CLE1BQU0sZUFBZSxDQUFDO0FBQ3RFLE9BQU8sZUFBZSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8saUJBQWlCLE1BQU0seUJBQXlCLENBQUM7QUFDeEQsT0FBTyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxZQUFZLE1BQU0sb0JBQW9CLENBQUM7QUFDOUMsT0FBTyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3BDLE9BQU8sVUFBVSxNQUFNLGtCQUFrQixDQUFDO0FBRTFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMzRCxPQUFPLEVBR0gsY0FBYyxHQUNqQixNQUFNLDJCQUEyQixDQUFDO0FBRW5DLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7QUFFdEQ7O0dBRUc7QUFFSCxNQUFNLE9BQU8sZUFBZTtJQU14QixZQUFnQyxNQUFzQjtRQUF0QixXQUFNLEdBQU4sTUFBTSxDQUFnQjtRQUx0RDs7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YSxFQUNiLFFBQVEsQ0FDWCxDQUFDO1FBRUYsT0FBTyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDL0MsTUFBTSxjQUFjLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQ3ZELFFBQVEsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLENBQy9CLENBQUM7WUFDRixJQUFJLENBQUMsY0FBYyxFQUFFO2dCQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQ25CO1lBQ0QsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFTyxvQkFBb0IsQ0FBQyxHQUFvQjtRQUM3QyxPQUFPO1lBQ0g7Z0JBQ0ksV0FBVyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFzQixFQUFFLEVBQUUsQ0FBQyxDQUFDO29CQUM5QyxLQUFLLEVBQUUsT0FBTztvQkFDZCxLQUFLLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7aUJBQ3BDLENBQUMsQ0FBQzthQUNOO1NBQ0osQ0FBQztJQUNOLENBQUM7K0dBM1ZRLGVBQWU7bUhBQWYsZUFBZSxjQURGLE1BQU07OzRGQUNuQixlQUFlO2tCQUQzQixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7MEJBT2pCLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSwgT3B0aW9uYWwsIFRyYWNrQnlGdW5jdGlvbiB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgX2RpZmZlcmVuY2VXaXRoIGZyb20gXCJsb2Rhc2gvZGlmZmVyZW5jZVdpdGhcIjtcbmltcG9ydCBfaW50ZXJzZWN0aW9uV2l0aCBmcm9tIFwibG9kYXNoL2ludGVyc2VjdGlvbldpdGhcIjtcbmltcG9ydCBfaXNFcXVhbCBmcm9tIFwibG9kYXNoL2lzRXF1YWxcIjtcbmltcG9ydCBfaXNVbmRlZmluZWQgZnJvbSBcImxvZGFzaC9pc1VuZGVmaW5lZFwiO1xuaW1wb3J0IF9yZWplY3QgZnJvbSBcImxvZGFzaC9yZWplY3RcIjtcbmltcG9ydCBfdW5pb25XaXRoIGZyb20gXCJsb2Rhc2gvdW5pb25XaXRoXCI7XG5cbmltcG9ydCB7IENoZWNrYm94U3RhdHVzLCBTZWxlY3Rpb25UeXBlIH0gZnJvbSBcIi4vcHVibGljLWFwaVwiO1xuaW1wb3J0IHsgTG9nZ2VyU2VydmljZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9sb2ctc2VydmljZVwiO1xuaW1wb3J0IHtcbiAgICBJU2VsZWN0aW9uLFxuICAgIElTZWxlY3RvclN0YXRlLFxuICAgIFNlbGVjdGlvbk1vZGVsLFxufSBmcm9tIFwiLi4vLi4vc2VydmljZXMvcHVibGljLWFwaVwiO1xuaW1wb3J0IHsgSU1lbnVHcm91cCB9IGZyb20gXCIuLi9tZW51L3B1YmxpYy1hcGlcIjtcbmltcG9ydCB7IFJlcGVhdFNlbGVjdGlvbk1vZGUgfSBmcm9tIFwiLi4vcmVwZWF0L3R5cGVzXCI7XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46IFwicm9vdFwiIH0pXG5leHBvcnQgY2xhc3MgU2VsZWN0b3JTZXJ2aWNlIHtcbiAgICAvKipcbiAgICAgKiBNYXAgaWYgU2VsZWN0aW9uVHlwZSB0byBpbnRlcm5hdGlvbmFsaXplZCBzZWxlY3RvciBvcHRpb25zXG4gICAgICovXG4gICAgcHVibGljIGkxOG5UaXRsZU1hcDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gICAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgcHJpdmF0ZSBsb2dnZXI/OiBMb2dnZXJTZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMuaTE4blRpdGxlTWFwW1xuICAgICAgICAgICAgU2VsZWN0aW9uVHlwZS5BbGxcbiAgICAgICAgXSA9ICRsb2NhbGl6ZWBTZWxlY3QgYWxsIGl0ZW1zIG9uIHRoaXMgcGFnZWA7XG4gICAgICAgIHRoaXMuaTE4blRpdGxlTWFwW1xuICAgICAgICAgICAgU2VsZWN0aW9uVHlwZS5BbGxQYWdlc1xuICAgICAgICBdID0gJGxvY2FsaXplYFNlbGVjdCBhbGwgaXRlbXMgb24gYWxsIHBhZ2VzYDtcbiAgICAgICAgdGhpcy5pMThuVGl0bGVNYXBbU2VsZWN0aW9uVHlwZS5Ob25lXSA9ICRsb2NhbGl6ZWBVbnNlbGVjdCBhbGwgaXRlbXNgO1xuICAgICAgICB0aGlzLmkxOG5UaXRsZU1hcFtcbiAgICAgICAgICAgIFNlbGVjdGlvblR5cGUuVW5zZWxlY3RBbGxcbiAgICAgICAgXSA9ICRsb2NhbGl6ZWBVbnNlbGVjdCBhbGwgaXRlbXMgb24gdGhpcyBwYWdlYDtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiB0aGluayBhYm91dCBhbiBhYmlsaXR5IHRvIHByb3ZpZGUgaXNFcXVhbCBmdW5jdGlvbiBmcm9tIG91dHNpZGVcblxuICAgIC8qKlxuICAgICAqIEFsbG93cyB0byByZWFjdCBvbiBjaGFuZ2VzIG9mIGEgc2VsZWN0b3IgY29tcG9uZW50LlxuICAgICAqIElmIHVzZXIgaGFzIHNlbGVjdGVkIG9uZSBvZiB0aGUgb3B0aW9ucyBpbiBhIHNlbGVjdG9yIChTZWxlY3QgYWxsIGl0ZW1zIHBhZ2VzLCBTZWxlY3QgYWxsIGl0ZW1zIG9uIGFsbCBwYWdlcyksXG4gICAgICogdGhlIG5ldyBzZWxlY3Rpb24gb2JqZWN0IHNob3VsZCBiZSBjcmVhdGVkLlxuICAgICAqIEBwYXJhbSB7SVNlbGVjdGlvbn0gY3VycmVudFNlbGVjdGlvblxuICAgICAqIEBwYXJhbSB7YW55W119IGN1cnJlbnRJdGVtcyBJdGVtcyBvbiBjdXJyZW50IHBhZ2VcbiAgICAgKiBAcGFyYW0ge1NlbGVjdGlvblR5cGV9IHNlbGVjdG9yVmFsdWVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdG90YWxJdGVtc1xuICAgICAqIEBwYXJhbSB0cmFja0J5XG4gICAgICogQHBhcmFtIHtib29sZWFufSB2aXJ0dWFsU2Nyb2xsIEVuYWJsZXMgdmlydHVhbCBzY3JvbGwgc2VsZWN0aW9uIGJlaGF2aW9yXG4gICAgICogQHJldHVybnMge0lTZWxlY3Rpb259IE5ldyBzZWxlY3Rpb24gb2JqZWN0XG4gICAgICovXG4gICAgcHVibGljIGFwcGx5U2VsZWN0b3IoXG4gICAgICAgIGN1cnJlbnRTZWxlY3Rpb246IElTZWxlY3Rpb24sXG4gICAgICAgIGN1cnJlbnRJdGVtczogYW55W10sXG4gICAgICAgIHNlbGVjdG9yVmFsdWU6IFNlbGVjdGlvblR5cGUsXG4gICAgICAgIHRvdGFsSXRlbXM6IG51bWJlcixcbiAgICAgICAgdHJhY2tCeTogVHJhY2tCeUZ1bmN0aW9uPGFueT4gPSAoaSwgZCkgPT4gZCxcbiAgICAgICAgdmlydHVhbFNjcm9sbD86IGJvb2xlYW5cbiAgICApOiBJU2VsZWN0aW9uIHtcbiAgICAgICAgaWYgKHZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBzZWxlY3RvclZhbHVlID09PSBTZWxlY3Rpb25UeXBlLkFsbFBhZ2VzIHx8XG4gICAgICAgICAgICAgICAgc2VsZWN0b3JWYWx1ZSA9PT0gU2VsZWN0aW9uVHlwZS5BbGxcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoeyBpc0FsbFBhZ2VzOiB0cnVlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBTZWxlY3Rpb25Nb2RlbCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGVjdG9yVmFsdWUgPT09IFNlbGVjdGlvblR5cGUuQWxsUGFnZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoeyBpc0FsbFBhZ2VzOiB0cnVlIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdHJhY2tlZEl0ZW1zID0gY3VycmVudEl0ZW1zLm1hcCgodmFsdWUsIGluZGV4KSA9PlxuICAgICAgICAgICAgdHJhY2tCeShpbmRleCwgdmFsdWUpXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjdXJyZW50U2VsZWN0aW9uLmlzQWxsUGFnZXMpIHtcbiAgICAgICAgICAgIGlmIChzZWxlY3RvclZhbHVlID09PSBTZWxlY3Rpb25UeXBlLkFsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoe1xuICAgICAgICAgICAgICAgICAgICBpc0FsbFBhZ2VzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBleGNsdWRlOiBfZGlmZmVyZW5jZVdpdGgoXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2VsZWN0aW9uLmV4Y2x1ZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFja2VkSXRlbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBfaXNFcXVhbFxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc2VsZWN0b3JWYWx1ZSA9PT0gU2VsZWN0aW9uVHlwZS5VbnNlbGVjdEFsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoe1xuICAgICAgICAgICAgICAgICAgICBpc0FsbFBhZ2VzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBleGNsdWRlOiBfdW5pb25XaXRoKFxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNlbGVjdGlvbi5leGNsdWRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2tlZEl0ZW1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgX2lzRXF1YWxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChzZWxlY3RvclZhbHVlID09PSBTZWxlY3Rpb25UeXBlLkFsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoe1xuICAgICAgICAgICAgICAgICAgICBpbmNsdWRlOiBfdW5pb25XaXRoKFxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNlbGVjdGlvbi5pbmNsdWRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2tlZEl0ZW1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgX2lzRXF1YWxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNlbGVjdG9yVmFsdWUgPT09IFNlbGVjdGlvblR5cGUuVW5zZWxlY3RBbGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNlbGVjdGlvbk1vZGVsKHtcbiAgICAgICAgICAgICAgICAgICAgaW5jbHVkZTogX2RpZmZlcmVuY2VXaXRoKFxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFNlbGVjdGlvbi5pbmNsdWRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2tlZEl0ZW1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgX2lzRXF1YWxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBZb3UgbWF5IG5lZWQgdG8gb2J0YWluIHRoZSBzZXQgb2YgaXRlbXMgdGhhdCBhcmUgc2VsZWN0ZWQgZ2l2ZW4gc2VsZWN0aW9uIG9iamVjdCBhbmQgc29tZSBzZXQgb2YgaXRlbXMuXG4gICAgICogQHBhcmFtIHtJU2VsZWN0aW9ufSBzZWxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtc1xuICAgICAqIEBwYXJhbSBjb21wYXJhdG9yXG4gICAgICogQHJldHVybnMge2FueVtdfSBTZXQgb2YgaXRlbXNcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U2VsZWN0ZWRJdGVtcyhzZWxlY3Rpb246IElTZWxlY3Rpb24sIGl0ZW1zOiBhbnlbXSwgY29tcGFyYXRvcjogKGE6IGFueSwgYjogYW55KSA9PiBib29sZWFuID0gX2lzRXF1YWwpOiBhbnlbXSB7XG4gICAgICAgIGlmIChzZWxlY3Rpb24uaXNBbGxQYWdlcykge1xuICAgICAgICAgICAgcmV0dXJuIF9kaWZmZXJlbmNlV2l0aChpdGVtcywgc2VsZWN0aW9uLmV4Y2x1ZGUsIGNvbXBhcmF0b3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIF9pbnRlcnNlY3Rpb25XaXRoKGl0ZW1zLCBzZWxlY3Rpb24uaW5jbHVkZSwgY29tcGFyYXRvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGxvd3MgdG8gcmVhY3Qgb24gY2hhbmdlcyBvZiBzZWxlY3RlZCBpdGVtcyAoZm9yIHNlbGVjdG9yKS5cbiAgICAgKiBJZiB1c2VyIHNlbGVjdHMgc29tZSBpdGVtcyBkaXJlY3RseSBpbiBhIGxpc3QsIHNlbGVjdG9yIHN0YXRlIG1heSBjaGFuZ2VcbiAgICAgKiBAcGFyYW0ge0lTZWxlY3Rpb259IGN1cnJlbnRTZWxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdG90YWxPbkN1cnJlbnRQYWdlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNlbGVjdGVkT25DdXJyZW50UGFnZVxuICAgICAqIEBwYXJhbSB0b3RhbEl0ZW1zXG4gICAgICogQHBhcmFtIHNlbGVjdGVkT25BbGxQYWdlc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gdmlydHVhbFNjcm9sbCBFbmFibGVzIHZpcnR1YWwgc2Nyb2xsIHNlbGVjdGlvbiBiZWhhdmlvclxuICAgICAqIEByZXR1cm5zIHtJU2VsZWN0b3JTdGF0ZX1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U2VsZWN0b3JTdGF0ZShcbiAgICAgICAgY3VycmVudFNlbGVjdGlvbjogSVNlbGVjdGlvbixcbiAgICAgICAgdG90YWxPbkN1cnJlbnRQYWdlOiBudW1iZXIsXG4gICAgICAgIHNlbGVjdGVkT25DdXJyZW50UGFnZTogbnVtYmVyLFxuICAgICAgICB0b3RhbEl0ZW1zPzogbnVtYmVyLFxuICAgICAgICBzZWxlY3RlZE9uQWxsUGFnZXM/OiBudW1iZXIsXG4gICAgICAgIHZpcnR1YWxTY3JvbGw/OiBib29sZWFuXG4gICAgKTogSVNlbGVjdG9yU3RhdGUge1xuICAgICAgICAvLyBOb3RlOiBzaG9ydCBjdXR0aW5nIHRoZSBmbG93IGluIGNhc2Ugd2UncmUgcHJlZm9ybWluZyB0aGUgc2VsZWN0aW9uIGluXG4gICAgICAgIC8vIHZpcnR1YWwgc2Nyb2xsIG1vZGUgd2hlcmUgd2UgY2FuJ3QgaGF2ZSBvcHRpb25zIGZvciBzZWxlY3Rpb24sIGp1c3Qgc2VsZWN0IGFsbCBhbmQgdW5zZWxlY3QgYWxsXG4gICAgICAgIGlmICh2aXJ0dWFsU2Nyb2xsKSB7XG4gICAgICAgICAgICAvLyBOb3RlOiBJbiBjYXNlIHVzZXIgbWFudWFsbHkgc2VsZWN0ZWQgYWxsIHRoZSBpdGVtcyB3ZSBzaG91bGQgc2V0IHRoZSBDaGVja2VkIHN0YXRlXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRPbkFsbFBhZ2VzID09PSB0b3RhbEl0ZW1zKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tib3hTdGF0dXM6IENoZWNrYm94U3RhdHVzLkNoZWNrZWQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdG9ySXRlbXM6IFtdLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjdXJyZW50U2VsZWN0aW9uLmlzQWxsUGFnZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiBJbiBjYXNlIG1hc3RlciBjaGVja2JveCBpcyBpbiB0aGUgY2hlY2tlZCBzdGF0ZSB3ZSBzaG91bGQgZW5zdXJlXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgd2UgZG9uJ3QgaGF2ZSBhbnkgZXhjbHVkZWQgaXRlbXMgdG8gcHJldmVudCBkaXNwbGF5aW5nIENoZWNrZWQgc3RhdGVcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tib3hTdGF0dXM6IGN1cnJlbnRTZWxlY3Rpb24uZXhjbHVkZS5sZW5ndGhcbiAgICAgICAgICAgICAgICAgICAgICAgID8gQ2hlY2tib3hTdGF0dXMuSW5kZXRlcm1pbmF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBDaGVja2JveFN0YXR1cy5DaGVja2VkLFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rvckl0ZW1zOiBbXSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiBJbiBjYXNlIG1hc3RlciBjaGVja2JveCBpcyBpbiB0aGUgdW5jaGVja2VkIHN0YXRlIHdlIHNob3VsZCBlbnN1cmVcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCB3ZSBkb24ndCBoYXZlIGFueSBpbmNsdWRlZCBpdGVtcyB0byBwcmV2ZW50IGRpc3BsYXlpbmcgVW5jaGVja2VkIHN0YXRlXG4gICAgICAgICAgICAgICAgICAgIGNoZWNrYm94U3RhdHVzOiBjdXJyZW50U2VsZWN0aW9uLmluY2x1ZGUubGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgICAgICA/IENoZWNrYm94U3RhdHVzLkluZGV0ZXJtaW5hdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIDogQ2hlY2tib3hTdGF0dXMuVW5jaGVja2VkLFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rvckl0ZW1zOiBbXSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkT25DdXJyZW50UGFnZSA9PT0gMCkge1xuICAgICAgICAgICAgaWYgKHRvdGFsT25DdXJyZW50UGFnZSA9PT0gdG90YWxJdGVtcykge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrYm94U3RhdHVzOiBDaGVja2JveFN0YXR1cy5VbmNoZWNrZWQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdG9ySXRlbXM6IHRoaXMuZ2V0RmxhdFNlbGVjdG9ySXRlbXMoW1xuICAgICAgICAgICAgICAgICAgICAgICAgU2VsZWN0aW9uVHlwZS5BbGwsXG4gICAgICAgICAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRPbkFsbFBhZ2VzICYmIHNlbGVjdGVkT25BbGxQYWdlcyA+IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGVja2JveFN0YXR1czogQ2hlY2tib3hTdGF0dXMuVW5jaGVja2VkLFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rvckl0ZW1zOiB0aGlzLmdldEZsYXRTZWxlY3Rvckl0ZW1zKFtcbiAgICAgICAgICAgICAgICAgICAgICAgIFNlbGVjdGlvblR5cGUuQWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgU2VsZWN0aW9uVHlwZS5BbGxQYWdlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIFNlbGVjdGlvblR5cGUuTm9uZSxcbiAgICAgICAgICAgICAgICAgICAgXSksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjaGVja2JveFN0YXR1czogQ2hlY2tib3hTdGF0dXMuVW5jaGVja2VkLFxuICAgICAgICAgICAgICAgIHNlbGVjdG9ySXRlbXM6IHRoaXMuZ2V0RmxhdFNlbGVjdG9ySXRlbXMoW1xuICAgICAgICAgICAgICAgICAgICBTZWxlY3Rpb25UeXBlLkFsbFBhZ2VzLFxuICAgICAgICAgICAgICAgICAgICBTZWxlY3Rpb25UeXBlLkFsbCxcbiAgICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2FzZSB3aGVuIHdlIGhhdmUgb25seSBvbmUgcGFnZS4gQ2xhcmlmaWVkIHdpdGggVVggdGVhbSB0aGF0IHdoZW4gd2UgaGF2ZSBvbmUgcGFnZSB3ZSBuZWVkIHRvIGhhdmUgU2VsZWN0aW9uVHlwZS5BbGxcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgc2VsZWN0ZWRPbkN1cnJlbnRQYWdlIDwgdG90YWxPbkN1cnJlbnRQYWdlICYmXG4gICAgICAgICAgICB0b3RhbE9uQ3VycmVudFBhZ2UgPT09IHRvdGFsSXRlbXNcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNoZWNrYm94U3RhdHVzOiBDaGVja2JveFN0YXR1cy5JbmRldGVybWluYXRlLFxuICAgICAgICAgICAgICAgIHNlbGVjdG9ySXRlbXM6IHRoaXMuZ2V0RmxhdFNlbGVjdG9ySXRlbXMoW1xuICAgICAgICAgICAgICAgICAgICBTZWxlY3Rpb25UeXBlLkFsbCxcbiAgICAgICAgICAgICAgICAgICAgU2VsZWN0aW9uVHlwZS5Ob25lLFxuICAgICAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZWxlY3RlZE9uQ3VycmVudFBhZ2UgPT09IHRvdGFsT25DdXJyZW50UGFnZSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjaGVja2JveFN0YXR1czogQ2hlY2tib3hTdGF0dXMuQ2hlY2tlZCxcbiAgICAgICAgICAgICAgICBzZWxlY3Rvckl0ZW1zOlxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2VsZWN0aW9uLmlzQWxsUGFnZXMgJiZcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNlbGVjdGlvbi5leGNsdWRlLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgICAgICAgICAgICAgPyB0aGlzLmdldEZsYXRTZWxlY3Rvckl0ZW1zKFtTZWxlY3Rpb25UeXBlLk5vbmVdKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiB0aGlzLmdldEZsYXRTZWxlY3Rvckl0ZW1zKFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNlbGVjdGlvblR5cGUuQWxsUGFnZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZWxlY3Rpb25UeXBlLk5vbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjaGVja2JveFN0YXR1czogQ2hlY2tib3hTdGF0dXMuSW5kZXRlcm1pbmF0ZSxcbiAgICAgICAgICAgIHNlbGVjdG9ySXRlbXM6IHRoaXMuZ2V0RmxhdFNlbGVjdG9ySXRlbXMoW1xuICAgICAgICAgICAgICAgIFNlbGVjdGlvblR5cGUuQWxsLFxuICAgICAgICAgICAgICAgIFNlbGVjdGlvblR5cGUuQWxsUGFnZXMsXG4gICAgICAgICAgICAgICAgU2VsZWN0aW9uVHlwZS5Ob25lLFxuICAgICAgICAgICAgXSksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxsb3dzIHRvIHJlYWN0IG9uIHNlbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0ge0lTZWxlY3Rpb259IHByZXZTZWxlY3Rpb24gUHJldmlvdXMgc2VsZWN0aW9uXG4gICAgICogQHBhcmFtIHthbnlbXX0gc2VsZWN0ZWRJdGVtcyBTZWxlY3RlZCBpdGVtcyBvbiB0aGUgY3VycmVudCBwYWdlXG4gICAgICogQHBhcmFtIHthbnlbXX0gaXRlbXMgSXRlbXMgb24gdGhlIGN1cnJlbnQgcGFnZVxuICAgICAqIEBwYXJhbSB7UmVwZWF0U2VsZWN0aW9uTW9kZX0gc2VsZWN0aW9uTW9kZSBPbmUgb2YgcG9zc2libGUgcmVwZWF0ZXIgc2VsZWN0aW9uIG1vZGVzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHRvdGFsSXRlbXMgRGVwcmVjYXRlZCBpbiB2OSAtIFVudXNlZCAtIFJlbW92YWw6IE5VSS01ODA5XG4gICAgICogQHJldHVybnMge0lTZWxlY3Rpb259IE5ldyBzZWxlY3Rpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgc2VsZWN0SXRlbXMoXG4gICAgICAgIHByZXZTZWxlY3Rpb246IElTZWxlY3Rpb24sXG4gICAgICAgIHNlbGVjdGVkSXRlbXM6IGFueVtdLFxuICAgICAgICBpdGVtczogYW55W10sXG4gICAgICAgIHNlbGVjdGlvbk1vZGU6IFJlcGVhdFNlbGVjdGlvbk1vZGUsXG4gICAgICAgIHRvdGFsSXRlbXM/OiBudW1iZXJcbiAgICApOiBJU2VsZWN0aW9uIHtcbiAgICAgICAgaWYgKCFfaXNVbmRlZmluZWQodG90YWxJdGVtcykpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyPy53YXJuKFxuICAgICAgICAgICAgICAgIFwiJ3RvdGFsSXRlbXMnIHBhcmFtZXRlciBvZiBTZWxlY3RvclNlcnZpY2Uuc2VsZWN0SXRlbXMgaXMgdW51c2VkIGFuZCBkZXByZWNhdGVkLiBBcyBvZiBOb3ZhIHY5LCB0aGlzIFxcXG4gICAgICAgICAgICAgICAgYXJndW1lbnQgbWF5IGJlIG9taXR0ZWQuIFJlbW92YWw6IE5VSS01ODk2XCJcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBzZWxlY3Rpb25Nb2RlID09PSBSZXBlYXRTZWxlY3Rpb25Nb2RlLnJhZGlvIHx8XG4gICAgICAgICAgICBzZWxlY3Rpb25Nb2RlID09PSBSZXBlYXRTZWxlY3Rpb25Nb2RlLnNpbmdsZSB8fFxuICAgICAgICAgICAgc2VsZWN0aW9uTW9kZSA9PT1cbiAgICAgICAgICAgICAgICBSZXBlYXRTZWxlY3Rpb25Nb2RlLnJhZGlvV2l0aE5vblJlcXVpcmVkU2VsZWN0aW9uIHx8XG4gICAgICAgICAgICBzZWxlY3Rpb25Nb2RlID09PSBSZXBlYXRTZWxlY3Rpb25Nb2RlLnNpbmdsZVdpdGhSZXF1aXJlZFNlbGVjdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoeyBpbmNsdWRlOiBzZWxlY3RlZEl0ZW1zIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhpcyBpcyBqdXN0IGNvbW1vbiBzZW5zZTogaWYgc2VsZWN0aW9uIG1vZGUgY2FuIGJlIGR5bmFtaWNhbGx5IGNoYW5nZWQgdGhpcyBtYXkgYmUgdXNlZnVsXG4gICAgICAgIGlmIChzZWxlY3Rpb25Nb2RlID09PSBSZXBlYXRTZWxlY3Rpb25Nb2RlLm5vbmUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2VsZWN0aW9uTW9kZWwoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGluY2x1ZGVkSXRlbXMgPSB0aGlzLmdldEluY2x1ZGVkSXRlbXMoXG4gICAgICAgICAgICBwcmV2U2VsZWN0aW9uLFxuICAgICAgICAgICAgaXRlbXMsXG4gICAgICAgICAgICBzZWxlY3RlZEl0ZW1zXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHByZXZTZWxlY3Rpb24uaXNBbGxQYWdlcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTZWxlY3Rpb25Nb2RlbCh7XG4gICAgICAgICAgICAgICAgaXNBbGxQYWdlczogcHJldlNlbGVjdGlvbi5pc0FsbFBhZ2VzLFxuICAgICAgICAgICAgICAgIGV4Y2x1ZGU6IHRoaXMuZ2V0RXhjbHVkZWRJdGVtcyhcbiAgICAgICAgICAgICAgICAgICAgcHJldlNlbGVjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgaXRlbXMsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkSXRlbXNcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV3IFNlbGVjdGlvbk1vZGVsKHtcbiAgICAgICAgICAgIGlzQWxsUGFnZXM6IHByZXZTZWxlY3Rpb24uaXNBbGxQYWdlcyxcbiAgICAgICAgICAgIGluY2x1ZGU6IGluY2x1ZGVkSXRlbXMsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIGl0ZW1zIGFyZSBhbGwgaXRlbXMgaW4gY3VycmVudCByZXBlYXRlclxuICAgIHByaXZhdGUgZ2V0SW5jbHVkZWRJdGVtcyhcbiAgICAgICAgcHJldlNlbGVjdGlvbjogSVNlbGVjdGlvbixcbiAgICAgICAgaXRlbXM6IGFueVtdLFxuICAgICAgICBzZWxlY3RlZEl0ZW1zOiBhbnlbXVxuICAgICk6IGFueVtdIHtcbiAgICAgICAgY29uc3QgdW5zZWxlY3RlZEl0ZW1zID0gX2RpZmZlcmVuY2VXaXRoKGl0ZW1zLCBzZWxlY3RlZEl0ZW1zLCBfaXNFcXVhbCk7XG4gICAgICAgIGNvbnN0IGluY2x1ZGVkSXRlbXMgPSBfcmVqZWN0KHByZXZTZWxlY3Rpb24uaW5jbHVkZSwgKGluY2x1ZGVkSXRlbSkgPT5cbiAgICAgICAgICAgIHVuc2VsZWN0ZWRJdGVtcy5zb21lKCh1bnNlbGVjdGVkSXRlbSkgPT5cbiAgICAgICAgICAgICAgICBfaXNFcXVhbChpbmNsdWRlZEl0ZW0sIHVuc2VsZWN0ZWRJdGVtKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gX3VuaW9uV2l0aChpbmNsdWRlZEl0ZW1zLCBzZWxlY3RlZEl0ZW1zLCBfaXNFcXVhbCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRFeGNsdWRlZEl0ZW1zKFxuICAgICAgICBwcmV2U2VsZWN0aW9uOiBJU2VsZWN0aW9uLFxuICAgICAgICBpdGVtczogYW55W10sXG4gICAgICAgIHNlbGVjdGVkSXRlbXM6IGFueVtdXG4gICAgKTogYW55W10ge1xuICAgICAgICBjb25zdCBleGNsdWRlZEl0ZW1zID0gX3JlamVjdChwcmV2U2VsZWN0aW9uLmV4Y2x1ZGUsIChleGNsdWRlZEl0ZW0pID0+XG4gICAgICAgICAgICBzZWxlY3RlZEl0ZW1zLnNvbWUoKGl0ZW0pID0+IF9pc0VxdWFsKGV4Y2x1ZGVkSXRlbSwgaXRlbSkpXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHVuc2VsZWN0ZWRJdGVtc09uUGFnZSA9IF9kaWZmZXJlbmNlV2l0aChcbiAgICAgICAgICAgIGl0ZW1zLFxuICAgICAgICAgICAgc2VsZWN0ZWRJdGVtcyxcbiAgICAgICAgICAgIF9pc0VxdWFsXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHVuc2VsZWN0ZWRJdGVtc09uUGFnZS5yZWR1Y2UoKG1lbW8sIGl0ZW0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGlzSXRlbUV4Y2x1ZGVkID0gZXhjbHVkZWRJdGVtcy5zb21lKChleGNsdWRlZEl0ZW0pID0+XG4gICAgICAgICAgICAgICAgX2lzRXF1YWwoZXhjbHVkZWRJdGVtLCBpdGVtKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmICghaXNJdGVtRXhjbHVkZWQpIHtcbiAgICAgICAgICAgICAgICBtZW1vLnB1c2goaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgICAgfSwgZXhjbHVkZWRJdGVtcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRGbGF0U2VsZWN0b3JJdGVtcyhhcnI6IFNlbGVjdGlvblR5cGVbXSk6IElNZW51R3JvdXBbXSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaXRlbXNTb3VyY2U6IGFyci5tYXAoKGVsZW1lbnQ6IFNlbGVjdGlvblR5cGUpID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICB0aXRsZTogdGhpcy5pMThuVGl0bGVNYXBbZWxlbWVudF0sXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXTtcbiAgICB9XG59XG4iXX0=