• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / automatalib / 13138848026

04 Feb 2025 02:53PM UTC coverage: 92.108% (+2.2%) from 89.877%
13138848026

push

github

mtf90
[maven-release-plugin] prepare release automatalib-0.12.0

16609 of 18032 relevant lines covered (92.11%)

1.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.88
/visualization/dot-visualizer/src/main/java/net/automatalib/visualization/dot/DOT.java
1
/* Copyright (C) 2013-2025 TU Dortmund University
2
 * This file is part of AutomataLib <https://automatalib.net>.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.automatalib.visualization.dot;
17

18
import java.awt.Desktop;
19
import java.awt.image.BufferedImage;
20
import java.io.File;
21
import java.io.IOException;
22
import java.io.InputStream;
23
import java.io.Reader;
24
import java.io.StringReader;
25
import java.nio.file.FileSystems;
26
import java.nio.file.Path;
27
import java.util.List;
28

29
import javax.imageio.ImageIO;
30

31
import net.automatalib.common.setting.AutomataLibProperty;
32
import net.automatalib.common.setting.AutomataLibSettings;
33
import net.automatalib.common.util.IOUtil;
34
import net.automatalib.common.util.Pair;
35
import net.automatalib.common.util.process.ProcessUtil;
36
import net.automatalib.visualization.dot.DOTMultiDialog.ThrowableExtractor;
37
import org.slf4j.Logger;
38
import org.slf4j.LoggerFactory;
39

40
/**
41
 * Utility class to simplify operating the GraphVIZ "dot" utility. Please note that all the provided methods require
42
 * GraphVIZ to be installed on the system, and that the "dot" binary resides in the execution path.
43
 */
