Menu

GraphMLReader and GraphMLWriter examples

Jay Mann
2008-08-04
2013-05-29
  • Jay Mann

    Jay Mann - 2008-08-04

    Are there any examples of using the new GraphMLReader and GraphMLWriter?
    I need to write my graph to a file, but i also need to store it's other attributes too.

    Not sure where to start.

    Thanks in advance,

    -J

     
    • Jay Mann

      Jay Mann - 2008-08-04

      Nevermind, i think i got it figured out.

       
      • Jay Mann

        Jay Mann - 2008-08-04

        Actually, if anyone has an example of using an GraphMLReader to get the "data" back into the vertices, that would help.

        Thanks in advance,

        -J

         
        • Joshua O'Madadhain

          Jay:

          Take a look at the GraphML unit tests.

          Joshua

           
    • Darrell Berry

      Darrell Berry - 2008-08-05

      hi -- ok its my day for not being able to find things, but where ARE the unit tests for this? cant find them in any of the source distro...?

      thanks

       
    • Jay Mann

      Jay Mann - 2008-08-05

      The test are located here:
      C:\src\jung2\jung-io\src\test\java\edu\uci\ics\jung\io

       
    • Nathan Mittler

      Nathan Mittler - 2008-08-05

      The unit tests for the jung-io module are under src/test/java (the standard location for Maven). 

      FYI - As it looks now, the unit tests for the newly proposed GraphML parser haven't been checked in yet.

       
    • Jay Mann

      Jay Mann - 2008-08-05

      I think There is a problem with the sax "character" override inside GraphMLReader, for some reason some of my strings come in truncated and then the rest of the string comes in on the next character call (before the endElement is called). 

      After some research i found this is by design:

      ----FROM http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JAXPSAX3.html----------------------
      Character Events

      To finish handling the content events, you need to handle the characters that the parser delivers to your application.

      Parsers are not required to return any particular number of characters at one time. A parser can return anything from a single character at a time up to several thousand and still be a standard-conforming implementation. So if your application needs to process the characters it sees, it is wise to accumulate the characters in a buffer and operate on them only when you are sure that all of them have been found.

      ------------------------------------------------------------------------------------

      So i think the character call just needs to keep appending the string, and the actual string processing need to happen at the endElement call.

      Does this sound right, or am i doing something wrong?

      -J

       
    • Darrell Berry

      Darrell Berry - 2008-08-05

      found now

      thanks

      d

       
    • Jay Mann

      Jay Mann - 2008-08-05

      Here is a patch for GraphMLReader.java if you are interested in using it.  I just moved some of the code around so that the "Character" override appends the text until it gets to the end element.  This will correct the issue where the parser only send part of the data in the first character call and then sends the rest of the characters in the subsequent calls.

      -J

      Index: GraphMLReader.java

      RCS file: /cvsroot/jung/jung2/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLReader.java,v
      retrieving revision 1.9
      diff -u -r1.9 GraphMLReader.java
      --- GraphMLReader.java    20 Jul 2008 22:32:27 -0000    1.9
      +++ GraphMLReader.java    5 Aug 2008 13:40:08 -0000
      @@ -96,6 +96,7 @@

           protected List<G> graphs;
          
      +    protected StringBuffer textBuffer;
           /**
            * Creates a <code>GraphMLReader</code> instance with the specified
            * vertex and edge factories.
      @@ -233,6 +234,9 @@
           @Override
           public void startElement(String uri, String name, String qName, Attributes atts) throws SAXNotSupportedException
           {
      +        //If we got a new element, we prob want to discard the textBuffer
      +        textBuffer = null;
      +       
               String tag = qName.toLowerCase();
               TagState state = tag_state.get(tag);
               if (state == null)
      @@ -374,103 +378,116 @@

          
           @Override
      -    public void characters(char[] ch, int start, int length) throws SAXNotSupportedException
      +    public void characters(char[] ch, int start, int length) throws SAXException
           {
      -        String text = new String(ch, start, length);
      -
      -        switch (this.current_states.getFirst())
      -        {
      -            case DESC:
      -                switch (this.current_states.get(1)) // go back one
      -                {
      -                    case GRAPH:
      -                        graph_desc.put(current_graph, text);
      -                        break;
      -                    case VERTEX:
      -                    case ENDPOINT:
      -                        vertex_desc.put(current_vertex, text);
      -                        break;
      -                    case EDGE:
      -                    case HYPEREDGE:
      -                        edge_desc.put(current_edge, text);
      -                        break;
      -                    case DATA:
      -                        switch (key_type)
      -                        {
      -                            case GRAPH:
      -                                graph_metadata.get(current_key).description = text;
      -                                break;
      -                            case VERTEX:
      -                                vertex_metadata.get(current_key).description = text;
      -                                break;
      -                            case EDGE:
      -                                edge_metadata.get(current_key).description = text;
      -                                break;
      -                            case ALL:
      -                                graph_metadata.get(current_key).description = text;
      -                                vertex_metadata.get(current_key).description = text;
      -                                edge_metadata.get(current_key).description = text;
      -                                break;
      -                            default:
      -                                throw new SAXNotSupportedException("Invalid key type" +
      -                                        " specified for default: " + key_type);
      -                        }
      -                       
      -                        break;
      -                    default:
      -                        break;
      -                }
      -                break;
      -            case DATA:
      -                switch (this.current_states.get(1))
      -                {
      -                    case GRAPH:
      -                        addDatum(graph_metadata, current_graph, text);
      -                        break;
      -                    case VERTEX:
      -                    case ENDPOINT:
      -                        addDatum(vertex_metadata, current_vertex, text);
      -                        break;
      -                    case EDGE:
      -                    case HYPEREDGE:
      -                        addDatum(edge_metadata, current_edge, text);
      -                        break;
      -                    default:
      -                        break;
      -                }
      -                break;
      -            case DEFAULT_KEY:
      -                if (this.current_states.get(1) != TagState.KEY)
      -                    throw new SAXNotSupportedException("'default' only defined in context of 'key' tag: " +
      -                            "stack: " + current_states.toString());
      -               
      -                switch (key_type)
      -                {
      -                    case GRAPH:
      -                        graph_metadata.get(current_key).default_value = text;
      -                        break;
      -                    case VERTEX:
      -                        vertex_metadata.get(current_key).default_value = text;
      -                        break;
      -                    case EDGE:
      -                        edge_metadata.get(current_key).default_value = text;
      -                        break;
      -                    case ALL:
      -                        graph_metadata.get(current_key).default_value = text;
      -                        vertex_metadata.get(current_key).default_value = text;
      -                        edge_metadata.get(current_key).default_value = text;
      -                        break;
      -                    default:
      -                        throw new SAXNotSupportedException("Invalid key type" +
      -                                " specified for default: " + key_type);
      -                }
      -               
      -                break;
      -            default:
      -                break;
      -        }
      +        String s = new String(ch, start, length);  
      +        if (textBuffer == null)
      +        {
      +            textBuffer = new StringBuffer(s);  
      +        }
      +        else
      +        {    
      +            textBuffer.append(s);
      +        }
      +    }
      +   
      +    private void processStringData(String textData) throws SAXNotSupportedException
      +    {
      +       
      +         switch (this.current_states.getFirst())
      +         {
      +             case DESC:
      +                 switch (this.current_states.get(1)) // go back one
      +                 {
      +                     case GRAPH:
      +                         graph_desc.put(current_graph, textData);
      +                         break;
      +                     case VERTEX:
      +                     case ENDPOINT:
      +                         vertex_desc.put(current_vertex, textData);
      +                         break;
      +                     case EDGE:
      +                     case HYPEREDGE:
      +                         edge_desc.put(current_edge, textData);
      +                         break;
      +                     case DATA:
      +                         switch (key_type)
      +                         {
      +                             case GRAPH:
      +                                 graph_metadata.get(current_key).description = textData;
      +                                 break;
      +                             case VERTEX:
      +                                 vertex_metadata.get(current_key).description = textData;
      +                                 break;
      +                             case EDGE:
      +                                 edge_metadata.get(current_key).description = textData;
      +                                 break;
      +                             case ALL:
      +                                 graph_metadata.get(current_key).description = textData;
      +                                 vertex_metadata.get(current_key).description = textData;
      +                                 edge_metadata.get(current_key).description = textData;
      +                                 break;
      +                             default:
      +                                 throw new SAXNotSupportedException("Invalid key type" +
      +                                         " specified for default: " + key_type);
      +                         }
      +                        
      +                         break;
      +                     default:
      +                         break;
      +                 }
      +                 break;
      +             case DATA:
      +                 switch (this.current_states.get(1))
      +                 {
      +                     case GRAPH:
      +                         addDatum(graph_metadata, current_graph, textData);
      +                         break;
      +                     case VERTEX:
      +                     case ENDPOINT:
      +                         addDatum(vertex_metadata, current_vertex, textData);
      +                         break;
      +                     case EDGE:
      +                     case HYPEREDGE:
      +                         addDatum(edge_metadata, current_edge, textData);
      +                         break;
      +                     default:
      +                         break;
      +                 }
      +                 break;
      +             case DEFAULT_KEY:
      +                 if (this.current_states.get(1) != TagState.KEY)
      +                     throw new SAXNotSupportedException("'default' only defined in context of 'key' tag: " +
      +                             "stack: " + current_states.toString());
      +                
      +                 switch (key_type)
      +                 {
      +                     case GRAPH:
      +                         graph_metadata.get(current_key).default_value = textData;
      +                         break;
      +                     case VERTEX:
      +                         vertex_metadata.get(current_key).default_value = textData;
      +                         break;
      +                     case EDGE:
      +                         edge_metadata.get(current_key).default_value = textData;
      +                         break;
      +                     case ALL:
      +                         graph_metadata.get(current_key).default_value = textData;
      +                         vertex_metadata.get(current_key).default_value = textData;
      +                         edge_metadata.get(current_key).default_value = textData;
      +                         break;
      +                     default:
      +                         throw new SAXNotSupportedException("Invalid key type" +
      +                                 " specified for default: " + key_type);
      +                 }
      +                
      +                 break;
      +             default:
      +                 break;
      +         }
           }
      -
      +   
      +   
           protected <T>void addDatum(Map<String, GraphMLMetadata<T>> metadata,
                   T current_elt, String text) throws SAXNotSupportedException
           {
      @@ -488,6 +505,11 @@
           @Override
           public void endElement(String uri, String name, String qName) throws SAXNotSupportedException
           {
      +        if(textBuffer != null)
      +        {
      +            processStringData(textBuffer.toString());
      +            textBuffer = null;
      +        }
               String tag = qName.toLowerCase();
               TagState state = tag_state.get(tag);
               if (state == null)

       
    • Nathan Mittler

      Nathan Mittler - 2008-08-09

      Jay,
      I'm not sure exactly what input you were using that caused the issue with the SAX characters, but would you mind trying the same test with the proposed GraphMLReader2 in CVS: (http://jung.cvs.sourceforge.net/jung/jung2/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLReader2.java?view=markup)

      It would be a shame to get this bug fixed in one of the reader classes and not the other :)

      Thanks,
      Nate

       
    • Jay Mann

      Jay Mann - 2008-08-11

      I actually switched over to the GraphMLReader2 because it was easier to get the data into my classes.  The GraphMLReader2 works perfectly.  The issue i was having with the normal GraphMLReader was due to the sax "Characters" override method only delivering small chunks of data at a time, i don't think your using that override in the GraphMLReader2.

      Here is more info on the characters method if interested: http://java.sun.com/j2se/1.5.0/docs/api/org/xml/sax/ContentHandler.html#characters\(char[],%20int,%20int)

      Thanks for the help.  GraphMLReader2 works great!

      Cheers,

      -J

       
    • Nathan Mittler

      Nathan Mittler - 2008-08-11

      Great - glad to hear it!

      Cheers,
      Nate

       
    • Jay Mann

      Jay Mann - 2008-08-25

      Nate,

      I was wrong, your GraphML reader exhibits the same behaivor as the normal Jung version.  I just tried processing a larger XML document today and had the same problem.  The string was only a few hundered characters, but i was only receiving the last 8 or so. 

      The problem occurs at line 72 in DataElementParser.java

      if (event.isCharacters()) {
                          Characters characters = (Characters) event;
                          data.setValue(characters.getData());
                      }

      The characters.getData() needs to be appended to a StringBuffer until the endtag is reached.

      -J

       
    • Nathan Mittler

      Nathan Mittler - 2008-09-07

      Hi Jay,
      Good catch!  Do you have a particular input file that will cause the problem?  We should probably add a unit test to verify that the problem is resolved going forward.

      Regards,
      Nate

       
    • Wim Pas

      Wim Pas - 2008-11-13

      Hello,

      I am encountering some errors with the GraphMLReader (and maybe the writer too)... I am not really an experienced programmer, so maybe I am making some basic mistakes or maybe I am encountering a similar problem as described above, but I don’t understand it completely.
      What I want to do is to save a graph in one program and open/ use it in another one. My code:

      Program one:

      GraphMLWriter gw = new GraphMLWriter();
      FileWriter outputFileReader  = new FileWriter("TEST.xml");
      gw.save(g, outputFileReader);
         
      Program two:

      Graph g = new SparseGraph<City, String>();
      GraphMLReader gr = new GraphMLReader();
      String directory = "C…";
      FileReader inputFileReader  = new FileReader(directory+ "TEST.xml");
      gr.load(inputFileReader, g);

      By doing this I get the following error:

      java.lang.IllegalArgumentException: If no edge factory is supplied, edge id may not be null: {source=WUH, directed=false, target=KHN}
          at edu.uci.ics.jung.io.GraphMLReader.createEdge(GraphMLReader.java:677)
          at edu.uci.ics.jung.io.GraphMLReader.startElement(GraphMLReader.java:282)
          at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(Unknown Source)
          at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)
          at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source)
          at …

      Am I doing something wrong or has this something to do with the problem described? And is there an "easy" solution for this?

      Thank you in advance,

      Wim

       

Log in to post a comment.