/** * Adds the specified JGraphT edge to be reflected by this graph model. To be called only for * edges that already exist in the JGraphT graph. * * @param jtEdge a JGraphT edge to be reflected by this graph model. */ void handleJGraphTAddedEdge(E jtEdge) { DefaultEdge edgeCell = cellFactory.createEdgeCell(jtEdge); edgeToCell.put(jtEdge, edgeCell); cellToEdge.put(edgeCell, jtEdge); ConnectionSet cs = new ConnectionSet(); cs.connect( edgeCell, getVertexPort(jtGraph.getEdgeSource(jtEdge)), getVertexPort(jtGraph.getEdgeTarget(jtEdge))); internalInsertCell(edgeCell, createEdgeAttributeMap(edgeCell), cs); }
/** * Adds to the underlying JGraphT graph a vertex corresponding to the specified JGraph vertex. In * JGraph, two vertices with the same user object are in principle allowed; in JGraphT, this would * lead to duplicate vertices, which is not allowed. So if such vertex already exists, the * specified vertex is REMOVED from the JGraph graph and a a warning is printed. * * <p>This method is to be called only for vertices that have already been added to the JGraph * graph. * * @param jVertex the JGraph vertex that has been added. */ @SuppressWarnings("unchecked") void handleJGraphInsertedVertex(GraphCell jVertex) { V jtVertex; if (jVertex instanceof DefaultGraphCell) { // FIXME hb 28-nov-05: waiting for jgraph to go generic jtVertex = (V) ((DefaultGraphCell) jVertex).getUserObject(); } else { // FIXME: Why toString? Explain if for a good reason otherwise fix. jtVertex = (V) jVertex.toString(); } if (vertexToCell.containsKey(jtVertex)) { // We have to remove the new vertex, because it would lead to // duplicate vertices. We can't use ShieldedGraph.removeVertex for // that, because it would remove the wrong (existing) vertex. System.err.println( "Warning: detected two JGraph vertices with " + "the same JGraphT vertex as user object. It is an " + "indication for a faulty situation that should NOT happen." + "Removing vertex: " + jVertex); internalRemoveCell(jVertex); } else { jtGraph.addVertex(jtVertex); cellToVertex.put(jVertex, jtVertex); vertexToCell.put(jtVertex, jVertex); } }
/** * Adds to the underlying JGraphT graph an edge that corresponds to the specified JGraph edge. If * the specified JGraph edge is a dangling edge, it is NOT added to the underlying JGraphT graph. * * <p>This method is to be called only for edges that have already been added to the JGraph graph. * * @param jEdge the JGraph edge that has been added. */ void handleJGraphInsertedEdge(org.jgraph.graph.Edge jEdge) { if (isDangling(jEdge)) { // JGraphT forbid dangling edges so we cannot add the edge yet. If // later the edge becomes connected, we will add it. } else { // FIXME hb 28-nov-05: waiting for jgraph to go generic Object jSource = getSourceVertex(this, jEdge); Object jTarget = getTargetVertex(this, jEdge); V jtSource = cellToVertex.get(jSource); V jtTarget = cellToVertex.get(jTarget); E jtEdge = jtGraph.addEdge(jtSource, jtTarget); if (jtEdge != null) { cellToEdge.put(jEdge, jtEdge); edgeToCell.put(jtEdge, jEdge); } else { // Adding failed because user is using a JGraphT graph the // forbids parallel edges. // For consistency, we remove the edge from the JGraph too. internalRemoveCell(jEdge); System.err.println( "Warning: an edge was deleted because the underlying " + "JGraphT graph refused to create it. " + "This situation can happen when a constraint of the " + "underlying graph is violated, e.g., an attempt to add " + "a parallel edge or a self-loop to a graph that forbids " + "them. To avoid this message, make sure to use a " + "suitable underlying JGraphT graph."); } } }
/** * Removes the edge corresponding to the specified JGraph edge from the JGraphT graph. If the * specified edge is not contained in {@link #cellToEdge}, it is silently ignored. * * <p>This method is to be called only for edges that have already been removed from the JGraph * graph. * * @param jEdge the JGraph edge that has been removed. */ void handleJGraphRemovedEdge(org.jgraph.graph.Edge jEdge) { if (cellToEdge.containsKey(jEdge)) { E jtEdge = cellToEdge.get(jEdge); jtGraph.removeEdge(jtEdge); cellToEdge.remove(jEdge); edgeToCell.remove(jtEdge); } }
/** * Adds/removes an edge to/from the underlying JGraphT graph according to the change in the * specified JGraph edge. If both vertices are connected, we ensure to have a corresponding * JGraphT edge. Otherwise, we ensure NOT to have a corresponding JGraphT edge. * * <p>This method is to be called only for edges that have already been changed in the JGraph * graph. * * @param jEdge the JGraph edge that has changed. */ void handleJGraphChangedEdge(org.jgraph.graph.Edge jEdge) { if (isDangling(jEdge)) { if (cellToEdge.containsKey(jEdge)) { // a non-dangling edge became dangling -- remove the JGraphT // edge by faking as if the edge is removed from the JGraph. // TODO: Consider keeping the JGraphT edges outside the graph // to avoid loosing user data, such as weights. handleJGraphRemovedEdge(jEdge); } else { // a dangling edge is still dangling -- just ignore. } } else { // edge is not dangling if (cellToEdge.containsKey(jEdge)) { // edge already has a corresponding JGraphT edge. // check if any change to its endpoints. E jtEdge = cellToEdge.get(jEdge); Object jSource = getSourceVertex(this, jEdge); Object jTarget = getTargetVertex(this, jEdge); Object jtSource = cellToVertex.get(jSource); Object jtTarget = cellToVertex.get(jTarget); if ((jtGraph.getEdgeSource(jtEdge) == jtSource) && (jtGraph.getEdgeTarget(jtEdge) == jtTarget)) { // no change in edge's endpoints -- nothing to do. } else { // edge's end-points have changed -- need to refresh the // JGraphT edge. Refresh by faking as if the edge has been // removed from JGraph and then added again. // ALSO HERE: consider an alternative that maintains user // data handleJGraphRemovedEdge(jEdge); handleJGraphInsertedEdge(jEdge); } } else { // a new edge handleJGraphInsertedEdge(jEdge); } } }
/** * Removes the vertex corresponding to the specified JGraph vertex from the JGraphT graph. If the * specified vertex is not contained in {@link #cellToVertex}, it is silently ignored. * * <p>If any edges are incident with this vertex, we first remove them from the both graphs, * because otherwise the JGraph graph would leave them intact and the JGraphT graph would throw * them out. TODO: Revise this behavior now that we gracefully tolerate dangling edges. It might * be possible to remove just the JGraphT edges. The JGraph edges will be left dangling, as a * result. * * <p>This method is to be called only for vertices that have already been removed from the JGraph * graph. * * @param jVertex the JGraph vertex that has been removed. */ void handleJGraphRemovedVertex(GraphCell jVertex) { if (cellToVertex.containsKey(jVertex)) { V jtVertex = cellToVertex.get(jVertex); Set<E> jtIncidentEdges = jtGraph.edgesOf(jtVertex); if (!jtIncidentEdges.isEmpty()) { // We can't just call removeAllEdges with this list: that // would throw a ConcurrentModificationException. So we create // a shallow copy. // This also triggers removal of the corresponding JGraph // edges. jtGraph.removeAllEdges(new ArrayList<E>(jtIncidentEdges)); } jtGraph.removeVertex(jtVertex); cellToVertex.remove(jVertex); vertexToCell.remove(jtVertex); } }