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.ygraphml;
25  
26  import java.io.File;
27  import java.io.FileWriter;
28  import java.io.IOException;
29  import java.io.OutputStream;
30  import java.text.DecimalFormat;
31  import java.text.NumberFormat;
32  import java.util.HashMap;
33  import java.util.Map;
34  
35  import javax.xml.stream.XMLOutputFactory;
36  import javax.xml.stream.XMLStreamException;
37  import javax.xml.stream.XMLStreamWriter;
38  
39  import org.dishevelled.graph.Edge;
40  import org.dishevelled.graph.Graph;
41  import org.dishevelled.graph.Node;
42  
43  import org.dishevelled.graph.io.GraphWriter;
44  
45  /**
46   * Graph writer for the yFiles extension to GraphML.
47   *
48   * @author  Michael Heuer
49   * @version $Revision$ $Date$
50   */
51  public final class YGraphMLWriter
52      implements GraphWriter<ShapeNode, PolyLineEdge>
53  {
54      /** XML output factory. */
55      private final XMLOutputFactory outputFactory;
56  
57  
58      /**
59       * Create a new YGraphML writer.
60       */
61      public YGraphMLWriter()
62      {
63          outputFactory = XMLOutputFactory.newInstance();
64      }
65  
66  
67      /** {@inheritDoc} */
68      public void write(final Graph<ShapeNode, PolyLineEdge> graph, final File file)
69          throws IOException
70      {
71          if (graph == null)
72          {
73              throw new IllegalArgumentException("graph must not be null");
74          }
75          if (file == null)
76          {
77              throw new IllegalArgumentException("file must not be null");
78          }
79          try
80          {
81              XMLStreamWriter writer = outputFactory.createXMLStreamWriter(new FileWriter(file));
82              write(graph, writer);
83          }
84          catch (XMLStreamException e)
85          {
86              //throw new IOException(e); jdk1.6+
87              throw new IOException(e.getMessage());
88          }
89      }
90  
91      /** {@inheritDoc} */
92      public void write(final Graph<ShapeNode, PolyLineEdge> graph, final OutputStream outputStream)
93          throws IOException
94      {
95          if (graph == null)
96          {
97              throw new IllegalArgumentException("graph must not be null");
98          }
99          if (outputStream == null)
100         {
101             throw new IllegalArgumentException("outputStream must not be null");
102         }
103         try
104         {
105             XMLStreamWriter writer = outputFactory.createXMLStreamWriter(outputStream);
106             write(graph, writer);
107         }
108         catch (XMLStreamException e)
109         {
110             //throw new IOException(e); jdk 1.6+
111             throw new IOException(e.getMessage());
112         }
113     }
114 
115     /**
116      * Write the specified graph to the specified XML stream writer.
117      *
118      * @param graph graph to write
119      * @param writer XML stream writer to write to
120      * @throws IOException if an error occurs
121      * @throws XMLStreamException if an error occurs
122      */
123     private void write(final Graph<ShapeNode, PolyLineEdge> graph, final XMLStreamWriter writer)
124         throws IOException, XMLStreamException
125     {
126         writer.writeStartDocument("1.0");
127         //writer.writeStartDocument("UTF-8", "1.0");
128         writer.writeStartElement("graphml");
129         writer.writeDefaultNamespace("http://graphml.graphdrawing.org/xmlns");
130         writer.writeNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
131         writer.writeNamespace("y", "http://www.yworks.com/xml/graphml");
132         writer.writeAttribute("xsi:schemaLocation", "http://graphml.graphdrawing.org/xmlns/graphml http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd");
133 
134         writer.writeStartElement("key");
135         writer.writeAttribute("id", "k0");
136         writer.writeAttribute("for", "node");
137         writer.writeAttribute("yfiles.type", "nodegraphics");
138         writer.writeEndElement(); // </key>
139 
140         writer.writeStartElement("key");
141         writer.writeAttribute("id", "k1");
142         writer.writeAttribute("for", "edge");
143         writer.writeAttribute("yfiles.type", "edgegraphics");
144         writer.writeEndElement(); // </key>
145 
146         writer.writeStartElement("graph");
147         writer.writeAttribute("id", "G");
148         writer.writeAttribute("edgedefault", "directed");
149         NumberFormat numberFormat = NumberFormat.getInstance();
150         if (numberFormat instanceof DecimalFormat)
151         {
152             ((DecimalFormat) numberFormat).setMinimumFractionDigits(1);
153         }
154         int n = 0;
155         Map<Node<ShapeNode, PolyLineEdge>, String> nodeIds = new HashMap<Node<ShapeNode, PolyLineEdge>, String>(graph.nodeCount());
156         for (Node<ShapeNode, PolyLineEdge> node : graph.nodes())
157         {
158             String nodeId = nodeIds.get(node);
159             if (nodeId == null)
160             {
161                 nodeId = "n" + n;
162                 n++;
163                 nodeIds.put(node, nodeId);
164             }
165             writer.writeStartElement("node");
166             writer.writeAttribute("id", nodeId);
167             writer.writeStartElement("data");
168             writer.writeAttribute("key", "k0");
169 
170             ShapeNode shapeNode = node.getValue();
171             writer.writeStartElement("http://www.yworks.com/xml/graphml", "ShapeNode");
172 
173             Fill fill = shapeNode.getFill();
174             writer.writeStartElement("http://www.yworks.com/xml/graphml", "Fill");
175             writer.writeAttribute("color", fill.getColor());
176             writer.writeAttribute("transparent", fill.isTransparent() ? "true" : "false");
177             writer.writeEndElement(); // <y:Fill>
178 
179             BorderStyle borderStyle = shapeNode.getBorderStyle();
180             writer.writeStartElement("http://www.yworks.com/xml/graphml", "BorderStyle");
181             writer.writeAttribute("type", borderStyle.getType());
182             writer.writeAttribute("width", numberFormat.format(borderStyle.getWidth()));
183             writer.writeAttribute("color", borderStyle.getColor());
184             writer.writeEndElement(); // <y:BorderStyle>
185 
186             NodeLabel nodeLabel = shapeNode.getNodeLabel();
187             writer.writeStartElement("http://www.yworks.com/xml/graphml", "NodeLabel");
188             writer.writeAttribute("visible", nodeLabel.isVisible() ? "true" : "false");
189             writer.writeAttribute("alignment", nodeLabel.getAlignment());
190             writer.writeAttribute("fontFamily", nodeLabel.getFontFamily());
191             writer.writeAttribute("fontSize", String.valueOf(nodeLabel.getFontSize()));
192             writer.writeAttribute("fontStyle", nodeLabel.getFontStyle());
193             writer.writeAttribute("textColor", nodeLabel.getTextColor());
194             writer.writeAttribute("modelName", nodeLabel.getModelName());
195             writer.writeAttribute("modelPosition", nodeLabel.getModelPosition());
196             writer.writeAttribute("autoSizePolicy", nodeLabel.getAutoSizePolicy());
197             writer.writeCharacters(nodeLabel.getText());
198             writer.writeEndElement(); // <y:NodeLabel>
199 
200             Shape shape = shapeNode.getShape();
201             writer.writeStartElement("http://www.yworks.com/xml/graphml", "Shape");
202             writer.writeAttribute("type", shape.getType());
203             writer.writeEndElement(); // <y:Shape>
204 
205             writer.writeEndElement(); // <y:ShapeNode>
206             writer.writeEndElement(); // </data>
207             writer.writeEndElement(); // </node>
208         }
209         int e = 0;
210         for (Edge<ShapeNode, PolyLineEdge> edge : graph.edges())
211         {
212             String edgeId = "e" + e;
213             e++;
214             writer.writeStartElement("edge");
215             writer.writeAttribute("id", edgeId);
216             writer.writeAttribute("source", nodeIds.get(edge.source()));
217             writer.writeAttribute("target", nodeIds.get(edge.target()));
218             writer.writeStartElement("data");
219             writer.writeAttribute("key", "k1");
220 
221             PolyLineEdge polyLineEdge = edge.getValue();
222             writer.writeStartElement("http://www.yworks.com/xml/graphml", "PolyLineEdge");
223 
224             LineStyle lineStyle = polyLineEdge.getLineStyle();
225             writer.writeStartElement("http://www.yworks.com/xml/graphml", "LineStyle");
226             writer.writeAttribute("type", lineStyle.getType());
227             writer.writeAttribute("width", numberFormat.format(lineStyle.getWidth()));
228             writer.writeAttribute("color", lineStyle.getColor());
229             writer.writeEndElement(); // <y:LineStyle>
230 
231             Arrows arrows = polyLineEdge.getArrows();
232             writer.writeStartElement("http://www.yworks.com/xml/graphml", "Arrows");
233             writer.writeAttribute("source", arrows.getSource());
234             writer.writeAttribute("target", arrows.getTarget());
235             writer.writeEndElement(); // <y:Arrows>
236 
237             EdgeLabel edgeLabel = polyLineEdge.getEdgeLabel();
238             writer.writeStartElement("http://www.yworks.com/xml/graphml", "EdgeLabel");
239             writer.writeAttribute("visible", edgeLabel.isVisible() ? "true" : "false");
240             writer.writeAttribute("alignment", edgeLabel.getAlignment());
241             writer.writeAttribute("fontFamily", edgeLabel.getFontFamily());
242             writer.writeAttribute("fontSize", String.valueOf(edgeLabel.getFontSize()));
243             writer.writeAttribute("fontStyle", edgeLabel.getFontStyle());
244             writer.writeAttribute("textColor", edgeLabel.getTextColor());
245             writer.writeAttribute("modelName", edgeLabel.getModelName());
246             writer.writeAttribute("modelPosition", edgeLabel.getModelPosition());
247             writer.writeAttribute("preferredPlacement", edgeLabel.getPreferredPlacement());
248             writer.writeAttribute("distance", numberFormat.format(edgeLabel.getDistance()));
249             writer.writeAttribute("ratio", numberFormat.format(edgeLabel.getRatio()));
250             writer.writeCharacters(edgeLabel.getText());
251             writer.writeEndElement(); // <y:EdgeLabel>
252 
253             BendStyle bendStyle = polyLineEdge.getBendStyle();
254             writer.writeStartElement("http://www.yworks.com/xml/graphml", "BendStyle");
255             writer.writeAttribute("smoothed", bendStyle.isSmoothed() ? "true" : "false");
256             writer.writeEndElement(); // <y:BendStyle>
257 
258             writer.writeEndElement(); // <y:PolyLineEdge>
259 
260             writer.writeEndElement(); // </data>
261             writer.writeEndElement(); // </edge>
262         }
263         writer.writeEndElement(); // </graph>
264         writer.writeEndElement(); // </graphml>
265         writer.close();
266    }
267 }