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.xgmml;
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   * XGMML graph writer.
46   *
47   * @param <N> node value type
48   * @param <E> edge value type
49   * @author  Michael Heuer
50   */
51  public final class XgmmlGraphWriter<N, E>
52      implements GraphWriter<N, E>
53  {
54      /** XML output factory. */
55      private final XMLOutputFactory outputFactory;
56  
57      /** Map of node value handlers keyed by name. */
58      private final Map<String, ValueHandler<N>> nodeValueHandlers;
59  
60      /** Map of edge value handlers keyed by name. */
61      private final Map<String, ValueHandler<E>> edgeValueHandlers;
62  
63  
64      /**
65       * Create a new XGMML graph writer.
66       */
67      public XgmmlGraphWriter()
68      {
69          outputFactory = XMLOutputFactory.newInstance();
70          nodeValueHandlers = new HashMap<String, ValueHandler<N>>();
71          edgeValueHandlers = new HashMap<String, ValueHandler<E>>();
72      }
73  
74  
75      /**
76       * Add the specified node value handler for the specified attribute name.
77       *
78       * @param name attribute name, must not be null
79       * @param nodeValueHandler node value handler to add, must not be null
80       */
81      public void addNodeValueHandler(final String name, final ValueHandler<N> nodeValueHandler)
82      {
83          if (name == null)
84          {
85              throw new IllegalArgumentException("name must not be null");
86          }
87          if (nodeValueHandler == null)
88          {
89              throw new IllegalArgumentException("nodeValueHandler must not be null");
90          }
91          nodeValueHandlers.put(name, nodeValueHandler);
92      }
93  
94      /**
95       * Add the specified edge value handler for the specified attribute name.
96       *
97       * @param name attribute name, must not be null
98       * @param edgeValueHandler edge value handler to add, must not be null
99       */
100     public void addEdgeValueHandler(final String name, final ValueHandler<E> edgeValueHandler)
101     {
102         if (name == null)
103         {
104             throw new IllegalArgumentException("name must not be null");
105         }
106         if (edgeValueHandler == null)
107         {
108             throw new IllegalArgumentException("edgeValueHandler must not be null");
109         }
110         edgeValueHandlers.put(name, edgeValueHandler);
111     }
112 
113     /** {@inheritDoc} */
114     public void write(final Graph<N, E> graph, final File file)
115         throws IOException
116     {
117         if (graph == null)
118         {
119             throw new IllegalArgumentException("graph must not be null");
120         }
121         if (file == null)
122         {
123             throw new IllegalArgumentException("file must not be null");
124         }
125         try
126         {
127             XMLStreamWriter writer = outputFactory.createXMLStreamWriter(new FileWriter(file));
128             write(graph, writer);
129         }
130         catch (XMLStreamException e)
131         {
132             //throw new IOException(e); jdk1.6+
133             throw new IOException(e.getMessage());
134         }
135     }
136 
137     /** {@inheritDoc} */
138     public void write(final Graph<N, E> graph, final OutputStream outputStream)
139         throws IOException
140     {
141         if (graph == null)
142         {
143             throw new IllegalArgumentException("graph must not be null");
144         }
145         if (outputStream == null)
146         {
147             throw new IllegalArgumentException("outputStream must not be null");
148         }
149         try
150         {
151             XMLStreamWriter writer = outputFactory.createXMLStreamWriter(outputStream);
152             write(graph, writer);
153         }
154         catch (XMLStreamException e)
155         {
156             //throw new IOException(e);
157             throw new IOException(e.getMessage());
158         }
159     }
160 
161     /**
162      * Write the specified graph to the specified XML stream writer.
163      *
164      * @param graph graph to write
165      * @param writer XML stream writer to write to
166      * @throws IOException if an error occurs
167      * @throws XMLStreamException if an error occurs
168      */
169     private void write(final Graph<N, E> graph, final XMLStreamWriter writer)
170         throws IOException, XMLStreamException
171     {
172         writer.writeStartDocument("1.0");
173         //writer.writeStartDocument("UTF-8", "1.0");
174         writer.writeStartElement("graph");
175         writer.writeDefaultNamespace("http://www.cs.rpi.edu/XGMML");
176         writer.writeNamespace("dc", "http://purl.org/dc/elements/1.1/");
177         writer.writeNamespace("xlink", "http://www.w3.org/1999/xlink");
178         writer.writeNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
179         //writer.writeAttribute("xsi:schemaLocation", "http://www.cs.rpi.edu/XGMML http://www.cs.rpi.edu/research/groups/pb/punin/public_html/XGMML/xgmml.xsd");
180         writer.writeAttribute("label", "graph0");
181         writer.writeAttribute("directed", "1");
182 
183         int n = 0;
184         Map<Node<N, E>, String> nodeIds = new HashMap<Node<N, E>, String>(graph.nodeCount());
185         for (Node<N, E> node : graph.nodes())
186         {
187             String nodeId = nodeIds.get(node);
188             if (nodeId == null)
189             {
190                 nodeId = "n" + n;
191                 n++;
192                 nodeIds.put(node, nodeId);
193             }
194             writer.writeStartElement("node");
195             writer.writeAttribute("id", nodeId);
196             writer.writeAttribute("label", nodeId);
197             for (Map.Entry<String, ValueHandler<N>> entry : nodeValueHandlers.entrySet())
198             {
199                 writer.writeStartElement("att");
200                 writer.writeAttribute("name", entry.getKey());
201                 ValueHandler<N> nodeValueHandler = entry.getValue();
202                 writer.writeAttribute("type", nodeValueHandler.getType());
203                 writer.writeAttribute("value", nodeValueHandler.getValue(node.getValue()));
204                 writer.writeEndElement(); // </att>
205             }
206             writer.writeEndElement(); // </node>
207         }
208         int e = 0;
209         for (Edge<N, E> edge : graph.edges())
210         {
211             String edgeId = "e" + e;
212             e++;
213             writer.writeStartElement("edge");
214             writer.writeAttribute("label", edgeId);
215             writer.writeAttribute("source", nodeIds.get(edge.source()));
216             writer.writeAttribute("target", nodeIds.get(edge.target()));
217             for (Map.Entry<String, ValueHandler<E>> entry : edgeValueHandlers.entrySet())
218             {
219                 writer.writeStartElement("att");
220                 writer.writeAttribute("name", entry.getKey());
221                 ValueHandler<E> edgeValueHandler = entry.getValue();
222                 writer.writeAttribute("type", edgeValueHandler.getType());
223                 writer.writeAttribute("value", edgeValueHandler.getValue(edge.getValue()));
224                 writer.writeEndElement(); // </att>
225             }
226             writer.writeEndElement(); // </edge>
227         }
228         writer.writeEndElement(); // </graph>
229         writer.close();
230     }
231 
232     /**
233      * Value handler.
234      *
235      * @param <V> value type
236      */
237     public interface ValueHandler<V>
238     {
239 
240         /**
241          * Return the type for this value handler.
242          *
243          * @param value value
244          * @return the type for this value handler
245          */
246         String getType();
247 
248         /**
249          * Convert the specified value to a string.
250          *
251          * @param value value
252          * @return the specified value converted to a string
253          */
254         String getValue(V value);
255     }
256 }