@tripsnek/tmf
Version:
TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)
354 lines • 46.8 kB
JavaScript
import { EEnumImpl } from '../metamodel/impl/eenum-impl.js';
import { EClassImpl } from '../metamodel/impl/eclass-impl.js';
import { EDataTypeImpl } from '../metamodel/impl/edata-type-impl.js';
import { EAttributeImpl } from '../metamodel/impl/eattribute-impl.js';
import { TUtils } from '../tutils.js';
/**
* Writes EPackage metamodels to Ecore XML string format.
* This class handles the core writing logic without file system dependencies.
*/
export class EcoreStringWriter {
indentLevel = 0;
indentString = ' ';
/**
* Converts an EPackage to Ecore XML string format.
* @param ePackage The root package to serialize
* @returns The XML string representation
*/
writeToString(ePackage) {
const xml = this.buildPackageXml(ePackage, true);
return `<?xml version="1.0" encoding="UTF-8"?>\n${xml}`;
}
/**
* Builds the XML for a package.
*/
buildPackageXml(ePackage, isRoot = false) {
const indent = this.getIndent();
let xml = '';
if (isRoot) {
// Root package with full namespace declarations
xml = `<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"`;
}
else {
xml = `${indent}<eSubpackages`;
}
// Add package attributes
xml += ` name="${this.escapeXml(ePackage.getName())}"`;
if (ePackage.getNsURI()) {
xml += ` nsURI="${this.escapeXml(ePackage.getNsURI())}"`;
}
if (ePackage.getNsPrefix()) {
xml += ` nsPrefix="${this.escapeXml(ePackage.getNsPrefix())}"`;
}
xml += '>';
this.indentLevel++;
// Add classifiers
for (const classifier of ePackage.getEClassifiers()) {
xml += '\n' + this.buildClassifierXml(classifier, ePackage);
}
// Add subpackages
for (const subPackage of ePackage.getESubPackages()) {
xml += '\n' + this.buildPackageXml(subPackage, false);
}
this.indentLevel--;
if (isRoot) {
xml += '\n</ecore:EPackage>';
}
else {
xml += `\n${indent}</eSubpackages>`;
}
return xml;
}
/**
* Builds the XML for a classifier (EClass, EEnum, or EDataType).
*/
buildClassifierXml(classifier, containingPackage) {
const indent = this.getIndent();
if (classifier instanceof EEnumImpl) {
return this.buildEnumXml(classifier);
}
else if (classifier instanceof EClassImpl) {
return this.buildClassXml(classifier, containingPackage);
}
else if (classifier instanceof EDataTypeImpl) {
return this.buildDataTypeXml(classifier);
}
return '';
}
/**
* Builds the XML for an EClass.
*/
buildClassXml(eClass, containingPackage) {
const indent = this.getIndent();
let xml = `${indent}<eClassifiers xsi:type="ecore:EClass" name="${this.escapeXml(eClass.getName())}"`;
// Add super types if any
const superTypes = eClass.getESuperTypes();
if (superTypes && superTypes.size() > 0) {
const superTypeRefs = [];
for (let i = 0; i < superTypes.size(); i++) {
const superType = superTypes.get(i);
superTypeRefs.push(this.getClassifierReference(superType, containingPackage));
}
xml += ` eSuperTypes="${superTypeRefs.join(' ')}"`;
}
// Add abstract/interface flags if set
if (eClass.isAbstract()) {
xml += ' abstract="true"';
}
if (eClass.isInterface()) {
xml += ' interface="true"';
}
// Check if class has content
const hasFeatures = eClass.getEStructuralFeatures() && eClass.getEStructuralFeatures().size() > 0;
const hasOperations = eClass.getEOperations() && eClass.getEOperations().size() > 0;
if (!hasFeatures && !hasOperations) {
xml += '/>';
return xml;
}
xml += '>';
this.indentLevel++;
// Add operations
if (hasOperations) {
for (let i = 0; i < eClass.getEOperations().size(); i++) {
const operation = eClass.getEOperations().get(i);
xml += '\n' + this.buildOperationXml(operation, containingPackage);
}
}
// Add structural features
if (hasFeatures) {
for (let i = 0; i < eClass.getEStructuralFeatures().size(); i++) {
const feature = eClass.getEStructuralFeatures().get(i);
xml += '\n' + this.buildFeatureXml(feature, containingPackage);
}
}
this.indentLevel--;
xml += `\n${indent}</eClassifiers>`;
return xml;
}
/**
* Builds the XML for an EOperation.
*/
buildOperationXml(operation, containingPackage) {
const indent = this.getIndent();
let xml = `${indent}<eOperations name="${this.escapeXml(operation.getName())}"`;
// Add return type if present
if (operation.getEType()) {
xml += ` eType="${this.getClassifierReference(operation.getEType(), containingPackage)}"`;
}
// Add upper bound if not 1
if (operation.getUpperBound() == -1) {
xml += ` upperBound="${operation.getUpperBound()}"`;
}
// Check if operation has parameters
const hasParameters = operation.getEParameters() && operation.getEParameters().size() > 0;
if (!hasParameters) {
xml += '/>';
return xml;
}
xml += '>';
this.indentLevel++;
// Add parameters
for (let i = 0; i < operation.getEParameters().size(); i++) {
const param = operation.getEParameters().get(i);
xml += '\n' + this.buildParameterXml(param, containingPackage);
}
this.indentLevel--;
xml += `\n${indent}</eOperations>`;
return xml;
}
/**
* Builds the XML for an EParameter.
*/
buildParameterXml(parameter, containingPackage) {
const indent = this.getIndent();
let xml = `${indent}<eParameters name="${this.escapeXml(parameter.getName())}"`;
if (parameter.getUpperBound() == -1) {
xml += ` upperBound="${parameter.getUpperBound()}"`;
}
//TODO: lower bounds for optional parameters? since we can support those in typescript
if (parameter.getEType()) {
xml += ` eType="${this.getClassifierReference(parameter.getEType(), containingPackage)}"`;
}
xml += '/>';
return xml;
}
/**
* Builds the XML for a structural feature (EAttribute or EReference).
*/
buildFeatureXml(feature, containingPackage) {
const indent = this.getIndent();
const isAttribute = feature instanceof EAttributeImpl;
const featureType = isAttribute ? 'ecore:EAttribute' : 'ecore:EReference';
let xml = `${indent}<eStructuralFeatures xsi:type="${featureType}" name="${this.escapeXml(feature.getName())}"`;
// Add type
if (feature.getEType()) {
xml += ` eType="${this.getClassifierReference(feature.getEType(), containingPackage)}"`;
}
//TODO: lowerbound? only seems to make sense if we have 'required' features
if (feature.getUpperBound() == -1) {
xml += ` upperBound="${feature.getUpperBound()}"`;
}
// Add feature-specific attributes
if (isAttribute) {
const attr = feature;
if (attr.isId()) {
xml += ' iD="true"';
}
}
else {
const ref = feature;
if (ref.isContainment()) {
xml += ' containment="true"';
}
if (ref.getEOpposite()) {
xml += ` eOpposite="${this.getFeatureReference(ref.getEOpposite())}"`;
}
}
// Add other properties
if (feature.isTransient()) {
xml += ' transient="true"';
}
// if (feature.isDerived()) {
// xml += ' derived="true"';
// }
if (!feature.isChangeable()) {
xml += ' changeable="false"';
}
if (feature.isVolatile()) {
xml += ' volatile="true"';
}
if (feature.getDefaultValueLiteral()) {
xml += ` defaultValueLiteral="${this.escapeXml(feature.getDefaultValueLiteral())}"`;
}
xml += '/>';
return xml;
}
/**
* Builds the XML for an EEnum.
*/
buildEnumXml(eEnum) {
const indent = this.getIndent();
let xml = `${indent}<eClassifiers xsi:type="ecore:EEnum" name="${this.escapeXml(eEnum.getName())}"`;
const hasLiterals = eEnum.getELiterals() && eEnum.getELiterals().size() > 0;
if (!hasLiterals) {
xml += '/>';
return xml;
}
xml += '>';
this.indentLevel++;
// Add enum literals
for (let i = 0; i < eEnum.getELiterals().size(); i++) {
const literal = eEnum.getELiterals().get(i);
xml += '\n' + this.buildEnumLiteralXml(literal);
}
this.indentLevel--;
xml += `\n${indent}</eClassifiers>`;
return xml;
}
/**
* Builds the XML for an EEnumLiteral.
*/
buildEnumLiteralXml(literal) {
const indent = this.getIndent();
let xml = `${indent}<eLiterals name="${this.escapeXml(literal.getName())}"`;
if (literal.getValue() !== undefined && literal.getValue() !== null) {
xml += ` value="${literal.getValue()}"`;
}
if (literal.getLiteral() && literal.getLiteral() !== literal.getName()) {
xml += ` literal="${this.escapeXml(literal.getLiteral())}"`;
}
xml += '/>';
return xml;
}
/**
* Builds the XML for an EDataType.
*/
buildDataTypeXml(dataType) {
const indent = this.getIndent();
let xml = `${indent}<eClassifiers xsi:type="ecore:EDataType" name="${this.escapeXml(dataType.getName())}"`;
// if (dataType.getInstanceClassName()) {
// xml += ` instanceClassName="${this.escapeXml(dataType.getInstanceClassName())}"`;
// }
xml += '/>';
return xml;
}
/**
* Gets a reference string for a classifier.
*/
getClassifierReference(classifier, fromPackage) {
// Check if it's a primitive type
const primitiveTypes = TUtils.PRIMITIVES;
if (primitiveTypes.includes(classifier.getName())) {
return `ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//${classifier.getName()}`;
}
// Build reference path
return this.buildReferencePath(classifier, fromPackage);
}
/**
* Gets a reference string for a feature.
*/
getFeatureReference(feature) {
const containingClass = feature.getEContainingClass();
if (!containingClass) {
return `#//${feature.getName()}`;
}
//root packages don't require package paths
if (!containingClass.getEPackage().getESuperPackage())
return `#//${containingClass.getName()}/${feature.getName()}`;
else
return `#//${this.getPackagePath(containingClass.getEPackage())}/${containingClass.getName()}/${feature.getName()}`;
}
/**
* Builds a reference path to a classifier.
*/
buildReferencePath(classifier, fromPackage) {
const classifierPackage = classifier.getEPackage();
// If in same package, use simple reference
// if (classifierPackage === fromPackage) {
// return `#//${classifier.getName()}`;
// }
// Build full path
const path = this.getPackagePath(classifierPackage);
if (path.length > 0)
return `#//${path.join('/')}/${classifier.getName()}`;
//root package elements don't require paths
return `#//${classifier.getName()}`;
}
/**
* Gets the path to a package from root.
*/
getPackagePath(pkg) {
const path = [];
let current = pkg;
while (current) {
path.unshift(current.getName());
current = current.getESuperPackage();
}
// Remove root package name from path
if (path.length > 0) {
path.shift();
}
return path;
}
/**
* Escapes special XML characters.
*/
escapeXml(str) {
if (!str)
return '';
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
/**
* Gets the current indentation string.
*/
getIndent() {
return this.indentString.repeat(this.indentLevel);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNvcmUtc3RyaW5nLXdyaXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZWNvcmUvZWNvcmUtc3RyaW5nLXdyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFXQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzlELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDdEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0Qzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDaEIsWUFBWSxHQUFHLElBQUksQ0FBQztJQUU1Qjs7OztPQUlHO0lBQ0ksYUFBYSxDQUFDLFFBQWtCO1FBQ3JDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pELE9BQU8sMkNBQTJDLEdBQUcsRUFBRSxDQUFDO0lBQzFELENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWUsQ0FBQyxRQUFrQixFQUFFLFNBQWtCLEtBQUs7UUFDakUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hDLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUViLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxnREFBZ0Q7WUFDaEQsR0FBRyxHQUFHO3dEQUM0QyxDQUFDO1FBQ3JELENBQUM7YUFBTSxDQUFDO1lBQ04sR0FBRyxHQUFHLEdBQUcsTUFBTSxlQUFlLENBQUM7UUFDakMsQ0FBQztRQUVELHlCQUF5QjtRQUN6QixHQUFHLElBQUksVUFBVSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDdkQsSUFBSSxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUN4QixHQUFHLElBQUksV0FBVyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDM0QsQ0FBQztRQUNELElBQUksUUFBUSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDM0IsR0FBRyxJQUFJLGNBQWMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsR0FBRyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxHQUFHLElBQUksR0FBRyxDQUFDO1FBRVgsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRW5CLGtCQUFrQjtRQUNsQixLQUFLLE1BQU0sVUFBVSxJQUFJLFFBQVEsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1lBQ3BELEdBQUcsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUM5RCxDQUFDO1FBRUQsa0JBQWtCO1FBQ2xCLEtBQUssTUFBTSxVQUFVLElBQUksUUFBUSxDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUM7WUFDcEQsR0FBRyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRW5CLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxHQUFHLElBQUkscUJBQXFCLENBQUM7UUFDL0IsQ0FBQzthQUFNLENBQUM7WUFDTixHQUFHLElBQUksS0FBSyxNQUFNLGlCQUFpQixDQUFDO1FBQ3RDLENBQUM7UUFFRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQixDQUFDLFVBQXVCLEVBQUUsaUJBQTJCO1FBQzdFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUVoQyxJQUFJLFVBQVUsWUFBWSxTQUFTLEVBQUUsQ0FBQztZQUNwQyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBbUIsQ0FBQyxDQUFDO1FBQ2hELENBQUM7YUFBTSxJQUFJLFVBQVUsWUFBWSxVQUFVLEVBQUUsQ0FBQztZQUM1QyxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBb0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7YUFBTSxJQUFJLFVBQVUsWUFBWSxhQUFhLEVBQUUsQ0FBQztZQUMvQyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUF1QixDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUVELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVEOztPQUVHO0lBQ0ssYUFBYSxDQUFDLE1BQWMsRUFBRSxpQkFBMkI7UUFDL0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hDLElBQUksR0FBRyxHQUFHLEdBQUcsTUFBTSwrQ0FBK0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDO1FBRXRHLHlCQUF5QjtRQUN6QixNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDM0MsSUFBSSxVQUFVLElBQUksVUFBVSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sYUFBYSxHQUFhLEVBQUUsQ0FBQztZQUNuQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQzNDLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7WUFDaEYsQ0FBQztZQUNELEdBQUcsSUFBSSxpQkFBaUIsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDO1FBQ3JELENBQUM7UUFFRCxzQ0FBc0M7UUFDdEMsSUFBSSxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUN4QixHQUFHLElBQUksa0JBQWtCLENBQUM7UUFDNUIsQ0FBQztRQUNELElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDekIsR0FBRyxJQUFJLG1CQUFtQixDQUFDO1FBQzdCLENBQUM7UUFFRCw2QkFBNkI7UUFDN0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLHNCQUFzQixFQUFFLElBQUksTUFBTSxDQUFDLHNCQUFzQixFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2xHLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxjQUFjLEVBQUUsSUFBSSxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRXBGLElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNuQyxHQUFHLElBQUksSUFBSSxDQUFDO1lBQ1osT0FBTyxHQUFHLENBQUM7UUFDYixDQUFDO1FBRUQsR0FBRyxJQUFJLEdBQUcsQ0FBQztRQUNYLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUVuQixpQkFBaUI7UUFDakIsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3hELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pELEdBQUcsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3JFLENBQUM7UUFDSCxDQUFDO1FBRUQsMEJBQTBCO1FBQzFCLElBQUksV0FBVyxFQUFFLENBQUM7WUFDaEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ2hFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkQsR0FBRyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ2pFLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25CLEdBQUcsSUFBSSxLQUFLLE1BQU0saUJBQWlCLENBQUM7UUFFcEMsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7O09BRUc7SUFDSyxpQkFBaUIsQ0FBQyxTQUFxQixFQUFFLGlCQUEyQjtRQUMxRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDaEMsSUFBSSxHQUFHLEdBQUcsR0FBRyxNQUFNLHNCQUFzQixJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFFaEYsNkJBQTZCO1FBQzdCLElBQUksU0FBUyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7WUFDekIsR0FBRyxJQUFJLFdBQVcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUcsRUFBRSxpQkFBaUIsQ0FBQyxHQUFHLENBQUM7UUFDN0YsQ0FBQztRQUVELDJCQUEyQjtRQUMzQixJQUFJLFNBQVMsQ0FBQyxhQUFhLEVBQUUsSUFBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ25DLEdBQUcsSUFBSSxnQkFBZ0IsU0FBUyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUM7UUFDdEQsQ0FBQztRQUVELG9DQUFvQztRQUNwQyxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsY0FBYyxFQUFFLElBQUksU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUUxRixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbkIsR0FBRyxJQUFJLElBQUksQ0FBQztZQUNaLE9BQU8sR0FBRyxDQUFDO1FBQ2IsQ0FBQztRQUVELEdBQUcsSUFBSSxHQUFHLENBQUM7UUFDWCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFbkIsaUJBQWlCO1FBQ2pCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUMzRCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hELEdBQUcsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFFRCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsR0FBRyxJQUFJLEtBQUssTUFBTSxnQkFBZ0IsQ0FBQztRQUVuQyxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRDs7T0FFRztJQUNLLGlCQUFpQixDQUFDLFNBQXFCLEVBQUUsaUJBQTJCO1FBQzFFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxJQUFJLEdBQUcsR0FBRyxHQUFHLE1BQU0sc0JBQXNCLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQztRQUVoRixJQUFJLFNBQVMsQ0FBQyxhQUFhLEVBQUUsSUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2xDLEdBQUcsSUFBSSxnQkFBZ0IsU0FBUyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUM7UUFDdEQsQ0FBQztRQUVELHNGQUFzRjtRQUV0RixJQUFJLFNBQVMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3pCLEdBQUcsSUFBSSxXQUFXLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLEVBQUUsaUJBQWlCLENBQUMsR0FBRyxDQUFDO1FBQzVGLENBQUM7UUFFRCxHQUFHLElBQUksSUFBSSxDQUFDO1FBQ1osT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7O09BRUc7SUFDSyxlQUFlLENBQUMsT0FBMkIsRUFBRSxpQkFBMkI7UUFDOUUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sV0FBVyxHQUFHLE9BQU8sWUFBWSxjQUFjLENBQUM7UUFDdEQsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUM7UUFFMUUsSUFBSSxHQUFHLEdBQUcsR0FBRyxNQUFNLGtDQUFrQyxXQUFXLFdBQVcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDO1FBRWhILFdBQVc7UUFDWCxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3ZCLEdBQUcsSUFBSSxXQUFXLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFHLEVBQUUsaUJBQWlCLENBQUMsR0FBRyxDQUFDO1FBQzNGLENBQUM7UUFFRCw2RUFBNkU7UUFDN0UsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFLElBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxHQUFHLElBQUksZ0JBQWdCLE9BQU8sQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDO1FBQ3BELENBQUM7UUFFRCxrQ0FBa0M7UUFDbEMsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNoQixNQUFNLElBQUksR0FBRyxPQUFxQixDQUFDO1lBQ25DLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQ2hCLEdBQUcsSUFBSSxZQUFZLENBQUM7WUFDdEIsQ0FBQztRQUNILENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxHQUFHLEdBQUcsT0FBcUIsQ0FBQztZQUNsQyxJQUFJLEdBQUcsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDO2dCQUN4QixHQUFHLElBQUkscUJBQXFCLENBQUM7WUFDL0IsQ0FBQztZQUNELElBQUksR0FBRyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7Z0JBQ3ZCLEdBQUcsSUFBSSxlQUFlLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFHLENBQUMsR0FBRyxDQUFDO1lBQ3pFLENBQUM7UUFDSCxDQUFDO1FBRUQsdUJBQXVCO1FBQ3ZCLElBQUksT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDMUIsR0FBRyxJQUFJLG1CQUFtQixDQUFDO1FBQzdCLENBQUM7UUFDRCw2QkFBNkI7UUFDN0IsOEJBQThCO1FBQzlCLElBQUk7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7WUFDNUIsR0FBRyxJQUFJLHFCQUFxQixDQUFDO1FBQy9CLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQ3pCLEdBQUcsSUFBSSxrQkFBa0IsQ0FBQztRQUM1QixDQUFDO1FBQ0QsSUFBSSxPQUFPLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxDQUFDO1lBQ3JDLEdBQUcsSUFBSSx5QkFBeUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDdEYsQ0FBQztRQUVELEdBQUcsSUFBSSxJQUFJLENBQUM7UUFDWixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRDs7T0FFRztJQUNLLFlBQVksQ0FBQyxLQUFZO1FBQy9CLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxJQUFJLEdBQUcsR0FBRyxHQUFHLE1BQU0sOENBQThDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQztRQUVwRyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsWUFBWSxFQUFFLElBQUksS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUU1RSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakIsR0FBRyxJQUFJLElBQUksQ0FBQztZQUNaLE9BQU8sR0FBRyxDQUFDO1FBQ2IsQ0FBQztRQUVELEdBQUcsSUFBSSxHQUFHLENBQUM7UUFDWCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFbkIsb0JBQW9CO1FBQ3BCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNyRCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVDLEdBQUcsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xELENBQUM7UUFFRCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsR0FBRyxJQUFJLEtBQUssTUFBTSxpQkFBaUIsQ0FBQztRQUVwQyxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRDs7T0FFRztJQUNLLG1CQUFtQixDQUFDLE9BQXFCO1FBQy9DLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxJQUFJLEdBQUcsR0FBRyxHQUFHLE1BQU0sb0JBQW9CLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQztRQUU1RSxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUUsS0FBSyxTQUFTLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3BFLEdBQUcsSUFBSSxXQUFXLE9BQU8sQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDO1FBQzFDLENBQUM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLEtBQUssT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDdkUsR0FBRyxJQUFJLGFBQWEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO1FBQzlELENBQUM7UUFFRCxHQUFHLElBQUksSUFBSSxDQUFDO1FBQ1osT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7O09BRUc7SUFDSyxnQkFBZ0IsQ0FBQyxRQUFtQjtRQUMxQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDaEMsSUFBSSxHQUFHLEdBQUcsR0FBRyxNQUFNLGtEQUFrRCxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFFM0cseUNBQXlDO1FBQ3pDLHNGQUFzRjtRQUN0RixJQUFJO1FBRUosR0FBRyxJQUFJLElBQUksQ0FBQztRQUNaLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVEOztPQUVHO0lBQ0ssc0JBQXNCLENBQUMsVUFBdUIsRUFBRSxXQUFxQjtRQUMzRSxpQ0FBaUM7UUFDakMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUN6QyxJQUFJLGNBQWMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNsRCxPQUFPLDJEQUEyRCxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUMzRixDQUFDO1FBRUQsdUJBQXVCO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxtQkFBbUIsQ0FBQyxPQUEyQjtRQUNyRCxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUN0RCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDckIsT0FBTyxNQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQ25DLENBQUM7UUFDRCwyQ0FBMkM7UUFDM0MsSUFBRyxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRTtZQUNsRCxPQUFPLE1BQU0sZUFBZSxDQUFDLE9BQU8sRUFBRSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDOztZQUUvRCxPQUFPLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxlQUFlLENBQUMsT0FBTyxFQUFFLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7SUFDdkgsQ0FBQztJQUVEOztPQUVHO0lBQ0ssa0JBQWtCLENBQUMsVUFBdUIsRUFBRSxXQUFxQjtRQUN2RSxNQUFNLGlCQUFpQixHQUFHLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUVuRCwyQ0FBMkM7UUFDM0MsMkNBQTJDO1FBQzNDLHlDQUF5QztRQUN6QyxJQUFJO1FBRUosa0JBQWtCO1FBQ2xCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUNwRCxJQUFHLElBQUksQ0FBQyxNQUFNLEdBQUMsQ0FBQztZQUNkLE9BQU8sTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBRXhELDJDQUEyQztRQUMzQyxPQUFPLE1BQU0sVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7SUFDdEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssY0FBYyxDQUFDLEdBQWE7UUFDbEMsTUFBTSxJQUFJLEdBQWEsRUFBRSxDQUFDO1FBQzFCLElBQUksT0FBTyxHQUFHLEdBQUcsQ0FBQztRQUVsQixPQUFPLE9BQU8sRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNoQyxPQUFPLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdkMsQ0FBQztRQUVELHFDQUFxQztRQUNyQyxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0ssU0FBUyxDQUFDLEdBQVc7UUFDM0IsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUNwQixPQUFPLEdBQUc7YUFDUCxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQzthQUN0QixPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQzthQUNyQixPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQzthQUNyQixPQUFPLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQzthQUN2QixPQUFPLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNLLFNBQVM7UUFDZixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNwRCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFUGFja2FnZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZXBhY2thZ2UuanMnO1xyXG5pbXBvcnQgeyBFQ2xhc3MgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VjbGFzcy5qcyc7XHJcbmltcG9ydCB7IEVDbGFzc2lmaWVyIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lY2xhc3NpZmllci5qcyc7XHJcbmltcG9ydCB7IEVEYXRhVHlwZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZWRhdGEtdHlwZS5qcyc7XHJcbmltcG9ydCB7IEVFbnVtIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lZW51bS5qcyc7XHJcbmltcG9ydCB7IEVTdHJ1Y3R1cmFsRmVhdHVyZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZXN0cnVjdHVyYWwtZmVhdHVyZS5qcyc7XHJcbmltcG9ydCB7IEVBdHRyaWJ1dGUgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VhdHRyaWJ1dGUuanMnO1xyXG5pbXBvcnQgeyBFUmVmZXJlbmNlIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lcmVmZXJlbmNlLmpzJztcclxuaW1wb3J0IHsgRU9wZXJhdGlvbiB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZW9wZXJhdGlvbi5qcyc7XHJcbmltcG9ydCB7IEVQYXJhbWV0ZXIgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VwYXJhbWV0ZXIuanMnO1xyXG5pbXBvcnQgeyBFRW51bUxpdGVyYWwgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VlbnVtLWxpdGVyYWwuanMnO1xyXG5pbXBvcnQgeyBFRW51bUltcGwgfSBmcm9tICcuLi9tZXRhbW9kZWwvaW1wbC9lZW51bS1pbXBsLmpzJztcclxuaW1wb3J0IHsgRUNsYXNzSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VjbGFzcy1pbXBsLmpzJztcclxuaW1wb3J0IHsgRURhdGFUeXBlSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VkYXRhLXR5cGUtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVBdHRyaWJ1dGVJbXBsIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2ltcGwvZWF0dHJpYnV0ZS1pbXBsLmpzJztcclxuaW1wb3J0IHsgVFV0aWxzIH0gZnJvbSAnLi4vdHV0aWxzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBXcml0ZXMgRVBhY2thZ2UgbWV0YW1vZGVscyB0byBFY29yZSBYTUwgc3RyaW5nIGZvcm1hdC5cclxuICogVGhpcyBjbGFzcyBoYW5kbGVzIHRoZSBjb3JlIHdyaXRpbmcgbG9naWMgd2l0aG91dCBmaWxlIHN5c3RlbSBkZXBlbmRlbmNpZXMuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgRWNvcmVTdHJpbmdXcml0ZXIge1xyXG4gIHByaXZhdGUgaW5kZW50TGV2ZWwgPSAwO1xyXG4gIHByaXZhdGUgaW5kZW50U3RyaW5nID0gJyAgJztcclxuICBcclxuICAvKipcclxuICAgKiBDb252ZXJ0cyBhbiBFUGFja2FnZSB0byBFY29yZSBYTUwgc3RyaW5nIGZvcm1hdC5cclxuICAgKiBAcGFyYW0gZVBhY2thZ2UgVGhlIHJvb3QgcGFja2FnZSB0byBzZXJpYWxpemVcclxuICAgKiBAcmV0dXJucyBUaGUgWE1MIHN0cmluZyByZXByZXNlbnRhdGlvblxyXG4gICAqL1xyXG4gIHB1YmxpYyB3cml0ZVRvU3RyaW5nKGVQYWNrYWdlOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCB4bWwgPSB0aGlzLmJ1aWxkUGFja2FnZVhtbChlUGFja2FnZSwgdHJ1ZSk7XHJcbiAgICByZXR1cm4gYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIlVURi04XCI/PlxcbiR7eG1sfWA7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhIHBhY2thZ2UuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZFBhY2thZ2VYbWwoZVBhY2thZ2U6IEVQYWNrYWdlLCBpc1Jvb3Q6IGJvb2xlYW4gPSBmYWxzZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBpbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xyXG4gICAgbGV0IHhtbCA9ICcnO1xyXG4gICAgXHJcbiAgICBpZiAoaXNSb290KSB7XHJcbiAgICAgIC8vIFJvb3QgcGFja2FnZSB3aXRoIGZ1bGwgbmFtZXNwYWNlIGRlY2xhcmF0aW9uc1xyXG4gICAgICB4bWwgPSBgPGVjb3JlOkVQYWNrYWdlIHhtaTp2ZXJzaW9uPVwiMi4wXCIgeG1sbnM6eG1pPVwiaHR0cDovL3d3dy5vbWcub3JnL1hNSVwiIHhtbG5zOnhzaT1cImh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlXCJcclxuICAgIHhtbG5zOmVjb3JlPVwiaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9lbWYvMjAwMi9FY29yZVwiYDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHhtbCA9IGAke2luZGVudH08ZVN1YnBhY2thZ2VzYDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gQWRkIHBhY2thZ2UgYXR0cmlidXRlc1xyXG4gICAgeG1sICs9IGAgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwoZVBhY2thZ2UuZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBpZiAoZVBhY2thZ2UuZ2V0TnNVUkkoKSkge1xyXG4gICAgICB4bWwgKz0gYCBuc1VSST1cIiR7dGhpcy5lc2NhcGVYbWwoZVBhY2thZ2UuZ2V0TnNVUkkoKSl9XCJgO1xyXG4gICAgfVxyXG4gICAgaWYgKGVQYWNrYWdlLmdldE5zUHJlZml4KCkpIHtcclxuICAgICAgeG1sICs9IGAgbnNQcmVmaXg9XCIke3RoaXMuZXNjYXBlWG1sKGVQYWNrYWdlLmdldE5zUHJlZml4KCkpfVwiYDtcclxuICAgIH1cclxuICAgIHhtbCArPSAnPic7XHJcbiAgICBcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcclxuICAgIFxyXG4gICAgLy8gQWRkIGNsYXNzaWZpZXJzXHJcbiAgICBmb3IgKGNvbnN0IGNsYXNzaWZpZXIgb2YgZVBhY2thZ2UuZ2V0RUNsYXNzaWZpZXJzKCkpIHtcclxuICAgICAgeG1sICs9ICdcXG4nICsgdGhpcy5idWlsZENsYXNzaWZpZXJYbWwoY2xhc3NpZmllciwgZVBhY2thZ2UpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgc3VicGFja2FnZXNcclxuICAgIGZvciAoY29uc3Qgc3ViUGFja2FnZSBvZiBlUGFja2FnZS5nZXRFU3ViUGFja2FnZXMoKSkge1xyXG4gICAgICB4bWwgKz0gJ1xcbicgKyB0aGlzLmJ1aWxkUGFja2FnZVhtbChzdWJQYWNrYWdlLCBmYWxzZSk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwtLTtcclxuICAgIFxyXG4gICAgaWYgKGlzUm9vdCkge1xyXG4gICAgICB4bWwgKz0gJ1xcbjwvZWNvcmU6RVBhY2thZ2U+JztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHhtbCArPSBgXFxuJHtpbmRlbnR9PC9lU3VicGFja2FnZXM+YDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuIHhtbDtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogQnVpbGRzIHRoZSBYTUwgZm9yIGEgY2xhc3NpZmllciAoRUNsYXNzLCBFRW51bSwgb3IgRURhdGFUeXBlKS5cclxuICAgKi9cclxuICBwcml2YXRlIGJ1aWxkQ2xhc3NpZmllclhtbChjbGFzc2lmaWVyOiBFQ2xhc3NpZmllciwgY29udGFpbmluZ1BhY2thZ2U6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGluZGVudCA9IHRoaXMuZ2V0SW5kZW50KCk7XHJcbiAgICBcclxuICAgIGlmIChjbGFzc2lmaWVyIGluc3RhbmNlb2YgRUVudW1JbXBsKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmJ1aWxkRW51bVhtbChjbGFzc2lmaWVyIGFzIEVFbnVtKTtcclxuICAgIH0gZWxzZSBpZiAoY2xhc3NpZmllciBpbnN0YW5jZW9mIEVDbGFzc0ltcGwpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuYnVpbGRDbGFzc1htbChjbGFzc2lmaWVyIGFzIEVDbGFzcywgY29udGFpbmluZ1BhY2thZ2UpO1xyXG4gICAgfSBlbHNlIGlmIChjbGFzc2lmaWVyIGluc3RhbmNlb2YgRURhdGFUeXBlSW1wbCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5idWlsZERhdGFUeXBlWG1sKGNsYXNzaWZpZXIgYXMgRURhdGFUeXBlKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuICcnO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgdGhlIFhNTCBmb3IgYW4gRUNsYXNzLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYnVpbGRDbGFzc1htbChlQ2xhc3M6IEVDbGFzcywgY29udGFpbmluZ1BhY2thZ2U6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGluZGVudCA9IHRoaXMuZ2V0SW5kZW50KCk7XHJcbiAgICBsZXQgeG1sID0gYCR7aW5kZW50fTxlQ2xhc3NpZmllcnMgeHNpOnR5cGU9XCJlY29yZTpFQ2xhc3NcIiBuYW1lPVwiJHt0aGlzLmVzY2FwZVhtbChlQ2xhc3MuZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBcclxuICAgIC8vIEFkZCBzdXBlciB0eXBlcyBpZiBhbnlcclxuICAgIGNvbnN0IHN1cGVyVHlwZXMgPSBlQ2xhc3MuZ2V0RVN1cGVyVHlwZXMoKTtcclxuICAgIGlmIChzdXBlclR5cGVzICYmIHN1cGVyVHlwZXMuc2l6ZSgpID4gMCkge1xyXG4gICAgICBjb25zdCBzdXBlclR5cGVSZWZzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN1cGVyVHlwZXMuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgICBjb25zdCBzdXBlclR5cGUgPSBzdXBlclR5cGVzLmdldChpKTtcclxuICAgICAgICBzdXBlclR5cGVSZWZzLnB1c2godGhpcy5nZXRDbGFzc2lmaWVyUmVmZXJlbmNlKHN1cGVyVHlwZSwgY29udGFpbmluZ1BhY2thZ2UpKTtcclxuICAgICAgfVxyXG4gICAgICB4bWwgKz0gYCBlU3VwZXJUeXBlcz1cIiR7c3VwZXJUeXBlUmVmcy5qb2luKCcgJyl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgYWJzdHJhY3QvaW50ZXJmYWNlIGZsYWdzIGlmIHNldFxyXG4gICAgaWYgKGVDbGFzcy5pc0Fic3RyYWN0KCkpIHtcclxuICAgICAgeG1sICs9ICcgYWJzdHJhY3Q9XCJ0cnVlXCInO1xyXG4gICAgfVxyXG4gICAgaWYgKGVDbGFzcy5pc0ludGVyZmFjZSgpKSB7XHJcbiAgICAgIHhtbCArPSAnIGludGVyZmFjZT1cInRydWVcIic7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIENoZWNrIGlmIGNsYXNzIGhhcyBjb250ZW50XHJcbiAgICBjb25zdCBoYXNGZWF0dXJlcyA9IGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkgJiYgZUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKS5zaXplKCkgPiAwO1xyXG4gICAgY29uc3QgaGFzT3BlcmF0aW9ucyA9IGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpICYmIGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpLnNpemUoKSA+IDA7XHJcbiAgICBcclxuICAgIGlmICghaGFzRmVhdHVyZXMgJiYgIWhhc09wZXJhdGlvbnMpIHtcclxuICAgICAgeG1sICs9ICcvPic7XHJcbiAgICAgIHJldHVybiB4bWw7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHhtbCArPSAnPic7XHJcbiAgICB0aGlzLmluZGVudExldmVsKys7XHJcbiAgICBcclxuICAgIC8vIEFkZCBvcGVyYXRpb25zXHJcbiAgICBpZiAoaGFzT3BlcmF0aW9ucykge1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpLnNpemUoKTsgaSsrKSB7XHJcbiAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gZUNsYXNzLmdldEVPcGVyYXRpb25zKCkuZ2V0KGkpO1xyXG4gICAgICAgIHhtbCArPSAnXFxuJyArIHRoaXMuYnVpbGRPcGVyYXRpb25YbWwob3BlcmF0aW9uLCBjb250YWluaW5nUGFja2FnZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gQWRkIHN0cnVjdHVyYWwgZmVhdHVyZXNcclxuICAgIGlmIChoYXNGZWF0dXJlcykge1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgICBjb25zdCBmZWF0dXJlID0gZUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKS5nZXQoaSk7XHJcbiAgICAgICAgeG1sICs9ICdcXG4nICsgdGhpcy5idWlsZEZlYXR1cmVYbWwoZmVhdHVyZSwgY29udGFpbmluZ1BhY2thZ2UpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwtLTtcclxuICAgIHhtbCArPSBgXFxuJHtpbmRlbnR9PC9lQ2xhc3NpZmllcnM+YDtcclxuICAgIFxyXG4gICAgcmV0dXJuIHhtbDtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogQnVpbGRzIHRoZSBYTUwgZm9yIGFuIEVPcGVyYXRpb24uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZE9wZXJhdGlvblhtbChvcGVyYXRpb246IEVPcGVyYXRpb24sIGNvbnRhaW5pbmdQYWNrYWdlOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBpbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xyXG4gICAgbGV0IHhtbCA9IGAke2luZGVudH08ZU9wZXJhdGlvbnMgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwob3BlcmF0aW9uLmdldE5hbWUoKSl9XCJgO1xyXG4gICAgXHJcbiAgICAvLyBBZGQgcmV0dXJuIHR5cGUgaWYgcHJlc2VudFxyXG4gICAgaWYgKG9wZXJhdGlvbi5nZXRFVHlwZSgpKSB7XHJcbiAgICAgIHhtbCArPSBgIGVUeXBlPVwiJHt0aGlzLmdldENsYXNzaWZpZXJSZWZlcmVuY2Uob3BlcmF0aW9uLmdldEVUeXBlKCkhLCBjb250YWluaW5nUGFja2FnZSl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgdXBwZXIgYm91bmQgaWYgbm90IDFcclxuICAgIGlmIChvcGVyYXRpb24uZ2V0VXBwZXJCb3VuZCgpID09LTEpIHtcclxuICAgICAgeG1sICs9IGAgdXBwZXJCb3VuZD1cIiR7b3BlcmF0aW9uLmdldFVwcGVyQm91bmQoKX1cImA7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIENoZWNrIGlmIG9wZXJhdGlvbiBoYXMgcGFyYW1ldGVyc1xyXG4gICAgY29uc3QgaGFzUGFyYW1ldGVycyA9IG9wZXJhdGlvbi5nZXRFUGFyYW1ldGVycygpICYmIG9wZXJhdGlvbi5nZXRFUGFyYW1ldGVycygpLnNpemUoKSA+IDA7XHJcbiAgICBcclxuICAgIGlmICghaGFzUGFyYW1ldGVycykge1xyXG4gICAgICB4bWwgKz0gJy8+JztcclxuICAgICAgcmV0dXJuIHhtbDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICc+JztcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcclxuICAgIFxyXG4gICAgLy8gQWRkIHBhcmFtZXRlcnNcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlcmF0aW9uLmdldEVQYXJhbWV0ZXJzKCkuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgY29uc3QgcGFyYW0gPSBvcGVyYXRpb24uZ2V0RVBhcmFtZXRlcnMoKS5nZXQoaSk7XHJcbiAgICAgIHhtbCArPSAnXFxuJyArIHRoaXMuYnVpbGRQYXJhbWV0ZXJYbWwocGFyYW0sIGNvbnRhaW5pbmdQYWNrYWdlKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgdGhpcy5pbmRlbnRMZXZlbC0tO1xyXG4gICAgeG1sICs9IGBcXG4ke2luZGVudH08L2VPcGVyYXRpb25zPmA7XHJcbiAgICBcclxuICAgIHJldHVybiB4bWw7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhbiBFUGFyYW1ldGVyLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYnVpbGRQYXJhbWV0ZXJYbWwocGFyYW1ldGVyOiBFUGFyYW1ldGVyLCBjb250YWluaW5nUGFja2FnZTogRVBhY2thZ2UpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaW5kZW50ID0gdGhpcy5nZXRJbmRlbnQoKTtcclxuICAgIGxldCB4bWwgPSBgJHtpbmRlbnR9PGVQYXJhbWV0ZXJzIG5hbWU9XCIke3RoaXMuZXNjYXBlWG1sKHBhcmFtZXRlci5nZXROYW1lKCkpfVwiYDtcclxuICAgIFxyXG4gICAgaWYgKHBhcmFtZXRlci5nZXRVcHBlckJvdW5kKCk9PS0xKSB7XHJcbiAgICAgIHhtbCArPSBgIHVwcGVyQm91bmQ9XCIke3BhcmFtZXRlci5nZXRVcHBlckJvdW5kKCl9XCJgO1xyXG4gICAgfVxyXG5cclxuICAgIC8vVE9ETzogbG93ZXIgYm91bmRzIGZvciBvcHRpb25hbCBwYXJhbWV0ZXJzPyBzaW5jZSB3ZSBjYW4gc3VwcG9ydCB0aG9zZSBpbiB0eXBlc2NyaXB0XHJcblxyXG4gICAgaWYgKHBhcmFtZXRlci5nZXRFVHlwZSgpKSB7XHJcbiAgICAgIHhtbCArPSBgIGVUeXBlPVwiJHt0aGlzLmdldENsYXNzaWZpZXJSZWZlcmVuY2UocGFyYW1ldGVyLmdldEVUeXBlKCksIGNvbnRhaW5pbmdQYWNrYWdlKX1cImA7XHJcbiAgICB9XHJcbiAgICAgIFxyXG4gICAgeG1sICs9ICcvPic7XHJcbiAgICByZXR1cm4geG1sO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgdGhlIFhNTCBmb3IgYSBzdHJ1Y3R1cmFsIGZlYXR1cmUgKEVBdHRyaWJ1dGUgb3IgRVJlZmVyZW5jZSkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZEZlYXR1cmVYbWwoZmVhdHVyZTogRVN0cnVjdHVyYWxGZWF0dXJlLCBjb250YWluaW5nUGFja2FnZTogRVBhY2thZ2UpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaW5kZW50ID0gdGhpcy5nZXRJbmRlbnQoKTtcclxuICAgIGNvbnN0IGlzQXR0cmlidXRlID0gZmVhdHVyZSBpbnN0YW5jZW9mIEVBdHRyaWJ1dGVJbXBsO1xyXG4gICAgY29uc3QgZmVhdHVyZVR5cGUgPSBpc0F0dHJpYnV0ZSA/ICdlY29yZTpFQXR0cmlidXRlJyA6ICdlY29yZTpFUmVmZXJlbmNlJztcclxuICAgIFxyXG4gICAgbGV0IHhtbCA9IGAke2luZGVudH08ZVN0cnVjdHVyYWxGZWF0dXJlcyB4c2k6dHlwZT1cIiR7ZmVhdHVyZVR5cGV9XCIgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwoZmVhdHVyZS5nZXROYW1lKCkpfVwiYDtcclxuICAgIFxyXG4gICAgLy8gQWRkIHR5cGVcclxuICAgIGlmIChmZWF0dXJlLmdldEVUeXBlKCkpIHtcclxuICAgICAgeG1sICs9IGAgZVR5cGU9XCIke3RoaXMuZ2V0Q2xhc3NpZmllclJlZmVyZW5jZShmZWF0dXJlLmdldEVUeXBlKCkhLCBjb250YWluaW5nUGFja2FnZSl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvL1RPRE86IGxvd2VyYm91bmQ/IG9ubHkgc2VlbXMgdG8gbWFrZSBzZW5zZSBpZiB3ZSBoYXZlICdyZXF1aXJlZCcgZmVhdHVyZXMgIFxyXG4gICAgaWYgKGZlYXR1cmUuZ2V0VXBwZXJCb3VuZCgpPT0tMSkge1xyXG4gICAgICB4bWwgKz0gYCB1cHBlckJvdW5kPVwiJHtmZWF0dXJlLmdldFVwcGVyQm91bmQoKX1cImA7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIEFkZCBmZWF0dXJlLXNwZWNpZmljIGF0dHJpYnV0ZXNcclxuICAgIGlmIChpc0F0dHJpYnV0ZSkge1xyXG4gICAgICBjb25zdCBhdHRyID0gZmVhdHVyZSBhcyBFQXR0cmlidXRlO1xyXG4gICAgICBpZiAoYXR0ci5pc0lkKCkpIHtcclxuICAgICAgICB4bWwgKz0gJyBpRD1cInRydWVcIic7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IHJlZiA9IGZlYXR1cmUgYXMgRVJlZmVyZW5jZTtcclxuICAgICAgaWYgKHJlZi5pc0NvbnRhaW5tZW50KCkpIHtcclxuICAgICAgICB4bWwgKz0gJyBjb250YWlubWVudD1cInRydWVcIic7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHJlZi5nZXRFT3Bwb3NpdGUoKSkge1xyXG4gICAgICAgIHhtbCArPSBgIGVPcHBvc2l0ZT1cIiR7dGhpcy5nZXRGZWF0dXJlUmVmZXJlbmNlKHJlZi5nZXRFT3Bwb3NpdGUoKSEpfVwiYDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgb3RoZXIgcHJvcGVydGllc1xyXG4gICAgaWYgKGZlYXR1cmUuaXNUcmFuc2llbnQoKSkge1xyXG4gICAgICB4bWwgKz0gJyB0cmFuc2llbnQ9XCJ0cnVlXCInO1xyXG4gICAgfVxyXG4gICAgLy8gaWYgKGZlYXR1cmUuaXNEZXJpdmVkKCkpIHtcclxuICAgIC8vICAgeG1sICs9ICcgZGVyaXZlZD1cInRydWVcIic7XHJcbiAgICAvLyB9XHJcbiAgICBpZiAoIWZlYXR1cmUuaXNDaGFuZ2VhYmxlKCkpIHtcclxuICAgICAgeG1sICs9ICcgY2hhbmdlYWJsZT1cImZhbHNlXCInO1xyXG4gICAgfVxyXG4gICAgaWYgKGZlYXR1cmUuaXNWb2xhdGlsZSgpKSB7XHJcbiAgICAgIHhtbCArPSAnIHZvbGF0aWxlPVwidHJ1ZVwiJztcclxuICAgIH1cclxuICAgIGlmIChmZWF0dXJlLmdldERlZmF1bHRWYWx1ZUxpdGVyYWwoKSkge1xyXG4gICAgICB4bWwgKz0gYCBkZWZhdWx0VmFsdWVMaXRlcmFsPVwiJHt0aGlzLmVzY2FwZVhtbChmZWF0dXJlLmdldERlZmF1bHRWYWx1ZUxpdGVyYWwoKSl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICB4bWwgKz0gJy8+JztcclxuICAgIHJldHVybiB4bWw7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhbiBFRW51bS5cclxuICAgKi9cclxuICBwcml2YXRlIGJ1aWxkRW51bVhtbChlRW51bTogRUVudW0pOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaW5kZW50ID0gdGhpcy5nZXRJbmRlbnQoKTtcclxuICAgIGxldCB4bWwgPSBgJHtpbmRlbnR9PGVDbGFzc2lmaWVycyB4c2k6dHlwZT1cImVjb3JlOkVFbnVtXCIgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwoZUVudW0uZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBcclxuICAgIGNvbnN0IGhhc0xpdGVyYWxzID0gZUVudW0uZ2V0RUxpdGVyYWxzKCkgJiYgZUVudW0uZ2V0RUxpdGVyYWxzKCkuc2l6ZSgpID4gMDtcclxuICAgIFxyXG4gICAgaWYgKCFoYXNMaXRlcmFscykge1xyXG4gICAgICB4bWwgKz0gJy8+JztcclxuICAgICAgcmV0dXJuIHhtbDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICc+JztcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcclxuICAgIFxyXG4gICAgLy8gQWRkIGVudW0gbGl0ZXJhbHNcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZUVudW0uZ2V0RUxpdGVyYWxzKCkuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgY29uc3QgbGl0ZXJhbCA9IGVFbnVtLmdldEVMaXRlcmFscygpLmdldChpKTtcclxuICAgICAgeG1sICs9ICdcXG4nICsgdGhpcy5idWlsZEVudW1MaXRlcmFsWG1sKGxpdGVyYWwpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICB0aGlzLmluZGVudExldmVsLS07XHJcbiAgICB4bWwgKz0gYFxcbiR7aW5kZW50fTwvZUNsYXNzaWZpZXJzPmA7XHJcbiAgICBcclxuICAgIHJldHVybiB4bWw7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhbiBFRW51bUxpdGVyYWwuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZEVudW1MaXRlcmFsWG1sKGxpdGVyYWw6IEVFbnVtTGl0ZXJhbCk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBpbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xyXG4gICAgbGV0IHhtbCA9IGAke2luZGVudH08ZUxpdGVyYWxzIG5hbWU9XCIke3RoaXMuZXNjYXBlWG1sKGxpdGVyYWwuZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBcclxuICAgIGlmIChsaXRlcmFsLmdldFZhbHVlKCkgIT09IHVuZGVmaW5lZCAmJiBsaXRlcmFsLmdldFZhbHVlKCkgIT09IG51bGwpIHtcclxuICAgICAgeG1sICs9IGAgdmFsdWU9XCIke2xpdGVyYWwuZ2V0VmFsdWUoKX1cImA7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIGlmIChsaXRlcmFsLmdldExpdGVyYWwoKSAmJiBsaXRlcmFsLmdldExpdGVyYWwoKSAhPT0gbGl0ZXJhbC5nZXROYW1lKCkpIHtcclxuICAgICAgeG1sICs9IGAgbGl0ZXJhbD1cIiR7dGhpcy5lc2NhcGVYbWwobGl0ZXJhbC5nZXRMaXRlcmFsKCkpfVwiYDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICcvPic7XHJcbiAgICByZXR1cm4geG1sO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgdGhlIFhNTCBmb3IgYW4gRURhdGFUeXBlLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYnVpbGREYXRhVHlwZVhtbChkYXRhVHlwZTogRURhdGFUeXBlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGluZGVudCA9IHRoaXMuZ2V0SW5kZW50KCk7XHJcbiAgICBsZXQgeG1sID0gYCR7aW5kZW50fTxlQ2xhc3NpZmllcnMgeHNpOnR5cGU9XCJlY29yZTpFRGF0YVR5cGVcIiBuYW1lPVwiJHt0aGlzLmVzY2FwZVhtbChkYXRhVHlwZS5nZXROYW1lKCkpfVwiYDtcclxuICAgIFxyXG4gICAgLy8gaWYgKGRhdGFUeXBlLmdldEluc3RhbmNlQ2xhc3NOYW1lKCkpIHtcclxuICAgIC8vICAgeG1sICs9IGAgaW5zdGFuY2VDbGFzc05hbWU9XCIke3RoaXMuZXNjYXBlWG1sKGRhdGFUeXBlLmdldEluc3RhbmNlQ2xhc3NOYW1lKCkpfVwiYDtcclxuICAgIC8vIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICcvPic7XHJcbiAgICByZXR1cm4geG1sO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBHZXRzIGEgcmVmZXJlbmNlIHN0cmluZyBmb3IgYSBjbGFzc2lmaWVyLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0Q2xhc3NpZmllclJlZmVyZW5jZShjbGFzc2lmaWVyOiBFQ2xhc3NpZmllciwgZnJvbVBhY2thZ2U6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIC8vIENoZWNrIGlmIGl0J3MgYSBwcmltaXRpdmUgdHlwZVxyXG4gICAgY29uc3QgcHJpbWl0aXZlVHlwZXMgPSBUVXRpbHMuUFJJTUlUSVZFUztcclxuICAgIGlmIChwcmltaXRpdmVUeXBlcy5pbmNsdWRlcyhjbGFzc2lmaWVyLmdldE5hbWUoKSkpIHtcclxuICAgICAgcmV0dXJuIGBlY29yZTpFRGF0YVR5cGUgaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9lbWYvMjAwMi9FY29yZSMvLyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gQnVpbGQgcmVmZXJlbmNlIHBhdGhcclxuICAgIHJldHVybiB0aGlzLmJ1aWxkUmVmZXJlbmNlUGF0aChjbGFzc2lmaWVyLCBmcm9tUGFja2FnZSk7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEdldHMgYSByZWZlcmVuY2Ugc3RyaW5nIGZvciBhIGZlYXR1cmUuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXRGZWF0dXJlUmVmZXJlbmNlKGZlYXR1cmU6IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjb250YWluaW5nQ2xhc3MgPSBmZWF0dXJlLmdldEVDb250YWluaW5nQ2xhc3MoKTtcclxuICAgIGlmICghY29udGFpbmluZ0NsYXNzKSB7XHJcbiAgICAgIHJldHVybiBgIy8vJHtmZWF0dXJlLmdldE5hbWUoKX1gO1xyXG4gICAgfVxyXG4gICAgLy9yb290IHBhY2thZ2VzIGRvbid0IHJlcXVpcmUgcGFja2FnZSBwYXRoc1xyXG4gICAgaWYoIWNvbnRhaW5pbmdDbGFzcy5nZXRFUGFja2FnZSgpLmdldEVTdXBlclBhY2thZ2UoKSlcclxuICAgICAgcmV0dXJuIGAjLy8ke2NvbnRhaW5pbmdDbGFzcy5nZXROYW1lKCl9LyR7ZmVhdHVyZS5nZXROYW1lKCl9YDtcclxuICAgIGVsc2VcclxuICAgICByZXR1cm4gYCMvLyR7dGhpcy5nZXRQYWNrYWdlUGF0aChjb250YWluaW5nQ2xhc3MuZ2V0RVBhY2thZ2UoKSl9LyR7Y29udGFpbmluZ0NsYXNzLmdldE5hbWUoKX0vJHtmZWF0dXJlLmdldE5hbWUoKX1gO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgYSByZWZlcmVuY2UgcGF0aCB0byBhIGNsYXNzaWZpZXIuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZFJlZmVyZW5jZVBhdGgoY2xhc3NpZmllcjogRUNsYXNzaWZpZXIsIGZyb21QYWNrYWdlOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjbGFzc2lmaWVyUGFja2FnZSA9IGNsYXNzaWZpZXIuZ2V0RVBhY2thZ2UoKTtcclxuICAgIFxyXG4gICAgLy8gSWYgaW4gc2FtZSBwYWNrYWdlLCB1c2Ugc2ltcGxlIHJlZmVyZW5jZVxyXG4gICAgLy8gaWYgKGNsYXNzaWZpZXJQYWNrYWdlID09PSBmcm9tUGFja2FnZSkge1xyXG4gICAgLy8gICByZXR1cm4gYCMvLyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuICAgIC8vIH1cclxuICAgIFxyXG4gICAgLy8gQnVpbGQgZnVsbCBwYXRoXHJcbiAgICBjb25zdCBwYXRoID0gdGhpcy5nZXRQYWNrYWdlUGF0aChjbGFzc2lmaWVyUGFja2FnZSk7XHJcbiAgICBpZihwYXRoLmxlbmd0aD4wKVxyXG4gICAgICByZXR1cm4gYCMvLyR7cGF0aC5qb2luKCcvJyl9LyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuXHJcbiAgICAvL3Jvb3QgcGFja2FnZSBlbGVtZW50cyBkb24ndCByZXF1aXJlIHBhdGhzXHJcbiAgICByZXR1cm4gYCMvLyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgcGF0aCB0byBhIHBhY2thZ2UgZnJvbSByb290LlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0UGFja2FnZVBhdGgocGtnOiBFUGFja2FnZSk6IHN0cmluZ1tdIHtcclxuICAgIGNvbnN0IHBhdGg6IHN0cmluZ1tdID0gW107XHJcbiAgICBsZXQgY3VycmVudCA9IHBrZztcclxuICAgIFxyXG4gICAgd2hpbGUgKGN1cnJlbnQpIHtcclxuICAgICAgcGF0aC51bnNoaWZ0KGN1cnJlbnQuZ2V0TmFtZSgpKTtcclxuICAgICAgY3VycmVudCA9IGN1cnJlbnQuZ2V0RVN1cGVyUGFja2FnZSgpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBSZW1vdmUgcm9vdCBwYWNrYWdlIG5hbWUgZnJvbSBwYXRoXHJcbiAgICBpZiAocGF0aC5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHBhdGguc2hpZnQoKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuIHBhdGg7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEVzY2FwZXMgc3BlY2lhbCBYTUwgY2hhcmFjdGVycy5cclxuICAgKi9cclxuICBwcml2YXRlIGVzY2FwZVhtbChzdHI6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAoIXN0cikgcmV0dXJuICcnO1xyXG4gICAgcmV0dXJuIHN0clxyXG4gICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxyXG4gICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpXHJcbiAgICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcclxuICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxyXG4gICAgICAucmVwbGFjZSgvJy9nLCAnJmFwb3M7Jyk7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgaW5kZW50YXRpb24gc3RyaW5nLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0SW5kZW50KCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5pbmRlbnRTdHJpbmcucmVwZWF0KHRoaXMuaW5kZW50TGV2ZWwpO1xyXG4gIH1cclxufSJdfQ==