@nova-ui/bits
Version:
SolarWinds Nova Framework
250 lines • 40.5 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 } from "@angular/core";
import _forEach from "lodash/forEach";
import _get from "lodash/get";
import _intersection from "lodash/intersection";
import _isEqual from "lodash/isEqual";
import _orderBy from "lodash/orderBy";
import { DataSourceService } from "./data-source.service";
import { SorterDirection } from "../../lib/sorter/public-api";
import { SearchService } from "../search.service";
import * as i0 from "@angular/core";
import * as i1 from "../search.service";
/**
* <example-url>./../examples/index.html#/common/data-source-service/deprecated-client-side</example-url>
* @deprecated in v11 - use ClientSideDataSource instead - Removal: NUI-5796
*/
export class LocalFilteringDataSource extends DataSourceService {
constructor(searchService) {
super();
this.searchService = searchService;
this._allCategoriesResult = {};
this._searchProps = [];
// cache used to store our previous fetched results while scrolling
// and more data is automatically fetched from the backend
this.virtualScrollData = [];
}
setData(initialData = []) {
this._allData = initialData;
}
setSearchProperties(properties) {
this._searchProps = properties;
}
async getFilteredData(filters) {
let nextChunk = this.prepareData();
// APPLY SEARCH USING CHECKBOX VALUES
const searchTerm = filters?.search?.value;
// APPLY SEARCH
if (searchTerm) {
nextChunk = this.searchHandler(searchTerm);
}
const multiFiltersArr = this.extractMultiFilters(filters);
// APPLY FILTERS with type 'string[]' if any
if (multiFiltersArr?.length) {
nextChunk = this.multiFilterHandler(nextChunk, multiFiltersArr);
}
const numberOfItems = nextChunk.length;
// RESET PAGINATION if needed
const filtersChanged = this.filtersChanged(filters, this.setItemsToCompare(filters, nextChunk, searchTerm, multiFiltersArr));
if (filtersChanged) {
if (filters?.paginator) {
const size = filters.paginator.value.end - filters.paginator.value.start;
filters.paginator.value.start = 0;
filters.paginator.value.end = size;
}
if (filters.virtualScroll) {
// reset virtual scroll items
this.virtualScrollData = [];
}
}
nextChunk = this.sortingHandler(filters, nextChunk);
nextChunk = this.paginationHandler(filters, nextChunk);
nextChunk = this.virtualScrollHandler(filters, nextChunk);
return {
repeat: {
itemsSource: nextChunk,
},
paginator: {
total: numberOfItems,
reset: filtersChanged,
},
...this._allCategoriesResult,
};
}
prepareData() {
return this._allData;
}
searchHandler(searchTerm) {
return this.searchService.search(this._allData, this._searchProps, searchTerm);
}
multiFilterHandler(nextChunk, multiFiltersArr) {
const allCategoriesArr = multiFiltersArr.map((el) => this.getAllCategories(el));
if (multiFiltersArr.length) {
const filteredResult = this.searchThru(multiFiltersArr, nextChunk);
const selectedFilters = this.getSelectedFilters(multiFiltersArr);
// if some filters selected and filter result = 0, returning empty array
if (filteredResult.length || selectedFilters.length) {
nextChunk = _intersection(...filteredResult);
}
}
// count number of occurrences of every item
this._allCategoriesResult = this.countAvailableResults(allCategoriesArr, nextChunk);
return nextChunk;
}
sortingHandler(filters, nextChunk) {
if (_get(filters, "sorter.value.sortBy") &&
_get(filters, "sorter.value.direction")) {
// Original direction means that sorting is not needed
if (filters.sorter.value.direction !== SorterDirection.original) {
return _orderBy(nextChunk, filters.sorter.value.sortBy, filters.sorter.value.direction);
}
}
return nextChunk;
}
paginationHandler(filters, nextChunk) {
if (filters?.paginator) {
return nextChunk.slice(filters.paginator.value.start, filters.paginator.value.end);
}
return nextChunk;
}
virtualScrollHandler(filters, nextChunk) {
let data = nextChunk;
if (filters?.virtualScroll) {
data = nextChunk.slice(filters.virtualScroll.value.start, filters.virtualScroll.value.end);
// for virtual scroll we must always append current chunk to the previous ones
data = this.virtualScrollData = this.virtualScrollData.concat(data);
}
return data;
}
/**
* @deprecated in v11 - Use filtersChanged instead - Removal: NUI-5796
*/
paginationReset(filters, itemsToCompare) {
return this.filtersChanged(filters, itemsToCompare);
}
filtersChanged(filters, itemsToCompare) {
if (this._previousFilters) {
if (this.isValueChanged(itemsToCompare)) {
return true;
}
}
return false;
}
setItemsToCompare(filters, nextChunk, searchTerm, multiFiltersArr) {
// GET FILTERS from previous filtering
const previousSortBy = _get(this._previousFilters, "sorter.value.sortBy");
const previousDirection = _get(this._previousFilters, "sorter.value.direction");
const previousSearchTerm = _get(this._previousFilters, "search.value");
const previousMultiFiltersArr = this.extractMultiFilters(this._previousFilters);
const sortBy = _get(filters, "sorter.value.sortBy");
const direction = _get(filters, "sorter.value.direction");
const itemsToCompare = [];
itemsToCompare.push({
previousValue: previousSortBy,
currentValue: sortBy,
});
itemsToCompare.push({
previousValue: previousDirection,
currentValue: direction,
});
itemsToCompare.push({
previousValue: previousSearchTerm,
currentValue: searchTerm,
});
itemsToCompare.push({
previousValue: previousMultiFiltersArr,
currentValue: multiFiltersArr,
});
return itemsToCompare;
}
extractMultiFilters(filters) {
const multiFilterArr = [];
_forEach(filters, (value, key) => {
if (value?.type === "string[]") {
multiFilterArr.push({ [key]: value });
}
});
return multiFilterArr;
}
getSelectedFilters(multiFiltersArr) {
return multiFiltersArr.reduce((prev, curr) => prev.concat(curr[Object.keys(curr)[0]].value), []);
}
countAvailableResults(allCategoriesArr, nextChunk) {
const allCategoriesResult = allCategoriesArr.map((el, index) => {
const key = Object.keys(el)[0];
const valuesArr = allCategoriesArr[index][key];
const resultArr = valuesArr.map((element) => {
const r = this.searchService.search(nextChunk, [key], element);
return { [element]: r.length };
});
return { [key]: resultArr };
});
return (allCategoriesResult
// convert array to an object
.reduce((prev, curr) => {
const [prop] = Object.keys(curr);
// convert array to an object
const newObj = curr[prop].reduce((previous, current) => {
const [property] = Object.keys(current);
previous[property] = current[property];
return previous;
}, {});
prev[prop] = newObj;
return prev;
}, {}));
}
searchThru(arrToMap, arrToSearchIn) {
// We are filtering out filter groups which doesn't have selected filters. If filters are not present,
// it means that filtered data with this filters should not participate in intersection
return arrToMap
.filter((arr) => !!arr[Object.keys(arr)[0]].value.length)
.map((multiFilter) => {
const [prop] = Object.keys(multiFilter);
return (multiFilter[prop].value // extract value array
// find matches
.map((el) => this.searchService.search(arrToSearchIn, [prop], el))
// flatten returned multidimensional arrays
.reduce((prev, curr) => prev.concat(curr), []));
});
}
getAllCategories(multiFilter) {
if (!multiFilter) {
return;
}
const [prop] = Object.keys(multiFilter);
const { metadata } = multiFilter[prop];
return { [prop]: metadata?.allCategories };
}
isValueChanged(valuesArr) {
for (const { previousValue, currentValue } of valuesArr) {
if (!_isEqual(previousValue, currentValue)) {
return true;
}
}
return false;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LocalFilteringDataSource, deps: [{ token: i1.SearchService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LocalFilteringDataSource }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LocalFilteringDataSource, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.SearchService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwtZmlsdGVyaW5nLWRhdGEtc291cmNlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvZGF0YS1zb3VyY2UvbG9jYWwtZmlsdGVyaW5nLWRhdGEtc291cmNlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxJQUFJLE1BQU0sWUFBWSxDQUFDO0FBQzlCLE9BQU8sYUFBYSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hELE9BQU8sUUFBUSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RDLE9BQU8sUUFBUSxNQUFNLGdCQUFnQixDQUFDO0FBRXRDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBVTFELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7OztBQVFsRDs7O0dBR0c7QUFFSCxNQUFNLE9BQU8sd0JBR1gsU0FBUSxpQkFBdUI7SUFTN0IsWUFBc0IsYUFBNEI7UUFDOUMsS0FBSyxFQUFFLENBQUM7UUFEVSxrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQVB4Qyx5QkFBb0IsR0FBc0IsRUFBRSxD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O2dCQUMxQyxlQUFlO2lCQUNkLEdBQUcsQ0FBQyxDQUFDLEVBQVUsRUFBRSxFQUFFLENBQ2hCLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUNyQixhQUFhLEVBQ2IsQ0FBQyxJQUFJLENBQUMsRUFDTixFQUFFLENBQ0wsQ0FDSjtnQkFDRCwyQ0FBMkM7aUJBQzFDLE1BQU0sQ0FDSCxDQUFDLElBQVMsRUFBRSxJQUFTLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQzNDLEVBQUUsQ0FDTCxDQUNSLENBQUM7UUFDTixDQUFDLENBQ0osQ0FBQztJQUNWLENBQUM7SUFFTyxnQkFBZ0IsQ0FDcEIsV0FBa0U7UUFFbEUsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNkLE9BQU87U0FDVjtRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FDZCxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEIsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxDQUFDO0lBQy9DLENBQUM7SUFFTyxjQUFjLENBQUMsU0FBNEI7UUFDL0MsS0FBSyxNQUFNLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxJQUFJLFNBQVMsRUFBRTtZQUNyRCxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsRUFBRTtnQkFDeEMsT0FBTyxJQUFJLENBQUM7YUFDZjtTQUNKO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQzsrR0FsVlEsd0JBQXdCO21IQUF4Qix3QkFBd0I7OzRGQUF4Qix3QkFBd0I7a0JBRHBDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgX2ZvckVhY2ggZnJvbSBcImxvZGFzaC9mb3JFYWNoXCI7XG5pbXBvcnQgX2dldCBmcm9tIFwibG9kYXNoL2dldFwiO1xuaW1wb3J0IF9pbnRlcnNlY3Rpb24gZnJvbSBcImxvZGFzaC9pbnRlcnNlY3Rpb25cIjtcbmltcG9ydCBfaXNFcXVhbCBmcm9tIFwibG9kYXNoL2lzRXF1YWxcIjtcbmltcG9ydCBfb3JkZXJCeSBmcm9tIFwibG9kYXNoL29yZGVyQnlcIjtcblxuaW1wb3J0IHsgRGF0YVNvdXJjZVNlcnZpY2UgfSBmcm9tIFwiLi9kYXRhLXNvdXJjZS5zZXJ2aWNlXCI7XG5pbXBvcnQge1xuICAgIElGaWx0ZXIsXG4gICAgSUZpbHRlckdyb3VwLFxuICAgIElGaWx0ZXJpbmdPdXRwdXRzLFxuICAgIElGaWx0ZXJJdGVtLFxuICAgIElNdWx0aUZpbHRlck1ldGFkYXRhLFxuICAgIElOb3ZhRmlsdGVyaW5nT3V0cHV0cyxcbiAgICBJTm92YUZpbHRlcnMsXG59IGZyb20gXCIuL3B1YmxpYy1hcGlcIjtcbmltcG9ydCB7IFNvcnRlckRpcmVjdGlvbiB9IGZyb20gXCIuLi8uLi9saWIvc29ydGVyL3B1YmxpYy1hcGlcIjtcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tIFwiLi4vc2VhcmNoLnNlcnZpY2VcIjtcblxuLyoqIEBpZ25vcmUgKi9cbmludGVyZmFjZSBDb21wYXJpc29uSXRlbXMge1xuICAgIHByZXZpb3VzVmFsdWU6IGFueTtcbiAgICBjdXJyZW50VmFsdWU6IGFueTtcbn1cblxuLyoqXG4gKiA8ZXhhbXBsZS11cmw+Li8uLi9leGFtcGxlcy9pbmRleC5odG1sIy9jb21tb24vZGF0YS1zb3VyY2Utc2VydmljZS9kZXByZWNhdGVkLWNsaWVudC1zaWRlPC9leGFtcGxlLXVybD5cbiAqIEBkZXByZWNhdGVkIGluIHYxMSAtIHVzZSBDbGllbnRTaWRlRGF0YVNvdXJjZSBpbnN0ZWFkIC0gUmVtb3ZhbDogTlVJLTU3OTZcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIExvY2FsRmlsdGVyaW5nRGF0YVNvdXJjZTxcbiAgICBULFxuICAgIEYgZXh0ZW5kcyBJTm92YUZpbHRlcnMgPSBJTm92YUZpbHRlcnNcbj4gZXh0ZW5kcyBEYXRhU291cmNlU2VydmljZTxULCBGPiB7XG4gICAgcHJvdGVjdGVkIF9hbGxEYXRhOiBUW107XG4gICAgcHJvdGVjdGVkIF9hbGxDYXRlZ29yaWVzUmVzdWx0OiBJRmlsdGVyaW5nT3V0cHV0cyA9IHt9O1xuICAgIHByb3RlY3RlZCBfc2VhcmNoUHJvcHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAvLyBjYWNoZSB1c2VkIHRvIHN0b3JlIG91ciBwcmV2aW91cyBmZXRjaGVkIHJlc3VsdHMgd2hpbGUgc2Nyb2xsaW5nXG4gICAgLy8gYW5kIG1vcmUgZGF0YSBpcyBhdXRvbWF0aWNhbGx5IGZldGNoZWQgZnJvbSB0aGUgYmFja2VuZFxuICAgIHByb3RlY3RlZCB2aXJ0dWFsU2Nyb2xsRGF0YTogVFtdID0gW107XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgc2VhcmNoU2VydmljZTogU2VhcmNoU2VydmljZSkge1xuICAgICAgICBzdXBlcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXREYXRhKGluaXRpYWxEYXRhOiBUW10gPSBbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLl9hbGxEYXRhID0gaW5pdGlhbERhdGE7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFNlYXJjaFByb3BlcnRpZXMocHJvcGVydGllczogc3RyaW5nW10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fc2VhcmNoUHJvcHMgPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRGaWx0ZXJlZERhdGEoZmlsdGVyczogRik6IFByb21pc2U8SU5vdmFGaWx0ZXJpbmdPdXRwdXRzPiB7XG4gICAgICAgIGxldCBuZXh0Q2h1bms6IFRbXSA9IHRoaXMucHJlcGFyZURhdGEoKTtcblxuICAgICAgICAvLyBBUFBMWSBTRUFSQ0ggVVNJTkcgQ0hFQ0tCT1ggVkFMVUVTXG4gICAgICAgIGNvbnN0IHNlYXJjaFRlcm06IHN0cmluZyB8IHVuZGVmaW5lZCA9IGZpbHRlcnM/LnNlYXJjaD8udmFsdWU7XG4gICAgICAgIC8vIEFQUExZIFNFQVJDSFxuICAgICAgICBpZiAoc2VhcmNoVGVybSkge1xuICAgICAgICAgICAgbmV4dENodW5rID0gdGhpcy5zZWFyY2hIYW5kbGVyKHNlYXJjaFRlcm0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbXVsdGlGaWx0ZXJzQXJyOiBJRmlsdGVyR3JvdXA8XG4gICAgICAgICAgICBJRmlsdGVyPHN0cmluZ1tdLCBJTXVsdGlGaWx0ZXJNZXRhZGF0YT5cbiAgICAgICAgPltdID0gdGhpcy5leHRyYWN0TXVsdGlGaWx0ZXJzKGZpbHRlcnMpO1xuICAgICAgICAvLyBBUFBMWSBGSUxURVJTIHdpdGggdHlwZSAnc3RyaW5nW10nIGlmIGFueVxuICAgICAgICBpZiAobXVsdGlGaWx0ZXJzQXJyPy5sZW5ndGgpIHtcbiAgICAgICAgICAgIG5leHRDaHVuayA9IHRoaXMubXVsdGlGaWx0ZXJIYW5kbGVyKG5leHRDaHVuaywgbXVsdGlGaWx0ZXJzQXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG51bWJlck9mSXRlbXMgPSBuZXh0Q2h1bmsubGVuZ3RoO1xuXG4gICAgICAgIC8vIFJFU0VUIFBBR0lOQVRJT04gaWYgbmVlZGVkXG4gICAgICAgIGNvbnN0IGZpbHRlcnNDaGFuZ2VkID0gdGhpcy5maWx0ZXJzQ2hhbmdlZChcbiAgICAgICAgICAgIGZpbHRlcnMsXG4gICAgICAgICAgICB0aGlzLnNldEl0ZW1zVG9Db21wYXJlKFxuICAgICAgICAgICAgICAgIGZpbHRlcnMsXG4gICAgICAgICAgICAgICAgbmV4dENodW5rLFxuICAgICAgICAgICAgICAgIHNlYXJjaFRlcm0sXG4gICAgICAgICAgICAgICAgbXVsdGlGaWx0ZXJzQXJyXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKGZpbHRlcnNDaGFuZ2VkKSB7XG4gICAgICAgICAgICBpZiAoZmlsdGVycz8ucGFnaW5hdG9yKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2l6ZSA9XG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcnMucGFnaW5hdG9yLnZhbHVlLmVuZCAtIGZpbHRlcnMucGFnaW5hdG9yLnZhbHVlLnN0YXJ0O1xuICAgICAgICAgICAgICAgIGZpbHRlcnMucGFnaW5hdG9yLnZhbHVlLnN0YXJ0ID0gMDtcbiAgICAgICAgICAgICAgICBmaWx0ZXJzLnBhZ2luYXRvci52YWx1ZS5lbmQgPSBzaXplO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZmlsdGVycy52aXJ0dWFsU2Nyb2xsKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVzZXQgdmlydHVhbCBzY3JvbGwgaXRlbXNcbiAgICAgICAgICAgICAgICB0aGlzLnZpcnR1YWxTY3JvbGxEYXRhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBuZXh0Q2h1bmsgPSA8VFtdPnRoaXMuc29ydGluZ0hhbmRsZXIoZmlsdGVycywgbmV4dENodW5rKTtcbiAgICAgICAgbmV4dENodW5rID0gdGhpcy5wYWdpbmF0aW9uSGFuZGxlcihmaWx0ZXJzLCBuZXh0Q2h1bmspO1xuICAgICAgICBuZXh0Q2h1bmsgPSB0aGlzLnZpcnR1YWxTY3JvbGxIYW5kbGVyKGZpbHRlcnMsIG5leHRDaHVuayk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlcGVhdDoge1xuICAgICAgICAgICAgICAgIGl0ZW1zU291cmNlOiBuZXh0Q2h1bmssXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFnaW5hdG9yOiB7XG4gICAgICAgICAgICAgICAgdG90YWw6IG51bWJlck9mSXRlbXMsXG4gICAgICAgICAgICAgICAgcmVzZXQ6IGZpbHRlcnNDaGFuZ2VkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC4uLnRoaXMuX2FsbENhdGVnb3JpZXNSZXN1bHQsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHByZXBhcmVEYXRhKCk6IFRbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hbGxEYXRhO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzZWFyY2hIYW5kbGVyKHNlYXJjaFRlcm06IGFueSk6IFRbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlYXJjaFNlcnZpY2Uuc2VhcmNoKFxuICAgICAgICAgICAgdGhpcy5fYWxsRGF0YSxcbiAgICAgICAgICAgIHRoaXMuX3NlYXJjaFByb3BzLFxuICAgICAgICAgICAgc2VhcmNoVGVybVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBtdWx0aUZpbHRlckhhbmRsZXIobmV4dENodW5rOiBUW10sIG11bHRpRmlsdGVyc0FycjogYW55KTogVFtdIHtcbiAgICAgICAgY29uc3QgYWxsQ2F0ZWdvcmllc0FycjogSUZpbHRlckl0ZW08c3RyaW5nW10+W10gPSBtdWx0aUZpbHRlcnNBcnIubWFwKFxuICAgICAgICAgICAgKGVsOiBJRmlsdGVyR3JvdXA8SUZpbHRlcjxzdHJpbmdbXSwgSU11bHRpRmlsdGVyTWV0YWRhdGE+PikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLmdldEFsbENhdGVnb3JpZXMoZWwpXG4gICAgICAgICk7XG4gICAgICAgIGlmIChtdWx0aUZpbHRlcnNBcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJlZFJlc3VsdCA9IHRoaXMuc2VhcmNoVGhydShtdWx0aUZpbHRlcnNBcnIsIG5leHRDaHVuayk7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RlZEZpbHRlcnMgPSB0aGlzLmdldFNlbGVjdGVkRmlsdGVycyhtdWx0aUZpbHRlcnNBcnIpO1xuICAgICAgICAgICAgLy8gaWYgc29tZSBmaWx0ZXJzIHNlbGVjdGVkIGFuZCBmaWx0ZXIgcmVzdWx0ID0gMCwgcmV0dXJuaW5nIGVtcHR5IGFycmF5XG4gICAgICAgICAgICBpZiAoZmlsdGVyZWRSZXN1bHQubGVuZ3RoIHx8IHNlbGVjdGVkRmlsdGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBuZXh0Q2h1bmsgPSBfaW50ZXJzZWN0aW9uKC4uLmZpbHRlcmVkUmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBjb3VudCBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgb2YgZXZlcnkgaXRlbVxuICAgICAgICB0aGlzLl9hbGxDYXRlZ29yaWVzUmVzdWx0ID0gdGhpcy5jb3VudEF2YWlsYWJsZVJlc3VsdHMoXG4gICAgICAgICAgICBhbGxDYXRlZ29yaWVzQXJyLFxuICAgICAgICAgICAgbmV4dENodW5rXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBuZXh0Q2h1bms7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNvcnRpbmdIYW5kbGVyKGZpbHRlcnM6IGFueSwgbmV4dENodW5rOiBUW10pOiBUW10ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBfZ2V0KGZpbHRlcnMsIFwic29ydGVyLnZhbHVlLnNvcnRCeVwiKSAmJlxuICAgICAgICAgICAgX2dldChmaWx0ZXJzLCBcInNvcnRlci52YWx1ZS5kaXJlY3Rpb25cIilcbiAgICAgICAgKSB7XG4gICAgICAgICAgICAvLyBPcmlnaW5hbCBkaXJlY3Rpb24gbWVhbnMgdGhhdCBzb3J0aW5nIGlzIG5vdCBuZWVkZWRcbiAgICAgICAgICAgIGlmIChmaWx0ZXJzLnNvcnRlci52YWx1ZS5kaXJlY3Rpb24gIT09IFNvcnRlckRpcmVjdGlvbi5vcmlnaW5hbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfb3JkZXJCeShcbiAgICAgICAgICAgICAgICAgICAgbmV4dENodW5rLFxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXJzLnNvcnRlci52YWx1ZS5zb3J0QnksXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcnMuc29ydGVyLnZhbHVlLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5leHRDaHVuaztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcGFnaW5hdGlvbkhhbmRsZXIoZmlsdGVyczogYW55LCBuZXh0Q2h1bms6IFRbXSk6IFRbXSB7XG4gICAgICAgIGlmIChmaWx0ZXJzPy5wYWdpbmF0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXh0Q2h1bmsuc2xpY2UoXG4gICAgICAgICAgICAgICAgZmlsdGVycy5wYWdpbmF0b3IudmFsdWUuc3RhcnQsXG4gICAgICAgICAgICAgICAgZmlsdGVycy5wYWdpbmF0b3IudmFsdWUuZW5kXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXh0Q2h1bms7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHZpcnR1YWxTY3JvbGxIYW5kbGVyKGZpbHRlcnM6IGFueSwgbmV4dENodW5rOiBUW10pOiBUW10ge1xuICAgICAgICBsZXQgZGF0YSA9IG5leHRDaHVuaztcbiAgICAgICAgaWYgKGZpbHRlcnM/LnZpcnR1YWxTY3JvbGwpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXh0Q2h1bmsuc2xpY2UoXG4gICAgICAgICAgICAgICAgZmlsdGVycy52aXJ0dWFsU2Nyb2xsLnZhbHVlLnN0YXJ0LFxuICAgICAgICAgICAgICAgIGZpbHRlcnMudmlydHVhbFNjcm9sbC52YWx1ZS5lbmRcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIGZvciB2aXJ0dWFsIHNjcm9sbCB3ZSBtdXN0IGFsd2F5cyBhcHBlbmQgY3VycmVudCBjaHVuayB0byB0aGUgcHJldmlvdXMgb25lc1xuICAgICAgICAgICAgZGF0YSA9IHRoaXMudmlydHVhbFNjcm9sbERhdGEgPSB0aGlzLnZpcnR1YWxTY3JvbGxEYXRhLmNvbmNhdChkYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIGluIHYxMSAtIFVzZSBmaWx0ZXJzQ2hhbmdlZCBpbnN0ZWFkIC0gUmVtb3ZhbDogTlVJLTU3OTZcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcGFnaW5hdGlvblJlc2V0KGZpbHRlcnM6IGFueSwgaXRlbXNUb0NvbXBhcmU6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5maWx0ZXJzQ2hhbmdlZChmaWx0ZXJzLCBpdGVtc1RvQ29tcGFyZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGZpbHRlcnNDaGFuZ2VkKGZpbHRlcnM6IGFueSwgaXRlbXNUb0NvbXBhcmU6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAodGhpcy5fcHJldmlvdXNGaWx0ZXJzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1ZhbHVlQ2hhbmdlZChpdGVtc1RvQ29tcGFyZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNldEl0ZW1zVG9Db21wYXJlKFxuICAgICAgICBmaWx0ZXJzOiBGLFxuICAgICAgICBuZXh0Q2h1bms6IFRbXSxcbiAgICAgICAgc2VhcmNoVGVybTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgICAgICBtdWx0aUZpbHRlcnNBcnI6IElGaWx0ZXJHcm91cDxJRmlsdGVyPHN0cmluZ1tdLCBJTXVsdGlGaWx0ZXJNZXRhZGF0YT4+W11cbiAgICApOiBDb21wYXJpc29uSXRlbXNbXSB7XG4gICAgICAgIC8vIEdFVCBGSUxURVJTIGZyb20gcHJldmlvdXMgZmlsdGVyaW5nXG4gICAgICAgIGNvbnN0IHByZXZpb3VzU29ydEJ5ID0gX2dldChcbiAgICAgICAgICAgIHRoaXMuX3ByZXZpb3VzRmlsdGVycyxcbiAgICAgICAgICAgIFwic29ydGVyLnZhbHVlLnNvcnRCeVwiXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzRGlyZWN0aW9uID0gX2dldChcbiAgICAgICAgICAgIHRoaXMuX3ByZXZpb3VzRmlsdGVycyxcbiAgICAgICAgICAgIFwic29ydGVyLnZhbHVlLmRpcmVjdGlvblwiXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzU2VhcmNoVGVybSA9IF9nZXQodGhpcy5fcHJldmlvdXNGaWx0ZXJzLCBcInNlYXJjaC52YWx1ZVwiKTtcbiAgICAgICAgY29uc3QgcHJldmlvdXNNdWx0aUZpbHRlcnNBcnIgPSB0aGlzLmV4dHJhY3RNdWx0aUZpbHRlcnMoXG4gICAgICAgICAgICB0aGlzLl9wcmV2aW91c0ZpbHRlcnNcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBzb3J0QnkgPSBfZ2V0KGZpbHRlcnMsIFwic29ydGVyLnZhbHVlLnNvcnRCeVwiKTtcbiAgICAgICAgY29uc3QgZGlyZWN0aW9uID0gX2dldChmaWx0ZXJzLCBcInNvcnRlci52YWx1ZS5kaXJlY3Rpb25cIik7XG5cbiAgICAgICAgY29uc3QgaXRlbXNUb0NvbXBhcmU6IENvbXBhcmlzb25JdGVtc1tdID0gW107XG4gICAgICAgIGl0ZW1zVG9Db21wYXJlLnB1c2goe1xuICAgICAgICAgICAgcHJldmlvdXNWYWx1ZTogcHJldmlvdXNTb3J0QnksXG4gICAgICAgICAgICBjdXJyZW50VmFsdWU6IHNvcnRCeSxcbiAgICAgICAgfSk7XG4gICAgICAgIGl0ZW1zVG9Db21wYXJlLnB1c2goe1xuICAgICAgICAgICAgcHJldmlvdXNWYWx1ZTogcHJldmlvdXNEaXJlY3Rpb24sXG4gICAgICAgICAgICBjdXJyZW50VmFsdWU6IGRpcmVjdGlvbixcbiAgICAgICAgfSk7XG4gICAgICAgIGl0ZW1zVG9Db21wYXJlLnB1c2goe1xuICAgICAgICAgICAgcHJldmlvdXNWYWx1ZTogcHJldmlvdXNTZWFyY2hUZXJtLFxuICAgICAgICAgICAgY3VycmVudFZhbHVlOiBzZWFyY2hUZXJtLFxuICAgICAgICB9KTtcbiAgICAgICAgaXRlbXNUb0NvbXBhcmUucHVzaCh7XG4gICAgICAgICAgICBwcmV2aW91c1ZhbHVlOiBwcmV2aW91c011bHRpRmlsdGVyc0FycixcbiAgICAgICAgICAgIGN1cnJlbnRWYWx1ZTogbXVsdGlGaWx0ZXJzQXJyLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGl0ZW1zVG9Db21wYXJlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBleHRyYWN0TXVsdGlGaWx0ZXJzKFxuICAgICAgICBmaWx0ZXJzOiBGXG4gICAgKTogSUZpbHRlckdyb3VwPElGaWx0ZXI8c3RyaW5nW10sIElNdWx0aUZpbHRlck1ldGFkYXRhPj5bXSB7XG4gICAgICAgIGNvbnN0IG11bHRpRmlsdGVyQXJyOiBJRmlsdGVyR3JvdXA8XG4gICAgICAgICAgICBJRmlsdGVyPHN0cmluZ1tdLCBJTXVsdGlGaWx0ZXJNZXRhZGF0YT5cbiAgICAgICAgPltdID0gW107XG4gICAgICAgIF9mb3JFYWNoKGZpbHRlcnMsICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgICAgICBpZiAodmFsdWU/LnR5cGUgPT09IFwic3RyaW5nW11cIikge1xuICAgICAgICAgICAgICAgIG11bHRpRmlsdGVyQXJyLnB1c2goeyBba2V5XTogdmFsdWUgfSBhcyBhbnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG11bHRpRmlsdGVyQXJyO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U2VsZWN0ZWRGaWx0ZXJzKFxuICAgICAgICBtdWx0aUZpbHRlcnNBcnI6IElGaWx0ZXJHcm91cDxJRmlsdGVyPHN0cmluZ1tdLCBJTXVsdGlGaWx0ZXJNZXRhZGF0YT4+W11cbiAgICApOiBzdHJpbmdbXSB7XG4gICAgICAgIHJldHVybiBtdWx0aUZpbHRlcnNBcnIucmVkdWNlKFxuICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgIHByZXY6IHN0cmluZ1tdLFxuICAgICAgICAgICAgICAgIGN1cnI6IElGaWx0ZXJHcm91cDxJRmlsdGVyPHN0cmluZ1tdLCBJTXVsdGlGaWx0ZXJNZXRhZGF0YT4+XG4gICAgICAgICAgICApID0+IHByZXYuY29uY2F0KGN1cnJbT2JqZWN0LmtleXMoY3VycilbMF1dLnZhbHVlKSxcbiAgICAgICAgICAgIFtdXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb3VudEF2YWlsYWJsZVJlc3VsdHMoXG4gICAgICAgIGFsbENhdGVnb3JpZXNBcnI6IElGaWx0ZXJJdGVtPHN0cmluZ1tdPltdLFxuICAgICAgICBuZXh0Q2h1bms6IFRbXVxuICAgICk6IElGaWx0ZXJHcm91cDxJRmlsdGVySXRlbTxudW1iZXI+PiB7XG4gICAgICAgIGNvbnN0IGFsbENhdGVnb3JpZXNSZXN1bHQ6IElGaWx0ZXJHcm91cDxJRmlsdGVySXRlbTxudW1iZXI+W10+W10gPVxuICAgICAgICAgICAgYWxsQ2F0ZWdvcmllc0Fyci5tYXAoKGVsLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGtleTogc3RyaW5nID0gT2JqZWN0LmtleXMoZWwpWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlc0Fycjogc3RyaW5nW10gPSBhbGxDYXRlZ29yaWVzQXJyW2luZGV4XVtrZXldO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdEFyciA9IHZhbHVlc0Fyci5tYXAoKGVsZW1lbnQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByOiBUW10gPSB0aGlzLnNlYXJjaFNlcnZpY2Uuc2VhcmNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dENodW5rLFxuICAgICAgICAgICAgICAgICAgICAgICAgW2tleV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IFtlbGVtZW50XTogci5sZW5ndGggfTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBba2V5XTogcmVzdWx0QXJyIH07XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgYWxsQ2F0ZWdvcmllc1Jlc3VsdFxuICAgICAgICAgICAgICAgIC8vIGNvbnZlcnQgYXJyYXkgdG8gYW4gb2JqZWN0XG4gICAgICAgICAgICAgICAgLnJlZHVjZSgocHJldjogYW55LCBjdXJyOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgW3Byb3BdID0gT2JqZWN0LmtleXMoY3Vycik7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnZlcnQgYXJyYXkgdG8gYW4gb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld09iaiA9IGN1cnJbcHJvcF0ucmVkdWNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgKHByZXZpb3VzOiBhbnksIGN1cnJlbnQ6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtwcm9wZXJ0eV0gPSBPYmplY3Qua2V5cyhjdXJyZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1twcm9wZXJ0eV0gPSBjdXJyZW50W3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXM7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAge31cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgcHJldltwcm9wXSA9IG5ld09iajtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByZXY7XG4gICAgICAgICAgICAgICAgfSwge30pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZWFyY2hUaHJ1KFxuICAgICAgICBhcnJUb01hcDogSUZpbHRlckdyb3VwPElGaWx0ZXI8c3RyaW5nW10sIElNdWx0aUZpbHRlck1ldGFkYXRhPj5bXSxcbiAgICAgICAgYXJyVG9TZWFyY2hJbjogVFtdXG4gICAgKSB7XG4gICAgICAgIC8vIFdlIGFyZSBmaWx0ZXJpbmcgb3V0IGZpbHRlciBncm91cHMgd2hpY2ggZG9lc24ndCBoYXZlIHNlbGVjdGVkIGZpbHRlcnMuIElmIGZpbHRlcnMgYXJlIG5vdCBwcmVzZW50LFxuICAgICAgICAvLyBpdCBtZWFucyB0aGF0IGZpbHRlcmVkIGRhdGEgd2l0aCB0aGlzIGZpbHRlcnMgc2hvdWxkIG5vdCBwYXJ0aWNpcGF0ZSBpbiBpbnRlcnNlY3Rpb25cbiAgICAgICAgcmV0dXJuIGFyclRvTWFwXG4gICAgICAgICAgICAuZmlsdGVyKChhcnIpID0+ICEhYXJyW09iamVjdC5rZXlzKGFycilbMF1dLnZhbHVlLmxlbmd0aClcbiAgICAgICAgICAgIC5tYXAoXG4gICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICBtdWx0aUZpbHRlcjogSUZpbHRlckdyb3VwPFxuICAgICAgICAgICAgICAgICAgICAgICAgSUZpbHRlcjxzdHJpbmdbXSwgSU11bHRpRmlsdGVyTWV0YWRhdGE+XG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICApID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgW3Byb3BdID0gT2JqZWN0LmtleXMobXVsdGlGaWx0ZXIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlGaWx0ZXJbcHJvcF0udmFsdWUgLy8gZXh0cmFjdCB2YWx1ZSBhcnJheVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbmQgbWF0Y2hlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKGVsOiBzdHJpbmcpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VhcmNoU2VydmljZS5zZWFyY2goXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJUb1NlYXJjaEluLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3Byb3BdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmbGF0dGVuIHJldHVybmVkIG11bHRpZGltZW5zaW9uYWwgYXJyYXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlZHVjZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByZXY6IFRbXSwgY3VycjogVFtdKSA9PiBwcmV2LmNvbmNhdChjdXJyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW11cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEFsbENhdGVnb3JpZXMoXG4gICAgICAgIG11bHRpRmlsdGVyOiBJRmlsdGVyR3JvdXA8SUZpbHRlcjxzdHJpbmdbXSwgSU11bHRpRmlsdGVyTWV0YWRhdGE+PlxuICAgICkge1xuICAgICAgICBpZiAoIW11bHRpRmlsdGVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgW3Byb3BdID0gT2JqZWN0LmtleXMobXVsdGlGaWx0ZXIpO1xuICAgICAgICBjb25zdCB7IG1ldGFkYXRhIH06IElGaWx0ZXI8c3RyaW5nW10sIElNdWx0aUZpbHRlck1ldGFkYXRhPiA9XG4gICAgICAgICAgICBtdWx0aUZpbHRlcltwcm9wXTtcbiAgICAgICAgcmV0dXJuIHsgW3Byb3BdOiBtZXRhZGF0YT8uYWxsQ2F0ZWdvcmllcyB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNWYWx1ZUNoYW5nZWQodmFsdWVzQXJyOiBDb21wYXJpc29uSXRlbXNbXSkge1xuICAgICAgICBmb3IgKGNvbnN0IHsgcHJldmlvdXNWYWx1ZSwgY3VycmVudFZhbHVlIH0gb2YgdmFsdWVzQXJyKSB7XG4gICAgICAgICAgICBpZiAoIV9pc0VxdWFsKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuIl19