breeze-client
Version:
Breeze data management for JavaScript clients
269 lines • 35 kB
JavaScript
import * as breeze from 'breeze-client';
let core = breeze.core;
export class ModelLibraryBackingStoreAdapter {
name;
constructor() {
this.name = "backingStore";
}
static register(config) {
config = config || breeze.config;
config.registerAdapter("modelLibrary", ModelLibraryBackingStoreAdapter);
return config.initializeAdapterInstance("modelLibrary", "backingStore", true);
}
initialize() {
}
getTrackablePropertyNames(entity) {
let names = [];
for (let p in entity) {
if (p === "entityAspect" || p === "entityType")
continue;
if (p === "_$typeName" || p === "_pendingSets" || p === "_backingStore")
continue;
let val = entity[p];
if (!core.isFunction(val)) {
names.push(p);
}
}
return names;
}
// This method is called during Metadata initialization
initializeEntityPrototype(proto) {
proto.getProperty = function (propertyName) {
return this[propertyName];
};
proto.setProperty = function (propertyName, value) {
//if (!this._backingStore.hasOwnProperty(propertyName)) {
// throw new Error("Unknown property name:" + propertyName);
//}
this[propertyName] = value;
// allow setProperty chaining.
return this;
};
movePropDefsToProto(proto);
}
// This method is called when an EntityAspect is first created - this will occur as part of the entityType.createEntity call.
// which can be called either directly or via standard query materialization
// entity is either an entity or a complexObject
startTracking(entity, proto) {
// can't touch the normal property sets within this method - access the backingStore directly instead.
let bs = movePropsToBackingStore(entity);
// assign default values to the entity
let stype = breeze.EntityAspect.isEntity(entity) ? entity.entityType : entity.complexType;
stype.getProperties().forEach(function (prop) {
let propName = prop.name;
let val = entity[propName];
if (prop instanceof breeze.DataProperty) {
if (prop.isComplexProperty) {
if (prop.isScalar) {
val = prop.dataType._createInstanceCore(entity, prop);
}
else {
val = breeze.makeComplexArray([], entity, prop);
}
}
else if (!prop.isScalar) {
val = breeze.makePrimitiveArray([], entity, prop);
}
else if (val === undefined) {
val = prop.defaultValue;
}
}
else if (prop.isNavigationProperty) {
if (val !== undefined && val !== null) {
throw new Error("Cannot assign a navigation property in an entity ctor.: " + propName);
}
if (prop.isScalar) {
// TODO: change this to nullstob later.
val = null;
}
else {
val = breeze.makeRelationArray([], entity, prop);
}
}
else {
throw new Error("unknown property: " + propName);
}
// can't touch the normal property sets within this method (IE9 Bug) - so we access the backingStore directly instead.
// otherwise we could just do
// entity[propName] = val
// after all of the interception logic had been injected.
if (prop.isSettable || prop.isNavigationProperty) {
bs[propName] = val;
}
});
}
}
breeze.config.registerAdapter("modelLibrary", ModelLibraryBackingStoreAdapter);
// private methods
// This method is called during Metadata initialization to correctly "wrap" properties.
function movePropDefsToProto(proto) {
let stype = (proto.entityType || proto.complexType);
let extra = stype._extra;
let alreadyWrapped = extra.alreadyWrappedProps || {};
stype.getProperties().forEach(function (prop) {
let propName = prop.name;
// we only want to wrap props that haven't already been wrapped
if (alreadyWrapped[propName])
return;
// If property is already defined on the prototype then wrap it in another propertyDescriptor.
// otherwise create a propDescriptor for it.
let descr;
if (propName in proto) {
descr = wrapPropDescription(proto, prop);
}
else {
descr = makePropDescription(proto, prop);
}
// descr will be null for a wrapped descr that is not configurable
if (descr != null) {
Object.defineProperty(proto, propName, descr);
}
alreadyWrapped[propName] = true;
});
extra.alreadyWrappedProps = alreadyWrapped;
}
// This method is called when an instance is first created via materialization or createEntity.
// this method cannot be called while a 'defineProperty' accessor is executing
// because of IE bug mentioned above.
function movePropsToBackingStore(instance) {
let bs = getBackingStore(instance);
let proto = Object.getPrototypeOf(instance);
let stype = (proto.entityType || proto.complexType);
stype.getProperties().forEach(function (prop) {
let propName = prop.name;
if (prop.isUnmapped) {
// insure that any unmapped properties that were added after entityType
// was first created are wrapped with a property descriptor.
if (!core.getPropertyDescriptor(proto, propName)) {
let descr = makePropDescription(proto, prop);
Object.defineProperty(proto, propName, descr);
}
}
if (!instance.hasOwnProperty(propName))
return;
// pulls off the value, removes the instance property and then rewrites it via ES5 accessor
let value = instance[propName];
delete instance[propName];
instance[propName] = value;
});
return bs;
}
function makePropDescription(proto, property) {
let propName = property.name;
let pendingStores = proto._pendingBackingStores;
if (!pendingStores) {
pendingStores = [];
proto._pendingBackingStores = pendingStores;
}
let descr = {
get: function () {
let bs = this._backingStore || getBackingStore(this);
return bs[propName];
},
set: function (value) {
// IE9 cannot touch instance._backingStore here
let bs = this._backingStore || getPendingBackingStore(this);
let accessorFn = getAccessorFn(bs, propName);
this._$interceptor(property, value, accessorFn);
},
enumerable: true,
configurable: true
};
descr.set.rawSet = function (value) {
let bs = this._backingStore || getPendingBackingStore(this);
let accessorFn = getAccessorFn(bs, propName);
accessorFn(value);
};
return descr;
}
function getAccessorFn(bs, propName) {
return function () {
if (arguments.length === 0) {
return bs[propName];
}
else {
bs[propName] = arguments[0];
return undefined;
}
};
}
function wrapPropDescription(proto, property) {
if (!proto.hasOwnProperty(property.name)) {
let nextProto = Object.getPrototypeOf(proto);
return wrapPropDescription(nextProto, property);
}
let propDescr = Object.getOwnPropertyDescriptor(proto, property.name);
if (!propDescr)
return undefined;
// if not configurable; we can't touch it - so leave.
if (!propDescr.configurable)
return undefined;
// if a data descriptor - don't change it - this is basically a static property - i.e. defined on every instance of the type with the same value.
if (propDescr.value)
return undefined;
// if a read only property descriptor - no need to change it.
if (!propDescr.set)
return undefined;
let localAccessorFn = function (entity) {
return function () {
if (!propDescr)
return undefined;
if (arguments.length === 0) {
return propDescr.get.bind(entity)();
}
else {
let set = propDescr.set;
let rawSet = set.rawSet || set;
rawSet.bind(entity)(arguments[0]);
return undefined;
}
};
};
let newDescr = {
get: function () {
if (!propDescr)
return undefined;
return propDescr.get.bind(this)();
},
set: function (value) {
this._$interceptor(property, value, localAccessorFn(this));
},
enumerable: propDescr.enumerable,
configurable: true
};
newDescr.set.rawSet = propDescr.set;
return newDescr;
}
function getBackingStore(instance) {
let proto = Object.getPrototypeOf(instance);
processPendingStores(proto);
let bs = instance._backingStore;
if (!bs) {
bs = {};
instance._backingStore = bs;
}
return bs;
}
// workaround for IE9 bug where instance properties cannot be changed when executing a property 'set' method.
function getPendingBackingStore(instance) {
let proto = Object.getPrototypeOf(instance);
let pendingStores = proto._pendingBackingStores;
let pending = core.arrayFirst(pendingStores, function (pending) {
return pending.entity === instance;
});
if (pending)
return pending.backingStore;
let bs = {};
pendingStores.push({ entity: instance, backingStore: bs });
return bs;
}
function processPendingStores(proto) {
let pendingStores = proto._pendingBackingStores;
if (pendingStores) {
pendingStores.forEach(function (pending) {
pending.entity._backingStore = pending.backingStore;
});
pendingStores.length = 0;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRhcHRlci1tb2RlbC1saWJyYXJ5LWJhY2tpbmctc3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWRhcHRlci1tb2RlbC1saWJyYXJ5LWJhY2tpbmctc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSxlQUFlLENBQUM7QUFFeEMsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztBQUV2QixNQUFNLE9BQU8sK0JBQStCO0lBQzFDLElBQUksQ0FBUztJQUViO1FBQ0UsSUFBSSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUVELE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBNEI7UUFDMUMsTUFBTSxHQUFHLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxlQUFlLENBQUMsY0FBYyxFQUFFLCtCQUErQixDQUFDLENBQUM7UUFDeEUsT0FBTyxNQUFNLENBQUMseUJBQXlCLENBQUMsY0FBYyxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQW9DLENBQUM7SUFDbkgsQ0FBQztJQUVELFVBQVU7SUFDVixDQUFDO0lBRUQseUJBQXlCLENBQUMsTUFBcUI7UUFDN0MsSUFBSSxLQUFLLEdBQWEsRUFBRSxDQUFDO1FBQ3pCLEtBQUssSUFBSSxDQUFDLElBQUksTUFBTSxFQUFFO1lBQ3BCLElBQUksQ0FBQyxLQUFLLGNBQWMsSUFBSSxDQUFDLEtBQUssWUFBWTtnQkFBRSxTQUFTO1lBQ3pELElBQUksQ0FBQyxLQUFLLFlBQVksSUFBSSxDQUFDLEtBQUssY0FBYyxJQUFJLENBQUMsS0FBSyxlQUFlO2dCQUFFLFNBQVM7WUFDbEYsSUFBSSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUN6QixLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ2Y7U0FDRjtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELHVEQUF1RDtJQUN2RCx5QkFBeUIsQ0FBQyxLQUFVO1FBRWxDLEtBQUssQ0FBQyxXQUFXLEdBQUcsVUFBVSxZQUFvQjtZQUNoRCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM1QixDQUFDLENBQUM7UUFFRixLQUFLLENBQUMsV0FBVyxHQUFHLFVBQVUsWUFBb0IsRUFBRSxLQUFVO1lBQzVELHlEQUF5RDtZQUN6RCwrREFBK0Q7WUFDL0QsR0FBRztZQUNILElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxLQUFLLENBQUM7WUFDM0IsOEJBQThCO1lBQzlCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxDQUFDO1FBRUYsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELDZIQUE2SDtJQUM3SCw0RUFBNEU7SUFFNUUsZ0RBQWdEO0lBQ2hELGFBQWEsQ0FBQyxNQUErQixFQUFFLEtBQVU7UUFDdkQsc0dBQXNHO1FBQ3RHLElBQUksRUFBRSxHQUFHLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXpDLHNDQUFzQztRQUN0QyxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQztRQUMxRixLQUFLLENBQUMsYUFBYSxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBSTtZQUUxQyxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ3pCLElBQUksR0FBRyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUzQixJQUFJLElBQUksWUFBWSxNQUFNLENBQUMsWUFBWSxFQUFFO2dCQUN2QyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtvQkFDMUIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO3dCQUNqQixHQUFHLEdBQUksSUFBSSxDQUFDLFFBQStCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO3FCQUMvRTt5QkFBTTt3QkFDTCxHQUFHLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7cUJBQ2pEO2lCQUNGO3FCQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO29CQUN6QixHQUFHLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7aUJBQ25EO3FCQUFNLElBQUksR0FBRyxLQUFLLFNBQVMsRUFBRTtvQkFDNUIsR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7aUJBQ3pCO2FBRUY7aUJBQU0sSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUU7Z0JBQ3BDLElBQUksR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssSUFBSSxFQUFFO29CQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLDBEQUEwRCxHQUFHLFFBQVEsQ0FBQyxDQUFDO2lCQUN4RjtnQkFDRCxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQ2pCLHVDQUF1QztvQkFDdkMsR0FBRyxHQUFHLElBQUksQ0FBQztpQkFDWjtxQkFBTTtvQkFDTCxHQUFHLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxNQUF1QixFQUFFLElBQUksQ0FBQyxDQUFDO2lCQUNuRTthQUNGO2lCQUFNO2dCQUNMLE1BQU0sSUFBSSxLQUFLLENBQUMsb0JBQW9CLEdBQUcsUUFBUSxDQUFDLENBQUM7YUFDbEQ7WUFDRCxzSEFBc0g7WUFDdEgsNkJBQTZCO1lBQzdCLHlCQUF5QjtZQUN6Qix5REFBeUQ7WUFDekQsSUFBSyxJQUE0QixDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUU7Z0JBQ3pFLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxHQUFHLENBQUM7YUFDcEI7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQUVELE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLGNBQWMsRUFBRSwrQkFBK0IsQ0FBQyxDQUFDO0FBRS9FLGtCQUFrQjtBQUVsQix1RkFBdUY7QUFDdkYsU0FBUyxtQkFBbUIsQ0FBQyxLQUFVO0lBQ3JDLElBQUksS0FBSyxHQUFHLENBQUMsS0FBSyxDQUFDLFVBQVUsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUEwQixDQUFDO0lBQzdFLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFFekIsSUFBSSxjQUFjLEdBQUcsS0FBSyxDQUFDLG1CQUFtQixJQUFJLEVBQUUsQ0FBQztJQUVyRCxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBSTtRQUMxQyxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3pCLCtEQUErRDtRQUMvRCxJQUFJLGNBQWMsQ0FBQyxRQUFRLENBQUM7WUFBRSxPQUFPO1FBRXJDLDhGQUE4RjtRQUM5Riw0Q0FBNEM7UUFDNUMsSUFBSSxLQUFVLENBQUM7UUFDZixJQUFJLFFBQVEsSUFBSSxLQUFLLEVBQUU7WUFDckIsS0FBSyxHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUMxQzthQUFNO1lBQ0wsS0FBSyxHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUMxQztRQUNELGtFQUFrRTtRQUNsRSxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUU7WUFDakIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQy9DO1FBQ0QsY0FBYyxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUNsQyxDQUFDLENBQUMsQ0FBQztJQUNILEtBQUssQ0FBQyxtQkFBbUIsR0FBRyxjQUFjLENBQUM7QUFDN0MsQ0FBQztBQUVELCtGQUErRjtBQUMvRiw4RUFBOEU7QUFDOUUscUNBQXFDO0FBRXJDLFNBQVMsdUJBQXVCLENBQUMsUUFBYTtJQUU1QyxJQUFJLEVBQUUsR0FBRyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkMsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxJQUFJLEtBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLFdBQVcsQ0FBMEIsQ0FBQztJQUM3RSxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBSTtRQUMxQyxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQix1RUFBdUU7WUFDdkUsNERBQTREO1lBQzVELElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxFQUFFO2dCQUNoRCxJQUFJLEtBQUssR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQzdDLE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUMvQztTQUNGO1FBQ0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDO1lBQUUsT0FBTztRQUMvQywyRkFBMkY7UUFDM0YsSUFBSSxLQUFLLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9CLE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzFCLFFBQVEsQ0FBQyxRQUFRLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUFDLEtBQVUsRUFBRSxRQUErQjtJQUN0RSxJQUFJLFFBQVEsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQzdCLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQztJQUNoRCxJQUFJLENBQUMsYUFBYSxFQUFFO1FBQ2xCLGFBQWEsR0FBRyxFQUFFLENBQUM7UUFDbkIsS0FBSyxDQUFDLHFCQUFxQixHQUFHLGFBQWEsQ0FBQztLQUM3QztJQUNELElBQUksS0FBSyxHQUFHO1FBQ1YsR0FBRyxFQUFFO1lBQ0gsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckQsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEIsQ0FBQztRQUNELEdBQUcsRUFBRSxVQUFVLEtBQVU7WUFDdkIsK0NBQStDO1lBQy9DLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxhQUFhLElBQUksc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUQsSUFBSSxVQUFVLEdBQUcsYUFBYSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUNELFVBQVUsRUFBRSxJQUFJO1FBQ2hCLFlBQVksRUFBRSxJQUFJO0tBQ25CLENBQUM7SUFFRCxLQUFLLENBQUMsR0FBVyxDQUFDLE1BQU0sR0FBRyxVQUFVLEtBQVU7UUFDOUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1RCxJQUFJLFVBQVUsR0FBRyxhQUFhLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzdDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwQixDQUFDLENBQUM7SUFDRixPQUFPLEtBQUssQ0FBQztBQUVmLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxFQUFNLEVBQUUsUUFBZ0I7SUFDN0MsT0FBTztRQUNMLElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDMUIsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDckI7YUFBTTtZQUNMLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUIsT0FBTyxTQUFTLENBQUM7U0FDbEI7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxLQUFVLEVBQUUsUUFBK0I7SUFDdEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ3hDLElBQUksU0FBUyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0MsT0FBTyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7S0FDakQ7SUFFRCxJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0RSxJQUFJLENBQUMsU0FBUztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ2pDLHFEQUFxRDtJQUNyRCxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVk7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUM5QyxpSkFBaUo7SUFDakosSUFBSSxTQUFTLENBQUMsS0FBSztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ3RDLDZEQUE2RDtJQUM3RCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUc7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUVyQyxJQUFJLGVBQWUsR0FBRyxVQUFVLE1BQVc7UUFDekMsT0FBTztZQUNMLElBQUksQ0FBQyxTQUFTO2dCQUFFLE9BQU8sU0FBUyxDQUFDO1lBQ2pDLElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7Z0JBQzFCLE9BQU8sU0FBUyxDQUFDLEdBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQzthQUN0QztpQkFBTTtnQkFDTCxJQUFJLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDO2dCQUN4QixJQUFJLE1BQU0sR0FBSSxHQUFXLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBQztnQkFDeEMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDbEMsT0FBTyxTQUFTLENBQUM7YUFDbEI7UUFDSCxDQUFDLENBQUM7SUFDSixDQUFDLENBQUM7SUFFRixJQUFJLFFBQVEsR0FBRztRQUNiLEdBQUcsRUFBRTtZQUNILElBQUksQ0FBQyxTQUFTO2dCQUFFLE9BQU8sU0FBUyxDQUFDO1lBQ2pDLE9BQU8sU0FBUyxDQUFDLEdBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNyQyxDQUFDO1FBQ0QsR0FBRyxFQUFFLFVBQVUsS0FBVTtZQUN2QixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDN0QsQ0FBQztRQUNELFVBQVUsRUFBRSxTQUFTLENBQUMsVUFBVTtRQUNoQyxZQUFZLEVBQUUsSUFBSTtLQUNuQixDQUFDO0lBQ0QsUUFBUSxDQUFDLEdBQVcsQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQztJQUM3QyxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDO0FBR0QsU0FBUyxlQUFlLENBQUMsUUFBYTtJQUNwQyxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzVDLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVCLElBQUksRUFBRSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUM7SUFDaEMsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNQLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDUixRQUFRLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQztLQUM3QjtJQUNELE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQztBQUVELDZHQUE2RztBQUM3RyxTQUFTLHNCQUFzQixDQUFDLFFBQWE7SUFDM0MsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxJQUFJLGFBQWEsR0FBRyxLQUFLLENBQUMscUJBQXFCLENBQUM7SUFDaEQsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsVUFBVSxPQUFPO1FBQzVELE9BQU8sT0FBTyxDQUFDLE1BQU0sS0FBSyxRQUFRLENBQUM7SUFDckMsQ0FBQyxDQUFDLENBQUM7SUFDSCxJQUFJLE9BQU87UUFBRSxPQUFRLE9BQWUsQ0FBQyxZQUFZLENBQUM7SUFDbEQsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQ1osYUFBYSxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDM0QsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxLQUFVO0lBQ3RDLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQztJQUNoRCxJQUFJLGFBQWEsRUFBRTtRQUNqQixhQUFhLENBQUMsT0FBTyxDQUFDLFVBQVUsT0FBWTtZQUMxQyxPQUFPLENBQUMsTUFBTSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDO1FBQ0gsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7S0FDMUI7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYnJlZXplIGZyb20gJ2JyZWV6ZS1jbGllbnQnO1xyXG5cclxubGV0IGNvcmUgPSBicmVlemUuY29yZTtcclxuXHJcbmV4cG9ydCBjbGFzcyBNb2RlbExpYnJhcnlCYWNraW5nU3RvcmVBZGFwdGVyIGltcGxlbWVudHMgYnJlZXplLk1vZGVsTGlicmFyeUFkYXB0ZXIge1xyXG4gIG5hbWU6IHN0cmluZztcclxuXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcbiAgICB0aGlzLm5hbWUgPSBcImJhY2tpbmdTdG9yZVwiO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIHJlZ2lzdGVyKGNvbmZpZz86IGJyZWV6ZS5CcmVlemVDb25maWcpIHtcclxuICAgIGNvbmZpZyA9IGNvbmZpZyB8fCBicmVlemUuY29uZmlnO1xyXG4gICAgY29uZmlnLnJlZ2lzdGVyQWRhcHRlcihcIm1vZGVsTGlicmFyeVwiLCBNb2RlbExpYnJhcnlCYWNraW5nU3RvcmVBZGFwdGVyKTtcclxuICAgIHJldHVybiBjb25maWcuaW5pdGlhbGl6ZUFkYXB0ZXJJbnN0YW5jZShcIm1vZGVsTGlicmFyeVwiLCBcImJhY2tpbmdTdG9yZVwiLCB0cnVlKSBhcyBNb2RlbExpYnJhcnlCYWNraW5nU3RvcmVBZGFwdGVyO1xyXG4gIH1cclxuXHJcbiAgaW5pdGlhbGl6ZSgpIHtcclxuICB9XHJcblxyXG4gIGdldFRyYWNrYWJsZVByb3BlcnR5TmFtZXMoZW50aXR5OiBicmVlemUuRW50aXR5KSB7XHJcbiAgICBsZXQgbmFtZXM6IHN0cmluZ1tdID0gW107XHJcbiAgICBmb3IgKGxldCBwIGluIGVudGl0eSkge1xyXG4gICAgICBpZiAocCA9PT0gXCJlbnRpdHlBc3BlY3RcIiB8fCBwID09PSBcImVudGl0eVR5cGVcIikgY29udGludWU7XHJcbiAgICAgIGlmIChwID09PSBcIl8kdHlwZU5hbWVcIiB8fCBwID09PSBcIl9wZW5kaW5nU2V0c1wiIHx8IHAgPT09IFwiX2JhY2tpbmdTdG9yZVwiKSBjb250aW51ZTtcclxuICAgICAgbGV0IHZhbCA9IGVudGl0eVtwXTtcclxuICAgICAgaWYgKCFjb3JlLmlzRnVuY3Rpb24odmFsKSkge1xyXG4gICAgICAgIG5hbWVzLnB1c2gocCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBuYW1lcztcclxuICB9XHJcblxyXG4gIC8vIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBkdXJpbmcgTWV0YWRhdGEgaW5pdGlhbGl6YXRpb25cclxuICBpbml0aWFsaXplRW50aXR5UHJvdG90eXBlKHByb3RvOiBhbnkpIHtcclxuXHJcbiAgICBwcm90by5nZXRQcm9wZXJ0eSA9IGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWU6IHN0cmluZykge1xyXG4gICAgICByZXR1cm4gdGhpc1twcm9wZXJ0eU5hbWVdO1xyXG4gICAgfTtcclxuXHJcbiAgICBwcm90by5zZXRQcm9wZXJ0eSA9IGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWU6IHN0cmluZywgdmFsdWU6IGFueSkge1xyXG4gICAgICAvL2lmICghdGhpcy5fYmFja2luZ1N0b3JlLmhhc093blByb3BlcnR5KHByb3BlcnR5TmFtZSkpIHtcclxuICAgICAgLy8gICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBwcm9wZXJ0eSBuYW1lOlwiICsgcHJvcGVydHlOYW1lKTtcclxuICAgICAgLy99XHJcbiAgICAgIHRoaXNbcHJvcGVydHlOYW1lXSA9IHZhbHVlO1xyXG4gICAgICAvLyBhbGxvdyBzZXRQcm9wZXJ0eSBjaGFpbmluZy5cclxuICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIG1vdmVQcm9wRGVmc1RvUHJvdG8ocHJvdG8pO1xyXG4gIH1cclxuXHJcbiAgLy8gVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW4gYW4gRW50aXR5QXNwZWN0IGlzIGZpcnN0IGNyZWF0ZWQgLSB0aGlzIHdpbGwgb2NjdXIgYXMgcGFydCBvZiB0aGUgZW50aXR5VHlwZS5jcmVhdGVFbnRpdHkgY2FsbC5cclxuICAvLyB3aGljaCBjYW4gYmUgY2FsbGVkIGVpdGhlciBkaXJlY3RseSBvciB2aWEgc3RhbmRhcmQgcXVlcnkgbWF0ZXJpYWxpemF0aW9uXHJcblxyXG4gIC8vIGVudGl0eSBpcyBlaXRoZXIgYW4gZW50aXR5IG9yIGEgY29tcGxleE9iamVjdFxyXG4gIHN0YXJ0VHJhY2tpbmcoZW50aXR5OiBicmVlemUuU3RydWN0dXJhbE9iamVjdCwgcHJvdG86IGFueSkge1xyXG4gICAgLy8gY2FuJ3QgdG91Y2ggdGhlIG5vcm1hbCBwcm9wZXJ0eSBzZXRzIHdpdGhpbiB0aGlzIG1ldGhvZCAtIGFjY2VzcyB0aGUgYmFja2luZ1N0b3JlIGRpcmVjdGx5IGluc3RlYWQuXHJcbiAgICBsZXQgYnMgPSBtb3ZlUHJvcHNUb0JhY2tpbmdTdG9yZShlbnRpdHkpO1xyXG5cclxuICAgIC8vIGFzc2lnbiBkZWZhdWx0IHZhbHVlcyB0byB0aGUgZW50aXR5XHJcbiAgICBsZXQgc3R5cGUgPSBicmVlemUuRW50aXR5QXNwZWN0LmlzRW50aXR5KGVudGl0eSkgPyBlbnRpdHkuZW50aXR5VHlwZSA6IGVudGl0eS5jb21wbGV4VHlwZTtcclxuICAgIHN0eXBlLmdldFByb3BlcnRpZXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XHJcblxyXG4gICAgICBsZXQgcHJvcE5hbWUgPSBwcm9wLm5hbWU7XHJcbiAgICAgIGxldCB2YWwgPSBlbnRpdHlbcHJvcE5hbWVdO1xyXG5cclxuICAgICAgaWYgKHByb3AgaW5zdGFuY2VvZiBicmVlemUuRGF0YVByb3BlcnR5KSB7XHJcbiAgICAgICAgaWYgKHByb3AuaXNDb21wbGV4UHJvcGVydHkpIHtcclxuICAgICAgICAgIGlmIChwcm9wLmlzU2NhbGFyKSB7XHJcbiAgICAgICAgICAgIHZhbCA9IChwcm9wLmRhdGFUeXBlIGFzIGJyZWV6ZS5Db21wbGV4VHlwZSkuX2NyZWF0ZUluc3RhbmNlQ29yZShlbnRpdHksIHByb3ApO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdmFsID0gYnJlZXplLm1ha2VDb21wbGV4QXJyYXkoW10sIGVudGl0eSwgcHJvcCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmICghcHJvcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgdmFsID0gYnJlZXplLm1ha2VQcmltaXRpdmVBcnJheShbXSwgZW50aXR5LCBwcm9wKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICB2YWwgPSBwcm9wLmRlZmF1bHRWYWx1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICB9IGVsc2UgaWYgKHByb3AuaXNOYXZpZ2F0aW9uUHJvcGVydHkpIHtcclxuICAgICAgICBpZiAodmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBudWxsKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgYXNzaWduIGEgbmF2aWdhdGlvbiBwcm9wZXJ0eSBpbiBhbiBlbnRpdHkgY3Rvci46IFwiICsgcHJvcE5hbWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocHJvcC5pc1NjYWxhcikge1xyXG4gICAgICAgICAgLy8gVE9ETzogY2hhbmdlIHRoaXMgdG8gbnVsbHN0b2IgbGF0ZXIuXHJcbiAgICAgICAgICB2YWwgPSBudWxsO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB2YWwgPSBicmVlemUubWFrZVJlbGF0aW9uQXJyYXkoW10sIGVudGl0eSBhcyBicmVlemUuRW50aXR5LCBwcm9wKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biBwcm9wZXJ0eTogXCIgKyBwcm9wTmFtZSk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gY2FuJ3QgdG91Y2ggdGhlIG5vcm1hbCBwcm9wZXJ0eSBzZXRzIHdpdGhpbiB0aGlzIG1ldGhvZCAoSUU5IEJ1ZykgLSBzbyB3ZSBhY2Nlc3MgdGhlIGJhY2tpbmdTdG9yZSBkaXJlY3RseSBpbnN0ZWFkLlxyXG4gICAgICAvLyBvdGhlcndpc2Ugd2UgY291bGQganVzdCBkb1xyXG4gICAgICAvLyBlbnRpdHlbcHJvcE5hbWVdID0gdmFsXHJcbiAgICAgIC8vIGFmdGVyIGFsbCBvZiB0aGUgaW50ZXJjZXB0aW9uIGxvZ2ljIGhhZCBiZWVuIGluamVjdGVkLlxyXG4gICAgICBpZiAoKHByb3AgYXMgYnJlZXplLkRhdGFQcm9wZXJ0eSkuaXNTZXR0YWJsZSB8fCBwcm9wLmlzTmF2aWdhdGlvblByb3BlcnR5KSB7XHJcbiAgICAgICAgYnNbcHJvcE5hbWVdID0gdmFsO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuXHJcbmJyZWV6ZS5jb25maWcucmVnaXN0ZXJBZGFwdGVyKFwibW9kZWxMaWJyYXJ5XCIsIE1vZGVsTGlicmFyeUJhY2tpbmdTdG9yZUFkYXB0ZXIpO1xyXG5cclxuLy8gcHJpdmF0ZSBtZXRob2RzXHJcblxyXG4vLyBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZHVyaW5nIE1ldGFkYXRhIGluaXRpYWxpemF0aW9uIHRvIGNvcnJlY3RseSBcIndyYXBcIiBwcm9wZXJ0aWVzLlxyXG5mdW5jdGlvbiBtb3ZlUHJvcERlZnNUb1Byb3RvKHByb3RvOiBhbnkpIHtcclxuICBsZXQgc3R5cGUgPSAocHJvdG8uZW50aXR5VHlwZSB8fCBwcm90by5jb21wbGV4VHlwZSkgYXMgYnJlZXplLlN0cnVjdHVyYWxUeXBlO1xyXG4gIGxldCBleHRyYSA9IHN0eXBlLl9leHRyYTtcclxuXHJcbiAgbGV0IGFscmVhZHlXcmFwcGVkID0gZXh0cmEuYWxyZWFkeVdyYXBwZWRQcm9wcyB8fCB7fTtcclxuXHJcbiAgc3R5cGUuZ2V0UHJvcGVydGllcygpLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHtcclxuICAgIGxldCBwcm9wTmFtZSA9IHByb3AubmFtZTtcclxuICAgIC8vIHdlIG9ubHkgd2FudCB0byB3cmFwIHByb3BzIHRoYXQgaGF2ZW4ndCBhbHJlYWR5IGJlZW4gd3JhcHBlZFxyXG4gICAgaWYgKGFscmVhZHlXcmFwcGVkW3Byb3BOYW1lXSkgcmV0dXJuO1xyXG5cclxuICAgIC8vIElmIHByb3BlcnR5IGlzIGFscmVhZHkgZGVmaW5lZCBvbiB0aGUgcHJvdG90eXBlIHRoZW4gd3JhcCBpdCBpbiBhbm90aGVyIHByb3BlcnR5RGVzY3JpcHRvci5cclxuICAgIC8vIG90aGVyd2lzZSBjcmVhdGUgYSBwcm9wRGVzY3JpcHRvciBmb3IgaXQuXHJcbiAgICBsZXQgZGVzY3I6IGFueTtcclxuICAgIGlmIChwcm9wTmFtZSBpbiBwcm90bykge1xyXG4gICAgICBkZXNjciA9IHdyYXBQcm9wRGVzY3JpcHRpb24ocHJvdG8sIHByb3ApO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZGVzY3IgPSBtYWtlUHJvcERlc2NyaXB0aW9uKHByb3RvLCBwcm9wKTtcclxuICAgIH1cclxuICAgIC8vIGRlc2NyIHdpbGwgYmUgbnVsbCBmb3IgYSB3cmFwcGVkIGRlc2NyIHRoYXQgaXMgbm90IGNvbmZpZ3VyYWJsZVxyXG4gICAgaWYgKGRlc2NyICE9IG51bGwpIHtcclxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCBwcm9wTmFtZSwgZGVzY3IpO1xyXG4gICAgfVxyXG4gICAgYWxyZWFkeVdyYXBwZWRbcHJvcE5hbWVdID0gdHJ1ZTtcclxuICB9KTtcclxuICBleHRyYS5hbHJlYWR5V3JhcHBlZFByb3BzID0gYWxyZWFkeVdyYXBwZWQ7XHJcbn1cclxuXHJcbi8vIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aGVuIGFuIGluc3RhbmNlIGlzIGZpcnN0IGNyZWF0ZWQgdmlhIG1hdGVyaWFsaXphdGlvbiBvciBjcmVhdGVFbnRpdHkuXHJcbi8vIHRoaXMgbWV0aG9kIGNhbm5vdCBiZSBjYWxsZWQgd2hpbGUgYSAnZGVmaW5lUHJvcGVydHknIGFjY2Vzc29yIGlzIGV4ZWN1dGluZ1xyXG4vLyBiZWNhdXNlIG9mIElFIGJ1ZyBtZW50aW9uZWQgYWJvdmUuXHJcblxyXG5mdW5jdGlvbiBtb3ZlUHJvcHNUb0JhY2tpbmdTdG9yZShpbnN0YW5jZTogYW55KSB7XHJcblxyXG4gIGxldCBicyA9IGdldEJhY2tpbmdTdG9yZShpbnN0YW5jZSk7XHJcbiAgbGV0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKGluc3RhbmNlKTtcclxuICBsZXQgc3R5cGUgPSAocHJvdG8uZW50aXR5VHlwZSB8fCBwcm90by5jb21wbGV4VHlwZSkgYXMgYnJlZXplLlN0cnVjdHVyYWxUeXBlO1xyXG4gIHN0eXBlLmdldFByb3BlcnRpZXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XHJcbiAgICBsZXQgcHJvcE5hbWUgPSBwcm9wLm5hbWU7XHJcbiAgICBpZiAocHJvcC5pc1VubWFwcGVkKSB7XHJcbiAgICAgIC8vIGluc3VyZSB0aGF0IGFueSB1bm1hcHBlZCBwcm9wZXJ0aWVzIHRoYXQgd2VyZSBhZGRlZCBhZnRlciBlbnRpdHlUeXBlXHJcbiAgICAgIC8vIHdhcyBmaXJzdCBjcmVhdGVkIGFyZSB3cmFwcGVkIHdpdGggYSBwcm9wZXJ0eSBkZXNjcmlwdG9yLlxyXG4gICAgICBpZiAoIWNvcmUuZ2V0UHJvcGVydHlEZXNjcmlwdG9yKHByb3RvLCBwcm9wTmFtZSkpIHtcclxuICAgICAgICBsZXQgZGVzY3IgPSBtYWtlUHJvcERlc2NyaXB0aW9uKHByb3RvLCBwcm9wKTtcclxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sIHByb3BOYW1lLCBkZXNjcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICghaW5zdGFuY2UuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSByZXR1cm47XHJcbiAgICAvLyBwdWxscyBvZmYgdGhlIHZhbHVlLCByZW1vdmVzIHRoZSBpbnN0YW5jZSBwcm9wZXJ0eSBhbmQgdGhlbiByZXdyaXRlcyBpdCB2aWEgRVM1IGFjY2Vzc29yXHJcbiAgICBsZXQgdmFsdWUgPSBpbnN0YW5jZVtwcm9wTmFtZV07XHJcbiAgICBkZWxldGUgaW5zdGFuY2VbcHJvcE5hbWVdO1xyXG4gICAgaW5zdGFuY2VbcHJvcE5hbWVdID0gdmFsdWU7XHJcbiAgfSk7XHJcbiAgcmV0dXJuIGJzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBtYWtlUHJvcERlc2NyaXB0aW9uKHByb3RvOiBhbnksIHByb3BlcnR5OiBicmVlemUuRW50aXR5UHJvcGVydHkpIHtcclxuICBsZXQgcHJvcE5hbWUgPSBwcm9wZXJ0eS5uYW1lO1xyXG4gIGxldCBwZW5kaW5nU3RvcmVzID0gcHJvdG8uX3BlbmRpbmdCYWNraW5nU3RvcmVzO1xyXG4gIGlmICghcGVuZGluZ1N0b3Jlcykge1xyXG4gICAgcGVuZGluZ1N0b3JlcyA9IFtdO1xyXG4gICAgcHJvdG8uX3BlbmRpbmdCYWNraW5nU3RvcmVzID0gcGVuZGluZ1N0b3JlcztcclxuICB9XHJcbiAgbGV0IGRlc2NyID0ge1xyXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGxldCBicyA9IHRoaXMuX2JhY2tpbmdTdG9yZSB8fCBnZXRCYWNraW5nU3RvcmUodGhpcyk7XHJcbiAgICAgIHJldHVybiBic1twcm9wTmFtZV07XHJcbiAgICB9LFxyXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWU6IGFueSkge1xyXG4gICAgICAvLyBJRTkgY2Fubm90IHRvdWNoIGluc3RhbmNlLl9iYWNraW5nU3RvcmUgaGVyZVxyXG4gICAgICBsZXQgYnMgPSB0aGlzLl9iYWNraW5nU3RvcmUgfHwgZ2V0UGVuZGluZ0JhY2tpbmdTdG9yZSh0aGlzKTtcclxuICAgICAgbGV0IGFjY2Vzc29yRm4gPSBnZXRBY2Nlc3NvckZuKGJzLCBwcm9wTmFtZSk7XHJcbiAgICAgIHRoaXMuXyRpbnRlcmNlcHRvcihwcm9wZXJ0eSwgdmFsdWUsIGFjY2Vzc29yRm4pO1xyXG4gICAgfSxcclxuICAgIGVudW1lcmFibGU6IHRydWUsXHJcbiAgICBjb25maWd1cmFibGU6IHRydWVcclxuICB9O1xyXG5cclxuICAoZGVzY3Iuc2V0IGFzIGFueSkucmF3U2V0ID0gZnVuY3Rpb24gKHZhbHVlOiBhbnkpIHtcclxuICAgIGxldCBicyA9IHRoaXMuX2JhY2tpbmdTdG9yZSB8fCBnZXRQZW5kaW5nQmFja2luZ1N0b3JlKHRoaXMpO1xyXG4gICAgbGV0IGFjY2Vzc29yRm4gPSBnZXRBY2Nlc3NvckZuKGJzLCBwcm9wTmFtZSk7XHJcbiAgICBhY2Nlc3NvckZuKHZhbHVlKTtcclxuICB9O1xyXG4gIHJldHVybiBkZXNjcjtcclxuXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEFjY2Vzc29yRm4oYnM6IHt9LCBwcm9wTmFtZTogc3RyaW5nKTogYW55IHtcclxuICByZXR1cm4gZnVuY3Rpb24gKCkge1xyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgcmV0dXJuIGJzW3Byb3BOYW1lXTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGJzW3Byb3BOYW1lXSA9IGFyZ3VtZW50c1swXTtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgIH1cclxuICB9O1xyXG59XHJcblxyXG5mdW5jdGlvbiB3cmFwUHJvcERlc2NyaXB0aW9uKHByb3RvOiBhbnksIHByb3BlcnR5OiBicmVlemUuRW50aXR5UHJvcGVydHkpOiBhbnkge1xyXG4gIGlmICghcHJvdG8uaGFzT3duUHJvcGVydHkocHJvcGVydHkubmFtZSkpIHtcclxuICAgIGxldCBuZXh0UHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xyXG4gICAgcmV0dXJuIHdyYXBQcm9wRGVzY3JpcHRpb24obmV4dFByb3RvLCBwcm9wZXJ0eSk7XHJcbiAgfVxyXG5cclxuICBsZXQgcHJvcERlc2NyID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihwcm90bywgcHJvcGVydHkubmFtZSk7XHJcbiAgaWYgKCFwcm9wRGVzY3IpIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgLy8gaWYgbm90IGNvbmZpZ3VyYWJsZTsgd2UgY2FuJ3QgdG91Y2ggaXQgLSBzbyBsZWF2ZS5cclxuICBpZiAoIXByb3BEZXNjci5jb25maWd1cmFibGUpIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgLy8gaWYgYSBkYXRhIGRlc2NyaXB0b3IgLSBkb24ndCBjaGFuZ2UgaXQgLSB0aGlzIGlzIGJhc2ljYWxseSBhIHN0YXRpYyBwcm9wZXJ0eSAtIGkuZS4gZGVmaW5lZCBvbiBldmVyeSBpbnN0YW5jZSBvZiB0aGUgdHlwZSB3aXRoIHRoZSBzYW1lIHZhbHVlLlxyXG4gIGlmIChwcm9wRGVzY3IudmFsdWUpIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgLy8gaWYgYSByZWFkIG9ubHkgcHJvcGVydHkgZGVzY3JpcHRvciAtIG5vIG5lZWQgdG8gY2hhbmdlIGl0LlxyXG4gIGlmICghcHJvcERlc2NyLnNldCkgcmV0dXJuIHVuZGVmaW5lZDtcclxuXHJcbiAgbGV0IGxvY2FsQWNjZXNzb3JGbiA9IGZ1bmN0aW9uIChlbnRpdHk6IGFueSkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcclxuICAgICAgaWYgKCFwcm9wRGVzY3IpIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgcmV0dXJuIHByb3BEZXNjci5nZXQhLmJpbmQoZW50aXR5KSgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGxldCBzZXQgPSBwcm9wRGVzY3Iuc2V0O1xyXG4gICAgICAgIGxldCByYXdTZXQgPSAoc2V0IGFzIGFueSkucmF3U2V0IHx8IHNldDtcclxuICAgICAgICByYXdTZXQuYmluZChlbnRpdHkpKGFyZ3VtZW50c1swXSk7XHJcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgICAgfVxyXG4gICAgfTtcclxuICB9O1xyXG5cclxuICBsZXQgbmV3RGVzY3IgPSB7XHJcbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgaWYgKCFwcm9wRGVzY3IpIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICAgIHJldHVybiBwcm9wRGVzY3IuZ2V0IS5iaW5kKHRoaXMpKCk7XHJcbiAgICB9LFxyXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWU6IGFueSkge1xyXG4gICAgICB0aGlzLl8kaW50ZXJjZXB0b3IocHJvcGVydHksIHZhbHVlLCBsb2NhbEFjY2Vzc29yRm4odGhpcykpO1xyXG4gICAgfSxcclxuICAgIGVudW1lcmFibGU6IHByb3BEZXNjci5lbnVtZXJhYmxlLFxyXG4gICAgY29uZmlndXJhYmxlOiB0cnVlXHJcbiAgfTtcclxuICAobmV3RGVzY3Iuc2V0IGFzIGFueSkucmF3U2V0ID0gcHJvcERlc2NyLnNldDtcclxuICByZXR1cm4gbmV3RGVzY3I7XHJcbn1cclxuXHJcblxyXG5mdW5jdGlvbiBnZXRCYWNraW5nU3RvcmUoaW5zdGFuY2U6IGFueSkge1xyXG4gIGxldCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihpbnN0YW5jZSk7XHJcbiAgcHJvY2Vzc1BlbmRpbmdTdG9yZXMocHJvdG8pO1xyXG4gIGxldCBicyA9IGluc3RhbmNlLl9iYWNraW5nU3RvcmU7XHJcbiAgaWYgKCFicykge1xyXG4gICAgYnMgPSB7fTtcclxuICAgIGluc3RhbmNlLl9iYWNraW5nU3RvcmUgPSBicztcclxuICB9XHJcbiAgcmV0dXJuIGJzO1xyXG59XHJcblxyXG4vLyB3b3JrYXJvdW5kIGZvciBJRTkgYnVnIHdoZXJlIGluc3RhbmNlIHByb3BlcnRpZXMgY2Fubm90IGJlIGNoYW5nZWQgd2hlbiBleGVjdXRpbmcgYSBwcm9wZXJ0eSAnc2V0JyBtZXRob2QuXHJcbmZ1bmN0aW9uIGdldFBlbmRpbmdCYWNraW5nU3RvcmUoaW5zdGFuY2U6IGFueSkge1xyXG4gIGxldCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihpbnN0YW5jZSk7XHJcbiAgbGV0IHBlbmRpbmdTdG9yZXMgPSBwcm90by5fcGVuZGluZ0JhY2tpbmdTdG9yZXM7XHJcbiAgbGV0IHBlbmRpbmcgPSBjb3JlLmFycmF5Rmlyc3QocGVuZGluZ1N0b3JlcywgZnVuY3Rpb24gKHBlbmRpbmcpIHtcclxuICAgIHJldHVybiBwZW5kaW5nLmVudGl0eSA9PT0gaW5zdGFuY2U7XHJcbiAgfSk7XHJcbiAgaWYgKHBlbmRpbmcpIHJldHVybiAocGVuZGluZyBhcyBhbnkpLmJhY2tpbmdTdG9yZTtcclxuICBsZXQgYnMgPSB7fTtcclxuICBwZW5kaW5nU3RvcmVzLnB1c2goeyBlbnRpdHk6IGluc3RhbmNlLCBiYWNraW5nU3RvcmU6IGJzIH0pO1xyXG4gIHJldHVybiBicztcclxufVxyXG5cclxuZnVuY3Rpb24gcHJvY2Vzc1BlbmRpbmdTdG9yZXMocHJvdG86IGFueSkge1xyXG4gIGxldCBwZW5kaW5nU3RvcmVzID0gcHJvdG8uX3BlbmRpbmdCYWNraW5nU3RvcmVzO1xyXG4gIGlmIChwZW5kaW5nU3RvcmVzKSB7XHJcbiAgICBwZW5kaW5nU3RvcmVzLmZvckVhY2goZnVuY3Rpb24gKHBlbmRpbmc6IGFueSkge1xyXG4gICAgICBwZW5kaW5nLmVudGl0eS5fYmFja2luZ1N0b3JlID0gcGVuZGluZy5iYWNraW5nU3RvcmU7XHJcbiAgICB9KTtcclxuICAgIHBlbmRpbmdTdG9yZXMubGVuZ3RoID0gMDtcclxuICB9XHJcbn1cclxuXHJcbiJdfQ==