@tripsnek/tmf
Version:
TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)
476 lines • 60.5 kB
JavaScript
import { TGenUtils as DU } from './tgen-utils.js';
import { EAttributeImpl } from '../metamodel/impl/eattribute-impl.js';
import { EClassImpl } from '../metamodel/impl/eclass-impl.js';
import { EReferenceImpl } from '../metamodel/impl/ereference-impl.js';
import { EEnumImpl } from '../metamodel/impl/eenum-impl.js';
import { EDataTypeImpl } from '../metamodel/impl/edata-type-impl.js';
/**
* Responsible for generating the interface and implementation of an
* EPackage source file, which provides static access to all the elements
* of a package in a TMF model.
*
* Note that generation of several swathes of the package content
* are ganged together into a single pass over the model. This owes
* to the fact that sufficient logic is shared across their computations, largely
* related to the tracking of IDs for individual elements, that it would
* be difficult to separate them out.
*/
export class TGeneratorPackage {
rootPackage;
generatePackageContents(pkg) {
const className = DU.genPackageClassName(pkg);
this.rootPackage = pkg;
while (this.rootPackage.getESuperPackage())
this.rootPackage = this.rootPackage.getESuperPackage();
//track package dependencies, import them at the end
const pkgToImport = new Set();
//static library of all package contents
let literalsContent = `
/** Provides static access to EClass and EStructuralFeature instances */
public static Literals = class {`;
let fieldDeclarationsContent = '';
let gettersContent = '';
//insert create/initialize methods
let createContent = ` public createPackageContents(): void {
if (this.isCreated) return;
this.isCreated = true;`;
let initContent = ` public initializePackageContents(): void {
if (this.isInitialized) return;
this.isInitialized = true;
//reusable handle for eoperations, used for adding parameters
let op: EOperation;`;
let idFieldsContent = '';
//iterate over all classes and features, create and initialize them AND create getters using the feature IDs
let ecIdCounter = 0;
//sort eclassifiers in such a way that base types are guaranteed to precede derived types so
//that we can reference feature IDs in correct order
const sortedClassifiers = this.sortClassifiersWithBaseTypesFirst(pkg);
//NOTE: This is the 'single-pass' loop for generating IDs, declaring element fields
//and initializing each and hooking up their references where appropriate. The
//content for all of these is then integrated into the full template of the package
//file in the return statement for this method
for (const eclassifier of sortedClassifiers) {
const eclassIdField = DU.genClassIdFieldName(eclassifier);
idFieldsContent += `
public static ${eclassIdField} = ${ecIdCounter};`;
ecIdCounter++;
//add eclassifier field
let type = 'EClass';
if (eclassifier instanceof EEnumImpl)
type = 'EEnum';
else if (eclassifier instanceof EDataTypeImpl)
type = 'EDataType';
const eclassFieldName = DU.uncapitalize(eclassifier.getName()) + type;
fieldDeclarationsContent += `
private ${eclassFieldName}!: ${type};`;
//add eclass getter
const eclassGetter = DU.genEclassGetterName(eclassifier);
gettersContent += `
public ${eclassGetter}(): ${type} {
return this.${eclassFieldName};
}`;
//add creation
createContent += `
this.${eclassFieldName} = this.create${type}(${className}.${eclassIdField});`;
//add Literals entry for EClassifier
literalsContent += `
static ${eclassIdField}: ${type} = ${className}._eINSTANCE.${DU.genEclassGetterName(eclassifier)}();`;
//add class initialization
if (eclassifier instanceof EClassImpl) {
const eclass = eclassifier;
for (const superType of eclassifier.getESuperTypes()) {
const pkgRef = DU.getReferenceToPackageInstance(superType, eclassifier, pkgToImport);
initContent += `
this.${eclassFieldName}.getESuperTypes().add(${pkgRef}.${DU.genEclassGetterName(superType)}());`;
}
initContent += `
this.init${type}(
this.${eclassFieldName},
'${eclassifier.getName()}',
${eclassifier.isAbstract()},
${eclassifier.isInterface()},
true
);`;
}
else {
initContent += `
this.init${type}(
this.${eclassFieldName}, '${eclassifier.getName()}');`;
if (eclassifier instanceof EEnumImpl) {
let literalInd = 0;
for (const literal of eclassifier.getELiterals()) {
const litRef = eclassifier.getName() + '.' + literal.getName();
initContent += `
this.addEEnumLiteral(this.${eclassFieldName}, '${literal.getName()}', ${literalInd});`;
literalInd++;
}
}
}
//process references and attributes
if (eclassifier instanceof EClassImpl) {
//find super type
const superType = eclassifier.getESuperTypes().size() > 0
? eclassifier.getESuperTypes().get(0)
: null;
//write out feature count field (will be the starting point for ID'ing new fields on this eclass)
const featureCountField = DU.genFeatureCountFieldName(eclassifier);
const superTypeFeatureCount = superType ? superType.getEAllStructuralFeatures().size() : 0;
//Eliminating references to super types in static initializers, since they could be in other packages (circular import)
// const superTypeCountField = superType
// ? DU.genPackageClassName(superType.getEPackage()) +
// '.' +
// DU.genFeatureCountFieldName(superType) +
// ' + '
// : '';
// if (superTypeCountField) {
// idFieldsContent += `
// public static ${featureCountField} =
// ${superTypeCountField}${eclassifier.getEStructuralFeatures().size()};`;
// } else {
// idFieldsContent += `
// public static ${featureCountField} = ${eclassifier.getEStructuralFeatures().size()};`;
// }
//this is the replacement - just a straight count of all features, shoudl be same
idFieldsContent += `
public static ${featureCountField} = ${eclassifier.getEAllStructuralFeatures().size()};`;
//keeps track of the feature's index in it's eClass (used for feature getter)
let thisClassFeatureIndex = 0;
for (const feature of eclassifier.getEStructuralFeatures()) {
const featureIdField = DU.genFeatureIdFieldName(feature);
//Eliminating references to super types in static initializers, since they could be in other packages (circular import)
// if (superTypeCountField) {
// idFieldsContent += `
// public static ${featureIdField} = ${superTypeCountField}${thisClassFeatureIndex};`;
// } else {
// idFieldsContent += `
// public static ${featureIdField} = ${thisClassFeatureIndex};`;
// }
//this is the replacement - just add to the super type feature count
idFieldsContent += `
public static ${featureIdField} = ${superTypeFeatureCount + thisClassFeatureIndex};`;
const featureType = feature instanceof EAttributeImpl ? 'EAttribute' : 'EReference';
literalsContent += `
static ${featureIdField}: ${featureType} =
${className}._eINSTANCE.get${DU.capitalize(eclassifier.getName())}_${DU.capitalize(feature.getName())}();`;
//create features
createContent += `
this.create${featureType}(
this.${eclassFieldName},
${className}.${featureIdField}
);`;
const featureGetterName = DU.genFeatureGetterName(feature);
//add feature getter
gettersContent += `
public ${featureGetterName}(): ${featureType} {
return <${featureType}>this.${eclassFieldName}.getEStructuralFeatures().get(${thisClassFeatureIndex});
}`;
//the getter for the feature's type (Eclassifier instance)
const featureTypeGetter = this.getterForEType(feature.getEType(), eclassifier, pkgToImport, pkg);
//initializers
initContent += `
this.init${featureType}(
this.${featureGetterName}()`;
if (feature instanceof EAttributeImpl) {
initContent += `,
${featureTypeGetter},
'${feature.getName()}',
${feature.getDefaultValueLiteral() ? feature.getDefaultValueLiteral() : `''`},
${feature.getLowerBound()},
${feature.getUpperBound()},
'',
${feature.isTransient() ?? false},
${feature.isVolatile() ?? false},
${feature.isChangeable() ?? true},
true,
${feature.isId() ?? false},
false,
false,
false`;
}
else if (feature instanceof EReferenceImpl) {
const pkgRef = DU.getReferenceToPackageInstance(feature.getEType(), eclassifier, pkgToImport);
let eopposite = 'undefined';
if (feature.getEOpposite()) {
eopposite = `${pkgRef}.${DU.genFeatureGetterName(feature.getEOpposite())}()`;
}
initContent += `,
${featureTypeGetter},
${eopposite},
'${feature.getName()}',
'',
${feature.getLowerBound()},
${feature.getUpperBound()},
'',
${feature.isTransient() ?? false},
${feature.isVolatile() ?? false},
${feature.isChangeable() ?? false},
${feature.isContainment() ?? false},
false,
true,
false,
false,
false`;
}
initContent += `
);`;
thisClassFeatureIndex++;
}
//logic for creating and initializing EOperations
let eopIndex = 0;
for (const eop of eclassifier.getEOperations()) {
const eopIdField = DU.genOperationIdFieldName(eop);
//add ID content
idFieldsContent += `
public static ${eopIdField} = ${eopIndex};`;
createContent += `
this.createEOperation(this.${eclassFieldName}, ${className}.${eopIdField});`;
const featureGetterName = DU.genOperationGetterName(eop);
gettersContent += `
public ${featureGetterName}(): EOperation {
return this.${eclassFieldName}.getEOperations().get(${eopIndex});
}`;
initContent += `
op = this.initEOperation(
this.${featureGetterName}(),
${this.getterForEType(eop.getEType(), eclassifier, pkgToImport, pkg)},
'${eop.getName()}',
0,
${eop.isMany() ? -1 : 1},
true,
true
);`;
for (const p of eop.getEParameters()) {
//TODO: Create parameters and add them to EOphere
initContent += `
this.createEParameter(
op,
'${p.getName()}',
${p.isMany() ? -1 : 1},
${this.getterForEType(p.getEType(), eclassifier, pkgToImport, pkg)}
);`;
}
eopIndex++;
}
}
}
createContent += `
}`;
initContent += `
}`;
literalsContent += `
};`;
//EcorePackage cannot extend EPackageImpl, as it it would create circular reference
const toExtend = pkg.getName().toLowerCase() === 'ecore' ? 'EPackage' : 'EPackageImpl';
let subPkgSetters = '';
// for(const subPkg of pkg.getESubPackages()){
// if(!pkgToImport.has(subPkg)){
// pkgToImport.add(subPkg);
// }
// subPkgSetters += `
// ${DU.genPackageClassName(subPkg)}.eINSTANCE.setESuperPackage(the${className})`;
// }
return `${this.generateImports(pkgToImport, pkg)}
export class ${className} extends ${toExtend} {${idFieldsContent}
/** Singleton */
public static _eINSTANCE: ${className} = ${className}.init();
//if the singleton is initialized
private static isInited = false;
static eNS_URI =
'${pkg.getNsURI()}';
static eNAME = '${pkg.getName()}';
static eNS_PREFIX = '${pkg.getNsPrefix()}';
${literalsContent}
//flags that keep track of whether package is initialized
private isCreated = false;
private isInitialized = false;
${fieldDeclarationsContent}
//causes EPackage.Registry registration event
//hard-coded URI, since referring to the static eNS_URI field in constructor can cause issues
constructor() {
super(
'${pkg.getName()}',
'${pkg.getNsURI()}',
'${pkg.getNsPrefix()}'
);
}
/**
* Invoked once. Initializes the Singleton.
*
* NOTE: Lots of differences here with the EMF version, which interacts with the package Registry,
* other packages from the same model to register interdependencies, and freezes the package meta-data.
*/
private static init(): ${className} {
if (${className}.isInited) return this._eINSTANCE;
// Obtain or create and register package
const the${className} = new ${className}();
//this is necessary specifically for EcorePackage generation, which needs to refer to itself
this._eINSTANCE = the${className};
${className}.isInited = true;
${subPkgSetters}
// Create package meta-data objects
the${className}.createPackageContents();
// Initialize created meta-data
// the${className}.initializePackageContents();
return this._eINSTANCE;
}
static get eINSTANCE(): ${className}{
this.ensureInitialized();
return this._eINSTANCE;
}
/**
* Ensures this package and it's depdendencies are fully initialized and registered with TJson
*/
private static ensureInitialized(): void {
const packageName = '${pkg.getName()}';
if (PackageRegistry.isInitialized(packageName)) {
return;
}
// Initialize this package's contents
const pkg = this._eINSTANCE;
pkg.initializePackageContents();
// Mark as initialized first to prevent cycles
PackageRegistry.markInitialized(packageName);
// Register with TJson
PackageRegistry.registerWithTJson(packageName, pkg);
}
/**
* Called by the factory to register itself with this package
*/
static registerFactory(factory: EFactory): void {
this._eINSTANCE.setEFactoryInstance(factory);
}
//this used to be direct lazy retrieval of the
//factory instance from the corresponding .ts factory file, but
//that was eliminated to avoid circular imports
public override getEFactoryInstance(): EFactory {
if (!this._eFactoryInstance) {
// Try to get factory from registry
const factory = PackageRegistry.getFactory('${pkg.getName()}');
if (factory) {
this.setEFactoryInstance(factory);
}
}
return this._eFactoryInstance;
}
/**
* This will be invoked by the Factory when it is initialized, any invocations
* afterwards will have no effect.
*/
public override setEFactoryInstance(factoryInst: EFactory): void {
if (!this._eFactoryInstance) this._eFactoryInstance = factoryInst;
}
${gettersContent}
${createContent}
${initContent}
}
`;
}
/**
* User for generating 'get' on the EType for a feature or operation.
*
* @param etype
* @param owningEClass
* @param pkgToImport
* @param pkg
* @returns
*/
getterForEType(etype, owningEClass, pkgToImport, pkg) {
let featureTypeGetter = undefined;
if (etype) {
const pkgRef = DU.getReferenceToPackageInstance(etype, owningEClass, pkgToImport);
if (etype instanceof EEnumImpl) {
featureTypeGetter = `${pkgRef}.get${etype.getName()}()`;
}
else if (etype instanceof EClassImpl) {
const pkgRef = DU.getReferenceToPackageInstance(etype, owningEClass, pkgToImport);
if (etype) {
featureTypeGetter = `${pkgRef}.${DU.genEclassGetterName(etype)}()`;
}
}
else {
let ecorePkgGetter = 'this.getEcorePackage()';
if (pkg.getName().toLowerCase() === 'ecore')
ecorePkgGetter = 'this';
featureTypeGetter = ecorePkgGetter + '.get' + etype.getName() + '()';
}
}
return featureTypeGetter;
}
generateImports(pkgToImport, pkg) {
//build path to root package initializer
const pathToRoot = DU.getPathToRoot(pkg);
let imports = `${DU.generateImportStatementsForExternalPackages(pkgToImport, pkg, './')}
import { EClass } from '@tripsnek/tmf';
import { EEnum } from '@tripsnek/tmf';
import { PackageRegistry } from '${pathToRoot}package-registry.js';
import { EPackageImpl } from '@tripsnek/tmf';
import { EAttribute } from '@tripsnek/tmf';
import { EFactory } from '@tripsnek/tmf';
import { EReference } from '@tripsnek/tmf';
import { EOperation } from '@tripsnek/tmf';`;
//we use relative imports for the EcorePackage, since it is in the same lib as the metamodel
if (pkg.getName().toLowerCase() === 'ecore') {
imports = `${DU.generateImportStatementsForExternalPackages(pkgToImport, pkg, '')}
import { EPackage } from './epackage.js';
import { EDataType } from './edata-type.js';
import { EClass } from './eclass.js';
import { EReference } from './ereference.js';
import { EAttribute } from './eattribute.js';
import { EFactory } from './efactory.js';`;
}
return imports;
}
/**
* Sort eclassifiers in such a way that base types are guaranteed to precede derived types so
* that we can reference feature IDs in correct order
*/
sortClassifiersWithBaseTypesFirst(pkg) {
const sortedClassifiers = new Array();
for (const eclassifier of pkg.getEClassifiers()) {
if (eclassifier instanceof EClassImpl) {
const eclass = eclassifier;
if (sortedClassifiers.indexOf(eclass) === -1) {
//insert eclass after it's last super type
let idxLastSuperType = -1;
for (const st of eclass.getEAllSuperTypes()) {
if (sortedClassifiers.indexOf(st) > -1) {
const index = sortedClassifiers.indexOf(st);
if (index > idxLastSuperType)
idxLastSuperType = index;
}
}
if (idxLastSuperType >= 0)
sortedClassifiers.splice(idxLastSuperType + 1, 0, eclass);
else
sortedClassifiers.splice(0, 0, eclass);
}
}
//enums and other EClassifiers can go wherever
else {
sortedClassifiers.push(eclassifier);
}
}
return sortedClassifiers;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGdlbmVyYXRvci1wYWNrYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9zb3VyY2UtZ2VuZXJhdG9ycy90Z2VuZXJhdG9yLXBhY2thZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxFQUFFLFNBQVMsSUFBSSxFQUFFLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDdEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzlELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUN0RSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDNUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBRXJFOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBRTNCLFdBQVcsQ0FBYTtJQUVsQix1QkFBdUIsQ0FBQyxHQUFhO1FBQzFDLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsV0FBVyxHQUFHLEdBQUcsQ0FBQztRQUN2QixPQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUU7WUFBRSxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUVsRyxvREFBb0Q7UUFDcEQsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLEVBQVksQ0FBQztRQUV4Qyx3Q0FBd0M7UUFDeEMsSUFBSSxlQUFlLEdBQUc7O21DQUVTLENBQUM7UUFFaEMsSUFBSSx3QkFBd0IsR0FBRyxFQUFFLENBQUM7UUFDbEMsSUFBSSxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBRXhCLGtDQUFrQztRQUNsQyxJQUFJLGFBQWEsR0FBRzs7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SUFBSSxNQUFNLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDO3dCQUM1QyxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDOzRCQUN2QyxNQUFNLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7NEJBQzVDLElBQUksS0FBSyxHQUFHLGdCQUFnQjtnQ0FBRSxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7d0JBQ3pELENBQUM7b0JBQ0gsQ0FBQztvQkFDRCxJQUFJLGdCQUFnQixJQUFJLENBQUM7d0JBQ3ZCLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDOzt3QkFDdkQsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQzlDLENBQUM7WUFDSCxDQUFDO1lBRUQsOENBQThDO2lCQUN6QyxDQUFDO2dCQUNKLGlCQUFpQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN0QyxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8saUJBQWlCLENBQUM7SUFDM0IsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRVBhY2thZ2UgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VwYWNrYWdlLmpzJztcclxuaW1wb3J0IHsgRUVudW0gfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VlbnVtLmpzJztcclxuaW1wb3J0IHsgRUNsYXNzIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lY2xhc3MuanMnO1xyXG5pbXBvcnQgeyBFQ2xhc3NpZmllciB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZWNsYXNzaWZpZXIuanMnO1xyXG5pbXBvcnQgeyBUR2VuVXRpbHMgYXMgRFUgfSBmcm9tICcuL3RnZW4tdXRpbHMuanMnO1xyXG5pbXBvcnQgeyBFQXR0cmlidXRlSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VhdHRyaWJ1dGUtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVDbGFzc0ltcGwgfSBmcm9tICcuLi9tZXRhbW9kZWwvaW1wbC9lY2xhc3MtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVSZWZlcmVuY2VJbXBsIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2ltcGwvZXJlZmVyZW5jZS1pbXBsLmpzJztcclxuaW1wb3J0IHsgRUVudW1JbXBsIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2ltcGwvZWVudW0taW1wbC5qcyc7XHJcbmltcG9ydCB7IEVEYXRhVHlwZUltcGwgfSBmcm9tICcuLi9tZXRhbW9kZWwvaW1wbC9lZGF0YS10eXBlLWltcGwuanMnO1xyXG5cclxuLyoqXHJcbiAqIFJlc3BvbnNpYmxlIGZvciBnZW5lcmF0aW5nIHRoZSBpbnRlcmZhY2UgYW5kIGltcGxlbWVudGF0aW9uIG9mIGFuXHJcbiAqIEVQYWNrYWdlIHNvdXJjZSBmaWxlLCB3aGljaCBwcm92aWRlcyBzdGF0aWMgYWNjZXNzIHRvIGFsbCB0aGUgZWxlbWVudHNcclxuICogb2YgYSBwYWNrYWdlIGluIGEgVE1GIG1vZGVsLlxyXG4gKlxyXG4gKiBOb3RlIHRoYXQgZ2VuZXJhdGlvbiBvZiBzZXZlcmFsIHN3YXRoZXMgb2YgdGhlIHBhY2thZ2UgY29udGVudFxyXG4gKiBhcmUgZ2FuZ2VkIHRvZ2V0aGVyIGludG8gYSBzaW5nbGUgcGFzcyBvdmVyIHRoZSBtb2RlbC4gVGhpcyBvd2VzXHJcbiAqIHRvIHRoZSBmYWN0IHRoYXQgc3VmZmljaWVudCBsb2dpYyBpcyBzaGFyZWQgYWNyb3NzIHRoZWlyIGNvbXB1dGF0aW9ucywgbGFyZ2VseVxyXG4gKiByZWxhdGVkIHRvIHRoZSB0cmFja2luZyBvZiBJRHMgZm9yIGluZGl2aWR1YWwgZWxlbWVudHMsIHRoYXQgaXQgd291bGRcclxuICogYmUgZGlmZmljdWx0IHRvIHNlcGFyYXRlIHRoZW0gb3V0LlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFRHZW5lcmF0b3JQYWNrYWdlIHtcclxuXHJcbiAgIHJvb3RQYWNrYWdlISA6IEVQYWNrYWdlO1xyXG5cclxuICBwdWJsaWMgZ2VuZXJhdGVQYWNrYWdlQ29udGVudHMocGtnOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjbGFzc05hbWUgPSBEVS5nZW5QYWNrYWdlQ2xhc3NOYW1lKHBrZyk7XHJcbiAgICB0aGlzLnJvb3RQYWNrYWdlID0gcGtnO1xyXG4gICAgd2hpbGUodGhpcy5yb290UGFja2FnZS5nZXRFU3VwZXJQYWNrYWdlKCkpIHRoaXMucm9vdFBhY2thZ2UgPSB0aGlzLnJvb3RQYWNrYWdlLmdldEVTdXBlclBhY2thZ2UoKTtcclxuXHJcbiAgICAvL3RyYWNrIHBhY2thZ2UgZGVwZW5kZW5jaWVzLCBpbXBvcnQgdGhlbSBhdCB0aGUgZW5kXHJcbiAgICBjb25zdCBwa2dUb0ltcG9ydCA9IG5ldyBTZXQ8RVBhY2thZ2U+KCk7XHJcblxyXG4gICAgLy9zdGF0aWMgbGlicmFyeSBvZiBhbGwgcGFja2FnZSBjb250ZW50c1xyXG4gICAgbGV0IGxpdGVyYWxzQ29udGVudCA9IGBcclxuICAvKiogUHJvdmlkZXMgc3RhdGljIGFjY2VzcyB0byBFQ2xhc3MgYW5kIEVTdHJ1Y3R1cmFsRmVhdHVyZSBpbnN0YW5jZXMgKi9cclxuICBwdWJsaWMgc3RhdGljIExpdGVyYWxzID0gY2xhc3Mge2A7XHJcblxyXG4gICAgbGV0IGZpZWxkRGVjbGFyYXRpb25zQ29udGVudCA9ICcnO1xyXG4gICAgbGV0IGdldHRlcnNDb250ZW50ID0gJyc7XHJcblxyXG4gICAgLy9pbnNlcnQgY3JlYXRlL2luaXRpYWxpemUgbWV0aG9kc1xyXG4gICAgbGV0IGNyZWF0ZUNvbnRlbnQgPSBgICBwdWJsaWMgY3JlYXRlUGFja2FnZUNvbnRlbnRzKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXNDcmVhdGVkKSByZXR1cm47XHJcbiAgICB0aGlzLmlzQ3JlYXRlZCA9IHRydWU7YDtcclxuXHJcbiAgICBsZXQgaW5pdENvbnRlbnQgPSBgICBwdWJsaWMgaW5pdGlhbGl6ZVBhY2thZ2VDb250ZW50cygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQpIHJldHVybjtcclxuICAgIHRoaXMuaXNJbml0aWFsaXplZCA9IHRydWU7XHJcblxyXG4gICAgLy9yZXVzYWJsZSBoYW5kbGUgZm9yIGVvcGVyYXRpb25zLCB1c2VkIGZvciBhZGRpbmcgcGFyYW1ldGVyc1xyXG4gICAgbGV0IG9wOiBFT3BlcmF0aW9uO2A7XHJcblxyXG4gICAgbGV0IGlkRmllbGRzQ29udGVudCA9ICcnO1xyXG5cclxuICAgIC8vaXRlcmF0ZSBvdmVyIGFsbCBjbGFzc2VzIGFuZCBmZWF0dXJlcywgY3JlYXRlIGFuZCBpbml0aWFsaXplIHRoZW0gQU5EIGNyZWF0ZSBnZXR0ZXJzIHVzaW5nIHRoZSBmZWF0dXJlIElEc1xyXG4gICAgbGV0IGVjSWRDb3VudGVyID0gMDtcclxuXHJcbiAgICAvL3NvcnQgZWNsYXNzaWZpZXJzIGluIHN1Y2ggYSB3YXkgdGhhdCBiYXNlIHR5cGVzIGFyZSBndWFyYW50ZWVkIHRvIHByZWNlZGUgZGVyaXZlZCB0eXBlcyBzb1xyXG4gICAgLy90aGF0IHdlIGNhbiByZWZlcmVuY2UgZmVhdHVyZSBJRHMgaW4gY29ycmVjdCBvcmRlclxyXG4gICAgY29uc3Qgc29ydGVkQ2xhc3NpZmllcnMgPSB0aGlzLnNvcnRDbGFzc2lmaWVyc1dpdGhCYXNlVHlwZXNGaXJzdChwa2cpO1xyXG5cclxuICAgIC8vTk9URTogVGhpcyBpcyB0aGUgJ3NpbmdsZS1wYXNzJyBsb29wIGZvciBnZW5lcmF0aW5nIElEcywgZGVjbGFyaW5nIGVsZW1lbnQgZmllbGRzXHJcbiAgICAvL2FuZCBpbml0aWFsaXppbmcgZWFjaCBhbmQgaG9va2luZyB1cCB0aGVpciByZWZlcmVuY2VzIHdoZXJlIGFwcHJvcHJpYXRlLiBUaGVcclxuICAgIC8vY29udGVudCBmb3IgYWxsIG9mIHRoZXNlIGlzIHRoZW4gaW50ZWdyYXRlZCBpbnRvIHRoZSBmdWxsIHRlbXBsYXRlIG9mIHRoZSBwYWNrYWdlXHJcbiAgICAvL2ZpbGUgaW4gdGhlIHJldHVybiBzdGF0ZW1lbnQgZm9yIHRoaXMgbWV0aG9kXHJcbiAgICBmb3IgKGNvbnN0IGVjbGFzc2lmaWVyIG9mIHNvcnRlZENsYXNzaWZpZXJzKSB7XHJcbiAgICAgIGNvbnN0IGVjbGFzc0lkRmllbGQgPSBEVS5nZW5DbGFzc0lkRmllbGROYW1lKGVjbGFzc2lmaWVyKTtcclxuICAgICAgaWRGaWVsZHNDb250ZW50ICs9IGBcclxuICBwdWJsaWMgc3RhdGljICR7ZWNsYXNzSWRGaWVsZH0gPSAke2VjSWRDb3VudGVyfTtgO1xyXG4gICAgICBlY0lkQ291bnRlcisrO1xyXG5cclxuICAgICAgLy9hZGQgZWNsYXNzaWZpZXIgZmllbGRcclxuICAgICAgbGV0IHR5cGUgPSAnRUNsYXNzJztcclxuICAgICAgaWYgKGVjbGFzc2lmaWVyIGluc3RhbmNlb2YgRUVudW1JbXBsKSB0eXBlID0gJ0VFbnVtJztcclxuICAgICAgZWxzZSBpZiAoZWNsYXNzaWZpZXIgaW5zdGFuY2VvZiBFRGF0YVR5cGVJbXBsKSB0eXBlID0gJ0VEYXRhVHlwZSc7XHJcbiAgICAgIGNvbnN0IGVjbGFzc0ZpZWxkTmFtZSA9IERVLnVuY2FwaXRhbGl6ZShlY2xhc3NpZmllci5nZXROYW1lKCkpICsgdHlwZTtcclxuICAgICAgZmllbGREZWNsYXJhdGlvbnNDb250ZW50ICs9IGBcclxuICBwcml2YXRlICR7ZWNsYXNzRmllbGROYW1lfSE6ICR7dHlwZX07YDtcclxuXHJcbiAgICAgIC8vYWRkIGVjbGFzcyBnZXR0ZXJcclxuICAgICAgY29uc3QgZWNsYXNzR2V0dGVyID0gRFUuZ2VuRWNsYXNzR2V0dGVyTmFtZShlY2xhc3NpZmllcik7XHJcbiAgICAgIGdldHRlcnNDb250ZW50ICs9IGBcclxuICBwdWJsaWMgJHtlY2xhc3NHZXR0ZXJ9KCk6ICR7dHlwZX0ge1xyXG4gICAgcmV0dXJuIHRoaXMuJHtlY2xhc3NGaWVsZE5hbWV9O1xyXG4gIH1gO1xyXG5cclxuICAgICAgLy9hZGQgY3JlYXRpb25cclxuICAgICAgY3JlYXRlQ29udGVudCArPSBgXHJcbiAgICB0aGlzLiR7ZWNsYXNzRmllbGROYW1lfSA9IHRoaXMuY3JlYXRlJHt0eXBlfSgke2NsYXNzTmFtZX0uJHtlY2xhc3NJZEZpZWxkfSk7YDtcclxuXHJcbiAgICAgIC8vYWRkIExpdGVyYWxzIGVudHJ5IGZvciBFQ2xhc3NpZmllclxyXG4gICAgICBsaXRlcmFsc0NvbnRlbnQgKz0gYFxyXG4gICAgc3RhdGljICR7ZWNsYXNzSWRGaWVsZH06ICR7dHlwZX0gPSAke2NsYXNzTmFtZX0uX2VJTlNUQU5DRS4ke0RVLmdlbkVjbGFzc0dldHRlck5hbWUoXHJcbiAgICAgICAgZWNsYXNzaWZpZXJcclxuICAgICAgKX0oKTtgO1xyXG5cclxuICAgICAgLy9hZGQgY2xhc3MgaW5pdGlhbGl6YXRpb25cclxuICAgICAgaWYgKGVjbGFzc2lmaWVyIGluc3RhbmNlb2YgRUNsYXNzSW1wbCkge1xyXG4gICAgICAgIGNvbnN0IGVjbGFzcyA9IDxFQ2xhc3M+ZWNsYXNzaWZpZXI7XHJcbiAgICAgICAgZm9yIChjb25zdCBzdXBlclR5cGUgb2YgZWNsYXNzaWZpZXIuZ2V0RVN1cGVyVHlwZXMoKSkge1xyXG4gICAgICAgICAgY29uc3QgcGtnUmVmID0gRFUuZ2V0UmVmZXJlbmNlVG9QYWNrYWdlSW5zdGFuY2UoXHJcbiAgICAgICAgICAgIHN1cGVyVHlwZSxcclxuICAgICAgICAgICAgZWNsYXNzaWZpZXIsXHJcbiAgICAgICAgICAgIHBrZ1RvSW1wb3J0XHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgaW5pdENvbnRlbnQgKz0gYFxyXG4gICAgdGhpcy4ke2VjbGFzc0ZpZWxkTmFtZX0uZ2V0RVN1cGVyVHlwZXMoKS5hZGQoJHtwa2dSZWZ9LiR7RFUuZ2VuRWNsYXNzR2V0dGVyTmFtZShcclxuICAgICAgICAgICAgc3VwZXJUeXBlXHJcbiAgICAgICAgICApfSgpKTtgO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpbml0Q29udGVudCArPSBgXHJcbiAgICB0aGlzLmluaXQke3R5cGV9KFxyXG4gICAgICB0aGlzLiR7ZWNsYXNzRmllbGROYW1lfSxcclxuICAgICAgJyR7ZWNsYXNzaWZpZXIuZ2V0TmFtZSgpfScsXHJcbiAgICAgICR7ZWNsYXNzaWZpZXIuaXNBYnN0cmFjdCgpfSxcclxuICAgICAgJHtlY2xhc3NpZmllci5pc0ludGVyZmFjZSgpfSxcclxuICAgICAgdHJ1ZVxyXG4gICAgKTtgO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGluaXRDb250ZW50ICs9IGBcclxuICAgIHRoaXMuaW5pdCR7dHlwZX0oXHJcbiAgICAgIHRoaXMuJHtlY2xhc3NGaWVsZE5hbWV9LCAnJHtlY2xhc3NpZmllci5nZXROYW1lKCl9Jyk7YDtcclxuXHJcbiAgICAgICAgaWYgKGVjbGFzc2lmaWVyIGluc3RhbmNlb2YgRUVudW1JbXBsKSB7XHJcbiAgICAgICAgICBsZXQgbGl0ZXJhbEluZCA9IDA7XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IGxpdGVyYWwgb2YgKDxFRW51bT5lY2xhc3NpZmllcikuZ2V0RUxpdGVyYWxzKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgbGl0UmVmID0gZWNsYXNzaWZpZXIuZ2V0TmFtZSgpICsgJy4nICsgbGl0ZXJhbC5nZXROYW1lKCk7XHJcbiAgICAgICAgICAgIGluaXRDb250ZW50ICs9IGBcclxuICAgIHRoaXMuYWRkRUVudW1MaXRlcmFsKHRoaXMuJHtlY2xhc3NGaWVsZE5hbWV9LCAnJHtsaXRlcmFsLmdldE5hbWUoKX0nLCAke2xpdGVyYWxJbmR9KTtgO1xyXG4gICAgICAgICAgICBsaXRlcmFsSW5kKys7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL3Byb2Nlc3MgcmVmZXJlbmNlcyBhbmQgYXR0cmlidXRlc1xyXG4gICAgICBpZiAoZWNsYXNzaWZpZXIgaW5zdGFuY2VvZiBFQ2xhc3NJbXBsKSB7XHJcbiAgICAgICAgLy9maW5kIHN1cGVyIHR5cGVcclxuICAgICAgICBjb25zdCBzdXBlclR5cGUgPVxyXG4gICAgICAgICAgZWNsYXNzaWZpZXIuZ2V0RVN1cGVyVHlwZXMoKS5zaXplKCkgPiAwXHJcbiAgICAgICAgICAgID8gZWNsYXNzaWZpZXIuZ2V0RVN1cGVyVHlwZXMoKS5nZXQoMClcclxuICAgICAgICAgICAgOiBudWxsO1xyXG5cclxuICAgICAgICAvL3dyaXRlIG91dCBmZWF0dXJlIGNvdW50IGZpZWxkICh3aWxsIGJlIHRoZSBzdGFydGluZyBwb2ludCBmb3IgSUQnaW5nIG5ldyBmaWVsZHMgb24gdGhpcyBlY2xhc3MpXHJcbiAgICAgICAgY29uc3QgZmVhdHVyZUNvdW50RmllbGQgPSBEVS5nZW5GZWF0dXJlQ291bnRGaWVsZE5hbWUoZWNsYXNzaWZpZXIpO1xyXG5cclxuICAgICAgICBjb25zdCBzdXBlclR5cGVGZWF0dXJlQ291bnQgPSAgc3VwZXJUeXBlPyBzdXBlclR5cGUuZ2V0RUFsbFN0cnVjdHVyYWxGZWF0dXJlcygpLnNpemUoKSA6IDA7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAvL0VsaW1pbmF0aW5nIHJlZmVyZW5jZXMgdG8gc3VwZXIgdHlwZXMgaW4gc3RhdGljIGluaXRpYWxpemVycywgc2luY2UgdGhleSBjb3VsZCBiZSBpbiBvdGhlciBwYWNrYWdlcyAoY2lyY3VsYXIgaW1wb3J0KVxyXG4gICAgICAgIC8vIGNvbnN0IHN1cGVyVHlwZUNvdW50RmllbGQgPSBzdXBlclR5cGVcclxuICAgICAgICAvLyAgID8gRFUuZ2VuUGFja2FnZUNsYXNzTmFtZShzdXBlclR5cGUuZ2V0RVBhY2thZ2UoKSkgK1xyXG4gICAgICAgIC8vICAgICAnLicgK1xyXG4gICAgICAgIC8vICAgICBEVS5nZW5GZWF0dXJlQ291bnRGaWVsZE5hbWUoc3VwZXJUeXBlKSArXHJcbiAgICAgICAgLy8gICAgICcgKyAnXHJcbiAgICAgICAgLy8gICA6ICcnO1xyXG4gICAgICAgIFxyXG4gIC8vICAgICAgIGlmIChzdXBlclR5cGVDb3VudEZpZWxkKSB7XHJcbiAgLy8gICAgICAgICBpZEZpZWxkc0NvbnRlbnQgKz0gYFxyXG4gIC8vIHB1YmxpYyBzdGF0aWMgJHtmZWF0dXJlQ291bnRGaWVsZH0gPVxyXG4gIC8vICAgJHtzdXBlclR5cGVDb3VudEZpZWxkfSR7ZWNsYXNzaWZpZXIuZ2V0RVN0cnVjdHVyYWxGZWF0dXJlcygpLnNpemUoKX07YDtcclxuICAvLyAgICAgICB9IGVsc2Uge1xyXG4gIC8vICAgICAgICAgaWRGaWVsZHNDb250ZW50ICs9IGBcclxuICAvLyBwdWJsaWMgc3RhdGljICR7ZmVhdHVyZUNvdW50RmllbGR9ID0gJHtlY2xhc3NpZmllci5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkuc2l6ZSgpfTtgO1xyXG4gIC8vICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvL3RoaXMgaXMgdGhlIHJlcGxhY2VtZW50IC0ganVzdCBhIHN0cmFpZ2h0IGNvdW50IG9mIGFsbCBmZWF0dXJlcywgc2hvdWRsIGJlIHNhbWVcclxuICAgICAgICAgIGlkRmllbGRzQ29udGVudCArPSBgXHJcbiAgcHVibGljIHN0YXRpYyAke2ZlYXR1cmVDb3VudEZpZWxkfSA9ICR7ZWNsYXNzaWZpZXIuZ2V0RUFsbFN0cnVjdHVyYWxGZWF0dXJlcygpLnNpemUoKX07YDtcclxuXHJcbiAgICAgICAgLy9rZWVwcyB0cmFjayBvZiB0aGUgZmVhdHVyZSdzIGluZGV4IGluIGl0J3MgZUNsYXNzICh1c2VkIGZvciBmZWF0dXJlIGdldHRlcilcclxuICAgICAgICBsZXQgdGhpc0NsYXNzRmVhdHVyZUluZGV4ID0gMDtcclxuICAgICAgICBmb3IgKGNvbnN0IGZlYXR1cmUgb2YgKDxFQ2xhc3M+ZWNsYXNzaWZpZXIpLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKSkge1xyXG4gICAgICAgICAgY29uc3QgZmVhdHVyZUlkRmllbGQgPSBEVS5nZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmVhdHVyZSk7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vRWxpbWluYXRpbmcgcmVmZXJlbmNlcyB0byBzdXBlciB0eXBlcyBpbiBzdGF0aWMgaW5pdGlhbGl6ZXJzLCBzaW5jZSB0aGV5IGNvdWxkIGJlIGluIG90aGVyIHBhY2thZ2VzIChjaXJjdWxhciBpbXBvcnQpICAgICAgICAgIFxyXG4gIC8vICAgICAgICAgaWYgKHN1cGVyVHlwZUNvdW50RmllbGQpIHtcclxuICAvLyAgICAgICAgICAgaWRGaWVsZHNDb250ZW50ICs9IGBcclxuICAvLyBwdWJsaWMgc3RhdGljICR7ZmVhdHVyZUlkRmllbGR9ID0gJHtzdXBlclR5cGVDb3VudEZpZWxkfSR7dGhpc0NsYXNzRmVhdHVyZUluZGV4fTtgO1xyXG4gIC8vICAgICAgICAgfSBlbHNlIHtcclxuICAvLyAgICAgICAgICAgaWRGaWVsZHNDb250ZW50ICs9IGBcclxuICAvLyBwdWJsaWMgc3RhdGljICR7ZmVhdHVyZUlkRmllbGR9ID0gJHt0aGlzQ2xhc3NGZWF0dXJlSW5kZXh9O2A7XHJcbiAgLy8gICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vdGhpcyBpcyB0aGUgcmVwbGFjZW1lbnQgLSBqdXN0IGFkZCB0byB0aGUgc3VwZXIgdHlwZSBmZWF0dXJlIGNvdW50XHJcbiAgICAgICAgICAgIGlkRmllbGRzQ29udGVudCArPSBgXHJcbiAgcHVibGljIHN0YXRpYyAke2ZlYXR1cmVJZEZpZWxkfSA9ICR7c3VwZXJUeXBlRmVhdHVyZUNvdW50ICsgdGhpc0NsYXNzRmVhdHVyZUluZGV4fTtgOyAgICAgICAgXHJcblxyXG5cclxuICAgICAgICAgIGNvbnN0IGZlYXR1cmVUeXBlID1cclxuICAgICAgICAgICAgZmVhdHVyZSBpbnN0YW5jZW9mIEVBdHRyaWJ1dGVJbXBsID8gJ0VBdHRyaWJ1dGUnIDogJ0VSZWZlcmVuY2UnO1xyXG4gICAgICAgICAgbGl0ZXJhbHNDb250ZW50ICs9IGBcclxuICAgIHN0YXRpYyAke2ZlYXR1cmVJZEZpZWxkfTogJHtmZWF0dXJlVHlwZX0gPVxyXG4gICAgICAke2NsYXNzTmFtZX0uX2VJTlNUQU5DRS5nZXQke0RVLmNhcGl0YWxpemUoXHJcbiAgICAgICAgICAgIGVjbGFzc2lmaWVyLmdldE5hbWUoKVxyXG4gICAgICAgICAgKX1fJHtEVS5jYXBpdGFsaXplKGZlYXR1cmUuZ2V0TmFtZSgpKX0oKTtgO1xyXG5cclxuICAgICAgICAgIC8vY3JlYXRlIGZlYXR1cmVzXHJcbiAgICAgICAgICBjcmVhdGVDb250ZW50ICs9IGBcclxuICAgIHRoaXMuY3JlYXRlJHtmZWF0dXJlVHlwZX0oXHJcbiAgICAgIHRoaXMuJHtlY2xhc3NGaWVsZE5hbWV9LFxyXG4gICAgICAke2NsYXNzTmFtZX0uJHtmZWF0dXJlSWRGaWVsZH1cclxuICAgICk7YDtcclxuXHJcbiAgICAgICAgICBjb25zdCBmZWF0dXJlR2V0dGVyTmFtZSA9IERVLmdlbkZlYXR1cmVHZXR0ZXJOYW1lKGZlYXR1cmUpO1xyXG5cclxuICAgICAgICAgIC8vYWRkIGZlYXR1cmUgZ2V0dGVyXHJcbiAgICAgICAgICBnZXR0ZXJzQ29udGVudCArPSBgXHJcbiAgcHVibGljICR7ZmVhdHVyZUdldHRlck5hbWV9KCk6ICR7ZmVhdHVyZVR5cGV9IHtcclxuICAgIHJldHVybiA8JHtmZWF0dXJlVHlwZX0+dGhpcy4ke2VjbGFzc0ZpZWxkTmFtZX0uZ2V0RVN0cnVjdHVyYWxGZWF0dXJlcygpLmdldCgke3RoaXNDbGFzc0ZlYXR1cmVJbmRleH0pO1xyXG4gIH1gO1xyXG5cclxuICAgICAgICAgIC8vdGhlIGdldHRlciBmb3IgdGhlIGZlYXR1cmUncyB0eXBlIChFY2xhc3NpZmllciBpbnN0YW5jZSlcclxuICAgICAgICAgIGNvbnN0IGZlYXR1cmVUeXBlR2V0dGVyID0gdGhpcy5nZXR0ZXJGb3JFVHlwZShcclxuICAgICAgICAgICAgZmVhdHVyZS5nZXRFVHlwZSgpISxcclxuICAgICAgICAgICAgZWNsYXNzaWZpZXIsXHJcbiAgICAgICAgICAgIHBrZ1RvSW1wb3J0LFxyXG4gICAgICAgICAgICBwa2dcclxuICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgLy9pbml0aWFsaXplcnNcclxuICAgICAgICAgIGluaXRDb250ZW50ICs9IGBcclxuICAgIHRoaXMuaW5pdCR7ZmVhdHVyZVR5cGV9KFxyXG4gICAgICB0aGlzLiR7ZmVhdHVyZUdldHRlck5hbWV9KClgO1xyXG4gICAgICAgICAgaWYgKGZlYXR1cmUgaW5zdGFuY2VvZiBFQXR0cmlidXRlSW1wbCkge1xyXG4gICAgICAgICAgICBpbml0Q29udGVudCArPSBgLFxyXG4gICAgICAke2ZlYXR1cmVUeXBlR2V0dGVyfSxcclxuICAgICAgJyR7ZmVhdHVyZS5nZXROYW1lKCl9JyxcclxuICAgICAgJHtmZWF0dXJlLmdldERlZmF1bHRWYWx1ZUxpdGVyYWwoKSA/IGZlYXR1cmUuZ2V0RGVmYXVsdFZhbHVlTGl0ZXJhbCgpIDogYCcnYH0sXHJcbiAgICAgICR7ZmVhdHVyZS5nZXRMb3dlckJvdW5kKCl9LFxyXG4gICAgICAke2ZlYXR1cmUuZ2V0VXBwZXJCb3VuZCgpfSxcclxuICAgICAgJycsXHJcbiAgICAgICR7ZmVhdHVyZS5pc1RyYW5zaWVudCgpID8/IGZhbHNlfSxcclxuICAgICAgJHtmZWF0dXJlLmlzVm9sYXRpbGUoKSA/PyBmYWxzZX0sXHJcbiAgICAgICR7ZmVhdHVyZS5pc0NoYW5nZWFibGUoKSA/PyB0cnVlfSxcclxuICAgICAgdHJ1ZSxcclxuICAgICAgJHtmZWF0dXJlLmlzSWQoKSA/PyBmYWxzZX0sXHJcbiAgICAgIGZhbHNlLFxyXG4gICAgICBmYWxzZSxcclxuICAgICAgZmFsc2VgIFxyXG4gICAgICAgICAgfSBlbHNlIGlmIChmZWF0dXJlIGluc3RhbmNlb2YgRVJlZmVyZW5jZUltcGwpIHtcclxuICAgICAgICAgICAgY29uc3QgcGtnUmVmID0gRFUuZ2V0UmVmZXJlbmNlVG9QYWNrYWdlSW5zdGFuY2UoXHJcbiAgICAgICAgICAgICAgZmVhdHVyZS5nZXRFVHlwZSgpISxcclxuICAgICAgICAgICAgICBlY2xhc3NpZmllcixcclxuICAgICAgICAgICAgICBwa2dUb0ltcG9ydFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBsZXQgZW9wcG9zaXRlID0gJ3VuZGVmaW5lZCc7XHJcbiAgICAgICAgICAgIGlmIChmZWF0dXJlLmdldEVPcHBvc2l0ZSgpKSB7XHJcbiAgICAgICAgICAgICAgZW9wcG9zaXRlID0gYCR7cGtnUmVmfS4ke0RVLmdlbkZlYXR1cmVHZXR0ZXJOYW1lKFxyXG4gICAgICAgICAgICAgICAgZmVhdHVyZS5nZXRFT3Bwb3NpdGUoKSFcclxuICAgICAgICAgICAgICApfSgpYDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpbml0Q29udGVudCArPSBgLFxyXG4gICAgICAke2ZlYXR1cmVUeXBlR2V0dGVyfSxcclxuICAgICAgJHtlb3Bwb3NpdGV9LFxyXG4gICAgICAnJHtmZWF0dXJlLmdldE5hbWUoKX0nLFxyXG4gICAgICAnJyxcclxuICAgICAgJHtmZWF0dXJlLmdldExvd2VyQm91bmQoKX0sXHJcbiAgICAgICR7ZmVhdHVyZS5nZXRVcHBlckJvdW5kKCl9LFxyXG4gICAgICAnJyxcclxuICAgICAgJHtmZWF0dXJlLmlzVHJhbnNpZW50KCkgPz8gZmFsc2V9LFxyXG4gICAgICAke2ZlYXR1cmUuaXNWb2xhdGlsZSgpID8/IGZhbHNlfSxcclxuICAgICAgJHtmZWF0dXJlLmlzQ2hhbmdlYWJsZSgpID8/IGZhbHNlfSxcclxuICAgICAgJHtmZWF0dXJlLmlzQ29udGFpbm1lbnQoKSA/PyBmYWxzZX0sXHJcbiAgICAgIGZhbHNlLFxyXG4gICAgICB0cnVlLFxyXG4gICAgICBmYWxzZSxcclxuICAgICAgZmFsc2UsXHJcbiAgICAgIGZhbHNlYDtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGluaXRDb250ZW50ICs9IGBcclxuICAgICk7YDtcclxuICAgICAgICAgIHRoaXNDbGFzc0ZlYXR1cmVJbmRleCsrO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9sb2dpYyBmb3IgY3JlYXRpbmcgYW5kIGluaXRpYWxpemluZyBFT3BlcmF0aW9uc1xyXG4gICAgICAgIGxldCBlb3BJbmRleCA9IDA7XHJcbiAgICAgICAgZm9yIChjb25zdCBlb3Agb2YgZWNsYXNzaWZpZXIuZ2V0RU9wZXJhdGlvbnMoKSkge1xyXG4gICAgICAgICAgY29uc3QgZW9wSWRGaWVsZCA9IERVLmdlbk9wZXJhdGlvbklkRmllbGROYW1lKGVvcCk7XHJcbiAgICAgICAgICAvL2FkZCBJRCBjb250ZW50XHJcbiAgICAgICAgICBpZEZpZWxkc0NvbnRlbnQgKz0gYFxyXG4gIHB1YmxpYyBzdGF0aWMgJHtlb3BJZEZpZWxkfSA9ICR7ZW9wSW5kZXh9O2A7XHJcbiAgICAgICAgICBjcmVhdGVDb250ZW50ICs9IGBcclxuICAgIHRoaXMuY3JlYXRlRU9wZXJhdGlvbih0aGlzLiR7ZWNsYXNzRmllbGROYW1lfSwgJHtjbGFzc05hbWV9LiR7ZW9wSWRGaWVsZH0pO2A7XHJcbiAgICAgICAgICBjb25zdCBmZWF0dXJlR2V0dGVyTmFtZSA9IERVLmdlbk9wZXJhdGlvbkdldHRlck5hbWUoZW9wKTtcclxuICAgICAgICAgIGdldHRlcnNDb250ZW50ICs9IGBcclxuICBwdWJsaWMgJHtmZWF0dXJlR2V0dGVyTmFtZX0oKTogRU9wZXJhdGlvbiB7XHJcbiAgICByZXR1cm4gdGhpcy4ke2VjbGFzc0ZpZWxkTmFtZX0uZ2V0RU9wZXJhdGlvbnMoKS5nZXQoJHtlb3BJbmRleH0pO1xyXG4gIH1gO1xyXG4gICAgICAgICAgaW5pdENvbnRlbnQgKz0gYFxyXG4gICAgb3AgPSB0aGlzLmluaXRFT3BlcmF0aW9uKFxyXG4gICAgICB0aGlzLiR7ZmVhdHVyZUdldHRlck5hbWV9KCksXHJcbiAgICAgICR7dGhpcy5nZXR0ZXJGb3JFVHlwZShlb3AuZ2V0RVR5cGUoKSEsIGVjbGFzc2lmaWVyLCBwa2dUb0ltcG9ydCwgcGtnKX0sXHJcbiAgICAgICcke2VvcC5nZXROYW1lKCl9JyxcclxuICAgICAgMCxcclxuICAgICAgJHtlb3AuaXNNYW55KCkgPyAtMSA6IDF9LFxyXG4gICAgICB0cnVlLFxyXG4gICAgICB0cnVlXHJcbiAgICApO2A7XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IHAgb2YgZW9wLmdldEVQYXJhbWV0ZXJzKCkpIHtcclxuICAgICAgICAgICAgLy9UT0RPOiBDcmVhdGUgcGFyYW1ldGVycyBhbmQgYWRkIHRoZW0gdG8gRU9waGVyZVxyXG4gICAgICAgICAgICBpbml0Q29udGVudCArPSBgXHJcbiAgICB0aGlzLmNyZWF0ZUVQYXJhbWV0ZXIoXHJcbiAgICAgIG9wLFxyXG4gICAgICAnJHtwLmdldE5hbWUoKX0nLFxyXG4gICAgICAke3AuaXNNYW55KCkgPyAtMSA6IDF9LFxyXG4gICAgICAgJHt0aGlzLmdldHRlckZvckVUeXBlKHAuZ2V0RVR5cGUoKSwgZWNsYXNzaWZpZXIsIHBrZ1RvSW1wb3J0LCBwa2cpfVxyXG4gICAgKTtgXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBlb3BJbmRleCsrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNyZWF0ZUNvbnRlbnQgKz0gYFxyXG4gIH1gO1xyXG4gICAgaW5pdENvbnRlbnQgKz0gYFxyXG4gIH1gO1xyXG4gICAgbGl0ZXJhbHNDb250ZW50ICs9IGBcclxuICB9O2A7XHJcblxyXG4gICAgLy9FY29yZVBhY2thZ2UgY2Fubm90IGV4dGVuZCBFUGFja2FnZUltcGwsIGFzIGl0IGl0IHdvdWxkIGNyZWF0ZSBjaXJjdWxhciByZWZlcmVuY2VcclxuICAgIGNvbnN0IHRvRXh0ZW5kID1cclxuICAgICAgcGtnLmdldE5hbWUoKS50b0xvd2VyQ2FzZSgpID09PSAnZWNvcmUnID8gJ0VQYWNrYWdlJyA6ICdFUGFja2FnZUltcGwnO1xyXG5cclxuICBsZXQgc3ViUGtnU2V0dGVycyA9ICcnO1xyXG5cclxuICAgIC8vIGZvcihjb25zdCBzdWJQa2cgb2YgcGtnLmdldEVTdWJQYWNrYWdlcygpKXtcclxuICAgIC8vICAgaWYoIXBrZ1RvSW1wb3J0LmhhcyhzdWJQa2cpKXtcclxuICAgIC8vICAgICBwa2dUb0ltcG9ydC5hZGQoc3ViUGtnKTtcclxuICAgIC8vICAgfVxyXG4gICAgLy8gICBzdWJQa2dTZXR0ZXJzICs9IGBcclxuICAgIC8vICR7RFUuZ2VuUGFja2FnZUNsYXNzTmFtZShzdWJQa2cpfS5lSU5TVEFOQ0Uuc2V0RVN1cGVyUGFja2FnZSh0aGUke2NsYXNzTmFtZX0pYDtcclxuICAgIC8vIH1cclxuXHJcbiAgICByZXR1cm4gYCR7dGhpcy5nZW5lcmF0ZUltcG9ydHMocGtnVG9JbXBvcnQsIHBrZyl9XHJcbmV4cG9ydCBjbGFzcyAke2NsYXNzTmFtZX0gZXh0ZW5kcyAke3RvRXh0ZW5kfSB7JHtpZEZpZWxkc0NvbnRlbnR9XHJcblxyXG4gIC8qKiBTaW5nbGV0b24gKi9cclxuICBwdWJsaWMgc3RhdGljIF9lSU5TVEFOQ0U6ICR7Y2xhc3NOYW1lfSA9ICR7Y2xhc3NOYW1lfS5pbml0KCk7XHJcblxyXG4gIC8vaWYgdGhlIHNpbmdsZXRvbiBpcyBpbml0aWFsaXplZFxyXG4gIHByaXZhdGUgc3RhdGljIGlzSW5pdGVkID0gZmFsc2U7XHJcblxyXG4gIHN0YXRpYyBlTlNfVVJJID1cclxuICAgICcke3BrZy5nZXROc1VSSSgpfSc7XHJcbiAgc3RhdGljIGVOQU1FID0gJyR7cGtnLmdldE5hbWUoKX0nO1xyXG4gIHN0YXRpYyBlTlNfUFJFRklYID0gJyR7cGtnLmdldE5zUHJlZml4KCl9JztcclxuJHtsaXRlcmFsc0NvbnRlbnR9XHJcblxyXG4gIC8vZmxhZ3MgdGhhdCBrZWVwIHRyYWNrIG9mIHdoZXRoZXIgcGFja2FnZSBpcyBpbml0aWFsaXplZFxyXG4gIHByaXZhdGUgaXNDcmVhdGVkID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBpc0luaXRpYWxpemVkID0gZmFsc2U7XHJcbiR7ZmllbGREZWNsYXJhdGlvbnNDb250ZW50fVxyXG5cclxuICAvL2NhdXNlcyBFUGFja2FnZS5SZWdpc3RyeSByZWdpc3RyYXRpb24gZXZlbnRcclxuICAvL2hhcmQtY29kZWQgVVJJLCBzaW5jZSByZWZlcnJpbmcgdG8gdGhlIHN0YXRpYyBlTlNfVVJJIGZpZWxkIGluIGNvbnN0cnVjdG9yIGNhbiBjYXVzZSBpc3N1ZXNcclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICAgIHN1cGVyKFxyXG4gICAgICAnJHtwa2cuZ2V0TmFtZSgpfScsXHJcbiAgICAgICcke3BrZy5nZXROc1VSSSgpfScsXHJcbiAgICAgICcke3BrZy5nZXROc1ByZWZpeCgpfSdcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbnZva2VkIG9uY2UuIEluaXRpYWxpemVzIHRoZSBTaW5nbGV0b24uXHJcbiAgICpcclxuICAgKiBOT1RFOiBMb3RzIG9mIGRpZmZlcmVuY2VzIGhlcmUgd2l0aCB0aGUgRU1GIHZlcnNpb24sIHdoaWNoIGludGVyYWN0cyB3aXRoIHRoZSBwYWNrYWdlIFJlZ2lzdHJ5LFxyXG4gICAqIG90aGVyIHBhY2thZ2VzIGZyb20gdGhlIHNhbWUgbW9kZWwgdG8gcmVnaXN0ZXIgaW50ZXJkZXBlbmRlbmNpZXMsIGFuZCBmcmVlemVzIHRoZSBwYWNrYWdlIG1ldGEtZGF0YS5cclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBpbml0KCk6ICR7Y2xhc3NOYW1lfSB7XHJcbiAgICBpZiAoJHtjbGFzc05hbWV9LmlzSW5pdGVkKSByZXR1cm4gdGhpcy5fZUlOU1RBTkNFO1xyXG4gICAgLy8gT2J0YWluIG9yIGNyZWF0ZSBhbmQgcmVnaXN0ZXIgcGFja2FnZVxyXG4gICAgY29uc3QgdGhlJHtjbGFzc05hbWV9ID0gbmV3ICR7Y2xhc3NOYW1lfSgpO1xyXG4gICAgLy90aGlzIGlzIG5lY2Vzc2FyeSBzcGVjaWZpY2FsbHkgZm9yIEVjb3JlUGFja2FnZSBnZW5lcmF0aW9uLCB3aGljaCBuZWVkcyB0byByZWZlciB0byBpdHNlbGZcclxuICAgIHRoaXMuX2VJTlNUQU5DRSA9IHRoZSR7Y2xhc3NOYW1lfTtcclxuICAgICR7Y2xhc3NOYW1lfS5pc0luaXRlZCA9IHRydWU7XHJcbiR7c3ViUGtnU2V0dGVyc30gICAgXHJcblxyXG4gICAgLy8gQ3JlYXRlIHBhY2thZ2UgbWV0YS1kYXRhIG9iamVjdHNcclxuICAgIHRoZSR7Y2xhc3NOYW1lfS5jcmVhdGVQYWNrYWdlQ29udGVudHMoKTtcclxuXHJcbiAgICAvLyBJbml0aWFsaXplIGNyZWF0ZWQgbWV0YS1kYXRhXHJcbiAgICAvLyB0aGUke2NsYXNzTmFtZX0uaW5pdGlhbGl6ZVBhY2thZ2VDb250ZW50cygpO1xyXG4gICAgcmV0dXJuIHRoaXMuX2VJTlNUQU5DRTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBnZXQgZUlOU1RBTkNFKCk6ICR7Y2xhc3NOYW1lfXtcclxuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcclxuICAgIHJldHVybiB0aGlzLl9lSU5TVEFOQ0U7XHJcbiAgfSAgXHJcblxyXG4gIC8qKlxyXG4gICAqIEVuc3VyZXMgdGhpcyBwYWNrYWdlIGFuZCBpdCdzIGRlcGRlbmRlbmNpZXMgYXJlIGZ1bGx5IGluaXRpYWxpemVkIGFuZCByZWdpc3RlcmVkIHdpdGggVEpzb25cclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBlbnN1cmVJbml0aWFsaXplZCgpOiB2b2lkIHtcclxuICAgIGNvbnN0IHBhY2thZ2VOYW1lID0gJyR7cGtnLmdldE5hbWUoKX0nO1xyXG5cclxuICAgIGlmIChQYWNrYWdlUmVnaXN0cnkuaXNJbml0aWFsaXplZChwYWNrYWdlTmFtZSkpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEluaXRpYWxpemUgdGhpcyBwYWNrYWdlJ3MgY29udGVudHNcclxuICAgIGNvbnN0IHBrZyA9IHRoaXMuX2VJTlNUQU5DRTtcclxuICAgIHBrZy5pbml0aWFsaXplUGFja2FnZUNvbnRlbnRzKCk7XHJcblxyXG4gICAgLy8gTWFyayBhcyBpbml0aWFsaXplZCBmaXJzdCB0byBwcmV2ZW50IGN5Y2xlc1xyXG4gICAgUGFja2FnZVJlZ2lzdHJ5Lm1hcmtJbml0aWFsaXplZChwYWNrYWdlTmFtZSk7XHJcblxyXG4gICAgLy8gUmVnaXN0ZXIgd2l0aCBUSnNvblxyXG4gICAgUGFja2FnZVJlZ2lzdHJ5LnJlZ2lzdGVyV2l0aFRKc29uKHBhY2thZ2VOYW1lLCBwa2cpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsbGVkIGJ5IHRoZSBmYWN0b3J5IHRvIHJlZ2lzdGVyIGl0c2VsZiB3aXRoIHRoaXMgcGFja2FnZVxyXG4gICAqL1xyXG4gIHN0YXRpYyByZWdpc3RlckZhY3RvcnkoZmFjdG9yeTogRUZhY3RvcnkpOiB2b2lkIHtcclxuICAgIHRoaXMuX2VJTlNUQU5DRS5zZXRFRmFjdG9yeUluc3RhbmNlKGZhY3RvcnkpO1xyXG4gIH0gIFxyXG5cclxuICAvL3RoaXMgdXNlZCB0byBiZSBkaXJlY3QgbGF6eSByZXRyaWV2YWwgb2YgdGhlXHJcbiAgLy9mYWN0b3J5IGluc3RhbmNlIGZyb20gdGhlIGNvcnJlc3BvbmRpbmcgLnRzIGZhY3RvcnkgZmlsZSwgYnV0XHJcbiAgLy90aGF0IHdhcyBlbGltaW5hdGVkIHRvIGF2b2lkIGNpcmN1bGFyIGltcG9ydHNcclxuICBwdWJsaWMgb3ZlcnJpZGUgZ2V0RUZhY3RvcnlJbnN0YW5jZSgpOiBFRmFjdG9yeSB7XHJcbiAgICBpZiAoIXRoaXMuX2VGYWN0b3J5SW5zdGFuY2UpIHtcclxuICAgICAgLy8gVHJ5IHRvIGdldCBmYWN0b3J5IGZyb20gcmVnaXN0cnlcclxuICAgICAgY29uc3QgZmFjdG9yeSA9IFBhY2thZ2VSZWdpc3RyeS5nZXRGYWN0b3J5KCcke3BrZy5nZXROYW1lKCl9Jyk7XHJcbiAgICAgIGlmIChmYWN0b3J5KSB7XHJcbiAgICAgICAgdGhpcy5zZXRFRmFjdG9yeUluc3RhbmNlKGZhY3RvcnkpO1xyXG4gICAgICB9XHJcbiAgICB9ICBcclxuICAgIHJldHVybiB0aGlzLl9lRmFjdG9yeUluc3RhbmNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhpcyB3aWxsIGJlIGludm9rZWQgYnkgdGhlIEZhY3Rvcnkgd2hlbiBpdCBpcyBpbml0aWFsaXplZCwgYW55IGludm9jYXRpb25zXHJcbiAgICogYWZ0ZXJ3YXJkcyB3aWxsIGhhdmUgbm8gZWZmZWN0LlxyXG4gICAqL1xyXG4gIHB1YmxpYyBvdmVycmlkZSBzZXRFRmFjdG9yeUluc3RhbmNlKGZhY3RvcnlJbnN0OiBFRmFjdG9yeSk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLl9lRmFjdG9yeUluc3RhbmNlKSB0aGlzLl9lRmFjdG9yeUluc3RhbmNlID0gZmFjdG9yeUluc3Q7XHJcbiAgfVxyXG4ke2dldHRlcnNDb250ZW50fVxyXG5cclxuJHtjcmVhdGVDb250ZW50fVxyXG5cclxuJHtpbml0Q29udGVudH1cclxufVxyXG5gO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVXNlciBmb3IgZ2VuZXJhdGluZyAnZ2V0JyBvbiB0aGUgRVR5cGUgZm9yIGEgZmVhdHVyZSBvciBvcGVyYXRpb24uXHJcbiAgICpcclxuICAgKiBAcGFyYW0gZXR5cGVcclxuICAgKiBAcGFyYW0gb3duaW5nRUNsYXNzXHJcbiAgICogQHBhcmFtIHBrZ1RvSW1wb3J0XHJcbiAgICogQHBhcmFtIHBrZ1xyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXR0ZXJGb3JFVHlwZShcclxuICAgIGV0eXBlOiBFQ2xhc3NpZmllcixcclxuICAgIG93bmluZ0VDbGFzczogRUNsYXNzLFxyXG4gICAgcGtnVG9JbXBvcnQ6IFNldDxFUGFja2FnZT4sXHJcbiAgICBwa2c6IEVQYWNrYWdlXHJcbiAgKSB7XHJcbiAgICBsZXQgZmVhdHVyZVR5cGVHZXR0ZXIgPSB1bmRlZmluZWQ7XHJcbiAgICBpZiAoZXR5cGUpIHtcclxuICAgICAgY29uc3QgcGtnUmVmID0gRFUuZ2V0UmVmZXJlbmNlVG9QYWNrYWdlSW5zdGFuY2UoXHJcbiAgICAgICAgZXR5cGUsXHJcbiAgICAgICAgb3duaW5nRUNsYXNzLFxyXG4gICAgICAgIHBrZ1RvSW1wb3J0XHJcbiAgICAgICk7XHJcbiAgICAgIGlmIChldHlwZSBpbnN0YW5jZW9mIEVFbnVtSW1wbCkge1xyXG4gICAgICAgIGZlYXR1cmVUeXBlR2V0dGVyID0gYCR7cGtnUmVmfS5nZXQke2V0eXBlLmdldE5hbWUoKX0oKWA7XHJcbiAgICAgIH0gZWxzZSBpZiAoZXR5cGUgaW5zdGFuY2VvZiBFQ2xhc3NJbXBsKSB7XHJcbiAgICAgICAgY29uc3QgcGtnUmVmID0gRFUuZ2V0UmVmZXJlbmNlVG9QYWNrYWdlSW5zdGFuY2UoXHJcbiAgICAgICAgICBldHlwZSxcclxuICAgICAgICAgIG93bmluZ0VDbGFzcyxcclxuICAgICAgICAgIHBrZ1RvSW1wb3J0XHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAoZXR5cGUpIHtcclxuICAgICAgICAgIGZlYXR1cmVUeXBlR2V0dGVyID0gYCR7cGtnUmVmfS4ke0RVLmdlbkVjbGFzc0dldHRlck5hbWUoZXR5cGUpfSgpYDtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbGV0IGVjb3JlUGtnR2V0dGVyID0gJ3RoaXMuZ2V0RWNvcmVQYWNrYWdlKCknO1xyXG4gICAgICAgIGlmIChwa2cuZ2V0TmFtZSgpLnRvTG93ZXJDYXNlKCkgPT09ICdlY29yZScpIGVjb3JlUGtnR2V0dGVyID0gJ3RoaXMnO1xyXG4gICAgICAgIGZlYXR1cmVUeXBlR2V0dGVyID0gZWNvcmVQa2dHZXR0ZXIgKyAnLmdldCcgKyBldHlwZS5nZXROYW1lKCkgKyAnKCknO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmVhdHVyZVR5cGVHZXR0ZXI7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbmVyYXRlSW1wb3J0cyhwa2dUb0ltcG9ydDogU2V0PEVQYWNrYWdlPiwgcGtnOiBFUGFja2FnZSkge1xyXG5cclxuICAgIC8vYnVpbGQgcGF0aCB0byByb290IHBhY2thZ2UgaW5pdGlhbGl6ZXJcclxuICAgIGNvbnN0IHBhdGhUb1Jvb3QgPSBEVS5nZXRQYXRoVG9Sb290KHBrZyk7XHJcblxyXG4gICAgbGV0IGltcG9ydHMgPSBgJHtEVS5nZW5lcmF0ZUltcG9ydFN0YXRlbWVudHNGb3JFeHRlcm5hbFBhY2thZ2VzKHBrZ1RvSW1wb3J0LCBwa2csICcuLycpfVxyXG5pbXBvcnQgeyBFQ2xhc3MgfSBmcm9tICdAdHJpcHNuZWsvdG1mJztcclxuaW1wb3J0IHsgRUVudW0gfSBmcm9tICdAdHJpcHNuZWsvdG1mJztcclxuaW1wb3J0IHsgUGFja2FnZVJlZ2lzdHJ5IH0gZnJvbSAnJHtwYXRoVG9Sb290fXBhY2thZ2UtcmVnaXN0cnkuanMnO1xyXG5pbXBvcnQgeyBFUGFja2FnZUltcGwgfSBmcm9tICdAdHJpcHNuZWsvdG1mJztcclxuaW1wb3J0IHsgRUF0dHJpYnV0ZSB9IGZyb20gJ0B0cmlwc25lay90bWYnO1xyXG5pbXBvcnQgeyBFRmFjdG9yeSB9IGZyb20gJ0B0cmlwc25lay90bWYnO1xyXG5pbXBvcnQgeyBFUmVmZXJlbmNlIH0gZnJvbSAnQHRyaXBzbmVrL3RtZic7XHJcbmltcG9ydCB7IEVPcGVyYXRpb24gfSBmcm9tICdAdHJpcHNuZWsvdG1mJztgO1xyXG5cclxuICAgIC8vd2UgdXNlIHJlbGF0aXZlIGltcG9ydHMgZm9yIHRoZSBFY29yZVBhY2thZ2UsIHNpbmNlIGl0IGlzIGluIHRoZSBzYW1lIGxpYiBhcyB0aGUgbWV0YW1vZGVsXHJcbiAgICBpZiAocGtnLmdldE5hbWUoKS50b0xvd2VyQ2FzZSgpID09PSAnZWNvcmUnKSB7XHJcbiAgICAgIGltcG9ydHMgPSBgJHtEVS5nZW5lcmF0ZUltcG9ydFN0YXRlbWVudHNGb3JFeHRlcm5hbFBhY2thZ2VzKHBrZ1RvSW1wb3J0LCBwa2csICcnKX1cclxuaW1wb3J0IHsgRVBhY2thZ2UgfSBmcm9tICcuL2VwYWNrYWdlLmpzJztcclxuaW1wb3J0IHsgRURhdGFUeXBlIH0gZnJvbSAnLi9lZGF0YS10eXBlLmpzJztcclxuaW1wb3J0IHsgRUNsYXNzIH0gZnJvbSAnLi9lY2xhc3MuanMnO1xyXG5pbXBvcnQgeyBFUmVmZXJlbmNlIH0gZnJvbSAnLi9lcmVmZXJlbmNlLmpzJztcclxuaW1wb3J0IHsgRUF0dHJpYnV0ZSB9IGZyb20gJy4vZWF0dHJpYnV0ZS5qcyc7XHJcbmltcG9ydCB7IEVGYWN0b3J5IH0gZnJvbSAnLi9lZmFjdG9yeS5qcyc7YDtcclxuICAgIH1cclxuICAgIHJldHVybiBpbXBvcnRzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU29ydCBlY2xhc3NpZmllcnMgaW4gc3VjaCBhIHdheSB0aGF0IGJhc2UgdHlwZXMgYXJlIGd1YXJhbnRlZWQgdG8gcHJlY2VkZSBkZXJpdmVkIHR5cGVzIHNvXHJcbiAgICogdGhhdCB3ZSBjYW4gcmVmZXJlbmNlIGZlYXR1cmUgSURzIGluIGNvcnJlY3Qgb3JkZXJcclxuICAgKi9cclxuICBwcml2YXRlIHNvcnRDbGFzc2lmaWVyc1dpdGhCYXNlVHlwZXNGaXJzdChwa2c6IEVQYWNrYWdlKSB7XHJcbiAgICBjb25zdCBzb3J0ZWRDbGFzc2lmaWVycyA9IG5ldyBBcnJheTxFQ2xhc3NpZmllcj4oKTtcclxuICAgIGZvciAoY29uc3QgZWNsYXNzaWZpZXIgb2YgcGtnLmdldEVDbGFzc2lmaWVycygpKSB7XHJcbiAgICAgIGlmIChlY2xhc3NpZmllciBpbnN0YW5jZW9mIEVDbGFzc0ltcGwpIHtcclxuICAgICAgICBjb25zdCBlY2xhc3MgPSA8RUNsYXNzPmVjbGFzc2lmaWVyO1xyXG4gICAgICAgIGlmIChzb3J0ZWRDbGFzc2lmaWVycy5pbmRleE9mKGVjbGFzcykgPT09IC0xKSB7XHJcbiAgICAgICAgICAvL2luc2VydCBlY2xhc3MgYWZ0ZXIgaXQncyBsYXN0IHN1cGVyIHR5cGVcclxuICAgICAgICAgIGxldCBpZHhMYXN0U3VwZXJUeXBlID0gLTE7XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IHN0IG9mIGVjbGFzcy5nZXRFQWxsU3VwZXJUeXBlcygpKSB7XHJcbiAgICAgICAgICAgIGlmIChzb3J0ZWRDbGFzc2lmaWVycy5pbmRleE9mKHN0KSA+IC0xKSB7XHJcbiAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzb3J0ZWRDbGFzc2lmaWVycy5pbmRleE9mKHN0KTtcclxuICAgICAgICAgICAgICBpZiAoaW5kZXggPiBpZHhMYXN0U3VwZXJUeXBlKSBpZHhMYXN0U3VwZXJUeXBlID0gaW5kZXg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChpZHhMYXN0U3VwZXJUeXBlID49IDApXHJcbiAgICAgICAgICAgIHNvcnRlZENsYXNzaWZpZXJzLnNwbGljZShpZHhMYXN0U3VwZXJUeXBlICsgMSwgMCwgZWNsYXNzKTtcclxuICAgICAgICAgIGVsc2Ugc29ydGVkQ2xhc3NpZmllcnMuc3BsaWNlKDAsIDAsIGVjbGFzcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvL2VudW1zIGFuZCBvdGhlciBFQ2xhc3NpZmllcnMgY2FuIGdvIHdoZXJldmVyXHJcbiAgICAgIGVsc2Uge1xyXG4gICAgICAgIHNvcnRlZENsYXNzaWZpZXJzLnB1c2goZWNsYXNzaWZpZXIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gc29ydGVkQ2xhc3NpZmllcnM7XHJcbiAgfVxyXG59Il19