org.conqat.lib.commons.graph.GraphvizGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teamscale-lib-commons Show documentation
Show all versions of teamscale-lib-commons Show documentation
Provides common utility functions
/*
* Copyright (c) CQSE GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conqat.lib.commons.graph;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.conqat.lib.commons.io.ProcessUtils;
/**
* Java interface to the Graphviz graph drawing toolkit.
*
* @author Florian Deissenboeck
* @author Benjamin Hummel
*/
public class GraphvizGenerator {
/** Name of the dot executable. */
public static final String DOT_EXECUTABLE = "dot";
/**
* Export a graph to a file.
*
* @param description
* the graph description
* @param file
* the file to export to.
* @param format
* the export format.
* @throws IOException
* if an I/O problem occurrs.
* @throws GraphvizException
* if Graphviz produced an error (exit code != 0)
*/
public void generateFile(String description, File file, EGraphvizOutputFormat format)
throws IOException, GraphvizException {
runDot(description, ProcessUtils.defaultStreamConsumer(false), "-T" + format.name().toLowerCase(), "-o" + file);
}
/**
* Export a graph to a file and return the HTML image map code.
*
* @param description
* the graph description
* @param file
* the file to export to.
* @param format
* the export format.
* @return the generated image map. These are only area-tags. The map tags including the name of the
* map must be created by the calling application.
* @throws IOException
* if an I/O problem occurrs.
* @throws GraphvizException
* if Graphviz produced an error (exit code != 0)
*/
public String generateFileAndImageMap(String description, File file, EGraphvizOutputFormat format)
throws IOException, GraphvizException {
ProcessUtils.DefaultStreamConsumer stdoutConsumer = ProcessUtils.defaultStreamConsumer(true);
runDot(description, stdoutConsumer, "-T" + format.name().toLowerCase(), "-o" + file, "-Tcmap");
return stdoutConsumer.getContent();
}
/**
* Generate an image from a graph description. This uses Graphviz to generate a PNG image of the
* graph and javax.imageio to create the image object. All communication with Graphviz is handled
* via streams so no temporary files are used.
*
* @param description
* the graph description.
* @return the image
* @throws IOException
* if an I/O problem occurrs.
* @throws GraphvizException
* if Graphviz produced an error (exit code != 0)
*/
public BufferedImage generateImage(String description) throws IOException, GraphvizException {
ImageReader imageReader = new ImageReader();
runDot(description, imageReader, "-Tpng");
return imageReader.getImage();
}
/**
* Executes DOT, feeding in the provided graph description. DOT errors are handled in this method.
*
* @param description
* the graph description.
* @param arguments
* the arguments passed to DOT.
* @throws IOException
* if an I/O problem occurrs.
* @throws GraphvizException
* if Graphviz produced an error (exit code != 0)
*/
private void runDot(String description, ProcessUtils.IStreamConsumer stdoutConsumer, String... arguments)
throws IOException, GraphvizException {
String[] completeArguments = new String[arguments.length + 1];
completeArguments[0] = DOT_EXECUTABLE;
System.arraycopy(arguments, 0, completeArguments, 1, arguments.length);
ProcessBuilder builder = new ProcessBuilder(completeArguments);
ProcessUtils.DefaultStreamConsumer stderrConsumer = ProcessUtils.defaultStreamConsumer(true);
int exitCode = ProcessUtils.execute(builder, description, -1, stdoutConsumer, stderrConsumer);
if (exitCode != 0
// recent versions do not exit with non-null on syntax errors
|| stderrConsumer.getContent().contains("syntax error")) {
throw new GraphvizException(stderrConsumer.getContent());
}
}
/** A stream reader for reading an image. */
private static class ImageReader implements ProcessUtils.IStreamConsumer {
/** The read image */
private BufferedImage image;
@Override
public synchronized void consume(InputStream stream) throws IOException {
image = ImageIO.read(stream);
}
public synchronized BufferedImage getImage() {
return image;
}
}
}