breeze-client
Version:
Breeze data management for JavaScript clients
269 lines • 36.5 kB
JavaScript
//#region Copyright, Version, and Description
/*
* Copyright 2015-2021 IdeaBlade, Inc. All Rights Reserved.
* Use, reproduction, distribution, and modification of this code is subject to the terms and
* conditions of the IdeaBlade Breeze license, available at http://www.breezejs.com/license
*
* Author: Ward Bell
* Version: 0.9.5 - Steve Schmitt - convert to TypeScript, migrate to breeze-client repo, add HasEntityGraph and mixinEntityGraph
* Version: 0.9.4 - Marcel Good - fix UMD module name
* --------------------------------------------------------------------------------
* Adds getEntityGraph method to Breeze EntityManager prototype.
* Call mixinEntityGraph(EntityManager) to apply the mixin in a tree-shaking-resistant way.
* Then (manager as any).getEntityGraph(entity, "child");
*
* Depends on Breeze which it patches
*
* For discussion, see:
* http://www.breezejs.com/documentation/getentitygraph
*
* For example usage, see:
* https://github.com/Breeze/breeze.js.samples/tree/master/net/DocCode/DocCode/tests/getEntityGraphTests.js
*/
//#endregion
import { EntityManager, EntityQuery, EntityState, ExpandClause } from 'breeze-client';
export function mixinEntityGraph(emclass) {
const proto = EntityManager.prototype;
if (!proto.getEntityGraph) {
proto.getEntityGraph = getEntityGraph;
}
}
mixinEntityGraph(EntityManager);
function getEntityGraph(roots, expand) {
if (roots instanceof EntityQuery) {
let newRoots = this.executeQueryLocally(roots);
return getEntityGraphCore(newRoots, expand || roots.expandClause);
}
else {
return getEntityGraphCore(roots, expand);
}
}
function getEntityGraphCore(root, expand) {
let entityGroupMap;
let graph = [];
let rootType;
let roots = Array.isArray(root) ? root : [root];
addToGraph(roots); // removes dups & nulls
roots = graph.slice(); // copy of de-duped roots
if (roots.length) {
getRootInfo();
getExpand();
buildGraph();
}
return graph;
function addToGraph(entities) {
entities.forEach(function (entity) {
if (entity && graph.indexOf(entity) < 0) {
graph.push(entity);
}
});
}
function getRootInfo() {
let compatTypes;
roots.forEach(function (root, ix) {
let aspect;
if (!root || !(aspect = root.entityAspect)) {
throw getRootErr(ix, 'is not an entity');
}
if (aspect.entityState === EntityState.Detached) {
throw getRootErr(ix, 'is a detached entity');
}
let em = aspect.entityManager;
if (entityGroupMap) {
if (entityGroupMap !== em._entityGroupMap) {
throw getRootErr(ix, "has a different 'EntityManager' than other roots");
}
}
else {
entityGroupMap = em._entityGroupMap;
}
getRootType(root, ix);
});
function getRootErr(ix, msg) {
return new Error("'getEntityGraph' root[" + ix + "] " + msg);
}
function getRootType(root, ix) {
let thisType = root.entityType;
if (!rootType) {
rootType = thisType;
return;
}
else if (rootType === thisType) {
return;
}
// Types differs. Look for closest common base type
// does thisType derive from current rootType?
let baseType = rootType;
do {
compatTypes = compatTypes || baseType.getSelfAndSubtypes();
if (compatTypes.indexOf(thisType) > -1) {
rootType = baseType;
return;
}
baseType = baseType.baseEntityType;
compatTypes = null;
} while (baseType);
// does current rootType derives from thisType?
baseType = thisType;
do {
compatTypes = baseType.getSelfAndSubtypes();
if (compatTypes.indexOf(rootType) > -1) {
rootType = baseType;
return;
}
baseType = baseType.baseEntityType;
} while (baseType);
throw getRootErr(ix, "is not EntityType-compatible with other roots");
}
}
function getExpand() {
try {
if (!expand) {
expand = [];
}
else if (typeof expand === 'string') {
// tricky because Breeze expandClause not exposed publically
expand = new EntityQuery().expand(expand).expandClause;
}
if (expand instanceof ExpandClause && expand.propertyPaths) { // expand clause
expand = expand.propertyPaths;
}
else if (Array.isArray(expand)) {
if (!expand.every(function (elem) { return typeof elem === 'string'; })) {
throw '';
}
}
else {
throw '';
}
}
catch (_) {
throw new Error("expand must be an expand string, array of string paths, or a query expand clause");
}
}
function buildGraph() {
if (expand && expand instanceof Array && expand.length) {
let fns = expand.map(makePathFn);
fns.forEach(function (fn) { fn(roots); });
}
}
// Make function to get entities along a single expand path
// such as 'Orders.OrderDetails.Product'
function makePathFn(path) {
let fns = [], segments = path.split('.'), type = rootType;
for (let i = 0, slen = segments.length; i < slen; i++) {
let f = makePathSegmentFn(type, segments[i]);
type = f.navType;
fns.push(f);
}
return function pathFn(entities) {
for (let j = 0, flen = fns.length; j < flen; j++) {
let elen = entities.length;
if (elen === 0) {
return;
} // nothing left to explore
// fn to get related entities for this path segment
let fn = fns[j];
// get entities related by this path segment
let related = [];
for (let k = 0; k < elen; k++) {
related = related.concat(fn(entities[k]));
}
addToGraph(related);
if (j >= flen - 1) {
return;
} // no more path segments
// reset entities to deduped related entities
entities = [];
for (let l = 0, rlen = related.length; l < rlen; l++) {
let r = related[l];
if (entities.indexOf(r) < 0) {
entities.push(r);
}
}
}
};
}
// Make function to get entities along a single expand path segment
// such as the 'OrderDetails' in the 'Orders.OrderDetails.Product' path
function makePathSegmentFn(baseType, segment) {
let baseTypeName, fn = undefined, navType;
try {
baseTypeName = baseType.name;
let nav = baseType.getNavigationProperty(segment);
let fkName = nav.foreignKeyNames[0];
if (!nav) {
throw new Error(segment + " is not a navigation property of " + baseTypeName);
}
navType = nav.entityType;
// add derived types
let navTypes = navType.getSelfAndSubtypes();
let grps = []; // non-empty groups for these types
navTypes.forEach(function (t) {
let grp = entityGroupMap[t.name];
if (grp && grp._entities.length > 0) {
grps.push(grp);
}
});
let grpCount = grps.length;
if (grpCount === 0) {
// no related entities in cache
fn = function () { return []; };
}
else if (fkName) {
fn = function (entity) {
let val = null;
try {
let keyValue = entity.getProperty(fkName);
for (let i = 0; i < grpCount; i += 1) {
val = grps[i]._entities[grps[i]._indexMap[keyValue]];
if (val) {
break;
}
}
}
catch (e) {
rethrow(e);
}
return val;
};
}
else {
fkName = nav.inverse ?
nav.inverse.foreignKeyNames[0] :
nav.invForeignKeyNames[0];
if (!fkName) {
throw new Error("No inverse keys");
}
fn = function (entity) {
let vals = [];
try {
let keyValue = entity.entityAspect.getKey().values[0];
grps.forEach(function (grp) {
vals = vals.concat(grp._entities.filter(function (en) {
return en && en.getProperty(fkName) === keyValue;
}));
});
}
catch (e) {
rethrow(e);
}
return vals;
};
}
fn.navType = navType;
fn.path = segment;
}
catch (err) {
rethrow(err);
}
return fn;
function rethrow(e) {
let typeName = baseTypeName || baseType;
let error = new Error("'getEntityGraph' can't expand '" + segment + "' for " + typeName);
error.innerError = e;
throw error;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWl4aW4tZ2V0LWVudGl0eS1ncmFwaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9taXhpbi1nZXQtZW50aXR5LWdyYXBoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDZDQUE2QztBQUM3Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxZQUFZO0FBQ1osT0FBTyxFQUFVLGFBQWEsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFjLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQXNDMUcsTUFBTSxVQUFVLGdCQUFnQixDQUFDLE9BQWlDO0lBQ2hFLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxTQUFTLENBQUM7SUFFdEMsSUFBSSxDQUFFLEtBQWEsQ0FBQyxjQUFjLEVBQUU7UUFDakMsS0FBYSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7S0FDaEQ7QUFDSCxDQUFDO0FBRUQsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQUM7QUFHaEMsU0FBUyxjQUFjLENBQUMsS0FBMkMsRUFBRSxNQUE2QztJQUNoSCxJQUFJLEtBQUssWUFBWSxXQUFXLEVBQUU7UUFDaEMsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQy9DLE9BQU8sa0JBQWtCLENBQUMsUUFBUSxFQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDbkU7U0FBTTtRQUNMLE9BQU8sa0JBQWtCLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQzFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQUMsSUFBNEIsRUFBRSxNQUE2QztJQUNyRyxJQUFJLGNBQWdELENBQUM7SUFDckQsSUFBSSxLQUFLLEdBQUcsRUFBbUIsQ0FBQztJQUNoQyxJQUFJLFFBQW9CLENBQUM7SUFDekIsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxD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QyxPQUFPLEdBQUcsT0FBTyxDQUFDO1lBQzdCLEVBQVUsQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDO1NBRTVCO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7U0FBRTtRQUMvQixPQUFPLEVBQUUsQ0FBQztRQUVWLFNBQVMsT0FBTyxDQUFDLENBQVE7WUFDdkIsSUFBSSxRQUFRLEdBQUcsWUFBWSxJQUFJLFFBQVEsQ0FBQztZQUN4QyxJQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsR0FBRyxPQUFPLEdBQUcsUUFBUSxHQUFHLFFBQVEsQ0FBQyxDQUFDO1lBQ3hGLEtBQWEsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1lBQzlCLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8jcmVnaW9uIENvcHlyaWdodCwgVmVyc2lvbiwgYW5kIERlc2NyaXB0aW9uXHJcbi8qXHJcbiAqIENvcHlyaWdodCAyMDE1LTIwMjEgSWRlYUJsYWRlLCBJbmMuICBBbGwgUmlnaHRzIFJlc2VydmVkLlxyXG4gKiBVc2UsIHJlcHJvZHVjdGlvbiwgZGlzdHJpYnV0aW9uLCBhbmQgbW9kaWZpY2F0aW9uIG9mIHRoaXMgY29kZSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBhbmRcclxuICogY29uZGl0aW9ucyBvZiB0aGUgSWRlYUJsYWRlIEJyZWV6ZSBsaWNlbnNlLCBhdmFpbGFibGUgYXQgaHR0cDovL3d3dy5icmVlemVqcy5jb20vbGljZW5zZVxyXG4gKlxyXG4gKiBBdXRob3I6IFdhcmQgQmVsbFxyXG4gKiBWZXJzaW9uOiAwLjkuNSAtIFN0ZXZlIFNjaG1pdHQgLSBjb252ZXJ0IHRvIFR5cGVTY3JpcHQsIG1pZ3JhdGUgdG8gYnJlZXplLWNsaWVudCByZXBvLCBhZGQgSGFzRW50aXR5R3JhcGggYW5kIG1peGluRW50aXR5R3JhcGhcclxuICogVmVyc2lvbjogMC45LjQgLSBNYXJjZWwgR29vZCAtIGZpeCBVTUQgbW9kdWxlIG5hbWVcclxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICogQWRkcyBnZXRFbnRpdHlHcmFwaCBtZXRob2QgdG8gQnJlZXplIEVudGl0eU1hbmFnZXIgcHJvdG90eXBlLlxyXG4gKiBDYWxsICAgbWl4aW5FbnRpdHlHcmFwaChFbnRpdHlNYW5hZ2VyKSAgIHRvIGFwcGx5IHRoZSBtaXhpbiBpbiBhIHRyZWUtc2hha2luZy1yZXNpc3RhbnQgd2F5LlxyXG4gKiBUaGVuICAgKG1hbmFnZXIgYXMgYW55KS5nZXRFbnRpdHlHcmFwaChlbnRpdHksIFwiY2hpbGRcIik7XHJcbiAqXHJcbiAqIERlcGVuZHMgb24gQnJlZXplIHdoaWNoIGl0IHBhdGNoZXNcclxuICpcclxuICogRm9yIGRpc2N1c3Npb24sIHNlZTpcclxuICogaHR0cDovL3d3dy5icmVlemVqcy5jb20vZG9jdW1lbnRhdGlvbi9nZXRlbnRpdHlncmFwaFxyXG4gKlxyXG4gKiBGb3IgZXhhbXBsZSB1c2FnZSwgc2VlOlxyXG4gKiBodHRwczovL2dpdGh1Yi5jb20vQnJlZXplL2JyZWV6ZS5qcy5zYW1wbGVzL3RyZWUvbWFzdGVyL25ldC9Eb2NDb2RlL0RvY0NvZGUvdGVzdHMvZ2V0RW50aXR5R3JhcGhUZXN0cy5qc1xyXG4gKi9cclxuLy8jZW5kcmVnaW9uXHJcbmltcG9ydCB7IEVudGl0eSwgRW50aXR5TWFuYWdlciwgRW50aXR5UXVlcnksIEVudGl0eVN0YXRlLCBFbnRpdHlUeXBlLCBFeHBhbmRDbGF1c2UgfSBmcm9tICdicmVlemUtY2xpZW50JztcclxuXHJcbmludGVyZmFjZSBFbnRpdHlHcm91cCB7XHJcbiAgX2VudGl0aWVzOiAoRW50aXR5IHwgbnVsbClbXTtcclxuICBfaW5kZXhNYXA6IHsgW2luZGV4OiBzdHJpbmddOiBudW1iZXIgfTtcclxufVxyXG5cclxuLy8gbW9kdWxlIGF1Z21lbnRhdGlvbiBmYWlsZWQgdG8gYnVpbGQgd2l0aCBuZy1wYWNrYWdyLCBzbyB3ZSBoYXZlIGEgc2VwYXJhdGUgaW50ZXJmYWNlXHJcbmV4cG9ydCBpbnRlcmZhY2UgSGFzRW50aXR5R3JhcGggZXh0ZW5kcyBFbnRpdHlNYW5hZ2VyIHtcclxuICAvKipcclxuICBHZXQgcmVsYXRlZCBlbnRpdGllcyBvZiByb290IGVudGl0eSAob3Igcm9vdCBlbnRpdGllcykgYXMgc3BlY2lmaWVkIGJ5IGV4cGFuZC5cclxuICBAZXhhbXBsZVxyXG4gICAgICB2YXIgZ3JhcGggPSBicmVlemUuRW50aXR5TWFuYWdlci5nZXRFbnRpdHlHcmFwaChjdXN0b21lciwgJ09yZGVycy5PcmRlckRldGFpbHMnKTtcclxuICAgICAgLy8gZ3JhcGggd2lsbCBiZSB0aGUgY3VzdG9tZXIsIGFsbCBvZiBpdHMgb3JkZXJzIGFuZCB0aGVpciBkZXRhaWxzIGV2ZW4gaWYgZGVsZXRlZC5cclxuICBAbWV0aG9kIGdldEVudGl0eUdyYXBoXHJcbiAgQHBhcmFtIHJvb3RzIHtFbnRpdHl8QXJyYXkgb2YgRW50aXR5fSBUaGUgcm9vdCBlbnRpdHkgb3Igcm9vdCBlbnRpdGllcy5cclxuICBAcGFyYW0gZXhwYW5kIHtTdHJpbmd8QXJyYXkgb2YgU3RyaW5nfE9iamVjdH0gYW4gZXhwYW5kIHN0cmluZywgYSBxdWVyeSBleHBhbmQgY2xhdXNlLCBvciBhcnJheSBvZiBzdHJpbmcgcGF0aHNcclxuICBAcmV0dXJuIHtBcnJheSBvZiBFbnRpdHl9IHJvb3QgZW50aXRpZXMgYW5kIHRoZWlyIHJlbGF0ZWQgZW50aXRpZXMsIGluY2x1ZGluZyBkZWxldGVkIGVudGl0aWVzLiBEdXBsaWNhdGVzIGFyZSByZW1vdmVkIGFuZCBlbnRpdHkgb3JkZXIgaXMgaW5kZXRlcm1pbmF0ZS5cclxuICAqKi9cclxuICBnZXRFbnRpdHlHcmFwaChyb290czogRW50aXR5IHwgQXJyYXk8RW50aXR5PiwgZXhwYW5kOiBzdHJpbmcgfCBBcnJheTxzdHJpbmc+IHwgRXhwYW5kQ2xhdXNlKTogQXJyYXk8RW50aXR5PjtcclxuXHJcbiAgLyoqXHJcbiAgRXhlY3V0ZSBxdWVyeSBsb2NhbGx5IGFuZCByZXR1cm4gYm90aCB0aGUgcXVlcnkgcmVzdWx0cyBhbmQgdGhlaXIgcmVsYXRlZCBlbnRpdGllcyBhcyBzcGVjaWZpZWQgYnkgdGhlIG9wdGlvbmFsIGV4cGFuZCBwYXJhbWV0ZXIgb3IgdGhlIHF1ZXJ5J3MgZXhwYW5kIGNsYXVzZS5cclxuICBAZXhhbXBsZVxyXG4gICAgICB2YXIgcXVlcnkgPSBicmVlemUuRW50aXR5UXVlcnkuZnJvbSgnQ3VzdG9tZXJzJylcclxuICAgICAgICAgICAgICAgICAgLndoZXJlKCdDb21wYW55TmFtZScsICdzdGFydHNXaXRoJywgJ0FsZnJlZCcpXHJcbiAgICAgICAgICAgICAgICAgIC5leHBhbmQoJ09yZGVycy5PcmRlckRldGFpbHMnKTtcclxuICAgICAgdmFyIGdyYXBoID0gbWFuYWdlci5nZXRFbnRpdHlHcmFwaChxdWVyeSk7XHJcbiAgICAgIC8vIGdyYXBoIHdpbGwgYmUgdGhlICdBbGZyZWQnIGN1c3RvbWVycywgdGhlaXIgb3JkZXJzIGFuZCB0aGVpciBkZXRhaWxzIGV2ZW4gaWYgZGVsZXRlZC5cclxuICBAbWV0aG9kIGdldEVudGl0eUdyYXBoXHJcbiAgQHBhcmFtIHF1ZXJ5IHtFbnRpdHlRdWVyeX0gQSBxdWVyeSB0byBiZSBleGVjdXRlZCBhZ2FpbnN0IHRoZSBtYW5hZ2VyJ3MgbG9jYWwgY2FjaGUuXHJcbiAgQHBhcmFtIFtleHBhbmRdIHtTdHJpbmd8QXJyYXkgb2YgU3RyaW5nfE9iamVjdH0gYW4gZXhwYW5kIHN0cmluZywgYSBxdWVyeSBleHBhbmQgY2xhdXNlLCBvciBhcnJheSBvZiBzdHJpbmcgcGF0aHNcclxuICBAcmV0dXJuIHtBcnJheSBvZiBFbnRpdHl9IGxvY2FsIHF1ZXJpZWQgcm9vdCBlbnRpdGllcyBhbmQgdGhlaXIgcmVsYXRlZCBlbnRpdGllcywgaW5jbHVkaW5nIGRlbGV0ZWQgZW50aXRpZXMuIER1cGxpY2F0ZXMgYXJlIHJlbW92ZWQgYW5kIGVudGl0eSBvcmRlciBpcyBpbmRldGVybWluYXRlLlxyXG4gICoqL1xyXG4gIGdldEVudGl0eUdyYXBoKHF1ZXJ5OiBFbnRpdHlRdWVyeSwgZXhwYW5kOiBzdHJpbmcgfCBBcnJheTxzdHJpbmc+IHwgRXhwYW5kQ2xhdXNlKTogQXJyYXk8RW50aXR5PjtcclxuXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBtaXhpbkVudGl0eUdyYXBoKGVtY2xhc3M6IHsgbmV3KCk6IEVudGl0eU1hbmFnZXIgfSkge1xyXG4gIGNvbnN0IHByb3RvID0gRW50aXR5TWFuYWdlci5wcm90b3R5cGU7XHJcblxyXG4gIGlmICghKHByb3RvIGFzIGFueSkuZ2V0RW50aXR5R3JhcGgpIHtcclxuICAgIChwcm90byBhcyBhbnkpLmdldEVudGl0eUdyYXBoID0gZ2V0RW50aXR5R3JhcGg7XHJcbiAgfVxyXG59XHJcblxyXG5taXhpbkVudGl0eUdyYXBoKEVudGl0eU1hbmFnZXIpO1xyXG5cclxuXHJcbmZ1bmN0aW9uIGdldEVudGl0eUdyYXBoKHJvb3RzOiBFbnRpdHkgfCBBcnJheTxFbnRpdHk+IHwgRW50aXR5UXVlcnksIGV4cGFuZDogc3RyaW5nIHwgQXJyYXk8c3RyaW5nPiB8IEV4cGFuZENsYXVzZSkge1xyXG4gIGlmIChyb290cyBpbnN0YW5jZW9mIEVudGl0eVF1ZXJ5KSB7XHJcbiAgICBsZXQgbmV3Um9vdHMgPSB0aGlzLmV4ZWN1dGVRdWVyeUxvY2FsbHkocm9vdHMpO1xyXG4gICAgcmV0dXJuIGdldEVudGl0eUdyYXBoQ29yZShuZXdSb290cywgZXhwYW5kIHx8IHJvb3RzLmV4cGFuZENsYXVzZSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHJldHVybiBnZXRFbnRpdHlHcmFwaENvcmUocm9vdHMsIGV4cGFuZCk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRFbnRpdHlHcmFwaENvcmUocm9vdDogRW50aXR5IHwgQXJyYXk8RW50aXR5PiwgZXhwYW5kOiBzdHJpbmcgfCBBcnJheTxzdHJpbmc+IHwgRXhwYW5kQ2xhdXNlKSB7XHJcbiAgbGV0IGVudGl0eUdyb3VwTWFwOiB7IFtpbmRleDogc3RyaW5nXTogRW50aXR5R3JvdXAgfTtcclxuICBsZXQgZ3JhcGggPSBbXSBhcyBBcnJheTxFbnRpdHk+O1xyXG4gIGxldCByb290VHlwZTogRW50aXR5VHlwZTtcclxuICBsZXQgcm9vdHMgPSBBcnJheS5pc0FycmF5KHJvb3QpID8gcm9vdCA6IFtyb290XTtcclxuICBhZGRUb0dyYXBoKHJvb3RzKTsgICAgIC8vIHJlbW92ZXMgZHVwcyAmIG51bGxzXHJcbiAgcm9vdHMgPSBncmFwaC5zbGljZSgpOyAvLyBjb3B5IG9mIGRlLWR1cGVkIHJvb3RzXHJcbiAgaWYgKHJvb3RzLmxlbmd0aCkge1xyXG4gICAgZ2V0Um9vdEluZm8oKTtcclxuICAgIGdldEV4cGFuZCgpO1xyXG4gICAgYnVpbGRHcmFwaCgpO1xyXG4gIH1cclxuICByZXR1cm4gZ3JhcGg7XHJcblxyXG4gIGZ1bmN0aW9uIGFkZFRvR3JhcGgoZW50aXRpZXM6IEFycmF5PEVudGl0eT4pIHtcclxuICAgIGVudGl0aWVzLmZvckVhY2goZnVuY3Rpb24gKGVudGl0eSkge1xyXG4gICAgICBpZiAoZW50aXR5ICYmIGdyYXBoLmluZGV4T2YoZW50aXR5KSA8IDApIHtcclxuICAgICAgICBncmFwaC5wdXNoKGVudGl0eSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZnVuY3Rpb24gZ2V0Um9vdEluZm8oKSB7XHJcbiAgICBsZXQgY29tcGF0VHlwZXM6IEFycmF5PEVudGl0eVR5cGU+O1xyXG5cclxuICAgIHJvb3RzLmZvckVhY2goZnVuY3Rpb24gKHJvb3QsIGl4KSB7XHJcbiAgICAgIGxldCBhc3BlY3Q7XHJcbiAgICAgIGlmICghcm9vdCB8fCAhKGFzcGVjdCA9IHJvb3QuZW50aXR5QXNwZWN0KSkge1xyXG4gICAgICAgIHRocm93IGdldFJvb3RFcnIoaXgsICdpcyBub3QgYW4gZW50aXR5Jyk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGFzcGVjdC5lbnRpdHlTdGF0ZSA9PT0gRW50aXR5U3RhdGUuRGV0YWNoZWQpIHtcclxuICAgICAgICB0aHJvdyBnZXRSb290RXJyKGl4LCAnaXMgYSBkZXRhY2hlZCBlbnRpdHknKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgbGV0IGVtID0gYXNwZWN0LmVudGl0eU1hbmFnZXI7XHJcbiAgICAgIGlmIChlbnRpdHlHcm91cE1hcCkge1xyXG4gICAgICAgIGlmIChlbnRpdHlHcm91cE1hcCAhPT0gZW0uX2VudGl0eUdyb3VwTWFwKSB7XHJcbiAgICAgICAgICB0aHJvdyBnZXRSb290RXJyKGl4LCBcImhhcyBhIGRpZmZlcmVudCAnRW50aXR5TWFuYWdlcicgdGhhbiBvdGhlciByb290c1wiKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZW50aXR5R3JvdXBNYXAgPSBlbS5fZW50aXR5R3JvdXBNYXA7XHJcbiAgICAgIH1cclxuICAgICAgZ2V0Um9vdFR5cGUocm9vdCwgaXgpO1xyXG5cclxuICAgIH0pO1xyXG5cclxuICAgIGZ1bmN0aW9uIGdldFJvb3RFcnIoaXg6IG51bWJlciwgbXNnOiBzdHJpbmcpIHtcclxuICAgICAgcmV0dXJuIG5ldyBFcnJvcihcIidnZXRFbnRpdHlHcmFwaCcgcm9vdFtcIiArIGl4ICsgXCJdIFwiICsgbXNnKTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBnZXRSb290VHlwZShyb290OiBFbnRpdHksIGl4OiBudW1iZXIpIHtcclxuICAgICAgbGV0IHRoaXNUeXBlID0gcm9vdC5lbnRpdHlUeXBlO1xyXG4gICAgICBpZiAoIXJvb3RUeXBlKSB7XHJcbiAgICAgICAgcm9vdFR5cGUgPSB0aGlzVHlwZTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH0gZWxzZSBpZiAocm9vdFR5cGUgPT09IHRoaXNUeXBlKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIC8vIFR5cGVzIGRpZmZlcnMuIExvb2sgZm9yIGNsb3Nlc3QgY29tbW9uIGJhc2UgdHlwZVxyXG4gICAgICAvLyBkb2VzIHRoaXNUeXBlIGRlcml2ZSBmcm9tIGN1cnJlbnQgcm9vdFR5cGU/XHJcbiAgICAgIGxldCBiYXNlVHlwZSA9IHJvb3RUeXBlO1xyXG4gICAgICBkbyB7XHJcbiAgICAgICAgY29tcGF0VHlwZXMgPSBjb21wYXRUeXBlcyB8fCBiYXNlVHlwZS5nZXRTZWxmQW5kU3VidHlwZXMoKTtcclxuICAgICAgICBpZiAoY29tcGF0VHlwZXMuaW5kZXhPZih0aGlzVHlwZSkgPiAtMSkge1xyXG4gICAgICAgICAgcm9vdFR5cGUgPSBiYXNlVHlwZTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgYmFzZVR5cGUgPSBiYXNlVHlwZS5iYXNlRW50aXR5VHlwZTtcclxuICAgICAgICBjb21wYXRUeXBlcyA9IG51bGw7XHJcbiAgICAgIH0gd2hpbGUgKGJhc2VUeXBlKTtcclxuXHJcbiAgICAgIC8vIGRvZXMgY3VycmVudCByb290VHlwZSBkZXJpdmVzIGZyb20gdGhpc1R5cGU/XHJcbiAgICAgIGJhc2VUeXBlID0gdGhpc1R5cGU7XHJcbiAgICAgIGRvIHtcclxuICAgICAgICBjb21wYXRUeXBlcyA9IGJhc2VUeXBlLmdldFNlbGZBbmRTdWJ0eXBlcygpO1xyXG4gICAgICAgIGlmIChjb21wYXRUeXBlcy5pbmRleE9mKHJvb3RUeXBlKSA+IC0xKSB7XHJcbiAgICAgICAgICByb290VHlwZSA9IGJhc2VUeXBlO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBiYXNlVHlwZSA9IGJhc2VUeXBlLmJhc2VFbnRpdHlUeXBlO1xyXG4gICAgICB9IHdoaWxlIChiYXNlVHlwZSk7XHJcblxyXG4gICAgICB0aHJvdyBnZXRSb290RXJyKGl4LCBcImlzIG5vdCBFbnRpdHlUeXBlLWNvbXBhdGlibGUgd2l0aCBvdGhlciByb290c1wiKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIGdldEV4cGFuZCgpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGlmICghZXhwYW5kKSB7XHJcbiAgICAgICAgZXhwYW5kID0gW107XHJcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGV4cGFuZCA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAvLyB0cmlja3kgYmVjYXVzZSBCcmVlemUgZXhwYW5kQ2xhdXNlIG5vdCBleHBvc2VkIHB1YmxpY2FsbHlcclxuICAgICAgICBleHBhbmQgPSBuZXcgRW50aXR5UXVlcnkoKS5leHBhbmQoZXhwYW5kKS5leHBhbmRDbGF1c2U7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGV4cGFuZCBpbnN0YW5jZW9mIEV4cGFuZENsYXVzZSAmJiBleHBhbmQucHJvcGVydHlQYXRocykgeyAvLyBleHBhbmQgY2xhdXNlXHJcbiAgICAgICAgZXhwYW5kID0gZXhwYW5kLnByb3BlcnR5UGF0aHM7XHJcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShleHBhbmQpKSB7XHJcbiAgICAgICAgaWYgKCFleHBhbmQuZXZlcnkoZnVuY3Rpb24gKGVsZW0pIHsgcmV0dXJuIHR5cGVvZiBlbGVtID09PSAnc3RyaW5nJzsgfSkpIHtcclxuICAgICAgICAgIHRocm93ICcnO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aHJvdyAnJztcclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoXykge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgICAgXCJleHBhbmQgbXVzdCBiZSBhbiBleHBhbmQgc3RyaW5nLCBhcnJheSBvZiBzdHJpbmcgcGF0aHMsIG9yIGEgcXVlcnkgZXhwYW5kIGNsYXVzZVwiKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIGJ1aWxkR3JhcGgoKSB7XHJcbiAgICBpZiAoZXhwYW5kICYmIGV4cGFuZCBpbnN0YW5jZW9mIEFycmF5ICYmIGV4cGFuZC5sZW5ndGgpIHtcclxuICAgICAgbGV0IGZucyA9IGV4cGFuZC5tYXAobWFrZVBhdGhGbik7XHJcbiAgICAgIGZucy5mb3JFYWNoKGZ1bmN0aW9uIChmbikgeyBmbihyb290cyk7IH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gTWFrZSBmdW5jdGlvbiB0byBnZXQgZW50aXRpZXMgYWxvbmcgYSBzaW5nbGUgZXhwYW5kIHBhdGhcclxuICAvLyBzdWNoIGFzICdPcmRlcnMuT3JkZXJEZXRhaWxzLlByb2R1Y3QnXHJcbiAgZnVuY3Rpb24gbWFrZVBhdGhGbihwYXRoOiBzdHJpbmcpIHtcclxuICAgIGxldCBmbnMgPSBbXSBhcyBBcnJheTxGdW5jdGlvbj4sXHJcbiAgICAgIHNlZ21lbnRzID0gcGF0aC5zcGxpdCgnLicpLFxyXG4gICAgICB0eXBlID0gcm9vdFR5cGU7XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDAsIHNsZW4gPSBzZWdtZW50cy5sZW5ndGg7IGkgPCBzbGVuOyBpKyspIHtcclxuICAgICAgbGV0IGYgPSBtYWtlUGF0aFNlZ21lbnRGbih0eXBlLCBzZWdtZW50c1tpXSk7XHJcbiAgICAgIHR5cGUgPSAoZiBhcyBhbnkpLm5hdlR5cGU7XHJcbiAgICAgIGZucy5wdXNoKGYpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBmdW5jdGlvbiBwYXRoRm4oZW50aXRpZXM6IEFycmF5PEVudGl0eT4pIHtcclxuICAgICAgZm9yIChsZXQgaiA9IDAsIGZsZW4gPSBmbnMubGVuZ3RoOyBqIDwgZmxlbjsgaisrKSB7XHJcbiAgICAgICAgbGV0IGVsZW4gPSBlbnRpdGllcy5sZW5ndGg7XHJcbiAgICAgICAgaWYgKGVsZW4gPT09IDApIHsgcmV0dXJuOyB9IC8vIG5vdGhpbmcgbGVmdCB0byBleHBsb3JlXHJcbiAgICAgICAgLy8gZm4gdG8gZ2V0IHJlbGF0ZWQgZW50aXRpZXMgZm9yIHRoaXMgcGF0aCBzZWdtZW50XHJcbiAgICAgICAgbGV0IGZuID0gZm5zW2pdO1xyXG4gICAgICAgIC8vIGdldCBlbnRpdGllcyByZWxhdGVkIGJ5IHRoaXMgcGF0aCBzZWdtZW50XHJcbiAgICAgICAgbGV0IHJlbGF0ZWQgPSBbXSBhcyBBcnJheTxFbnRpdHk+O1xyXG4gICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgZWxlbjsgaysrKSB7XHJcbiAgICAgICAgICByZWxhdGVkID0gcmVsYXRlZC5jb25jYXQoZm4oZW50aXRpZXNba10pKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYWRkVG9HcmFwaChyZWxhdGVkKTtcclxuICAgICAgICBpZiAoaiA+PSBmbGVuIC0gMSkgeyByZXR1cm47IH0gLy8gbm8gbW9yZSBwYXRoIHNlZ21lbnRzXHJcblxyXG4gICAgICAgIC8vIHJlc2V0IGVudGl0aWVzIHRvIGRlZHVwZWQgcmVsYXRlZCBlbnRpdGllc1xyXG4gICAgICAgIGVudGl0aWVzID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgbCA9IDAsIHJsZW4gPSByZWxhdGVkLmxlbmd0aDsgbCA8IHJsZW47IGwrKykge1xyXG4gICAgICAgICAgbGV0IHIgPSByZWxhdGVkW2xdO1xyXG4gICAgICAgICAgaWYgKGVudGl0aWVzLmluZGV4T2YocikgPCAwKSB7IGVudGl0aWVzLnB1c2gocik7IH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBNYWtlIGZ1bmN0aW9uIHRvIGdldCBlbnRpdGllcyBhbG9uZyBhIHNpbmdsZSBleHBhbmQgcGF0aCBzZWdtZW50XHJcbiAgLy8gc3VjaCBhcyB0aGUgJ09yZGVyRGV0YWlscycgaW4gdGhlICdPcmRlcnMuT3JkZXJEZXRhaWxzLlByb2R1Y3QnIHBhdGhcclxuICBmdW5jdGlvbiBtYWtlUGF0aFNlZ21lbnRGbihiYXNlVHlwZTogRW50aXR5VHlwZSwgc2VnbWVudDogc3RyaW5nKSB7XHJcbiAgICBsZXQgYmFzZVR5cGVOYW1lOiBzdHJpbmcsIGZuID0gdW5kZWZpbmVkLCBuYXZUeXBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgYmFzZVR5cGVOYW1lID0gYmFzZVR5cGUubmFtZTtcclxuICAgICAgbGV0IG5hdiA9IGJhc2VUeXBlLmdldE5hdmlnYXRpb25Qcm9wZXJ0eShzZWdtZW50KTtcclxuICAgICAgbGV0IGZrTmFtZSA9IG5hdi5mb3JlaWduS2V5TmFtZXNbMF07XHJcbiAgICAgIGlmICghbmF2KSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHNlZ21lbnQgKyBcIiBpcyBub3QgYSBuYXZpZ2F0aW9uIHByb3BlcnR5IG9mIFwiICsgYmFzZVR5cGVOYW1lKTtcclxuICAgICAgfVxyXG4gICAgICBuYXZUeXBlID0gbmF2LmVudGl0eVR5cGU7XHJcbiAgICAgIC8vIGFkZCBkZXJpdmVkIHR5cGVzXHJcbiAgICAgIGxldCBuYXZUeXBlcyA9IG5hdlR5cGUuZ2V0U2VsZkFuZFN1YnR5cGVzKCk7XHJcbiAgICAgIGxldCBncnBzID0gW10gYXMgQXJyYXk8RW50aXR5R3JvdXA+OyAvLyBub24tZW1wdHkgZ3JvdXBzIGZvciB0aGVzZSB0eXBlc1xyXG4gICAgICBuYXZUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uICh0KSB7XHJcbiAgICAgICAgbGV0IGdycCA9IGVudGl0eUdyb3VwTWFwW3QubmFtZV07XHJcbiAgICAgICAgaWYgKGdycCAmJiBncnAuX2VudGl0aWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIGdycHMucHVzaChncnApO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICAgIGxldCBncnBDb3VudCA9IGdycHMubGVuZ3RoO1xyXG4gICAgICBpZiAoZ3JwQ291bnQgPT09IDApIHtcclxuICAgICAgICAvLyBubyByZWxhdGVkIGVudGl0aWVzIGluIGNhY2hlXHJcbiAgICAgICAgZm4gPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXSBhcyBBcnJheTxFbnRpdHk+OyB9O1xyXG4gICAgICB9IGVsc2UgaWYgKGZrTmFtZSkge1xyXG4gICAgICAgIGZuID0gZnVuY3Rpb24gKGVudGl0eTogRW50aXR5KSB7XHJcbiAgICAgICAgICBsZXQgdmFsID0gbnVsbDtcclxuICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGxldCBrZXlWYWx1ZSA9IGVudGl0eS5nZXRQcm9wZXJ0eShma05hbWUpO1xyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdycENvdW50OyBpICs9IDEpIHtcclxuICAgICAgICAgICAgICB2YWwgPSBncnBzW2ldLl9lbnRpdGllc1tncnBzW2ldLl9pbmRleE1hcFtrZXlWYWx1ZV1dO1xyXG4gICAgICAgICAgICAgIGlmICh2YWwpIHsgYnJlYWs7IH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBjYXRjaCAoZSkgeyByZXRocm93KGUpOyB9XHJcbiAgICAgICAgICByZXR1cm4gdmFsO1xyXG4gICAgICAgIH07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZmtOYW1lID0gbmF2LmludmVyc2UgP1xyXG4gICAgICAgICAgbmF2LmludmVyc2UuZm9yZWlnbktleU5hbWVzWzBdIDpcclxuICAgICAgICAgIG5hdi5pbnZGb3JlaWduS2V5TmFtZXNbMF07XHJcbiAgICAgICAgaWYgKCFma05hbWUpIHsgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW52ZXJzZSBrZXlzXCIpOyB9XHJcbiAgICAgICAgZm4gPSBmdW5jdGlvbiAoZW50aXR5OiBFbnRpdHkpIHtcclxuICAgICAgICAgIGxldCB2YWxzID0gW10gYXMgQXJyYXk8RW50aXR5PjtcclxuICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGxldCBrZXlWYWx1ZSA9IGVudGl0eS5lbnRpdHlBc3BlY3QuZ2V0S2V5KCkudmFsdWVzWzBdO1xyXG4gICAgICAgICAgICBncnBzLmZvckVhY2goZnVuY3Rpb24gKGdycCkge1xyXG4gICAgICAgICAgICAgIHZhbHMgPSB2YWxzLmNvbmNhdChncnAuX2VudGl0aWVzLmZpbHRlcihmdW5jdGlvbiAoZW4pIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBlbiAmJiBlbi5nZXRQcm9wZXJ0eShma05hbWUpID09PSBrZXlWYWx1ZTtcclxuICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfSBjYXRjaCAoZSkgeyByZXRocm93KGUpOyB9XHJcbiAgICAgICAgICByZXR1cm4gdmFscztcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICAgIChmbiBhcyBhbnkpLm5hdlR5cGUgPSBuYXZUeXBlO1xyXG4gICAgICAoZm4gYXMgYW55KS5wYXRoID0gc2VnbWVudDtcclxuXHJcbiAgICB9IGNhdGNoIChlcnIpIHsgcmV0aHJvdyhlcnIpOyB9XHJcbiAgICByZXR1cm4gZm47XHJcblxyXG4gICAgZnVuY3Rpb24gcmV0aHJvdyhlOiBFcnJvcikge1xyXG4gICAgICBsZXQgdHlwZU5hbWUgPSBiYXNlVHlwZU5hbWUgfHwgYmFzZVR5cGU7XHJcbiAgICAgIGxldCBlcnJvciA9IG5ldyBFcnJvcihcIidnZXRFbnRpdHlHcmFwaCcgY2FuJ3QgZXhwYW5kICdcIiArIHNlZ21lbnQgKyBcIicgZm9yIFwiICsgdHlwZU5hbWUpO1xyXG4gICAgICAoZXJyb3IgYXMgYW55KS5pbm5lckVycm9yID0gZTtcclxuICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5cclxuIl19