UNPKG

@tripsnek/tmf

Version:

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

544 lines 65.7 kB
import { TGenUtils as DU } from './tgen-utils.js';
import { TUtils } from '../tutils.js';
import { EReferenceImpl } from '../metamodel/impl/ereference-impl.js';
import { EClassImpl } from '../metamodel/impl/eclass-impl.js';
/**
 * Source code generation for *gen.ts files for EClasses.
 *
 * @author dtuohy
 */
export class TGeneratorGen {
    _pkg;
    _packageName;
    /**
     * Generates a template string containing all source code for the *gen.ts
     * file for the given EClass.
     *
     * @param eClass
     * @param toImport
     * @param genToImport
     * @param pkgToImport
     */
    generate(eClass, toImport, genToImport, pkgToImport) {
        this._pkg = eClass.getEPackage();
        this._packageName = DU.genPackageClassName(this._pkg);
        const genClassName = DU.genGenClassName(eClass);
        const apiClassName = eClass.getName();
        return `${this.generateAllImportStatements(eClass, toImport, genToImport, pkgToImport)}

//make sure package is initialized
${this._packageName}.eINSTANCE;

/**
 * This file is source-code generated and should never be edited. It implements
 * the core TMF functionality for ${eClass.getName()}.
 */
export abstract class ${genClassName} ${this.generateExtends(eClass)} implements ${apiClassName} {
  /** feature declarations */
${this.genFeatureDeclarations(eClass)}
${this.genConstructor(eClass)}
${this.genGettersAndSetters(eClass)}
${this.genEoperations(eClass)}
  //======================================================================
  // Standard EObject behavior
${this.genEGet(eClass)}
${this.genESet(eClass)}
${this.genEIsSet(eClass)}
${this.genEUnset(eClass)}
${this.genBasicSetters(eClass)}
${this.genEInverseAdd(eClass)}
${this.genEInverseRemove(eClass)}

  //======================================================================
  // eClass()

  public override eClass(): EClass {
    return ${this._packageName}.Literals.${DU.snakeUpperCase(eClass.getName())};
  }
}`;
    }
    /**
     * Generates import statements for all APIs, Gen classes
     * and packages to import.
     *
     * @param eClass
     * @param toImport
     * @param genToImport
     * @param pkgToImport
     */
    generateAllImportStatements(eClass, toImport, genToImport, pkgToImport, async) {
        let className = eClass.getName();
        if (async)
            className += 'Async';
        const isEcore = eClass.getEPackage().getName() == 'ecore';
        let result = `${isEcore ? DU.ECORE_DEFAULT_IMPORTS : DU.DEFAULT_IMPORTS}
${DU.genApiImports(eClass, toImport, `..${DU.API_PATH}`)}
import { ${this._packageName} } from '../${DU.genPackageFileName(this._pkg)}.js';
import { ${className} } from '..${DU.API_PATH}/${DU.genClassApiName(eClass, async)}.js';
`;
        //gen and impl classes that need to be imported
        for (const ec of genToImport) {
            if (ec) {
                let pathToImport = './';
                //only import Gen and Impl if it is an EClass (not an EEnum)
                if (ec instanceof EClassImpl) {
                    if (ec.getEPackage() !== eClass.getEPackage()) {
                        //if root package is shared, the classes are assumed to exist in the same lib, and can be imported with relative paths
                        if (ec.getRootPackage() === eClass.getRootPackage()) {
                            pathToImport = `${DU.getPathToTypeInOtherPkg(eClass, ec)}/`;
                            result += `import { ${ec.getName()}Gen } from '${pathToImport + 'gen/' + DU.genClassGenName(ec)}.js';\n`;
                            result += `import { ${ec.getName()}Impl } from '${pathToImport + 'impl/' + DU.genClassImplName(ec)}.js';\n`;
                        }
                        //otherwise, use non-relative paths
                        else {
                            console.log('WARNING: CROSS-PACKAGE IMPORTS NOT SUPPORTED');
                        }
                    }
                    else {
                        result += `import { ${ec.getName()}Gen } from './${DU.genClassGenName(ec)}.js';\n`;
                        result += `import { ${ec.getName()}Impl } from '../impl/${DU.genClassImplName(ec)}.js';\n`;
                    }
                }
            }
        }
        //add package imports (e.g. for references to types in external packages)
        result += DU.generateImportStatementsForExternalPackages(pkgToImport, this._pkg, '../');
        return result;
    }
    generateExtends(eclass) {
        if (eclass.getName() == 'EObject')
            return '';
        let result = `extends EObjectImpl`;
        let sti = 0;
        for (const superType of eclass.getESuperTypes()) {
            //TODO: Add support for multiple-inheritance on implementation class?
            if (sti === 0) {
                if (!superType.isInterface()) {
                    result = ` extends ${superType.getName()}Impl`;
                }
            }
            sti++;
        }
        return result;
    }
    genFeatureDeclarations(eclass) {
        let sourceContent = ``;
        for (const f of eclass.getEStructuralFeatures()) {
            const typeName = DU.getTypeName(f);
            let initializer = '';
            if (f.isMany()) {
                //get feature ID for inverse reference, if specified
                let inverseFeatureId = 'undefined';
                if (f instanceof EReferenceImpl) {
                    if (f.getEOpposite()) {
                        const oppRef = f.getEOpposite();
                        if (oppRef) {
                            inverseFeatureId = `${DU.genPackageClassName(oppRef.getEContainingClass().getEPackage())}.${DU.genFeatureIdFieldName(oppRef)}`;
                        }
                    }
                }
                //list is initialized with information about owning object, the
                //field it represents, and any inverse field
                initializer += ` = new Basic${typeName}(
    undefined,
    this,
    ${this._packageName}.${DU.genFeatureIdFieldName(f)},
    ${inverseFeatureId}
  )`;
            }
            //TODO: only add '!' is feature is marked as required (lowerBound = 1)
            let optionalityOperator = f.isMany() ? '' : '!';
            sourceContent += `  protected ${f.getName()}${optionalityOperator}: ${typeName}${initializer};\n`;
        }
        return sourceContent;
    }
    genConstructor(eClass) {
        // Build sorted list of all constructor arguments
        let argFields = [];
        // Build sorted list constructor arguments from possible superType
        const superFields = [];
        let result = '';
        if (argFields.length > 0) {
            // Now build up the constructor code...
            result += `
      //======================================================================
      // Constructor
      
      public constructor(`;
            for (const field of argFields) {
                if (field.isMany()) {
                    const type = TUtils.getTypescriptName(field.getEType());
                    result += `_${field.getName()}?: EList<${type}>, `;
                }
                else {
                    const type = TUtils.getTypescriptName(field.getEType());
                    result += `_${field.getName()}?: ${type}, `;
                }
            }
            result += ') {';
            // Deal with invoking 'super(....)' if necessary
            if (superFields) {
                result += 'super(';
                for (const field of superFields) {
                    result += `_${field.getName()}, `;
                }
                result += ');';
                argFields = argFields.filter((f) => !superFields.includes(f));
            }
            else {
                result += 'super();';
            }
            // Deal with setting the remaining (locally defined) fields
            for (const field of argFields) {
                if (field.isMany()) {
                    const eListVar = field.getName() + 'EList';
                    result += `if (_${field.getName()}) {
            const ${eListVar} = this.${DU.getterName(field)}();
            for(const val of _${field.getName()}) { ${eListVar}.add(val); }
          }`;
                }
                else {
                    result += `this.${DU.setterName(field)}(_${field.getName()});`;
                }
            }
            result += '}';
        }
        return result;
    }
    genGettersAndSetters(eClass) {
        let result = `
  //======================================================================
  // Getters and Setters
`;
        for (const field of eClass.getEStructuralFeatures()) {
            result += this.genGetter(eClass, field);
            result += this.genSetter(eClass, field);
        }
        return result;
    }
    genGetter(eClass, field) {
        const visibility = 'public';
        let result = `

  ${visibility} ${DU.getterSig(field)} {`;
        if (field.isVolatile()) {
            result += `
    throw new Error(
      'Unsupported operation on volatile field. Override in ${eClass.getName()}Impl.'
    );`;
        }
        else {
            result += `
    return this.${field.getName()};`;
        }
        result += `
  }`; // End of Getter definition
        return result;
    }
    genSetter(eClass, field) {
        let result = ``;
        if (!field.isMany()) {
            const paramName = DU.setterParamName(field);
            const visibility = field.isChangeable() ? 'public' : 'private';
            result += `

  ${visibility} ${DU.setterSig(field)} {`;
            if (field.isVolatile()) {
                result += `
    throw new Error(
      'Unsupported operation on volatile field. Override in ${eClass.getName()}Impl.'
    );`;
            }
            else {
                //handle containment enforcement if appropriate
                if (field instanceof EReferenceImpl && field.isContainment()) {
                    const oldVar = 'old' + DU.capitalize(field.getName());
                    result += `
    const ${oldVar} = this.${field.getName()};
    if (${oldVar}) ${oldVar}.setEContainer(undefined, undefined);
    if (${paramName}) ${paramName}.setEContainer(this, ${DU.genPackageClassName(this._pkg)}.${DU.genFeatureIdFieldName(field)});`;
                }
                //handle inverse references if appropriate
                if (field instanceof EReferenceImpl && field.getEOpposite()) {
                    //TODO: handle opposites in other packages?
                    const oppositeIdField = `${this._packageName}.${DU.genFeatureIdFieldName(field.getEOpposite())}`;
                    result += `
    if (this.${field.getName()} !== ${paramName}) {
      if (this.${field.getName()}) {
        this.${field.getName()}.eInverseRemove(this, ${oppositeIdField});
      }
      if (${paramName}) {
        ${paramName}.eInverseAdd(this, ${oppositeIdField});
      }
    }`;
                }
                result += `
    this.basic${DU.capitalize(DU.setterName(field))}(${paramName});`;
                // sourceContent += `this.${f.getName()} = ${paramName};}`;
            }
            result += `
  }`; // End of Setter definition
        }
        return result;
    }
    genBasicSetters(eClass) {
        let result = `
  //======================================================================
  // Basic setters (allow EOpposite enforcement without triggering infinite cycles)
`;
        for (const field of eClass.getEStructuralFeatures()) {
            //only include basic setters for internal references
            if (!field.isMany() && !field.isVolatile()) {
                const visibility = field.isChangeable() ? 'public' : 'private';
                const paramName = DU.setterParamName(field);
                result += `

  ${visibility} basic${DU.capitalize(DU.setterSig(field))} {`;
                if (field instanceof EReferenceImpl &&
                    field.getEOpposite() &&
                    field.getEOpposite().isContainment()) {
                    result += `
    this.eBasicSetContainer(${paramName}, ${DU.genPackageClassName(eClass.getEPackage())}.${DU.genFeatureIdFieldName(field.getEOpposite())});`;
                }
                result += `
    this.${field.getName()} = ${paramName};
  }`;
            }
        }
        return result;
    }
    genEoperations(eClass) {
        let result = `
  //======================================================================
  // API Operations
`;
        for (const eop of eClass.getEOperations()) {
            result += `

  public ${DU.eopSignature(eop)} {
    throw new Error('Not implemented');
  }`;
        }
        //if this class directly inherits from an interface, need to add implementations of those as well
        for (const st of eClass.getESuperTypes()) {
            if (st.isInterface()) {
                for (const eop of st.getEOperations()) {
                    result += `

  public ${DU.eopSignature(eop)} {
    throw new Error('Not implemented');
  }`;
                }
            }
        }
        return result;
    }
    genEGet(eClass) {
        let result = `
  /**
   * eGet() - provides reflective access to all features.
   */
  public override eGet(feature: number | EStructuralFeature): any {
    const featureID: number =
      typeof feature === 'number'
        ? feature
        : (<EStructuralFeature>feature).getFeatureID();
    switch (featureID) {`;
        for (const feature of eClass.getEStructuralFeatures()) {
            const featureIdField = DU.genFeatureIdFieldName(feature);
            result += `
      case ${this._packageName}.${featureIdField}:
        return this.${DU.getterName(feature)}();`;
        }
        result += `
    }
    return super.eGet(featureID);
  }`;
        return result;
    }
    genESet(eClass) {
        let result = `

  /**
   * eSet() - provides ability to reflectively set all features.
   */
  public override eSet(feature: number | EStructuralFeature, newValue: any): void {
    const featureID: number =
      typeof feature === 'number'
        ? feature
        : (<EStructuralFeature>feature).getFeatureID();
    switch (featureID) {`;
        for (const feature of eClass.getEStructuralFeatures()) {
            const featureIdField = DU.genFeatureIdFieldName(feature);
            result += `
      case ${this._packageName}.${featureIdField}:`;
            if (!feature.isMany()) {
                result += `
        this.${DU.setterName(feature)}(newValue);
        return;`;
            }
            else {
                const getter = DU.getterName(feature);
                result += `
        this.${getter}().clear();
        this.${getter}().addAll(newValue);
        return;`;
            }
        }
        result += `
    }
    return super.eSet(featureID, newValue);
  }`;
        return result;
    }
    genEIsSet(eClass) {
        let result = `

  /**
   * eIsSet() - provides ability to reflectively check if any feature is set.
   */
  public override eIsSet(feature: number | EStructuralFeature): boolean {
    const featureID: number =
      typeof feature === 'number'
        ? feature
        : (<EStructuralFeature>feature).getFeatureID();
    switch (featureID) {`;
        for (const feature of eClass.getEStructuralFeatures()) {
            const featureIdField = DU.genFeatureIdFieldName(feature);
            result += `
      case ${this._packageName}.${featureIdField}:`;
            if (!feature.isMany()) {
                result += `
        return this.${DU.getterName(feature)}() != null;`;
            }
            else {
                const getter = DU.getterName(feature);
                result += `
        return !this.${getter}().isEmpty();`;
            }
        }
        result += `
    }
    return super.eIsSet(featureID);
  }`;
        return result;
    }
    genEUnset(eClass) {
        let result = `

  /**
   * eUnset() - provides ability to reflectively unset any feature.
   */
  public override eUnset(feature: number | EStructuralFeature): void {
    const featureID: number =
      typeof feature === 'number'
        ? feature
        : (<EStructuralFeature>feature).getFeatureID();
    switch (featureID) {`;
        for (const feature of eClass.getEStructuralFeatures()) {
            const featureIdField = DU.genFeatureIdFieldName(feature);
            result += `
      case ${this._packageName}.${featureIdField}:`;
            if (!feature.isMany()) {
                result += `
        this.${DU.setterName(feature)}(undefined!);
        return;`;
            }
            else {
                const getter = DU.getterName(feature);
                result += `
        this.${getter}().clear();
        return;`;
            }
        }
        result += `
    }
    return super.eUnset(featureID);
  }`;
        return result;
    }
    genEInverseAdd(eClass) {
        let result = `
  //======================================================================
  // Inverse Adders (if needed)`;
        let numSwitches = 0;
        for (const f of eClass.getEStructuralFeatures()) {
            if (f instanceof EReferenceImpl) {
                if (!f.isVolatile() && f.getEOpposite()) {
                    if (numSwitches === 0) {
                        result += `
  public override eInverseAdd(otherEnd: EObject, featureID: number): void {
    switch (featureID) {`;
                    }
                    //TODO: Do I also need to do a basic remove from container if this sets a new container?
                    result += `
      case ${this._packageName}.${DU.genFeatureIdFieldName(f)}:`;
                    if (f.isMany()) {
                        result += `
        return (<EList<EObject>>this.${DU.getterName(f)}()).basicAdd(otherEnd);`;
                    }
                    else {
                        if (f.getEOpposite()) {
                            const oppositeFeatureField = `${this._packageName}.${DU.genFeatureIdFieldName(f.getEOpposite())}`;
                            result += `
        if (this.${f.getName()})
          this.${f.getName()}.eInverseRemove(
            this,
            ${oppositeFeatureField}
          );`;
                        }
                        result += `
        return this.basic${DU.capitalize(DU.setterName(f))}(<${f
                            .getEType()
                            .getName()}>otherEnd);`;
                    }
                    numSwitches++;
                }
            }
        }
        if (numSwitches > 0) {
            result += `
    }
    return super.eInverseAdd(otherEnd, featureID);
  }`;
        }
        return result;
    }
    genEInverseRemove(eClass) {
        let result = `

  //======================================================================
  // Inverse Removers (if needed)`;
        let numSwitches = 0;
        for (const f of eClass.getEStructuralFeatures()) {
            if (f instanceof EReferenceImpl) {
                if (!f.isVolatile() && f.getEOpposite()) {
                    if (numSwitches === 0) {
                        result += `
  public override eInverseRemove(otherEnd: EObject, featureID: number): void {
    switch (featureID) {`;
                    }
                    result += `
      case ${this._packageName}.${DU.genFeatureIdFieldName(f)}:`;
                    if (f.isMany()) {
                        result += `
        return (<EList<EObject>>this.${DU.getterName(f)}()).basicRemove(otherEnd);`;
                    }
                    else {
                        result += `
        return this.basic${DU.capitalize(DU.setterName(f))}(undefined!);`;
                    }
                    numSwitches++;
                }
            }
        }
        if (numSwitches > 0) {
            result += `
    }
    return super.eInverseRemove(otherEnd, featureID);
  }`;
        }
        return result;
    }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGdlbmVyYXRvci1nZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3NvdXJjZS1nZW5lcmF0b3JzL3RnZW5lcmF0b3ItZ2VuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE9BQU8sRUFBRSxTQUFTLElBQUksRUFBRSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDdEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRTlEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUNoQixJQUFJLENBQVk7SUFDaEIsWUFBWSxDQUFVO0lBRTlCOzs7Ozs7OztPQVFHO0lBQ0ksUUFBUSxDQUNiLE1BQWMsRUFDZCxRQUEwQixFQUMxQixXQUE2QixFQUM3QixXQUEwQjtRQUUxQixJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEQsTUFBTSxZQUFZLEdBQUcsRUFBRSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFdEMsT0FBTyxHQUFHLElBQUksQ0FBQywyQkFBMkIsQ0FDeEMsTUFBTSxFQUNOLFFBQVEsRUFDUixXQUFXLEVBQ1gsV0FBVyxDQUNaOzs7RUFHSCxJQUFJLENBQUMsWUFBWTs7OztvQ0FJaUIsTUFBTSxDQUFDLE9BQU8sRUFBRTs7d0JBRTVCLFlBQVksSUFBSSxJQUFJLENBQUMsZUFBZSxDQUN0RCxNQUFNLENBQ1AsZUFBZSxZQUFZOztFQUU5QixJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDO0VBQ25DLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDO0VBQzNCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUM7RUFDakMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUM7OztFQUczQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztFQUNwQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztFQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztFQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztFQUN0QixJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQztFQUM1QixJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQztFQUMzQixJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDOzs7Ozs7YUFNbkIsSUFBSSxDQUFDLFlBQVksYUFBYSxFQUFFLENBQUMsY0FBYyxDQUN0RCxNQUFNLENBQUMsT0FBTyxFQUFFLENBQ2pCOztFQUVILENBQUM7SUFDRCxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSywyQkFBMkIsQ0FDakMsTUFBYyxFQUNkLFFBQTBCLEVBQzFCLFdBQTZCLEVBQzdCLFdBQTBCLEVBQzFCLEtBQWU7UUFFZixJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDakMsSUFBSSxLQUFLO1lBQUUsU0FBUyxJQUFJLE9BQU8sQ0FBQztRQUNoQyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksT0FBTyxDQUFDO1FBRTFELElBQUksTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxlQUFlO0VBQ3pFLEVBQUUsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztXQUM3QyxJQUFJLENBQUMsWUFBWSxlQUFlLEVBQUUsQ0FBQyxrQkFBa0IsQ0FDMUQsSUFBSSxDQUFDLElBQUksQ0FDVjtXQUNNLFNBQVMsY0FBYyxFQUFFLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxlQUFlLENBQzdELE1BQU0sRUFDTixLQUFLLENBQ047Q0FDSixDQUFDO1FBRUUsK0NBQStDO1FBQy9DLEtBQUssTUFBTSxFQUFFLElBQUksV0FBVyxFQUFFLENBQUM7WUFDN0IsSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDUCxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUM7Z0JBRXhCLDREQUE0RDtnQkFDNUQsSUFBSSxFQUFFLFlBQVksVUFBVSxFQUFFLENBQUM7b0JBQzdCLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxLQUFLLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO3dCQUM5QyxzSEFBc0g7d0JBQ3RILElBQUksRUFBRSxDQUFDLGNBQWMsRUFBRSxLQUFLLE1BQU0sQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDOzRCQUNwRCxZQUFZLEdBQUcsR0FBRyxFQUFFLENBQUMsdUJBQXVCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUM7NEJBQzVELE1BQU0sSUFBSSxZQUFZLEVBQUUsQ0FBQyxPQUFPLEVBQUUsZUFDaEMsWUFBWSxHQUFHLE1BQU0sR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFTLEVBQUUsQ0FDdkQsU0FBUyxDQUFDOzRCQUNWLE1BQU0sSUFBSSxZQUFZLEVBQUUsQ0FBQyxPQUFPLEVBQUUsZ0JBQ2hDLFlBQVksR0FBRyxPQUFPLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFTLEVBQUUsQ0FDekQsU0FBUyxDQUFDO3dCQUNaLENBQUM7d0JBQ0QsbUNBQW1DOzZCQUM5QixDQUFDOzRCQUNKLE9BQU8sQ0FBQyxHQUFHLENBQUMsOENBQThDLENBQUMsQ0FBQzt3QkFDOUQsQ0FBQztvQkFDSCxDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxJQUFJLFlBQVksRUFBRSxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxDQUFDLGVBQWUsQ0FDbkUsRUFBWSxDQUNiLFNBQVMsQ0FBQzt3QkFDWCxNQUFNLElBQUksWUFBWSxFQUFFLENBQUMsT0FBTyxFQUFFLHdCQUF3QixFQUFFLENBQUMsZ0JBQWdCLENBQzNFLEVBQVksQ0FDYixTQUFTLENBQUM7b0JBQ2IsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCx5RUFBeUU7UUFDekUsTUFBTSxJQUFJLEVBQUUsQ0FBQywyQ0FBMkMsQ0FDdEQsV0FBVyxFQUNYLElBQUksQ0FBQyxJQUFJLEVBQ1QsS0FBSyxDQUNOLENBQUM7UUFDRixPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sZUFBZSxDQUFDLE1BQWM7UUFDcEMsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLElBQUksU0FBUztZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQzdDLElBQUksTUFBTSxHQUFHLHFCQUFxQixDQUFDO1FBQ25DLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNaLEtBQUssTUFBTSxTQUFTLElBQUksTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUM7WUFDaEQscUVBQXFFO1lBQ3JFLElBQUksR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNkLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztvQkFDN0IsTUFBTSxHQUFHLFlBQVksU0FBUyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUM7Z0JBQ2pELENBQUM7WUFDSCxDQUFDO1lBQ0QsR0FBRyxFQUFFLENBQUM7UUFDUixDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLHNCQUFzQixDQUFDLE1BQWM7UUFDM0MsSUFBSSxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLHNCQUFzQixFQUFFLEVBQUUsQ0FBQztZQUNoRCxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLElBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO2dCQUNmLG9EQUFvRDtnQkFDcEQsSUFBSSxnQkFBZ0IsR0FBRyxXQUFXLENBQUM7Z0JBQ25DLElBQUksQ0FBQyxZQUFZLGNBQWMsRUFBRSxDQUFDO29CQUNoQyxJQUFJLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO3dCQUNyQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7d0JBRWhDLElBQUcsTUFBTSxFQUFDLENBQUM7NEJBQ1QsZ0JBQWdCLEdBQUcsR0FBRyxFQUFFLENBQUMsbUJBQW1CLENBQzFDLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUMzQyxJQUFJLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO3dCQUMxQyxDQUFDO29CQUNILENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCwrREFBK0Q7Z0JBQy9ELDRDQUE0QztnQkFDNUMsV0FBVyxJQUFJLGVBQWUsUUFBUTs7O01BR3hDLElBQUksQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztNQUNoRCxnQkFBZ0I7SUFDbEIsQ0FBQztZQUNDLENBQUM7WUFDRCxzRUFBc0U7WUFFdEUsSUFBSSxtQkFBbUIsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBRWhELGFBQWEsSUFBSSxlQUFlLENBQUMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxtQkFBbUIsS0FBSyxRQUFRLEdBQUcsV0FBVyxLQUFLLENBQUM7UUFDcEcsQ0FBQztRQUNELE9BQU8sYUFBYSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxjQUFjLENBQUMsTUFBYztRQUNuQyxpREFBaUQ7UUFDakQsSUFBSSxTQUFTLEdBQVUsRUFBRSxDQUFDO1FBRTFCLGtFQUFrRTtRQUNsRSxNQUFNLFdBQVcsR0FBVyxFQUFFLENBQUM7UUFFL0IsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLElBQUksU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6Qix1Q0FBdUM7WUFDdkMsTUFBTSxJQUFJOzs7OzBCQUlVLENBQUM7WUFDckIsS0FBSyxNQUFNLEtBQUssSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDOUIsSUFBSSxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztvQkFDbkIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO29CQUN4RCxNQUFNLElBQUksSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLFlBQVksSUFBSSxLQUFLLENBQUM7Z0JBQ3JELENBQUM7cUJBQU0sQ0FBQztvQkFDTixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7b0JBQ3hELE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsTUFBTSxJQUFJLElBQUksQ0FBQztnQkFDOUMsQ0FBQztZQUNILENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUFDO1lBQ2hCLGdEQUFnRDtZQUNoRCxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksUUFBUSxDQUFDO2dCQUNuQixLQUFLLE1BQU0sS0FBSyxJQUFJLFdBQVcsRUFBRSxDQUFDO29CQUNoQyxNQUFNLElBQUksSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQztnQkFDcEMsQ0FBQztnQkFDRCxNQUFNLElBQUksSUFBSSxDQUFDO2dCQUNmLFNBQVMsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNoRSxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxJQUFJLFVBQVUsQ0FBQztZQUN2QixDQUFDO1lBQ0QsMkRBQTJEO1lBQzNELEtBQUssTUFBTSxLQUFLLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQzlCLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7b0JBQ25CLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUM7b0JBQzNDLE1BQU0sSUFBSSxRQUFRLEtBQUssQ0FBQyxPQUFPLEVBQUU7b0JBQ3ZCLFFBQVEsV0FBVyxFQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztnQ0FDM0IsS0FBSyxDQUFDLE9BQU8sRUFBRSxPQUFPLFFBQVE7WUFDbEQsQ0FBQztnQkFDTCxDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxJQUFJLFFBQVEsRUFBRSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQztnQkFDakUsQ0FBQztZQUNILENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxDQUFDO1FBQ2hCLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sb0JBQW9CLENBQUMsTUFBYztRQUN6QyxJQUFJLE1BQU0sR0FBRzs7O0NBR2hCLENBQUM7UUFDRSxLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUM7WUFDcEQsTUFBTSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLFNBQVMsQ0FBQyxNQUFjLEVBQUUsS0FBeUI7UUFDekQsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDO1FBQzVCLElBQUksTUFBTSxHQUFHOztJQUViLFVBQVUsSUFBSSxFQUFFLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFDdEMsSUFBSSxLQUFLLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUk7OzhEQUU4QyxNQUFNLENBQUMsT0FBTyxFQUFFO09BQ3ZFLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSTtrQkFDRSxLQUFLLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQztRQUNqQyxDQUFDO1FBQ0QsTUFBTSxJQUFJO0lBQ1YsQ0FBQyxDQUFDLDJCQUEyQjtRQUM3QixPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sU0FBUyxDQUFDLE1BQWMsRUFBRSxLQUF5QjtRQUN6RCxJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDaEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUMsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUMvRCxNQUFNLElBQUk7O0lBRVosVUFBVSxJQUFJLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztZQUNwQyxJQUFJLEtBQUssQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO2dCQUN2QixNQUFNLElBQUk7OzhEQUU0QyxNQUFNLENBQUMsT0FBTyxFQUFFO09BQ3ZFLENBQUM7WUFDRixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sK0NBQStDO2dCQUMvQyxJQUFJLEtBQUssWUFBWSxjQUFjLElBQUksS0FBSyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUM7b0JBQzdELE1BQU0sTUFBTSxHQUFHLEtBQUssR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO29CQUN0RCxNQUFNLElBQUk7WUFDUixNQUFNLFdBQVcsS0FBSyxDQUFDLE9BQU8sRUFBRTtVQUNsQyxNQUFNLEtBQUssTUFBTTtVQUNqQixTQUFTLEtBQUssU0FBUyx3QkFBd0IsRUFBRSxDQUFDLG1CQUFtQixDQUNuRSxJQUFJLENBQUMsSUFBSSxDQUNWLElBQUksRUFBRSxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7Z0JBQzNDLENBQUM7Z0JBQ0QsMENBQTBDO2dCQUMxQyxJQUFJLEtBQUssWUFBWSxjQUFjLElBQUksS0FBSyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7b0JBQzVELDJDQUEyQztvQkFDM0MsTUFBTSxlQUFlLEdBQUcsR0FDdEIsSUFBSSxDQUFDLFlBQ1AsSUFBSSxFQUFFLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRyxDQUFDLEVBQUUsQ0FBQztvQkFDdEQsTUFBTSxJQUFJO2VBQ0wsS0FBSyxDQUFDLE9BQU8sRUFBRSxRQUFRLFNBQVM7aUJBQzlCLEtBQUssQ0FBQyxPQUFPLEVBQUU7ZUFDakIsS0FBSyxDQUFDLE9BQU8sRUFBRSx5QkFBeUIsZUFBZTs7WUFFMUQsU0FBUztVQUNYLFNBQVMsc0JBQXNCLGVBQWU7O01BRWxELENBQUM7Z0JBQ0MsQ0FBQztnQkFDRCxNQUFNLElBQUk7Z0JBQ0YsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksU0FBUyxJQUFJLENBQUM7Z0JBQzdELDJEQUEyRDtZQUM3RCxDQUFDO1lBQ0QsTUFBTSxJQUFJO0lBQ1osQ0FBQyxDQUFDLDJCQUEyQjtRQUM3QixDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLGVBQWUsQ0FBQyxNQUFjO1FBQ3BDLElBQUksTUFBTSxHQUFHOzs7Q0FHaEIsQ0FBQztRQUNFLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxDQUFDLHNCQUFzQixFQUFFLEVBQUUsQ0FBQztZQUNwRCxvREFBb0Q7WUFDcEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO2dCQUMzQyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO2dCQUMvRCxNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM1QyxNQUFNLElBQUk7O0lBRWQsVUFBVSxTQUFTLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3RELElBQ0UsS0FBSyxZQUFZLGNBQWM7b0JBQy9CLEtBQUssQ0FBQyxZQUFZLEVBQUU7b0JBQ3BCLEtBQUssQ0FBQyxZQUFZLEVBQUcsQ0FBQyxhQUFhLEVBQUUsRUFDckMsQ0FBQztvQkFDRCxNQUFNLElBQUk7OEJBQ1UsU0FBUyxLQUFLLEVBQUUsQ0FBQyxtQkFBbUIsQ0FDdEQsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUNyQixJQUFJLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFHLENBQUMsSUFBSSxDQUFDO2dCQUMzRCxDQUFDO2dCQUNELE1BQU0sSUFBSTtXQUNQLEtBQUssQ0FBQyxPQUFPLEVBQUUsTUFBTSxTQUFTO0lBQ3JDLENBQUM7WUFDQyxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxjQUFjLENBQUMsTUFBYztRQUNuQyxJQUFJLE1BQU0sR0FBRzs7O0NBR2hCLENBQUM7UUFDRSxLQUFLLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDO1lBQzFDLE1BQU0sSUFBSTs7V0FFTCxFQUFFLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQzs7SUFFM0IsQ0FBQztRQUNELENBQUM7UUFFRCxpR0FBaUc7UUFDakcsS0FBSyxNQUFNLEVBQUUsSUFBSSxNQUFNLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztZQUN6QyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO2dCQUNyQixLQUFLLE1BQU0sR0FBRyxJQUFJLEVBQUUsQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDO29CQUN0QyxNQUFNLElBQUk7O1dBRVQsRUFBRSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUM7O0lBRTNCLENBQUM7Z0JBQ0csQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBR0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLE9BQU8sQ0FBQyxNQUFjO1FBQzVCLElBQUksTUFBTSxHQUFHOzs7Ozs7Ozs7eUJBU1EsQ0FBQztRQUN0QixLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUM7WUFDdEQsTUFBTSxjQUFjLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pELE1BQU0sSUFBSTthQUNILElBQUksQ0FBQyxZQUFZLElBQUksY0FBYztzQkFDMUIsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQzlDLENBQUM7UUFDRCxNQUFNLElBQUk7OztJQUdWLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sT0FBTyxDQUFDLE1BQWM7UUFDNUIsSUFBSSxNQUFNLEdBQUc7Ozs7Ozs7Ozs7eUJBVVEsQ0FBQztRQUN0QixLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUM7WUFDdEQsTUFBTSxjQUFjLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pELE1BQU0sSUFBSTthQUNILElBQUksQ0FBQyxZQUFZLElBQUksY0FBYyxHQUFHLENBQUM7WUFFOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO2dCQUN0QixNQUFNLElBQUk7ZUFDSCxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQztnQkFDckIsQ0FBQztZQUNYLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLElBQUk7ZUFDSCxNQUFNO2VBQ04sTUFBTTtnQkFDTCxDQUFDO1lBQ1gsQ0FBQztRQUNILENBQUM7UUFDRCxNQUFNLElBQUk7OztJQUdWLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sU0FBUyxDQUFDLE1BQWM7UUFDOUIsSUFBSSxNQUFNLEdBQUc7Ozs7Ozs7Ozs7eUJBVVEsQ0FBQztRQUN0QixLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUM7WUFDdEQsTUFBTSxjQUFjLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pELE1BQU0sSUFBSTthQUNILElBQUksQ0FBQyxZQUFZLElBQUksY0FBYyxHQUFHLENBQUM7WUFDOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO2dCQUN0QixNQUFNLElBQUk7c0JBQ0ksRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDO1lBQ3BELENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLElBQUk7dUJBQ0ssTUFBTSxlQUFlLENBQUM7WUFDdkMsQ0FBQztRQUNILENBQUM7UUFDRCxNQUFNLElBQUk7OztJQUdWLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sU0FBUyxDQUFDLE1BQWM7UUFDOUIsSUFBSSxNQUFNLEdBQUc7Ozs7Ozs7Ozs7eUJBVVEsQ0FBQztRQUN0QixLQUFLLE1BQU0sT0FBTyxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUM7WUFDdEQsTUFBTSxjQUFjLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pELE1BQU0sSUFBSTthQUNILElBQUksQ0FBQyxZQUFZLElBQUksY0FBYyxHQUFHLENBQUM7WUFDOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO2dCQUN0QixNQUFNLElBQUk7ZUFDSCxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQztnQkFDckIsQ0FBQztZQUNYLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLElBQUk7ZUFDSCxNQUFNO2dCQUNMLENBQUM7WUFDWCxDQUFDO1FBQ0gsQ0FBQztRQUNELE1BQU0sSUFBSTs7O0lBR1YsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxjQUFjLENBQUMsTUFBYztRQUNuQyxJQUFJLE1BQU0sR0FBRzs7Z0NBRWUsQ0FBQztRQUM3QixJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDcEIsS0FBSyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxDQUFDO1lBQ2hELElBQUksQ0FBQyxZQUFZLGNBQWMsRUFBRSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO29CQUN4QyxJQUFJLFdBQVcsS0FBSyxDQUFDLEVBQUUsQ0FBQzt3QkFDdEIsTUFBTSxJQUFJOzt5QkFFRyxDQUFDO29CQUNoQixDQUFDO29CQUNELHdGQUF3RjtvQkFDeEYsTUFBTSxJQUFJO2FBQ1AsSUFBSSxDQUFDLFlBQVksSUFBSSxFQUFFLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztvQkFDdkQsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQzt3QkFDZixNQUFNLElBQUk7dUNBQ2lCLEVBQUUsQ0FBQyxVQUFVLENBQ3RDLENBQUMsQ0FDRix5QkFBeUIsQ0FBQztvQkFDN0IsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLElBQUksQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7NEJBQ3JCLE1BQU0sb0JBQW9CLEdBQUcsR0FDM0IsSUFBSSxDQUFDLFlBQ1AsSUFBSSxFQUFFLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLFlBQVksRUFBRyxDQUFDLEVBQUUsQ0FBQzs0QkFDbEQsTUFBTSxJQUFJO21CQUNMLENBQUMsQ0FBQyxPQUFPLEVBQUU7aUJBQ2IsQ0FBQyxDQUFDLE9BQU8sRUFBRTs7Y0FFZCxvQkFBb0I7YUFDckIsQ0FBQzt3QkFDRixDQUFDO3dCQUNELE1BQU0sSUFBSTsyQkFDSyxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDOzZCQUNqRCxRQUFRLEVBQUU7NkJBQ1YsT0FBTyxFQUFFLGFBQWEsQ0FBQztvQkFDNUIsQ0FBQztvQkFDRCxXQUFXLEVBQUUsQ0FBQztnQkFDaEIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDcEIsTUFBTSxJQUFJOzs7SUFHWixDQUFDO1FBQ0QsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxNQUFjO1FBQ3RDLElBQUksTUFBTSxHQUFHOzs7a0NBR2lCLENBQUM7UUFDL0IsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLEtBQUssTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLHNCQUFzQixFQUFFLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsWUFBWSxjQUFjLEVBQUUsQ0FBQztnQkFDaEMsSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztvQkFDeEMsSUFBSSxXQUFXLEtBQUssQ0FBQyxFQUFFLENBQUM7d0JBQ3RCLE1BQU0sSUFBSTs7eUJBRUcsQ0FBQztvQkFDaEIsQ0FBQztvQkFDRCxNQUFNLElBQUk7YUFDUCxJQUFJLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO29CQUN2RCxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO3dCQUNmLE1BQU0sSUFBSTt1Q0FDaUIsRUFBRSxDQUFDLFVBQVUsQ0FDdEMsQ0FBQyxDQUNGLDRCQUE0QixDQUFDO29CQUNoQyxDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxJQUFJOzJCQUNLLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUM7b0JBQ2hFLENBQUM7b0JBQ0QsV0FBVyxFQUFFLENBQUM7Z0JBQ2hCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksV0FBVyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSTs7O0lBR1osQ0FBQztRQUNELENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFUGFja2FnZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZXBhY2thZ2UuanMnO1xyXG5pbXBvcnQgeyBFQ2xhc3NpZmllciB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZWNsYXNzaWZpZXIuanMnO1xyXG5pbXBvcnQgeyBFQ2xhc3MgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VjbGFzcy5qcyc7XHJcbmltcG9ydCB7IEVSZWZlcmVuY2UgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VyZWZlcmVuY2UuanMnO1xyXG5pbXBvcnQgeyBUR2VuVXRpbHMgYXMgRFUgfSBmcm9tICcuL3RnZW4tdXRpbHMuanMnO1xyXG5pbXBvcnQgeyBUVXRpbHMgfSBmcm9tICcuLi90dXRpbHMuanMnO1xyXG5pbXBvcnQgeyBFU3RydWN0dXJhbEZlYXR1cmUgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VzdHJ1Y3R1cmFsLWZlYXR1cmUuanMnO1xyXG5pbXBvcnQgeyBFUmVmZXJlbmNlSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VyZWZlcmVuY2UtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVDbGFzc0ltcGwgfSBmcm9tICcuLi9tZXRhbW9kZWwvaW1wbC9lY2xhc3MtaW1wbC5qcyc7XHJcblxyXG4vKipcclxuICogU291cmNlIGNvZGUgZ2VuZXJhdGlvbiBmb3IgKmdlbi50cyBmaWxlcyBmb3IgRUNsYXNzZXMuXHJcbiAqXHJcbiAqIEBhdXRob3IgZHR1b2h5XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVEdlbmVyYXRvckdlbiB7XHJcbiAgcHJpdmF0ZSBfcGtnITogRVBhY2thZ2U7XHJcbiAgcHJpdmF0ZSBfcGFja2FnZU5hbWUhOiBzdHJpbmc7XHJcblxyXG4gIC8qKlxyXG4gICAqIEdlbmVyYXRlcyBhIHRlbXBsYXRlIHN0cmluZyBjb250YWluaW5nIGFsbCBzb3VyY2UgY29kZSBmb3IgdGhlICpnZW4udHNcclxuICAgKiBmaWxlIGZvciB0aGUgZ2l2ZW4gRUNsYXNzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGVDbGFzc1xyXG4gICAqIEBwYXJhbSB0b0ltcG9ydFxyXG4gICAqIEBwYXJhbSBnZW5Ub0ltcG9ydFxyXG4gICAqIEBwYXJhbSBwa2dUb0ltcG9ydFxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZW5lcmF0ZShcclxuICAgIGVDbGFzczogRUNsYXNzLFxyXG4gICAgdG9JbXBvcnQ6IFNldDxFQ2xhc3NpZmllcj4sXHJcbiAgICBnZW5Ub0ltcG9ydDogU2V0PEVDbGFzc2lmaWVyPixcclxuICAgIHBrZ1RvSW1wb3J0OiBTZXQ8RVBhY2thZ2U+XHJcbiAgKTogc3RyaW5nIHtcclxuICAgIHRoaXMuX3BrZyA9IGVDbGFzcy5nZXRFUGFja2FnZSgpO1xyXG4gICAgdGhpcy5fcGFja2FnZU5hbWUgPSBEVS5nZW5QYWNrYWdlQ2xhc3NOYW1lKHRoaXMuX3BrZyk7XHJcbiAgICBjb25zdCBnZW5DbGFzc05hbWUgPSBEVS5nZW5HZW5DbGFzc05hbWUoZUNsYXNzKTtcclxuICAgIGNvbnN0IGFwaUNsYXNzTmFtZSA9IGVDbGFzcy5nZXROYW1lKCk7XHJcblxyXG4gICAgcmV0dXJuIGAke3RoaXMuZ2VuZXJhdGVBbGxJbXBvcnRTdGF0ZW1lbnRzKFxyXG4gICAgICBlQ2xhc3MsXHJcbiAgICAgIHRvSW1wb3J0LFxyXG4gICAgICBnZW5Ub0ltcG9ydCxcclxuICAgICAgcGtnVG9JbXBvcnRcclxuICAgICl9XHJcblxyXG4vL21ha2Ugc3VyZSBwYWNrYWdlIGlzIGluaXRpYWxpemVkXHJcbiR7dGhpcy5fcGFja2FnZU5hbWV9LmVJTlNUQU5DRTtcclxuXHJcbi8qKlxyXG4gKiBUaGlzIGZpbGUgaXMgc291cmNlLWNvZGUgZ2VuZXJhdGVkIGFuZCBzaG91bGQgbmV2ZXIgYmUgZWRpdGVkLiBJdCBpbXBsZW1lbnRzXHJcbiAqIHRoZSBjb3JlIFRNRiBmdW5jdGlvbmFsaXR5IGZvciAke2VDbGFzcy5nZXROYW1lKCl9LlxyXG4gKi9cclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzICR7Z2VuQ2xhc3NOYW1lfSAke3RoaXMuZ2VuZXJhdGVFeHRlbmRzKFxyXG4gICAgICBlQ2xhc3NcclxuICAgICl9IGltcGxlbWVudHMgJHthcGlDbGFzc05hbWV9IHtcclxuICAvKiogZmVhdHVyZSBkZWNsYXJhdGlvbnMgKi9cclxuJHt0aGlzLmdlbkZlYXR1cmVEZWNsYXJhdGlvbnMoZUNsYXNzKX1cclxuJHt0aGlzLmdlbkNvbnN0cnVjdG9yKGVDbGFzcyl9XHJcbiR7dGhpcy5nZW5HZXR0ZXJzQW5kU2V0dGVycyhlQ2xhc3MpfVxyXG4ke3RoaXMuZ2VuRW9wZXJhdGlvbnMoZUNsYXNzKX1cclxuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICAvLyBTdGFuZGFyZCBFT2JqZWN0IGJlaGF2aW9yXHJcbiR7dGhpcy5nZW5FR2V0KGVDbGFzcyl9XHJcbiR7dGhpcy5nZW5FU2V0KGVDbGFzcyl9XHJcbiR7dGhpcy5nZW5FSXNTZXQoZUNsYXNzKX1cclxuJHt0aGlzLmdlbkVVbnNldChlQ2xhc3MpfVxyXG4ke3RoaXMuZ2VuQmFzaWNTZXR0ZXJzKGVDbGFzcyl9XHJcbiR7dGhpcy5nZW5FSW52ZXJzZUFkZChlQ2xhc3MpfVxyXG4ke3RoaXMuZ2VuRUludmVyc2VSZW1vdmUoZUNsYXNzKX1cclxuXHJcbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgLy8gZUNsYXNzKClcclxuXHJcbiAgcHVibGljIG92ZXJyaWRlIGVDbGFzcygpOiBFQ2xhc3Mge1xyXG4gICAgcmV0dXJuICR7dGhpcy5fcGFja2FnZU5hbWV9LkxpdGVyYWxzLiR7RFUuc25ha2VVcHBlckNhc2UoXHJcbiAgICAgIGVDbGFzcy5nZXROYW1lKClcclxuICAgICl9O1xyXG4gIH1cclxufWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZW5lcmF0ZXMgaW1wb3J0IHN0YXRlbWVudHMgZm9yIGFsbCBBUElzLCBHZW4gY2xhc3Nlc1xyXG4gICAqIGFuZCBwYWNrYWdlcyB0byBpbXBvcnQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gZUNsYXNzXHJcbiAgICogQHBhcmFtIHRvSW1wb3J0XHJcbiAgICogQHBhcmFtIGdlblRvSW1wb3J0XHJcbiAgICogQHBhcmFtIHBrZ1RvSW1wb3J0XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZW5lcmF0ZUFsbEltcG9ydFN0YXRlbWVudHMoXHJcbiAgICBlQ2xhc3M6IEVDbGFzcyxcclxuICAgIHRvSW1wb3J0OiBTZXQ8RUNsYXNzaWZpZXI+LFxyXG4gICAgZ2VuVG9JbXBvcnQ6IFNldDxFQ2xhc3NpZmllcj4sXHJcbiAgICBwa2dUb0ltcG9ydDogU2V0PEVQYWNrYWdlPixcclxuICAgIGFzeW5jPzogYm9vbGVhblxyXG4gICkge1xyXG4gICAgbGV0IGNsYXNzTmFtZSA9IGVDbGFzcy5nZXROYW1lKCk7XHJcbiAgICBpZiAoYXN5bmMpIGNsYXNzTmFtZSArPSAnQXN5bmMnO1xyXG4gICAgY29uc3QgaXNFY29yZSA9IGVDbGFzcy5nZXRFUGFja2FnZSgpLmdldE5hbWUoKSA9PSAnZWNvcmUnO1xyXG5cclxuICAgIGxldCByZXN1bHQgPSBgJHtpc0Vjb3JlID8gRFUuRUNPUkVfREVGQVVMVF9JTVBPUlRTIDogRFUuREVGQVVMVF9JTVBPUlRTfVxyXG4ke0RVLmdlbkFwaUltcG9ydHMoZUNsYXNzLCB0b0ltcG9ydCwgYC4uJHtEVS5BUElfUEFUSH1gKX1cclxuaW1wb3J0IHsgJHt0aGlzLl9wYWNrYWdlTmFtZX0gfSBmcm9tICcuLi8ke0RVLmdlblBhY2thZ2VGaWxlTmFtZShcclxuICAgICAgdGhpcy5fcGtnXHJcbiAgICApfS5qcyc7XHJcbmltcG9ydCB7ICR7Y2xhc3NOYW1lfSB9IGZyb20gJy4uJHtEVS5BUElfUEFUSH0vJHtEVS5nZW5DbGFzc0FwaU5hbWUoXHJcbiAgICAgIGVDbGFzcyxcclxuICAgICAgYXN5bmNcclxuICAgICl9LmpzJztcclxuYDtcclxuXHJcbiAgICAvL2dlbiBhbmQgaW1wbCBjbGFzc2VzIHRoYXQgbmVlZCB0byBiZSBpbXBvcnRlZFxyXG4gICAgZm9yIChjb25zdCBlYyBvZiBnZW5Ub0ltcG9ydCkge1xyXG4gICAgICBpZiAoZWMpIHtcclxuICAgICAgICBsZXQgcGF0aFRvSW1wb3J0ID0gJy4vJztcclxuXHJcbiAgICAgICAgLy9vbmx5IGltcG9ydCBHZW4gYW5kIEltcGwgaWYgaXQgaXMgYW4gRUNsYXNzIChub3QgYW4gRUVudW0pXHJcbiAgICAgICAgaWYgKGVjIGluc3RhbmNlb2YgRUNsYXNzSW1wbCkge1xyXG4gICAgICAgICAgaWYgKGVjLmdldEVQYWNrYWdlKCkgIT09IGVDbGFzcy5nZXRFUGFja2FnZSgpKSB7XHJcbiAgICAgICAgICAgIC8vaWYgcm9vdCBwYWNrYWdlIGlzIHNoYXJlZCwgdGhlIGNsYXNzZXMgYXJlIGFzc3VtZWQgdG8gZXhpc3QgaW4gdGhlIHNhbWUgbGliLCBhbmQgY2FuIGJlIGltcG9ydGVkIHdpdGggcmVsYXRpdmUgcGF0aHNcclxuICAgICAgICAgICAgaWYgKGVjLmdldFJvb3RQYWNrYWdlKCkgPT09IGVDbGFzcy5nZXRSb290UGFja2FnZSgpKSB7XHJcbiAgICAgICAgICAgICAgcGF0aFRvSW1wb3J0ID0gYCR7RFUuZ2V0UGF0aFRvVHlwZUluT3RoZXJQa2coZUNsYXNzLCBlYyl9L2A7XHJcbiAgICAgICAgICAgICAgcmVzdWx0ICs9IGBpbXBvcnQgeyAke2VjLmdldE5hbWUoKX1HZW4gfSBmcm9tICcke1xyXG4gICAgICAgICAgICAgICAgcGF0aFRvSW1wb3J0ICsgJ2dlbi8nICsgRFUuZ2VuQ2xhc3NHZW5OYW1lKDxFQ2xhc3M+ZWMpXHJcbiAgICAgICAgICAgICAgfS5qcyc7XFxuYDtcclxuICAgICAgICAgICAgICByZXN1bHQgKz0gYGltcG9ydCB7ICR7ZWMuZ2V0TmFtZSgpfUltcGwgfSBmcm9tICcke1xyXG4gICAgICAgICAgICAgICAgcGF0aFRvSW1wb3J0ICsgJ2ltcGwvJyArIERVLmdlbkNsYXNzSW1wbE5hbWUoPEVDbGFzcz5lYylcclxuICAgICAgICAgICAgICB9LmpzJztcXG5gO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vb3RoZXJ3aXNlLCB1c2Ugbm9uLXJlbGF0aXZlIHBhdGhzXHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXQVJOSU5HOiBDUk9TUy1QQUNLQUdFIElNUE9SVFMgTk9UIFNVUFBPUlRFRCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXN1bHQgKz0gYGltcG9ydCB7ICR7ZWMuZ2V0TmFtZSgpfUdlbiB9IGZyb20gJy4vJHtEVS5nZW5DbGFzc0dlbk5hbWUoXHJcbiAgICAgICAgICAgICAgZWMgYXMgRUNsYXNzXHJcbiAgICAgICAgICAgICl9LmpzJztcXG5gO1xyXG4gICAgICAgICAgICByZXN1bHQgKz0gYGltcG9ydCB7ICR7ZWMuZ2V0TmFtZSgpfUltcGwgfSBmcm9tICcuLi9pbXBsLyR7RFUuZ2VuQ2xhc3NJbXBsTmFtZShcclxuICAgICAgICAgICAgICBlYyBhcyBFQ2xhc3NcclxuICAgICAgICAgICAgKX0uanMnO1xcbmA7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9hZGQgcGFja2FnZSBpbXBvcnRzIChlLmcuIGZvciByZWZlcmVuY2VzIHRvIHR5cGVzIGluIGV4dGVybmFsIHBhY2thZ2VzKVxyXG4gICAgcmVzdWx0ICs9IERVLmdlbmVyYXRlSW1wb3J0U3RhdGVtZW50c0ZvckV4dGVybmFsUGFja2FnZXMoXHJcbiAgICAgIHBrZ1RvSW1wb3J0LFxyXG4gICAgICB0aGlzLl9wa2csXHJcbiAgICAgICcuLi8nXHJcbiAgICApO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuZXJhdGVFeHRlbmRzKGVjbGFzczogRUNsYXNzKTogc3RyaW5nIHtcclxuICAgIGlmIChlY2xhc3MuZ2V0TmFtZSgpID09ICdFT2JqZWN0JykgcmV0dXJuICcnO1xyXG4gICAgbGV0IHJlc3VsdCA9IGBleHRlbmRzIEVPYmplY3RJbXBsYDtcclxuICAgIGxldCBzdGkgPSAwO1xyXG4gICAgZm9yIChjb25zdCBzdXBlclR5cGUgb2YgZWNsYXNzLmdldEVTdXBlclR5cGVzKCkpIHtcclxuICAgICAgLy9UT0RPOiBBZGQgc3VwcG9ydCBmb3IgbXVsdGlwbGUtaW5oZXJpdGFuY2Ugb24gaW1wbGVtZW50YXRpb24gY2xhc3M/XHJcbiAgICAgIGlmIChzdGkgPT09IDApIHtcclxuICAgICAgICBpZiAoIXN1cGVyVHlwZS5pc0ludGVyZmFjZSgpKSB7XHJcbiAgICAgICAgICByZXN1bHQgPSBgIGV4dGVuZHMgJHtzdXBlclR5cGUuZ2V0TmFtZSgpfUltcGxgO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBzdGkrKztcclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbkZlYXR1cmVEZWNsYXJhdGlvbnMoZWNsYXNzOiBFQ2xhc3MpIHtcclxuICAgIGxldCBzb3VyY2VDb250ZW50ID0gYGA7XHJcbiAgICBmb3IgKGNvbnN0IGYgb2YgZWNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKSkge1xyXG4gICAgICBjb25zdCB0eXBlTmFtZSA9IERVLmdldFR5cGVOYW1lKGYpO1xyXG4gICAgICBsZXQgaW5pdGlhbGl6ZXIgPSAnJztcclxuICAgICAgaWYgKGYuaXNNYW55KCkpIHtcclxuICAgICAgICAvL2dldCBmZWF0dXJlIElEIGZvciBpbnZlcnNlIHJlZmVyZW5jZSwgaWYgc3BlY2lmaWVkXHJcbiAgICAgICAgbGV0IGludmVyc2VGZWF0dXJlSWQgPSAndW5kZWZpbmVkJztcclxuICAgICAgICBpZiAoZiBpbnN0YW5jZW9mIEVSZWZlcmVuY2VJbXBsKSB7XHJcbiAgICAgICAgICBpZiAoZi5nZXRFT3Bwb3NpdGUoKSkge1xyXG4gICAgICAgICAgICBjb25zdCBvcHBSZWYgPSBmLmdldEVPcHBvc2l0ZSgpO1xyXG5cclxuICAgICAgICAgICAgaWYob3BwUmVmKXtcclxuICAgICAgICAgICAgICBpbnZlcnNlRmVhdHVyZUlkID0gYCR7RFUuZ2VuUGFja2FnZUNsYXNzTmFtZShcclxuICAgICAgICAgICAgICAgIG9wcFJlZi5nZXRFQ29udGFpbmluZ0NsYXNzKCkuZ2V0RVBhY2thZ2UoKVxyXG4gICAgICAgICAgICAgICl9LiR7RFUuZ2VuRmVhdHVyZUlkRmllbGROYW1lKG9wcFJlZil9YDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICAvL2xpc3QgaXMgaW5pdGlhbGl6ZWQgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBvd25pbmcgb2JqZWN0LCB0aGVcclxuICAgICAgICAvL2ZpZWxkIGl0IHJlcHJlc2VudHMsIGFuZCBhbnkgaW52ZXJzZSBmaWVsZFxyXG4gICAgICAgIGluaXRpYWxpemVyICs9IGAgPSBuZXcgQmFzaWMke3R5cGVOYW1lfShcclxuICAgIHVuZGVmaW5lZCxcclxuICAgIHRoaXMsXHJcbiAgICAke3RoaXMuX3BhY2thZ2VOYW1lfS4ke0RVLmdlbkZlYXR1cmVJZEZpZWxkTmFtZShmKX0sXHJcbiAgICAke2ludmVyc2VGZWF0dXJlSWR9XHJcbiAgKWA7XHJcbiAgICAgIH1cclxuICAgICAgLy9UT0RPOiBvbmx5IGFkZCAnIScgaXMgZmVhdHVyZSBpcyBtYXJrZWQgYXMgcmVxdWlyZWQgKGxvd2VyQm91bmQgPSAxKVxyXG5cclxuICAgICAgbGV0IG9wdGlvbmFsaXR5T3BlcmF0b3IgPSBmLmlzTWFueSgpID8gJycgOiAnISc7XHJcblxyXG4gICAgICBzb3VyY2VDb250ZW50ICs9IGAgIHByb3RlY3RlZCAke2YuZ2V0TmFtZSgpfSR7b3B0aW9uYWxpdHlPcGVyYXRvcn06ICR7dHlwZU5hbWV9JHtpbml0aWFsaXplcn07XFxuYDtcclxuICAgIH1cclxuICAgIHJldHVybiBzb3VyY2VDb250ZW50O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZW5Db25zdHJ1Y3RvcihlQ2xhc3M6IEVDbGFzcyk6IHN0cmluZyB7XHJcbiAgICAvLyBCdWlsZCBzb3J0ZWQgbGlzdCBvZiBhbGwgY29uc3RydWN0b3IgYXJndW1lbnRzXHJcbiAgICBsZXQgYXJnRmllbGRzOiBhbnlbXSA9IFtdO1xyXG5cclxuICAgIC8vIEJ1aWxkIHNvcnRlZCBsaXN0IGNvbnN0cnVjdG9yIGFyZ3VtZW50cyBmcm9tIHBvc3NpYmxlIHN1cGVyVHlwZVxyXG4gICAgY29uc3Qgc3VwZXJGaWVsZHMgOiBhbnlbXSA9IFtdO1xyXG5cclxuICAgIGxldCByZXN1bHQgPSAnJztcclxuICAgIGlmIChhcmdGaWVsZHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAvLyBOb3cgYnVpbGQgdXAgdGhlIGNvbnN0cnVjdG9yIGNvZGUuLi5cclxuICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgIC8vIENvbnN0cnVjdG9yXHJcbiAgICAgIFxyXG4gICAgICBwdWJsaWMgY29uc3RydWN0b3IoYDtcclxuICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiBhcmdGaWVsZHMpIHtcclxuICAgICAgICBpZiAoZmllbGQuaXNNYW55KCkpIHtcclxuICAgICAgICAgIGNvbnN0IHR5cGUgPSBUVXRpbHMuZ2V0VHlwZXNjcmlwdE5hbWUoZmllbGQuZ2V0RVR5cGUoKSk7XHJcbiAgICAgICAgICByZXN1bHQgKz0gYF8ke2ZpZWxkLmdldE5hbWUoKX0/OiBFTGlzdDwke3R5cGV9PiwgYDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29uc3QgdHlwZSA9IFRVdGlscy5nZXRUeXBlc2NyaXB0TmFtZShmaWVsZC5nZXRFVHlwZSgpKTtcclxuICAgICAgICAgIHJlc3VsdCArPSBgXyR7ZmllbGQuZ2V0TmFtZSgpfT86ICR7dHlwZX0sIGA7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIHJlc3VsdCArPSAnKSB7JztcclxuICAgICAgLy8gRGVhbCB3aXRoIGludm9raW5nICdzdXBlciguLi4uKScgaWYgbmVjZXNzYXJ5XHJcbiAgICAgIGlmIChzdXBlckZpZWxkcykge1xyXG4gICAgICAgIHJlc3VsdCArPSAnc3VwZXIoJztcclxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHN1cGVyRmllbGRzKSB7XHJcbiAgICAgICAgICByZXN1bHQgKz0gYF8ke2ZpZWxkLmdldE5hbWUoKX0sIGA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlc3VsdCArPSAnKTsnO1xyXG4gICAgICAgIGFyZ0ZpZWxkcyA9IGFyZ0ZpZWxkcy5maWx0ZXIoKGYpID0+ICFzdXBlckZpZWxkcy5pbmNsdWRlcyhmKSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmVzdWx0ICs9ICdzdXBlcigpOyc7XHJcbiAgICAgIH1cclxuICAgICAgLy8gRGVhbCB3aXRoIHNldHRpbmcgdGhlIHJlbWFpbmluZyAobG9jYWxseSBkZWZpbmVkKSBmaWVsZHNcclxuICAgICAgZm9yIChjb25zdCBmaWVsZCBvZiBhcmdGaWVsZHMpIHtcclxuICAgICAgICBpZiAoZmllbGQuaXNNYW55KCkpIHtcclxuICAgICAgICAgIGNvbnN0IGVMaXN0VmFyID0gZmllbGQuZ2V0TmFtZSgpICsgJ0VMaXN0JztcclxuICAgICAgICAgIHJlc3VsdCArPSBgaWYgKF8ke2ZpZWxkLmdldE5hbWUoKX0pIHtcclxuICAgICAgICAgICAgY29uc3QgJHtlTGlzdFZhcn0gPSB0aGlzLiR7RFUuZ2V0dGVyTmFtZShmaWVsZCl9KCk7XHJcbiAgICAgICAgICAgIGZvcihjb25zdCB2YWwgb2YgXyR7ZmllbGQuZ2V0TmFtZSgpfSkgeyAke2VMaXN0VmFyfS5hZGQodmFsKTsgfVxyXG4gICAgICAgICAgfWA7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHJlc3VsdCArPSBgdGhpcy4ke0RVLnNldHRlck5hbWUoZmllbGQpfShfJHtmaWVsZC5nZXROYW1lKCl9KTtgO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICByZXN1bHQgKz0gJ30nO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuR2V0dGVyc0FuZFNldHRlcnMoZUNsYXNzOiBFQ2xhc3MpOiBzdHJpbmcge1xyXG4gICAgbGV0IHJlc3VsdCA9IGBcclxuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICAvLyBHZXR0ZXJzIGFuZCBTZXR0ZXJzXHJcbmA7XHJcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkpIHtcclxuICAgICAgcmVzdWx0ICs9IHRoaXMuZ2VuR2V0dGVyKGVDbGFzcywgZmllbGQpO1xyXG4gICAgICByZXN1bHQgKz0gdGhpcy5nZW5TZXR0ZXIoZUNsYXNzLCBmaWVsZCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZW5HZXR0ZXIoZUNsYXNzOiBFQ2xhc3MsIGZpZWxkOiBFU3RydWN0dXJhbEZlYXR1cmUpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgdmlzaWJpbGl0eSA9ICdwdWJsaWMnO1xyXG4gICAgbGV0IHJlc3VsdCA9IGBcclxuXHJcbiAgJHt2aXNpYmlsaXR5fSAke0RVLmdldHRlclNpZyhmaWVsZCl9IHtgO1xyXG4gICAgaWYgKGZpZWxkLmlzVm9sYXRpbGUoKSkge1xyXG4gICAgICByZXN1bHQgKz0gYFxyXG4gICAgdGhyb3cgbmV3IEVycm9yKFxyXG4gICAgICAnVW5zdXBwb3J0ZWQgb3BlcmF0aW9uIG9uIHZvbGF0aWxlIGZpZWxkLiBPdmVycmlkZSBpbiAke2VDbGFzcy5nZXROYW1lKCl9SW1wbC4nXHJcbiAgICApO2A7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXN1bHQgKz0gYFxyXG4gICAgcmV0dXJuIHRoaXMuJHtmaWVsZC5nZXROYW1lKCl9O2A7XHJcbiAgICB9XHJcbiAgICByZXN1bHQgKz0gYFxyXG4gIH1gOyAvLyBFbmQgb2YgR2V0dGVyIGRlZmluaXRpb25cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlblNldHRlcihlQ2xhc3M6IEVDbGFzcywgZmllbGQ6IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IHN0cmluZyB7XHJcbiAgICBsZXQgcmVzdWx0ID0gYGA7XHJcbiAgICBpZiAoIWZpZWxkLmlzTWFueSgpKSB7XHJcbiAgICAgIGNvbnN0IHBhcmFtTmFtZSA9IERVLnNldHRlclBhcmFtTmFtZShmaWVsZCk7XHJcbiAgICAgIGNvbnN0IHZpc2liaWxpdHkgPSBmaWVsZC5pc0NoYW5nZWFibGUoKSA/ICdwdWJsaWMnIDogJ3ByaXZhdGUnO1xyXG4gICAgICByZXN1bHQgKz0gYFxyXG5cclxuICAke3Zpc2liaWxpdHl9ICR7RFUuc2V0dGVyU2lnKGZpZWxkKX0ge2A7XHJcbiAgICAgIGlmIChmaWVsZC5pc1ZvbGF0aWxlKCkpIHtcclxuICAgICAgICByZXN1bHQgKz0gYFxyXG4gICAgdGhyb3cgbmV3IEVycm9yKFxyXG4gICAgICAnVW5zdXBwb3J0ZWQgb3BlcmF0aW9uIG9uIHZvbGF0aWxlIGZpZWxkLiBPdmVycmlkZSBpbiAke2VDbGFzcy5nZXROYW1lKCl9SW1wbC4nXHJcbiAgICApO2A7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy9oYW5kbGUgY29udGFpbm1lbnQgZW5mb3JjZW1lbnQgaWYgYXBwcm9wcmlhdGVcclxuICAgICAgICBpZiAoZmllbGQgaW5zdGFuY2VvZiBFUmVmZXJlbmNlSW1wbCAmJiBmaWVsZC5pc0NvbnRhaW5tZW50KCkpIHtcclxuICAgICAgICAgIGNvbnN0IG9sZFZhciA9ICdvbGQnICsgRFUuY2FwaXRhbGl6ZShmaWVsZC5nZXROYW1lKCkpO1xyXG4gICAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgIGNvbnN0ICR7b2xkVmFyfSA9IHRoaXMuJHtmaWVsZC5nZXROYW1lKCl9O1xyXG4gICAgaWYgKCR7b2xkVmFyfSkgJHtvbGRWYXJ9LnNldEVDb250YWluZXIodW5kZWZpbmVkLCB1bmRlZmluZWQpO1xyXG4gICAgaWYgKCR7cGFyYW1OYW1lfSkgJHtwYXJhbU5hbWV9LnNldEVDb250YWluZXIodGhpcywgJHtEVS5nZW5QYWNrYWdlQ2xhc3NOYW1lKFxyXG4gICAgICAgICAgICB0aGlzLl9wa2dcclxuICAgICAgICAgICl9LiR7RFUuZ2VuRmVhdHVyZUlkRmllbGROYW1lKGZpZWxkKX0pO2A7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vaGFuZGxlIGludmVyc2UgcmVmZXJlbmNlcyBpZiBhcHByb3ByaWF0ZVxyXG4gICAgICAgIGlmIChmaWVsZCBpbnN0YW5jZW9mIEVSZWZlcmVuY2VJbXBsICYmIGZpZWxkLmdldEVPcHBvc2l0ZSgpKSB7XHJcbiAgICAgICAgICAvL1RPRE86IGhhbmRsZSBvcHBvc2l0ZXMgaW4gb3RoZXIgcGFja2FnZXM/XHJcbiAgICAgICAgICBjb25zdCBvcHBvc2l0ZUlkRmllbGQgPSBgJHtcclxuICAgICAgICAgICAgdGhpcy5fcGFja2FnZU5hbWVcclxuICAgICAgICAgIH0uJHtEVS5nZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmllbGQuZ2V0RU9wcG9zaXRlKCkhKX1gO1xyXG4gICAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgIGlmICh0aGlzLiR7ZmllbGQuZ2V0TmFtZSgpfSAhPT0gJHtwYXJhbU5hbWV9KSB7XHJcbiAgICAgIGlmICh0aGlzLiR7ZmllbGQuZ2V0TmFtZSgpfSkge1xyXG4gICAgICAgIHRoaXMuJHtmaWVsZC5nZXROYW1lKCl9LmVJbnZlcnNlUmVtb3ZlKHRoaXMsICR7b3Bwb3NpdGVJZEZpZWxkfSk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKCR7cGFyYW1OYW1lfSkge1xyXG4gICAgICAgICR7cGFyYW1OYW1lfS5lSW52ZXJzZUFkZCh0aGlzLCAke29wcG9zaXRlSWRGaWVsZH0pO1xyXG4gICAgICB9XHJcbiAgICB9YDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgIHRoaXMuYmFzaWMke0RVLmNhcGl0YWxpemUoRFUuc2V0dGVyTmFtZShmaWVsZCkpfSgke3BhcmFtTmFtZX0pO2A7XHJcbiAgICAgICAgLy8gc291cmNlQ29udGVudCArPSBgdGhpcy4ke2YuZ2V0TmFtZSgpfSA9ICR7cGFyYW1OYW1lfTt9YDtcclxuICAgICAgfVxyXG4gICAgICByZXN1bHQgKz0gYFxyXG4gIH1gOyAvLyBFbmQgb2YgU2V0dGVyIGRlZmluaXRpb25cclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbkJhc2ljU2V0dGVycyhlQ2xhc3M6IEVDbGFzcyk6IHN0cmluZyB7XHJcbiAgICBsZXQgcmVzdWx0ID0gYFxyXG4gIC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gIC8vIEJhc2ljIHNldHRlcnMgKGFsbG93IEVPcHBvc2l0ZSBlbmZvcmNlbWVudCB3aXRob3V0IHRyaWdnZXJpbmcgaW5maW5pdGUgY3ljbGVzKVxyXG5gO1xyXG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiBlQ2xhc3MuZ2V0RVN0cnVjdHVyYWxGZWF0dXJlcygpKSB7XHJcbiAgICAgIC8vb25seSBpbmNsdWRlIGJhc2ljIHNldHRlcnMgZm9yIGludGVybmFsIHJlZmVyZW5jZXNcclxuICAgICAgaWYgKCFmaWVsZC5pc01hbnkoKSAmJiAhZmllbGQuaXNWb2xhdGlsZSgpKSB7XHJcbiAgICAgICAgY29uc3QgdmlzaWJpbGl0eSA9IGZpZWxkLmlzQ2hhbmdlYWJsZSgpID8gJ3B1YmxpYycgOiAncHJpdmF0ZSc7XHJcbiAgICAgICAgY29uc3QgcGFyYW1OYW1lID0gRFUuc2V0dGVyUGFyYW1OYW1lKGZpZWxkKTtcclxuICAgICAgICByZXN1bHQgKz0gYFxyXG5cclxuICAke3Zpc2liaWxpdHl9IGJhc2ljJHtEVS5jYXBpdGFsaXplKERVLnNldHRlclNpZyhmaWVsZCkpfSB7YDtcclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICBmaWVsZCBpbnN0YW5jZW9mIEVSZWZlcmVuY2VJbXBsICYmXHJcbiAgICAgICAgICBmaWVsZC5nZXRFT3Bwb3NpdGUoKSAmJlxyXG4gICAgICAgICAgZmllbGQuZ2V0RU9wcG9zaXRlKCkhLmlzQ29udGFpbm1lbnQoKVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgIHRoaXMuZUJhc2ljU2V0Q29udGFpbmVyKCR7cGFyYW1OYW1lfSwgJHtEVS5nZW5QYWNrYWdlQ2xhc3NOYW1lKFxyXG4gICAgICAgICAgICBlQ2xhc3MuZ2V0RVBhY2thZ2UoKVxyXG4gICAgICAgICAgKX0uJHtEVS5nZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmllbGQuZ2V0RU9wcG9zaXRlKCkhKX0pO2A7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlc3VsdCArPSBgXHJcbiAgICB0aGlzLiR7ZmllbGQuZ2V0TmFtZSgpfSA9ICR7cGFyYW1OYW1lfTtcclxuICB9YDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuRW9wZXJhdGlvbnMoZUNsYXNzOiBFQ2xhc3MpIHtcclxuICAgIGxldCByZXN1bHQgPSBgXHJcbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgLy8gQVBJIE9wZXJhdGlvbnNcclxuYDtcclxuICAgIGZvciAoY29uc3QgZW9wIG9mIGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpKSB7XHJcbiAgICAgIHJlc3VsdCArPSBgXHJcblxyXG4gIHB1YmxpYyAke0RVLmVvcFNpZ25hdHVyZShlb3ApfSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xyXG4gIH1gO1xyXG4gICAgfVxyXG5cclxuICAgIC8vaWYgdGhpcyBjbGFzcyBkaXJlY3RseSBpbmhlcml0cyBmcm9tIGFuIGludGVyZmFjZSwgbmVlZCB0byBhZGQgaW1wbGVtZW50YXRpb25zIG9mIHRob3NlIGFzIHdlbGxcclxuICAgIGZvciAoY29uc3Qgc3Qgb2YgZUNsYXNzLmdldEVTdXBlclR5cGVzKCkpIHtcclxuICAgICAgaWYgKHN0LmlzSW50ZXJmYWNlKCkpIHtcclxuICAgICAgICBmb3IgKGNvbnN0IGVvcCBvZiBzdC5nZXRFT3BlcmF0aW9ucygpKSB7XHJcbiAgICAgICAgICByZXN1bHQgKz0gYFxyXG5cclxuICBwdWJsaWMgJHtEVS5lb3BTaWduYXR1cmUoZW9wKX0ge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcclxuICB9YDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcblxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuRUdldChlQ2xhc3M6IEVDbGFzcyk6IHN0cmluZyB7XHJcbiAgICBsZXQgcmVzdWx0ID0gYFxyXG4gIC8qKlxyXG4gICAqIGVHZXQoKSAtIHByb3ZpZGVzIHJlZmxlY3RpdmUgYWNjZXNzIHRvIGFsbCBmZWF0dXJlcy5cclxuICAgKi9cclxuICBwdWJsaWMgb3ZlcnJpZGUgZUdldChmZWF0dXJlOiBudW1iZXIgfCBFU3RydWN0dXJhbEZlYXR1cmUpOiBhbnkge1xyXG4gICAgY29uc3QgZmVhdHVyZUlEOiBudW1iZXIgPVxyXG4gICAgICB0eXBlb2YgZmVhdHVyZSA9PT0gJ251bWJlcidcclxuICAgICAgICA/IGZlYXR1cmVcclxuICAgICAgICA6ICg8RVN0cnVjdHVyYWxGZWF0dXJlPmZlYXR1cmUpLmdldEZlYXR1cmVJRCgpO1xyXG4gICAgc3dpdGNoIChmZWF0dXJlSUQpIHtgO1xyXG4gICAgZm9yIChjb25zdCBmZWF0dXJlIG9mIGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkpIHtcclxuICAgICAgY29uc3QgZmVhdHVyZUlkRmllbGQgPSBEVS5nZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmVhdHVyZSk7XHJcbiAgICAgIHJlc3VsdCArPSBgXHJcbiAgICAgIGNhc2UgJHt0aGlzLl9wYWNrYWdlTmFtZX0uJHtmZWF0dXJlSWRGaWVsZH06XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuJHtEVS5nZXR0ZXJOYW1lKGZlYXR1cmUpfSgpO2A7XHJcbiAgICB9XHJcbiAgICByZXN1bHQgKz0gYFxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHN1cGVyLmVHZXQoZmVhdHVyZUlEKTtcclxuICB9YDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbkVTZXQoZUNsYXNzOiBFQ2xhc3MpOiBzdHJpbmcge1xyXG4gICAgbGV0IHJlc3VsdCA9IGBcclxuXHJcbiAgLyoqXHJcbiAgICogZVNldCgpIC0gcHJvdmlkZXMgYWJpbGl0eSB0byByZWZsZWN0aXZlbHkgc2V0IGFsbCBmZWF0dXJlcy5cclxuICAgKi9cclxuICBwdWJsaWMgb3ZlcnJpZGUgZVNldChmZWF0dXJlOiBudW1iZXIgfCBFU3RydWN0dXJhbEZlYXR1cmUsIG5ld1ZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgIGNvbnN0IGZlYXR1cmVJRDogbnVtYmVyID1cclxuICAgICAgdHlwZW9mIGZlYXR1cmUgPT09ICdudW1iZXInXHJcbiAgICAgICAgPyBmZWF0dXJlXHJcbiAgICAgICAgOiAoPEVTdHJ1Y3R1cmFsRmVhdHVyZT5mZWF0dXJlKS5nZXRGZWF0dXJlSUQoKTtcclxuICAgIHN3aXRjaCAoZmVhdHVyZUlEKSB7YDtcclxuICAgIGZvciAoY29uc3QgZmVhdHVyZSBvZiBlQ2xhc3MuZ2V0RVN0cnVjdHVyYWxGZWF0dXJlcygpKSB7XHJcbiAgICAgIGNvbnN0IGZlYXR1cmVJZEZpZWxkID0gRFUuZ2VuRmVhdHVyZUlkRmllbGROYW1lKGZlYXR1cmUpO1xyXG4gICAgICByZXN1bHQgKz0gYFxyXG4gICAgICBjYXNlICR7dGhpcy5fcGFja2FnZU5hbWV9LiR7ZmVhdHVyZUlkRmllbGR9OmA7XHJcblxyXG4gICAgICBpZiAoIWZlYXR1cmUuaXNNYW55KCkpIHtcclxuICAgICAgICByZXN1bHQgKz0gYFxyXG4gICAgICAgIHRoaXMuJHtEVS5zZXR0ZXJOYW1lKGZlYXR1cmUpfShuZXdWYWx1ZSk7XHJcbiAgICAgICAgcmV0dXJuO2A7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29uc3QgZ2V0dGVyID0gRFUuZ2V0dGVyTmFtZShmZWF0dXJlKTtcclxuICAgICAgICByZXN1bHQgKz0gYFxyXG4gICAgICAgIHRoaXMuJHtnZXR0ZXJ9KCkuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLiR7Z2V0dGVyfSgpLmFkZEFsbChuZXdWYWx1ZSk7XHJcbiAgICAgICAgcmV0dXJuO2A7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJlc3VsdCArPSBgXHJcbiAgICB9XHJcbiAgICByZXR1cm4gc3VwZXIuZVNldChmZWF0dXJlSUQsIG5ld1ZhbHVlKTtcclxuICB9YDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbkVJc1NldChlQ2xhc3M6IEVDbGFzcyk6IHN0cmluZyB7XHJcbiAgICBsZXQgcmVzdWx0ID0gYFxyXG5cclxuICAvKipcclxuICAgKiBlSXNTZXQoKSAtIHByb3ZpZGVzIGFiaWxpdHkgdG8gcmVmbGVjdGl2ZWx5IGNoZWNrIGlmIGFueSBmZWF0dXJlIGlzIHNldC5cclxuICAgKi9cclxuICBwdWJsaWMgb3ZlcnJpZGUgZUlzU2V0KGZlYXR1cmU6IG51bWJlciB8IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgZmVhdHVyZUlEOiBudW1iZXIgPVxyXG4gICAgICB0eXBlb2YgZmVhdHVyZSA9PT0gJ251bWJlcidcclxuICAgICAgICA/IGZlYXR1cmVcclxuICAgICAgICA6ICg8RVN0cnVjdHVyYWxGZWF0dXJlPmZlYXR1cmUpLmdldEZlYXR1cmVJRCgpO1xyXG4gICAgc3dpdGNoIChmZWF0dXJlSUQpIHtgO1xyXG4gICAgZm9yIChjb25zdCBmZWF0dXJlIG9mIGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkpIHtcclxuICAgICAgY29uc3QgZmVhdHVyZUlkRmllbGQgPSBEVS5nZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmVhdHVyZSk7XHJcbiAgICAgIHJlc3VsdCArPSBgXHJcbiAgICAgIGNhc2UgJHt0aGlzLl9wYWNrYWdlTmFtZX0uJHtmZWF0dXJlSWRGaWVsZH06YDtcclxuICAgICAgaWYgKCFmZWF0dXJlLmlzTWFueSgpKSB7XHJcbiAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgICByZXR1cm4gdGhpcy4ke0RVLmdldHRlck5hbWUoZmVhdHVyZSl9KCkgIT0gbnVsbDtgO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IGdldHRlciA9IERVLmdldHRlck5hbWUoZmVhdHVyZSk7XHJcbiAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgICByZXR1cm4gIXRoaXMuJHtnZXR0ZXJ9KCkuaXNFbXB0eSgpO2A7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJlc3VsdCArPSBgXHJcbiAgICB9XHJcbiAgICByZXR1cm4gc3VwZXIuZUlzU2V0KGZlYXR1cmVJRCk7XHJcbiAgfWA7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZW5FVW5zZXQoZUNsYXNzOiBFQ2xhc3MpOiBzdHJpbmcge1xyXG4gICAgbGV0IHJlc3VsdCA9IGBcclxuXHJcbiAgLyoqXHJcbiAgICogZVVuc2V0KCkgLSBwcm92aWRlcyBhYmlsaXR5IHRvIHJlZmxlY3RpdmVseSB1bnNldCBhbnkgZmVhdHVyZS5cclxuICAgKi9cclxuICBwdWJsaWMgb3ZlcnJpZGUgZVVuc2V0KGZlYXR1cmU6IG51bWJlciB8IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IHZvaWQge1xyXG4gICAgY29uc3QgZmVhdHVyZUlEOiBudW1iZXIgPVxyXG4gICAgICB0eXBlb2YgZmVhdHVyZSA9PT0gJ251bWJlcidcclxuICAgICAgICA/IGZlYXR1cmVcclxuICAgICAgICA6ICg8RVN0cnVjdHVyYWxGZWF0dXJlPmZlYXR1cmUpLmdldEZlYXR1cmVJRCgpO1xyXG4gICAgc3dpdGNoIChmZWF0dXJlSUQpIHtgO1xyXG4gICAgZm9yIChjb25zdCBmZWF0dXJlIG9mIGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkpIHtcclxuICAgICAgY29uc3QgZmVhdHVyZUlkRmllbGQgPSBEVS5nZW5GZWF0dXJlSWRGaWVsZE5hbWUoZmVhdHVyZSk7XHJcbiAgICAgIHJlc3VsdCArPSBgXHJcbiAgICAgIGNhc2UgJHt0aGlzLl9wYWNrYWdlTmFtZX0uJHtmZWF0dXJlSWRGaWVsZH06YDtcclxuICAgICAgaWYgKCFmZWF0dXJlLmlzTWFueSgpKSB7XHJcbiAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgICB0aGlzLiR7RFUuc2V0dGVyTmFtZShmZWF0dXJlKX0odW5kZWZpbmVkISk7XHJcbiAgICAgICAgcmV0dXJuO2A7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29uc3QgZ2V0dGVyID0gRFUuZ2V0dGVyTmFtZShmZWF0dXJlKTtcclxuICAgICAgICByZXN1bHQgKz0gYFxyXG4gICAgICAgIHRoaXMuJHtnZXR0ZXJ9KCkuY2xlYXIoKTtcclxuICAgICAgICByZXR1cm47YDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmVzdWx0ICs9IGBcclxuICAgIH1cclxuICAgIHJldHVybiBzdXBlci5lVW5zZXQoZmVhdHVyZUlEKTtcclxuICB9YDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbkVJbnZlcnNlQWRkKGVDbGFzczogRUNsYXNzKSB7XHJcbiAgICBsZXQgcmVzdWx0ID0gYFxyXG4gIC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gIC8vIEludmVyc2UgQWRkZXJzIChpZiBuZWVkZWQpYDtcclxuICAgIGxldCBudW1Td2l0Y2hlcyA9IDA7XHJcbiAgICBmb3IgKGNvbnN0IGYgb2YgZUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKSkge1xyXG4gICAgICBpZiAoZiBpbnN0YW5jZW9mIEVSZWZlcmVuY2VJbXBsKSB7XHJcbiAgICAgICAgaWYgKCFmLmlzVm9sYXRpbGUoKSAmJiBmLmdldEVPcHBvc2l0ZSgpKSB7XHJcbiAgICAgICAgICBpZiAobnVtU3dpdGNoZXMgPT09IDApIHtcclxuICAgICAgICAgICAgcmVzdWx0ICs9IGBcclxuICBwdWJsaWMgb3ZlcnJpZGUgZUludmVyc2VBZGQob3RoZXJFbmQ6IEVPYmplY3QsIGZlYXR1cmVJRDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBzd2l0Y2ggKGZlYXR1cmVJRCkge2A7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICAvL1RPRE86IERvIEkgYWxzbyBuZWVkIHRvIGRvIGEgYmFzaWMgcmVtb3ZlIGZyb20gY29udGFpbmVyIGlmIHRoaXMgc2V0cyBhIG5ldyBjb250YWluZXI/XHJcbiAgICAgICAgICByZXN1bHQgKz0gYFxyXG4gICAgICBjYXNlICR7dGhpcy5fcGFja2FnZU5hbWV9LiR7RFUuZ2VuRmVhdHVyZUlkRmllbGROYW1lKGYpfTpgO1xyXG4gICAgICAgICAgaWYgKGYuaXNNYW55KCkpIHtcclxuICAgICAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgICByZXR1cm4gKDxFTGlzdDxFT2JqZWN0Pj50aGlzLiR7RFUuZ2V0dGVyTmFtZShcclxuICAgICAgICAgICAgICBmXHJcbiAgICAgICAgICAgICl9KCkpLmJhc2ljQWRkKG90aGVyRW5kKTtgO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKGYuZ2V0RU9wcG9zaXRlKCkpIHtcclxuICAgICAgICAgICAgICBjb25zdCBvcHBvc2l0ZUZlYXR1cmVGaWVsZCA9IGAke1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fcGFja2FnZU5hbWVcclxuICAgICAgICAgICAgICB9LiR7RFUuZ2VuRmVhdHVyZUlkRmllbGROYW1lKGYuZ2V0RU9wcG9zaXRlKCkhKX1gO1xyXG4gICAgICAgICAgICAgIHJlc3VsdCArPSBgXHJcbiAgICAgICAgaWYgKHRoaXMuJHtmLmdldE5hbWUoKX0pXHJcbiAgICAgICAgICB0aGlzLiR7Zi5nZXROYW1lKCl9LmVJbnZlcnNlUmVtb3ZlKFxyXG4gICAgICAgICAgICB0aGlzLFxyXG4gICAgICAgICAgICAke29wcG9zaXRlRmVhdHVyZUZpZWxkfVxyXG4gICAgICAgICAgKTtgO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJlc3VsdCArPSBgXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYmFzaWMke0RVLmNhcGl0YWxpemUoRFUuc2V0dGVyTmFtZShmKSl9KDwke2ZcclxuICAgICAgICAgICAgICAuZ2V0RVR5cGUoKVxyXG4gICAgICAgICAgICAgIC5nZXROYW1lKCl9Pm90aGVyRW5kKTtgO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgbnVtU3dpdGNoZXMrKztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChudW1Td2l0Y2hlcyA+IDApIHtcclxuICAgICAgcmVzdWx0ICs9IGBcclxuICAgIH1cclxuICAgIHJldHVybiBzdXBlci5lSW52ZXJzZUFkZChvdGhlckVuZCwgZmVhdHVyZUlEKTtcclxuICB9YDtcclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbkVJbnZlcnNlUmVtb3ZlKGVDbGFzczogRUNsYXNzKSB7XHJcbiAgICBsZXQgcmVzdWx0ID0gYFxyXG5cclxuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICAvLyBJbnZlcnNlIFJlbW92ZXJzIChpZiBuZWVkZWQpYDtcclxuICAgIGxldCBudW1Td2l0Y2hlcyA9IDA7XHJcbiAgICBmb3IgKGNvbnN0IGYgb2YgZUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKSkge1xyXG4gICAgICBpZiAoZiBpbnN0YW5jZW9mIEVSZWZlcmVuY2VJbXBsKSB7XHJcbiAgICAgICAgaWYgKCFmLmlzVm9sYXRpbGUoKSAmJiBmLmdldEVPcHBvc2l0ZSgpKSB7XHJcbiAgICAgICAgICBpZiAobnVtU3dpdGNoZXMgPT09IDApIHtcclxuICAgICAgICAgICAgcmVzdWx0ICs9IGBcclxuICBwdWJsaWMgb3ZlcnJpZGUgZUludmVyc2VSZW1vdmUob3RoZXJFbmQ6IEVPYmplY3QsIGZlYXR1cmVJRDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBzd2l0Y2ggKGZlYXR1cmVJRCkge2A7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICByZXN1bHQgKz0gYFxyXG4gICAgICBjYXNlICR7dGhpcy5fcGFja2FnZU5hbWV9LiR7RFUuZ2VuRmVhdHVyZUlkRmllbGROYW1lKGYpfTpgO1xyXG4gICAgICAgICAgaWYgKGYuaXNNYW55KCkpIHtcclxuICAgICAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgICByZXR1cm4gKDxFTGlzdDxFT2JqZWN0Pj50aGlzLiR7RFUuZ2V0dGVyTmFtZShcclxuICAgICAgICAgICAgICBmXHJcbiAgICAgICAgICAgICl9KCkpLmJhc2ljUmVtb3ZlKG90aGVyRW5kKTtgO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmVzdWx0ICs9IGBcclxuICAgICAgICByZXR1cm4gdGhpcy5iYXNpYyR7RFUuY2FwaXRhbGl6ZShEVS5zZXR0ZXJOYW1lKGYpKX0odW5kZWZpbmVkISk7YDtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIG51bVN3aXRjaGVzKys7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAobnVtU3dpdGNoZXMgPiAwKSB7XHJcbiAgICAgIHJlc3VsdCArPSBgXHJcbiAgICB9XHJcbiAgICByZXR1cm4gc3VwZXIuZUludmVyc2VSZW1vdmUob3RoZXJFbmQsIGZlYXR1cmVJRCk7XHJcbiAgfWA7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxufSJdfQ==