/** @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) */ public void edgeRemoved(GraphEdgeChangeEvent<V, E> e) { E jtEdge = e.getEdge(); if (!jtElementsBeingRemoved.remove(jtEdge)) { handleJGraphTRemovedEdge(jtEdge); } }
/** @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) */ public void edgeRemoved(GraphEdgeChangeEvent<V, E> e) { E edge = e.getEdge(); V source = graph.getEdgeSource(edge); V target = graph.getEdgeTarget(edge); if (successorMap.containsKey(source)) { successorMap.get(source).removeNeighbor(target); } if (predecessorMap.containsKey(target)) { predecessorMap.get(target).removeNeighbor(source); } }
/** @see GraphListener#edgeAdded(GraphEdgeChangeEvent) */ public void edgeAdded(GraphEdgeChangeEvent<V, E> e) { E edge = e.getEdge(); V source = graph.getEdgeSource(edge); V target = graph.getEdgeTarget(edge); // if a map does not already contain an entry, // then skip addNeighbor, since instantiating the map // will take care of processing the edge (which has already // been added) if (successorMap.containsKey(source)) { getSuccessors(source).addNeighbor(target); } else { getSuccessors(source); } if (predecessorMap.containsKey(target)) { getPredecessors(target).addNeighbor(source); } else { getPredecessors(target); } }
@Override public void edgeRemoved(final GraphEdgeChangeEvent<Spot, DefaultWeightedEdge> event) { // To signal to ModelChangeListeners edgesRemoved.add(event.getEdge()); // To maintain connected sets coherence final DefaultWeightedEdge e = event.getEdge(); final Integer id = edgeToID.get(e); if (null == id) { throw new RuntimeException("Edge is unkown to this model: " + e); } final Set<DefaultWeightedEdge> set = connectedEdgeSets.get(id); if (null == set) { throw new RuntimeException("Unknown set ID: " + id); } // Remove edge from set. final boolean removed = set.remove(e); if (!removed) { throw new RuntimeException("Could not removed edge " + e + " from set with ID: " + id); } // Forget about edge. edgeToID.remove(e); /* * Ok the trouble is that now we might be left with 2 sets if the * edge "was in the middle". Or 1 if it was in the end. Or 0 if it * was the last edge of the set. */ if (set.size() == 0) { // The set is empty, remove it from the map. connectedEdgeSets.remove(id); names.remove(id); visibility.remove(id); /* We need to remove also the vertices */ final Set<Spot> vertexSet = connectedVertexSets.get(id); // Forget the vertices were in a set for (final Spot spot : vertexSet) { vertexToID.remove(spot); } // Forget the vertex set connectedVertexSets.remove(id); /* * We do not mark it as a track to update, for it disappeared. * On the other hand, it might *have been* marked as a track to * update. Since it just joined oblivion, we remove it from the * list of tracks to update. */ tracksUpdated.remove(id); } else { // So there are some edges remaining in the set. // Look at the connected component of its source and target. // Source final HashSet<Spot> sourceVCS = new HashSet<Spot>(); final HashSet<DefaultWeightedEdge> sourceECS = new HashSet<DefaultWeightedEdge>(); { final Spot source = graph.getEdgeSource(e); // Get its connected set final BreadthFirstIterator<Spot, DefaultWeightedEdge> i = new BreadthFirstIterator<Spot, DefaultWeightedEdge>(graph, source); while (i.hasNext()) { final Spot sv = i.next(); sourceVCS.add(sv); sourceECS.addAll(graph.edgesOf(sv)); } } // Target final HashSet<Spot> targetVCS = new HashSet<Spot>(); final HashSet<DefaultWeightedEdge> targetECS = new HashSet<DefaultWeightedEdge>(); { final Spot target = graph.getEdgeTarget(e); // Get its connected set final BreadthFirstIterator<Spot, DefaultWeightedEdge> i = new BreadthFirstIterator<Spot, DefaultWeightedEdge>(graph, target); while (i.hasNext()) { final Spot sv = i.next(); targetVCS.add(sv); targetECS.addAll(graph.edgesOf(sv)); } } /* * If the two connected components are the same, it means that * the edge was an "internal" edge: Because there is another * path that connect its source and target, removing it did NOT * split the track in 2. We therefore need not to re-attribute * it. */ if (targetVCS.equals(sourceVCS)) { tracksUpdated.add(id); connectedEdgeSets.get(id).remove(e); return; } /* * Re-attribute the found connected sets to the model. The * largest one (in vertices) gets the original id, the other * gets a new id. As for names: the largest one keeps its name, * the small one gets a new name. */ if (targetVCS.size() > sourceVCS.size()) { connectedEdgeSets.put(id, targetECS); connectedVertexSets.put(id, targetVCS); // they already // have the // right id in // #vertexToId tracksUpdated.add(id); // old track has changed if (sourceECS.size() > 0) { // the smaller part is still a track final int newid = IDcounter++; connectedEdgeSets.put(newid, sourceECS); // otherwise // forget it for (final DefaultWeightedEdge te : sourceECS) { edgeToID.put(te, newid); } connectedVertexSets.put(newid, sourceVCS); for (final Spot tv : sourceVCS) { vertexToID.put(tv, newid); } final Boolean targetVisibility = visibility.get(id); visibility.put(newid, targetVisibility); names.put(newid, nameGenerator.next()); // Transaction: both children tracks are marked for // update. tracksUpdated.add(newid); } else { /* * Nothing remains from the smallest part. The remaining * solitary vertex has no right to be called a track. */ final Spot solitary = sourceVCS.iterator().next(); vertexToID.remove(solitary); } } else { if (sourceECS.size() > 0) { // There are still some pieces left. It is worth noting // it. connectedEdgeSets.put(id, sourceECS); connectedVertexSets.put(id, sourceVCS); tracksUpdated.add(id); if (targetECS.size() > 0) { // the small part is still a track final int newid = IDcounter++; connectedEdgeSets.put(newid, targetECS); for (final DefaultWeightedEdge te : targetECS) { edgeToID.put(te, newid); } connectedVertexSets.put(newid, targetVCS); for (final Spot v : targetVCS) { vertexToID.put(v, newid); } final Boolean targetVisibility = visibility.get(id); visibility.put(newid, targetVisibility); names.put(newid, nameGenerator.next()); // Transaction: both children tracks are marked for // update. tracksUpdated.add(newid); } else { /* * Nothing remains from the smallest part. The * remaining solitary vertex has no right to be * called a track. */ final Spot solitary = targetVCS.iterator().next(); vertexToID.remove(solitary); } } else { // Nothing remains (maybe a solitary vertex) -> forget // about it all. connectedEdgeSets.remove(id); connectedVertexSets.remove(id); names.remove(id); visibility.remove(id); tracksUpdated.remove(id); } } } }
@Override public void edgeAdded(final GraphEdgeChangeEvent<Spot, DefaultWeightedEdge> event) { // To signal to ModelChangeListener edgesAdded.add(event.getEdge()); // To maintain connected sets coherence: /* * This is the tricky part: when we add an edge to our set model, * first we need to find to what existing set it has been added. * Then a new edge sometime come with 1 or 2 vertices that might be * new or belonging to an existing set. */ final DefaultWeightedEdge e = event.getEdge(); // Was it added to known tracks? final Spot sv = graph.getEdgeSource(e); final Integer sid = vertexToID.get(sv); final Spot tv = graph.getEdgeTarget(e); final Integer tid = vertexToID.get(tv); if (null != tid && null != sid) { // Case 1: it was added between two existing sets. We connect // them, therefore // and take the id of the largest one. The other id, disappear, // unless they // belonged to the same set. // Did they come from the same set? if (tid.equals(sid)) { // They come from the same set (equals ID). Not much to do. final Set<DefaultWeightedEdge> ses = connectedEdgeSets.get(sid); ses.add(e); edgeToID.put(e, sid); } else { // They come from different sets. // Edges: final Set<DefaultWeightedEdge> ses = connectedEdgeSets.get(sid); final Set<DefaultWeightedEdge> tes = connectedEdgeSets.get(tid); final HashSet<DefaultWeightedEdge> nes = new HashSet<DefaultWeightedEdge>(ses.size() + tes.size() + 1); nes.addAll(ses); nes.addAll(tes); nes.add(e); // Vertices: final Set<Spot> svs = connectedVertexSets.get(sid); final Set<Spot> tvs = connectedVertexSets.get(tid); final HashSet<Spot> nvs = new HashSet<Spot>(ses.size() + tes.size()); nvs.addAll(svs); nvs.addAll(tvs); Integer nid, rid; if (nvs.size() > tvs.size()) { nid = sid; rid = tid; for (final Spot v : tvs) { // Vertices of target set change id vertexToID.put(v, nid); } for (final DefaultWeightedEdge te : tes) { edgeToID.put(te, nid); } } else { nid = tid; rid = sid; for (final Spot v : svs) { // Vertices of source set change id vertexToID.put(v, nid); } for (final DefaultWeightedEdge se : ses) { edgeToID.put(se, nid); } } edgeToID.put(e, nid); connectedVertexSets.put(nid, nvs); connectedVertexSets.remove(rid); connectedEdgeSets.put(nid, nes); connectedEdgeSets.remove(rid); // Transaction: we signal that the large id is to be // updated, and forget about the small one tracksUpdated.add(nid); tracksUpdated.remove(rid); // Visibility: if at least one is visible, the new set is // made visible. final Boolean targetVisibility = visibility.get(sid) || visibility.get(tid); visibility.put(nid, targetVisibility); visibility.remove(rid); // Name: the new set gets the name of the largest one. names.remove(rid); // 'nid' already has the right name. } } else if (null == sid && null == tid) { // Case 4: the edge was added between two lonely vertices. // Create a new set id from this final HashSet<Spot> nvs = new HashSet<Spot>(2); nvs.add(graph.getEdgeSource(e)); nvs.add(graph.getEdgeTarget(e)); final HashSet<DefaultWeightedEdge> nes = new HashSet<DefaultWeightedEdge>(1); nes.add(e); final int nid = IDcounter++; connectedEdgeSets.put(nid, nes); connectedVertexSets.put(nid, nvs); vertexToID.put(sv, nid); vertexToID.put(tv, nid); edgeToID.put(e, nid); // Give it visibility visibility.put(nid, Boolean.TRUE); // and a default name. names.put(nid, nameGenerator.next()); // Transaction: we mark the new track as updated tracksUpdated.add(nid); } else if (null == sid) { // Case 2: the edge was added to the target set. No source set, // but there is a source vertex. // Add it, with the source vertex, to the target id. connectedEdgeSets.get(tid).add(e); edgeToID.put(e, tid); connectedVertexSets.get(tid).add(sv); vertexToID.put(sv, tid); // We do not change the visibility, nor the name. // Transaction: we mark the mother track as updated tracksUpdated.add(tid); } else if (null == tid) { // Case 3: the edge was added to the source set. No target set, // but there is a target vertex. // Add it, with the target vertex, to the source id. connectedEdgeSets.get(sid).add(e); edgeToID.put(e, sid); connectedVertexSets.get(sid).add(tv); vertexToID.put(tv, sid); // We do not change the visibility, nor the name. // Transaction: we mark the mother track as updated tracksUpdated.add(sid); } }