UNPKG

basicprimitives

Version:

Basic Primitives Diagrams for JavaScript - data visualization components library that implements organizational chart and multi-parent dependency diagrams, contains implementations of JavaScript Controls and PDF rendering plugins.

154 lines (128 loc) 5.25 kB
import getFamilyLoops from '../../algorithms/getFamilyLoops'; import FamilyItem from '../../models/FamilyItem'; import { GroupByType } from '../../enums'; export default function RemoveLoopsTask(logicalFamilyTask) { var _data = { logicalFamily: null, maximumId: null, loops: [] // populate collection of pairs between fake parents and fake children }; function process(debug) { var logicalFamily = logicalFamilyTask.getLogicalFamily(), maximumId = logicalFamilyTask.getMaximumId(); var result = removeLoops(logicalFamily, maximumId, debug); _data.logicalFamily = result.logicalFamily; _data.maximumId = result.maximumId; _data.loops = result.loops; if (debug && !logicalFamily.validate()) { throw "References are broken in family structure!"; } return true; } function removeLoops(logicalFamily, maximumId, debug) { var fakeChild, fakeParent, index, len, index2, len2, edgesToReverse = getFamilyLoops(logicalFamily, debug), fakePairs = []; /* group edges by child node */ var loops = []; var loopsHash = {}; for (index = 0, len = edgesToReverse.length; index < len; index += 1) { var edge = edgesToReverse[index]; if (!loopsHash.hasOwnProperty(edge.to)) { loopsHash[edge.to] = { itemid: edge.to, parents: [edge.from] }; loops.push(loopsHash[edge.to]); } else { loopsHash[edge.to].parents.push(edge.from); } } var fakeChildren = {}; // reuse fake children across removed edges if (loops.length > 0) { logicalFamily = logicalFamily.clone(); for (index = 0, len = loops.length; index < len; index += 1) { var loop = loops[index]; var parents = loop.parents; var itemParents = []; logicalFamily.loopParents(this, loop.itemid, function (parentid, parent) { itemParents.push(parentid); return logicalFamily.SKIP; }); for (index2 = 0, len2 = itemParents.length; index2 < len2; index2 += 1) { /* remove relation in temp structure */ logicalFamily.removeChildRelation(itemParents[index2], loop.itemid); } /* create fake parent and child items to loop item to its parent */ maximumId += 1; var isConnectionsVisible = (itemParents.length <= parents.length); /* add fake parent */ fakeParent = new FamilyItem({ id: (maximumId), isVisible: false, isActive: false, isLevelNeutral: false, hideParentConnection: isConnectionsVisible, hideChildrenConnection: isConnectionsVisible, levelGravity: GroupByType.Children, itemConfig: { title: "fake parent #" + maximumId, description: "This is a fake parent item, it was created by loops removal task." } }); logicalFamily.add([], fakeParent.id, fakeParent); logicalFamily.adopt([fakeParent.id], loop.itemid); fakePairs.push({ from: fakeParent.id, to: loop.itemid, isOppositeFlow: false }); for (index2 = 0, len2 = parents.length; index2 < len2; index2 += 1) { var parentid = parents[index2]; fakeChild = fakeChildren[parentid]; if (fakeChild == null) { /* add fake child */ maximumId += 1; fakeChild = new FamilyItem({ id: (maximumId), isVisible: false, isActive: false, isLevelNeutral: false, hideParentConnection: true, hideChildrenConnection: true, levelGravity: GroupByType.Parents, itemConfig: { title: "fake child #" + maximumId, description: "This is a fake child item, it was created by loops removal task." } }); fakeChildren[parentid] = fakeChild; logicalFamily.add([parentid], fakeChild.id, fakeChild); fakePairs.push({ from: parentid, to: fakeChild.id, isOppositeFlow: false }); } logicalFamily.adopt([fakeParent.id], fakeChild.id); fakePairs.push({ from: fakeParent.id, to: fakeChild.id, isOppositeFlow: true }); } // assign remaining parents of our item to the fake parent var parentsHash = {}; for (index2 = 0, len2 = parents.length; index2 < len2; index2 += 1) { parentsHash[parents[index2]] = true; } for (index2 = 0, len2 = itemParents.length; index2 < len2; index2 += 1) { if (!parentsHash.hasOwnProperty(itemParents[index2])) { logicalFamily.adopt([itemParents[index2]], fakeParent.id); } } } } return { maximumId: maximumId, logicalFamily: logicalFamily, loops: fakePairs } } function getLogicalFamily() { return _data.logicalFamily; } function getMaximumId() { return _data.maximumId; } function getLoops() { return _data.loops; } return { process: process, getLogicalFamily: getLogicalFamily, getMaximumId: getMaximumId, getLoops: getLoops }; };