UNPKG

@knora/core

Version:
208 lines (197 loc) 32.9 kB
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==