001/*
002 * Copyright 2006 - 2013
003 *      Stefan Balev    <stefan.balev@graphstream-project.org>
004 *      Julien Baudry   <julien.baudry@graphstream-project.org>
005 *      Antoine Dutot   <antoine.dutot@graphstream-project.org>
006 *      Yoann Pigné         <yoann.pigne@graphstream-project.org>
007 *      Guilhelm Savin  <guilhelm.savin@graphstream-project.org>
008 *  
009 * GraphStream is a library whose purpose is to handle static or dynamic
010 * graph, create them from scratch, file or any source and display them.
011 * 
012 * This program is free software distributed under the terms of two licenses, the
013 * CeCILL-C license that fits European law, and the GNU Lesser General Public
014 * License. You can  use, modify and/ or redistribute the software under the terms
015 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
016 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
017 * the Free Software Foundation, either version 3 of the License, or (at your
018 * option) any later version.
019 * 
020 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
021 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
022 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
023 * 
024 * You should have received a copy of the GNU Lesser General Public License
025 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
026 * 
027 * The fact that you are presently reading this means that you have had
028 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
029 */
030package org.graphstream.stream.file;
031
032import java.io.FileWriter;
033import java.io.IOException;
034import java.io.OutputStream;
035import java.io.OutputStreamWriter;
036import java.io.Writer;
037
038import javax.xml.stream.XMLStreamException;
039
040import org.graphstream.graph.Graph;
041import org.graphstream.stream.GraphReplay;
042import org.graphstream.stream.PipeBase;
043import org.graphstream.stream.file.gexf.GEXF;
044import org.graphstream.stream.file.gexf.SmartXMLWriter;
045
046public class FileSinkGEXF2 extends PipeBase implements FileSink {
047        class Context {
048                GEXF gexf;
049                Writer output;
050                SmartXMLWriter stream;
051                boolean closeStreamAtEnd;
052        }
053
054        Context currentContext;
055
056        Context createContext(String fileName) throws IOException {
057                FileWriter w = new FileWriter(fileName);
058                Context ctx = createContext(w);
059                ctx.closeStreamAtEnd = true;
060
061                return ctx;
062        }
063
064        Context createContext(OutputStream output) throws IOException {
065                OutputStreamWriter w = new OutputStreamWriter(output);
066                return createContext(w);
067        }
068
069        Context createContext(Writer w) throws IOException {
070                Context ctx = new Context();
071
072                ctx.output = w;
073                ctx.closeStreamAtEnd = false;
074                ctx.gexf = new GEXF();
075
076                try {
077                        ctx.stream = new SmartXMLWriter(w, true);
078                } catch (Exception e) {
079                        throw new IOException(e);
080                }
081
082                return ctx;
083        }
084
085        protected void export(Context ctx, Graph g) throws IOException {
086                ctx.gexf.disable(GEXF.Extension.DYNAMICS);
087
088                GraphReplay replay = new GraphReplay("replay");
089                replay.addSink(ctx.gexf);
090                replay.replay(g);
091
092                try {
093                        ctx.gexf.export(ctx.stream);
094                        ctx.stream.close();
095
096                        if (ctx.closeStreamAtEnd)
097                                ctx.output.close();
098                } catch (XMLStreamException e) {
099                        throw new IOException(e);
100                }
101        }
102
103        /*
104         * (non-Javadoc)
105         * 
106         * @see
107         * org.graphstream.stream.file.FileSink#writeAll(org.graphstream.graph.Graph
108         * , java.lang.String)
109         */
110        public void writeAll(Graph graph, String fileName) throws IOException {
111                Context ctx = createContext(fileName);
112                export(ctx, graph);
113        }
114
115        /*
116         * (non-Javadoc)
117         * 
118         * @see
119         * org.graphstream.stream.file.FileSink#writeAll(org.graphstream.graph.Graph
120         * , java.io.OutputStream)
121         */
122        public void writeAll(Graph graph, OutputStream stream) throws IOException {
123                Context ctx = createContext(stream);
124                export(ctx, graph);
125        }
126
127        /*
128         * (non-Javadoc)
129         * 
130         * @see
131         * org.graphstream.stream.file.FileSink#writeAll(org.graphstream.graph.Graph
132         * , java.io.Writer)
133         */
134        public void writeAll(Graph graph, Writer writer) throws IOException {
135                Context ctx = createContext(writer);
136                export(ctx, graph);
137        }
138
139        /*
140         * (non-Javadoc)
141         * 
142         * @see org.graphstream.stream.file.FileSink#begin(java.lang.String)
143         */
144        public void begin(String fileName) throws IOException {
145                if (currentContext != null)
146                        throw new IOException(
147                                        "cannot call begin() twice without calling end() before.");
148
149                currentContext = createContext(fileName);
150                addSink(currentContext.gexf);
151        }
152
153        /*
154         * (non-Javadoc)
155         * 
156         * @see org.graphstream.stream.file.FileSink#begin(java.io.OutputStream)
157         */
158        public void begin(OutputStream stream) throws IOException {
159                if (currentContext != null)
160                        throw new IOException(
161                                        "cannot call begin() twice without calling end() before.");
162
163                currentContext = createContext(stream);
164                addSink(currentContext.gexf);
165        }
166
167        /*
168         * (non-Javadoc)
169         * 
170         * @see org.graphstream.stream.file.FileSink#begin(java.io.Writer)
171         */
172        public void begin(Writer writer) throws IOException {
173                if (currentContext != null)
174                        throw new IOException(
175                                        "cannot call begin() twice without calling end() before.");
176
177                currentContext = createContext(writer);
178                addSink(currentContext.gexf);
179        }
180
181        /*
182         * (non-Javadoc)
183         * 
184         * @see org.graphstream.stream.file.FileSink#flush()
185         */
186        public void flush() throws IOException {
187                if (currentContext != null)
188                        currentContext.stream.flush();
189        }
190
191        /*
192         * (non-Javadoc)
193         * 
194         * @see org.graphstream.stream.file.FileSink#end()
195         */
196        public void end() throws IOException {
197                removeSink(currentContext.gexf);
198
199                try {
200                        currentContext.gexf.export(currentContext.stream);
201                        currentContext.stream.close();
202
203                        if (currentContext.closeStreamAtEnd)
204                                currentContext.output.close();
205                } catch (XMLStreamException e) {
206                        throw new IOException(e);
207                }
208
209                currentContext = null;
210        }
211}