1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.7. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2009 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.io;
15  
16  import y.io.GIFIOHandler;
17  import y.io.GMLIOHandler;
18  import y.io.GraphMLIOHandler;
19  import y.io.IOHandler;
20  import y.io.ImageOutputHandler;
21  import y.io.JPGIOHandler;
22  import y.io.YGFIOHandler;
23  import y.io.ZipGraphMLIOHandler;
24  import y.util.D;
25  import y.view.Graph2D;
26  import y.view.Graph2DView;
27  import y.view.hierarchy.HierarchyManager;
28  
29  import java.awt.Dimension;
30  import java.awt.Rectangle;
31  import java.io.IOException;
32  import java.util.Collection;
33  import java.util.Iterator;
34  import java.util.LinkedList;
35  
36  
37  /**
38   * This class implements a command line driven graph format converter.
39   * Possible input formats are GraphML, ZIPGraphML, GML or YGF.
40   * Output formats are GraphML, ZIPGraphML, GML, YGF, GIF, and JPG.
41   * <br>
42   * Additionally, it is possible to write to the formats PDF, EMF, SWF, EPS, SVG, and SVGZ
43   *  in case the corresponding
44   * yFiles extension packages ySVG and yExport are installed.
45   * The size of some output formats can be specified.
46   */
47  public class GraphFormatConverter {
48    private Collection ioHandlers;
49    private int outputWidth = -1;
50    private int outputHeight = -1;
51    private String inFile;
52    private String outFile;
53  
54  
55    private static void usage(String msg) {
56      System.err.println(msg + "\n\n" +
57          "Usage: java demo.io.GraphFormatConverter -in <infile> -out <outfile> [options]\n" +
58          "Usage: where the format of infile is GraphML, ZIPGraphML, YGF or GML \n" +
59          "Usage: and the format of outfile in in GraphML, ZIPGraphML, YGF, GML, JPG or GIF.\n" +
60          "Usage: SVG/SVGZ output needs the ySVG extension package.\n" +
61          "Usage: EMF, PDF, EPS and SWF output needs the yExport extension package.\n" +
62          "Usage: File formats are determined by the file name extensions.\n" +
63          "Usage: Additional options which work for some output formats:\n" +
64          "Usage: -width <w>   the width of the output format\n" +
65          "Usage: -height<h>   the height of the output format\n" +
66          "Usage:  If neither option is specified, a value of 1024\n" +
67          "Usage:  is used for both dimensions\n");
68      System.exit(1);
69    }
70  
71    private static void error(String msg) {
72      System.err.println(msg);
73      System.exit(1);
74    }
75  
76    /**
77     * Creates a new instance of GraphFormatConverter.
78     * Adds all known IOHandlers to the conversion engine
79     */
80    public GraphFormatConverter() {
81      ioHandlers = new LinkedList();
82      ioHandlers.add(new GraphMLIOHandler());
83      ioHandlers.add(new ZipGraphMLIOHandler());
84      ioHandlers.add(new YGFIOHandler());
85      ioHandlers.add(new GMLIOHandler());
86      ioHandlers.add(new GIFIOHandler());
87      ioHandlers.add(new JPGIOHandler());
88      try { //try to support SVG(Z) output format if it is present
89        ioHandlers.add((IOHandler) Class.forName("yext.svg.io.SVGIOHandler").newInstance());
90        ioHandlers.add((IOHandler) Class.forName("yext.svg.io.SVGZIOHandler").newInstance());
91      }
92      catch (ClassNotFoundException cnfex) {
93        //SVG(Z) format disabled. Put ySVG extension package in your classpath
94      }
95      catch (Exception ex) {
96        D.trace(ex);
97      }
98  
99      try { //try to support PDF output format if it is present
100       ioHandlers.add((IOHandler) Class.forName("yext.export.io.PDFOutputHandler").newInstance());
101     } catch (ClassNotFoundException cnfex) {
102       //PDF format disabled. Put yExport extension package in your classpath
103     } catch (Exception ex) {
104       D.trace(ex);
105     }
106 
107     try { //try to support SWF output format if it is present
108       ioHandlers.add((IOHandler) Class.forName("yext.export.io.SWFOutputHandler").newInstance());
109     } catch (ClassNotFoundException cnfex) {
110       //SWF format disabled. Put yExport extension package in your classpath
111     } catch (Exception ex) {
112       D.trace(ex);
113     }
114 
115     try { //try to support EPS output format if it is present
116       ioHandlers.add((IOHandler) Class.forName("yext.export.io.EPSOutputHandler").newInstance());
117     } catch (ClassNotFoundException cnfex) {
118       //EPS format disabled. Put yExport extension package in your classpath
119     } catch (Exception ex) {
120       D.trace(ex);
121     }
122 
123     try { //try to support EMF output format if it is present
124       ioHandlers.add((IOHandler) Class.forName("yext.export.io.EMFOutputHandler").newInstance());
125     } catch (ClassNotFoundException cnfex) {
126       //EMF format disabled. Put yExport extension package in your classpath
127     } catch (Exception ex) {
128       D.trace(ex);
129     }
130 
131   }
132 
133   /**
134    * does the conversion specified on the command line.
135    * @param args the command line arguments.
136    */
137   public void convert(String[] args) {
138     parseArgs(args);
139 
140     Graph2D graph = new Graph2D();
141 
142     //add HierarchyManager in case the input and output files
143     //are able to handle graph hierarchy information
144     HierarchyManager hierarchy = new HierarchyManager(graph);
145 
146     //read in the graph using inpoutHandler
147     IOHandler inputHandler = getIOHandler(inFile);
148 
149     if (inputHandler != null && inputHandler.canRead()) {
150       try {
151         inputHandler.read(graph, inFile);
152       }
153       catch (IOException iex) {
154         error("Error while decoding file " + inFile + "\n" + iex);
155       }
156     } else {
157       usage("Can't determine input format");
158     }
159 
160     //write out the graph using outputHandler
161     IOHandler outputHandler = getIOHandler(outFile);
162 
163     if (outputHandler != null && outputHandler.canWrite()) {
164       Graph2DView view = null;
165       if (outputHandler instanceof ImageOutputHandler) {
166         //configure rendering component for image formats
167         view = ((ImageOutputHandler) outputHandler).createDefaultGraph2DView(graph);
168       } else {
169         view = new Graph2DView(graph);
170       }
171       configureView(view);
172       //set the viewport view to the current view of the graph.
173       graph.setCurrentView(view);
174       try {
175         outputHandler.write(graph, outFile);
176       }
177       catch (IOException iex) {
178         error("Error while encoding file " + outFile + "\n" + iex);
179       }
180       //deregister the viewport view for the graph again.
181       graph.removeView(view);
182     } else {
183       usage("Can't determine output format");
184     }
185 
186   }
187 
188   /**
189    * Configures the view that is used as rendering environment for some
190    * output formats.
191    */
192   private void configureView(Graph2DView view) {
193     Graph2D graph = view.getGraph2D();
194     Rectangle box = graph.getBoundingBox();
195     Dimension dim = getOutputSize(box);
196     view.setSize(dim);
197     view.zoomToArea(box.getX() - 10, box.getY() - 10, box.getWidth() + 20, box.getHeight() + 20);
198     view.setPaintDetailThreshold(0.0); //never switch to less detail mode
199   }
200 
201   /**
202    * Parses the command line arguments and set attributes
203    */
204   public void parseArgs(String[] args) {
205     for (int i = 0; i < args.length; i++) {
206       if ("-in".equals(args[i]) && inFile == null) {
207         inFile = args[++i];
208       } else if ("-out".equals(args[i]) && outFile == null) {
209         outFile = args[++i];
210       } else if ("-width".equals(args[i])) {
211         outputWidth = Integer.parseInt(args[++i]);
212       } else if ("-height".equals(args[i])) {
213         outputHeight = Integer.parseInt(args[++i]);
214       }
215     }
216 
217     if (inFile == null) {
218       usage("No input file specified");
219     }
220 
221     if (outFile == null) {
222       usage("No output file specified");
223     }
224   }
225 
226   /**
227    * Returns the output size of image formats by
228    * inspecting the input size of the graph and the output size
229    * parameters.
230    */
231   private Dimension getOutputSize(Rectangle inBox) {
232     if (outputWidth > 0 && outputHeight > 0) {
233       //output completely specified. use it
234       return new Dimension((int) outputWidth, (int) outputHeight);
235     } else if (outputWidth > 0) {
236       //output width specified. determine output height
237       return new Dimension(outputWidth,
238           (int) (outputWidth * (inBox.getHeight() / inBox.getWidth())));
239     } else if (outputHeight > 0) {
240       //output height specified. determine output width
241       return new Dimension((int) (outputHeight * (inBox.getWidth() / inBox.getHeight())),
242           outputHeight);
243     } else //no output size specified
244     {
245       //no output size specified. use input size, but only if smaller than 1024
246       double width = inBox.getWidth();
247       double height = inBox.getHeight();
248       //scale down if necessary, keeping aspect ratio
249       if (width > 1024) {
250         height *= 1024 / width;
251         width = 1024;
252       }
253       if (height > 1024) {
254         width *= 1024 / height;
255         height = 1024;
256       }
257       return new Dimension((int) width, (int) height);
258     }
259   }
260 
261   /**
262    * returns the IOHandler that is responsible for files with the
263    * given name.
264    */
265   private IOHandler getIOHandler(String fileName) {
266     for (Iterator iter = ioHandlers.iterator(); iter.hasNext();) {
267       IOHandler ioh = (IOHandler) iter.next();
268       if (fileName.endsWith(ioh.getFileNameExtension())) {
269         return ioh;
270       }
271     }
272     return null;
273   }
274 
275   //////////////////////////////////////////////////////////////////////////////
276   // STATIC LAUNCHER SECTION ///////////////////////////////////////////////////
277   //////////////////////////////////////////////////////////////////////////////
278 
279   public static void main(String[] args) {
280     GraphFormatConverter converter = new GraphFormatConverter();
281     converter.convert(args);
282   }
283 
284 }
285