UNPKG

ngx-relationship-visualiser

Version:

A D3 force-directed-graph, implemented in Typescript for Angular, generates a visualisation graph with customisable link lengths and multiple labels between nodes. The graph can handle new data that will update lines, nodes, links, and path labels. Whenev

153 lines 19.6 kB
import * as dagre from '@dagrejs/dagre'; import { Injectable } from '@angular/core'; import * as i0 from "@angular/core"; export var Orientation; (function (Orientation) { Orientation["LEFT_TO_RIGHT"] = "LR"; Orientation["RIGHT_TO_LEFT"] = "RL"; Orientation["TOP_TO_BOTTOM"] = "TB"; Orientation["BOTTOM_TO_TOP"] = "BT"; })(Orientation || (Orientation = {})); export var Alignment; (function (Alignment) { Alignment["CENTER"] = "C"; Alignment["UP_LEFT"] = "UL"; Alignment["UP_RIGHT"] = "UR"; Alignment["DOWN_LEFT"] = "DL"; Alignment["DOWN_RIGHT"] = "DR"; })(Alignment || (Alignment = {})); export class DagreNodesOnlyLayout { defaultSettings = { orientation: Orientation.LEFT_TO_RIGHT, marginX: 70, marginY: 70, edgePadding: 200, rankPadding: 300, nodePadding: 100, curveDistance: 20, multigraph: true, compound: true, align: Alignment.UP_RIGHT, acyclicer: undefined, ranker: 'network-simplex', }; dagreGraph; dagreNodes; dagreEdges; renderLayout(graph) { this.createDagreGraph(graph); dagre.layout(this.dagreGraph); for (const dagreNodeId in this.dagreGraph._nodes) { const dagreNode = this.dagreGraph._nodes[dagreNodeId]; const node = graph.nodes.find((n) => n.id === dagreNode.id); if (node.fx === null && node.fy === null) { // Check if the node has any associated edges const hasAssociatedEdges = graph.links.some((link) => link.source === dagreNode.id || link.target === dagreNode.id); if (hasAssociatedEdges) { node.fx = dagreNode.x; node.fy = dagreNode.y; } } node.dimension = { width: dagreNode.width, height: dagreNode.height, }; } return graph; } initRenderLayout(graph) { this.createDagreGraph(graph); dagre.layout(this.dagreGraph); let minFy = Infinity; for (const dagreNodeId in this.dagreGraph._nodes) { const dagreNode = this.dagreGraph._nodes[dagreNodeId]; const node = graph.nodes.find((n) => n.id === dagreNode.id); // Check if the node has any associated edges const hasAssociatedEdges = graph.links.some((link) => link.source === dagreNode.id || link.target === dagreNode.id); if (hasAssociatedEdges) { node.fx = dagreNode.x; node.fy = dagreNode.y; minFy = Math.min(minFy, dagreNode.y - this.defaultSettings.marginY); } else { // Give them a null value to later random position them only when the layout button is pressed so they come into view node.fx = null; node.fy = null; } node.dimension = { width: dagreNode.width, height: dagreNode.height, }; } // Adjust the fy values to start from 0 if there are associated edges if (minFy !== Infinity) { for (const node of graph.nodes) { if (node.fy !== null) { node.fy -= minFy; } } } return graph; } createDagreGraph(graph) { const settings = Object.assign({}, this.defaultSettings); this.dagreGraph = new dagre.graphlib.Graph({ compound: settings.compound, multigraph: settings.multigraph, }); this.dagreGraph.setGraph({ rankdir: settings.orientation, marginx: settings.marginX, marginy: settings.marginY, edgesep: settings.edgePadding, ranksep: settings.rankPadding, nodesep: settings.nodePadding, align: settings.align, acyclicer: settings.acyclicer, ranker: settings.ranker, multigraph: settings.multigraph, compound: settings.compound, }); this.dagreNodes = graph.nodes.map((n) => { const node = Object.assign({}, n); node.width = 20; node.height = 20; node.x = n.fx; node.y = n.fy; return node; }); this.dagreEdges = graph.links.map((l) => { const newLink = Object.assign({}, l); return newLink; }); for (const node of this.dagreNodes) { if (!node.width) { node.width = 20; } if (!node.height) { node.height = 30; } // update dagre this.dagreGraph.setNode(node.id, node); } // update dagre for (const edge of this.dagreEdges) { if (settings.multigraph) { this.dagreGraph.setEdge(edge.source, edge.target, edge, edge.linkId); } else { this.dagreGraph.setEdge(edge.source, edge.target); } } return this.dagreGraph; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DagreNodesOnlyLayout, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DagreNodesOnlyLayout, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DagreNodesOnlyLayout, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFncmUtbGF5b3V0LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVsYXRpb25zaGlwLXZpc3VhbGlzZXItbGliL2xpYi92aXN1YWxpc2VyL3NlcnZpY2VzL2RhZ3JlLWxheW91dC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxLQUFLLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFFM0MsTUFBTSxDQUFOLElBQVksV0FLWDtBQUxELFdBQVksV0FBVztJQUNyQixtQ0FBb0IsQ0FBQTtJQUNwQixtQ0FBb0IsQ0FBQTtJQUNwQixtQ0FBb0IsQ0FBQTtJQUNwQixtQ0FBb0IsQ0FBQTtBQUN0QixDQUFDLEVBTFcsV0FBVyxLQUFYLFdBQVcsUUFLdEI7QUFFRCxNQUFNLENBQU4sSUFBWSxTQU1YO0FBTkQsV0FBWSxTQUFTO0lBQ25CLHlCQUFZLENBQUE7SUFDWiwyQkFBYyxDQUFBO0lBQ2QsNEJBQWUsQ0FBQTtJQUNmLDZCQUFnQixDQUFBO0lBQ2hCLDhCQUFpQixDQUFBO0FBQ25CLENBQUMsRUFOVyxTQUFTLEtBQVQsU0FBUyxRQU1wQjtBQW1CRCxNQUFNLE9BQU8sb0JBQW9CO0lBQy9CLGVBQWUsR0FBRztRQUNoQixXQUFXLEVBQUUsV0FBVyxDQUFDLGFBQWE7UUFDdEMsT0FBTyxFQUFFLEVBQUU7UUFDWCxPQUFPLEVBQUUsRUFBRTtRQUNYLFdBQVcsRUFBRSxHQUFHO1FBQ2hCLFdBQVcsRUFBRSxHQUFHO1FBQ2hCLFdBQVcsRUFBRSxHQUFHO1FBQ2hCLGFBQWEsRUFBRSxFQUFFO1FBQ2pCLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLFFBQVEsRUFBRSxJQUFJO1FBQ2QsS0FBSyxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQ3pCLFNBQVMsRUFBRSxTQUFTO1FBQ3BCLE1BQU0sRUFB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QUFFLENBQUM7WUFDbkIsQ0FBQztZQUVELGVBQWU7WUFDZixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pDLENBQUM7UUFFRCxlQUFlO1FBQ2YsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbkMsSUFBSSxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3ZFLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNwRCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO3dHQWpKVSxvQkFBb0I7NEdBQXBCLG9CQUFvQixjQUZuQixNQUFNOzs0RkFFUCxvQkFBb0I7a0JBSGhDLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZGFncmUgZnJvbSAnQGRhZ3JlanMvZGFncmUnO1xyXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5leHBvcnQgZW51bSBPcmllbnRhdGlvbiB7XHJcbiAgTEVGVF9UT19SSUdIVCA9ICdMUicsXHJcbiAgUklHSFRfVE9fTEVGVCA9ICdSTCcsXHJcbiAgVE9QX1RPX0JPVFRPTSA9ICdUQicsXHJcbiAgQk9UVE9NX1RPX1RPUCA9ICdCVCcsXHJcbn1cclxuXHJcbmV4cG9ydCBlbnVtIEFsaWdubWVudCB7XHJcbiAgQ0VOVEVSID0gJ0MnLFxyXG4gIFVQX0xFRlQgPSAnVUwnLFxyXG4gIFVQX1JJR0hUID0gJ1VSJyxcclxuICBET1dOX0xFRlQgPSAnREwnLFxyXG4gIERPV05fUklHSFQgPSAnRFInLFxyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIERhZ3JlU2V0dGluZ3Mge1xyXG4gIG9yaWVudGF0aW9uPzogT3JpZW50YXRpb247XHJcbiAgbWFyZ2luWD86IG51bWJlcjtcclxuICBtYXJnaW5ZPzogbnVtYmVyO1xyXG4gIGVkZ2VQYWRkaW5nPzogbnVtYmVyO1xyXG4gIHJhbmtQYWRkaW5nPzogbnVtYmVyO1xyXG4gIG5vZGVQYWRkaW5nPzogbnVtYmVyO1xyXG4gIGFsaWduPzogQWxpZ25tZW50O1xyXG4gIGFjeWNsaWNlcj86ICdncmVlZHknO1xyXG4gIHJhbmtlcj86ICduZXR3b3JrLXNpbXBsZXgnIHwgJ3RpZ2h0LXRyZWUnIHwgJ2xvbmdlc3QtcGF0aCc7XHJcbiAgbXVsdGlncmFwaD86IGJvb2xlYW47XHJcbiAgY29tcG91bmQ/OiBib29sZWFuO1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgRGFncmVOb2Rlc09ubHlMYXlvdXQge1xyXG4gIGRlZmF1bHRTZXR0aW5ncyA9IHtcclxuICAgIG9yaWVudGF0aW9uOiBPcmllbnRhdGlvbi5MRUZUX1RPX1JJR0hULFxyXG4gICAgbWFyZ2luWDogNzAsXHJcbiAgICBtYXJnaW5ZOiA3MCxcclxuICAgIGVkZ2VQYWRkaW5nOiAyMDAsXHJcbiAgICByYW5rUGFkZGluZzogMzAwLFxyXG4gICAgbm9kZVBhZGRpbmc6IDEwMCxcclxuICAgIGN1cnZlRGlzdGFuY2U6IDIwLFxyXG4gICAgbXVsdGlncmFwaDogdHJ1ZSxcclxuICAgIGNvbXBvdW5kOiB0cnVlLFxyXG4gICAgYWxpZ246IEFsaWdubWVudC5VUF9SSUdIVCxcclxuICAgIGFjeWNsaWNlcjogdW5kZWZpbmVkLFxyXG4gICAgcmFua2VyOiAnbmV0d29yay1zaW1wbGV4JyxcclxuICB9O1xyXG5cclxuICBkYWdyZUdyYXBoOiBhbnk7XHJcbiAgZGFncmVOb2RlczogYW55O1xyXG4gIGRhZ3JlRWRnZXM6IGFueTtcclxuXHJcbiAgcHVibGljIHJlbmRlckxheW91dChncmFwaCkge1xyXG4gICAgdGhpcy5jcmVhdGVEYWdyZUdyYXBoKGdyYXBoKTtcclxuICAgIGRhZ3JlLmxheW91dCh0aGlzLmRhZ3JlR3JhcGgpO1xyXG5cclxuICAgIGZvciAoY29uc3QgZGFncmVOb2RlSWQgaW4gdGhpcy5kYWdyZUdyYXBoLl9ub2Rlcykge1xyXG4gICAgICBjb25zdCBkYWdyZU5vZGUgPSB0aGlzLmRhZ3JlR3JhcGguX25vZGVzW2RhZ3JlTm9kZUlkXTtcclxuICAgICAgY29uc3Qgbm9kZSA9IGdyYXBoLm5vZGVzLmZpbmQoKG4pID0+IG4uaWQgPT09IGRhZ3JlTm9kZS5pZCk7XHJcblxyXG4gICAgICBpZiAobm9kZS5meCA9PT0gbnVsbCAmJiBub2RlLmZ5ID09PSBudWxsKSB7XHJcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIG5vZGUgaGFzIGFueSBhc3NvY2lhdGVkIGVkZ2VzXHJcbiAgICAgICAgY29uc3QgaGFzQXNzb2NpYXRlZEVkZ2VzID0gZ3JhcGgubGlua3Muc29tZShcclxuICAgICAgICAgIChsaW5rKSA9PiBsaW5rLnNvdXJjZSA9PT0gZGFncmVOb2RlLmlkIHx8IGxpbmsudGFyZ2V0ID09PSBkYWdyZU5vZGUuaWRcclxuICAgICAgICApO1xyXG4gICAgICAgIGlmIChoYXNBc3NvY2lhdGVkRWRnZXMpIHtcclxuICAgICAgICAgIG5vZGUuZnggPSBkYWdyZU5vZGUueDtcclxuICAgICAgICAgIG5vZGUuZnkgPSBkYWdyZU5vZGUueTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIG5vZGUuZGltZW5zaW9uID0ge1xyXG4gICAgICAgIHdpZHRoOiBkYWdyZU5vZGUud2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBkYWdyZU5vZGUuaGVpZ2h0LFxyXG4gICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBncmFwaDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBpbml0UmVuZGVyTGF5b3V0KGdyYXBoKSB7XHJcbiAgICB0aGlzLmNyZWF0ZURhZ3JlR3JhcGgoZ3JhcGgpO1xyXG4gICAgZGFncmUubGF5b3V0KHRoaXMuZGFncmVHcmFwaCk7XHJcbiAgICBsZXQgbWluRnkgPSBJbmZpbml0eTtcclxuICAgIGZvciAoY29uc3QgZGFncmVOb2RlSWQgaW4gdGhpcy5kYWdyZUdyYXBoLl9ub2Rlcykge1xyXG4gICAgICBjb25zdCBkYWdyZU5vZGUgPSB0aGlzLmRhZ3JlR3JhcGguX25vZGVzW2RhZ3JlTm9kZUlkXTtcclxuICAgICAgY29uc3Qgbm9kZSA9IGdyYXBoLm5vZGVzLmZpbmQoKG4pID0+IG4uaWQgPT09IGRhZ3JlTm9kZS5pZCk7XHJcblxyXG4gICAgICAvLyBDaGVjayBpZiB0aGUgbm9kZSBoYXMgYW55IGFzc29jaWF0ZWQgZWRnZXNcclxuICAgICAgY29uc3QgaGFzQXNzb2NpYXRlZEVkZ2VzID0gZ3JhcGgubGlua3Muc29tZShcclxuICAgICAgICAobGluaykgPT4gbGluay5zb3VyY2UgPT09IGRhZ3JlTm9kZS5pZCB8fCBsaW5rLnRhcmdldCA9PT0gZGFncmVOb2RlLmlkXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBpZiAoaGFzQXNzb2NpYXRlZEVkZ2VzKSB7XHJcbiAgICAgICAgbm9kZS5meCA9IGRhZ3JlTm9kZS54O1xyXG4gICAgICAgIG5vZGUuZnkgPSBkYWdyZU5vZGUueTtcclxuICAgICAgICBtaW5GeSA9IE1hdGgubWluKG1pbkZ5LCBkYWdyZU5vZGUueSAtIHRoaXMuZGVmYXVsdFNldHRpbmdzLm1hcmdpblkpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIEdpdmUgdGhlbSBhIG51bGwgdmFsdWUgdG8gbGF0ZXIgcmFuZG9tIHBvc2l0aW9uIHRoZW0gb25seSB3aGVuIHRoZSBsYXlvdXQgYnV0dG9uIGlzIHByZXNzZWQgc28gdGhleSBjb21lIGludG8gdmlld1xyXG4gICAgICAgIG5vZGUuZnggPSBudWxsO1xyXG4gICAgICAgIG5vZGUuZnkgPSBudWxsO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBub2RlLmRpbWVuc2lvbiA9IHtcclxuICAgICAgICB3aWR0aDogZGFncmVOb2RlLndpZHRoLFxyXG4gICAgICAgIGhlaWdodDogZGFncmVOb2RlLmhlaWdodCxcclxuICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBZGp1c3QgdGhlIGZ5IHZhbHVlcyB0byBzdGFydCBmcm9tIDAgaWYgdGhlcmUgYXJlIGFzc29jaWF0ZWQgZWRnZXNcclxuICAgIGlmIChtaW5GeSAhPT0gSW5maW5pdHkpIHtcclxuICAgICAgZm9yIChjb25zdCBub2RlIG9mIGdyYXBoLm5vZGVzKSB7XHJcbiAgICAgICAgaWYgKG5vZGUuZnkgIT09IG51bGwpIHtcclxuICAgICAgICAgIG5vZGUuZnkgLT0gbWluRnk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGdyYXBoO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGNyZWF0ZURhZ3JlR3JhcGgoZ3JhcGgpOiBhbnkge1xyXG4gICAgY29uc3Qgc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmRlZmF1bHRTZXR0aW5ncyk7XHJcbiAgICB0aGlzLmRhZ3JlR3JhcGggPSBuZXcgZGFncmUuZ3JhcGhsaWIuR3JhcGgoe1xyXG4gICAgICBjb21wb3VuZDogc2V0dGluZ3MuY29tcG91bmQsXHJcbiAgICAgIG11bHRpZ3JhcGg6IHNldHRpbmdzLm11bHRpZ3JhcGgsXHJcbiAgICB9KTtcclxuICAgIHRoaXMuZGFncmVHcmFwaC5zZXRHcmFwaCh7XHJcbiAgICAgIHJhbmtkaXI6IHNldHRpbmdzLm9yaWVudGF0aW9uLFxyXG4gICAgICBtYXJnaW54OiBzZXR0aW5ncy5tYXJnaW5YLFxyXG4gICAgICBtYXJnaW55OiBzZXR0aW5ncy5tYXJnaW5ZLFxyXG4gICAgICBlZGdlc2VwOiBzZXR0aW5ncy5lZGdlUGFkZGluZyxcclxuICAgICAgcmFua3NlcDogc2V0dGluZ3MucmFua1BhZGRpbmcsXHJcbiAgICAgIG5vZGVzZXA6IHNldHRpbmdzLm5vZGVQYWRkaW5nLFxyXG4gICAgICBhbGlnbjogc2V0dGluZ3MuYWxpZ24sXHJcbiAgICAgIGFjeWNsaWNlcjogc2V0dGluZ3MuYWN5Y2xpY2VyLFxyXG4gICAgICByYW5rZXI6IHNldHRpbmdzLnJhbmtlcixcclxuICAgICAgbXVsdGlncmFwaDogc2V0dGluZ3MubXVsdGlncmFwaCxcclxuICAgICAgY29tcG91bmQ6IHNldHRpbmdzLmNvbXBvdW5kLFxyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5kYWdyZU5vZGVzID0gZ3JhcGgubm9kZXMubWFwKChuKSA9PiB7XHJcbiAgICAgIGNvbnN0IG5vZGU6IGFueSA9IE9iamVjdC5hc3NpZ24oe30sIG4pO1xyXG4gICAgICBub2RlLndpZHRoID0gMjA7XHJcbiAgICAgIG5vZGUuaGVpZ2h0ID0gMjA7XHJcbiAgICAgIG5vZGUueCA9IG4uZng7XHJcbiAgICAgIG5vZGUueSA9IG4uZnk7XHJcbiAgICAgIHJldHVybiBub2RlO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5kYWdyZUVkZ2VzID0gZ3JhcGgubGlua3MubWFwKChsKSA9PiB7XHJcbiAgICAgIGNvbnN0IG5ld0xpbms6IGFueSA9IE9iamVjdC5hc3NpZ24oe30sIGwpO1xyXG4gICAgICByZXR1cm4gbmV3TGluaztcclxuICAgIH0pO1xyXG5cclxuICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzLmRhZ3JlTm9kZXMpIHtcclxuICAgICAgaWYgKCFub2RlLndpZHRoKSB7XHJcbiAgICAgICAgbm9kZS53aWR0aCA9IDIwO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICghbm9kZS5oZWlnaHQpIHtcclxuICAgICAgICBub2RlLmhlaWdodCA9IDMwO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyB1cGRhdGUgZGFncmVcclxuICAgICAgdGhpcy5kYWdyZUdyYXBoLnNldE5vZGUobm9kZS5pZCwgbm9kZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdXBkYXRlIGRhZ3JlXHJcbiAgICBmb3IgKGNvbnN0IGVkZ2Ugb2YgdGhpcy5kYWdyZUVkZ2VzKSB7XHJcbiAgICAgIGlmIChzZXR0aW5ncy5tdWx0aWdyYXBoKSB7XHJcbiAgICAgICAgdGhpcy5kYWdyZUdyYXBoLnNldEVkZ2UoZWRnZS5zb3VyY2UsIGVkZ2UudGFyZ2V0LCBlZGdlLCBlZGdlLmxpbmtJZCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5kYWdyZUdyYXBoLnNldEVkZ2UoZWRnZS5zb3VyY2UsIGVkZ2UudGFyZ2V0KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmRhZ3JlR3JhcGg7XHJcbiAgfVxyXG59XHJcbiJdfQ==