All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.conqat.lib.commons.graph.GraphvizGenerator Maven / Gradle / Ivy

There is a newer version: 2024.7.2
Show newest version
/*
 * 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;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy