Search code examples
javagraphbigdatajunggraphml

loading custom nodes and edges with graphml and jung


I'm confronted with problems while I#m trying to read and write graphs from and to a text file with JUNG. The situation is as follows: Given is a file that contains coordinates of a multigraph and its weight.

An example is:

6346    6728    5911    156 5
6346    6728    6599    156 10
6346    6728    8555    156 5

I have written a converter with JUNG that reads a file that contains millions of such rows and constructs a

DirectedSparseMultigraph<Node, Edge>

Nodes and Edges are custom made classes listed below

class Node {
    int id; // good coding practice would have this as private

    public Node(int id) {
        this.id = id;
    }
    public String toString() { // Always a good idea for debuging
        return "V"+id;
   // JUNG2 makes good use of these.
    }        
}

class Edge { 
    Context context;  
    Time time;
    Value value;
    int id;
    public Edge(int id, Context context, Time time, Value value) {
        this.id = id; // This is defined in the outer class.
        this.context = context;
        this.time = time;
        this.value = value;
    } 
    public String toString() { // Always good for debugging
        return "E"+id;
    }
}

Constructing a graph in memory from this data works fine. We come closer to the problem. It is important to note that saving the constructed graph to disk works fine by using a method save() of the DirectedSparseMultigraph object. In a next step, the constructed DirectedSparseMultigraph is loaded from disk by the following lines of code

    GraphMLReader<DirectedSparseMultigraph<Node, Edge>, Node, Edge> gmlr = null;

    try
    {
        gmlr = new GraphMLReader<DirectedSparseMultigraph<Node, Edge>, Node, Edge>();
    } catch (ParserConfigurationException e1)
    {
        e1.printStackTrace();
    } catch (SAXException e1)
    {
        e1.printStackTrace();
    }

    DirectedSparseMultigraph<Node, Edge> g_new = null;
    try
    {
        gmlr.load("bla.sh", g_new);
    } catch (IOException e)
    {
        e.printStackTrace();
    }

And that is where the problem starts. The error message is as follows:

Exception in thread "main" java.lang.IllegalArgumentException: If no edge factory is supplied, edge id may not be null: {source=V6818, target=V2472}
at edu.uci.ics.jung.io.GraphMLReader.createEdge(GraphMLReader.java:693)
at edu.uci.ics.jung.io.GraphMLReader.startElement(GraphMLReader.java:299)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:182)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2786)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:333)
at edu.uci.ics.jung.io.GraphMLReader.parse(GraphMLReader.java:241)
at edu.uci.ics.jung.io.GraphMLReader.load(GraphMLReader.java:192)
at edu.uci.ics.jung.io.GraphMLReader.load(GraphMLReader.java:201)
at main.Graph.main(Graph.java:99)

If you have any Ideas or hints how this problem can be solved, I really look forward to your message. greetings J Bug


Solution

  • There are two ways for GraphMLReader to be able to parse your file:

    (1) You supply node and edge factories; in this case your node and edge types can be anything you want. (constructor with factories)

    (2) You don't supply node and edge factories; in this case your node and edge types must be Strings. (constructor without factories)

    Your code doesn't supply node and edge factories, and your Edge type is not assignment-compatible with String, so it blows up. Admittedly this is not super-obvious from the error message, but it's fairly clear in the code.

    In this case you can't really provide Node and Edge factories (without redesigning them), because you don't have a no-arg constructor. So you'd either need to redesign those classes, or use a two-stage process, i.e.: parse the graph using simple String keys for the nodes and edges + populate the metadata, and then build a new graph based on the data structures that GraphMLReader provides.