@tripsnek/tmf
Version:
TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)
425 lines • 53.8 kB
JavaScript
import { v4 as uuid } from 'uuid';
import { EcorePackage } from './metamodel/ecorepackage.js';
import { TJson } from './json/tjson.js';
import { EEnumImpl } from './metamodel/impl/eenum-impl.js';
import { EDataTypeImpl } from './metamodel/impl/edata-type-impl.js';
import { EClassImpl } from './metamodel/impl/eclass-impl.js';
/**
* Various utilities for interacting with TMF-modeled data objects, some
* of which are relied upon by core TMF components (e.g. TJson) and generated
* source code.
*/
export class TUtils {
//All primitive EDataTypes supported by TMF
static PRIMITIVES = [
'EString',
'EBoolean',
'EDouble',
'EDoubleObject',
'EFloat',
'EFloatObject',
'EInt',
'EIntegerObject',
'EDate',
];
/**
* Ensures all objects have IDs.
* @param obj
*/
static generateIdsForAllContained(obj) {
for (const e of obj.eAllContents())
this.genIdIfNotExists(e);
}
/**
* Sets an ID for the given object on it's ID EAttribute. If
* an ID is already specified, does nothing.
*
* @param obj
*/
static genIdIfNotExists(obj) {
//TODO: Support IDs other than string uuids
if (obj && obj.eClass().getEIDAttribute() && !obj.fullId()) {
obj.eSet(obj.eClass().getEIDAttribute(), uuid());
}
}
/**
* If an ID is specified on the object, returns a new TId instance with that ID value. If not, a
* new ID is assigned and that TId returned.
*
* @param obj
*/
static getOrCreateIdForObject(obj) {
this.genIdIfNotExists(obj);
return obj.fullId();
}
/**
* Gets the Typescript name for a given EClassifier, including
* translation of primitive EDataType names (e.g. EBoolean -> boolean).
* @param type
*/
static getTypescriptName(type) {
if (!type)
return 'null';
let typeStr = type.getName();
if (!(type instanceof EEnumImpl) && type instanceof EDataTypeImpl)
typeStr = TUtils.toTypeScriptPrimitive(type);
return typeStr;
}
/**
* Gets the TypeScript primitive type for a given TMF EClassifier that represents a
* primitive type.
* @param classifier
*/
static toTypeScriptPrimitive(classifier) {
if (!classifier || !classifier.getName())
return 'any';
switch (classifier.getName().toLowerCase()) {
case 'estring': {
return 'string';
break;
}
case 'eboolean': {
return 'boolean';
break;
}
case 'edouble': {
return 'number';
break;
}
case 'edoubleobject': {
return 'number';
break;
}
case 'efloat': {
return 'number';
break;
}
case 'efloatobject': {
return 'number';
break;
}
case 'eint': {
return 'number';
break;
}
case 'eintegerobject': {
return 'number';
break;
}
case 'edate': {
return 'Date';
break;
}
case 'earray': {
return '[]';
}
default: {
return 'any';
}
}
}
static lookupNamedField(object, fieldName) {
const curClass = object.eClass();
const field = curClass.getEStructuralFeature(fieldName);
if (!field) {
console.log(curClass.getName(), ' has no field named', fieldName);
return undefined;
}
return field;
}
static getNamedFieldValue(object, fieldName) {
const field = this.lookupNamedField(object, fieldName);
if (field)
return object.eGet(field);
return undefined;
}
static setNamedFieldValue(object, fieldName, newValue) {
const field = this.lookupNamedField(object, fieldName);
if (field)
object.eSet(field, newValue);
return undefined;
}
/**
* Parses a value for an EAttribute from it's JSON representation.
*
* @param attr
* @param jsonVal
*/
static parseAttrValFromString(attr, stringVal) {
return this.parseValueFromString(attr.getEType(), stringVal + '');
}
static parseValueFromString(attrType, stringVal) {
let tVal = null;
//if an empty string was set for the field, just return null
if (!stringVal ||
(stringVal.toString().trim() === '' &&
attrType !== EcorePackage.Literals.E_STRING)) {
return null;
}
if (attrType === EcorePackage.Literals.E_STRING) {
tVal = stringVal.toString();
}
else if (attrType === EcorePackage.Literals.E_DOUBLE ||
attrType === EcorePackage.Literals.E_DOUBLE_OBJECT) {
tVal = Number.parseFloat(stringVal.toString());
}
else if (attrType === EcorePackage.Literals.E_FLOAT ||
attrType === EcorePackage.Literals.E_FLOAT_OBJECT) {
tVal = Number.parseFloat(stringVal.toString());
}
else if (attrType === EcorePackage.Literals.E_BOOLEAN ||
attrType === EcorePackage.Literals.E_BOOLEAN_OBJECT) {
tVal = stringVal.toString() === 'true';
}
else if (attrType === EcorePackage.Literals.E_SHORT ||
attrType === EcorePackage.Literals.E_SHORT_OBJECT) {
tVal = Number.parseInt(stringVal.toString(), 10);
}
else if (attrType === EcorePackage.Literals.E_INT ||
attrType === EcorePackage.Literals.E_INTEGER_OBJECT) {
tVal = Number.parseInt(stringVal.toString(), 10);
}
else if (attrType === EcorePackage.Literals.E_LONG ||
attrType === EcorePackage.Literals.E_LONG_OBJECT) {
tVal = Number.parseInt(stringVal.toString(), 10);
}
else if (attrType === EcorePackage.Literals.E_DATE) {
tVal = new Date(Date.parse(stringVal));
}
else if (attrType instanceof EEnumImpl) {
const eenum = attrType;
const literal = eenum.getEEnumLiteral(stringVal.toString());
if (literal != null) {
tVal = literal.getLiteral();
}
else {
console.warn('Could not parse literal value ' +
stringVal.toString() +
' for ' +
eenum.getName());
}
}
return tVal;
}
/**
* Creates a deep copy of an Root and it's containment hierarchy, with optional
* lists for specifying specific EReferences to traverse or prune during the copy. New
* IDs will be assigned to all copied entities. Internal references will be preserved where possible.
*
* @param toClone - root of container containment hierarchy to copy
* @param prune - EReferences not to traverse during copy. If specified, these
* references will not be traversed during copy
* @param traverse - EReferences to traverse during copy. If specified, no EReference
* will be traversed unless it is in this list.
* @param target - Allows specification of an entity into which to copy data, which does not have
* to be of the same type as the copied entity (non-overlapping structure will be ignored).
* @returns the copy
*/
static clone(toClone, prune, traverse, target, oldToNewEntities) {
//create new instance
const newContainer = target
? target
: (toClone
.eClass()
.getEPackage()
.getEFactoryInstance()
.create(toClone.eClass()));
//map of old entities to new entities that will be filled in during the duplication
const oldToNew = oldToNewEntities
? oldToNewEntities
: new Map();
//recursive duplication of containment hierachy
this.cloneInto(toClone, newContainer, prune ? prune : [], traverse ? traverse : [], oldToNew);
//re-establish container internal references for all entities in the
//container, including the container root itself
const allOldEntities = toClone.eAllContents();
allOldEntities.push(toClone);
for (const oldEntity of allOldEntities) {
const newEntity = oldToNew.get(oldEntity);
if (newEntity) {
for (const eref of newEntity.eClass().getEAllReferences()) {
//only look at container internal references
if (!eref.isContainment() && !eref.isTransient()) {
const oldRefVal = oldEntity.eGet(eref);
if (oldRefVal) {
//handle many-valued references
if (eref.isMany()) {
const newRefList = newEntity.eGet(eref);
if (newRefList) {
for (const oldRef of oldRefVal) {
const newRef = oldToNew.get(oldRef);
if (newRef)
newRefList.add(newRef);
else if (oldRef)
newRefList.add(oldRef);
}
}
}
//handle single-valued references
else {
const newVal = oldToNew.get(oldRefVal);
if (newVal)
newEntity.eSet(eref, newVal);
else
newEntity.eSet(eref, oldRefVal);
}
}
}
}
}
}
return newContainer;
}
static cloneInto(copyFrom, copyInto, pruneOnlyTheseReferences, traverseOnlyTheseReferences, oldToNew) {
for (const attr of copyInto.eClass().getEAllAttributes()) {
if (!attr.isVolatile()) {
copyInto.eSet(attr, copyFrom.eGet(attr));
}
}
//assign new ID to entity
if (copyInto.eClass().getEIDAttribute())
copyInto.eSet(copyInto.eClass().getEIDAttribute(), uuid());
//register old to new entity in Map, if specified
if (oldToNew)
oldToNew.set(copyFrom, copyInto);
//recurse containments
for (const ref of copyInto.eClass().getEAllReferences()) {
//determine if reference should be traversed
let traverse = true;
//do not traverse pruned references
if (traverse && pruneOnlyTheseReferences) {
for (const toPrune of pruneOnlyTheseReferences) {
if (toPrune === ref)
traverse = false;
}
}
//do not traverse references not in the traverse list (if it is specified)
if (traverse && traverseOnlyTheseReferences) {
traverse = false;
for (const toPrune of traverseOnlyTheseReferences) {
if (toPrune === ref)
traverse = true;
}
}
//recursively copy the containment
if (traverse) {
if (ref.isContainment()) {
//many-valued containment
if (ref.isMany()) {
const list = copyInto.eGet(ref);
for (const toCopy of copyFrom.eGet(ref)) {
list.add(this.clone(toCopy, pruneOnlyTheseReferences, traverseOnlyTheseReferences, null, oldToNew));
}
}
//single valued containment
else {
const toCopy = copyFrom.eGet(ref);
if (toCopy) {
copyInto.eSet(ref, this.clone(toCopy, pruneOnlyTheseReferences, traverseOnlyTheseReferences, null, oldToNew));
}
}
}
//simply assign non-containment references if they have no eopposite
else if (!ref.getEOpposite() &&
!ref.isContainer() &&
!ref.isVolatile()) {
if (ref.isMany()) {
const list = copyInto.eGet(ref);
for (const member of copyFrom.eGet(ref))
list.add(member);
}
else
copyInto.eSet(ref, copyFrom.eGet(ref));
}
}
}
return copyInto;
}
static carbonCopy(obj) {
return TJson.makeEObject(TJson.makeJson(obj));
}
/**
* Overwrites all attributes values, and replaces all containments with
* carbon copies. Non-containment references are left alone.
*
* @param currentState
* @param newState
*/
static shallowUpdate(currentState, newState) {
//copy all EAttributes at the roote level
for (const attr of newState.eClass().getEAllAttributes()) {
if (!attr.isVolatile()) {
currentState.eSet(attr, newState.eGet(attr));
}
}
//replace all contained instances
for (const ref of newState.eClass().getEAllContainments()) {
if (ref.isMany()) {
const newContained = newState.eGet(ref);
if (newContained)
currentState.eSet(ref, this.carbonCopy(newContained));
else
currentState.eSet(ref, null);
}
else {
const currentContained = currentState.eGet(ref);
currentContained.clear();
const newContainedList = newState.eGet(ref);
for (const newContained of newContainedList) {
currentContained.add(this.carbonCopy(newContained));
}
}
}
}
/**
* Returns the package and transitive closure of all contained subpackages.
*
* @param pkg
* @returns
*/
static allPackagesRecursive(pkg, addTo) {
let pkgs = addTo ? addTo : [];
pkgs.push(pkg);
for (const sp of pkg.getESubPackages()) {
this.allPackagesRecursive(sp, pkgs);
}
return pkgs;
}
static getRootEClasses(root) {
if (!root)
return [];
const allPkgs = this.allPackagesRecursive(root);
const allClasses = [];
const containedClasses = new Set();
// First, collect all non-abstract, non-interface classes
for (const ePackage of allPkgs) {
ePackage.getEClassifiers().forEach((classifier) => {
if (classifier instanceof EClassImpl &&
!classifier.isAbstract() &&
!classifier.isInterface()) {
allClasses.push(classifier);
}
});
}
// Then, find which classes are contained by others
allClasses.forEach((eClass) => {
eClass.getEAllReferences().forEach((ref) => {
if (ref.isContainment()) {
const targetType = ref.getEType();
if (targetType instanceof EClassImpl) {
containedClasses.add(targetType);
// Also add all subtypes
allClasses.forEach((otherClass) => {
if (otherClass.getEAllSuperTypes().contains(targetType)) {
containedClasses.add(otherClass);
}
});
}
}
});
});
// Return classes that are not contained by any other class
return allClasses.filter((c) => !containedClasses.has(c)).reverse();
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi90dXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0EsT0FBTyxFQUFFLEVBQUUsSUFBSSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBSTNELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDM0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBSXBFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU3RDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLE1BQU07SUFDakIsMkNBQTJDO0lBQ3BDLE1BQU0sQ0FBQyxVQUFVLEdBQUc7UUFDekIsU0FBUztRQUNULFVBQVU7UUFDVixTQUFTO1FBQ1QsZUFBZTtRQUNmLFFBQVE7UUFDUixjQUFjO1FBQ2QsTUFBTTtRQUNOLGdCQUFnQjtRQUNoQixPQUFPO0tBQ1IsQ0FBQztJQUVGOzs7T0FHRztJQUNILE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxHQUFZO1FBQzVDLEtBQUssTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLFlBQVksRUFBRTtZQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBQ0Q7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsR0FBWTtRQUNsQywyQ0FBMkM7UUFDM0MsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDM0QsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMs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bW9kZWwvYXBpL2VjbGFzc2lmaWVyLmpzJztcbmltcG9ydCB7IEVPYmplY3QgfSBmcm9tICcuL21ldGFtb2RlbC9hcGkvZW9iamVjdC5qcyc7XG5pbXBvcnQgeyBFRW51bSB9IGZyb20gJy4vbWV0YW1vZGVsL2FwaS9lZW51bS5qcyc7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSAndXVpZCc7XG5pbXBvcnQgeyBFY29yZVBhY2thZ2UgfSBmcm9tICcuL21ldGFtb2RlbC9lY29yZXBhY2thZ2UuanMnO1xuaW1wb3J0IHsgRUF0dHJpYnV0ZSB9IGZyb20gJy4vbWV0YW1vZGVsL2FwaS9lYXR0cmlidXRlLmpzJztcbmltcG9ydCB7IEVTdHJ1Y3R1cmFsRmVhdHVyZSB9IGZyb20gJy4vbWV0YW1vZGVsL2FwaS9lc3RydWN0dXJhbC1mZWF0dXJlLmpzJztcbmltcG9ydCB7IEVSZWZlcmVuY2UgfSBmcm9tICcuL21ldGFtb2RlbC9hcGkvZXJlZmVyZW5jZS5qcyc7XG5pbXBvcnQgeyBUSnNvbiB9IGZyb20gJy4vanNvbi90anNvbi5qcyc7XG5pbXBvcnQgeyBFRW51bUltcGwgfSBmcm9tICcuL21ldGFtb2RlbC9pbXBsL2VlbnVtLWltcGwuanMnO1xuaW1wb3J0IHsgRURhdGFUeXBlSW1wbCB9IGZyb20gJy4vbWV0YW1vZGVsL2ltcGwvZWRhdGEtdHlwZS1pbXBsLmpzJztcbmltcG9ydCB7IEVMaXN0IH0gZnJvbSAnLi9tZXRhbW9kZWwvYXBpL2VsaXN0LmpzJztcbmltcG9ydCB7IEVDbGFzcyB9IGZyb20gJy4vbWV0YW1vZGVsL2FwaS9lY2xhc3MuanMnO1xuaW1wb3J0IHsgRVBhY2thZ2UgfSBmcm9tICcuL21ldGFtb2RlbC9hcGkvZXBhY2thZ2UuanMnO1xuaW1wb3J0IHsgRUNsYXNzSW1wbCB9IGZyb20gJy4vbWV0YW1vZGVsL2ltcGwvZWNsYXNzLWltcGwuanMnO1xuXG4vKipcbiAqIFZhcmlvdXMgdXRpbGl0aWVzIGZvciBpbnRlcmFjdGluZyB3aXRoIFRNRi1tb2RlbGVkIGRhdGEgb2JqZWN0cywgc29tZVxuICogb2Ygd2hpY2ggYXJlIHJlbGllZCB1cG9uIGJ5IGNvcmUgVE1GIGNvbXBvbmVudHMgKGUuZy4gVEpzb24pIGFuZCBnZW5lcmF0ZWRcbiAqIHNvdXJjZSBjb2RlLlxuICovXG5leHBvcnQgY2xhc3MgVFV0aWxzIHtcbiAgLy9BbGwgcHJpbWl0aXZlIEVEYXRhVHlwZXMgc3VwcG9ydGVkIGJ5IFRNRlxuICBwdWJsaWMgc3RhdGljIFBSSU1JVElWRVMgPSBbXG4gICAgJ0VTdHJpbmcnLFxuICAgICdFQm9vbGVhbicsXG4gICAgJ0VEb3VibGUnLFxuICAgICdFRG91YmxlT2JqZWN0JyxcbiAgICAnRUZsb2F0JyxcbiAgICAnRUZsb2F0T2JqZWN0JyxcbiAgICAnRUludCcsXG4gICAgJ0VJbnRlZ2VyT2JqZWN0JyxcbiAgICAnRURhdGUnLFxuICBdO1xuXG4gIC8qKlxuICAgKiBFbnN1cmVzIGFsbCBvYmplY3RzIGhhdmUgSURzLlxuICAgKiBAcGFyYW0gb2JqXG4gICAqL1xuICBzdGF0aWMgZ2VuZXJhdGVJZHNGb3JBbGxDb250YWluZWQob2JqOiBFT2JqZWN0KSB7XG4gICAgZm9yIChjb25zdCBlIG9mIG9iai5lQWxsQ29udGVudHMoKSkgdGhpcy5nZW5JZElmTm90RXhpc3RzKGUpO1xuICB9XG4gIC8qKlxuICAgKiBTZXRzIGFuIElEIGZvciB0aGUgZ2l2ZW4gb2JqZWN0IG9uIGl0J3MgSUQgRUF0dHJpYnV0ZS4gSWZcbiAgICogYW4gSUQgaXMgYWxyZWFkeSBzcGVjaWZpZWQsIGRvZXMgbm90aGluZy5cbiAgICpcbiAgICogQHBhcmFtIG9ialxuICAgKi9cbiAgc3RhdGljIGdlbklkSWZOb3RFeGlzdHMob2JqOiBFT2JqZWN0KSB7XG4gICAgLy9UT0RPOiBTdXBwb3J0IElEcyBvdGhlciB0aGFuIHN0cmluZyB1dWlkc1xuICAgIGlmIChvYmogJiYgb2JqLmVDbGFzcygpLmdldEVJREF0dHJpYnV0ZSgpICYmICFvYmouZnVsbElkKCkpIHtcbiAgICAgIG9iai5lU2V0KG9iai5lQ2xhc3MoKS5nZXRFSURBdHRyaWJ1dGUoKSBhcyBFQXR0cmlidXRlLCB1dWlkKCkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJZiBhbiBJRCBpcyBzcGVjaWZpZWQgb24gdGhlIG9iamVjdCwgcmV0dXJucyBhIG5ldyBUSWQgaW5zdGFuY2Ugd2l0aCB0aGF0IElEIHZhbHVlLiBJZiBub3QsIGFcbiAgICogbmV3IElEIGlzIGFzc2lnbmVkIGFuZCB0aGF0IFRJZCByZXR1cm5lZC5cbiAgICpcbiAgICogQHBhcmFtIG9ialxuICAgKi9cbiAgc3RhdGljIGdldE9yQ3JlYXRlSWRGb3JPYmplY3Qob2JqOiBFT2JqZWN0KTogc3RyaW5nIHtcbiAgICB0aGlzLmdlbklkSWZOb3RFeGlzdHMob2JqKTtcbiAgICByZXR1cm4gb2JqLmZ1bGxJZCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIFR5cGVzY3JpcHQgbmFtZSBmb3IgYSBnaXZlbiBFQ2xhc3NpZmllciwgaW5jbHVkaW5nXG4gICAqIHRyYW5zbGF0aW9uIG9mIHByaW1pdGl2ZSBFRGF0YVR5cGUgbmFtZXMgKGUuZy4gRUJvb2xlYW4gLT4gYm9vbGVhbikuXG4gICAqIEBwYXJhbSB0eXBlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldFR5cGVzY3JpcHROYW1lKHR5cGU6IEVDbGFzc2lmaWVyKSB7XG4gICAgaWYgKCF0eXBlKSByZXR1cm4gJ251bGwnO1xuICAgIGxldCB0eXBlU3RyID0gdHlwZS5nZXROYW1lKCk7XG4gICAgaWYgKCEodHlwZSBpbnN0YW5jZW9mIEVFbnVtSW1wbCkgJiYgdHlwZSBpbnN0YW5jZW9mIEVEYXRhVHlwZUltcGwpXG4gICAgICB0eXBlU3RyID0gVFV0aWxzLnRvVHlwZVNjcmlwdFByaW1pdGl2ZSh0eXBlKTtcbiAgICByZXR1cm4gdHlwZVN0cjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBUeXBlU2NyaXB0IHByaW1pdGl2ZSB0eXBlIGZvciBhIGdpdmVuIFRNRiBFQ2xhc3NpZmllciB0aGF0IHJlcHJlc2VudHMgYVxuICAgKiBwcmltaXRpdmUgdHlwZS5cbiAgICogQHBhcmFtIGNsYXNzaWZpZXJcbiAgICovXG4gIHN0YXRpYyB0b1R5cGVTY3JpcHRQcmltaXRpdmUoY2xhc3NpZmllcjogRUNsYXNzaWZpZXIpOiBzdHJpbmcge1xuICAgIGlmICghY2xhc3NpZmllciB8fCAhY2xhc3NpZmllci5nZXROYW1lKCkpIHJldHVybiAnYW55JztcbiAgICBzd2l0Y2ggKGNsYXNzaWZpZXIuZ2V0TmFtZSgpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIGNhc2UgJ2VzdHJpbmcnOiB7XG4gICAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdlYm9vbGVhbic6IHtcbiAgICAgICAgcmV0dXJuICdib29sZWFuJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdlZG91YmxlJzoge1xuICAgICAgICByZXR1cm4gJ251bWJlcic7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnZWRvdWJsZW9iamVjdCc6IHtcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2VmbG9hdCc6IHtcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2VmbG9hdG9iamVjdCc6IHtcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2VpbnQnOiB7XG4gICAgICAgIHJldHVybiAnbnVtYmVyJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdlaW50ZWdlcm9iamVjdCc6IHtcbiAgICAgICAgcmV0dXJuICdudW1iZXInO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2VkYXRlJzoge1xuICAgICAgICByZXR1cm4gJ0RhdGUnO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2VhcnJheSc6IHtcbiAgICAgICAgcmV0dXJuICdbXSc7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIHJldHVybiAnYW55JztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgbG9va3VwTmFtZWRGaWVsZChcbiAgICBvYmplY3Q6IEVPYmplY3QsXG4gICAgZmllbGROYW1lOiBzdHJpbmdcbiAgKTogRVN0cnVjdHVyYWxGZWF0dXJlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjdXJDbGFzcyA9IG9iamVjdC5lQ2xhc3MoKTtcbiAgICBjb25zdCBmaWVsZCA9IGN1ckNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZShmaWVsZE5hbWUpO1xuXG4gICAgaWYgKCFmaWVsZCkge1xuICAgICAgY29uc29sZS5sb2coY3VyQ2xhc3MuZ2V0TmFtZSgpLCAnIGhhcyBubyBmaWVsZCBuYW1lZCcsIGZpZWxkTmFtZSk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gZmllbGQ7XG4gIH1cblxuICBzdGF0aWMgZ2V0TmFtZWRGaWVsZFZhbHVlKG9iamVjdDogRU9iamVjdCwgZmllbGROYW1lOiBzdHJpbmcpOiBhbnkge1xuICAgIGNvbnN0IGZpZWxkID0gdGhpcy5sb29rdXBOYW1lZEZpZWxkKG9iamVjdCwgZmllbGROYW1lKTtcbiAgICBpZiAoZmllbGQpIHJldHVybiBvYmplY3QuZUdldChmaWVsZCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHN0YXRpYyBzZXROYW1lZEZpZWxkVmFsdWUob2JqZWN0OiBFT2JqZWN0LCBmaWVsZE5hbWU6IHN0cmluZywgbmV3VmFsdWU6IGFueSkge1xuICAgIGNvbnN0IGZpZWxkID0gdGhpcy5sb29rdXBOYW1lZEZpZWxkKG9iamVjdCwgZmllbGROYW1lKTtcbiAgICBpZiAoZmllbGQpIG9iamVjdC5lU2V0KGZpZWxkLCBuZXdWYWx1ZSk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgYSB2YWx1ZSBmb3IgYW4gRUF0dHJpYnV0ZSBmcm9tIGl0J3MgSlNPTiByZXByZXNlbnRhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGF0dHJcbiAgICogQHBhcmFtIGpzb25WYWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcGFyc2VBdHRyVmFsRnJvbVN0cmluZyhhdHRyOiBFQXR0cmlidXRlLCBzdHJpbmdWYWw6IGFueSk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VWYWx1ZUZyb21TdHJpbmcoXG4gICAgICBhdHRyLmdldEVUeXBlKCkgYXMgRUNsYXNzaWZpZXIsXG4gICAgICBzdHJpbmdWYWwgKyAnJ1xuICAgICk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIHBhcnNlVmFsdWVGcm9tU3RyaW5nKGF0dHJUeXBlOiBFQ2xhc3NpZmllciwgc3RyaW5nVmFsOiBzdHJpbmcpIHtcbiAgICBsZXQgdFZhbCA9IG51bGw7XG4gICAgLy9pZiBhbiBlbXB0eSBzdHJpbmcgd2FzIHNldCBmb3IgdGhlIGZpZWxkLCBqdXN0IHJldHVybiBudWxsXG4gICAgaWYgKFxuICAgICAgIXN0cmluZ1ZhbCB8fFxuICAgICAgKHN0cmluZ1ZhbC50b1N0cmluZygpLnRyaW0oKSA9PT0gJycgJiZcbiAgICAgICAgYXR0clR5cGUgIT09IEVjb3JlUGFja2FnZS5MaXRlcmFscy5FX1NUUklORylcbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmIChhdHRyVHlwZSA9PT0gRWNvcmVQYWNrYWdlLkxpdGVyYWxzLkVfU1RSSU5HKSB7XG4gICAgICB0VmFsID0gc3RyaW5nVmFsLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9ET1VCTEUgfHxcbiAgICAgIGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9ET1VCTEVfT0JKRUNUXG4gICAgKSB7XG4gICAgICB0VmFsID0gTnVtYmVyLnBhcnNlRmxvYXQoc3RyaW5nVmFsLnRvU3RyaW5nKCkpO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICBhdHRyVHlwZSA9PT0gRWNvcmVQYWNrYWdlLkxpdGVyYWxzLkVfRkxPQVQgfHxcbiAgICAgIGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9GTE9BVF9PQkpFQ1RcbiAgICApIHtcbiAgICAgIHRWYWwgPSBOdW1iZXIucGFyc2VGbG9hdChzdHJpbmdWYWwudG9TdHJpbmcoKSk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9CT09MRUFOIHx8XG4gICAgICBhdHRyVHlwZSA9PT0gRWNvcmVQYWNrYWdlLkxpdGVyYWxzLkVfQk9PTEVBTl9PQkpFQ1RcbiAgICApIHtcbiAgICAgIHRWYWwgPSBzdHJpbmdWYWwudG9TdHJpbmcoKSA9PT0gJ3RydWUnO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICBhdHRyVHlwZSA9PT0gRWNvcmVQYWNrYWdlLkxpdGVyYWxzLkVfU0hPUlQgfHxcbiAgICAgIGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9TSE9SVF9PQkpFQ1RcbiAgICApIHtcbiAgICAgIHRWYWwgPSBOdW1iZXIucGFyc2VJbnQoc3RyaW5nVmFsLnRvU3RyaW5nKCksIDEwKTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgYXR0clR5cGUgPT09IEVjb3JlUGFja2FnZS5MaXRlcmFscy5FX0lOVCB8fFxuICAgICAgYXR0clR5cGUgPT09IEVjb3JlUGFja2FnZS5MaXRlcmFscy5FX0lOVEVHRVJfT0JKRUNUXG4gICAgKSB7XG4gICAgICB0VmFsID0gTnVtYmVyLnBhcnNlSW50KHN0cmluZ1ZhbC50b1N0cmluZygpLCAxMCk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9MT05HIHx8XG4gICAgICBhdHRyVHlwZSA9PT0gRWNvcmVQYWNrYWdlLkxpdGVyYWxzLkVfTE9OR19PQkpFQ1RcbiAgICApIHtcbiAgICAgIHRWYWwgPSBOdW1iZXIucGFyc2VJbnQoc3RyaW5nVmFsLnRvU3RyaW5nKCksIDEwKTtcbiAgICB9IGVsc2UgaWYgKGF0dHJUeXBlID09PSBFY29yZVBhY2thZ2UuTGl0ZXJhbHMuRV9EQVRFKSB7XG4gICAgICB0VmFsID0gbmV3IERhdGUoRGF0ZS5wYXJzZShzdHJpbmdWYWwpKTtcbiAgICB9IGVsc2UgaWYgKGF0dHJUeXBlIGluc3RhbmNlb2YgRUVudW1JbXBsKSB7XG4gICAgICBjb25zdCBlZW51bSA9IDxFRW51bT5hdHRyVHlwZTtcbiAgICAgIGNvbnN0IGxpdGVyYWwgPSBlZW51bS5nZXRFRW51bUxpdGVyYWwoc3RyaW5nVmFsLnRvU3RyaW5nKCkpO1xuICAgICAgaWYgKGxpdGVyYWwgIT0gbnVsbCkge1xuICAgICAgICB0VmFsID0gbGl0ZXJhbC5nZXRMaXRlcmFsKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ0NvdWxkIG5vdCBwYXJzZSBsaXRlcmFsIHZhbHVlICcgK1xuICAgICAgICAgICAgc3RyaW5nVmFsLnRvU3RyaW5nKCkgK1xuICAgICAgICAgICAgJyBmb3IgJyArXG4gICAgICAgICAgICBlZW51bS5nZXROYW1lKClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRWYWw7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGRlZXAgY29weSBvZiBhbiBSb290IGFuZCBpdCdzIGNvbnRhaW5tZW50IGhpZXJhcmNoeSwgd2l0aCBvcHRpb25hbFxuICAgKiBsaXN0cyBmb3Igc3BlY2lmeWluZyBzcGVjaWZpYyBFUmVmZXJlbmNlcyB0byB0cmF2ZXJzZSBvciBwcnVuZSBkdXJpbmcgdGhlIGNvcHkuIE5ld1xuICAgKiBJRHMgd2lsbCBiZSBhc3NpZ25lZCB0byBhbGwgY29waWVkIGVudGl0aWVzLiBJbnRlcm5hbCByZWZlcmVuY2VzIHdpbGwgYmUgcHJlc2VydmVkIHdoZXJlIHBvc3NpYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gdG9DbG9uZSAtIHJvb3Qgb2YgY29udGFpbmVyIGNvbnRhaW5tZW50IGhpZXJhcmNoeSB0byBjb3B5XG4gICAqIEBwYXJhbSBwcnVuZSAtICBFUmVmZXJlbmNlcyBub3QgdG8gdHJhdmVyc2UgZHVyaW5nIGNvcHkuIElmIHNwZWNpZmllZCwgdGhlc2VcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZlcmVuY2VzIHdpbGwgbm90IGJlIHRyYXZlcnNlZCBkdXJpbmcgY29weVxuICAgKiBAcGFyYW0gdHJhdmVyc2UgLSBFUmVmZXJlbmNlcyB0byB0cmF2ZXJzZSBkdXJpbmcgY29weS4gSWYgc3BlY2lmaWVkLCBubyBFUmVmZXJlbmNlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWxsIGJlIHRyYXZlcnNlZCB1bmxlc3MgaXQgaXMgaW4gdGhpcyBsaXN0LlxuICAgKiBAcGFyYW0gdGFyZ2V0IC0gQWxsb3dzIHNwZWNpZmljYXRpb24gb2YgYW4gZW50aXR5IGludG8gd2hpY2ggdG8gY29weSBkYXRhLCB3aGljaCBkb2VzIG5vdCBoYXZlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgdG8gYmUgb2YgdGhlIHNhbWUgdHlwZSBhcyB0aGUgY29waWVkIGVudGl0eSAobm9uLW92ZXJsYXBwaW5nIHN0cnVjdHVyZSB3aWxsIGJlIGlnbm9yZWQpLlxuICAgKiBAcmV0dXJucyB0aGUgY29weVxuICAgKi9cbiAgc3RhdGljIGNsb25lPFQgZXh0ZW5kcyBFT2JqZWN0PihcbiAgICB0b0Nsb25lOiBULFxuICAgIHBydW5lPzogRVJlZmVyZW5jZVtdLFxuICAgIHRyYXZlcnNlPzogRVJlZmVyZW5jZVtdLFxuICAgIHRhcmdldD86IFQsXG4gICAgb2xkVG9OZXdFbnRpdGllcz86IE1hcDxFT2JqZWN0LCBFT2JqZWN0PlxuICApOiBUIHtcbiAgICAvL2NyZWF0ZSBuZXcgaW5zdGFuY2VcbiAgICBjb25zdCBuZXdDb250YWluZXIgPSB0YXJnZXRcbiAgICAgID8gdGFyZ2V0XG4gICAgICA6IDxUPihcbiAgICAgICAgICB0b0Nsb25lXG4gICAgICAgICAgICAuZUNsYXNzKClcbiAgICAgICAgICAgIC5nZXRFUGFja2FnZSgpXG4gICAgICAgICAgICAuZ2V0RUZhY3RvcnlJbnN0YW5jZSgpXG4gICAgICAgICAgICAuY3JlYXRlKHRvQ2xvbmUuZUNsYXNzKCkpXG4gICAgICAgICk7XG5cbiAgICAvL21hcCBvZiBvbGQgZW50aXRpZXMgdG8gbmV3IGVudGl0aWVzIHRoYXQgd2lsbCBiZSBmaWxsZWQgaW4gZHVyaW5nIHRoZSBkdXBsaWNhdGlvblxuICAgIGNvbnN0IG9sZFRvTmV3ID0gb2xkVG9OZXdFbnRpdGllc1xuICAgICAgPyBvbGRUb05ld0VudGl0aWVzXG4gICAgICA6IG5ldyBNYXA8RU9iamVjdCwgRU9iamVjdD4oKTtcblxuICAgIC8vcmVjdXJzaXZlIGR1cGxpY2F0aW9uIG9mIGNvbnRhaW5tZW50IGhpZXJhY2h5XG4gICAgdGhpcy5jbG9uZUludG88VD4oXG4gICAgICB0b0Nsb25lLFxuICAgICAgbmV3Q29udGFpbmVyLFxuICAgICAgcHJ1bmUgPyBwcnVuZSA6IFtdLFxuICAgICAgdHJhdmVyc2UgPyB0cmF2ZXJzZSA6IFtdLFxuICAgICAgb2xkVG9OZXdcbiAgICApO1xuXG4gICAgLy9yZS1lc3RhYmxpc2ggY29udGFpbmVyIGludGVybmFsIHJlZmVyZW5jZXMgZm9yIGFsbCBlbnRpdGllcyBpbiB0aGVcbiAgICAvL2NvbnRhaW5lciwgaW5jbHVkaW5nIHRoZSBjb250YWluZXIgcm9vdCBpdHNlbGZcbiAgICBjb25zdCBhbGxPbGRFbnRpdGllcyA9IHRvQ2xvbmUuZUFsbENvbnRlbnRzKCk7XG4gICAgYWxsT2xkRW50aXRpZXMucHVzaCh0b0Nsb25lKTtcbiAgICBmb3IgKGNvbnN0IG9sZEVudGl0eSBvZiBhbGxPbGRFbnRpdGllcykge1xuICAgICAgY29uc3QgbmV3RW50aXR5ID0gb2xkVG9OZXcuZ2V0KG9sZEVudGl0eSk7XG4gICAgICBpZiAobmV3RW50aXR5KSB7XG4gICAgICAgIGZvciAoY29uc3QgZXJlZiBvZiBuZXdFbnRpdHkuZUNsYXNzKCkuZ2V0RUFsbFJlZmVyZW5jZXMoKSkge1xuICAgICAgICAgIC8vb25seSBsb29rIGF0IGNvbnRhaW5lciBpbnRlcm5hbCByZWZlcmVuY2VzXG4gICAgICAgICAgaWYgKCFlcmVmLmlzQ29udGFpbm1lbnQoKSAmJiAhZXJlZi5pc1RyYW5zaWVudCgpKSB7XG4gICAgICAgICAgICBjb25zdCBvbGRSZWZWYWwgPSBvbGRFbnRpdHkuZUdldChlcmVmKTtcbiAgICAgICAgICAgIGlmIChvbGRSZWZWYWwpIHtcbiAgICAgICAgICAgICAgLy9oYW5kbGUgbWFueS12YWx1ZWQgcmVmZXJlbmNlc1xuICAgICAgICAgICAgICBpZiAoZXJlZi5pc01hbnkoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1JlZkxpc3QgPSBuZXdFbnRpdHkuZUdldChlcmVmKTtcbiAgICAgICAgICAgICAgICBpZiAobmV3UmVmTGlzdCkge1xuICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvbGRSZWYgb2Ygb2xkUmVmVmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld1JlZiA9IG9sZFRvTmV3LmdldChvbGRSZWYpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV3UmVmKSBuZXdSZWZMaXN0LmFkZChuZXdSZWYpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChvbGRSZWYpIG5ld1JlZkxpc3QuYWRkKG9sZFJlZik7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vaGFuZGxlIHNpbmdsZS12YWx1ZWQgcmVmZXJlbmNlc1xuICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdWYWwgPSBvbGRUb05ldy5nZXQob2xkUmVmVmFsKTtcbiAgICAgICAgICAgICAgICBpZiAobmV3VmFsKSBuZXdFbnRpdHkuZVNldChlcmVmLCBuZXdWYWwpO1xuICAgICAgICAgICAgICAgIGVsc2UgbmV3RW50aXR5LmVTZXQoZXJlZiwgb2xkUmVmVmFsKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3Q29udGFpbmVyO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgY2xvbmVJbnRvPFQgZXh0ZW5kcyBFT2JqZWN0PihcbiAgICBjb3B5RnJvbTogVCxcbiAgICBjb3B5SW50bzogVCxcbiAgICBwcnVuZU9ubHlUaGVzZVJlZmVyZW5jZXM6IEVSZWZlcmVuY2VbXSxcbiAgICB0cmF2ZXJzZU9ubHlUaGVzZVJlZmVyZW5jZXM6IEVSZWZlcmVuY2VbXSxcbiAgICBvbGRUb05ldz86IE1hcDxFT2JqZWN0LCBFT2JqZWN0PlxuICApIHtcbiAgICBmb3IgKGNvbnN0IGF0dHIgb2YgY29weUludG8uZUNsYXNzKCkuZ2V0RUFsbEF0dHJpYnV0ZXMoKSkge1xuICAgICAgaWYgKCFhdHRyLmlzVm9sYXRpbGUoKSkge1xuICAgICAgICBjb3B5SW50by5lU2V0KGF0dHIsIGNvcHlGcm9tLmVHZXQoYXR0cikpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vYXNzaWduIG5ldyBJRCB0byBlbnRpdHlcbiAgICBpZiAoY29weUludG8uZUNsYXNzKCkuZ2V0RUlEQXR0cmlidXRlKCkpXG4gICAgICBjb3B5SW50by5lU2V0KGNvcHlJbnRvLmVDbGFzcygpLmdldEVJREF0dHJpYnV0ZSgpIGFzIEVBdHRyaWJ1dGUsIHV1aWQoKSk7XG5cbiAgICAvL3JlZ2lzdGVyIG9sZCB0byBuZXcgZW50aXR5IGluIE1hcCwgaWYgc3BlY2lmaWVkXG4gICAgaWYgKG9sZFRvTmV3KSBvbGRUb05ldy5zZXQoY29weUZyb20sIGNvcHlJbnRvKTtcblxuICAgIC8vcmVjdXJzZSBjb250YWlubWVudHNcbiAgICBmb3IgKGNvbnN0IHJlZiBvZiBjb3B5SW50by5lQ2xhc3MoKS5nZXRFQWxsUmVmZXJlbmNlcygpKSB7XG4gICAgICAvL2RldGVybWluZSBpZiByZWZlcmVuY2Ugc2hvdWxkIGJlIHRyYXZlcnNlZFxuICAgICAgbGV0IHRyYXZlcnNlID0gdHJ1ZTtcblxuICAgICAgLy9kbyBub3QgdHJhdmVyc2UgcHJ1bmVkIHJlZmVyZW5jZXNcbiAgICAgIGlmICh0cmF2ZXJzZSAmJiBwcnVuZU9ubHlUaGVzZVJlZmVyZW5jZXMpIHtcbiAgICAgICAgZm9yIChjb25zdCB0b1BydW5lIG9mIHBydW5lT25seVRoZXNlUmVmZXJlbmNlcykge1xuICAgICAgICAgIGlmICh0b1BydW5lID09PSByZWYpIHRyYXZlcnNlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vZG8gbm90IHRyYXZlcnNlIHJlZmVyZW5jZXMgbm90IGluIHRoZSB0cmF2ZXJzZSBsaXN0IChpZiBpdCBpcyBzcGVjaWZpZWQpXG4gICAgICBpZiAodHJhdmVyc2UgJiYgdHJhdmVyc2VPbmx5VGhlc2VSZWZlcmVuY2VzKSB7XG4gICAgICAgIHRyYXZlcnNlID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3QgdG9QcnVuZSBvZiB0cmF2ZXJzZU9ubHlUaGVzZVJlZmVyZW5jZXMpIHtcbiAgICAgICAgICBpZiAodG9QcnVuZSA9PT0gcmVmKSB0cmF2ZXJzZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy9yZWN1cnNpdmVseSBjb3B5IHRoZSBjb250YWlubWVudFxuICAgICAgaWYgKHRyYXZlcnNlKSB7XG4gICAgICAgIGlmIChyZWYuaXNDb250YWlubWVudCgpKSB7XG4gICAgICAgICAgLy9tYW55LXZhbHVlZCBjb250YWlubWVudFxuICAgICAgICAgIGlmIChyZWYuaXNNYW55KCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxpc3QgPSBjb3B5SW50by5lR2V0KHJlZik7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRvQ29weSBvZiBjb3B5RnJvbS5lR2V0KHJlZikpIHtcbiAgICAgICAgICAgICAgbGlzdC5hZGQoXG4gICAgICAgICAgICAgICAgdGhpcy5jbG9uZShcbiAgICAgICAgICAgICAgICAgIHRvQ29weSxcbiAgICAgICAgICAgICAgICAgIHBydW5lT25seVRoZXNlUmVmZXJlbmNlcyxcbiAgICAgICAgICAgICAgICAgIHRyYXZlcnNlT25seVRoZXNlUmVmZXJlbmNlcyxcbiAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICBvbGRUb05ld1xuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvL3NpbmdsZSB2YWx1ZWQgY29udGFpbm1lbnRcbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHRvQ29weSA9IGNvcHlGcm9tLmVHZXQocmVmKTtcbiAgICAgICAgICAgIGlmICh0b0NvcHkpIHtcbiAgICAgICAgICAgICAgY29weUludG8uZVNldChcbiAgICAgICAgICAgICAgICByZWYsXG4gICAgICAgICAgICAgICAgdGhpcy5jbG9uZShcbiAgICAgICAgICAgICAgICAgIHRvQ29weSxcbiAgICAgICAgICAgICAgICAgIHBydW5lT25seVRoZXNlUmVmZXJlbmNlcyxcbiAgICAgICAgICAgICAgICAgIHRyYXZlcnNlT25seVRoZXNlUmVmZXJlbmNlcyxcbiAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICBvbGRUb05ld1xuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy9zaW1wbHkgYXNzaWduIG5vbi1jb250YWlubWVudCByZWZlcmVuY2VzIGlmIHRoZXkgaGF2ZSBubyBlb3Bwb3NpdGVcbiAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgIXJlZi5nZXRFT3Bwb3NpdGUoKSAmJlxuICAgICAgICAgICFyZWYuaXNDb250YWluZXIoKSAmJlxuICAgICAgICAgICFyZWYuaXNWb2xhdGlsZSgpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmIChyZWYuaXNNYW55KCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxpc3QgPSBjb3B5SW50by5lR2V0KHJlZik7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlciBvZiBjb3B5RnJvbS5lR2V0KHJlZikpIGxpc3QuYWRkKG1lbWJlcik7XG4gICAgICAgICAgfSBlbHNlIGNvcHlJbnRvLmVTZXQocmVmLCBjb3B5RnJvbS5lR2V0KHJlZikpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb3B5SW50bztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgY2FyYm9uQ29weTxUIGV4dGVuZHMgRU9iamVjdD4ob2JqOiBUKTogVCB7XG4gICAgcmV0dXJuIFRKc29uLm1ha2VFT2JqZWN0KFRKc29uLm1ha2VKc29uKG9iaikpIGFzIFQ7XG4gIH1cblxuICAvKipcbiAgICogT3ZlcndyaXRlcyBhbGwgYXR0cmlidXRlcyB2YWx1ZXMsIGFuZCByZXBsYWNlcyBhbGwgY29udGFpbm1lbnRzIHdpdGhcbiAgICogY2FyYm9uIGNvcGllcy4gTm9uLWNvbnRhaW5tZW50IHJlZmVyZW5jZXMgYXJlIGxlZn