javajung2

How to draw same edge name by JUNG2


I am doing a draw network topology project by JUNG2, now found JUNG2 couldn't draw same edge(name) on different vertex. And report follow:

Exception in thread "main" java.lang.IllegalArgumentException: edge GigabitEthernet0/3<--->GigabitEthernet0/0/0/0 already exists in this graph with endpoints <HKBR1, HKBR3> and cannot be added with endpoints <HKBR2, HKBR4>
at edu.uci.ics.jung.graph.AbstractGraph.getValidatedEndpoints(AbstractGraph.java:93)
at edu.uci.ics.jung.graph.SparseMultigraph.addEdge(SparseMultigraph.java:123)
at edu.uci.ics.jung.graph.AbstractGraph.addEdge(AbstractGraph.java:60)
at pkg.DrawnTopology.DrawnTopology(DrawnTopology.java:45)
at pkg.ReadLine.main(ReadLine.java:85)

I had stored all edge and vertex to a two-dimensional array. Two-dimensional array data learn from different files, so data is dynamic. Due to network topology maybe have same edge name, so how to resolve that?


Solution

  • The question clearly lacks details, but from the description and error message, one can probably guess what's wrong here:

    Your graph may be defined to be a Graph<V, String>.

    It may be a subclass of Graph, and the vertex type does not matter. The crucial point is that the edge type is String)

    And you are attempting to add edges to the graph like this:

    g.addEdge("edge0", v0, v1);
    g.addEdge("edge0", v2, v3);
    

    This will cause an error, because the edge "edge0" exists twice. (And this makes sense. Otherwise: What should happen when you ask the graph for the endpoints of "edge0"? Should it return v0,v1 or v2,v3? It's simply ambiguous).

    (Note that this is not only the case when the edge type is String. It will happen for any edge type, as long as two edges are equal to each other).

    One simple solution here is to introduce a dedicated Edge class that wraps the String:

    class Edge
    {
        private final String name;
    
        Edge(String name)
        {
            this.name = name;
        }
    
        @Override
        public String toString()
        {
            return name;
        }
    }
    

    This class does not have its equals method overridden. So two objects of this type will not be equal, even when the Strings are equal:

    Edge e0 = new Edge("edge0");
    Edge e1 = new Edge("edge0");
    System.out.println(e0.equals(e1)); // prints "false"
    

    The edge labels can then simply be the toString representations of these edges, which return the original string.

    An example:

    import javax.swing.JFrame;
    
    import org.apache.commons.collections15.Transformer;
    
    import edu.uci.ics.jung.algorithms.layout.FRLayout;
    import edu.uci.ics.jung.graph.DirectedSparseGraph;
    import edu.uci.ics.jung.graph.Graph;
    import edu.uci.ics.jung.visualization.VisualizationViewer;
    
    class Edge
    {
        private final String name;
    
        Edge(String name)
        {
            this.name = name;
        }
    
        @Override
        public String toString()
        {
            return name;
        }
    }
    
    public class JungDuplicateEdgesTest
    {
        public static void main(String[] args)
        {
            JFrame jf = new JFrame();
            final Graph<String, Edge> g = getGraph();
            VisualizationViewer<String, Edge> vv = 
                new VisualizationViewer<String, Edge>(
                    new FRLayout<String, Edge>(g));
    
            class EdgeLabelTransformer implements Transformer<Edge, String>
            {
                @Override
                public String transform(Edge edge)
                {
                    return edge.toString();
                }
            }
            vv.getRenderContext().setEdgeLabelTransformer(
                new EdgeLabelTransformer());
    
            jf.getContentPane().add(vv);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.pack();
            jf.setVisible(true);
        }
    
        public static Graph<String, Edge> getGraph()
        {
            Graph<String, Edge> g = new DirectedSparseGraph<String, Edge>();
            g.addVertex("v0");
            g.addVertex("v1");
            g.addEdge(new Edge("e0"), "v0", "v1");
            g.addEdge(new Edge("e0"), "v1", "v0");
            return g;
        }
    }
    

    A side note: It could, for some applications, make sense to store the vertices of the edge in the Edge class as well. Then you could implement the equals and hashCode method in a way that allows you treating two edges as equal when they have the same vertices.