1 | /* | |
2 | * Copyright 2006 - 2013 | |
3 | * Stefan Balev <stefan.balev@graphstream-project.org> | |
4 | * Julien Baudry <julien.baudry@graphstream-project.org> | |
5 | * Antoine Dutot <antoine.dutot@graphstream-project.org> | |
6 | * Yoann Pign�� <yoann.pigne@graphstream-project.org> | |
7 | * Guilhelm Savin <guilhelm.savin@graphstream-project.org> | |
8 | * | |
9 | * This file is part of GraphStream <http://graphstream-project.org>. | |
10 | * | |
11 | * GraphStream is a library whose purpose is to handle static or dynamic | |
12 | * graph, create them from scratch, file or any source and display them. | |
13 | * | |
14 | * This program is free software distributed under the terms of two licenses, the | |
15 | * CeCILL-C license that fits European law, and the GNU Lesser General Public | |
16 | * License. You can use, modify and/ or redistribute the software under the terms | |
17 | * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following | |
18 | * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by | |
19 | * the Free Software Foundation, either version 3 of the License, or (at your | |
20 | * option) any later version. | |
21 | * | |
22 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | |
23 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | |
24 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU Lesser General Public License | |
27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
28 | * | |
29 | * The fact that you are presently reading this means that you have had | |
30 | * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. | |
31 | */ | |
32 | package org.graphstream.stream.file; | |
33 | ||
34 | import java.io.IOException; | |
35 | import java.io.PrintWriter; | |
36 | ||
37 | /** | |
38 | * Graph writer for the GraphViz DOT format. | |
39 | */ | |
40 | public class FileSinkDOT extends FileSinkBase { | |
41 | // Attribute | |
42 | ||
43 | /** | |
44 | * The output. | |
45 | */ | |
46 | protected PrintWriter out; | |
47 | ||
48 | /** | |
49 | * The graph name (set as soon as known). | |
50 | */ | |
51 | protected String graphName = ""; | |
52 | ||
53 | /** | |
54 | * Is the graph directed ? | |
55 | */ | |
56 | protected boolean digraph; | |
57 | ||
58 | /** | |
59 | * What element ?. | |
60 | */ | |
61 | protected enum What { | |
62 | NODE, EDGE, OTHER | |
63 | }; | |
64 | ||
65 | /** | |
66 | * Build a new DOT sink to export undirected graph. | |
67 | */ | |
68 | public FileSinkDOT() { | |
69 | this(false); | |
70 | } | |
71 | ||
72 | /** | |
73 | * Build a new DOT sink specifying if the graph is directed or not. | |
74 | * | |
75 | * @param digraph | |
76 | * true if the graph is directed | |
77 | */ | |
78 | public FileSinkDOT(boolean digraph) { | |
79 | this.digraph = digraph; | |
80 | } | |
81 | ||
82 | // Command | |
83 | ||
84 | /** | |
85 | * Set flag indicating if exported graph is directed or not. | |
86 | * | |
87 | * @param digraph | |
88 | * true is exported graph is directed | |
89 | */ | |
90 | public void setDirected(boolean digraph) { | |
91 | this.digraph = digraph; | |
92 | } | |
93 | ||
94 | /** | |
95 | * Get the flag indicating if exported graph is directed or not. | |
96 | * | |
97 | * @return true if exported graph is directed | |
98 | */ | |
99 | public boolean isDirected() { | |
100 |
1
1. isDirected : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return digraph; |
101 | } | |
102 | ||
103 | @Override | |
104 | protected void outputHeader() throws IOException { | |
105 | out = (PrintWriter) output; | |
106 |
1
1. outputHeader : negated conditional → NO_COVERAGE |
out.printf("%s {%n", digraph ? "digraph" : "graph"); |
107 | ||
108 |
2
1. outputHeader : changed conditional boundary → NO_COVERAGE 2. outputHeader : negated conditional → NO_COVERAGE |
if (graphName.length() > 0) |
109 | out.printf("\tgraph [label=%s];%n", graphName); | |
110 | } | |
111 | ||
112 | @Override | |
113 | protected void outputEndOfFile() throws IOException { | |
114 | out.printf("}%n"); | |
115 | } | |
116 | ||
117 | public void edgeAttributeAdded(String graphId, long timeId, String edgeId, | |
118 | String attribute, Object value) { | |
119 | // NOP | |
120 | } | |
121 | ||
122 | public void edgeAttributeChanged(String graphId, long timeId, | |
123 | String edgeId, String attribute, Object oldValue, Object newValue) { | |
124 | // NOP | |
125 | } | |
126 | ||
127 | public void edgeAttributeRemoved(String graphId, long timeId, | |
128 | String edgeId, String attribute) { | |
129 | // NOP | |
130 | } | |
131 | ||
132 | public void graphAttributeAdded(String graphId, long timeId, | |
133 | String attribute, Object value) { | |
134 | out | |
135 | .printf("\tgraph [ %s ];%n", outputAttribute(attribute, value, | |
136 | true)); | |
137 | } | |
138 | ||
139 | public void graphAttributeChanged(String graphId, long timeId, | |
140 | String attribute, Object oldValue, Object newValue) { | |
141 | out.printf("\tgraph [ %s ];%n", outputAttribute(attribute, newValue, | |
142 | true)); | |
143 | } | |
144 | ||
145 | public void graphAttributeRemoved(String graphId, long timeId, | |
146 | String attribute) { | |
147 | // NOP | |
148 | } | |
149 | ||
150 | public void nodeAttributeAdded(String graphId, long timeId, String nodeId, | |
151 | String attribute, Object value) { | |
152 | out.printf("\t\"%s\" [ %s ];%n", nodeId, outputAttribute(attribute, | |
153 | value, true)); | |
154 | } | |
155 | ||
156 | public void nodeAttributeChanged(String graphId, long timeId, | |
157 | String nodeId, String attribute, Object oldValue, Object newValue) { | |
158 | out.printf("\t\"%s\" [ %s ];%n", nodeId, outputAttribute(attribute, | |
159 | newValue, true)); | |
160 | } | |
161 | ||
162 | public void nodeAttributeRemoved(String graphId, long timeId, | |
163 | String nodeId, String attribute) { | |
164 | // NOP | |
165 | } | |
166 | ||
167 | public void edgeAdded(String graphId, long timeId, String edgeId, | |
168 | String fromNodeId, String toNodeId, boolean directed) { | |
169 |
1
1. edgeAdded : negated conditional → NO_COVERAGE |
if (digraph) { |
170 | out.printf("\t\"%s\" -> \"%s\"", fromNodeId, toNodeId); | |
171 | ||
172 |
1
1. edgeAdded : negated conditional → NO_COVERAGE |
if (!directed) |
173 | out.printf(" -> \"%s\"", fromNodeId); | |
174 | ||
175 | out.printf("\n;"); | |
176 | } else | |
177 | out.printf("\t\"%s\" -- \"%s\";%n", fromNodeId, toNodeId); | |
178 | } | |
179 | ||
180 | public void edgeRemoved(String graphId, long timeId, String edgeId) { | |
181 | // NOP | |
182 | } | |
183 | ||
184 | public void graphCleared(String graphId, long timeId) { | |
185 | // NOP | |
186 | } | |
187 | ||
188 | public void nodeAdded(String graphId, long timeId, String nodeId) { | |
189 | out.printf("\t\"%s\";%n", nodeId); | |
190 | } | |
191 | ||
192 | public void nodeRemoved(String graphId, long timeId, String nodeId) { | |
193 | // NOP | |
194 | } | |
195 | ||
196 | public void stepBegins(String graphId, long timeId, double step) { | |
197 | // NOP | |
198 | } | |
199 | ||
200 | // Utility | |
201 | /* | |
202 | * protected void outputAttributes(Map<String, Object> attributes, What | |
203 | * what) throws IOException { out.printf(" ["); | |
204 | * | |
205 | * boolean first = true; | |
206 | * | |
207 | * for (String key : attributes.keySet()) { Object value = | |
208 | * attributes.get(key); | |
209 | * | |
210 | * if (what == What.NODE) { // if( ! nodeForbiddenAttrs.contains( key ) ) { | |
211 | * first = outputAttribute(key, value, first); } } else if (what == | |
212 | * What.EDGE) { // if( ! edgeForbiddenAttrs.contains( key ) ) { first = | |
213 | * outputAttribute(key, value, first); } } else { first = | |
214 | * outputAttribute(key, value, first); } | |
215 | * | |
216 | * } | |
217 | * | |
218 | * out.printf("]"); } | |
219 | */ | |
220 | protected String outputAttribute(String key, Object value, boolean first) { | |
221 | boolean quote = true; | |
222 | ||
223 |
1
1. outputAttribute : negated conditional → NO_COVERAGE |
if (value instanceof Number) |
224 | quote = false; | |
225 | ||
226 |
2
1. outputAttribute : negated conditional → NO_COVERAGE 2. outputAttribute : mutated return of Object value for org/graphstream/stream/file/FileSinkDOT::outputAttribute to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return String.format("%s\"%s\"=%s%s%s", first ? "" : ",", key, |
227 |
2
1. outputAttribute : negated conditional → NO_COVERAGE 2. outputAttribute : negated conditional → NO_COVERAGE |
quote ? "\"" : "", value, quote ? "\"" : ""); |
228 | } | |
229 | } | |
Mutations | ||
100 |
1.1 |
|
106 |
1.1 |
|
108 |
1.1 2.2 |
|
169 |
1.1 |
|
172 |
1.1 |
|
223 |
1.1 |
|
226 |
1.1 2.2 |
|
227 |
1.1 2.2 |