View Javadoc

1   /*
2   
3       dsh-graph-io  Directed graph readers and writers.
4       Copyright (c) 2008-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.graph.io.graphml;
25  
26  import java.io.File;
27  import java.io.FileWriter;
28  import java.io.IOException;
29  import java.io.OutputStream;
30  
31  import java.util.HashMap;
32  import java.util.Map;
33  
34  import javax.xml.stream.XMLOutputFactory;
35  import javax.xml.stream.XMLStreamException;
36  import javax.xml.stream.XMLStreamWriter;
37  
38  import org.dishevelled.graph.Edge;
39  import org.dishevelled.graph.Node;
40  import org.dishevelled.graph.Graph;
41  
42  import org.dishevelled.graph.io.GraphWriter;
43  
44  /**
45   * GraphML writer.
46   *
47   * @param <N> node value type
48   * @param <E> edge value type
49   * @author  Michael Heuer
50   * @version $Revision$ $Date$
51   */
52  public final class GraphMLWriter<N, E>
53      implements GraphWriter<N, E>
54  {
55      /** XML output factory. */
56      private final XMLOutputFactory outputFactory;
57  
58      /** Node value handler. */
59      private ValueHandler<N> nodeValueHandler;
60  
61      /** Edge value handler. */
62      private ValueHandler<E> edgeValueHandler;
63  
64  
65      /**
66       * Create a new GraphML writer.
67       */
68      public GraphMLWriter()
69      {
70          outputFactory = XMLOutputFactory.newInstance();
71      }
72  
73  
74      /**
75       * Set the node value handler for this GraphML writer to <code>nodeValueHandler</code>.
76       *
77       * @param nodeValueHandler node value handler
78       */
79      public void setNodeValueHandler(final ValueHandler<N> nodeValueHandler)
80      {
81          this.nodeValueHandler = nodeValueHandler;
82      }
83  
84      /**
85       * Set the edge value handler for this GraphML writer to <code>edgeValueHandler</code>.
86       *
87       * @param edgeValueHandler edge value handler
88       */
89      public void setEdgeValueHandler(final ValueHandler<E> edgeValueHandler)
90      {
91          this.edgeValueHandler = edgeValueHandler;
92      }
93  
94      /** {@inheritDoc} */
95      public void write(final Graph<N, E> graph, final File file)
96          throws IOException
97      {
98          if (graph == null)
99          {
100             throw new IllegalArgumentException("graph must not be null");
101         }
102         if (file == null)
103         {
104             throw new IllegalArgumentException("file must not be null");
105         }
106         try
107         {
108             XMLStreamWriter writer = outputFactory.createXMLStreamWriter(new FileWriter(file));
109             write(graph, writer);
110         }
111         catch (XMLStreamException e)
112         {
113             //throw new IOException(e); jdk1.6+
114             throw new IOException(e.getMessage());
115         }
116     }
117 
118     /** {@inheritDoc} */
119     public void write(final Graph<N, E> graph, final OutputStream outputStream)
120         throws IOException
121     {
122         if (graph == null)
123         {
124             throw new IllegalArgumentException("graph must not be null");
125         }
126         if (outputStream == null)
127         {
128             throw new IllegalArgumentException("outputStream must not be null");
129         }
130         try
131         {
132             XMLStreamWriter writer = outputFactory.createXMLStreamWriter(outputStream);
133             write(graph, writer);
134         }
135         catch (XMLStreamException e)
136         {
137             //throw new IOException(e);
138             throw new IOException(e.getMessage());
139         }
140     }
141 
142     /**
143      * Write the specified graph to the specified XML stream writer.
144      *
145      * @param graph graph to write
146      * @param writer XML stream writer to write to
147      * @throws IOException if an error occurs
148      * @throws XMLStreamException if an error occurs
149      */
150     private void write(final Graph<N, E> graph, final XMLStreamWriter writer)
151         throws IOException, XMLStreamException
152     {
153         writer.writeStartDocument("1.0");
154         //writer.writeStartDocument("UTF-8", "1.0");
155         writer.writeStartElement("graphml");
156         writer.writeDefaultNamespace("http://graphml.graphdrawing.org/xmlns");
157         writer.writeNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
158         writer.writeAttribute("xsi:schemaLocation", "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd");
159         if (nodeValueHandler != null)
160         {
161             writer.writeStartElement("key");
162             writer.writeAttribute("id", "k0");
163             writer.writeAttribute("for", "node");
164             writer.writeEndElement(); // </key>
165         }
166         if (edgeValueHandler != null)
167         {
168             writer.writeStartElement("key");
169             writer.writeAttribute("id", "k1");
170             writer.writeAttribute("for", "edge");
171             writer.writeEndElement(); // </key>
172         }
173         writer.writeStartElement("graph");
174         writer.writeAttribute("id", "G");
175         writer.writeAttribute("edgedefault", "directed");
176         int n = 0;
177         Map<Node<N, E>, String> nodeIds = new HashMap<Node<N, E>, String>(graph.nodeCount());
178         for (Node<N, E> node : graph.nodes())
179         {
180             String nodeId = nodeIds.get(node);
181             if (nodeId == null)
182             {
183                 nodeId = "n" + n;
184                 n++;
185                 nodeIds.put(node, nodeId);
186             }
187             writer.writeStartElement("node");
188             writer.writeAttribute("id", nodeId);
189             if (nodeValueHandler != null)
190             {
191                 writer.writeStartElement("data");
192                 writer.writeAttribute("key", "k0");
193                 nodeValueHandler.write(node.getValue(), writer);
194                 writer.writeEndElement(); // </data>
195             }
196             writer.writeEndElement(); // </node>
197         }
198         int e = 0;
199         for (Edge<N, E> edge : graph.edges())
200         {
201             String edgeId = "e" + e;
202             e++;
203             writer.writeStartElement("edge");
204             writer.writeAttribute("id", edgeId);
205             writer.writeAttribute("source", nodeIds.get(edge.source()));
206             writer.writeAttribute("target", nodeIds.get(edge.target()));
207             if (edgeValueHandler != null)
208             {
209                 writer.writeStartElement("data");
210                 writer.writeAttribute("key", "k1");
211                 edgeValueHandler.write(edge.getValue(), writer);
212                 writer.writeEndElement(); // </data>
213             }
214             writer.writeEndElement(); // </edge>
215         }
216         writer.writeEndElement(); // </graph>
217         writer.writeEndElement(); // </graphml>
218         writer.close();
219     }
220 
221     /**
222      * Value handler.
223      *
224      * @param <V> value type
225      */
226     public interface ValueHandler<V>
227     {
228 
229         /**
230          * Write the specified value to the specified XML stream writer.
231          *
232          * @param value value to write
233          * @param writer XML stream writer to write to, must not be null
234          * @throws IOException if an error occurs
235          * @throws XMLStreamException if an error occurs
236          */
237         void write(V value, XMLStreamWriter writer) throws IOException, XMLStreamException;
238     }
239 }