UNPKG

@tripsnek/tmf

Version:

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

354 lines 46.8 kB
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, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&apos;'); } /** * Gets the current indentation string. */ getIndent() { return this.indentString.repeat(this.indentLevel); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNvcmUtc3RyaW5nLXdyaXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZWNvcmUvZWNvcmUtc3RyaW5nLXdyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFXQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzlELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDdEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0Qzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDaEIsWUFBWSxHQUFHLElBQUksQ0FBQztJQUU1Qjs7OztPQUlHO0lBQ0ksYUFBYSxDQUFDLFFBQWtCO1FBQ3JDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pELE9BQU8sMkNBQTJDLEdBQUcsRUFBRSxDQUFDO0lBQzFELENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWUsQ0FBQyxRQUFrQixFQUFFLFNBQWtCLEtBQUs7UUFDakUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hDLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUViLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxnREFBZ0Q7WUFDaEQsR0FBRyxHQUFHO3dEQUM0QyxDQUFDO1FBQ3JELENBQUM7YUFBTSxDQUFDO1lBQ04sR0FBRyxHQUFHLEdBQUcsTUFBTSxlQUFlLENBQUM7UUFDakMsQ0FBQztRQUVELHlCQUF5QjtRQUN6QixHQUFHLElBQUksVUFBVSxJQUFJLENBQUMsU0FBUyxDQUFDLFFB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O0lBQ0ssY0FBYyxDQUFDLEdBQWE7UUFDbEMsTUFBTSxJQUFJLEdBQWEsRUFBRSxDQUFDO1FBQzFCLElBQUksT0FBTyxHQUFHLEdBQUcsQ0FBQztRQUVsQixPQUFPLE9BQU8sRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNoQyxPQUFPLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdkMsQ0FBQztRQUVELHFDQUFxQztRQUNyQyxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0ssU0FBUyxDQUFDLEdBQVc7UUFDM0IsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUNwQixPQUFPLEdBQUc7YUFDUCxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQzthQUN0QixPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQzthQUNyQixPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQzthQUNyQixPQUFPLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQzthQUN2QixPQUFPLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNLLFNBQVM7UUFDZixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNwRCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFUGFja2FnZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZXBhY2thZ2UuanMnO1xyXG5pbXBvcnQgeyBFQ2xhc3MgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VjbGFzcy5qcyc7XHJcbmltcG9ydCB7IEVDbGFzc2lmaWVyIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lY2xhc3NpZmllci5qcyc7XHJcbmltcG9ydCB7IEVEYXRhVHlwZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZWRhdGEtdHlwZS5qcyc7XHJcbmltcG9ydCB7IEVFbnVtIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lZW51bS5qcyc7XHJcbmltcG9ydCB7IEVTdHJ1Y3R1cmFsRmVhdHVyZSB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZXN0cnVjdHVyYWwtZmVhdHVyZS5qcyc7XHJcbmltcG9ydCB7IEVBdHRyaWJ1dGUgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VhdHRyaWJ1dGUuanMnO1xyXG5pbXBvcnQgeyBFUmVmZXJlbmNlIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lcmVmZXJlbmNlLmpzJztcclxuaW1wb3J0IHsgRU9wZXJhdGlvbiB9IGZyb20gJy4uL21ldGFtb2RlbC9hcGkvZW9wZXJhdGlvbi5qcyc7XHJcbmltcG9ydCB7IEVQYXJhbWV0ZXIgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VwYXJhbWV0ZXIuanMnO1xyXG5pbXBvcnQgeyBFRW51bUxpdGVyYWwgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VlbnVtLWxpdGVyYWwuanMnO1xyXG5pbXBvcnQgeyBFRW51bUltcGwgfSBmcm9tICcuLi9tZXRhbW9kZWwvaW1wbC9lZW51bS1pbXBsLmpzJztcclxuaW1wb3J0IHsgRUNsYXNzSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VjbGFzcy1pbXBsLmpzJztcclxuaW1wb3J0IHsgRURhdGFUeXBlSW1wbCB9IGZyb20gJy4uL21ldGFtb2RlbC9pbXBsL2VkYXRhLXR5cGUtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVBdHRyaWJ1dGVJbXBsIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2ltcGwvZWF0dHJpYnV0ZS1pbXBsLmpzJztcclxuaW1wb3J0IHsgVFV0aWxzIH0gZnJvbSAnLi4vdHV0aWxzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBXcml0ZXMgRVBhY2thZ2UgbWV0YW1vZGVscyB0byBFY29yZSBYTUwgc3RyaW5nIGZvcm1hdC5cclxuICogVGhpcyBjbGFzcyBoYW5kbGVzIHRoZSBjb3JlIHdyaXRpbmcgbG9naWMgd2l0aG91dCBmaWxlIHN5c3RlbSBkZXBlbmRlbmNpZXMuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgRWNvcmVTdHJpbmdXcml0ZXIge1xyXG4gIHByaXZhdGUgaW5kZW50TGV2ZWwgPSAwO1xyXG4gIHByaXZhdGUgaW5kZW50U3RyaW5nID0gJyAgJztcclxuICBcclxuICAvKipcclxuICAgKiBDb252ZXJ0cyBhbiBFUGFja2FnZSB0byBFY29yZSBYTUwgc3RyaW5nIGZvcm1hdC5cclxuICAgKiBAcGFyYW0gZVBhY2thZ2UgVGhlIHJvb3QgcGFja2FnZSB0byBzZXJpYWxpemVcclxuICAgKiBAcmV0dXJucyBUaGUgWE1MIHN0cmluZyByZXByZXNlbnRhdGlvblxyXG4gICAqL1xyXG4gIHB1YmxpYyB3cml0ZVRvU3RyaW5nKGVQYWNrYWdlOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCB4bWwgPSB0aGlzLmJ1aWxkUGFja2FnZVhtbChlUGFja2FnZSwgdHJ1ZSk7XHJcbiAgICByZXR1cm4gYDw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIlVURi04XCI/PlxcbiR7eG1sfWA7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhIHBhY2thZ2UuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZFBhY2thZ2VYbWwoZVBhY2thZ2U6IEVQYWNrYWdlLCBpc1Jvb3Q6IGJvb2xlYW4gPSBmYWxzZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBpbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xyXG4gICAgbGV0IHhtbCA9ICcnO1xyXG4gICAgXHJcbiAgICBpZiAoaXNSb290KSB7XHJcbiAgICAgIC8vIFJvb3QgcGFja2FnZSB3aXRoIGZ1bGwgbmFtZXNwYWNlIGRlY2xhcmF0aW9uc1xyXG4gICAgICB4bWwgPSBgPGVjb3JlOkVQYWNrYWdlIHhtaTp2ZXJzaW9uPVwiMi4wXCIgeG1sbnM6eG1pPVwiaHR0cDovL3d3dy5vbWcub3JnL1hNSVwiIHhtbG5zOnhzaT1cImh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlXCJcclxuICAgIHhtbG5zOmVjb3JlPVwiaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9lbWYvMjAwMi9FY29yZVwiYDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHhtbCA9IGAke2luZGVudH08ZVN1YnBhY2thZ2VzYDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gQWRkIHBhY2thZ2UgYXR0cmlidXRlc1xyXG4gICAgeG1sICs9IGAgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwoZVBhY2thZ2UuZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBpZiAoZVBhY2thZ2UuZ2V0TnNVUkkoKSkge1xyXG4gICAgICB4bWwgKz0gYCBuc1VSST1cIiR7dGhpcy5lc2NhcGVYbWwoZVBhY2thZ2UuZ2V0TnNVUkkoKSl9XCJgO1xyXG4gICAgfVxyXG4gICAgaWYgKGVQYWNrYWdlLmdldE5zUHJlZml4KCkpIHtcclxuICAgICAgeG1sICs9IGAgbnNQcmVmaXg9XCIke3RoaXMuZXNjYXBlWG1sKGVQYWNrYWdlLmdldE5zUHJlZml4KCkpfVwiYDtcclxuICAgIH1cclxuICAgIHhtbCArPSAnPic7XHJcbiAgICBcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcclxuICAgIFxyXG4gICAgLy8gQWRkIGNsYXNzaWZpZXJzXHJcbiAgICBmb3IgKGNvbnN0IGNsYXNzaWZpZXIgb2YgZVBhY2thZ2UuZ2V0RUNsYXNzaWZpZXJzKCkpIHtcclxuICAgICAgeG1sICs9ICdcXG4nICsgdGhpcy5idWlsZENsYXNzaWZpZXJYbWwoY2xhc3NpZmllciwgZVBhY2thZ2UpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgc3VicGFja2FnZXNcclxuICAgIGZvciAoY29uc3Qgc3ViUGFja2FnZSBvZiBlUGFja2FnZS5nZXRFU3ViUGFja2FnZXMoKSkge1xyXG4gICAgICB4bWwgKz0gJ1xcbicgKyB0aGlzLmJ1aWxkUGFja2FnZVhtbChzdWJQYWNrYWdlLCBmYWxzZSk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwtLTtcclxuICAgIFxyXG4gICAgaWYgKGlzUm9vdCkge1xyXG4gICAgICB4bWwgKz0gJ1xcbjwvZWNvcmU6RVBhY2thZ2U+JztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHhtbCArPSBgXFxuJHtpbmRlbnR9PC9lU3VicGFja2FnZXM+YDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuIHhtbDtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogQnVpbGRzIHRoZSBYTUwgZm9yIGEgY2xhc3NpZmllciAoRUNsYXNzLCBFRW51bSwgb3IgRURhdGFUeXBlKS5cclxuICAgKi9cclxuICBwcml2YXRlIGJ1aWxkQ2xhc3NpZmllclhtbChjbGFzc2lmaWVyOiBFQ2xhc3NpZmllciwgY29udGFpbmluZ1BhY2thZ2U6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGluZGVudCA9IHRoaXMuZ2V0SW5kZW50KCk7XHJcbiAgICBcclxuICAgIGlmIChjbGFzc2lmaWVyIGluc3RhbmNlb2YgRUVudW1JbXBsKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmJ1aWxkRW51bVhtbChjbGFzc2lmaWVyIGFzIEVFbnVtKTtcclxuICAgIH0gZWxzZSBpZiAoY2xhc3NpZmllciBpbnN0YW5jZW9mIEVDbGFzc0ltcGwpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuYnVpbGRDbGFzc1htbChjbGFzc2lmaWVyIGFzIEVDbGFzcywgY29udGFpbmluZ1BhY2thZ2UpO1xyXG4gICAgfSBlbHNlIGlmIChjbGFzc2lmaWVyIGluc3RhbmNlb2YgRURhdGFUeXBlSW1wbCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5idWlsZERhdGFUeXBlWG1sKGNsYXNzaWZpZXIgYXMgRURhdGFUeXBlKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuICcnO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgdGhlIFhNTCBmb3IgYW4gRUNsYXNzLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYnVpbGRDbGFzc1htbChlQ2xhc3M6IEVDbGFzcywgY29udGFpbmluZ1BhY2thZ2U6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGluZGVudCA9IHRoaXMuZ2V0SW5kZW50KCk7XHJcbiAgICBsZXQgeG1sID0gYCR7aW5kZW50fTxlQ2xhc3NpZmllcnMgeHNpOnR5cGU9XCJlY29yZTpFQ2xhc3NcIiBuYW1lPVwiJHt0aGlzLmVzY2FwZVhtbChlQ2xhc3MuZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBcclxuICAgIC8vIEFkZCBzdXBlciB0eXBlcyBpZiBhbnlcclxuICAgIGNvbnN0IHN1cGVyVHlwZXMgPSBlQ2xhc3MuZ2V0RVN1cGVyVHlwZXMoKTtcclxuICAgIGlmIChzdXBlclR5cGVzICYmIHN1cGVyVHlwZXMuc2l6ZSgpID4gMCkge1xyXG4gICAgICBjb25zdCBzdXBlclR5cGVSZWZzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN1cGVyVHlwZXMuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgICBjb25zdCBzdXBlclR5cGUgPSBzdXBlclR5cGVzLmdldChpKTtcclxuICAgICAgICBzdXBlclR5cGVSZWZzLnB1c2godGhpcy5nZXRDbGFzc2lmaWVyUmVmZXJlbmNlKHN1cGVyVHlwZSwgY29udGFpbmluZ1BhY2thZ2UpKTtcclxuICAgICAgfVxyXG4gICAgICB4bWwgKz0gYCBlU3VwZXJUeXBlcz1cIiR7c3VwZXJUeXBlUmVmcy5qb2luKCcgJyl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgYWJzdHJhY3QvaW50ZXJmYWNlIGZsYWdzIGlmIHNldFxyXG4gICAgaWYgKGVDbGFzcy5pc0Fic3RyYWN0KCkpIHtcclxuICAgICAgeG1sICs9ICcgYWJzdHJhY3Q9XCJ0cnVlXCInO1xyXG4gICAgfVxyXG4gICAgaWYgKGVDbGFzcy5pc0ludGVyZmFjZSgpKSB7XHJcbiAgICAgIHhtbCArPSAnIGludGVyZmFjZT1cInRydWVcIic7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIENoZWNrIGlmIGNsYXNzIGhhcyBjb250ZW50XHJcbiAgICBjb25zdCBoYXNGZWF0dXJlcyA9IGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkgJiYgZUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKS5zaXplKCkgPiAwO1xyXG4gICAgY29uc3QgaGFzT3BlcmF0aW9ucyA9IGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpICYmIGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpLnNpemUoKSA+IDA7XHJcbiAgICBcclxuICAgIGlmICghaGFzRmVhdHVyZXMgJiYgIWhhc09wZXJhdGlvbnMpIHtcclxuICAgICAgeG1sICs9ICcvPic7XHJcbiAgICAgIHJldHVybiB4bWw7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHhtbCArPSAnPic7XHJcbiAgICB0aGlzLmluZGVudExldmVsKys7XHJcbiAgICBcclxuICAgIC8vIEFkZCBvcGVyYXRpb25zXHJcbiAgICBpZiAoaGFzT3BlcmF0aW9ucykge1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVDbGFzcy5nZXRFT3BlcmF0aW9ucygpLnNpemUoKTsgaSsrKSB7XHJcbiAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gZUNsYXNzLmdldEVPcGVyYXRpb25zKCkuZ2V0KGkpO1xyXG4gICAgICAgIHhtbCArPSAnXFxuJyArIHRoaXMuYnVpbGRPcGVyYXRpb25YbWwob3BlcmF0aW9uLCBjb250YWluaW5nUGFja2FnZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gQWRkIHN0cnVjdHVyYWwgZmVhdHVyZXNcclxuICAgIGlmIChoYXNGZWF0dXJlcykge1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVDbGFzcy5nZXRFU3RydWN0dXJhbEZlYXR1cmVzKCkuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgICBjb25zdCBmZWF0dXJlID0gZUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZXMoKS5nZXQoaSk7XHJcbiAgICAgICAgeG1sICs9ICdcXG4nICsgdGhpcy5idWlsZEZlYXR1cmVYbWwoZmVhdHVyZSwgY29udGFpbmluZ1BhY2thZ2UpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwtLTtcclxuICAgIHhtbCArPSBgXFxuJHtpbmRlbnR9PC9lQ2xhc3NpZmllcnM+YDtcclxuICAgIFxyXG4gICAgcmV0dXJuIHhtbDtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogQnVpbGRzIHRoZSBYTUwgZm9yIGFuIEVPcGVyYXRpb24uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZE9wZXJhdGlvblhtbChvcGVyYXRpb246IEVPcGVyYXRpb24sIGNvbnRhaW5pbmdQYWNrYWdlOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBpbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xyXG4gICAgbGV0IHhtbCA9IGAke2luZGVudH08ZU9wZXJhdGlvbnMgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwob3BlcmF0aW9uLmdldE5hbWUoKSl9XCJgO1xyXG4gICAgXHJcbiAgICAvLyBBZGQgcmV0dXJuIHR5cGUgaWYgcHJlc2VudFxyXG4gICAgaWYgKG9wZXJhdGlvbi5nZXRFVHlwZSgpKSB7XHJcbiAgICAgIHhtbCArPSBgIGVUeXBlPVwiJHt0aGlzLmdldENsYXNzaWZpZXJSZWZlcmVuY2Uob3BlcmF0aW9uLmdldEVUeXBlKCkhLCBjb250YWluaW5nUGFja2FnZSl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgdXBwZXIgYm91bmQgaWYgbm90IDFcclxuICAgIGlmIChvcGVyYXRpb24uZ2V0VXBwZXJCb3VuZCgpID09LTEpIHtcclxuICAgICAgeG1sICs9IGAgdXBwZXJCb3VuZD1cIiR7b3BlcmF0aW9uLmdldFVwcGVyQm91bmQoKX1cImA7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIENoZWNrIGlmIG9wZXJhdGlvbiBoYXMgcGFyYW1ldGVyc1xyXG4gICAgY29uc3QgaGFzUGFyYW1ldGVycyA9IG9wZXJhdGlvbi5nZXRFUGFyYW1ldGVycygpICYmIG9wZXJhdGlvbi5nZXRFUGFyYW1ldGVycygpLnNpemUoKSA+IDA7XHJcbiAgICBcclxuICAgIGlmICghaGFzUGFyYW1ldGVycykge1xyXG4gICAgICB4bWwgKz0gJy8+JztcclxuICAgICAgcmV0dXJuIHhtbDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICc+JztcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcclxuICAgIFxyXG4gICAgLy8gQWRkIHBhcmFtZXRlcnNcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlcmF0aW9uLmdldEVQYXJhbWV0ZXJzKCkuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgY29uc3QgcGFyYW0gPSBvcGVyYXRpb24uZ2V0RVBhcmFtZXRlcnMoKS5nZXQoaSk7XHJcbiAgICAgIHhtbCArPSAnXFxuJyArIHRoaXMuYnVpbGRQYXJhbWV0ZXJYbWwocGFyYW0sIGNvbnRhaW5pbmdQYWNrYWdlKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgdGhpcy5pbmRlbnRMZXZlbC0tO1xyXG4gICAgeG1sICs9IGBcXG4ke2luZGVudH08L2VPcGVyYXRpb25zPmA7XHJcbiAgICBcclxuICAgIHJldHVybiB4bWw7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhbiBFUGFyYW1ldGVyLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYnVpbGRQYXJhbWV0ZXJYbWwocGFyYW1ldGVyOiBFUGFyYW1ldGVyLCBjb250YWluaW5nUGFja2FnZTogRVBhY2thZ2UpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaW5kZW50ID0gdGhpcy5nZXRJbmRlbnQoKTtcclxuICAgIGxldCB4bWwgPSBgJHtpbmRlbnR9PGVQYXJhbWV0ZXJzIG5hbWU9XCIke3RoaXMuZXNjYXBlWG1sKHBhcmFtZXRlci5nZXROYW1lKCkpfVwiYDtcclxuICAgIFxyXG4gICAgaWYgKHBhcmFtZXRlci5nZXRVcHBlckJvdW5kKCk9PS0xKSB7XHJcbiAgICAgIHhtbCArPSBgIHVwcGVyQm91bmQ9XCIke3BhcmFtZXRlci5nZXRVcHBlckJvdW5kKCl9XCJgO1xyXG4gICAgfVxyXG5cclxuICAgIC8vVE9ETzogbG93ZXIgYm91bmRzIGZvciBvcHRpb25hbCBwYXJhbWV0ZXJzPyBzaW5jZSB3ZSBjYW4gc3VwcG9ydCB0aG9zZSBpbiB0eXBlc2NyaXB0XHJcblxyXG4gICAgaWYgKHBhcmFtZXRlci5nZXRFVHlwZSgpKSB7XHJcbiAgICAgIHhtbCArPSBgIGVUeXBlPVwiJHt0aGlzLmdldENsYXNzaWZpZXJSZWZlcmVuY2UocGFyYW1ldGVyLmdldEVUeXBlKCksIGNvbnRhaW5pbmdQYWNrYWdlKX1cImA7XHJcbiAgICB9XHJcbiAgICAgIFxyXG4gICAgeG1sICs9ICcvPic7XHJcbiAgICByZXR1cm4geG1sO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgdGhlIFhNTCBmb3IgYSBzdHJ1Y3R1cmFsIGZlYXR1cmUgKEVBdHRyaWJ1dGUgb3IgRVJlZmVyZW5jZSkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZEZlYXR1cmVYbWwoZmVhdHVyZTogRVN0cnVjdHVyYWxGZWF0dXJlLCBjb250YWluaW5nUGFja2FnZTogRVBhY2thZ2UpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaW5kZW50ID0gdGhpcy5nZXRJbmRlbnQoKTtcclxuICAgIGNvbnN0IGlzQXR0cmlidXRlID0gZmVhdHVyZSBpbnN0YW5jZW9mIEVBdHRyaWJ1dGVJbXBsO1xyXG4gICAgY29uc3QgZmVhdHVyZVR5cGUgPSBpc0F0dHJpYnV0ZSA/ICdlY29yZTpFQXR0cmlidXRlJyA6ICdlY29yZTpFUmVmZXJlbmNlJztcclxuICAgIFxyXG4gICAgbGV0IHhtbCA9IGAke2luZGVudH08ZVN0cnVjdHVyYWxGZWF0dXJlcyB4c2k6dHlwZT1cIiR7ZmVhdHVyZVR5cGV9XCIgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwoZmVhdHVyZS5nZXROYW1lKCkpfVwiYDtcclxuICAgIFxyXG4gICAgLy8gQWRkIHR5cGVcclxuICAgIGlmIChmZWF0dXJlLmdldEVUeXBlKCkpIHtcclxuICAgICAgeG1sICs9IGAgZVR5cGU9XCIke3RoaXMuZ2V0Q2xhc3NpZmllclJlZmVyZW5jZShmZWF0dXJlLmdldEVUeXBlKCkhLCBjb250YWluaW5nUGFja2FnZSl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvL1RPRE86IGxvd2VyYm91bmQ/IG9ubHkgc2VlbXMgdG8gbWFrZSBzZW5zZSBpZiB3ZSBoYXZlICdyZXF1aXJlZCcgZmVhdHVyZXMgIFxyXG4gICAgaWYgKGZlYXR1cmUuZ2V0VXBwZXJCb3VuZCgpPT0tMSkge1xyXG4gICAgICB4bWwgKz0gYCB1cHBlckJvdW5kPVwiJHtmZWF0dXJlLmdldFVwcGVyQm91bmQoKX1cImA7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIEFkZCBmZWF0dXJlLXNwZWNpZmljIGF0dHJpYnV0ZXNcclxuICAgIGlmIChpc0F0dHJpYnV0ZSkge1xyXG4gICAgICBjb25zdCBhdHRyID0gZmVhdHVyZSBhcyBFQXR0cmlidXRlO1xyXG4gICAgICBpZiAoYXR0ci5pc0lkKCkpIHtcclxuICAgICAgICB4bWwgKz0gJyBpRD1cInRydWVcIic7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IHJlZiA9IGZlYXR1cmUgYXMgRVJlZmVyZW5jZTtcclxuICAgICAgaWYgKHJlZi5pc0NvbnRhaW5tZW50KCkpIHtcclxuICAgICAgICB4bWwgKz0gJyBjb250YWlubWVudD1cInRydWVcIic7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHJlZi5nZXRFT3Bwb3NpdGUoKSkge1xyXG4gICAgICAgIHhtbCArPSBgIGVPcHBvc2l0ZT1cIiR7dGhpcy5nZXRGZWF0dXJlUmVmZXJlbmNlKHJlZi5nZXRFT3Bwb3NpdGUoKSEpfVwiYDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBBZGQgb3RoZXIgcHJvcGVydGllc1xyXG4gICAgaWYgKGZlYXR1cmUuaXNUcmFuc2llbnQoKSkge1xyXG4gICAgICB4bWwgKz0gJyB0cmFuc2llbnQ9XCJ0cnVlXCInO1xyXG4gICAgfVxyXG4gICAgLy8gaWYgKGZlYXR1cmUuaXNEZXJpdmVkKCkpIHtcclxuICAgIC8vICAgeG1sICs9ICcgZGVyaXZlZD1cInRydWVcIic7XHJcbiAgICAvLyB9XHJcbiAgICBpZiAoIWZlYXR1cmUuaXNDaGFuZ2VhYmxlKCkpIHtcclxuICAgICAgeG1sICs9ICcgY2hhbmdlYWJsZT1cImZhbHNlXCInO1xyXG4gICAgfVxyXG4gICAgaWYgKGZlYXR1cmUuaXNWb2xhdGlsZSgpKSB7XHJcbiAgICAgIHhtbCArPSAnIHZvbGF0aWxlPVwidHJ1ZVwiJztcclxuICAgIH1cclxuICAgIGlmIChmZWF0dXJlLmdldERlZmF1bHRWYWx1ZUxpdGVyYWwoKSkge1xyXG4gICAgICB4bWwgKz0gYCBkZWZhdWx0VmFsdWVMaXRlcmFsPVwiJHt0aGlzLmVzY2FwZVhtbChmZWF0dXJlLmdldERlZmF1bHRWYWx1ZUxpdGVyYWwoKSl9XCJgO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICB4bWwgKz0gJy8+JztcclxuICAgIHJldHVybiB4bWw7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhbiBFRW51bS5cclxuICAgKi9cclxuICBwcml2YXRlIGJ1aWxkRW51bVhtbChlRW51bTogRUVudW0pOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaW5kZW50ID0gdGhpcy5nZXRJbmRlbnQoKTtcclxuICAgIGxldCB4bWwgPSBgJHtpbmRlbnR9PGVDbGFzc2lmaWVycyB4c2k6dHlwZT1cImVjb3JlOkVFbnVtXCIgbmFtZT1cIiR7dGhpcy5lc2NhcGVYbWwoZUVudW0uZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBcclxuICAgIGNvbnN0IGhhc0xpdGVyYWxzID0gZUVudW0uZ2V0RUxpdGVyYWxzKCkgJiYgZUVudW0uZ2V0RUxpdGVyYWxzKCkuc2l6ZSgpID4gMDtcclxuICAgIFxyXG4gICAgaWYgKCFoYXNMaXRlcmFscykge1xyXG4gICAgICB4bWwgKz0gJy8+JztcclxuICAgICAgcmV0dXJuIHhtbDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICc+JztcclxuICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcclxuICAgIFxyXG4gICAgLy8gQWRkIGVudW0gbGl0ZXJhbHNcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZUVudW0uZ2V0RUxpdGVyYWxzKCkuc2l6ZSgpOyBpKyspIHtcclxuICAgICAgY29uc3QgbGl0ZXJhbCA9IGVFbnVtLmdldEVMaXRlcmFscygpLmdldChpKTtcclxuICAgICAgeG1sICs9ICdcXG4nICsgdGhpcy5idWlsZEVudW1MaXRlcmFsWG1sKGxpdGVyYWwpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICB0aGlzLmluZGVudExldmVsLS07XHJcbiAgICB4bWwgKz0gYFxcbiR7aW5kZW50fTwvZUNsYXNzaWZpZXJzPmA7XHJcbiAgICBcclxuICAgIHJldHVybiB4bWw7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyB0aGUgWE1MIGZvciBhbiBFRW51bUxpdGVyYWwuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZEVudW1MaXRlcmFsWG1sKGxpdGVyYWw6IEVFbnVtTGl0ZXJhbCk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBpbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xyXG4gICAgbGV0IHhtbCA9IGAke2luZGVudH08ZUxpdGVyYWxzIG5hbWU9XCIke3RoaXMuZXNjYXBlWG1sKGxpdGVyYWwuZ2V0TmFtZSgpKX1cImA7XHJcbiAgICBcclxuICAgIGlmIChsaXRlcmFsLmdldFZhbHVlKCkgIT09IHVuZGVmaW5lZCAmJiBsaXRlcmFsLmdldFZhbHVlKCkgIT09IG51bGwpIHtcclxuICAgICAgeG1sICs9IGAgdmFsdWU9XCIke2xpdGVyYWwuZ2V0VmFsdWUoKX1cImA7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIGlmIChsaXRlcmFsLmdldExpdGVyYWwoKSAmJiBsaXRlcmFsLmdldExpdGVyYWwoKSAhPT0gbGl0ZXJhbC5nZXROYW1lKCkpIHtcclxuICAgICAgeG1sICs9IGAgbGl0ZXJhbD1cIiR7dGhpcy5lc2NhcGVYbWwobGl0ZXJhbC5nZXRMaXRlcmFsKCkpfVwiYDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICcvPic7XHJcbiAgICByZXR1cm4geG1sO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgdGhlIFhNTCBmb3IgYW4gRURhdGFUeXBlLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYnVpbGREYXRhVHlwZVhtbChkYXRhVHlwZTogRURhdGFUeXBlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGluZGVudCA9IHRoaXMuZ2V0SW5kZW50KCk7XHJcbiAgICBsZXQgeG1sID0gYCR7aW5kZW50fTxlQ2xhc3NpZmllcnMgeHNpOnR5cGU9XCJlY29yZTpFRGF0YVR5cGVcIiBuYW1lPVwiJHt0aGlzLmVzY2FwZVhtbChkYXRhVHlwZS5nZXROYW1lKCkpfVwiYDtcclxuICAgIFxyXG4gICAgLy8gaWYgKGRhdGFUeXBlLmdldEluc3RhbmNlQ2xhc3NOYW1lKCkpIHtcclxuICAgIC8vICAgeG1sICs9IGAgaW5zdGFuY2VDbGFzc05hbWU9XCIke3RoaXMuZXNjYXBlWG1sKGRhdGFUeXBlLmdldEluc3RhbmNlQ2xhc3NOYW1lKCkpfVwiYDtcclxuICAgIC8vIH1cclxuICAgIFxyXG4gICAgeG1sICs9ICcvPic7XHJcbiAgICByZXR1cm4geG1sO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBHZXRzIGEgcmVmZXJlbmNlIHN0cmluZyBmb3IgYSBjbGFzc2lmaWVyLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0Q2xhc3NpZmllclJlZmVyZW5jZShjbGFzc2lmaWVyOiBFQ2xhc3NpZmllciwgZnJvbVBhY2thZ2U6IEVQYWNrYWdlKTogc3RyaW5nIHtcclxuICAgIC8vIENoZWNrIGlmIGl0J3MgYSBwcmltaXRpdmUgdHlwZVxyXG4gICAgY29uc3QgcHJpbWl0aXZlVHlwZXMgPSBUVXRpbHMuUFJJTUlUSVZFUztcclxuICAgIGlmIChwcmltaXRpdmVUeXBlcy5pbmNsdWRlcyhjbGFzc2lmaWVyLmdldE5hbWUoKSkpIHtcclxuICAgICAgcmV0dXJuIGBlY29yZTpFRGF0YVR5cGUgaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9lbWYvMjAwMi9FY29yZSMvLyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gQnVpbGQgcmVmZXJlbmNlIHBhdGhcclxuICAgIHJldHVybiB0aGlzLmJ1aWxkUmVmZXJlbmNlUGF0aChjbGFzc2lmaWVyLCBmcm9tUGFja2FnZSk7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEdldHMgYSByZWZlcmVuY2Ugc3RyaW5nIGZvciBhIGZlYXR1cmUuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXRGZWF0dXJlUmVmZXJlbmNlKGZlYXR1cmU6IEVTdHJ1Y3R1cmFsRmVhdHVyZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjb250YWluaW5nQ2xhc3MgPSBmZWF0dXJlLmdldEVDb250YWluaW5nQ2xhc3MoKTtcclxuICAgIGlmICghY29udGFpbmluZ0NsYXNzKSB7XHJcbiAgICAgIHJldHVybiBgIy8vJHtmZWF0dXJlLmdldE5hbWUoKX1gO1xyXG4gICAgfVxyXG4gICAgLy9yb290IHBhY2thZ2VzIGRvbid0IHJlcXVpcmUgcGFja2FnZSBwYXRoc1xyXG4gICAgaWYoIWNvbnRhaW5pbmdDbGFzcy5nZXRFUGFja2FnZSgpLmdldEVTdXBlclBhY2thZ2UoKSlcclxuICAgICAgcmV0dXJuIGAjLy8ke2NvbnRhaW5pbmdDbGFzcy5nZXROYW1lKCl9LyR7ZmVhdHVyZS5nZXROYW1lKCl9YDtcclxuICAgIGVsc2VcclxuICAgICByZXR1cm4gYCMvLyR7dGhpcy5nZXRQYWNrYWdlUGF0aChjb250YWluaW5nQ2xhc3MuZ2V0RVBhY2thZ2UoKSl9LyR7Y29udGFpbmluZ0NsYXNzLmdldE5hbWUoKX0vJHtmZWF0dXJlLmdldE5hbWUoKX1gO1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBCdWlsZHMgYSByZWZlcmVuY2UgcGF0aCB0byBhIGNsYXNzaWZpZXIuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZFJlZmVyZW5jZVBhdGgoY2xhc3NpZmllcjogRUNsYXNzaWZpZXIsIGZyb21QYWNrYWdlOiBFUGFja2FnZSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjbGFzc2lmaWVyUGFja2FnZSA9IGNsYXNzaWZpZXIuZ2V0RVBhY2thZ2UoKTtcclxuICAgIFxyXG4gICAgLy8gSWYgaW4gc2FtZSBwYWNrYWdlLCB1c2Ugc2ltcGxlIHJlZmVyZW5jZVxyXG4gICAgLy8gaWYgKGNsYXNzaWZpZXJQYWNrYWdlID09PSBmcm9tUGFja2FnZSkge1xyXG4gICAgLy8gICByZXR1cm4gYCMvLyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuICAgIC8vIH1cclxuICAgIFxyXG4gICAgLy8gQnVpbGQgZnVsbCBwYXRoXHJcbiAgICBjb25zdCBwYXRoID0gdGhpcy5nZXRQYWNrYWdlUGF0aChjbGFzc2lmaWVyUGFja2FnZSk7XHJcbiAgICBpZihwYXRoLmxlbmd0aD4wKVxyXG4gICAgICByZXR1cm4gYCMvLyR7cGF0aC5qb2luKCcvJyl9LyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuXHJcbiAgICAvL3Jvb3QgcGFja2FnZSBlbGVtZW50cyBkb24ndCByZXF1aXJlIHBhdGhzXHJcbiAgICByZXR1cm4gYCMvLyR7Y2xhc3NpZmllci5nZXROYW1lKCl9YDtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgcGF0aCB0byBhIHBhY2thZ2UgZnJvbSByb290LlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0UGFja2FnZVBhdGgocGtnOiBFUGFja2FnZSk6IHN0cmluZ1tdIHtcclxuICAgIGNvbnN0IHBhdGg6IHN0cmluZ1tdID0gW107XHJcbiAgICBsZXQgY3VycmVudCA9IHBrZztcclxuICAgIFxyXG4gICAgd2hpbGUgKGN1cnJlbnQpIHtcclxuICAgICAgcGF0aC51bnNoaWZ0KGN1cnJlbnQuZ2V0TmFtZSgpKTtcclxuICAgICAgY3VycmVudCA9IGN1cnJlbnQuZ2V0RVN1cGVyUGFja2FnZSgpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBSZW1vdmUgcm9vdCBwYWNrYWdlIG5hbWUgZnJvbSBwYXRoXHJcbiAgICBpZiAocGF0aC5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHBhdGguc2hpZnQoKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgcmV0dXJuIHBhdGg7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEVzY2FwZXMgc3BlY2lhbCBYTUwgY2hhcmFjdGVycy5cclxuICAgKi9cclxuICBwcml2YXRlIGVzY2FwZVhtbChzdHI6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAoIXN0cikgcmV0dXJuICcnO1xyXG4gICAgcmV0dXJuIHN0clxyXG4gICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxyXG4gICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpXHJcbiAgICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcclxuICAgICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxyXG4gICAgICAucmVwbGFjZSgvJy9nLCAnJmFwb3M7Jyk7XHJcbiAgfVxyXG4gIFxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgaW5kZW50YXRpb24gc3RyaW5nLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0SW5kZW50KCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5pbmRlbnRTdHJpbmcucmVwZWF0KHRoaXMuaW5kZW50TGV2ZWwpO1xyXG4gIH1cclxufSJdfQ==