123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- package de.tu_darmstadt.informatik.tk.scopviz.graphs;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Random;
- import org.graphstream.graph.Element;
- import org.graphstream.graph.Node;
- import org.graphstream.ui.geom.Point3;
- import org.graphstream.ui.graphicGraph.GraphPosLengthUtils;
- import de.tu_darmstadt.informatik.tk.scopviz.debug.Debug;
- import de.tu_darmstadt.informatik.tk.scopviz.main.Layer;
- import de.tu_darmstadt.informatik.tk.scopviz.main.Main;
- import de.tu_darmstadt.informatik.tk.scopviz.ui.OptionsManager;
- public class GraphHelper {
- public static MyGraph newMerge(boolean vertical, MyGraph... sources) {
- String newID = "Composite";
- for (MyGraph g : sources) {
- newID = newID.concat("_" + g.getId());
- }
- MyGraph result = new MyGraph(newID);
- for (MyGraph g : sources) {
- result.addSubGraph(g);
- mergeInto(result, g);
- }
- return result;
- }
- /**
- * merges the two graphs into one. every Node gets two attributes,
- * originalGraph and originalElement which are the ids of the Graph and the
- * graphid + "+#" + nodeid
- *
- * @param target
- * the graph that the source will be merged into
- * @param source
- * the graph that will be merged into the traget graph
- */
- // TODO better way to do scaling
- private static void mergeInto(MyGraph target, MyGraph source) {
- double targetMinX = target.getMinX();
- double targetMaxX = target.getMaxX();
- double sourceMinX = source.getMinX();
- double sourceMaxX = source.getMaxX();
- double scalingFactorX = ((targetMaxX - targetMinX + 1) / (target.getNodeCount() + 1))
- / ((sourceMaxX - sourceMinX + 1) / (source.getNodeCount() + 1));
- double xOffset = targetMaxX - sourceMinX + 10;
- double targetMinY = target.getMinY();
- double sourceMinY = source.getMinY();
- double scalingFactorY = scalingFactorX;
- // adjust Cordinates and Attributes
- adjustSourceXCoordinates(source, scalingFactorX, xOffset, sourceMinX);
- graphAttribute(target);
- graphAttribute(source);
- adjustSourceYCoordinates(source, scalingFactorY, targetMinY, sourceMinY);
- // Copy Nodes and Edges
- HashMap<String, String> newIds = copyNodes(target, source);
- copyEdges(target, source, newIds);
- }
- /**
- * copys all edges from one Graph to another adjusting for nodeId changes.
- * this must always be called after copyNodes.
- *
- * @param target
- * the graph that the new node will be added into
- * @param source
- * the Graph that has the nodes to be copied
- * @param newIds
- * a HashMap that give the new id Values of copied Nodes
- */
- private static void copyEdges(MyGraph target, MyGraph source, HashMap<String, String> newIds) {
- Random ran = new Random();
- boolean searchingForId = true;
- for (MyEdge e : source.<MyEdge>getEdgeSet()) {
- // finding a new ID for the Node
- searchingForId = true;
- String newId = source.getId() + e.getId();
- while (searchingForId) {
- if (target.getEdge(newId) == null) {
- searchingForId = false;
- target.addEdge(newId, newIds.get(e.getSourceNode().getId()), newIds.get(e.getTargetNode().getId()),
- e.isDirected());
- if (e.getAttribute("originalElement") == null) {
- target.getEdge(newId).addAttribute("originalElement", source.getId().concat("+#" + e.getId()));
- } else {
- target.getEdge(newId).addAttribute("originalElement", e.getAttribute("originalElement"));
- }
- } else {
- newId = newId.concat(String.valueOf((char) (ran.nextInt(52) + 'a')));
- }
- }
- for (String s : e.getAttributeKeySet()) {
- target.getEdge(newId).addAttribute(s, e.getAttribute(s));
- }
- }
- }
- /**
- * copies all Nodes from one Graph to another always must be called before
- * copyEdges
- *
- * @param target
- * the Graph that the Nodes will be copied into
- * @param source
- * the graph that the node will be taken from
- * @return a HahMap to convert the old id of Nodes to new ones
- */
- private static HashMap<String, String> copyNodes(MyGraph target, MyGraph source) {
- HashMap<String, String> newIds = new HashMap<>();
- Random ran = new Random();
- boolean searchingForId = true;
- for (MyNode n : source.<MyNode>getNodeSet()) {
- // finding a new ID for the Node
- searchingForId = true;
- String newId = source.getId() + n.getId();
- while (searchingForId) {
- if (target.getNode(newId) == null) {
- searchingForId = false;
- target.addNode(newId);
- newIds.put(n.getId(), newId);
- if (n.getAttribute("originalElement") == null) {
- target.getNode(newId).addAttribute("originalElement", source.getId().concat("+#" + n.getId()));
- } else {
- target.getNode(newId).addAttribute("originalElement", n.getAttribute("originalElement"));
- }
- } else {
- newId = newId.concat(String.valueOf((char) (ran.nextInt(52) + 'a')));
- }
- }
- for (String s : n.getAttributeKeySet()) {
- Debug.out(s);
- target.getNode(newId).addAttribute(s, n.getAttribute(s));
- }
- }
- return newIds;
- }
- /**
- * adjusts the y coordinates of the source graph so the two are of similar
- * size
- *
- * @param g
- * the source graph with unaltered coordinates
- * @param scalingFactor
- * the factor that is used to ensure a roughly similiar size
- * between the Graphs
- * @param targetMinY
- * the minimal y Coordinate of the target Graph
- * @param sourceMinY
- * the minimal y Coordinate of the source Graph
- */
- private static void adjustSourceYCoordinates(MyGraph g, double scalingFactor, double targetMinY,
- double sourceMinY) {
- for (MyNode n : g.<MyNode>getNodeSet()) {
- double d = (Double) n.getAttribute("y");
- d = d - sourceMinY;
- d = d * scalingFactor;
- d = d + targetMinY;
- n.addAttribute("y", d);
- }
- }
- /**
- * gives all Nodes a parameter that has the Id of the Graph they belonged to
- * before the merge. if a node already has this attriute it will be ignored
- *
- * @param g
- * the originalGraph of the Nodes
- */
- private static void graphAttribute(MyGraph g) {
- for (MyNode n : g.<MyNode>getNodeSet()) {
- if (n.getAttribute("originalGraph") == null) {
- n.addAttribute("originalGraph", g.getId());
- }
- }
- }
- /**
- * adjusts the x coordinates of the source graph so the two are of similar
- * size
- *
- * @param g
- * the source graph with unaltered coordinates
- * @param scalingFactor
- * the factor that is used to ensure a roughly similiar size
- * between the Graphs
- * @param xOffset
- * the x distance between the graphs
- * @param sourceMinY
- * the minimal x Coordinate of the source Graph
- */
- private static void adjustSourceXCoordinates(MyGraph g, Double scalingFactor, Double xOffset, Double SourceMinX) {
- for (MyNode n : g.<MyNode>getNodeSet()) {
- Double d = (Double) n.getAttribute("x");
- d = d - SourceMinX;
- d = d * scalingFactor;
- d = d + xOffset;
- d = d + SourceMinX;
- n.addAttribute("x", d);
- }
- }
- /**
- * Converts the Coordinates of all Nodes into a saveable and uniform Format.
- */
- public static void correctCoordinates(MyGraph g) {
- Point3 coords;
- MyNode n = null;
- Iterator<MyNode> allNodes = g.getNodeIterator();
- while (allNodes.hasNext()) {
- n = allNodes.next();
- if (n.hasAttribute("xyz")) {
- coords = GraphPosLengthUtils.nodePointPosition(n);
- n.setAttribute("x", coords.x);
- propagateAttribute(g, n, "x", coords.x);
- n.setAttribute("y", coords.y);
- propagateAttribute(g, n, "y", coords.y);
- n.removeAttribute("xyz");
- }
- }
- }
- /**
- * Converts the weight property into a label to display on the Graph.
- * Removes all labels if that option is set
- */
- public static void handleEdgeWeight(MyGraph g) {
- if (!Layer.UNDERLAY.equals(g.getAttribute("layer"))) {
- return;
- }
- MyEdge e = null;
- Iterator<MyEdge> allEdges = g.getEdgeIterator();
- while (allEdges.hasNext()) {
- e = allEdges.next();
- if (!e.hasAttribute("weight")) {
- e.addAttribute("weight", OptionsManager.getDefaultWeight());
- }
- if (OptionsManager.isWeightShown()) {
- e.setAttribute("ui.label", e.getAttribute("weight").toString());
- } else {
- e.removeAttribute("ui.label");
- }
- }
- }
- /**
- * adds default to all Nodes and converts yEd attributes to regular ones.
- *
- * @param g
- * the graph that the attributes will be added onto
- */
- public static void setAllDefaults(MyGraph g) {
- for (Node n : g.getNodeSet()) {
- // general defaults
- if (!n.hasAttribute("ui.label")) {
- n.addAttribute("ui.label", "");
- }
- if (!n.hasAttribute("typeofNode") || n.getAttribute("typeofNode").equals("")) {
- n.addAttribute("typeofNode", "standard");
- }
- // underlay defaults
- if (Layer.UNDERLAY.equals(g.getAttribute("layer"))) {
- if (!n.hasAttribute("typeofDevice") || n.getAttribute("typeofDevice").equals("")) {
- n.addAttribute("typeofDevice", "unknown");
- }
- if (!n.hasAttribute("lat") || n.getAttribute("long").equals("")) {
- n.addAttribute("lat", OptionsManager.getDefaultLat());
- }
- if (!n.hasAttribute("long") || n.getAttribute("long").equals("")) {
- n.addAttribute("long", OptionsManager.getDefaultLong());
- }
- if (!n.hasAttribute("process-max") || n.getAttribute("process-max").equals("")) {
- n.addAttribute("process-max", 0.0);
- }
- }
- // operator defaults
- if (Layer.OPERATOR.equals(g.getAttribute("layer"))) {
- if (!n.hasAttribute("process-need") || n.getAttribute("process-need").equals("")) {
- n.addAttribute("process-need", 0.0);
- }
- }
- }
- }
- /**
- * propagates an Attribute to the Node in the Graph it originated from
- *
- * @param g
- * the root of the Multigraph
- * @param n
- * the Element of the multigraph that was changed
- * @param attribute
- * the attribute that was changed
- * @param value
- * the value the attribute was changed to
- */
- public static void propagateAttribute(MyGraph g, Element n, String attribute, Object value) {
- if (n.getAttribute("originalElement") == null) {
- Debug.out("Debug: Attribute originalElement does not Exist");
- return;
- }
- String origGraph = n.getAttribute("originalElement").toString().split("\\+#")[0];
- String origNode = n.getAttribute("originalElement").toString().split("\\+#")[1];
- MyNode oldNode = null;
- MyEdge oldEdge = null;
- MyGraph old = null;
- Iterator<MyGraph> graphIter = g.getAllSubGraphs().iterator();
- while (graphIter.hasNext()) {
- old = graphIter.next();
- if (old.getId().equals(origGraph)) {
- Iterator<MyNode> nodeIter = old.getNodeIterator();
- while (nodeIter.hasNext()) {
- oldNode = nodeIter.next();
- if (oldNode.getId().equals(origNode)) {
- if (value == null) {
- oldNode.removeAttribute(attribute);
- } else {
- oldNode.addAttribute(attribute, value);
- }
- Debug.out("Debug: propagating successfull");
- return;
- }
- }
- Iterator<MyEdge> edgeIter = old.getEdgeIterator();
- while (edgeIter.hasNext()) {
- oldEdge = edgeIter.next();
- if (oldEdge.getId().equals(origNode)) {
- if (value == null) {
- oldEdge.removeAttribute(attribute);
- } else {
- oldEdge.addAttribute(attribute, value);
- }
- Debug.out("Debug: propagating successfull");
- return;
- }
- }
- Debug.out("WARNING: could not find the specified Element " + origNode + " in the Graph " + origGraph,
- 2);
- return;
- }
- }
- Debug.out("WARNING: could not find the specified Graph " + origGraph, 2);
- }
- /**
- * propagates the deletion of a collection of Elements to the Graph the
- * element originally came from.
- *
- * @param g
- * the root graph of the multigraph
- * @param col
- * the collection that has to be deleted
- * @return the id of the graph that the elements were deleted from or null
- * if no change occurred
- */
- public static String propagateElementDeletion(MyGraph g, Collection<? extends Element> col) {
- Iterator<? extends Element> elementIter = col.iterator();
- while (elementIter.hasNext()) {
- Element e = elementIter.next();
- return propagateElementDeletion(g, e);
- }
- return null;
- }
- /**
- * propagates the deletion of an Element to the Graph it originated from
- *
- * @param g
- * the root graph of the multigraph
- * @param e
- * the element that will be deleted
- * @return the id of the graph that the elements were deleted from or null
- * if no change occurred
- */
- public static String propagateElementDeletion(MyGraph g, Element e) {
- if (e.getAttribute("originalElement") == null) {
- return null;
- }
- String origGraph = e.getAttribute("originalElement").toString().split("\\+#")[0];
- String origId = e.getAttribute("originalElement").toString().split("\\+#")[1];
- Iterator<MyGraph> graphIter = g.getAllSubGraphs().iterator();
- while (graphIter.hasNext()) {
- MyGraph temp = graphIter.next();
- if (temp.getId().equals(origGraph)) {
- if (e instanceof MyNode && temp.getNode(origId) != null) {
- temp.removeNode(origId);
- return temp.getId();
- } else if (e instanceof MyEdge && temp.getEdge(origId) != null) {
- temp.removeEdge(origId);
- return temp.getId();
- } else {
- Debug.out("INFORMATION: could not Delete Element bećause it didn't exist: " + origGraph + ":"
- + origId, 1);
- }
- return null;
- }
- }
- Debug.out("WARNING: could not find the specified Graph " + origGraph, 2);
- return null;
- }
- /**
- * propagates the undeletion of an Element
- *
- * @param g
- * the root graph of the multigraph
- * @param e
- * the element that will be readded
- * @param newNodeId
- * the new id of the undeleted Node, only important if elemen is
- * an Edge
- * @return the new originalElement Attribute
- */
- public static String propagateElementUndeletion(MyGraph g, Element e, String newNodeId) {
- if (e.getAttribute("originalElement") == null) {
- return null;
- }
- String origGraph = e.getAttribute("originalElement").toString().split("\\+#")[0];
- // String origId =
- // e.getAttribute("originalElement").toString().split("\\+#")[1];
- Iterator<MyGraph> graphIter = g.getAllSubGraphs().iterator();
- HashMap<String, Object> attributes = new HashMap<String, Object>();
- for (String s : e.getAttributeKeySet()) {
- attributes.put(s, e.getAttribute(s));
- }
- while (graphIter.hasNext()) {
- MyGraph temp = graphIter.next();
- if (temp.getId().equals(origGraph)) {
- String newId = Main.getInstance().getUnusedID(new GraphManager(temp));
- if (e instanceof MyNode) {
- temp.addNode(newId);
- temp.getNode(newId).addAttributes(attributes);
- return temp.getId() + "+#" + newId;// the id of
- // Graph+newNode
- } else if (e instanceof MyEdge) {
- MyEdge ed = (MyEdge) e;
- String sourceId = ed.getSourceNode().getAttribute("originalElement").toString()
- .split("\\+#")[newNodeId.split("\\+#").length - 1];
- String targetId = ed.getTargetNode().getAttribute("originalElement").toString()
- .split("\\+#")[newNodeId.split("\\+#").length - 1];
- if (temp.getNode(sourceId) == null) {
- sourceId = newNodeId.split("\\+#")[newNodeId.split("\\+#").length - 1];
- } else {
- targetId = newNodeId.split("\\+#")[newNodeId.split("\\+#").length - 1];
- }
- temp.addEdge(newId, sourceId, targetId, ed.isDirected());
- temp.getEdge(newId).addAttributes(attributes);
- return temp.getId() + "+#" + newId;// the id of
- // graph+newEdge
- }
- }
- }
- Debug.out("WARNING: could not find the specified Graph " + origGraph, 2);
- return null;
- }
- }
|