@alfresco/adf-content-services
Version:
Alfresco ADF content services
377 lines • 52.2 kB
JavaScript
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { SiteMemberPaging, PeopleApi, SitesApi, SearchApi, FavoritesApi, SharedlinksApi, TrashcanApi, NodesApi, SEARCH_LANGUAGE } from '@alfresco/js-api';
import { Injectable } from '@angular/core';
import { Observable, from, of } from 'rxjs';
import { map } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "../../services/alfresco-api.service";
const CREATE_PERMISSION = 'create';
export class CustomResourcesService {
get peopleApi() {
this._peopleApi = this._peopleApi ?? new PeopleApi(this.apiService.getInstance());
return this._peopleApi;
}
get sitesApi() {
this._sitesApi = this._sitesApi ?? new SitesApi(this.apiService.getInstance());
return this._sitesApi;
}
get trashcanApi() {
this._trashcanApi = this._trashcanApi ?? new TrashcanApi(this.apiService.getInstance());
return this._trashcanApi;
}
get searchApi() {
this._searchApi = this._searchApi ?? new SearchApi(this.apiService.getInstance());
return this._searchApi;
}
get sharedLinksApi() {
this._sharedLinksApi = this._sharedLinksApi ?? new SharedlinksApi(this.apiService.getInstance());
return this._sharedLinksApi;
}
get favoritesApi() {
this._favoritesApi = this._favoritesApi ?? new FavoritesApi(this.apiService.getInstance());
return this._favoritesApi;
}
get nodesApi() {
this._nodesApi = this._nodesApi ?? new NodesApi(this.apiService.getInstance());
return this._nodesApi;
}
constructor(apiService) {
this.apiService = apiService;
}
/**
* Gets files recently accessed by a user.
*
* @param personId ID of the user
* @param pagination Specifies how to paginate the results
* @param filters Specifies additional filters to apply (joined with **AND**)
* @returns List of nodes for the recently used files
*/
getRecentFiles(personId, pagination, filters) {
const defaultFilter = [
'TYPE:"content"',
'-PATH:"//cm:wiki/*"',
'-TYPE:"app:filelink"',
'-TYPE:"cm:thumbnail"',
'-TYPE:"cm:failedThumbnail"',
'-TYPE:"cm:rating"',
'-TYPE:"dl:dataList"',
'-TYPE:"dl:todoList"',
'-TYPE:"dl:issue"',
'-TYPE:"dl:contact"',
'-TYPE:"dl:eventAgenda"',
'-TYPE:"dl:event"',
'-TYPE:"dl:task"',
'-TYPE:"dl:simpletask"',
'-TYPE:"dl:meetingAgenda"',
'-TYPE:"dl:location"',
'-TYPE:"fm:topic"',
'-TYPE:"fm:post"',
'-TYPE:"ia:calendarEvent"',
'-TYPE:"lnk:link"'
];
return new Observable((observer) => {
this.peopleApi.getPerson(personId).then((person) => {
const username = person.entry.id;
const filterQueries = [
{ query: `cm:modified:[NOW/DAY-30DAYS TO NOW/DAY+1DAY]` },
{ query: `cm:modifier:'${username}' OR cm:creator:'${username}'` },
{ query: defaultFilter.join(' AND ') }
];
if (filters && filters.length > 0) {
filterQueries.push({
query: filters.join()
});
}
const query = {
query: {
query: '*',
language: SEARCH_LANGUAGE.AFTS
},
filterQueries,
include: ['path', 'properties', 'allowableOperations', 'aspectNames'],
sort: [
{
type: 'FIELD',
field: 'cm:modified',
ascending: false
}
],
paging: {
maxItems: pagination.maxItems,
skipCount: pagination.skipCount
}
};
return this.searchApi.search(query).then((searchResult) => {
observer.next(searchResult);
observer.complete();
}, (err) => {
observer.error(err);
observer.complete();
});
}, (err) => {
observer.error(err);
observer.complete();
});
});
}
/**
* Gets favorite files for the current user.
*
* @param pagination Specifies how to paginate the results
* @param includeFields List of data field names to include in the results
* @param where A string to restrict the returned objects by using a predicate
* @returns List of favorite files
*/
loadFavorites(pagination, includeFields = [], where) {
const includeFieldsRequest = this.getIncludesFields(includeFields);
const defaultPredicate = '(EXISTS(target/file) OR EXISTS(target/folder))';
const options = {
maxItems: pagination.maxItems,
skipCount: pagination.skipCount,
where: where ? `${where} AND ${defaultPredicate}` : defaultPredicate,
include: includeFieldsRequest
};
return new Observable((observer) => {
this.favoritesApi.listFavorites('-me-', options).then((result) => {
const page = {
list: {
entries: result.list.entries.map(({ entry }) => {
const target = entry.target.file || entry.target.folder;
target.properties = {
...(target.properties || {
'cm:title': entry.title || target.title,
'cm:description': entry.description || target.description
}),
...(entry.properties || {})
};
target.aspectNames = entry?.aspectNames ?? [];
target.allowableOperations = entry?.allowableOperations ?? [];
return {
entry: target
};
}),
pagination: result.list.pagination
}
};
observer.next(page);
observer.complete();
}, (err) => {
observer.error(err);
observer.complete();
});
});
}
/**
* Gets sites that the current user is a member of.
*
* @param pagination Specifies how to paginate the results
* @param where A string to restrict the returned objects by using a predicate
* @returns List of sites
*/
loadMemberSites(pagination, where) {
const options = {
include: ['properties'],
maxItems: pagination.maxItems,
skipCount: pagination.skipCount,
where
};
return new Observable((observer) => {
this.sitesApi.listSiteMembershipsForPerson('-me-', options).then((result) => {
const page = new SiteMemberPaging({
list: {
entries: result.list.entries.map(({ entry: { site } }) => {
site.allowableOperations = site.allowableOperations ? site.allowableOperations : [CREATE_PERMISSION];
site.name = site.name || site.title;
return {
entry: site
};
}),
pagination: result.list.pagination
}
});
observer.next(page);
observer.complete();
}, (err) => {
observer.error(err);
observer.complete();
});
});
}
/**
* Gets all sites in the repository.
*
* @param pagination Specifies how to paginate the results
* @param where A string to restrict the returned objects by using a predicate
* @returns List of sites
*/
loadSites(pagination, where) {
const options = {
include: ['properties', 'aspectNames'],
maxItems: pagination.maxItems,
skipCount: pagination.skipCount,
where
};
return new Observable((observer) => {
this.sitesApi.listSites(options).then((page) => {
page.list.entries.map(({ entry }) => {
entry.name = entry.name || entry.title;
return { entry };
});
observer.next(page);
observer.complete();
}, (err) => {
observer.error(err);
observer.complete();
});
});
}
/**
* Gets all items currently in the trash.
*
* @param pagination Specifies how to paginate the results
* @param includeFields List of data field names to include in the results
* @returns List of deleted items
*/
loadTrashcan(pagination, includeFields = []) {
const includeFieldsRequest = this.getIncludesFields(includeFields);
const options = {
include: includeFieldsRequest,
maxItems: pagination.maxItems,
skipCount: pagination.skipCount
};
return from(this.trashcanApi.listDeletedNodes(options));
}
/**
* Gets shared links for the current user.
*
* @param pagination Specifies how to paginate the results
* @param includeFields List of data field names to include in the results
* @param where A string to restrict the returned objects by using a predicate
* @returns List of shared links
*/
loadSharedLinks(pagination, includeFields = [], where) {
const includeFieldsRequest = this.getIncludesFields(includeFields);
const options = {
include: includeFieldsRequest,
maxItems: pagination.maxItems,
skipCount: pagination.skipCount,
where
};
return from(this.sharedLinksApi.listSharedLinks(options));
}
/**
* Is the folder ID one of the well-known aliases?
*
* @param folderId Folder ID name to check
* @returns True if the ID is a well-known name, false otherwise
*/
isCustomSource(folderId) {
let isCustomSources = false;
const sources = ['-trashcan-', '-sharedlinks-', '-sites-', '-mysites-', '-favorites-', '-recent-'];
if (sources.indexOf(folderId) > -1) {
isCustomSources = true;
}
return isCustomSources;
}
/**
* Is the folder ID a "-my", "-root-", or "-shared-" alias?
*
* @param folderId Folder ID name to check
* @returns True if the ID is one of the supported sources, false otherwise
*/
isSupportedSource(folderId) {
let isSupportedSources = false;
const sources = ['-my-', '-root-', '-shared-'];
if (sources.indexOf(folderId) > -1) {
isSupportedSources = true;
}
return isSupportedSources;
}
/**
* Gets a folder's contents.
*
* @param nodeId ID of the target folder node
* @param pagination Specifies how to paginate the results
* @param includeFields List of data field names to include in the results
* @param where Filters the Node list using the *where* condition of the REST API (for example, isFolder=true). See the REST API documentation for more information.
* @returns List of items contained in the folder
*/
loadFolderByNodeId(nodeId, pagination, includeFields = [], where) {
if (nodeId === '-trashcan-') {
return this.loadTrashcan(pagination, includeFields);
}
else if (nodeId === '-sharedlinks-') {
return this.loadSharedLinks(pagination, includeFields, where);
}
else if (nodeId === '-sites-') {
return this.loadSites(pagination, where);
}
else if (nodeId === '-mysites-') {
return this.loadMemberSites(pagination, where);
}
else if (nodeId === '-favorites-') {
return this.loadFavorites(pagination, includeFields, where);
}
else if (nodeId === '-recent-') {
return this.getRecentFiles('-me-', pagination);
}
}
// TODO: remove it from here
/**
* Gets the contents of one of the well-known aliases in the form of node ID strings.
*
* @param nodeId ID of the target folder node
* @param pagination Specifies how to paginate the results
* @returns List of node IDs
*/
getCorrespondingNodeIds(nodeId, pagination = {}) {
if (this.isCustomSource(nodeId)) {
return this.loadFolderByNodeId(nodeId, pagination).pipe(map((result) => result.list.entries.map((node) => this.getIdFromEntry(node, nodeId))));
}
else if (nodeId) {
// cases when nodeId is '-my-', '-root-' or '-shared-'
return from(this.nodesApi.getNode(nodeId).then((node) => [node.entry.id]));
}
return of([]);
}
/**
* Chooses the correct ID for a node entry.
*
* @param node Node object
* @param nodeId ID of the node object
* @returns ID value
*/
getIdFromEntry(node, nodeId) {
if (nodeId === '-sharedlinks-') {
return node.entry.nodeId;
}
else if (nodeId === '-sites-' || nodeId === '-mysites-') {
return node.entry.guid;
}
else if (nodeId === '-favorites-') {
return node.entry.targetGuid;
}
else {
return node.entry.id;
}
}
/**
* Does the well-known alias have a corresponding node ID?
*
* @param nodeId Node to check
* @returns True if the alias has a corresponding node ID, false otherwise
*/
hasCorrespondingNodeIds(nodeId) {
return this.isCustomSource(nodeId) || this.isSupportedSource(nodeId);
}
getIncludesFields(includeFields) {
return ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields].filter((element, index, array) => index === array.indexOf(element));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CustomResourcesService, deps: [{ token: i1.AlfrescoApiService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CustomResourcesService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: CustomResourcesService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1.AlfrescoApiService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tLXJlc291cmNlcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGliL2NvbnRlbnQtc2VydmljZXMvc3JjL2xpYi9kb2N1bWVudC1saXN0L3NlcnZpY2VzL2N1c3RvbS1yZXNvdXJjZXMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFrQkEsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDekUsT0FBTyxFQUtILGdCQUFnQixFQUVoQixTQUFTLEVBQ1QsUUFBUSxFQUNSLFNBQVMsRUFDVCxZQUFZLEVBQ1osY0FBYyxFQUNkLFdBQVcsRUFDWCxRQUFRLEVBR1IsZUFBZSxFQUNsQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBRXJDLE1BQU0saUJBQWlCLEdBQVcsUUFBUSxDQUFDO0FBRzNDLE1BQU0sT0FBTyxzQkFBc0I7SUFFL0IsSUFBSSxTQUFTO1FBQ1QsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNsRixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDM0IsQ0FBQztJQUdELElBQUksUUFBUTtRQUNSLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDL0UsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzFCLENBQUM7SUFHRCxJ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QXNCLGNBRFQsTUFBTTs7MkZBQ25CLHNCQUFzQjtrQkFEbEMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgwqkgMjAwNS0yMDI1IEh5bGFuZCBTb2Z0d2FyZSwgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFBhZ2luYXRpb25Nb2RlbCB9IGZyb20gJ0BhbGZyZXNjby9hZGYtY29yZSc7XG5pbXBvcnQgeyBBbGZyZXNjb0FwaVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9hbGZyZXNjby1hcGkuc2VydmljZSc7XG5pbXBvcnQge1xuICAgIERlbGV0ZWROb2Rlc1BhZ2luZyxcbiAgICBTZWFyY2hSZXF1ZXN0LFxuICAgIFNoYXJlZExpbmtQYWdpbmcsXG4gICAgRmF2b3JpdGVQYWdpbmcsXG4gICAgU2l0ZU1lbWJlclBhZ2luZyxcbiAgICBTaXRlUm9sZVBhZ2luZyxcbiAgICBQZW9wbGVBcGksXG4gICAgU2l0ZXNBcGksXG4gICAgU2VhcmNoQXBpLFxuICAgIEZhdm9yaXRlc0FwaSxcbiAgICBTaGFyZWRsaW5rc0FwaSxcbiAgICBUcmFzaGNhbkFwaSxcbiAgICBOb2Rlc0FwaSxcbiAgICBTaXRlUGFnaW5nLFxuICAgIFJlc3VsdFNldFBhZ2luZyxcbiAgICBTRUFSQ0hfTEFOR1VBR0Vcbn0gZnJvbSAnQGFsZnJlc2NvL2pzLWFwaSc7XG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBmcm9tLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5jb25zdCBDUkVBVEVfUEVSTUlTU0lPTjogc3RyaW5nID0gJ2NyZWF0ZSc7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQ3VzdG9tUmVzb3VyY2VzU2VydmljZSB7XG4gICAgcHJpdmF0ZSBfcGVvcGxlQXBpOiBQZW9wbGVBcGk7XG4gICAgZ2V0IHBlb3BsZUFwaSgpOiBQZW9wbGVBcGkge1xuICAgICAgICB0aGlzLl9wZW9wbGVBcGkgPSB0aGlzLl9wZW9wbGVBcGkgPz8gbmV3IFBlb3BsZUFwaSh0aGlzLmFwaVNlcnZpY2UuZ2V0SW5zdGFuY2UoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9wZW9wbGVBcGk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfc2l0ZXNBcGk6IFNpdGVzQXBpO1xuICAgIGdldCBzaXRlc0FwaSgpOiBTaXRlc0FwaSB7XG4gICAgICAgIHRoaXMuX3NpdGVzQXBpID0gdGhpcy5fc2l0ZXNBcGkgPz8gbmV3IFNpdGVzQXBpKHRoaXMuYXBpU2VydmljZS5nZXRJbnN0YW5jZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NpdGVzQXBpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3RyYXNoY2FuQXBpOiBUcmFzaGNhbkFwaTtcbiAgICBnZXQgdHJhc2hjYW5BcGkoKTogVHJhc2hjYW5BcGkge1xuICAgICAgICB0aGlzLl90cmFzaGNhbkFwaSA9IHRoaXMuX3RyYXNoY2FuQXBpID8/IG5ldyBUcmFzaGNhbkFwaSh0aGlzLmFwaVNlcnZpY2UuZ2V0SW5zdGFuY2UoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLl90cmFzaGNhbkFwaTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zZWFyY2hBcGk6IFNlYXJjaEFwaTtcbiAgICBnZXQgc2VhcmNoQXBpKCk6IFNlYXJjaEFwaSB7XG4gICAgICAgIHRoaXMuX3NlYXJjaEFwaSA9IHRoaXMuX3NlYXJjaEFwaSA/PyBuZXcgU2VhcmNoQXBpKHRoaXMuYXBpU2VydmljZS5nZXRJbnN0YW5jZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlYXJjaEFwaTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zaGFyZWRMaW5rc0FwaTogU2hhcmVkbGlua3NBcGk7XG4gICAgZ2V0IHNoYXJlZExpbmtzQXBpKCk6IFNoYXJlZGxpbmtzQXBpIHtcbiAgICAgICAgdGhpcy5fc2hhcmVkTGlua3NBcGkgPSB0aGlzLl9zaGFyZWRMaW5rc0FwaSA/PyBuZXcgU2hhcmVkbGlua3NBcGkodGhpcy5hcGlTZXJ2aWNlLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fc2hhcmVkTGlua3NBcGk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZmF2b3JpdGVzQXBpOiBGYXZvcml0ZXNBcGk7XG4gICAgZ2V0IGZhdm9yaXRlc0FwaSgpOiBGYXZvcml0ZXNBcGkge1xuICAgICAgICB0aGlzLl9mYXZvcml0ZXNBcGkgPSB0aGlzLl9mYXZvcml0ZXNBcGkgPz8gbmV3IEZhdm9yaXRlc0FwaSh0aGlzLmFwaVNlcnZpY2UuZ2V0SW5zdGFuY2UoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9mYXZvcml0ZXNBcGk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfbm9kZXNBcGk6IE5vZGVzQXBpO1xuICAgIGdldCBub2Rlc0FwaSgpOiBOb2Rlc0FwaSB7XG4gICAgICAgIHRoaXMuX25vZGVzQXBpID0gdGhpcy5fbm9kZXNBcGkgPz8gbmV3IE5vZGVzQXBpKHRoaXMuYXBpU2VydmljZS5nZXRJbnN0YW5jZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX25vZGVzQXBpO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBpU2VydmljZTogQWxmcmVzY29BcGlTZXJ2aWNlKSB7fVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBmaWxlcyByZWNlbnRseSBhY2Nlc3NlZCBieSBhIHVzZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGVyc29uSWQgSUQgb2YgdGhlIHVzZXJcbiAgICAgKiBAcGFyYW0gcGFnaW5hdGlvbiBTcGVjaWZpZXMgaG93IHRvIHBhZ2luYXRlIHRoZSByZXN1bHRzXG4gICAgICogQHBhcmFtIGZpbHRlcnMgU3BlY2lmaWVzIGFkZGl0aW9uYWwgZmlsdGVycyB0byBhcHBseSAoam9pbmVkIHdpdGggKipBTkQqKilcbiAgICAgKiBAcmV0dXJucyBMaXN0IG9mIG5vZGVzIGZvciB0aGUgcmVjZW50bHkgdXNlZCBmaWxlc1xuICAgICAqL1xuICAgIGdldFJlY2VudEZpbGVzKHBlcnNvbklkOiBzdHJpbmcsIHBhZ2luYXRpb246IFBhZ2luYXRpb25Nb2RlbCwgZmlsdGVycz86IHN0cmluZ1tdKTogT2JzZXJ2YWJsZTxSZXN1bHRTZXRQYWdpbmc+IHtcbiAgICAgICAgY29uc3QgZGVmYXVsdEZpbHRlciA9IFtcbiAgICAgICAgICAgICdUWVBFOlwiY29udGVudFwiJyxcbiAgICAgICAgICAgICctUEFUSDpcIi8vY206d2lraS8qXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiYXBwOmZpbGVsaW5rXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiY206dGh1bWJuYWlsXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiY206ZmFpbGVkVGh1bWJuYWlsXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiY206cmF0aW5nXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiZGw6ZGF0YUxpc3RcIicsXG4gICAgICAgICAgICAnLVRZUEU6XCJkbDp0b2RvTGlzdFwiJyxcbiAgICAgICAgICAgICctVFlQRTpcImRsOmlzc3VlXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiZGw6Y29udGFjdFwiJyxcbiAgICAgICAgICAgICctVFlQRTpcImRsOmV2ZW50QWdlbmRhXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiZGw6ZXZlbnRcIicsXG4gICAgICAgICAgICAnLVRZUEU6XCJkbDp0YXNrXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiZGw6c2ltcGxldGFza1wiJyxcbiAgICAgICAgICAgICctVFlQRTpcImRsOm1lZXRpbmdBZ2VuZGFcIicsXG4gICAgICAgICAgICAnLVRZUEU6XCJkbDpsb2NhdGlvblwiJyxcbiAgICAgICAgICAgICctVFlQRTpcImZtOnRvcGljXCInLFxuICAgICAgICAgICAgJy1UWVBFOlwiZm06cG9zdFwiJyxcbiAgICAgICAgICAgICctVFlQRTpcImlhOmNhbGVuZGFyRXZlbnRcIicsXG4gICAgICAgICAgICAnLVRZUEU6XCJsbms6bGlua1wiJ1xuICAgICAgICBdO1xuXG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGVvcGxlQXBpLmdldFBlcnNvbihwZXJzb25JZCkudGhlbihcbiAgICAgICAgICAgICAgICAocGVyc29uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVzZXJuYW1lID0gcGVyc29uLmVudHJ5LmlkO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJRdWVyaWVzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgeyBxdWVyeTogYGNtOm1vZGlmaWVkOltOT1cvREFZLTMwREFZUyBUTyBOT1cvREFZKzFEQVldYCB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyBxdWVyeTogYGNtOm1vZGlmaWVyOicke3VzZXJuYW1lfScgT1IgY206Y3JlYXRvcjonJHt1c2VybmFtZX0nYCB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyBxdWVyeTogZGVmYXVsdEZpbHRlci5qb2luKCcgQU5EICcpIH1cbiAgICAgICAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsdGVycyAmJiBmaWx0ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlclF1ZXJpZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVlcnk6IGZpbHRlcnMuam9pbigpXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHF1ZXJ5OiBTZWFyY2hSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcXVlcnk6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWVyeTogJyonLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbmd1YWdlOiBTRUFSQ0hfTEFOR1VBR0UuQUZUU1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlclF1ZXJpZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlOiBbJ3BhdGgnLCAncHJvcGVydGllcycsICdhbGxvd2FibGVPcGVyYXRpb25zJywgJ2FzcGVjdE5hbWVzJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3J0OiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnRklFTEQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZDogJ2NtOm1vZGlmaWVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNjZW5kaW5nOiBmYWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBwYWdpbmc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhJdGVtczogcGFnaW5hdGlvbi5tYXhJdGVtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwQ291bnQ6IHBhZ2luYXRpb24uc2tpcENvdW50XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2VhcmNoQXBpLnNlYXJjaChxdWVyeSkudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgIChzZWFyY2hSZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHNlYXJjaFJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgZmF2b3JpdGUgZmlsZXMgZm9yIHRoZSBjdXJyZW50IHVzZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGFnaW5hdGlvbiBTcGVjaWZpZXMgaG93IHRvIHBhZ2luYXRlIHRoZSByZXN1bHRzXG4gICAgICogQHBhcmFtIGluY2x1ZGVGaWVsZHMgTGlzdCBvZiBkYXRhIGZpZWxkIG5hbWVzIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdHNcbiAgICAgKiBAcGFyYW0gd2hlcmUgQSBzdHJpbmcgdG8gcmVzdHJpY3QgdGhlIHJldHVybmVkIG9iamVjdHMgYnkgdXNpbmcgYSBwcmVkaWNhdGVcbiAgICAgKiBAcmV0dXJucyBMaXN0IG9mIGZhdm9yaXRlIGZpbGVzXG4gICAgICovXG4gICAgbG9hZEZhdm9yaXRlcyhwYWdpbmF0aW9uOiBQYWdpbmF0aW9uTW9kZWwsIGluY2x1ZGVGaWVsZHM6IHN0cmluZ1tdID0gW10sIHdoZXJlPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxGYXZvcml0ZVBhZ2luZz4ge1xuICAgICAgICBjb25zdCBpbmNsdWRlRmllbGRzUmVxdWVzdCA9IHRoaXMuZ2V0SW5jbHVkZXNGaWVsZHMoaW5jbHVkZUZpZWxkcyk7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRQcmVkaWNhdGUgPSAnKEVYSVNUUyh0YXJnZXQvZmlsZSkgT1IgRVhJU1RTKHRhcmdldC9mb2xkZXIpKSc7XG5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIG1heEl0ZW1zOiBwYWdpbmF0aW9uLm1heEl0ZW1zLFxuICAgICAgICAgICAgc2tpcENvdW50OiBwYWdpbmF0aW9uLnNraXBDb3VudCxcbiAgICAgICAgICAgIHdoZXJlOiB3aGVyZSA/IGAke3doZXJlfSBBTkQgJHtkZWZhdWx0UHJlZGljYXRlfWAgOiBkZWZhdWx0UHJlZGljYXRlLFxuICAgICAgICAgICAgaW5jbHVkZTogaW5jbHVkZUZpZWxkc1JlcXVlc3RcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmZhdm9yaXRlc0FwaS5saXN0RmF2b3JpdGVzKCctbWUtJywgb3B0aW9ucykudGhlbihcbiAgICAgICAgICAgICAgICAocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2U6IEZhdm9yaXRlUGFnaW5nID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGlzdDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXM6IHJlc3VsdC5saXN0LmVudHJpZXMubWFwKCh7IGVudHJ5IH06IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBlbnRyeS50YXJnZXQuZmlsZSB8fCBlbnRyeS50YXJnZXQuZm9sZGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQucHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLih0YXJnZXQucHJvcGVydGllcyB8fCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NtOnRpdGxlJzogZW50cnkudGl0bGUgfHwgdGFyZ2V0LnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjbTpkZXNjcmlwdGlvbic6IGVudHJ5LmRlc2NyaXB0aW9uIHx8IHRhcmdldC5kZXNjcmlwdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4oZW50cnkucHJvcGVydGllcyB8fCB7fSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LmFzcGVjdE5hbWVzID0gZW50cnk/LmFzcGVjdE5hbWVzID8/IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQuYWxsb3dhYmxlT3BlcmF0aW9ucyA9IGVudHJ5Py5hbGxvd2FibGVPcGVyYXRpb25zID8/IFtdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyeTogdGFyZ2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnaW5hdGlvbjogcmVzdWx0Lmxpc3QucGFnaW5hdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQocGFnZSk7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBzaXRlcyB0aGF0IHRoZSBjdXJyZW50IHVzZXIgaXMgYSBtZW1iZXIgb2YuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGFnaW5hdGlvbiBTcGVjaWZpZXMgaG93IHRvIHBhZ2luYXRlIHRoZSByZXN1bHRzXG4gICAgICogQHBhcmFtIHdoZXJlIEEgc3RyaW5nIHRvIHJlc3RyaWN0IHRoZSByZXR1cm5lZCBvYmplY3RzIGJ5IHVzaW5nIGEgcHJlZGljYXRlXG4gICAgICogQHJldHVybnMgTGlzdCBvZiBzaXRlc1xuICAgICAqL1xuICAgIGxvYWRNZW1iZXJTaXRlcyhwYWdpbmF0aW9uOiBQYWdpbmF0aW9uTW9kZWwsIHdoZXJlPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxTaXRlTWVtYmVyUGFnaW5nPiB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBpbmNsdWRlOiBbJ3Byb3BlcnRpZXMnXSxcbiAgICAgICAgICAgIG1heEl0ZW1zOiBwYWdpbmF0aW9uLm1heEl0ZW1zLFxuICAgICAgICAgICAgc2tpcENvdW50OiBwYWdpbmF0aW9uLnNraXBDb3VudCxcbiAgICAgICAgICAgIHdoZXJlXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xuICAgICAgICAgICAgdGhpcy5zaXRlc0FwaS5saXN0U2l0ZU1lbWJlcnNoaXBzRm9yUGVyc29uKCctbWUtJywgb3B0aW9ucykudGhlbihcbiAgICAgICAgICAgICAgICAocmVzdWx0OiBTaXRlUm9sZVBhZ2luZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlOiBTaXRlTWVtYmVyUGFnaW5nID0gbmV3IFNpdGVNZW1iZXJQYWdpbmcoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbGlzdDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXM6IHJlc3VsdC5saXN0LmVudHJpZXMubWFwKCh7IGVudHJ5OiB7IHNpdGUgfSB9OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l0ZS5hbGxvd2FibGVPcGVyYXRpb25zID0gc2l0ZS5hbGxvd2FibGVPcGVyYXRpb25zID8gc2l0ZS5hbGxvd2FibGVPcGVyYXRpb25zIDogW0NSRUFURV9QRVJNSVNTSU9OXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l0ZS5uYW1lID0gc2l0ZS5uYW1lIHx8IHNpdGUudGl0bGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyeTogc2l0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2luYXRpb246IHJlc3VsdC5saXN0LnBhZ2luYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChwYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBzaXRlcyBpbiB0aGUgcmVwb3NpdG9yeS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYWdpbmF0aW9uIFNwZWNpZmllcyBob3cgdG8gcGFnaW5hdGUgdGhlIHJlc3VsdHNcbiAgICAgKiBAcGFyYW0gd2hlcmUgQSBzdHJpbmcgdG8gcmVzdHJpY3QgdGhlIHJldHVybmVkIG9iamVjdHMgYnkgdXNpbmcgYSBwcmVkaWNhdGVcbiAgICAgKiBAcmV0dXJucyBMaXN0IG9mIHNpdGVzXG4gICAgICovXG4gICAgbG9hZFNpdGVzKHBhZ2luYXRpb246IFBhZ2luYXRpb25Nb2RlbCwgd2hlcmU/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFNpdGVQYWdpbmc+IHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGluY2x1ZGU6IFsncHJvcGVydGllcycsICdhc3BlY3ROYW1lcyddLFxuICAgICAgICAgICAgbWF4SXRlbXM6IHBhZ2luYXRpb24ubWF4SXRlbXMsXG4gICAgICAgICAgICBza2lwQ291bnQ6IHBhZ2luYXRpb24uc2tpcENvdW50LFxuICAgICAgICAgICAgd2hlcmVcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNpdGVzQXBpLmxpc3RTaXRlcyhvcHRpb25zKS50aGVuKFxuICAgICAgICAgICAgICAgIChwYWdlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHBhZ2UubGlzdC5lbnRyaWVzLm1hcCgoeyBlbnRyeSB9OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5Lm5hbWUgPSBlbnRyeS5uYW1lIHx8IGVudHJ5LnRpdGxlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZW50cnkgfTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQocGFnZSk7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgaXRlbXMgY3VycmVudGx5IGluIHRoZSB0cmFzaC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYWdpbmF0aW9uIFNwZWNpZmllcyBob3cgdG8gcGFnaW5hdGUgdGhlIHJlc3VsdHNcbiAgICAgKiBAcGFyYW0gaW5jbHVkZUZpZWxkcyBMaXN0IG9mIGRhdGEgZmllbGQgbmFtZXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0c1xuICAgICAqIEByZXR1cm5zIExpc3Qgb2YgZGVsZXRlZCBpdGVtc1xuICAgICAqL1xuICAgIGxvYWRUcmFzaGNhbihwYWdpbmF0aW9uOiBQYWdpbmF0aW9uTW9kZWwsIGluY2x1ZGVGaWVsZHM6IHN0cmluZ1tdID0gW10pOiBPYnNlcnZhYmxlPERlbGV0ZWROb2Rlc1BhZ2luZz4ge1xuICAgICAgICBjb25zdCBpbmNsdWRlRmllbGRzUmVxdWVzdCA9IHRoaXMuZ2V0SW5jbHVkZXNGaWVsZHMoaW5jbHVkZUZpZWxkcyk7XG5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGluY2x1ZGU6IGluY2x1ZGVGaWVsZHNSZXF1ZXN0LFxuICAgICAgICAgICAgbWF4SXRlbXM6IHBhZ2luYXRpb24ubWF4SXRlbXMsXG4gICAgICAgICAgICBza2lwQ291bnQ6IHBhZ2luYXRpb24uc2tpcENvdW50XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGZyb20odGhpcy50cmFzaGNhbkFwaS5saXN0RGVsZXRlZE5vZGVzKG9wdGlvbnMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHNoYXJlZCBsaW5rcyBmb3IgdGhlIGN1cnJlbnQgdXNlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYWdpbmF0aW9uIFNwZWNpZmllcyBob3cgdG8gcGFnaW5hdGUgdGhlIHJlc3VsdHNcbiAgICAgKiBAcGFyYW0gaW5jbHVkZUZpZWxkcyBMaXN0IG9mIGRhdGEgZmllbGQgbmFtZXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0c1xuICAgICAqIEBwYXJhbSB3aGVyZSBBIHN0cmluZyB0byByZXN0cmljdCB0aGUgcmV0dXJuZWQgb2JqZWN0cyBieSB1c2luZyBhIHByZWRpY2F0ZVxuICAgICAqIEByZXR1cm5zIExpc3Qgb2Ygc2hhcmVkIGxpbmtzXG4gICAgICovXG4gICAgbG9hZFNoYXJlZExpbmtzKHBhZ2luYXRpb246IFBhZ2luYXRpb25Nb2RlbCwgaW5jbHVkZUZpZWxkczogc3RyaW5nW10gPSBbXSwgd2hlcmU/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFNoYXJlZExpbmtQYWdpbmc+IHtcbiAgICAgICAgY29uc3QgaW5jbHVkZUZpZWxkc1JlcXVlc3QgPSB0aGlzLmdldEluY2x1ZGVzRmllbGRzKGluY2x1ZGVGaWVsZHMpO1xuXG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBpbmNsdWRlOiBpbmNsdWRlRmllbGRzUmVxdWVzdCxcbiAgICAgICAgICAgIG1heEl0ZW1zOiBwYWdpbmF0aW9uLm1heEl0ZW1zLFxuICAgICAgICAgICAgc2tpcENvdW50OiBwYWdpbmF0aW9uLnNraXBDb3VudCxcbiAgICAgICAgICAgIHdoZXJlXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIGZyb20odGhpcy5zaGFyZWRMaW5rc0FwaS5saXN0U2hhcmVkTGlua3Mob3B0aW9ucykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElzIHRoZSBmb2xkZXIgSUQgb25lIG9mIHRoZSB3ZWxsLWtub3duIGFsaWFzZXM/XG4gICAgICpcbiAgICAgKiBAcGFyYW0gZm9sZGVySWQgRm9sZGVyIElEIG5hbWUgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBJRCBpcyBhIHdlbGwta25vd24gbmFtZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaXNDdXN0b21Tb3VyY2UoZm9sZGVySWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgaXNDdXN0b21Tb3VyY2VzID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IHNvdXJjZXMgPSBbJy10cmFzaGNhbi0nLCAnLXNoYXJlZGxpbmtzLScsICctc2l0ZXMtJywgJy1teXNpdGVzLScsICctZmF2b3JpdGVzLScsICctcmVjZW50LSddO1xuXG4gICAgICAgIGlmIChzb3VyY2VzLmluZGV4T2YoZm9sZGVySWQpID4gLTEpIHtcbiAgICAgICAgICAgIGlzQ3VzdG9tU291cmNlcyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaXNDdXN0b21Tb3VyY2VzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElzIHRoZSBmb2xkZXIgSUQgYSBcIi1teVwiLCBcIi1yb290LVwiLCBvciBcIi1zaGFyZWQtXCIgYWxpYXM/XG4gICAgICpcbiAgICAgKiBAcGFyYW0gZm9sZGVySWQgRm9sZGVyIElEIG5hbWUgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBJRCBpcyBvbmUgb2YgdGhlIHN1cHBvcnRlZCBzb3VyY2VzLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpc1N1cHBvcnRlZFNvdXJjZShmb2xkZXJJZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBpc1N1cHBvcnRlZFNvdXJjZXMgPSBmYWxzZTtcbiAgICAgICAgY29uc3Qgc291cmNlcyA9IFsnLW15LScsICctcm9vdC0nLCAnLXNoYXJlZC0nXTtcblxuICAgICAgICBpZiAoc291cmNlcy5pbmRleE9mKGZvbGRlcklkKSA+IC0xKSB7XG4gICAgICAgICAgICBpc1N1cHBvcnRlZFNvdXJjZXMgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGlzU3VwcG9ydGVkU291cmNlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgZm9sZGVyJ3MgY29udGVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZUlkIElEIG9mIHRoZSB0YXJnZXQgZm9sZGVyIG5vZGVcbiAgICAgKiBAcGFyYW0gcGFnaW5hdGlvbiBTcGVjaWZpZXMgaG93IHRvIHBhZ2luYXRlIHRoZSByZXN1bHRzXG4gICAgICogQHBhcmFtIGluY2x1ZGVGaWVsZHMgTGlzdCBvZiBkYXRhIGZpZWxkIG5hbWVzIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdHNcbiAgICAgKiBAcGFyYW0gd2hlcmUgIEZpbHRlcnMgdGhlIE5vZGUgbGlzdCB1c2luZyB0aGUgKndoZXJlKiBjb25kaXRpb24gb2YgdGhlIFJFU1QgQVBJIChmb3IgZXhhbXBsZSwgaXNGb2xkZXI9dHJ1ZSkuIFNlZSB0aGUgUkVTVCBBUEkgZG9jdW1lbnRhdGlvbiBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiAgICAgKiBAcmV0dXJucyBMaXN0IG9mIGl0ZW1zIGNvbnRhaW5lZCBpbiB0aGUgZm9sZGVyXG4gICAgICovXG4gICAgbG9hZEZvbGRlckJ5Tm9kZUlkKG5vZGVJZDogc3RyaW5nLCBwYWdpbmF0aW9uOiBQYWdpbmF0aW9uTW9kZWwsIGluY2x1ZGVGaWVsZHM6IHN0cmluZ1tdID0gW10sIHdoZXJlPzogc3RyaW5nKTogYW55IHtcbiAgICAgICAgaWYgKG5vZGVJZCA9PT0gJy10cmFzaGNhbi0nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2FkVHJhc2hjYW4ocGFnaW5hdGlvbiwgaW5jbHVkZUZpZWxkcyk7XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZUlkID09PSAnLXNoYXJlZGxpbmtzLScpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvYWRTaGFyZWRMaW5rcyhwYWdpbmF0aW9uLCBpbmNsdWRlRmllbGRzLCB3aGVyZSk7XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZUlkID09PSAnLXNpdGVzLScpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvYWRTaXRlcyhwYWdpbmF0aW9uLCB3aGVyZSk7XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZUlkID09PSAnLW15c2l0ZXMtJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9hZE1lbWJlclNpdGVzKHBhZ2luYXRpb24sIHdoZXJlKTtcbiAgICAgICAgfSBlbHNlIGlmIChub2RlSWQgPT09ICctZmF2b3JpdGVzLScpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvYWRGYXZvcml0ZXMocGFnaW5hdGlvbiwgaW5jbHVkZUZpZWxkcywgd2hlcmUpO1xuICAgICAgICB9IGVsc2UgaWYgKG5vZGVJZCA9PT0gJy1yZWNlbnQtJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVjZW50RmlsZXMoJy1tZS0nLCBwYWdpbmF0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE86IHJlbW92ZSBpdCBmcm9tIGhlcmVcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGNvbnRlbnRzIG9mIG9uZSBvZiB0aGUgd2VsbC1rbm93biBhbGlhc2VzIGluIHRoZSBmb3JtIG9mIG5vZGUgSUQgc3RyaW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBub2RlSWQgSUQgb2YgdGhlIHRhcmdldCBmb2xkZXIgbm9kZVxuICAgICAqIEBwYXJhbSBwYWdpbmF0aW9uIFNwZWNpZmllcyBob3cgdG8gcGFnaW5hdGUgdGhlIHJlc3VsdHNcbiAgICAgKiBAcmV0dXJucyBMaXN0IG9mIG5vZGUgSURzXG4gICAgICovXG4gICAgZ2V0Q29ycmVzcG9uZGluZ05vZGVJZHMobm9kZUlkOiBzdHJpbmcsIHBhZ2luYXRpb246IFBhZ2luYXRpb25Nb2RlbCA9IHt9KTogT2JzZXJ2YWJsZTxzdHJpbmdbXT4ge1xuICAgICAgICBpZiAodGhpcy5pc0N1c3RvbVNvdXJjZShub2RlSWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2FkRm9sZGVyQnlOb2RlSWQobm9kZUlkLCBw