1 /*
2 * Copyright (c) 2003-2008, by Henrik Arro and Contributors
3 *
4 * This file is part of JSeq, a tool to automatically create
5 * sequence diagrams by tracing program execution.
6 *
7 * See <http://jseq.sourceforge.net> for more information.
8 *
9 * JSeq is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of
12 * the License, or (at your option) any later version.
13 *
14 * JSeq is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with JSeq. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 package th.co.edge.jseq.argouml;
24
25 import java.io.File;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.OutputStreamWriter;
29 import java.io.StringWriter;
30 import java.io.Writer;
31 import java.util.List;
32 import java.util.zip.ZipEntry;
33 import java.util.zip.ZipOutputStream;
34
35 import org.w3c.dom.Document;
36
37 import ru.novosoft.uml.model_management.MModel;
38 import ru.novosoft.uml.xmi.IncompleteXMIException;
39 import ru.novosoft.uml.xmi.XMIWriter;
40 import th.co.edge.jseq.Diagram;
41 import th.co.edge.jseq.util.XMLUtil;
42
43 /**
44 * An <code>ArgoUMLDiagram</code> is a <code>Diagram</code> that can be used
45 * to generate sequence diagrams in .zargo format, readable by the tool <a
46 * href="http://argouml.tigris.org/" target="new">ArgoUML</a>.
47 *
48 * <p>
49 * The current version has only been verified to work with version 0.12 of
50 * ArgoUML, and it is a known problem that it does not work with version 0.24 (<a
51 * href=https://sourceforge.net/tracker/index.php?func=detail&aid=2046485&group_id=230519&atid=1080391"
52 * target="new">SourceForge issue 2046485</a>).
53 */
54 public class ArgoUMLDiagram implements Diagram {
55 private Document argo;
56 private MModel model;
57 private List<SequenceDiagram> diagrams;
58
59 /**
60 * Creates a new <code>ArgoUMLDiagram</code>.
61 *
62 * @param argo
63 * an XML <code>Document</code> defining the contents of this
64 * file
65 * @param model
66 * an <code>MModel</code> representation of an XMI document
67 * defining the parts of this UML model
68 * @param diagrams
69 * a list of <code>SequenceDiagram</code>s, one per root
70 * activation
71 */
72 public ArgoUMLDiagram(Document argo, MModel model,
73 List<SequenceDiagram> diagrams) {
74 this.argo = argo;
75 this.model = model;
76 this.diagrams = diagrams;
77 }
78
79 /**
80 * Writes this <code>ArgoUMLDiagram</code> to file in .zargo format, that
81 * is, as a zipped set of XML model files.
82 *
83 * @param file
84 * the <code>File</code> to write to
85 *
86 * @throws IOException
87 * if the diagram could not be saved
88 */
89 public void save(File file) throws IOException {
90 Writer writer = null;
91 try {
92 ZipOutputStream zip =
93 new ZipOutputStream(new FileOutputStream(file));
94 writer = new OutputStreamWriter(zip);
95 writeXML(argo, "Untitled.argo", zip, writer);
96 writeModel(model, "Untitled.xmi", zip, writer);
97 int n = 0;
98 for (SequenceDiagram diagram : diagrams) {
99 String name = "SequenceDiagram" + (n++) + ".pgml";
100 writeXML(diagram.getDocument(), name, zip, writer);
101 }
102 } finally {
103 if (writer != null) {
104 try {
105 writer.close();
106 } catch (IOException e) {
107 System.err.println(e);
108 }
109 }
110 }
111 }
112
113 private void writeXML(Document xml, String name, ZipOutputStream zip,
114 Writer writer) throws IOException {
115 zip.putNextEntry(new ZipEntry(name));
116 writer.write(XMLUtil.toString(xml));
117 writer.flush();
118 zip.closeEntry();
119 }
120
121 private void writeModel(MModel mModel, String name, ZipOutputStream zip,
122 Writer writer) throws IOException {
123 // It is necessary to write XMI to a StringWriter first, because
124 // XMIWriter.gen seems to close the stream, making it impossible
125 // to add more ZIP entries.
126 StringWriter stringWriter = new StringWriter();
127 XMIWriter xmiWriter = new XMIWriter(mModel, stringWriter);
128 try {
129 xmiWriter.gen();
130 } catch (IncompleteXMIException e) {
131 e.printStackTrace();
132 throw new IOException("Writing XMI failed: " + e.getMessage());
133 }
134 zip.putNextEntry(new ZipEntry(name));
135 writer.write(stringWriter.toString());
136 writer.flush();
137 zip.closeEntry();
138 }
139 }