GraphML With JUNG: Loading From GraphML

This is a follow up to my earlier post on saving to GraphML using the JUNG library. It would make more sense if you browsed through my earlier post before reading this one.

BufferedReader fileReader = new BufferedReader(
                            new FileReader(filename));

You first need to read from your file. This snippet creates a standard Java BufferedReader, which in turn is fed from a FileReader that reads from the file specified by the String filename.

The problem is, the GraphMLReader2 just a smart text parser, for it to do anything useful, you need to specify Transformers for the vertices, edges, hyperedges and the graph itself. We pump these transformers into the function reading the graph so it understands what exactly to do after it reads these different components in from the file.

 /* Create the Graph Transformer */
 Transformer<GraphMetadata, Graph<MyVertex, MyEdge>>
 graphTransformer = new Transformer<GraphMetadata,
                           Graph<MyVertex, MyEdge>>() {

   public Graph<MyVertex, MyEdge>
       transform(GraphMetadata metadata) {
         if (metadata.getEdgeDefault().equals(
         metadata.getEdgeDefault().DIRECTED)) {
             return new
             DirectedSparseGraph<MyVertex, MyEdge>();
         } else {
             return new
             UndirectedSparseGraph<MyVertex, MyEdge>();
         }
       }
 };

This transformer is used to parse the tag in my GraphML file and create a new Graph object by transforming that String. (it would really help if you had your GraphML file open at this point to understand what the transformers are doing). This tag specifies the beginning of your graph, and whether the graph is directed or undirected. The function metadata.getEdgeDefault() in this case returns “undirected” which is equal to the library-defined constant metadata.getEdgeDefault().DIRECTED. So this transformer checks whether the graph in the file is directed and returns the required Graph object.

/* Create the Vertex Transformer */
Transformer<NodeMetadata, MyVertex> vertexTransformer
= new Transformer<NodeMetadata, MyVertex>() {
    public MyVertex transform(NodeMetadata metadata) {
        MyVertex v =
            MyVertexFactory.getInstance().create();
        v.setX(Double.parseDouble(
                           metadata.getProperty("x")));
        v.setY(Double.parseDouble(
                           metadata.getProperty("y")));
        return v;
    }
};

The vertex transformer is slightly more involved. I’ll list out the various parts:

  • MyVertexFactory: This is my custom Factory that generates objects of my custom MyVertex class.
  • MyVertexFactory.getInstance(): This returns an object of the MyVertexFactory class that I can now use to access it’s methods.
  • v.setX(Double d)/v.setY(Double d): These are custom functions I’ve defined for my MyVertex class that set the private int x and private int y properties of the current vertex to the specified value.
  • metadata.getProperty("x")/metadata.getProperty("y"): This gets the value of the “x” and “y” properties that I’ve stored in my GraphML file (we used the addVertexData function in the previous post to save these out).

The vertex transformer parses the vertex data from the file and reads in its “x” and “y” coordinates, and then sets the x and y properties on the newly created MyVertex object.

/* Create the Edge Transformer */
 Transformer<EdgeMetadata, MyEdge> edgeTransformer =
 new Transformer<EdgeMetadata, MyEdge>() {
     public MyEdge transform(EdgeMetadata metadata) {
         MyEdge e = MyEdgeFactory.getInstance().create();
         return e;
     }
 };

Similar to the previous transformer, this edge transformer reads in the edge data from the file and creates a new edge. The MyEdgeFactory and getInstance() are analogous to those just discussed for the MyVertex class.

/* Create the Hyperedge Transformer */
Transformer<HyperEdgeMetadata, MyEdge> hyperEdgeTransformer
= new Transformer<HyperEdgeMetadata, MyEdge>() {
     public MyEdge transform(HyperEdgeMetadata metadata) {
         MyEdge e = MyEdgeFactory.getInstance().create();
         return e;
     }
};

This is pretty much the same code as my edge transformer! My graphs didn’t have hyper-edges, but the GraphMLReader2 definition requires that you specify a hyperedge transformer too. So let’s just get it done with. Finally, you create your graph reader object:

/* Create the graphMLReader2 */
GraphMLReader2<Graph<MyVertex, MyEdge>, MyVertex, MyEdge>
graphReader = new
GraphMLReader2<Graph<MyVertex, MyEdge>, MyVertex, MyEdge>
      (fileReader, graphTransformer, vertexTransformer,
       edgeTransformer, hyperEdgeTransformer);

It’s a pretty long statement to create one object, so make sure you’ve got all your angle brackets in place.

try {
    /* Get the new graph object from the GraphML file */
    Graph g = graphReader.readGraph();
} catch (GraphIOException ex) {}

Now you have your Graph object! Assuming you’ve worked with simple JUNG Graph objects enough to want to save them out, you should be able to take it from here. There is a small catch though; the graph right now will be displayed without any regard to the x and y properties associated with its vertex objects. So you’ll need to specify a StaticLayout with a custom transformer, that reads in the x and y properties of each vertex and places them accordingly on your canvas. You do that like this:

StaticLayout<MyVerex, MyEdge> layout =
 new StaticLayout(g, new Transformer<MyVertex, Point2D>() {
   public Point2D transform(MyVertex v) {
       Point2D p = new Point2D.Double(v.getX(), v.getY());
       return p;
   }               
 });

This transformer is required to convert a vertex object to a Point2D object that the layout needs to position its vertices. It creates a new Point2D object by using the custom getX() and getY() methods that return the x and y properties of the vertex.

9 responses to “GraphML With JUNG: Loading From GraphML

  1. It was useful!
    Thank you!

  2. Hi Emaad
    I have used your tutorial to both save out and now to load from the Graphml file. Saving out is working perfectly but for some reason when the file is loaded the graph doesnt get drawn? Any ideas?

    • You probably haven’t refreshed the visualization viewer for your graph, or created one. You’ll need to take your loaded Graph g and your StaticLayout layout and render it using a VisualizationViewer.

      • I already have a custom vv that uses layout. Do I need to create a new vv?? I have tried layout.repaint() but it doesnt solve the problem. I appreciate the help Emaad

  3. Of Course :)
    it’s the same code with a simple cast
    graphWriter.addVertexData(“x”, null, “0”,
    new Transformer() {
    public String transform(MyNode n) {
    return Double.toString(((AbstractLayout) layout).getX(n));
    }
    }
    );

    (Layout layout = new StaticLayout(graph);)

  4. Thanks a lot Emaad :)
    it’s working finally ..
    i think it is a matter of version because when i omit the graph and set the x by layout.getx(v) it does work

  5. Hi :)
    i tried the two post and they are working perfectly :)
    i just don’t know how to set the x and y ? i didn’t find the way to set them in the create() methode in my factories
    i would be really grateful if you help me out

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s