@alfresco/adf-content-services
Version:
Alfresco ADF content services
509 lines • 62.7 kB
JavaScript
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BehaviorSubject, from, ReplaySubject, Subject } from 'rxjs';
import { SEARCH_LANGUAGE, SearchApi } from '@alfresco/js-api';
import { Buffer } from 'buffer';
import { inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
export class BaseQueryBuilderService {
get searchApi() {
this._searchApi = this._searchApi ?? new SearchApi(this.alfrescoApiService.getInstance());
return this._searchApi;
}
get userQuery() {
return this._userQuery;
}
set userQuery(value) {
value = (value || '').trim();
this._userQuery = value ? `(${value})` : '';
}
constructor(appConfig, alfrescoApiService) {
this.appConfig = appConfig;
this.alfrescoApiService = alfrescoApiService;
this.router = inject(Router);
this.activatedRoute = inject(ActivatedRoute);
/* Stream that emits the search configuration whenever the user change the search forms */
this.configUpdated = new Subject();
/* Stream that emits the event each time when search filter finishes loading initial value */
this.filterLoaded = new Subject();
/* Stream that emits the query before search whenever user search */
this.updated = new Subject();
/* Stream that emits the results whenever user search */
this.executed = new Subject();
/* Stream that emits the error whenever user search */
this.error = new Subject();
/* Stream that emits search forms */
this.searchForms = new ReplaySubject(1);
/* Stream that emits void when change in filterQueries */
this.filterQueryUpdate = new Subject();
/* Stream that emits the initial value for some or all search filters */
this.populateFilters = new BehaviorSubject({});
this.categories = [];
this.queryFragments = {};
this.filterQueries = [];
this.filterRawParams = {};
this.paging = null;
this.sorting = [];
this.sortingOptions = [];
this._userQuery = '';
this.userFacetBuckets = {};
this.config = {
categories: []
};
// TODO: to be supported in future iterations
this.ranges = {};
this.resetToDefaults();
}
resetToDefaults(withNavigate = false) {
if (withNavigate) {
this.router.navigate([], {
queryParams: { q: null },
relativeTo: this.activatedRoute,
queryParamsHandling: 'merge'
});
}
const currentConfig = this.getDefaultConfiguration();
this.resetSearchOptions();
this.configUpdated.next(currentConfig);
this.searchForms.next(this.getSearchFormDetails());
this.setUpSearchConfiguration(currentConfig);
}
getDefaultConfiguration() {
const configurations = this.loadConfiguration();
if (Array.isArray(configurations)) {
if (this.selectedConfiguration !== undefined) {
return configurations[this.selectedConfiguration];
}
return configurations.find((configuration) => configuration.default);
}
return configurations;
}
updateSelectedConfiguration(index) {
const currentConfig = this.loadConfiguration();
if (Array.isArray(currentConfig) && currentConfig[index] !== undefined) {
this.selectedConfiguration = index;
this.configUpdated.next(currentConfig[index]);
this.searchForms.next(this.getSearchFormDetails());
this.resetSearchOptions();
this.setUpSearchConfiguration(currentConfig[index]);
this.update();
}
}
resetSearchOptions() {
this.categories = [];
this.queryFragments = {};
this.filterQueries = [];
this.sorting = [];
this.sortingOptions = [];
this.userFacetBuckets = {};
this.scope = null;
this.filterRawParams = {};
this._userQuery = '';
this.populateFilters.next({});
}
getSearchFormDetails() {
const configurations = this.loadConfiguration();
if (Array.isArray(configurations)) {
return configurations.map((configuration, index) => ({
index,
name: configuration.name || 'SEARCH.UNKNOWN_CONFIGURATION',
default: configuration.default || false,
selected: this.selectedConfiguration !== undefined ? index === this.selectedConfiguration : configuration.default
}));
}
else if (configurations) {
return [
{
index: 0,
name: configurations.name || 'SEARCH.UNKNOWN_CONFIGURATION',
default: true,
selected: true
}
];
}
return [];
}
setUpSearchConfiguration(currentConfiguration) {
if (currentConfiguration) {
this.config = JSON.parse(JSON.stringify(currentConfiguration));
this.categories = (this.config.categories || []).filter((category) => category.enabled);
this.filterQueries = this.config.filterQueries || [];
this.userFacetBuckets = {};
if (this.config.sorting) {
this.sorting = this.config.sorting.defaults || [];
this.sortingOptions = this.config.sorting.options || [];
}
}
}
/**
* Adds a facet bucket to a field.
*
* @param field The target field
* @param bucket Bucket to add
*/
addUserFacetBucket(field, bucket) {
if (field && bucket) {
const buckets = this.userFacetBuckets[field] || [];
const existing = buckets.find((facetBucket) => facetBucket.label === bucket.label);
if (!existing) {
buckets.push(bucket);
}
this.userFacetBuckets[field] = buckets;
}
}
/**
* Gets the buckets currently added to a field
*
* @param field The target fields
* @returns Bucket array
*/
getUserFacetBuckets(field) {
return this.userFacetBuckets[field] || [];
}
/**
* Removes an existing bucket from a field.
*
* @param field The target field
* @param bucket Bucket to remove
*/
removeUserFacetBucket(field, bucket) {
if (field && bucket) {
const buckets = this.userFacetBuckets[field] || [];
this.userFacetBuckets[field] = buckets.filter((facetBucket) => facetBucket.label !== bucket.label);
}
}
/**
* Adds a filter query to the current query.
*
* @param query Query string to add
*/
addFilterQuery(query) {
if (query) {
const existing = this.filterQueries.find((filterQuery) => filterQuery.query === query);
if (!existing) {
this.filterQueries.push({ query });
this.filterQueryUpdate.next();
}
}
}
/**
* Removes an existing filter query.
*
* @param query The query to remove
*/
removeFilterQuery(query) {
if (query) {
this.filterQueries = this.filterQueries.filter((filterQuery) => filterQuery.query !== query);
this.filterQueryUpdate.next();
}
}
/**
* Gets a facet query by label.
*
* @param label Label of the query
* @returns Facet query data
*/
getFacetQuery(label) {
if (label && this.hasFacetQueries) {
const result = this.config.facetQueries.queries.find((query) => query.label === label);
if (result) {
return { ...result };
}
}
return null;
}
/**
* Gets a facet field by label.
*
* @param label Label of the facet field
* @returns Facet field data
*/
getFacetField(label) {
if (label) {
const fields = this.config.facetFields.fields || [];
const result = fields.find((field) => field.label === label);
if (result) {
result.label = this.getSupportedLabel(result.label);
return { ...result };
}
}
return null;
}
setScope(scope) {
this.scope = scope;
}
getScope() {
return this.scope;
}
/**
* Builds the current query and triggers the `updated` event.
*
* @param queryBody query settings
*/
update(queryBody) {
const query = queryBody ? queryBody : this.buildQuery();
this.updated.next(query);
}
/**
* Builds and executes the current query.
*
* @param updateQueryParams whether query params should be updated with encoded query
* @param queryBody query settings
*/
async execute(updateQueryParams = true, queryBody) {
try {
const query = queryBody ? queryBody : this.buildQuery();
if (query) {
if (updateQueryParams) {
this.updateSearchQueryParams();
}
const resultSetPaging = await this.searchApi.search(query);
this.executed.next(resultSetPaging);
}
}
catch (error) {
this.error.next(error);
this.executed.next({
list: {
pagination: {
totalItems: 0
},
entries: []
}
});
}
}
search(queryBody) {
const promise = this.searchApi.search(queryBody);
promise.then((resultSetPaging) => {
this.executed.next(resultSetPaging);
});
return from(promise);
}
/**
* Builds the current query.
*
* @returns The finished query
*/
buildQuery() {
const query = this.getFinalQuery();
const include = this.config.include || [];
if (include.length === 0) {
include.push('path', 'allowableOperations');
}
if (query) {
const result = {
query: {
query,
language: SEARCH_LANGUAGE.AFTS
},
include,
paging: this.paging,
fields: this.config.fields,
filterQueries: this.filterQueries,
facetQueries: this.facetQueries,
facetIntervals: this.facetIntervals,
facetFields: this.facetFields,
sort: this.sort,
highlight: this.highlight
};
if (this.scope) {
result.scope = this.scope;
}
result['facetFormat'] = 'V2';
return result;
}
return null;
}
/**
* Gets the primary sorting definition.
*
* @returns The primary sorting definition
*/
getPrimarySorting() {
if (this.sorting?.length > 0) {
return this.sorting[0];
}
return null;
}
/**
* Gets all pre-configured sorting options that users can choose from.
*
* @returns Pre-configured sorting options
*/
getSortingOptions() {
return this.config?.sorting?.options || [];
}
/**
* Gets the query group.
*
* @param query Target query
* @returns Query group
*/
getQueryGroup(query) {
return query.group || this.config.facetQueries.label || 'Facet Queries';
}
/**
* Checks if FacetQueries has been defined
*
* @returns True if defined, false otherwise
*/
get hasFacetQueries() {
return this.config?.facetQueries?.queries?.length > 0;
}
/**
* Checks if FacetIntervals has been defined
*
* @returns True if defined, false otherwise
*/
get hasFacetIntervals() {
return this.config?.facetIntervals?.intervals?.length > 0;
}
get hasFacetHighlight() {
return !!this.config?.highlight;
}
get sort() {
return this.sorting.map((def) => ({
type: def.type,
field: def.field,
ascending: def.ascending
}));
}
get facetQueries() {
if (this.hasFacetQueries) {
return this.config.facetQueries.queries.map((query) => {
query.group = this.getQueryGroup(query);
return { ...query };
});
}
return null;
}
get facetIntervals() {
if (this.hasFacetIntervals) {
const configIntervals = this.config.facetIntervals;
return {
intervals: configIntervals.intervals.map((interval) => ({
label: this.getSupportedLabel(interval.label),
field: interval.field,
sets: interval.sets.map((set) => ({
label: this.getSupportedLabel(set.label),
start: set.start,
end: set.end,
startInclusive: set.startInclusive,
endInclusive: set.endInclusive
}))
}))
};
}
return null;
}
get highlight() {
return this.hasFacetHighlight ? this.config.highlight : null;
}
getFinalQuery() {
let query = '';
if (this.userQuery) {
this.filterRawParams['userQuery'] = this.userQuery;
}
this.categories.forEach((facet) => {
const customQuery = this.queryFragments[facet.id];
if (customQuery) {
if (query.length > 0) {
query += ' AND ';
}
query += `(${customQuery})`;
}
});
let result = [this.userQuery, query].filter((entry) => entry).join(' AND ');
if (this.userFacetBuckets) {
Object.keys(this.userFacetBuckets).forEach((key) => {
const subQuery = (this.userFacetBuckets[key] || [])
.filter((bucket) => bucket.filterQuery)
.map((bucket) => bucket.filterQuery)
.join(' OR ');
if (subQuery) {
if (result.length > 0) {
result += ' AND ';
}
result += `(${subQuery})`;
}
});
}
return result;
}
get facetFields() {
const facetFields = this.config.facetFields?.fields;
if (facetFields?.length > 0) {
return {
facets: facetFields.map((facet) => ({
field: facet.field,
mincount: facet.mincount,
label: this.getSupportedLabel(facet.label),
limit: facet.limit,
offset: facet.offset,
prefix: facet.prefix
}))
};
}
return null;
}
/**
* Encloses a label name with double quotes if it contains whitespace characters.
*
* @param configLabel Original label text
* @returns Label, possibly with quotes if it contains spaces
*/
getSupportedLabel(configLabel) {
const spaceInsideLabelIndex = configLabel.search(/\s/g);
if (spaceInsideLabelIndex > -1) {
return `"${configLabel}"`;
}
return configLabel;
}
/**
* Encodes filter configuration stored in filterRawParams object.
*/
encodeQuery() {
this.encodedQuery = Buffer.from(JSON.stringify(this.filterRawParams)).toString('base64');
}
/**
* Encodes existing filters configuration and updates search query param value.
*/
updateSearchQueryParams() {
this.encodeQuery();
this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams: { q: this.encodedQuery },
queryParamsHandling: 'merge'
});
}
/**
* Builds search query with provided user query, executes query, encodes latest filter config and navigates to search.
*
* @param query user query to search for
* @param searchUrl search url to navigate to
*/
async navigateToSearch(query, searchUrl) {
this.userQuery = query;
await this.execute();
await this.router.navigate([searchUrl], {
queryParams: { q: this.encodedQuery },
queryParamsHandling: 'merge'
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1xdWVyeS1idWlsZGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL3NlYXJjaC9zZXJ2aWNlcy9iYXNlLXF1ZXJ5LWJ1aWxkZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBYyxhQUFhLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRWpGLE9BQU8sRUFNSCxlQUFlLEVBQ2YsU0FBUyxFQUVaLE1BQU0sa0JBQWtCLENBQUM7QUFXMUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNoQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFekQsTUFBTSxPQUFnQix1QkFBdUI7SUFJekMsSUFBSSxTQUFTO1FBQ1QsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMzQixDQUFDO0lBd0NELElBQUksU0FBUztRQUNULE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMzQixDQUFDO0lBRUQsSUFBSSxTQUFTLENBQUMsS0FBYTtRQUN2QixLQUFLLEdBQUcsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNo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KiBDb3B5cmlnaHQgwqkgMjAwNS0yMDI1IEh5bGFuZCBTb2Z0d2FyZSwgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgZnJvbSwgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgQXBwQ29uZmlnU2VydmljZSB9IGZyb20gJ0BhbGZyZXNjby9hZGYtY29yZSc7XG5pbXBvcnQge1xuICAgIFJlcXVlc3RGYWNldEZpZWxkcyxcbiAgICBSZXF1ZXN0SGlnaGxpZ2h0LFxuICAgIFJlcXVlc3RTY29wZSxcbiAgICBSZXF1ZXN0U29ydERlZmluaXRpb25Jbm5lcixcbiAgICBSZXN1bHRTZXRQYWdpbmcsXG4gICAgU0VBUkNIX0xBTkdVQUdFLFxuICAgIFNlYXJjaEFwaSxcbiAgICBTZWFyY2hSZXF1ZXN0XG59IGZyb20gJ0BhbGZyZXNjby9qcy1hcGknO1xuaW1wb3J0IHsgU2VhcmNoQ2F0ZWdvcnkgfSBmcm9tICcuLi9tb2RlbHMvc2VhcmNoLWNhdGVnb3J5LmludGVyZmFjZSc7XG5pbXBvcnQgeyBGaWx0ZXJRdWVyeSB9IGZyb20gJy4uL21vZGVscy9maWx0ZXItcXVlcnkuaW50ZXJmYWNlJztcbmltcG9ydCB7IFNlYXJjaFJhbmdlIH0gZnJvbSAnLi4vbW9kZWxzL3NlYXJjaC1yYW5nZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgU2VhcmNoQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL21vZGVscy9zZWFyY2gtY29uZmlndXJhdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRmFjZXRRdWVyeSB9IGZyb20gJy4uL21vZGVscy9mYWNldC1xdWVyeS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgU2VhcmNoU29ydGluZ0RlZmluaXRpb24gfSBmcm9tICcuLi9tb2RlbHMvc2VhcmNoLXNvcnRpbmctZGVmaW5pdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRmFjZXRGaWVsZCB9IGZyb20gJy4uL21vZGVscy9mYWNldC1maWVsZC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRmFjZXRGaWVsZEJ1Y2tldCB9IGZyb20gJy4uL21vZGVscy9mYWNldC1maWVsZC1idWNrZXQuaW50ZXJmYWNlJztcbmltcG9ydCB7IFNlYXJjaEZvcm0gfSBmcm9tICcuLi9tb2RlbHMvc2VhcmNoLWZvcm0uaW50ZXJmYWNlJztcbmltcG9ydCB7IEFsZnJlc2NvQXBpU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FsZnJlc2NvLWFwaS5zZXJ2aWNlJztcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5pbXBvcnQgeyBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZVF1ZXJ5QnVpbGRlclNlcnZpY2Uge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcm91dGVyID0gaW5qZWN0KFJvdXRlcik7XG4gICAgcHJpdmF0ZSByZWFkb25seSBhY3RpdmF0ZWRSb3V0ZSA9IGluamVjdChBY3RpdmF0ZWRSb3V0ZSk7XG4gICAgcHJpdmF0ZSBfc2VhcmNoQXBpOiBTZWFyY2hBcGk7XG4gICAgZ2V0IHNlYXJjaEFwaSgpOiBTZWFyY2hBcGkge1xuICAgICAgICB0aGlzLl9zZWFyY2hBcGkgPSB0aGlzLl9zZWFyY2hBcGkgPz8gbmV3IFNlYXJjaEFwaSh0aGlzLmFsZnJlc2NvQXBpU2VydmljZS5nZXRJbnN0YW5jZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlYXJjaEFwaTtcbiAgICB9XG5cbiAgICAvKiAgU3RyZWFtIHRoYXQgZW1pdHMgdGhlIHNlYXJjaCBjb25maWd1cmF0aW9uIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZSB0aGUgc2VhcmNoIGZvcm1zICovXG4gICAgY29uZmlnVXBkYXRlZCA9IG5ldyBTdWJqZWN0PFNlYXJjaENvbmZpZ3VyYXRpb24+KCk7XG5cbiAgICAvKiAgU3RyZWFtIHRoYXQgZW1pdHMgdGhlIGV2ZW50IGVhY2ggdGltZSB3aGVuIHNlYXJjaCBmaWx0ZXIgZmluaXNoZXMgbG9hZGluZyBpbml0aWFsIHZhbHVlICovXG4gICAgZmlsdGVyTG9hZGVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIC8qICBTdHJlYW0gdGhhdCBlbWl0cyB0aGUgcXVlcnkgYmVmb3JlIHNlYXJjaCB3aGVuZXZlciB1c2VyIHNlYXJjaCAgKi9cbiAgICB1cGRhdGVkID0gbmV3IFN1YmplY3Q8U2VhcmNoUmVxdWVzdD4oKTtcblxuICAgIC8qICBTdHJlYW0gdGhhdCBlbWl0cyB0aGUgcmVzdWx0cyB3aGVuZXZlciB1c2VyIHNlYXJjaCAgKi9cbiAgICBleGVjdXRlZCA9IG5ldyBTdWJqZWN0PFJlc3VsdFNldFBhZ2luZz4oKTtcblxuICAgIC8qICBTdHJlYW0gdGhhdCBlbWl0cyB0aGUgZXJyb3Igd2hlbmV2ZXIgdXNlciBzZWFyY2ggICovXG4gICAgZXJyb3IgPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgLyogIFN0cmVhbSB0aGF0IGVtaXRzIHNlYXJjaCBmb3JtcyAgKi9cbiAgICBzZWFyY2hGb3JtcyA9IG5ldyBSZXBsYXlTdWJqZWN0PFNlYXJjaEZvcm1bXT4oMSk7XG5cbiAgICAvKiAgU3RyZWFtIHRoYXQgZW1pdHMgdm9pZCB3aGVuIGNoYW5nZSBpbiBmaWx0ZXJRdWVyaWVzICAqL1xuICAgIGZpbHRlclF1ZXJ5VXBkYXRlID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIC8qICBTdHJlYW0gdGhhdCBlbWl0cyB0aGUgaW5pdGlhbCB2YWx1ZSBmb3Igc29tZSBvciBhbGwgc2VhcmNoIGZpbHRlcnMgKi9cbiAgICBwb3B1bGF0ZUZpbHRlcnMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHsgW2tleTogc3RyaW5nXTogYW55IH0+KHt9KTtcblxuICAgIGNhdGVnb3JpZXM6IFNlYXJjaENhdGVnb3J5W10gPSBbXTtcbiAgICBxdWVyeUZyYWdtZW50czogeyBbaWQ6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gICAgZmlsdGVyUXVlcmllczogRmlsdGVyUXVlcnlbXSA9IFtdO1xuICAgIGZpbHRlclJhd1BhcmFtczogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHt9O1xuICAgIHBhZ2luZzogeyBtYXhJdGVtcz86IG51bWJlcjsgc2tpcENvdW50PzogbnVtYmVyIH0gPSBudWxsO1xuICAgIHNvcnRpbmc6IFNlYXJjaFNvcnRpbmdEZWZpbml0aW9uW10gPSBbXTtcbiAgICBzb3J0aW5nT3B0aW9uczogU2VhcmNoU29ydGluZ0RlZmluaXRpb25bXSA9IFtdO1xuICAgIHByaXZhdGUgZW5jb2RlZFF1ZXJ5OiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBzY29wZTogUmVxdWVzdFNjb3BlO1xuICAgIHByaXZhdGUgc2VsZWN0ZWRDb25maWd1cmF0aW9uOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfdXNlclF1ZXJ5ID0gJyc7XG5cbiAgICBwcm90ZWN0ZWQgdXNlckZhY2V0QnVja2V0czogeyBba2V5OiBzdHJpbmddOiBGYWNldEZpZWxkQnVja2V0W10gfSA9IHt9O1xuXG4gICAgZ2V0IHVzZXJRdWVyeSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5fdXNlclF1ZXJ5O1xuICAgIH1cblxuICAgIHNldCB1c2VyUXVlcnkodmFsdWU6IHN0cmluZykge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSB8fCAnJykudHJpbSgpO1xuICAgICAgICB0aGlzLl91c2VyUXVlcnkgPSB2YWx1ZSA/IGAoJHt2YWx1ZX0pYCA6ICcnO1xuICAgIH1cblxuICAgIGNvbmZpZzogU2VhcmNoQ29uZmlndXJhdGlvbiA9IHtcbiAgICAgICAgY2F0ZWdvcmllczogW11cbiAgICB9O1xuXG4gICAgLy8gVE9ETzogdG8gYmUgc3VwcG9ydGVkIGluIGZ1dHVyZSBpdGVyYXRpb25zXG4gICAgcmFuZ2VzOiB7IFtpZDogc3RyaW5nXTogU2VhcmNoUmFuZ2UgfSA9IHt9O1xuXG4gICAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBhcHBDb25maWc6IEFwcENvbmZpZ1NlcnZpY2UsIHByb3RlY3RlZCByZWFkb25seSBhbGZyZXNjb0FwaVNlcnZpY2U6IEFsZnJlc2NvQXBpU2VydmljZSkge1xuICAgICAgICB0aGlzLnJlc2V0VG9EZWZhdWx0cygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhYnN0cmFjdCBsb2FkQ29uZmlndXJhdGlvbigpOiBTZWFyY2hDb25maWd1cmF0aW9uIHwgU2VhcmNoQ29uZmlndXJhdGlvbltdO1xuXG4gICAgcHVibGljIGFic3RyYWN0IGlzRmlsdGVyU2VydmljZUFjdGl2ZSgpOiBib29sZWFuO1xuXG4gICAgcHVibGljIHJlc2V0VG9EZWZhdWx0cyh3aXRoTmF2aWdhdGUgPSBmYWxzZSkge1xuICAgICAgICBpZiAod2l0aE5hdmlnYXRlKSB7XG4gICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXSwge1xuICAgICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zOiB7IHE6IG51bGwgfSxcbiAgICAgICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2YXRlZFJvdXRlLFxuICAgICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zSGFuZGxpbmc6ICdtZXJnZSdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGN1cnJlbnRDb25maWcgPSB0aGlzLmdldERlZmF1bHRDb25maWd1cmF0aW9uKCk7XG4gICAgICAgIHRoaXMucmVzZXRTZWFyY2hPcHRpb25zKCk7XG4gICAgICAgIHRoaXMuY29uZmlnVXBkYXRlZC5uZXh0KGN1cnJlbnRDb25maWcpO1xuICAgICAgICB0aGlzLnNlYXJjaEZvcm1zLm5leHQodGhpcy5nZXRTZWFyY2hGb3JtRGV0YWlscygpKTtcbiAgICAgICAgdGhpcy5zZXRVcFNlYXJjaENvbmZpZ3VyYXRpb24oY3VycmVudENvbmZpZyk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldERlZmF1bHRDb25maWd1cmF0aW9uKCk6IFNlYXJjaENvbmZpZ3VyYXRpb24gfCB1bmRlZmluZWQge1xuICAgICAgICBjb25zdCBjb25maWd1cmF0aW9ucyA9IHRoaXMubG9hZENvbmZpZ3VyYXRpb24oKTtcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb25maWd1cmF0aW9ucykpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkQ29uZmlndXJhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbmZpZ3VyYXRpb25zW3RoaXMuc2VsZWN0ZWRDb25maWd1cmF0aW9uXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGNvbmZpZ3VyYXRpb25zLmZpbmQoKGNvbmZpZ3VyYXRpb24pID0+IGNvbmZpZ3VyYXRpb24uZGVmYXVsdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbmZpZ3VyYXRpb25zO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVTZWxlY3RlZENvbmZpZ3VyYXRpb24oaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjdXJyZW50Q29uZmlnID0gdGhpcy5sb2FkQ29uZmlndXJhdGlvbigpO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50Q29uZmlnKSAmJiBjdXJyZW50Q29uZmlnW2luZGV4XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkQ29uZmlndXJhdGlvbiA9IGluZGV4O1xuICAgICAgICAgICAgdGhpcy5jb25maWdVcGRhdGVkLm5leHQoY3VycmVudENvbmZpZ1tpbmRleF0pO1xuICAgICAgICAgICAgdGhpcy5zZWFyY2hGb3Jtcy5uZXh0KHRoaXMuZ2V0U2VhcmNoRm9ybURldGFpbHMoKSk7XG4gICAgICAgICAgICB0aGlzLnJlc2V0U2VhcmNoT3B0aW9ucygpO1xuICAgICAgICAgICAgdGhpcy5zZXRVcFNlYXJjaENvbmZpZ3VyYXRpb24oY3VycmVudENvbmZpZ1tpbmRleF0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVzZXRTZWFyY2hPcHRpb25zKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmNhdGVnb3JpZXMgPSBbXTtcbiAgICAgICAgdGhpcy5xdWVyeUZyYWdtZW50cyA9IHt9O1xuICAgICAgICB0aGlzLmZpbHRlclF1ZXJpZXMgPSBbXTtcbiAgICAgICAgdGhpcy5zb3J0aW5nID0gW107XG4gICAgICAgIHRoaXMuc29ydGluZ09wdGlvbnMgPSBbXTtcbiAgICAgICAgdGhpcy51c2VyRmFjZXRCdWNrZXRzID0ge307XG4gICAgICAgIHRoaXMuc2NvcGUgPSBudWxsO1xuICAgICAgICB0aGlzLmZpbHRlclJhd1BhcmFtcyA9IHt9O1xuICAgICAgICB0aGlzLl91c2VyUXVlcnkgPSAnJztcbiAgICAgICAgdGhpcy5wb3B1bGF0ZUZpbHRlcnMubmV4dCh7fSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNlYXJjaEZvcm1EZXRhaWxzKCk6IFNlYXJjaEZvcm1bXSB7XG4gICAgICAgIGNvbnN0IGNvbmZpZ3VyYXRpb25zID0gdGhpcy5sb2FkQ29uZmlndXJhdGlvbigpO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb25maWd1cmF0aW9ucykpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25maWd1cmF0aW9ucy5tYXAoKGNvbmZpZ3VyYXRpb24sIGluZGV4KSA9PiAoe1xuICAgICAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgICAgIG5hbWU6IGNvbmZpZ3VyYXRpb24ubmFtZSB8fCAnU0VBUkNILlVOS05PV05fQ09ORklHVVJBVElPTicsXG4gICAgICAgICAgICAgICAgZGVmYXVsdDogY29uZmlndXJhdGlvbi5kZWZhdWx0IHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkOiB0aGlzLnNlbGVjdGVkQ29uZmlndXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gaW5kZXggPT09IHRoaXMuc2VsZWN0ZWRDb25maWd1cmF0aW9uIDogY29uZmlndXJhdGlvbi5kZWZhdWx0XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH0gZWxzZSBpZiAoY29uZmlndXJhdGlvbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogY29uZmlndXJhdGlvbnMubmFtZSB8fCAnU0VBUkNILlVOS05PV05fQ09ORklHVVJBVElPTicsXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkOiB0cnVlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXRVcFNlYXJjaENvbmZpZ3VyYXRpb24oY3VycmVudENvbmZpZ3VyYXRpb246IFNlYXJjaENvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgaWYgKGN1cnJlbnRDb25maWd1cmF0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZyA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoY3VycmVudENvbmZpZ3VyYXRpb24pKTtcbiAgICAgICAgICAgIHRoaXMuY2F0ZWdvcmllcyA9ICh0aGlzLmNvbmZpZy5jYXRlZ29yaWVzIHx8IFtdKS5maWx0ZXIoKGNhdGVnb3J5KSA9PiBjYXRlZ29yeS5lbmFibGVkKTtcbiAgICAgICAgICAgIHRoaXMuZmlsdGVyUXVlcmllcyA9IHRoaXMuY29uZmlnLmZpbHRlclF1ZXJpZXMgfHwgW107XG4gICAgICAgICAgICB0aGlzLnVzZXJGYWNldEJ1Y2tldHMgPSB7fTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zb3J0aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zb3J0aW5nID0gdGhpcy5jb25maWcuc29ydGluZy5kZWZhdWx0cyB8fCBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLnNvcnRpbmdPcHRpb25zID0gdGhpcy5jb25maWcuc29ydGluZy5vcHRpb25zIHx8IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGZhY2V0IGJ1Y2tldCB0byBhIGZpZWxkLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpZWxkIFRoZSB0YXJnZXQgZmllbGRcbiAgICAgKiBAcGFyYW0gYnVja2V0IEJ1Y2tldCB0byBhZGRcbiAgICAgKi9cbiAgICBhZGRVc2VyRmFjZXRCdWNrZXQoZmllbGQ6IHN0cmluZywgYnVja2V0OiBGYWNldEZpZWxkQnVja2V0KSB7XG4gICAgICAgIGlmIChmaWVsZCAmJiBidWNrZXQpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1Y2tldHMgPSB0aGlzLnVzZXJGYWNldEJ1Y2tldHNbZmllbGRdIHx8IFtdO1xuICAgICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBidWNrZXRzLmZpbmQoKGZhY2V0QnVja2V0KSA9PiBmYWNldEJ1Y2tldC5sYWJlbCA9PT0gYnVja2V0LmxhYmVsKTtcbiAgICAgICAgICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgICAgICAgICAgICBidWNrZXRzLnB1c2goYnVja2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXNlckZhY2V0QnVja2V0c1tmaWVsZF0gPSBidWNrZXRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYnVja2V0cyBjdXJyZW50bHkgYWRkZWQgdG8gYSBmaWVsZFxuICAgICAqXG4gICAgICogQHBhcmFtIGZpZWxkIFRoZSB0YXJnZXQgZmllbGRzXG4gICAgICogQHJldHVybnMgQnVja2V0IGFycmF5XG4gICAgICovXG4gICAgZ2V0VXNlckZhY2V0QnVja2V0cyhmaWVsZDogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVzZXJGYWNldEJ1Y2tldHNbZmllbGRdIHx8IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYW4gZXhpc3RpbmcgYnVja2V0IGZyb20gYSBmaWVsZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmaWVsZCBUaGUgdGFyZ2V0IGZpZWxkXG4gICAgICogQHBhcmFtIGJ1Y2tldCBCdWNrZXQgdG8gcmVtb3ZlXG4gICAgICovXG4gICAgcmVtb3ZlVXNlckZhY2V0QnVja2V0KGZpZWxkOiBzdHJpbmcsIGJ1Y2tldDogRmFjZXRGaWVsZEJ1Y2tldCkge1xuICAgICAgICBpZiAoZmllbGQgJiYgYnVja2V0KSB7XG4gICAgICAgICAgICBjb25zdCBidWNrZXRzID0gdGhpcy51c2VyRmFjZXRCdWNrZXRzW2ZpZWxkXSB8fCBbXTtcbiAgICAgICAgICAgIHRoaXMudXNlckZhY2V0QnVja2V0c1tmaWVsZF0gPSBidWNrZXRzLmZpbHRlcigoZmFjZXRCdWNrZXQpID0+IGZhY2V0QnVja2V0LmxhYmVsICE9PSBidWNrZXQubGFiZWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGZpbHRlciBxdWVyeSB0byB0aGUgY3VycmVudCBxdWVyeS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBxdWVyeSBRdWVyeSBzdHJpbmcgdG8gYWRkXG4gICAgICovXG4gICAgYWRkRmlsdGVyUXVlcnkocXVlcnk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZiAocXVlcnkpIHtcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5maWx0ZXJRdWVyaWVzLmZpbmQoKGZpbHRlclF1ZXJ5KSA9PiBmaWx0ZXJRdWVyeS5xdWVyeSA9PT0gcXVlcnkpO1xuICAgICAgICAgICAgaWYgKCFleGlzdGluZykge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyUXVlcmllcy5wdXNoKHsgcXVlcnkgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJRdWVyeVVwZGF0ZS5uZXh0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFuIGV4aXN0aW5nIGZpbHRlciBxdWVyeS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBxdWVyeSBUaGUgcXVlcnkgdG8gcmVtb3ZlXG4gICAgICovXG4gICAgcmVtb3ZlRmlsdGVyUXVlcnkocXVlcnk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZiAocXVlcnkpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsdGVyUXVlcmllcyA9IHRoaXMuZmlsdGVyUXVlcmllcy5maWx0ZXIoKGZpbHRlclF1ZXJ5KSA9PiBmaWx0ZXJRdWVyeS5xdWVyeSAhPT0gcXVlcnkpO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJRdWVyeVVwZGF0ZS5uZXh0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgZmFjZXQgcXVlcnkgYnkgbGFiZWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbGFiZWwgTGFiZWwgb2YgdGhlIHF1ZXJ5XG4gICAgICogQHJldHVybnMgRmFjZXQgcXVlcnkgZGF0YVxuICAgICAqL1xuICAgIGdldEZhY2V0UXVlcnkobGFiZWw6IHN0cmluZyk6IEZhY2V0UXVlcnkge1xuICAgICAgICBpZiAobGFiZWwgJiYgdGhpcy5oYXNGYWNldFF1ZXJpZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuY29uZmlnLmZhY2V0UXVlcmllcy5xdWVyaWVzLmZpbmQoKHF1ZXJ5KSA9PiBxdWVyeS5sYWJlbCA9PT0gbGFiZWwpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLnJlc3VsdCB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYSBmYWNldCBmaWVsZCBieSBsYWJlbC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBsYWJlbCBMYWJlbCBvZiB0aGUgZmFjZXQgZmllbGRcbiAgICAgKiBAcmV0dXJucyBGYWNldCBmaWVsZCBkYXRhXG4gICAgICovXG4gICAgZ2V0RmFjZXRGaWVsZChsYWJlbDogc3RyaW5nKTogRmFjZXRGaWVsZCB7XG4gICAgICAgIGlmIChsYWJlbCkge1xuICAgICAgICAgICAgY29uc3QgZmllbGRzID0gdGhpcy5jb25maWcuZmFjZXRGaWVsZHMuZmllbGRzIHx8IFtdO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gZmllbGRzLmZpbmQoKGZpZWxkKSA9PiBmaWVsZC5sYWJlbCA9PT0gbGFiZWwpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5sYWJlbCA9IHRoaXMuZ2V0U3VwcG9ydGVkTGFiZWwocmVzdWx0LmxhYmVsKTtcbiAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5yZXN1bHQgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1