44
public final class DOT {
45

46
    private static final Logger LOGGER = LoggerFactory.getLogger(DOT.class);
2✔
47

48
    private static String dotExe;
49

50
    static {
51
        final AutomataLibSettings settings = AutomataLibSettings.getInstance();
2✔
52

53
        final String dotExePath = settings.getProperty(AutomataLibProperty.DOT_EXE_DIR);
2✔
54
        final String dotExeName = settings.getProperty(AutomataLibProperty.DOT_EXE_NAME, "dot");
2✔
55

56
        String dotExe = dotExeName;
2✔
57
        if (dotExePath != null) {
2✔
58
            Path dotBasePath = FileSystems.getDefault().getPath(dotExePath);
×
59
            Path resolvedDotPath = dotBasePath.resolve(dotExeName);
×
60
            dotExe = resolvedDotPath.toString();
×
61
        }
62

63
        DOT.dotExe = dotExe;
2✔
64
    }
2✔
65

66
    private DOT() {}
67

68
    /**
69
     * Explicitly sets the path to the DOT utility executable.
70
     *
71
     * @param dotExe
72
     *         the path to the DOT utility executable
73
     */
74
    public static void setDotExe(String dotExe) {
75
        DOT.dotExe = dotExe;
×
76
    }
×
77

78
    /**
79
     * Checks whether the DOT utility can be successfully invoked.
80
     *
81
     * @return whether the DOT utility can be successfully invoked
82
     */
83
    public static boolean checkUsable() {
84
        try {
85
            final String[] dotCheck = buildRawDOTCommand("-V");
2✔
86
            return ProcessUtil.invokeProcess(dotCheck) == 0;
2✔
87
        } catch (IOException | InterruptedException ex) {
×
88
            LOGGER.error("Error executing dot", ex);
×
89
        }
90
        return false;
×
91
    }
92

93
    /**
94
     * Invokes the DOT utility on a file. Convenience method for {@link #runDOT(Reader, String, String...)}.
95
     *
96
     * @param dotFile
97
     *         the file from which the GraphVIZ description is obtained
98
     * @param format
99
     *         the output format, as understood by the dot utility, e.g., png, ps, etc.
100
     * @param additionalOpts
101
     *         additional parameters passed to the dot invocation
102
     *
103
     * @return an input stream from which the image data can be read
104
     *
105
     * @throws IOException
106
     *         if reading from the file or the call to the DOT utility fails.
107
     */
108
    public static InputStream runDOT(File dotFile, String format, String... additionalOpts) throws IOException {
109
        return runDOT(IOUtil.asBufferedUTF8Reader(dotFile), format, additionalOpts);
×
110
    }
111

112
    /**
113
     * Invokes the GraphVIZ DOT utility for rendering graphs.
114
     *
115
     * @param r
116
     *         the reader from which the GraphVIZ description is obtained
117
     * @param format
118
     *         the output format, as understood by the dot utility, e.g., png, ps, etc.
119
     * @param additionalOpts
120
     *         additional parameters passed to the dot invocation
121
     *
122
     * @return an input stream from which the image data can be read
123
     *
124
     * @throws IOException
125
     *         if reading from the reader or the call to the DOT utility fails.
126
     */
127
    public static InputStream runDOT(Reader r, String format, String... additionalOpts) throws IOException {
128
        final String[] dotCommand = buildDOTCommand(format, additionalOpts);
2✔
129

130
        final Process p = ProcessUtil.buildProcess(dotCommand, r, null, LOGGER::warn);
2✔
131

132
        return p.getInputStream();
2✔
133
    }
134

135
    /**
136
     * Invokes the DOT utility on a string. Convenience method for {@link #runDOT(Reader, String, String...)}.
137
     *
138
     * @param dotText
139
     *         the string from which the GraphVIZ description is obtained
140
     * @param format
141
     *         the output format, as understood by the dot utility, e.g., png, ps, etc.
142
     * @param additionalOpts
143
     *         additional parameters passed to the dot invocation
144
     *
145
     * @return an input stream from which the image data can be read
146
     *
147
     * @throws IOException
148
     *         if the call to the DOT utility fails.
149
     */
150
    public static InputStream runDOT(String dotText, String format, String... additionalOpts) throws IOException {
151
        try (StringReader sr = new StringReader(dotText)) {
×
152
            return runDOT(sr, format, additionalOpts);
×
153
        }
154
    }
155

156
    /**
157
     * Invokes the DOT utility on a file, producing an output file. Convenience method for
158
     * {@link #runDOT(Reader, String, File)}.
159
     *
160
     * @param dotFile
161
     *         the file from which the GraphVIZ description is read
162
     * @param format
163
     *         the output format to produce
164
     * @param out
165
     *         the file to which the output is written
166
     *
167
     * @throws IOException
168
     *         if reading from the file, the call to the DOT utility, or writing to the file fails.
169
     */
170
    public static void runDOT(File dotFile, String format, File out) throws IOException {
171
        runDOT(IOUtil.asBufferedUTF8Reader(dotFile), format, out);
2✔
172
    }
2✔
173

174
    /**
175
     * Invokes the GraphVIZ DOT utility for rendering graphs, writing output to the specified file.
176
     *
177
     * @param r
178
     *         the reader from which the GraphVIZ description is read
179
     * @param format
180
     *         the output format to produce
181
     * @param out
182
     *         the file to which the output is written.
183
     *
184
     * @throws IOException
185
     *         if reading from the reader, the call to the DOT utility, or writing to the file fails.
186
     */
187
    public static void runDOT(Reader r, String format, File out) throws IOException {
188
        final String[] dotCommand = buildDOTCommand(format, "-o" + out.getAbsolutePath());
2✔
189

190
        try {
191
            ProcessUtil.invokeProcess(dotCommand, r, LOGGER::warn);
2✔
192
        } catch (InterruptedException ex) {
×
193
            LOGGER.error("Interrupted while waiting for 'dot' process to exit.", ex);
×
194
        }
2✔
195
    }
2✔
196

197
    /**
198
     * Invokes the DOT utility on a string, producing an output file. Convenience method for
199
     * {@link #runDOT(Reader, String, File)}.
200
     *
201
     * @param dotText
202
     *         the string from which the GraphVIZ description is read
203
     * @param format
204
     *         the output format to produce
205
     * @param out
206
     *         the file to which the output is written
207
     *
208
     * @throws IOException
209
     *         if the call to the DOT utility or writing to the file fails.
210
     */
211
    public static void runDOT(String dotText, String format, File out) throws IOException {
212
        runDOT(new StringReader(dotText), format, out);
×
213
    }
×
214

215
    /**
216
     * Renders a GraphVIZ description from a file, using an external program for displaying. Convenience method for
217
     * {@link #renderDOTExternal(Reader, String)}.
218
     *
219
     * @param dotFile
220
     *         the file from which the GraphVIZ description is read
221
     * @param format
222
     *         the output format, as understood by the dot utility, e.g., png, ps, etc.
223
     *
224
     * @throws IOException
225
     *         if reading from the file or the call to the DOT utility fails.
226
     */
227
    public static void renderDOTExternal(File dotFile, String format) throws IOException {
228
        renderDOTExternal(IOUtil.asBufferedUTF8Reader(dotFile), format);
×
229
    }
×
230

231
    /**
232
     * Renders a GraphVIZ description, using an external program for displaying. The program is determined by the
233
     * system's file type associations, using the {@link Desktop#open(File)} method.
234
     *
235
     * @param r
236
     *         the reader from which the GraphVIZ description is read
237
     * @param format
238
     *         the output format, as understood by the dot utility, e.g., png, ps, etc.
239
     *
240
     * @throws IOException
241
     *         if reading from the reader or the call to the DOT utility fails.
242
     */
243
    public static void renderDOTExternal(Reader r, String format) throws IOException {
244
        final File image = File.createTempFile("dot", format);
×
245
        runDOT(r, format, image);
×
246
        Desktop.getDesktop().open(image);
×
247
    }
×
248

249
    /**
250
     * Renders a GraphVIZ description from a string, using an external program for displaying. Convenience method for
251
     * {@link #renderDOTExternal(Reader, String)}.
252
     *
253
     * @param dotText
254
     *         the string from which the GraphVIZ description is read.
255
     * @param format
256
     *         the output format, as understood by the dot utility, e.g., png, ps, etc.
257
     *
258
     * @throws IOException
259
     *         if the call to the DOT utility fails.
260
     */
261
    public static void renderDOTExternal(String dotText, String format) throws IOException {
262
        renderDOTExternal(new StringReader(dotText), format);
×
263
    }
×
264

265
    /**
266
     * Renders a GraphVIZ description from a {@link File} and displays it in a Swing window. Convenience method for
267
     * {@link #renderDOT(Reader, boolean)}.
268
     *
269
     * @param dotFile
270
     *         the file from which the description is obtained
271
     * @param modal
272
     *         whether the dialog should be modal
273
     *
274
     * @throws IOException
275
     *         if reading from the file or the call to the DOT utility fails.
276
     */
277
    public static void renderDOT(File dotFile, boolean modal) throws IOException {
278
        renderDOT(IOUtil.asBufferedUTF8Reader(dotFile), modal);
×
279
    }
×
280

281
    /**
282
     * Renders a GraphVIZ description from a {@link Reader} and displays it in a Swing window. Convenience method for
283
     * {@link #renderDOT(String, boolean)}.
284
     *
285
     * @param r
286
     *         the reader from which the description is obtained
287
     * @param modal
288
     *         whether the dialog should be modal
289
     *
290
     * @throws IOException
291
     *         if reading from the reader or the call to the DOT utility fails.
292
     */
293
    public static void renderDOT(Reader r, boolean modal) throws IOException {
294
        renderDOT(IOUtil.toString(r), modal);
×
295
    }
×
296

297
    /**
298
     * Renders a GraphVIZ description and displays it in a Swing window.
299
     *
300
     * @param dotText
301
     *         the string from which the description is obtained
302
     * @param modal
303
     *         whether the dialog should be modal
304
     *
305
     * @throws IOException
306
     *         if the call to the DOT utility fails.
307
     */
308
    public static void renderDOT(String dotText, boolean modal) throws IOException {
309
        new DOTDialog(dotText, modal);
2✔
310
    }
2✔
311

312
    /**
313
     * Renders multiple (named) GraphVIZ descriptions from {@link File}s and displays them in a Swing window.
314
     * Convenience method for {@link #renderDOTStrings(List, boolean)}.
315
     *
316
     * @param files
317
     *         the file from which the description is obtained. The first element of the {@link Pair} should contain the
318
     *         name, the second element should contain the DOT file.
319
     * @param modal
320
     *         whether the dialog should be modal
321
     *
322
     * @throws IOException
323
     *         if reading from the files or the calls to the DOT utility fail.
324
     */
325
    public static void renderDOTFiles(List<Pair<String, File>> files, boolean modal) throws IOException {
326
        renderDOTInternal(files, modal, f -> IOUtil.toString(IOUtil.asBufferedUTF8Reader(f)));
×
327
    }
×
328

329
    /**
330
     * Renders multiple (named) GraphVIZ descriptions from {@link Reader}s and displays them in a Swing window.
331
     * Convenience method for {@link #renderDOTStrings(List, boolean)}.
332
     *
333
     * @param readers
334
     *         the readers from which the description is obtained. The first element of the {@link Pair} should contain
335
     *         the name, the second element should contain a reader for the DOT definition.
336
     * @param modal
337
     *         whether the dialog should be modal
338
     *
339
     * @throws IOException
340
     *         if reading from the readers or the calls to the DOT utility fail.
341
     */
342
    public static void renderDOTReaders(List<Pair<String, Reader>> readers, boolean modal) throws IOException {
343
        renderDOTInternal(readers, modal, IOUtil::toString);
2✔
344
    }
2✔
345

346
    /**
347
     * Renders multiple (named) GraphVIZ descriptions and displays them in a Swing window.
348
     *
349
     * @param dotTexts
350
     *         the strings from which the description is obtained. The first element of the {@link Pair} should contain
351
     *         the name, the second element should contain the DOT code.
352
     * @param modal
353
     *         whether the dialog should be modal
354
     *
355
     * @throws IOException
356
     *         if the calls to the DOT utility fail.
357
     */
358
    public static void renderDOTStrings(List<Pair<String, String>> dotTexts, boolean modal) throws IOException {
359
        renderDOTInternal(dotTexts, modal, s -> s);
2✔
360
    }
2✔
361

362
    private static <I> void renderDOTInternal(List<Pair<String, I>> dots,
363
                                              boolean modal,
364
                                              ThrowableExtractor<I, String> extractor) throws IOException {
365
        new DOTMultiDialog<>(dots, modal, extractor);
2✔
366
    }
2✔
367

368
    /**
369
     * Reads a DOT description from a file and returns the PNG rendering result as a {@link BufferedImage}.
370
     *
371
     * @param dotFile
372
     *         the file containing the DOT description
373
     *
374
     * @return the rendering result
375
     *
376
     * @throws IOException
377
     *         if reading from the file or the call to the DOT utility fails.
378
     */
379
    public static BufferedImage renderDOTImage(File dotFile) throws IOException {
380
        return renderDOTImage(IOUtil.asBufferedUTF8Reader(dotFile));
×
381
    }
382

383
    /**
384
     * Reads a DOT description from a reader and returns the PNG rendering result as a {@link BufferedImage}.
385
     *
386
     * @param dotReader
387
     *         the reader from which to read the description
388
     *
389
     * @return the rendering result
390
     *
391
     * @throws IOException
392
     *         if reading from the reader or the call to the DOT utility fails.
393
     */
394
    public static BufferedImage renderDOTImage(Reader dotReader) throws IOException {
395
        try (InputStream pngIs = runDOT(dotReader, "png")) {
2✔
396
            return ImageIO.read(pngIs);
2✔
397
        }
398
    }
399

400
    /**
401
     * Reads a DOT description from a string and returns the PNG rendering result as a {@link BufferedImage}.
402
     *
403
     * @param dotText
404
     *         the DOT description
405
     *
406
     * @return the rendering result
407
     *
408
     * @throws IOException
409
     *         if the call to the DOT utility fails.
410
     */
411
    public static BufferedImage renderDOTImage(String dotText) throws IOException {
412
        return renderDOTImage(new StringReader(dotText));
2✔
413
    }
414

415
    private static String[] buildRawDOTCommand(String... opts) {
416
        String[] dotArgs = new String[1 + opts.length];
2✔
417
        dotArgs[0] = dotExe;
2✔
418
        System.arraycopy(opts, 0, dotArgs, 1, opts.length);
2✔
419

420
        return dotArgs;
2✔
421
    }
422

423
    private static String[] buildDOTCommand(String format, String... additionalOpts) {
424
        String[] dotArgs = new String[1 + additionalOpts.length];
2✔
425
        dotArgs[0] = "-T" + format;
2✔
426
        System.arraycopy(additionalOpts, 0, dotArgs, 1, additionalOpts.length);
2✔
427

428
        return buildRawDOTCommand(dotArgs);
2✔
429
    }
430

431
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc