UNPKG

@tripsnek/tmf

Version:

TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)

409 lines 53.8 kB
import { TUtils } from '../tutils.js';
import { EcorePackage } from '../metamodel/ecorepackage.js';
import { EAttributeImpl } from '../metamodel/impl/eattribute-impl.js';
import { EEnumImpl } from '../metamodel/impl/eenum-impl.js';
/**
 * Utility methods used for TMF source code generation, including
 * EPackage/EFactory specializations and individual EClassifier files.
 */
export class TGenUtils {
    //paths to which files are written
    static API_PATH = '/api';
    static GEN_PATH = '/gen';
    static IMPL_PATH = '/impl';
    //imports needed by every api/gen/impl of every EClass
    static DEFAULT_IMPORTS = `import { EObject } from '@tripsnek/tmf';
import { TUtils } from '@tripsnek/tmf';
import { EStructuralFeature } from '@tripsnek/tmf';
import { BasicEList } from '@tripsnek/tmf';
import { EClass } from '@tripsnek/tmf';
import { EList } from '@tripsnek/tmf';
import { EEnum } from '@tripsnek/tmf';
import { EDataType } from '@tripsnek/tmf';
import { EObjectImpl } from '@tripsnek/tmf';`;
    static ECORE_DEFAULT_IMPORTS = `import { EObjectImpl } from '../impl/e-object.js';
      import { EStructuralFeature } from '../api/e-structural-feature.js';
      import { BasicEList } from '../common/basic-e-list.js';
      import { EList } from '../common/e-list.js';
      `;
    /**
     * Generates statements for importing a set of packages into a file residing
     * in the directory of the host package.
     * @param pkgToImport
     * @param host
     */
    static generateImportStatementsForExternalPackages(pkgToImport, host, prefix) {
        let pkgImports = '';
        for (const pkgDependency of pkgToImport) {
            //if we need to support importing EcorePackage, need to resolve it's path specially (or use an alias)
            if (pkgDependency !== EcorePackage.eINSTANCE) {
                if (pkgDependency) {
                    const pkgName = TGenUtils.genPackageClassName(pkgDependency);
                    //for nested package structures (allowable from Ecore)
                    let pkgPath = this.getPathToOtherPackage(host, pkgDependency);
                    //for packages defined as 'x-data' folders in lib without nesting
                    // if (!host.getESuperPackage())
                    //   pkgPath = this.getPathToOtherPackageFlat(host, pkgDependency);
                    // if packages share a root, use relative imports
                    if (host.getRootPackage() === pkgDependency.getRootPackage()) {
                        pkgImports += `import { ${pkgName}} from '${prefix}${pkgPath}${this.kebabLowerCase(pkgDependency.getName())}-package.js';`;
                    }
                    else {
                        console.log('WARNING: CROSS-PACKAGE IMPORTS NOT SUPPORTED');
                    }
                }
            }
        }
        return pkgImports;
    }
    /**
     * Generates import statements for the API .ts files for a set of EClassifiers.
     * @param imports
     */
    static genApiImports(eclass, toImport, pathToApiDir) {
        let imports = ``;
        //add necessary imports for e.g. EOperations, cross-references and super types
        for (const ec of toImport) {
            if (ec) {
                let genPathToImport = `${pathToApiDir}/${this.genClassApiName(ec)}`;
                //construct path to the type, which may reside in another package
                if (ec.getEPackage() !== eclass.getEPackage()) {
                    //if both eclasses are from the same root package, then we use relative paths
                    if (ec.getRootPackage() === eclass.getRootPackage()) {
                        //traverse from here up to root
                        let pathToImport = TGenUtils.getPathToTypeInOtherPkg(eclass, ec);
                        // pathToImport += 'api/' + ec.getName();
                        pathToImport += `api/${this.genClassApiName(ec)}`;
                        genPathToImport = pathToImport;
                    }
                    // Otherwise, Alternate path-based import from another library
                    else {
                        console.log('WARNING: CROSS-PACKAGE IMPORTS NOT SUPPORTED');
                    }
                    // console.log(
                    //   eclass.getEPackage().getName() + ' to ' + ec.getEPackage().getName() + ' ' + genPathToImport
                    // );
                }
                imports += `import { ${ec.getName()} } from '${genPathToImport}.js';\n`;
            }
        }
        return imports;
    }
    /**
     * Method signature for an EOperation.
     * @param eop
     */
    static eopSignature(eop) {
        let signature = `${eop.getName()}(`;
        //determine return type
        const returnType = TGenUtils.eopReturnType(eop);
        //add parameters
        let paramInd = 0;
        for (const param of eop.getEParameters()) {
            if (param.getEType()) {
                if (paramInd > 0)
                    signature += ', ';
                let paramType = TUtils.getTypescriptName(param.getEType());
                if (param.isMany()) {
                    paramType = `EList<${paramType}>`;
                }
                const paramName = param.getName() + (param.isOptional() ? '?' : '');
                signature += `${paramName}: ${paramType}`;
                paramInd++;
            }
        }
        return `${signature}): ${returnType}`;
    }
    static eopReturnType(eop) {
        let returnType = eop.getEType()
            ? TUtils.getTypescriptName(eop.getEType())
            : 'void';
        //handle lists
        if (eop.isMany()) {
            returnType = `EList<${returnType}>`;
        }
        return returnType;
    }
    /**
     * Invocation of an EOperation.
     *
     * @param eop
     */
    static eopInvocation(eop) {
        let signature = `${eop.getName()}(`;
        //add parameters
        let paramInd = 0;
        for (const param of eop.getEParameters()) {
            if (paramInd > 0)
                signature += ',';
            signature += `${param.getName()}`;
            paramInd++;
        }
        return `${signature})`;
    }
    static genGenClassName(eclass) {
        return eclass.getName() + 'Gen';
    }
    static genImplClassName(eclass) {
        return eclass.getName() + 'Impl';
    }
    /**
     * Method name for feature setter.
     * @param f
     */
    static setterName(f) {
        return 'set' + TGenUtils.capitalize(f.getName());
    }
    static basicSetterName(f) {
        return `basic${TGenUtils.capitalize(TGenUtils.setterSig(f))}`;
    }
    /**
     * Method name for feature getter.
     * @param f
     */
    static getterName(f) {
        return ((f.getEType()?.getName() === 'EBoolean' ? 'is' : 'get') +
            TGenUtils.capitalize(f.getName()));
    }
    /**
     * Method signature for feature setter.
     * @param f
     */
    static setterSig(f) {
        return `${TGenUtils.setterName(f)}(${TGenUtils.setterParamName(f)}: ${TGenUtils.getTypeName(f)}): void`;
    }
    /**
     * Method signature for feature basic setter.
     * @param f
     */
    static basicSetterSig(f) {
        return `${TGenUtils.basicSetterName(f)}(${TGenUtils.setterParamName(f)}: ${TGenUtils.getTypeName(f)}): void`;
    }
    static setterParamName(f) {
        return `new${TGenUtils.capitalize(f.getName())}`;
    }
    /**
     * Method signature for feature getter.
     * @param f
     */
    static getterSig(f) {
        return `${TGenUtils.getterName(f)}(): ${TGenUtils.getTypeName(f)}`;
    }
    /**
     * Gets the name of the data type for the given feature.
     * @param f
     */
    static getTypeName(f) {
        let typeName = f.getEType()?.getName ? f.getEType()?.getName() : 'any';
        if (f instanceof EAttributeImpl) {
            if (f.getEType() instanceof EEnumImpl) {
                typeName = f.getEType()?.getName();
            }
            else {
                typeName = TUtils.toTypeScriptPrimitive(f.getEType());
            }
        }
        if (f.isMany()) {
            typeName = `EList<${typeName}>`;
        }
        return typeName;
    }
    //======================================================================
    // Basic string manipulation for naming (e.g., casing)
    /**
     * Capitalizes the first letter of the given string.
     * @param s
     */
    static capitalize(s) {
        return !s ? '' : s.charAt(0).toUpperCase() + s.slice(1);
    }
    /**
     * First letter to lower case.
     * @param s
     */
    static uncapitalize(s) {
        return !s ? '' : s.charAt(0).toLowerCase() + s.slice(1);
    }
    /**
     * Converts the string to snake case (with underscores preceding
     * upper letters), and then to all upper case.
     *
     * @param str
     */
    static snakeUpperCase(str) {
        let converted = str
            .replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
            .toUpperCase();
        if (converted.startsWith('_')) {
            converted = converted.substring(1);
        }
        return converted;
    }
    /**
     * Converts the string to kebab case (with dashes preceding
     * upper letters), and then to all lower case.
     *
     * @param str
     */
    static kebabLowerCase(str) {
        let converted = str
            .replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)
            .toLowerCase();
        if (converted.startsWith('-')) {
            converted = converted.substring(1);
        }
        return converted;
    }
    //======================================================================
    // Generate specific package, class, and/or field -associated names
    /**
     * Generates camel-case class name from original '-'separated package name
     * with some optional suffix (like 'Factory' or 'Package') tacked on.
     * @param pkg
     * @param suffix
     */
    static genPkgClassName(pkg, suffix) {
        if (!pkg)
            return 'ErrorNoSuchPackage' + suffix;
        const pkgNameParts = pkg.getName().split('-').map(this.capitalize);
        pkgNameParts.push(suffix);
        return pkgNameParts.join('');
    }
    static genPackageClassName(pkg) {
        return this.genPkgClassName(pkg, 'Package');
    }
    static genPackageFileName(pkg) {
        return this.kebabLowerCase(pkg.getName()) + '-package';
    }
    static genUtilsFileName(pkg) {
        return this.kebabLowerCase(pkg.getName()) + '-utils';
    }
    static genFactoryClassName(pkg) {
        return this.genPkgClassName(pkg, 'Factory');
    }
    static genFactoryFileName(pkg) {
        return this.kebabLowerCase(pkg.getName()) + '-factory';
    }
    static genClassApiName(eClass, async) {
        return this.kebabLowerCase(eClass.getName()) + (async ? '-async' : '');
    }
    static genClassGenName(eClass, async) {
        return (this.kebabLowerCase(eClass.getName()) + '-gen' + (async ? '-async' : ''));
    }
    static genClassImplName(eClass) {
        return this.kebabLowerCase(eClass.getName()) + '-impl';
    }
    static genClassIdFieldName(eclassifier) {
        return this.snakeUpperCase(eclassifier.getName());
    }
    static genFeatureIdFieldName(feature) {
        return (this.snakeUpperCase(feature.getEContainingClass().getName()) +
            '__' +
            this.snakeUpperCase(feature.getName()));
    }
    static genOperationIdFieldName(feature) {
        return (this.snakeUpperCase(feature.getEContainingClass().getName()) +
            '__' +
            this.snakeUpperCase(feature.getName()));
    }
    static genFeatureCountFieldName(eclass) {
        return this.snakeUpperCase(eclass.getName()) + '_FEATURE_COUNT';
    }
    static genFeatureGetterName(feature) {
        const className = feature.getEContainingClass().getName();
        const featureName = this.capitalize(feature.getName());
        return `get${className}_${featureName}`;
    }
    static genOperationGetterName(feature) {
        const className = feature.getEContainingClass().getName();
        const featureName = this.capitalize(feature.getName());
        return `get${className}_${featureName}`;
    }
    static genEdataTypeGetter(feature) {
        return `EcorePackage.eINSTANCE.get${this.capitalize(feature.getName())}()`;
    }
    static genEclassGetterName(eclassifier) {
        const getter = 'get' + this.capitalize(eclassifier.getName());
        return getter;
    }
    //======================================================================
    /**
     * Generates reference to the package instance for the 'to' EClass, and
     * registers it as a package to import if it is different from that
     * of the 'from' EClass.
     *
     * @param to
     * @param from
     * @param pkgToImport
     */
    static getReferenceToPackageInstance(to, from, pkgToImport) {
        let pkgRef = 'this';
        //handle inheritance from objects in other packages
        if (to.getEPackage() !== from.getEPackage()) {
            pkgToImport.add(to.getEPackage());
            pkgRef = TGenUtils.genPackageClassName(to.getEPackage()) + '.eINSTANCE';
        }
        return pkgRef;
    }
    static getPathToRoot(pkg) {
        let pathToRoot = './';
        if (pkg.getESuperPackage()) {
            let cursor = pkg;
            pathToRoot = '';
            while (cursor.getESuperPackage()) {
                pathToRoot += '../';
                cursor = cursor.getESuperPackage();
            }
        }
        return pathToRoot;
    }
    //======================================================================
    // File/path related methods (TODO: Should use imported PATH library???)
    /**
     * Computes the import path necessary to resolve an EClass in a different
     * package.
     * @param fromClass
     * @param toClass
     */
    static getPathToTypeInOtherPkg(fromClass, toClass) {
        //TODO: If cross-package references are not being correctly computed, it
        //may be because eclass.setEPackage is not being called during Ecore parsing.
        //Correct fix would be for this to be set as part of a proper inverse
        //reference with EPackage.eclassifiers
        const fromPackage = fromClass.getEPackage();
        const toPackage = toClass.getEPackage();
        //for nested package structures (allowable from Ecore)
        if (fromPackage.getESuperPackage())
            return '../' + this.getPathToOtherPackage(fromPackage, toPackage);
        //for packages defined as 'x-data' folders in lib without nesting
        return '../' + this.getPathToOtherPackageFlat(fromPackage, toPackage);
    }
    static getPathToOtherPackageFlat(fromPackage, toPackage) {
        const pkgName = toPackage ? toPackage.getName() : 'PackageNotFound';
        console.log('WARNING: CROSS-PACKAGE IMPORTS NOT SUPPORTED');
        return `'${this.kebabLowerCase(pkgName)}'`;
    }
    static getPathToOtherPackage(fromPackage, toPackage) {
        let pathToImport = '';
        let cursor = fromPackage;
        while (cursor.getESuperPackage()) {
            pathToImport += '../';
            cursor = cursor.getESuperPackage();
        }
        //and back down to the element to be imported
        const pathDown = new Array();
        cursor = toPackage;
        while (cursor.getESuperPackage()) {
            pathDown.unshift(cursor);
            cursor = cursor.getESuperPackage();
        }
        for (const pathPkg of pathDown) {
            pathToImport += pathPkg.getName() + '/';
        }
        return pathToImport;
    }
    static inSameLib(eclass1, eclass2) {
        return eclass1.getRootPackage() === eclass2.getRootPackage();
    }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGdlbi11dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvc291cmNlLWdlbmVyYXRvcnMvdGdlbi11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUU1RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDdEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRTVEOzs7R0FHRztBQUNILE1BQU0sT0FBTyxTQUFTO0lBQ3BCLGtDQUFrQztJQUNsQyxNQUFNLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztJQUN6QixNQUFNLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztJQUN6QixNQUFNLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQztJQUUzQixzREFBc0Q7SUFDdEQsTUFBTSxDQUFDLGVBQWUsR0FBRzs7Ozs7Ozs7NkNBUWtCLENBQUM7SUFFNUMsTUFBTSxDQUFDLHFCQUFxQixHQUFHOzs7O09BSTFCLENBQUM7SUFFTjs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQywyQ0FBMkMsQ0FDdkQsV0FBMEIsRUFDMUIsSUFBYyxFQUNkLE1BQWM7UUFFZCxJQUFJLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDcEIsS0FBSyxNQUFNLGFBQWEsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUN4QyxxR0FBcUc7WUFDckcsSUFBSSxhQUFhLEtBQUssWUFBWSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUM3QyxJQUFJLGFBQWEsRUFBRSxDQUFDO29CQUNsQixNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsbUJBQW1CLENBQUMsYUFBYSxDQUFDLENBQUM7b0JBRTdELHNEQUFzRDtvQkFDdEQsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixD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LE1BQU0sR0FBRyxTQUFTLENBQUM7UUFDbkIsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDO1lBQ2pDLFFBQVEsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDekIsTUFBTSxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JDLENBQUM7UUFDRCxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQy9CLFlBQVksSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsR0FBRyxDQUFDO1FBQzFDLENBQUM7UUFDRCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0lBRU0sTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFlLEVBQUUsT0FBZTtRQUN0RCxPQUFPLE9BQU8sQ0FBQyxjQUFjLEVBQUUsS0FBSyxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDL0QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVQYWNrYWdlIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lcGFja2FnZS5qcyc7XHJcbmltcG9ydCB7IEVDbGFzcyB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZWNsYXNzLmpzJztcclxuaW1wb3J0IHsgRUNsYXNzaWZpZXIgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VjbGFzc2lmaWVyLmpzJztcclxuaW1wb3J0IHsgRVN0cnVjdHVyYWxGZWF0dXJlIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lc3RydWN0dXJhbC1mZWF0dXJlLmpzJztcclxuaW1wb3J0IHsgRU9wZXJhdGlvbiB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZW9wZXJhdGlvbi5qcyc7XHJcbmltcG9ydCB7IFRVdGlscyB9IGZyb20gJy4uL3R1dGlscy5qcyc7XHJcbmltcG9ydCB7IEVjb3JlUGFja2FnZSB9IGZyb20gJy4uL21ldGFtb2RlbC9lY29yZXBhY2thZ2UuanMnO1xyXG5pbXBvcnQgeyBFRGF0YVR5cGUgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VkYXRhLXR5cGUuanMnO1xyXG5pbXBvcnQgeyBFQXR0cmlidXRlSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VhdHRyaWJ1dGUtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVFbnVtSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VlbnVtLWltcGwuanMnO1xyXG5cclxuLyoqXHJcbiAqIFV0aWxpdHkgbWV0aG9kcyB1c2VkIGZvciBUTUYgc291cmNlIGNvZGUgZ2VuZXJhdGlvbiwgaW5jbHVkaW5nXHJcbiAqIEVQYWNrYWdlL0VGYWN0b3J5IHNwZWNpYWxpemF0aW9ucyBhbmQgaW5kaXZpZHVhbCBFQ2xhc3NpZmllciBmaWxlcy5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBUR2VuVXRpbHMge1xyXG4gIC8vcGF0aHMgdG8gd2hpY2ggZmlsZXMgYXJlIHdyaXR0ZW5cclxuICBzdGF0aWMgQVBJX1BBVEggPSAnL2FwaSc7XHJcbiAgc3RhdGljIEdFTl9QQVRIID0gJy9nZW4nO1xyXG4gIHN0YXRpYyBJTVBMX1BBVEggPSAnL2ltcGwnO1xyXG5cclxuICAvL2ltcG9ydHMgbmVlZGVkIGJ5IGV2ZXJ5IGFwaS9nZW4vaW1wbCBvZiBldmVyeSBFQ2xhc3NcclxuICBzdGF0aWMgREVGQVVMVF9JTVBPUlRTID0gYGltcG9ydCB7IEVPYmplY3QgfSBmcm9tICdAdHJpcHNuZWsvdG1mJztcclxuaW1wb3J0IHsgVFV0aWxzIH0gZnJvbSAnQHRyaXBzbmVrL3RtZic7XHJcbmltcG9ydCB7IEVTdHJ1Y3R1cmFsRmVhdHVyZSB9IGZyb20gJ0B0cmlwc25lay90bWYnO1xyXG5pbXBvcnQgeyBCYXNpY0VMaXN0IH0gZnJvbSAnQHRyaXBzbmVrL3RtZic7XHJcbmltcG9ydCB7IEVDbGFzcyB9IGZyb20gJ0B0cmlwc25lay90bWYnO1xyXG5pbXBvcnQgeyBFTGlzdCB9IGZyb20gJ0B0cmlwc25lay90bWYnO1xyXG5pbXBvcnQgeyBFRW51bSB9IGZyb20gJ0B0cmlwc25lay90bWYnO1xyXG5pbXBvcnQgeyBFRGF0YVR5cGUgfSBmcm9tICdAdHJpcHNuZWsvdG1mJztcclxuaW1wb3J0IHsgRU9iamVjdEltcGwgfSBmcm9tICdAdHJpcHNuZWsvdG1mJztgO1xyXG5cclxuICBzdGF0aWMgRUNPUkVfREVGQVVMVF9JTVBPUlRTID0gYGltcG9ydCB7IEVPYmplY3RJbXBsIH0gZnJvbSAnLi4vaW1wbC9lLW9iamVjdC5qcyc7XHJcbiAgICAgIGltcG9ydCB7IEVTdHJ1Y3R1cmFsRmVhdHVyZSB9IGZyb20gJy4uL2FwaS9lLXN0cnVjdHVyYWwtZmVhdHVyZS5qcyc7XHJcbiAgICAgIGltcG9ydCB7IEJhc2ljRUxpc3QgfSBmcm9tICcuLi9jb21tb24vYmFzaWMtZS1saXN0LmpzJztcclxuICAgICAgaW1wb3J0IHsgRUxpc3QgfSBmcm9tICcuLi9jb21tb24vZS1saXN0LmpzJztcclxuICAgICAgYDtcclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIHN0YXRlbWVudHMgZm9yIGltcG9ydGluZyBhIHNldCBvZiBwYWNrYWdlcyBpbnRvIGEgZmlsZSByZXNpZGluZ1xyXG4gICAqIGluIHRoZSBkaXJlY3Rvcnkgb2YgdGhlIGhvc3QgcGFja2FnZS5cclxuICAgKiBAcGFyYW0gcGtnVG9JbXBvcnRcclxuICAgKiBAcGFyYW0gaG9zdFxyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0aWMgZ2VuZXJhdGVJbXBvcnRTdGF0ZW1lbnRzRm9yRXh0ZXJuYWxQYWNrYWdlcyhcclxuICAgIHBrZ1RvSW1wb3J0OiBTZXQ8RVBhY2thZ2U+LFxyXG4gICAgaG9zdDogRVBhY2thZ2UsXHJcbiAgICBwcmVmaXg6IHN0cmluZ1xyXG4gICkge1xyXG4gICAgbGV0IHBrZ0ltcG9ydHMgPSAnJztcclxuICAgIGZvciAoY29uc3QgcGtnRGVwZW5kZW5jeSBvZiBwa2dUb0ltcG9ydCkge1xyXG4gICAgICAvL2lmIHdlIG5lZWQgdG8gc3VwcG9ydCBpbXBvcnRpbmcgRWNvcmVQYWNrYWdlLCBuZWVkIHRvIHJlc29sdmUgaXQncyBwYXRoIHNwZWNpYWxseSAob3IgdXNlIGFuIGFsaWFzKVxyXG4gICAgICBpZiAocGtnRGVwZW5kZW5jeSAhPT0gRWNvcmVQYWNrYWdlLmVJTlNUQU5DRSkge1xyXG4gICAgICAgIGlmIChwa2dEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgICBjb25zdCBwa2dOYW1lID0gVEdlblV0aWxzLmdlblBhY2thZ2VDbGFzc05hbWUocGtnRGVwZW5kZW5jeSk7XHJcblxyXG4gICAgICAgICAgLy9mb3IgbmVzdGVkIHBhY2thZ2Ugc3RydWN0dXJlcyAoYWxsb3dhYmxlIGZyb20gRWNvcmUpXHJcbiAgICAgICAgICBsZXQgcGtnUGF0aCA9IHRoaXMuZ2V0UGF0aFRvT3RoZXJQYWNrYWdlKGhvc3QsIHBrZ0RlcGVuZGVuY3kpO1xyXG5cclxuICAgICAgICAgIC8vZm9yIHBhY2thZ2VzIGRlZmluZWQgYXMgJ3gtZGF0YScgZm9sZGVycyBpbiBsaWIgd2l0aG91dCBuZXN0aW5nXHJcbiAgICAgICAgICAvLyBpZiAoIWhvc3QuZ2V0RVN1cGVyUGFja2FnZSgpKVxyXG4gICAgICAgICAgLy8gICBwa2dQYXRoID0gdGhpcy5nZXRQYXRoVG9PdGhlclBhY2thZ2VGbGF0KGhvc3QsIHBrZ0RlcGVuZGVuY3kpO1xyXG5cclxuICAgICAgICAgIC8vIGlmIHBhY2thZ2VzIHNoYXJlIGEgcm9vdCwgdXNlIHJlbGF0aXZlIGltcG9ydHNcclxuICAgICAgICAgIGlmIChob3N0LmdldFJvb3RQYWNrYWdlKCkgPT09IHBrZ0RlcGVuZGVuY3kuZ2V0Um9vdFBhY2thZ2UoKSkge1xyXG4gICAgICAgICAgICBwa2dJbXBvcnRzICs9IGBpbXBvcnQgeyAke3BrZ05hbWUgfX0gZnJvbSAnJHtwcmVmaXh9JHtwa2dQYXRofSR7dGhpcy5rZWJhYkxvd2VyQ2FzZShwa2dEZXBlbmRlbmN5LmdldE5hbWUoKSl9LXBhY2thZ2UuanMnO2A7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZygnV0FSTklORzogQ1JPU1MtUEFDS0FHRSBJTVBPUlRTIE5PVCBTVVBQT1JURUQnKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBwa2dJbXBvcnRzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIGltcG9ydCBzdGF0ZW1lbnRzIGZvciB0aGUgQVBJIC50cyBmaWxlcyBmb3IgYSBzZXQgb2YgRUNsYXNzaWZpZXJzLlxyXG4gICAqIEBwYXJhbSBpbXBvcnRzXHJcbiAgICovXHJcbiAgc3RhdGljIGdlbkFwaUltcG9ydHMoXHJcbiAgICBlY2xhc3M6IEVDbGFzcyxcclxuICAgIHRvSW1wb3J0OiBTZXQ8RUNsYXNzaWZpZXI+LFxyXG4gICAgcGF0aFRvQXBpRGlyOiBzdHJpbmdcclxuICApOiBzdHJpbmcge1xyXG4gICAgbGV0IGltcG9ydHMgPSBgYDtcclxuICAgIC8vYWRkIG5lY2Vzc2FyeSBpbXBvcnRzIGZvciBlLmcuIEVPcGVyYXRpb25zLCBjcm9zcy1yZWZlcmVuY2VzIGFuZCBzdXBlciB0eXBlc1xyXG4gICAgZm9yIChjb25zdCBlYyBvZiB0b0ltcG9ydCkge1xyXG4gICAgICBpZiAoZWMpIHtcclxuICAgICAgICBsZXQgZ2VuUGF0aFRvSW1wb3J0ID0gYCR7cGF0aFRvQXBpRGlyfS8ke3RoaXMuZ2VuQ2xhc3NBcGlOYW1lKGVjKX1gO1xyXG5cclxuICAgICAgICAvL2NvbnN0cnVjdCBwYXRoIHRvIHRoZSB0eXBlLCB3aGljaCBtYXkgcmVzaWRlIGluIGFub3RoZXIgcGFja2FnZVxyXG4gICAgICAgIGlmIChlYy5nZXRFUGFja2FnZSgpICE9PSBlY2xhc3MuZ2V0RVBhY2thZ2UoKSkge1xyXG4gICAgICAgICAgLy9pZiBib3RoIGVjbGFzc2VzIGFyZSBmcm9tIHRoZSBzYW1lIHJvb3QgcGFja2FnZSwgdGhlbiB3ZSB1c2UgcmVsYXRpdmUgcGF0aHNcclxuICAgICAgICAgIGlmIChlYy5nZXRSb290UGFja2FnZSgpID09PSBlY2xhc3MuZ2V0Um9vdFBhY2thZ2UoKSkge1xyXG4gICAgICAgICAgICAvL3RyYXZlcnNlIGZyb20gaGVyZSB1cCB0byByb290XHJcbiAgICAgICAgICAgIGxldCBwYXRoVG9JbXBvcnQgPSBUR2VuVXRpbHMuZ2V0UGF0aFRvVHlwZUluT3RoZXJQa2coZWNsYXNzLCBlYyk7XHJcbiAgICAgICAgICAgIC8vIHBhdGhUb0ltcG9ydCArPSAnYXBpLycgKyBlYy5nZXROYW1lKCk7XHJcbiAgICAgICAgICAgIHBhdGhUb0ltcG9ydCArPSBgYXBpLyR7dGhpcy5nZW5DbGFzc0FwaU5hbWUoZWMpfWA7XHJcbiAgICAgICAgICAgIGdlblBhdGhUb0ltcG9ydCA9IHBhdGhUb0ltcG9ydDtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQWx0ZXJuYXRlIHBhdGgtYmFzZWQgaW1wb3J0IGZyb20gYW5vdGhlciBsaWJyYXJ5XHJcbiAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coJ1dBUk5JTkc6IENST1NTLVBBQ0tBR0UgSU1QT1JUUyBOT1QgU1VQUE9SVEVEJyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcclxuICAgICAgICAgIC8vICAgZWNsYXNzLmdldEVQYWNrYWdlKCkuZ2V0TmFtZSgpICsgJyB0byAnICsgZWMuZ2V0RVBhY2thZ2UoKS5nZXROYW1lKCkgKyAnICcgKyBnZW5QYXRoVG9JbXBvcnRcclxuICAgICAgICAgIC8vICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpbXBvcnRzICs9IGBpbXBvcnQgeyAke2VjLmdldE5hbWUoKX0gfSBmcm9tICcke2dlblBhdGhUb0ltcG9ydH0uanMnO1xcbmA7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gaW1wb3J0cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ldGhvZCBzaWduYXR1cmUgZm9yIGFuIEVPcGVyYXRpb24uXHJcbiAgICogQHBhcmFtIGVvcFxyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0aWMgZW9wU2lnbmF0dXJlKGVvcDogRU9wZXJhdGlvbik6IHN0cmluZyB7XHJcbiAgICBsZXQgc2lnbmF0dXJlID0gYCR7ZW9wLmdldE5hbWUoKX0oYDtcclxuXHJcbiAgICAvL2RldGVybWluZSByZXR1cm4gdHlwZVxyXG4gICAgY29uc3QgcmV0dXJuVHlwZSA9IFRHZW5VdGlscy5lb3BSZXR1cm5UeXBlKGVvcCk7XHJcblxyXG4gICAgLy9hZGQgcGFyYW1ldGVyc1xyXG4gICAgbGV0IHBhcmFtSW5kID0gMDtcclxuICAgIGZvciAoY29uc3QgcGFyYW0gb2YgZW9wLmdldEVQYXJhbWV0ZXJzKCkpIHtcclxuICAgICAgaWYgKHBhcmFtLmdldEVUeXBlKCkpIHtcclxuICAgICAgICBpZiAocGFyYW1JbmQgPiAwKSBzaWduYXR1cmUgKz0gJywgJztcclxuICAgICAgICBsZXQgcGFyYW1UeXBlID0gVFV0aWxzLmdldFR5cGVzY3JpcHROYW1lKHBhcmFtLmdldEVUeXBlKCkhKTtcclxuICAgICAgICBpZiAocGFyYW0uaXNNYW55KCkpIHtcclxuICAgICAgICAgIHBhcmFtVHlwZSA9IGBFTGlzdDwke3BhcmFtVHlwZX0+YDtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgcGFyYW1OYW1lID0gcGFyYW0uZ2V0TmFtZSgpICsgKHBhcmFtLmlzT3B0aW9uYWwoKSA/ICc/JyA6ICcnKTtcclxuICAgICAgICBzaWduYXR1cmUgKz0gYCR7cGFyYW1OYW1lfTogJHtwYXJhbVR5cGV9YDtcclxuICAgICAgICBwYXJhbUluZCsrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYCR7c2lnbmF0dXJlfSk6ICR7cmV0dXJuVHlwZX1gO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBlb3BSZXR1cm5UeXBlKGVvcDogRU9wZXJhdGlvbikge1xyXG4gICAgbGV0IHJldHVyblR5cGUgPSBlb3AuZ2V0RVR5cGUoKVxyXG4gICAgICA/IFRVdGlscy5nZXRUeXBlc2NyaXB0TmFtZShlb3AuZ2V0RVR5cGUoKSEpXHJcbiAgICAgIDogJ3ZvaWQnO1xyXG5cclxuICAgIC8vaGFuZGxlIGxpc3RzXHJcbiAgICBpZiAoZW9wLmlzTWFueSgpKSB7XHJcbiAgICAgIHJldHVyblR5cGUgPSBgRUxpc3Q8JHtyZXR1cm5UeXBlfT5gO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJldHVyblR5cGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbnZvY2F0aW9uIG9mIGFuIEVPcGVyYXRpb24uXHJcbiAgICpcclxuICAgKiBAcGFyYW0gZW9wXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXRpYyBlb3BJbnZvY2F0aW9uKGVvcDogRU9wZXJhdGlvbik6IHN0cmluZyB7XHJcbiAgICBsZXQgc2lnbmF0dXJlID0gYCR7ZW9wLmdldE5hbWUoKX0oYDtcclxuICAgIC8vYWRkIHBhcmFtZXRlcnNcclxuICAgIGxldCBwYXJhbUluZCA9IDA7XHJcbiAgICBmb3IgKGNvbnN0IHBhcmFtIG9mIGVvcC5nZXRFUGFyYW1ldGVycygpKSB7XHJcbiAgICAgIGlmIChwYXJhbUluZCA+IDApIHNpZ25hdHVyZSArPSAnLCc7XHJcbiAgICAgIHNpZ25hdHVyZSArPSBgJHtwYXJhbS5nZXROYW1lKCl9YDtcclxuICAgICAgcGFyYW1JbmQrKztcclxuICAgIH1cclxuICAgIHJldHVybiBgJHtzaWduYXR1cmV9KWA7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkdlbkNsYXNzTmFtZShlY2xhc3M6IEVDbGFzcykge1xyXG4gICAgcmV0dXJuIGVjbGFzcy5nZXROYW1lKCkgKyAnR2VuJztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2VuSW1wbENsYXNzTmFtZShlY2xhc3M6IEVDbGFzcykge1xyXG4gICAgcmV0dXJuIGVjbGFzcy5nZXROYW1lKCkgKyAnSW1wbCc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRob2QgbmFtZSBmb3IgZmVhdHVyZSBzZXR0ZXIuXHJcbiAgICogQHBhcmFtIGZcclxuICAgKi9cclxuICBwdWJsaWMgc3RhdGljIHNldHRlck5hbWUoZjogRVN0cnVjdHVyYWxGZWF0dXJlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiAnc2V0JyArIFRHZW5VdGlscy5jYXBpdGFsaXplKGYuZ2V0TmFtZSgpKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgYmFzaWNTZXR0ZXJOYW1lKGY6IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gYGJhc2ljJHtUR2VuVXRpbHMuY2FwaXRhbGl6ZShUR2VuVXRpbHMuc2V0dGVyU2lnKGYpKX1gO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0aG9kIG5hbWUgZm9yIGZlYXR1cmUgZ2V0dGVyLlxyXG4gICAqIEBwYXJhbSBmXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXRpYyBnZXR0ZXJOYW1lKGY6IEVTdHJ1Y3R1cmFsRmVhdHVyZSkge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgKGYuZ2V0RVR5cGUoKT8uZ2V0TmFtZSgpID09PSAnRUJvb2xlYW4nID8gJ2lzJyA6ICdnZXQnKSArXHJcbiAgICAgIFRHZW5VdGlscy5jYXBpdGFsaXplKGYuZ2V0TmFtZSgpKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ldGhvZCBzaWduYXR1cmUgZm9yIGZlYXR1cmUgc2V0dGVyLlxyXG4gICAqIEBwYXJhbSBmXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXRpYyBzZXR0ZXJTaWcoZjogRVN0cnVjdHVyYWxGZWF0dXJlKSB7XHJcbiAgICByZXR1cm4gYCR7VEdlblV0aWxzLnNldHRlck5hbWUoZil9KCR7VEdlblV0aWxzLnNldHRlclBhcmFtTmFtZShcclxuICAgICAgZlxyXG4gICAgKX06ICR7VEdlblV0aWxzLmdldFR5cGVOYW1lKGYpfSk6IHZvaWRgO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0aG9kIHNpZ25hdHVyZSBmb3IgZmVhdHVyZSBiYXNpYyBzZXR0ZXIuXHJcbiAgICogQHBhcmFtIGZcclxuICAgKi9cclxuICBwdWJsaWMgc3RhdGljIGJhc2ljU2V0dGVyU2lnKGY6IEVTdHJ1Y3R1cmFsRmVhdHVyZSkge1xyXG4gICAgcmV0dXJuIGAke1RHZW5VdGlscy5iYXNpY1NldHRlck5hbWUoZil9KCR7VEdlblV0aWxzLnNldHRlclBhcmFtTmFtZShcclxuICAgICAgZlxyXG4gICAgKX06ICR7VEdlblV0aWxzLmdldFR5cGVOYW1lKGYpfSk6IHZvaWRgO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBzZXR0ZXJQYXJhbU5hbWUoZjogRVN0cnVjdHVyYWxGZWF0dXJlKSB7XHJcbiAgICByZXR1cm4gYG5ldyR7VEdlblV0aWxzLmNhcGl0YWxpemUoZi5nZXROYW1lKCkpfWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRob2Qgc2lnbmF0dXJlIGZvciBmZWF0dXJlIGdldHRlci5cclxuICAgKiBAcGFyYW0gZlxyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0dGVyU2lnKGY6IEVTdHJ1Y3R1cmFsRmVhdHVyZSkge1xyXG4gICAgcmV0dXJuIGAke1RHZW5VdGlscy5nZXR0ZXJOYW1lKGYpfSgpOiAke1RHZW5VdGlscy5nZXRUeXBlTmFtZShmKX1gO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgbmFtZSBvZiB0aGUgZGF0YSB0eXBlIGZvciB0aGUgZ2l2ZW4gZmVhdHVyZS5cclxuICAgKiBAcGFyYW0gZlxyXG4gICAqL1xyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0VHlwZU5hbWUoZjogRVN0cnVjdHVyYWxGZWF0dXJlKTogc3RyaW5nIHtcclxuICAgIGxldCB0eXBlTmFtZSA9IGYuZ2V0RVR5cGUoKT8uZ2V0TmFtZSA/IGYuZ2V0RVR5cGUoKT8uZ2V0TmFtZSgpIDogJ2FueSc7XHJcbiAgICBpZiAoZiBpbnN0YW5jZW9mIEVBdHRyaWJ1dGVJbXBsKSB7XHJcbiAgICAgIGlmIChmLmdldEVUeXBlKCkgaW5zdGFuY2VvZiBFRW51bUltcGwpIHtcclxuICAgICAgICB0eXBlTmFtZSA9IGYuZ2V0RVR5cGUoKT8uZ2V0TmFtZSgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHR5cGVOYW1lID0gVFV0aWxzLnRvVHlwZVNjcmlwdFByaW1pdGl2ZShmLmdldEVUeXBlKCkhKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGYuaXNNYW55KCkpIHtcclxuICAgICAgdHlwZU5hbWUgPSBgRUxpc3Q8JHt0eXBlTmFtZX0+YDtcclxuICAgIH1cclxuICAgIHJldHVybiB0eXBlTmFtZSE7XHJcbiAgfVxyXG5cclxuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICAvLyBCYXNpYyBzdHJpbmcgbWFuaXB1bGF0aW9uIGZvciBuYW1pbmcgKGUuZy4sIGNhc2luZylcclxuXHJcbiAgLyoqXHJcbiAgICogQ2FwaXRhbGl6ZXMgdGhlIGZpcnN0IGxldHRlciBvZiB0aGUgZ2l2ZW4gc3RyaW5nLlxyXG4gICAqIEBwYXJhbSBzXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXRpYyBjYXBpdGFsaXplKHM6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gIXMgPyAnJyA6IHMuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzLnNsaWNlKDEpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRmlyc3QgbGV0dGVyIHRvIGxvd2VyIGNhc2UuXHJcbiAgICogQHBhcmFtIHNcclxuICAgKi9cclxuICBwdWJsaWMgc3RhdGljIHVuY2FwaXRhbGl6ZShzOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuICFzID8gJycgOiBzLmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpICsgcy5zbGljZSgxKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnZlcnRzIHRoZSBzdHJpbmcgdG8gc25ha2UgY2FzZSAod2l0aCB1bmRlcnNjb3JlcyBwcmVjZWRpbmdcclxuICAgKiB1cHBlciBsZXR0ZXJzKSwgYW5kIHRoZW4gdG8gYWxsIHVwcGVyIGNhc2UuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gc3RyXHJcbiAgICovXHJcbiAgc3RhdGljIHNuYWtlVXBwZXJDYXNlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGxldCBjb252ZXJ0ZWQgPSBzdHJcclxuICAgICAgLnJlcGxhY2UoL1tBLVpdL2csIChsZXR0ZXIpID0+IGBfJHtsZXR0ZXIudG9Mb3dlckNhc2UoKX1gKVxyXG4gICAgICAudG9VcHBlckNhc2UoKTtcclxuICAgIGlmIChjb252ZXJ0ZWQuc3RhcnRzV2l0aCgnXycpKSB7XHJcbiAgICAgIGNvbnZlcnRlZCA9IGNvbnZlcnRlZC5zdWJzdHJpbmcoMSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY29udmVydGVkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ29udmVydHMgdGhlIHN0cmluZyB0byBrZWJhYiBjYXNlICh3aXRoIGRhc2hlcyBwcmVjZWRpbmdcclxuICAgKiB1cHBlciBsZXR0ZXJzKSwgYW5kIHRoZW4gdG8gYWxsIGxvd2VyIGNhc2UuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gc3RyXHJcbiAgICovXHJcbiAgc3RhdGljIGtlYmFiTG93ZXJDYXNlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGxldCBjb252ZXJ0ZWQgPSBzdHJcclxuICAgICAgLnJlcGxhY2UoL1tBLVpdL2csIChsZXR0ZXIpID0+IGAtJHtsZXR0ZXIudG9Mb3dlckNhc2UoKX1gKVxyXG4gICAgICAudG9Mb3dlckNhc2UoKTtcclxuICAgIGlmIChjb252ZXJ0ZWQuc3RhcnRzV2l0aCgnLScpKSB7XHJcbiAgICAgIGNvbnZlcnRlZCA9IGNvbnZlcnRlZC5zdWJzdHJpbmcoMSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY29udmVydGVkO1xyXG4gIH1cclxuXHJcbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgLy8gR2VuZXJhdGUgc3BlY2lmaWMgcGFja2FnZSwgY2xhc3MsIGFuZC9vciBmaWVsZCAtYXNzb2NpYXRlZCBuYW1lc1xyXG5cclxuICAvKipcclxuICAgKiBHZW5lcmF0ZXMgY2FtZWwtY2FzZSBjbGFzcyBuYW1lIGZyb20gb3JpZ2luYWwgJy0nc2VwYXJhdGVkIHBhY2thZ2UgbmFtZVxyXG4gICAqIHdpdGggc29tZSBvcHRpb25hbCBzdWZmaXggKGxpa2UgJ0ZhY3RvcnknIG9yICdQYWNrYWdlJykgdGFja2VkIG9uLlxyXG4gICAqIEBwYXJhbSBwa2dcclxuICAgKiBAcGFyYW0gc3VmZml4XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzdGF0aWMgZ2VuUGtnQ2xhc3NOYW1lKHBrZzogRVBhY2thZ2UsIHN1ZmZpeDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICghcGtnKSByZXR1cm4gJ0Vycm9yTm9TdWNoUGFja2FnZScgKyBzdWZmaXg7XHJcbiAgICBjb25zdCBwa2dOYW1lUGFydHMgPSBwa2cuZ2V0TmFtZSgpLnNwbGl0KCctJykubWFwKHRoaXMuY2FwaXRhbGl6ZSk7XHJcbiAgICBwa2dOYW1lUGFydHMucHVzaChzdWZmaXgpO1xyXG4gICAgcmV0dXJuIHBrZ05hbWVQYXJ0cy5qb2luKCcnKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2VuUGFja2FnZUNsYXNzTmFtZShwa2c6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmdlblBrZ0NsYXNzTmFtZShwa2csICdQYWNrYWdlJyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlblBhY2thZ2VGaWxlTmFtZShwa2c6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmtlYmFiTG93ZXJDYXNlKHBrZy5nZXROYW1lKCkpICsgJy1wYWNrYWdlJztcclxuICB9XHJcbiAgcHVibGljIHN0YXRpYyBnZW5VdGlsc0ZpbGVOYW1lKHBrZzogRVBhY2thZ2UpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMua2ViYWJMb3dlckNhc2UocGtnLmdldE5hbWUoKSkgKyAnLXV0aWxzJztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2VuRmFjdG9yeUNsYXNzTmFtZShwa2c6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmdlblBrZ0NsYXNzTmFtZShwa2csICdGYWN0b3J5Jyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkZhY3RvcnlGaWxlTmFtZShwa2c6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmtlYmFiTG93ZXJDYXNlKHBrZy5nZXROYW1lKCkpICsgJy1mYWN0b3J5JztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2VuQ2xhc3NBcGlOYW1lKGVDbGFzczogRUNsYXNzaWZpZXIsIGFzeW5jPzogYm9vbGVhbik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5rZWJhYkxvd2VyQ2FzZShlQ2xhc3MuZ2V0TmFtZSgpKSArIChhc3luYyA/ICctYXN5bmMnIDogJycpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBnZW5DbGFzc0dlbk5hbWUoZUNsYXNzOiBFQ2xhc3MsIGFzeW5jPzogYm9vbGVhbik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gKFxyXG4gICAgICB0aGlzLmtlYmFiTG93ZXJDYXNlKGVDbGFzcy5nZXROYW1lKCkpICsgJy1nZW4nICsgKGFzeW5jID8gJy1hc3luYycgOiAnJylcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkNsYXNzSW1wbE5hbWUoZUNsYXNzOiBFQ2xhc3MpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMua2ViYWJMb3dlckNhc2UoZUNsYXNzLmdldE5hbWUoKSkgKyAnLWltcGwnO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBnZW5DbGFzc0lkRmllbGROYW1lKGVjbGFzc2lmaWVyOiBFQ2xhc3NpZmllcik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5zbmFrZVVwcGVyQ2FzZShlY2xhc3NpZmllci5nZXROYW1lKCkpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBnZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmVhdHVyZTogRVN0cnVjdHVyYWxGZWF0dXJlKTogc3RyaW5nIHtcclxuICAgIHJldHVybiAoXHJcbiAgICAgIHRoaXMuc25ha2VVcHBlckNhc2UoZmVhdHVyZS5nZXRFQ29udGFpbmluZ0NsYXNzKCkuZ2V0TmFtZSgpKSArXHJcbiAgICAgICdfXycgK1xyXG4gICAgICB0aGlzLnNuYWtlVXBwZXJDYXNlKGZlYXR1cmUuZ2V0TmFtZSgpKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2VuT3BlcmF0aW9uSWRGaWVsZE5hbWUoZmVhdHVyZTogRU9wZXJhdGlvbik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gKFxyXG4gICAgICB0aGlzLnNuYWtlVXBwZXJDYXNlKGZlYXR1cmUuZ2V0RUNvbnRhaW5pbmdDbGFzcygpLmdldE5hbWUoKSkgK1xyXG4gICAgICAnX18nICtcclxuICAgICAgdGhpcy5zbmFrZVVwcGVyQ2FzZShmZWF0dXJlLmdldE5hbWUoKSlcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkZlYXR1cmVDb3VudEZpZWxkTmFtZShlY2xhc3M6IEVDbGFzcyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5zbmFrZVVwcGVyQ2FzZShlY2xhc3MuZ2V0TmFtZSgpKSArICdfRkVBVFVSRV9DT1VOVCc7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkZlYXR1cmVHZXR0ZXJOYW1lKGZlYXR1cmU6IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjbGFzc05hbWUgPSBmZWF0dXJlLmdldEVDb250YWluaW5nQ2xhc3MoKS5nZXROYW1lKCk7XHJcbiAgICBjb25zdCBmZWF0dXJlTmFtZSA9IHRoaXMuY2FwaXRhbGl6ZShmZWF0dXJlLmdldE5hbWUoKSk7XHJcbiAgICByZXR1cm4gYGdldCR7Y2xhc3NOYW1lfV8ke2ZlYXR1cmVOYW1lfWA7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbk9wZXJhdGlvbkdldHRlck5hbWUoZmVhdHVyZTogRU9wZXJhdGlvbik6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjbGFzc05hbWUgPSBmZWF0dXJlLmdldEVDb250YWluaW5nQ2xhc3MoKS5nZXROYW1lKCk7XHJcbiAgICBjb25zdCBmZWF0dXJlTmFtZSA9IHRoaXMuY2FwaXRhbGl6ZShmZWF0dXJlLmdldE5hbWUoKSk7XHJcbiAgICByZXR1cm4gYGdldCR7Y2xhc3NOYW1lfV8ke2ZlYXR1cmVOYW1lfWA7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkVkYXRhVHlwZUdldHRlcihmZWF0dXJlOiBFRGF0YVR5cGUpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGBFY29yZVBhY2thZ2UuZUlOU1RBTkNFLmdldCR7dGhpcy5jYXBpdGFsaXplKGZlYXR1cmUuZ2V0TmFtZSgpKX0oKWA7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc3RhdGljIGdlbkVjbGFzc0dldHRlck5hbWUoZWNsYXNzaWZpZXI6IEVDbGFzc2lmaWVyKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGdldHRlciA9ICdnZXQnICsgdGhpcy5jYXBpdGFsaXplKGVjbGFzc2lmaWVyLmdldE5hbWUoKSk7XHJcbiAgICByZXR1cm4gZ2V0dGVyO1xyXG4gIH1cclxuXHJcbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcblxyXG4gIC8qKlxyXG4gICAqIEdlbmVyYXRlcyByZWZlcmVuY2UgdG8gdGhlIHBhY2thZ2UgaW5zdGFuY2UgZm9yIHRoZSAndG8nIEVDbGFzcywgYW5kXHJcbiAgICogcmVnaXN0ZXJzIGl0IGFzIGEgcGFja2FnZSB0byBpbXBvcnQgaWYgaXQgaXMgZGlmZmVyZW50IGZyb20gdGhhdFxyXG4gICAqIG9mIHRoZSAnZnJvbScgRUNsYXNzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHRvXHJcbiAgICogQHBhcmFtIGZyb21cclxuICAgKiBAcGFyYW0gcGtnVG9JbXBvcnRcclxuICAgKi9cclxuICBwdWJsaWMgc3RhdGljIGdldFJlZmVyZW5jZVRvUGFja2FnZUluc3RhbmNlKFxyXG4gICAgdG86IEVDbGFzc2lmaWVyLFxyXG4gICAgZnJvbTogRUNsYXNzaWZpZXIsXHJcbiAgICBwa2dUb0ltcG9ydDogU2V0PEVQYWNrYWdlPlxyXG4gICkge1xyXG4gICAgbGV0IHBrZ1JlZiA9ICd0aGlzJztcclxuICAgIC8vaGFuZGxlIGluaGVyaXRhbmNlIGZyb20gb2JqZWN0cyBpbiBvdGhlciBwYWNrYWdlc1xyXG4gICAgaWYgKHRvLmdldEVQYWNrYWdlKCkgIT09IGZyb20uZ2V0RVBhY2thZ2UoKSkge1xyXG4gICAgICBwa2dUb0ltcG9ydC5hZGQodG8uZ2V0RVBhY2thZ2UoKSk7XHJcbiAgICAgIHBrZ1JlZiA9IFRHZW5VdGlscy5nZW5QYWNrYWdlQ2xhc3NOYW1lKHRvLmdldEVQYWNrYWdlKCkpICsgJy5lSU5TVEFOQ0UnO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHBrZ1JlZjtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0UGF0aFRvUm9vdChwa2c6IEVQYWNrYWdlKSB7XHJcbiAgICBsZXQgcGF0aFRvUm9vdCA9ICcuLyc7XHJcbiAgICBpZiAocGtnLmdldEVTdXBlclBhY2thZ2UoKSkge1xyXG4gICAgICBsZXQgY3Vyc29yID0gcGtnO1xyXG4gICAgICBwYXRoVG9Sb290ID0gJyc7XHJcbiAgICAgIHdoaWxlIChjdXJzb3IuZ2V0RVN1cGVyUGFja2FnZSgpKSB7XHJcbiAgICAgICAgcGF0aFRvUm9vdCArPSAnLi4vJztcclxuICAgICAgICBjdXJzb3IgPSBjdXJzb3IuZ2V0RVN1cGVyUGFja2FnZSgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcGF0aFRvUm9vdDtcclxuICB9XHJcblxyXG5cclxuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICAvLyBGaWxlL3BhdGggcmVsYXRlZCBtZXRob2RzIChUT0RPOiBTaG91bGQgdXNlIGltcG9ydGVkIFBBVEggbGlicmFyeT8/PylcclxuXHJcbiAgLyoqXHJcbiAgICogQ29tcHV0ZXMgdGhlIGltcG9ydCBwYXRoIG5lY2Vzc2FyeSB0byByZXNvbHZlIGFuIEVDbGFzcyBpbiBhIGRpZmZlcmVudFxyXG4gICAqIHBhY2thZ2UuXHJcbiAgICogQHBhcmFtIGZyb21DbGFzc1xyXG4gICAqIEBwYXJhbSB0b0NsYXNzXHJcbiAgICovXHJcbiAgcHVibGljIHN0YXRpYyBnZXRQYXRoVG9UeXBlSW5PdGhlclBrZyhcclxuICAgIGZyb21DbGFzczogRUNsYXNzLFxyXG4gICAgdG9DbGFzczogRUNsYXNzaWZpZXJcclxuICApIHtcclxuICAgIC8vVE9ETzogSWYgY3Jvc3MtcGFja2FnZSByZWZlcmVuY2VzIGFyZSBub3QgYmVpbmcgY29ycmVjdGx5IGNvbXB1dGVkLCBpdFxyXG4gICAgLy9tYXkgYmUgYmVjYXVzZSBlY2xhc3Muc2V0RVBhY2thZ2UgaXMgbm90IGJlaW5nIGNhbGxlZCBkdXJpbmcgRWNvcmUgcGFyc2luZy5cclxuICAgIC8vQ29ycmVjdCBmaXggd291bGQgYmUgZm9yIHRoaXMgdG8gYmUgc2V0IGFzIHBhcnQgb2YgYSBwcm9wZXIgaW52ZXJzZVxyXG4gICAgLy9yZWZlcmVuY2Ugd2l0aCBFUGFja2FnZS5lY2xhc3NpZmllcnNcclxuICAgIGNvbnN0IGZyb21QYWNrYWdlID0gZnJvbUNsYXNzLmdldEVQYWNrYWdlKCk7XHJcbiAgICBjb25zdCB0b1BhY2thZ2UgPSB0b0NsYXNzLmdldEVQYWNrYWdlKCk7XHJcblxyXG4gICAgLy9mb3IgbmVzdGVkIHBhY2thZ2Ugc3RydWN0dXJlcyAoYWxsb3dhYmxlIGZyb20gRWNvcmUpXHJcbiAgICBpZiAoZnJvbVBhY2thZ2UuZ2V0RVN1cGVyUGFja2FnZSgpKVxyXG4gICAgICByZXR1cm4gJy4uLycgKyB0aGlzLmdldFBhdGhUb090aGVyUGFja2FnZShmcm9tUGFja2FnZSwgdG9QYWNrYWdlKTtcclxuXHJcbiAgICAvL2ZvciBwYWNrYWdlcyBkZWZpbmVkIGFzICd4LWRhdGEnIGZvbGRlcnMgaW4gbGliIHdpdGhvdXQgbmVzdGluZ1xyXG4gICAgcmV0dXJuICcuLi8nICsgdGhpcy5nZXRQYXRoVG9PdGhlclBhY2thZ2VGbGF0KGZyb21QYWNrYWdlLCB0b1BhY2thZ2UpO1xyXG4gIH1cclxuICBwdWJsaWMgc3RhdGljIGdldFBhdGhUb090aGVyUGFja2FnZUZsYXQoXHJcbiAgICBmcm9tUGFja2FnZTogRVBhY2thZ2UsXHJcbiAgICB0b1BhY2thZ2U6IEVQYWNrYWdlXHJcbiAgKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHBrZ05hbWUgPSB0b1BhY2thZ2UgPyB0b1BhY2thZ2UuZ2V0TmFtZSgpIDogJ1BhY2thZ2VOb3RGb3VuZCc7XHJcbiAgICBjb25zb2xlLmxvZygnV0FSTklORzogQ1JPU1MtUEFDS0FHRSBJTVBPUlRTIE5PVCBTVVBQT1JURUQnKTtcclxuICAgIHJldHVybiBgJyR7dGhpcy5rZWJhYkxvd2VyQ2FzZShwa2dOYW1lKX0nYDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgZ2V0UGF0aFRvT3RoZXJQYWNrYWdlKFxyXG4gICAgZnJvbVBhY2thZ2U6IEVQYWNrYWdlLFxyXG4gICAgdG9QYWNrYWdlOiBFUGFja2FnZVxyXG4gICk6IHN0cmluZyB7XHJcbiAgICBsZXQgcGF0aFRvSW1wb3J0ID0gJyc7XHJcbiAgICBsZXQgY3Vyc29yID0gZnJvbVBhY2thZ2U7XHJcbiAgICB3aGlsZSAoY3Vyc29yLmdldEVTdXBlclBhY2thZ2UoKSkge1xyXG4gICAgICBwYXRoVG9JbXBvcnQgKz0gJy4uLyc7XHJcbiAgICAgIGN1cnNvciA9IGN1cnNvci5nZXRFU3VwZXJQYWNrYWdlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy9hbmQgYmFjayBkb3duIHRvIHRoZSBlbGVtZW50IHRvIGJlIGltcG9ydGVkXHJcbiAgICBjb25zdCBwYXRoRG93biA9IG5ldyBBcnJheTxFUGFja2FnZT4oKTtcclxuICAgIGN1cnNvciA9IHRvUGFja2FnZTtcclxuICAgIHdoaWxlIChjdXJzb3IuZ2V0RVN1cGVyUGFja2FnZSgpKSB7XHJcbiAgICAgIHBhdGhEb3duLnVuc2hpZnQoY3Vyc29yKTtcclxuICAgICAgY3Vyc29yID0gY3Vyc29yLmdldEVTdXBlclBhY2thZ2UoKTtcclxuICAgIH1cclxuICAgIGZvciAoY29uc3QgcGF0aFBrZyBvZiBwYXRoRG93bikge1xyXG4gICAgICBwYXRoVG9JbXBvcnQgKz0gcGF0aFBrZy5nZXROYW1lKCkgKyAnLyc7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcGF0aFRvSW1wb3J0O1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHN0YXRpYyBpblNhbWVMaWIoZWNsYXNzMTogRUNsYXNzLCBlY2xhc3MyOiBFQ2xhc3MpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBlY2xhc3MxLmdldFJvb3RQYWNrYWdlKCkgPT09IGVjbGFzczIuZ2V0Um9vdFBhY2thZ2UoKTtcclxuICB9XHJcbn1cclxuIl19