@knora/core
Version:
Knora ui module: core
208 lines (197 loc) • 32.9 kB
JavaScript
import * as tslib_1 from "tslib";
var GravsearchGenerationService_1;
import { Injectable } from '@angular/core';
import { Constants } from '@knora/api';
import { KnoraConstants, KnoraSchema } from '../../declarations/api/knora-constants';
import { ExtendedSearchParams, SearchParamsService } from './search-params.service';
import * as i0 from "@angular/core";
import * as i1 from "./search-params.service";
/**
* @deprecated Use new service from `@knora/api` (github:dasch-swiss/knora-api-js-lib) instead
*
* Create GravSearch queries from provided parameters.
*/
let GravsearchGenerationService = GravsearchGenerationService_1 = class GravsearchGenerationService {
constructor(_searchParamsService) {
this._searchParamsService = _searchParamsService;
}
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
*
* Generates a Gravsearch query from the provided arguments.
*
* @param {PropertyWithValue[]} properties the properties specified by the user.
* @param {string} [mainResourceClassOption] the class of the main resource, if specified.
* @param {number} offset the offset to be used (nth page of results).
* @returns string - a KnarQL query string.
*/
createGravsearchQuery(properties, mainResourceClassOption, offset = 0) {
// class restriction for the resource searched for
let mainResourceClass = '';
// if given, create the class restriction for the main resource
if (mainResourceClassOption !== undefined) {
mainResourceClass = `?mainRes a <${mainResourceClassOption}> .`;
}
// criteria for the order by statement
const orderByCriteria = [];
// statements to be returned in query results
const returnStatements = [];
// loop over given properties and create statements and filters from them
const props = properties.map((propWithVal, index) => {
// represents the object of a statement
let propValue;
if (!propWithVal.property.isLinkProperty || propWithVal.valueLiteral.comparisonOperator.getClassName() === 'Exists') {
// it is not a linking property, create a variable for the value (to be used by a subsequent FILTER)
// OR the comparison operator Exists is used in which case we do not need to specify the object any further
propValue = `?propVal${index}`;
}
else {
// it is a linking property and the comparison operator is not Exists, use its IRI
propValue = propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex);
}
// generate statement
let statement = `?mainRes <${propWithVal.property.id}> ${propValue} .`;
// check if it is a linking property that has to be wrapped in a FILTER NOT EXISTS (comparison operator NOT_EQUALS) to negate it
if (propWithVal.property.isLinkProperty && propWithVal.valueLiteral.comparisonOperator.getClassName() === 'NotEquals') {
// do not include statement in results, because the query checks for the absence of this statement
statement = `FILTER NOT EXISTS {
${statement}
}`;
}
else {
// TODO: check if statement should be returned returned in results (Boolean flag from checkbox)
returnStatements.push(statement);
statement = `
${statement}
`;
}
// generate restricting expression (e.g., a FILTER) if comparison operator is not Exists
let restriction = '';
// only create a FILTER if the comparison operator is not EXISTS and it is not a linking property
if (!propWithVal.property.isLinkProperty && propWithVal.valueLiteral.comparisonOperator.getClassName() !== 'Exists') {
// generate variable for value literal
const propValueLiteral = `${propValue}Literal`;
if (propWithVal.valueLiteral.comparisonOperator.getClassName() === 'Like') {
// generate statement to value literal
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propValueLiteral}` + '\n';
// use regex function for LIKE
restriction += `FILTER regex(${propValueLiteral}, ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)}, "i")`;
}
else if (propWithVal.valueLiteral.comparisonOperator.getClassName() === 'Match') {
// generate statement to value literal
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propValueLiteral}` + '\n';
// use contains function for MATCH
restriction += `FILTER <${KnoraConstants.MatchFunction}>(${propValueLiteral}, ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)})`;
}
else if (propWithVal.property.objectType === Constants.DateValue) {
// handle date property
restriction = `FILTER(knora-api:toSimpleDate(${propValue}) ${propWithVal.valueLiteral.comparisonOperator.type} ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)})`;
}
else if (propWithVal.property.objectType === Constants.ListValue) {
// handle list node
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)}` + '\n';
// check for comparison operator "not equals"
if (propWithVal.valueLiteral.comparisonOperator.getClassName() === 'NotEquals') {
restriction = `FILTER NOT EXISTS {
${restriction}
}`;
}
}
else {
// generate statement to value literal
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propValueLiteral}` + '\n';
// generate filter expression
restriction += `FILTER(${propValueLiteral} ${propWithVal.valueLiteral.comparisonOperator.type} ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)})`;
}
}
// check if current value is a sort criterion
if (propWithVal.isSortCriterion)
orderByCriteria.push(propValue);
return `${statement}
${restriction}
`;
});
let orderByStatement = '';
if (orderByCriteria.length > 0) {
orderByStatement = `
ORDER BY ${orderByCriteria.join(' ')}
`;
}
// template of the Gravsearch query with dynamic components
const gravsearchTemplate = `
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
CONSTRUCT {
?mainRes knora-api:isMainResource true .
${returnStatements.join('\n')}
} WHERE {
?mainRes a knora-api:Resource .
${mainResourceClass}
${props.join('')}
}
${orderByStatement}`;
// offset component of the Gravsearch query
const offsetTemplate = `
OFFSET ${offset}
`;
// function that generates the same KnarQL query with the given offset
const generateGravsearchQueryWithCustomOffset = (localOffset) => {
const offsetCustomTemplate = `
OFFSET ${localOffset}
`;
return gravsearchTemplate + offsetCustomTemplate;
};
if (offset === 0) {
// store the function so another KnarQL query can be created with an increased offset
this._searchParamsService.changeSearchParamsMsg(new ExtendedSearchParams(generateGravsearchQueryWithCustomOffset));
}
return gravsearchTemplate + offsetTemplate;
}
};
/**
* @ignore
*
* Map of complex knora-api value types to simple ones.
* Use computed property name: http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
*/
GravsearchGenerationService.typeConversionComplexToSimple = {
'http://api.knora.org/ontology/knora-api/v2#IntValue': Constants.XsdInteger,
'http://api.knora.org/ontology/knora-api/v2#DecimalValue': Constants.XsdDecimal,
'http://api.knora.org/ontology/knora-api/v2#BooleanValue': Constants.XsdBoolean,
'http://api.knora.org/ontology/knora-api/v2#TextValue': Constants.XsdString,
'http://api.knora.org/ontology/knora-api/v2#UriValue': Constants.XsdAnyUri,
'http://api.knora.org/ontology/knora-api/v2#DateValue': KnoraConstants.dateSimple,
'http://api.knora.org/ontology/knora-api/v2#IntervalValue': KnoraConstants.intervalSimple,
'http://api.knora.org/ontology/knora-api/v2#GeomValue': KnoraConstants.geomSimple,
'http://api.knora.org/ontology/knora-api/v2#ColorValue': KnoraConstants.colorSimple,
'http://api.knora.org/ontology/knora-api/v2#GeonameValue': KnoraConstants.geonameSimple,
'http://api.knora.org/ontology/knora-api/v2#StillImageFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#FileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#MovingImageFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#DDDFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#AudioFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#DocumentFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#TextFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#ListValue': KnoraConstants.listNodeSimple
};
GravsearchGenerationService.complexTypeToProp = {
'http://api.knora.org/ontology/knora-api/v2#IntValue': Constants.IntValueAsInt,
'http://api.knora.org/ontology/knora-api/v2#DecimalValue': Constants.DecimalValueAsDecimal,
'http://api.knora.org/ontology/knora-api/v2#BooleanValue': Constants.BooleanValueAsBoolean,
'http://api.knora.org/ontology/knora-api/v2#TextValue': Constants.ValueAsString,
'http://api.knora.org/ontology/knora-api/v2#UriValue': Constants.UriValueAsUri,
'http://api.knora.org/ontology/knora-api/v2#ListValue': Constants.ListValueAsListNode
};
GravsearchGenerationService.ctorParameters = () => [
{ type: SearchParamsService }
];
GravsearchGenerationService.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function GravsearchGenerationService_Factory() { return new GravsearchGenerationService(i0.ɵɵinject(i1.SearchParamsService)); }, token: GravsearchGenerationService, providedIn: "root" });
GravsearchGenerationService = GravsearchGenerationService_1 = tslib_1.__decorate([
Injectable({
providedIn: 'root'
}),
tslib_1.__metadata("design:paramtypes", [SearchParamsService])
], GravsearchGenerationService);
export { GravsearchGenerationService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3Jhdi1zZWFyY2guc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0Brbm9yYS9jb3JlLyIsInNvdXJjZXMiOlsibGliL3NlcnZpY2VzL3YyL2dyYXYtc2VhcmNoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFdkMsT0FBTyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUdyRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7O0FBRXBGOzs7O0dBSUc7QUFJSCxJQUFhLDJCQUEyQixtQ0FBeEMsTUFBYSwyQkFBMkI7SUFzQ3BDLFlBQW9CLG9CQUF5QztRQUF6Qyx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQXFCO0lBQUksQ0FBQztJQUVsRTs7Ozs7Ozs7Ozs7T0FXRztJQUNILHFCQUFxQixDQUFDLFVBQStCLEVBQUUsdUJBQWdDLEVBQUUsU0FBaUIsQ0FBQztRQUV2RyxrREFBa0Q7UUFDbEQsSUFBSSxpQkFBaUIsR0FBRyxFQUFFLENBQUM7UUFFM0IsK0RBQStEO1FBQy9ELElBQUksdUJBQXVCLEtBQUssU0FBUyxFQUFFO1lBQ3ZDLGlCQUFpQixHQUFHLGVBQWUsdUJBQXVCLEtBQUssQ0FBQztTQUNuRTtRQUVELHNDQUFzQztRQUN0QyxNQUFNLGVBQWUsR0FBRyxFQUFFLENBQUM7UUFFM0IsNkNBQTZDO1FBQzdDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO1FBRTVCLHlFQUF5RTtRQUN6RSxNQUFNLEtBQUssR0FBYSxVQUFVLENBQUMsR0FBRyxDQUNsQyxDQUFDLFdBQThCLEVBQUUsS0FBYSxFQUFFLEVBQUU7WUFFOUMsdUNBQXVDO1lBQ3ZDLElBQUksU0FBUyxDQUFDO1lBQ2QsSUFBSSxDQUFDLFdBQVcs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LGNBQWMsQ0FBQyxhQUFhO0lBQ3ZGLGdFQUFnRSxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQzNGLHNEQUFzRCxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQ2pGLGlFQUFpRSxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQzVGLHlEQUF5RCxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQ3BGLDJEQUEyRCxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQ3RGLDhEQUE4RCxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQ3pGLDBEQUEwRCxFQUFFLGNBQWMsQ0FBQyxVQUFVO0lBQ3JGLHNEQUFzRCxFQUFFLGNBQWMsQ0FBQyxjQUFjO0NBQ3hGLENBQUM7QUFFWSw2Q0FBaUIsR0FBRztJQUM5QixxREFBcUQsRUFBRSxTQUFTLENBQUMsYUFBYTtJQUM5RSx5REFBeUQsRUFBRSxTQUFTLENBQUMscUJBQXFCO0lBQzFGLHlEQUF5RCxFQUFFLFNBQVMsQ0FBQyxxQkFBcUI7SUFDMUYsc0RBQXNELEVBQUUsU0FBUyxDQUFDLGFBQWE7SUFDL0UscURBQXFELEVBQUUsU0FBUyxDQUFDLGFBQWE7SUFDOUUsc0RBQXNELEVBQUUsU0FBUyxDQUFDLG1CQUFtQjtDQUN4RixDQUFDOztZQUV3QyxtQkFBbUI7OztBQXRDcEQsMkJBQTJCO0lBSHZDLFVBQVUsQ0FBQztRQUNSLFVBQVUsRUFBRSxNQUFNO0tBQ3JCLENBQUM7NkNBdUM0QyxtQkFBbUI7R0F0Q3BELDJCQUEyQixDQTBNdkM7U0ExTVksMkJBQTJCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RhbnRzIH0gZnJvbSAnQGtub3JhL2FwaSc7XG5cbmltcG9ydCB7IEtub3JhQ29uc3RhbnRzLCBLbm9yYVNjaGVtYSB9IGZyb20gJy4uLy4uL2RlY2xhcmF0aW9ucy9hcGkva25vcmEtY29uc3RhbnRzJztcbmltcG9ydCB7IFByb3BlcnR5V2l0aFZhbHVlIH0gZnJvbSAnLi4vLi4vZGVjbGFyYXRpb25zL2FwaS9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBFeHRlbmRlZFNlYXJjaFBhcmFtcywgU2VhcmNoUGFyYW1zU2VydmljZSB9IGZyb20gJy4vc2VhcmNoLXBhcmFtcy5zZXJ2aWNlJztcblxuLyoqXG4gKiBAZGVwcmVjYXRlZCBVc2UgbmV3IHNlcnZpY2UgZnJvbSBgQGtub3JhL2FwaWAgKGdpdGh1YjpkYXNjaC1zd2lzcy9rbm9yYS1hcGktanMtbGliKSBpbnN0ZWFkXG4gKlxuICogQ3JlYXRlIEdyYXZTZWFyY2ggcXVlcmllcyBmcm9tIHByb3ZpZGVkIHBhcmFtZXRlcnMuXG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgR3JhdnNlYXJjaEdlbmVyYXRpb25TZXJ2aWNlIHtcblxuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKlxuICAgICAqIE1hcCBvZiBjb21wbGV4IGtub3JhLWFwaSB2YWx1ZSB0eXBlcyB0byBzaW1wbGUgb25lcy5cbiAgICAgKiBVc2UgY29tcHV0ZWQgcHJvcGVydHkgbmFtZTogaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLW9iamVjdC1pbml0aWFsaXplci5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIHR5cGVDb252ZXJzaW9uQ29tcGxleFRvU2ltcGxlID0ge1xuICAgICAgICAnaHR0cDovL2FwaS5rbm9yYS5vcmcvb250b2xvZ3kva25vcmEtYXBpL3YyI0ludFZhbHVlJzogQ29uc3RhbnRzLlhzZEludGVnZXIsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjRGVjaW1hbFZhbHVlJzogQ29uc3RhbnRzLlhzZERlY2ltYWwsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjQm9vbGVhblZhbHVlJzogQ29uc3RhbnRzLlhzZEJvb2xlYW4sXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjVGV4dFZhbHVlJzogQ29uc3RhbnRzLlhzZFN0cmluZyxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNVcmlWYWx1ZSc6IENvbnN0YW50cy5Yc2RBbnlVcmksXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjRGF0ZVZhbHVlJzogS25vcmFDb25zdGFudHMuZGF0ZVNpbXBsZSxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNJbnRlcnZhbFZhbHVlJzogS25vcmFDb25zdGFudHMuaW50ZXJ2YWxTaW1wbGUsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjR2VvbVZhbHVlJzogS25vcmFDb25zdGFudHMuZ2VvbVNpbXBsZSxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNDb2xvclZhbHVlJzogS25vcmFDb25zdGFudHMuY29sb3JTaW1wbGUsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjR2VvbmFtZVZhbHVlJzogS25vcmFDb25zdGFudHMuZ2VvbmFtZVNpbXBsZSxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNTdGlsbEltYWdlRmlsZVZhbHVlJzogS25vcmFDb25zdGFudHMuZmlsZVNpbXBsZSxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNGaWxlVmFsdWUnOiBLbm9yYUNvbnN0YW50cy5maWxlU2ltcGxlLFxuICAgICAgICAnaHR0cDovL2FwaS5rbm9yYS5vcmcvb250b2xvZ3kva25vcmEtYXBpL3YyI01vdmluZ0ltYWdlRmlsZVZhbHVlJzogS25vcmFDb25zdGFudHMuZmlsZVNpbXBsZSxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNERERGaWxlVmFsdWUnOiBLbm9yYUNvbnN0YW50cy5maWxlU2ltcGxlLFxuICAgICAgICAnaHR0cDovL2FwaS5rbm9yYS5vcmcvb250b2xvZ3kva25vcmEtYXBpL3YyI0F1ZGlvRmlsZVZhbHVlJzogS25vcmFDb25zdGFudHMuZmlsZVNpbXBsZSxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNEb2N1bWVudEZpbGVWYWx1ZSc6IEtub3JhQ29uc3RhbnRzLmZpbGVTaW1wbGUsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjVGV4dEZpbGVWYWx1ZSc6IEtub3JhQ29uc3RhbnRzLmZpbGVTaW1wbGUsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjTGlzdFZhbHVlJzogS25vcmFDb25zdGFudHMubGlzdE5vZGVTaW1wbGVcbiAgICB9O1xuXG4gICAgcHVibGljIHN0YXRpYyBjb21wbGV4VHlwZVRvUHJvcCA9IHtcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNJbnRWYWx1ZSc6IENvbnN0YW50cy5JbnRWYWx1ZUFzSW50LFxuICAgICAgICAnaHR0cDovL2FwaS5rbm9yYS5vcmcvb250b2xvZ3kva25vcmEtYXBpL3YyI0RlY2ltYWxWYWx1ZSc6IENvbnN0YW50cy5EZWNpbWFsVmFsdWVBc0RlY2ltYWwsXG4gICAgICAgICdodHRwOi8vYXBpLmtub3JhLm9yZy9vbnRvbG9neS9rbm9yYS1hcGkvdjIjQm9vbGVhblZhbHVlJzogQ29uc3RhbnRzLkJvb2xlYW5WYWx1ZUFzQm9vbGVhbixcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNUZXh0VmFsdWUnOiBDb25zdGFudHMuVmFsdWVBc1N0cmluZyxcbiAgICAgICAgJ2h0dHA6Ly9hcGkua25vcmEub3JnL29udG9sb2d5L2tub3JhLWFwaS92MiNVcmlWYWx1ZSc6IENvbnN0YW50cy5VcmlWYWx1ZUFzVXJpLFxuICAgICAgICAnaHR0cDovL2FwaS5rbm9yYS5vcmcvb250b2xvZ3kva25vcmEtYXBpL3YyI0xpc3RWYWx1ZSc6IENvbnN0YW50cy5MaXN0VmFsdWVBc0xpc3ROb2RlXG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX3NlYXJjaFBhcmFtc1NlcnZpY2U6IFNlYXJjaFBhcmFtc1NlcnZpY2UpIHsgfVxuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjEwLjAuMFxuICAgICAqXG4gICAgICogV2lsbCBiZSByZXBsYWNlZCBieSBgQGtub3JhL2FwaWAgKGdpdGh1Yjprbm9yYS1hcGktanMtbGliKVxuICAgICAqXG4gICAgICogR2VuZXJhdGVzIGEgR3JhdnNlYXJjaCBxdWVyeSBmcm9tIHRoZSBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1Byb3BlcnR5V2l0aFZhbHVlW119IHByb3BlcnRpZXMgdGhlIHByb3BlcnRpZXMgc3BlY2lmaWVkIGJ5IHRoZSB1c2VyLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbbWFpblJlc291cmNlQ2xhc3NPcHRpb25dIHRoZSBjbGFzcyBvZiB0aGUgbWFpbiByZXNvdXJjZSwgaWYgc3BlY2lmaWVkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgdGhlIG9mZnNldCB0byBiZSB1c2VkIChudGggcGFnZSBvZiByZXN1bHRzKS5cbiAgICAgKiBAcmV0dXJucyBzdHJpbmcgLSBhIEtuYXJRTCBxdWVyeSBzdHJpbmcuXG4gICAgICovXG4gICAgY3JlYXRlR3JhdnNlYXJjaFF1ZXJ5KHByb3BlcnRpZXM6IFByb3BlcnR5V2l0aFZhbHVlW10sIG1haW5SZXNvdXJjZUNsYXNzT3B0aW9uPzogc3RyaW5nLCBvZmZzZXQ6IG51bWJlciA9IDApOiBzdHJpbmcge1xuXG4gICAgICAgIC8vIGNsYXNzIHJlc3RyaWN0aW9uIGZvciB0aGUgcmVzb3VyY2Ugc2VhcmNoZWQgZm9yXG4gICAgICAgIGxldCBtYWluUmVzb3VyY2VDbGFzcyA9ICcnO1xuXG4gICAgICAgIC8vIGlmIGdpdmVuLCBjcmVhdGUgdGhlIGNsYXNzIHJlc3RyaWN0aW9uIGZvciB0aGUgbWFpbiByZXNvdXJjZVxuICAgICAgICBpZiAobWFpblJlc291cmNlQ2xhc3NPcHRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbWFpblJlc291cmNlQ2xhc3MgPSBgP21haW5SZXMgYSA8JHttYWluUmVzb3VyY2VDbGFzc09wdGlvbn0+IC5gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY3JpdGVyaWEgZm9yIHRoZSBvcmRlciBieSBzdGF0ZW1lbnRcbiAgICAgICAgY29uc3Qgb3JkZXJCeUNyaXRlcmlhID0gW107XG5cbiAgICAgICAgLy8gc3RhdGVtZW50cyB0byBiZSByZXR1cm5lZCBpbiBxdWVyeSByZXN1bHRzXG4gICAgICAgIGNvbnN0IHJldHVyblN0YXRlbWVudHMgPSBbXTtcblxuICAgICAgICAvLyBsb29wIG92ZXIgZ2l2ZW4gcHJvcGVydGllcyBhbmQgY3JlYXRlIHN0YXRlbWVudHMgYW5kIGZpbHRlcnMgZnJvbSB0aGVtXG4gICAgICAgIGNvbnN0IHByb3BzOiBzdHJpbmdbXSA9IHByb3BlcnRpZXMubWFwKFxuICAgICAgICAgICAgKHByb3BXaXRoVmFsOiBQcm9wZXJ0eVdpdGhWYWx1ZSwgaW5kZXg6IG51bWJlcikgPT4ge1xuXG4gICAgICAgICAgICAgICAgLy8gcmVwcmVzZW50cyB0aGUgb2JqZWN0IG9mIGEgc3RhdGVtZW50XG4gICAgICAgICAgICAgICAgbGV0IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAoIXByb3BXaXRoVmFsLnByb3BlcnR5LmlzTGlua1Byb3BlcnR5IHx8IHByb3BXaXRoVmFsLnZhbHVlTGl0ZXJhbC5jb21wYXJpc29uT3BlcmF0b3IuZ2V0Q2xhc3NOYW1lKCkgPT09ICdFeGlzdHMnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0IGlzIG5vdCBhIGxpbmtpbmcgcHJvcGVydHksIGNyZWF0ZSBhIHZhcmlhYmxlIGZvciB0aGUgdmFsdWUgKHRvIGJlIHVzZWQgYnkgYSBzdWJzZXF1ZW50IEZJTFRFUilcbiAgICAgICAgICAgICAgICAgICAgLy8gT1IgdGhlIGNvbXBhcmlzb24gb3BlcmF0b3IgRXhpc3RzIGlzIHVzZWQgaW4gd2hpY2ggY2FzZSB3ZSBkbyBub3QgbmVlZCB0byBzcGVjaWZ5IHRoZSBvYmplY3QgYW55IGZ1cnRoZXJcbiAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlID0gYD9wcm9wVmFsJHtpbmRleH1gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGl0IGlzIGEgbGlua2luZyBwcm9wZXJ0eSBhbmQgdGhlIGNvbXBhcmlzb24gb3BlcmF0b3IgaXMgbm90IEV4aXN0cywgdXNlIGl0cyBJUklcbiAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlID0gcHJvcFdpdGhWYWwudmFsdWVMaXRlcmFsLnZhbHVlLnRvU3BhcnFsKEtub3JhU2NoZW1hLmNvbXBsZXgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGdlbmVyYXRlIHN0YXRlbWVudFxuICAgICAgICAgICAgICAgIGxldCBzdGF0ZW1lbnQ6IHN0cmluZyA9IGA/bWFpblJlcyA8JHtwcm9wV2l0aFZhbC5wcm9wZXJ0eS5pZH0+ICR7cHJvcFZhbHVlfSAuYDtcblxuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGl0IGlzIGEgbGlua2luZyBwcm9wZXJ0eSB0aGF0IGhhcyB0byBiZSB3cmFwcGVkIGluIGEgRklMVEVSIE5PVCBFWElTVFMgKGNvbXBhcmlzb24gb3BlcmF0b3IgTk9UX0VRVUFMUykgdG8gbmVnYXRlIGl0XG4gICAgICAgICAgICAgICAgaWYgKHByb3BXaXRoVmFsLnByb3BlcnR5LmlzTGlua1Byb3BlcnR5ICYmIHByb3BXaXRoVmFsLnZhbHVlTGl0ZXJhbC5jb21wYXJpc29uT3BlcmF0b3IuZ2V0Q2xhc3NOYW1lKCkgPT09ICdOb3RFcXVhbHMnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGRvIG5vdCBpbmNsdWRlIHN0YXRlbWVudCBpbiByZXN1bHRzLCBiZWNhdXNlIHRoZSBxdWVyeSBjaGVja3MgZm9yIHRoZSBhYnNlbmNlIG9mIHRoaXMgc3RhdGVtZW50XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlbWVudCA9IGBGSUxURVIgTk9UIEVYSVNUUyB7XG4ke3N0YXRlbWVudH1cblxuXG59YDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBjaGVjayBpZiBzdGF0ZW1lbnQgc2hvdWxkIGJlIHJldHVybmVkIHJldHVybmVkIGluIHJlc3VsdHMgKEJvb2xlYW4gZmxhZyBmcm9tIGNoZWNrYm94KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5TdGF0ZW1lbnRzLnB1c2goc3RhdGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGVtZW50ID0gYFxuJHtzdGF0ZW1lbnR9XG5cblxuYDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBnZW5lcmF0ZSByZXN0cmljdGluZyBleHByZXNzaW9uIChlLmcuLCBhIEZJTFRFUikgaWYgY29tcGFyaXNvbiBvcGVyYXRvciBpcyBub3QgRXhpc3RzXG4gICAgICAgICAgICAgICAgbGV0IHJlc3RyaWN0aW9uOiBzdHJpbmcgPSAnJztcbiAgICAgICAgICAgICAgICAvLyBvbmx5IGNyZWF0ZSBhIEZJTFRFUiBpZiB0aGUgY29tcGFyaXNvbiBvcGVyYXRvciBpcyBub3QgRVhJU1RTIGFuZCBpdCBpcyBub3QgYSBsaW5raW5nIHByb3BlcnR5XG4gICAgICAgICAgICAgICAgaWYgKCFwcm9wV2l0aFZhbC5wcm9wZXJ0eS5pc0xpbmtQcm9wZXJ0eSAmJiBwcm9wV2l0aFZhbC52YWx1ZUxpdGVyYWwuY29tcGFyaXNvbk9wZXJhdG9yLmdldENsYXNzTmFtZSgpICE9PSAnRXhpc3RzJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBnZW5lcmF0ZSB2YXJpYWJsZSBmb3IgdmFsdWUgbGl0ZXJhbFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9wVmFsdWVMaXRlcmFsID0gYCR7cHJvcFZhbHVlfUxpdGVyYWxgO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wV2l0aFZhbC52YWx1ZUxpdGVyYWwuY29tcGFyaXNvbk9wZXJhdG9yLmdldENsYXNzTmFtZSgpID09PSAnTGlrZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGdlbmVyYXRlIHN0YXRlbWVudCB0byB2YWx1ZSBsaXRlcmFsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN0cmljdGlvbiA9IGAke3Byb3BWYWx1ZX0gPCR7R3JhdnNlYXJjaEdlbmVyYXRpb25TZXJ2aWNlLmNvbXBsZXhUeXBlVG9Qcm9wW3Byb3BXaXRoVmFsLnByb3BlcnR5Lm9iamVjdFR5cGVdfT4gJHtwcm9wVmFsdWVMaXRlcmFsfWAgKyAnXFxuJztcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVzZSByZWdleCBmdW5jdGlvbiBmb3IgTElLRVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb24gKz0gYEZJTFRFUiByZWdleCgke3Byb3BWYWx1ZUxpdGVyYWx9LCAke3Byb3BXaXRoVmFsLnZhbHVlTGl0ZXJhbC52YWx1ZS50b1NwYXJxbChLbm9yYVNjaGVtYS5jb21wbGV4KX0sIFwiaVwiKWA7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcFdpdGhWYWwudmFsdWVMaXRlcmFsLmNvbXBhcmlzb25PcGVyYXRvci5nZXRDbGFzc05hbWUoKSA9PT0gJ01hdGNoJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2VuZXJhdGUgc3RhdGVtZW50IHRvIHZhbHVlIGxpdGVyYWxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uID0gYCR7cHJvcFZhbHVlfSA8JHtHcmF2c2VhcmNoR2VuZXJhdGlvblNlcnZpY2UuY29tcGxleFR5cGVUb1Byb3BbcHJvcFdpdGhWYWwucHJvcGVydHkub2JqZWN0VHlwZV19PiAke3Byb3BWYWx1ZUxpdGVyYWx9YCArICdcXG4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdXNlIGNvbnRhaW5zIGZ1bmN0aW9uIGZvciBNQVRDSFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb24gKz0gYEZJTFRFUiA8JHtLbm9yYUNvbnN0YW50cy5NYXRjaEZ1bmN0aW9ufT4oJHtwcm9wVmFsdWVMaXRlcmFsfSwgJHtwcm9wV2l0aFZhbC52YWx1ZUxpdGVyYWwudmFsdWUudG9TcGFycWwoS25vcmFTY2hlbWEuY29tcGxleCl9KWA7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcFdpdGhWYWwucHJvcGVydHkub2JqZWN0VHlwZSA9PT0gQ29uc3RhbnRzLkRhdGVWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGFuZGxlIGRhdGUgcHJvcGVydHlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uID0gYEZJTFRFUihrbm9yYS1hcGk6dG9TaW1wbGVEYXRlKCR7cHJvcFZhbHVlfSkgJHtwcm9wV2l0aFZhbC52YWx1ZUxpdGVyYWwuY29tcGFyaXNvbk9wZXJhdG9yLnR5cGV9ICR7cHJvcFdpdGhWYWwudmFsdWVMaXRlcmFsLnZhbHVlLnRvU3BhcnFsKEtub3JhU2NoZW1hLmNvbXBsZXgpfSlgO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BXaXRoVmFsLnByb3BlcnR5Lm9iamVjdFR5cGUgPT09IENvbnN0YW50cy5MaXN0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhbmRsZSBsaXN0IG5vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uID0gYCR7cHJvcFZhbHVlfSA8JHtHcmF2c2VhcmNoR2VuZXJhdGlvblNlcnZpY2UuY29tcGxleFR5cGVUb1Byb3BbcHJvcFdpdGhWYWwucHJvcGVydHkub2JqZWN0VHlwZV19PiAke3Byb3BXaXRoVmFsLnZhbHVlTGl0ZXJhbC52YWx1ZS50b1NwYXJxbChLbm9yYVNjaGVtYS5jb21wbGV4KX1gICsgJ1xcbic7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBmb3IgY29tcGFyaXNvbiBvcGVyYXRvciBcIm5vdCBlcXVhbHNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BXaXRoVmFsLnZhbHVlTGl0ZXJhbC5jb21wYXJpc29uT3BlcmF0b3IuZ2V0Q2xhc3NOYW1lKCkgPT09ICdOb3RFcXVhbHMnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdHJpY3Rpb24gPSBgRklMVEVSIE5PVCBFWElTVFMge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAke3Jlc3RyaWN0aW9ufVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2VuZXJhdGUgc3RhdGVtZW50IHRvIHZhbHVlIGxpdGVyYWxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uID0gYCR7cHJvcFZhbHVlfSA8JHtHcmF2c2VhcmNoR2VuZXJhdGlvblNlcnZpY2UuY29tcGxleFR5cGVUb1Byb3BbcHJvcFdpdGhWYWwucHJvcGVydHkub2JqZWN0VHlwZV19PiAke3Byb3BWYWx1ZUxpdGVyYWx9YCArICdcXG4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2VuZXJhdGUgZmlsdGVyIGV4cHJlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RyaWN0aW9uICs9IGBGSUxURVIoJHtwcm9wVmFsdWVMaXRlcmFsfSAke3Byb3BXaXRoVmFsLnZhbHVlTGl0ZXJhbC5jb21wYXJpc29uT3BlcmF0b3IudHlwZX0gJHtwcm9wV2l0aFZhbC52YWx1ZUxpdGVyYWwudmFsdWUudG9TcGFycWwoS25vcmFTY2hlbWEuY29tcGxleCl9KWA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBjdXJyZW50IHZhbHVlIGlzIGEgc29ydCBjcml0ZXJpb25cbiAgICAgICAgICAgICAgICBpZiAocHJvcFdpdGhWYWwuaXNTb3J0Q3JpdGVyaW9uKSBvcmRlckJ5Q3JpdGVyaWEucHVzaChwcm9wVmFsdWUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke3N0YXRlbWVudH1cbiR7cmVzdHJpY3Rpb259XG5gO1xuXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBsZXQgb3JkZXJCeVN0YXRlbWVudCA9ICcnO1xuXG4gICAgICAgIGlmIChvcmRlckJ5Q3JpdGVyaWEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgb3JkZXJCeVN0YXRlbWVudCA9IGBcbk9SREVSIEJZICR7b3JkZXJCeUNyaXRlcmlhLmpvaW4oJyAnKX1cbmA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0ZW1wbGF0ZSBvZiB0aGUgR3JhdnNlYXJjaCBxdWVyeSB3aXRoIGR5bmFtaWMgY29tcG9uZW50c1xuICAgICAgICBjb25zdCBncmF2c2VhcmNoVGVtcGxhdGUgPSBgXG5QUkVGSVgga25vcmEtYXBpOiA8aHR0cDovL2FwaS5rbm9yYS5vcmcvb250b2xvZ3kva25vcmEtYXBpL3YyIz5cbkNPTlNUUlVDVCB7XG5cbj9tYWluUmVzIGtub3JhLWFwaTppc01haW5SZXNvdXJjZSB0cnVlIC5cblxuJHtyZXR1cm5TdGF0ZW1lbnRzLmpvaW4oJ1xcbicpfVxuXG59IFdIRVJFIHtcblxuP21haW5SZXMgYSBrbm9yYS1hcGk6UmVzb3VyY2UgLlxuXG4ke21haW5SZXNvdXJjZUNsYXNzfVxuXG4ke3Byb3BzLmpvaW4oJycpfVxuXG59XG4ke29yZGVyQnlTdGF0ZW1lbnR9YDtcblxuICAgICAgICAvLyBvZmZzZXQgY29tcG9uZW50IG9mIHRoZSBHcmF2c2VhcmNoIHF1ZXJ5XG4gICAgICAgIGNvbnN0IG9mZnNldFRlbXBsYXRlID0gYFxuT0ZGU0VUICR7b2Zmc2V0fVxuYDtcblxuICAgICAgICAvLyBmdW5jdGlvbiB0aGF0IGdlbmVyYXRlcyB0aGUgc2FtZSBLbmFyUUwgcXVlcnkgd2l0aCB0aGUgZ2l2ZW4gb2Zmc2V0XG4gICAgICAgIGNvbnN0IGdlbmVyYXRlR3JhdnNlYXJjaFF1ZXJ5V2l0aEN1c3RvbU9mZnNldCA9IChsb2NhbE9mZnNldDogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldEN1c3RvbVRlbXBsYXRlID0gYFxuT0ZGU0VUICR7bG9jYWxPZmZzZXR9XG5gO1xuXG4gICAgICAgICAgICByZXR1cm4gZ3JhdnNlYXJjaFRlbXBsYXRlICsgb2Zmc2V0Q3VzdG9tVGVtcGxhdGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKG9mZnNldCA9PT0gMCkge1xuICAgICAgICAgICAgLy8gc3RvcmUgdGhlIGZ1bmN0aW9uIHNvIGFub3RoZXIgS25hclFMIHF1ZXJ5IGNhbiBiZSBjcmVhdGVkIHdpdGggYW4gaW5jcmVhc2VkIG9mZnNldFxuICAgICAgICAgICAgdGhpcy5fc2VhcmNoUGFyYW1zU2VydmljZS5jaGFuZ2VTZWFyY2hQYXJhbXNNc2cobmV3IEV4dGVuZGVkU2VhcmNoUGFyYW1zKGdlbmVyYXRlR3JhdnNlYXJjaFF1ZXJ5V2l0aEN1c3RvbU9mZnNldCkpO1xuICAgICAgICB9XG5cblxuICAgICAgICByZXR1cm4gZ3JhdnNlYXJjaFRlbXBsYXRlICsgb2Zmc2V0VGVtcGxhdGU7XG5cbiAgICB9XG5cbn1cbiJdfQ==