// -------------------------------------------------------------------------------------------------------------------- // // Jamie Dixon // // // Defines the GraphGeneration type. // // -------------------------------------------------------------------------------------------------------------------- namespace GraphVizWrapper { using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Reflection; using Commands; using Queries; /// /// The main entry class for the wrapper. /// public class GraphGeneration : IGraphGeneration { private const string ProcessFolder = "GraphViz"; private const string ConfigFile = "config6"; private readonly IGetStartProcessQuery startProcessQuery; private readonly IGetProcessStartInfoQuery getProcessStartInfoQuery; private readonly IRegisterLayoutPluginCommand registerLayoutPlugincommand; private Enums.RenderingEngine renderingEngine; private String graphvizPath = null; public GraphGeneration(IGetStartProcessQuery startProcessQuery, IGetProcessStartInfoQuery getProcessStartInfoQuery, IRegisterLayoutPluginCommand registerLayoutPlugincommand) { this.startProcessQuery = startProcessQuery; this.getProcessStartInfoQuery = getProcessStartInfoQuery; this.registerLayoutPlugincommand = registerLayoutPlugincommand; this.graphvizPath = ConfigurationManager.AppSettings["graphVizLocation"]; } #region Properties public String GraphvizPath { get { return graphvizPath ?? AssemblyDirectory + "/" + ProcessFolder; } set { if (value != null && value.Trim().Length > 0) { String path = value.Replace("\\", "/"); graphvizPath = path.EndsWith("/") ? path.Substring(0, path.LastIndexOf('/')) : path; } else { graphvizPath = null; } } } public Enums.RenderingEngine RenderingEngine { get { return this.renderingEngine; } set { this.renderingEngine = value; } } private string ConfigLocation { get { return GraphvizPath + "/" + ConfigFile; } } private bool ConfigExists { get { return File.Exists(ConfigLocation); } } private static string AssemblyDirectory { get { var uriBuilder = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase); string path = Uri.UnescapeDataString(uriBuilder.Path); return path.Substring(0, path.LastIndexOf('/')); } } private string FilePath { get { return GraphvizPath + "/" + this.GetRenderingEngine(this.renderingEngine) + ".exe"; } } #endregion /// /// Generates a graph based on the dot file passed in. /// /// /// A string representation of a dot file. /// /// /// The type of file to be returned. /// /// /// a byte array. /// public byte[] GenerateGraph(string dotFile, Enums.GraphReturnType returnType) { byte[] output; if (!ConfigExists) { this.registerLayoutPlugincommand.Invoke(FilePath, this.RenderingEngine); } string fileType = this.GetReturnType(returnType); var processStartInfo = this.GetProcessStartInfo(fileType); using (var process = this.startProcessQuery.Invoke(processStartInfo)) { process.BeginErrorReadLine(); using (var stdIn = process.StandardInput) { stdIn.WriteLine(dotFile); } using (var stdOut = process.StandardOutput) { var baseStream = stdOut.BaseStream; output = this.ReadFully(baseStream); } } return output; } #region Private Methods private System.Diagnostics.ProcessStartInfo GetProcessStartInfo(string returnType) { return this.getProcessStartInfoQuery.Invoke(new ProcessStartInfoWrapper { FileName = this.FilePath, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, Arguments = "-v -o -T" + returnType, CreateNoWindow = true }); } private byte[] ReadFully(Stream input) { using (var ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } private string GetReturnType(Enums.GraphReturnType returnType) { var nameValues = new Dictionary { { Enums.GraphReturnType.Png, "png" }, { Enums.GraphReturnType.Jpg, "jpg" }, { Enums.GraphReturnType.Pdf, "pdf" }, { Enums.GraphReturnType.Plain, "plain" }, { Enums.GraphReturnType.PlainExt, "plain-ext" }, { Enums.GraphReturnType.Svg, "svg" } }; return nameValues[returnType]; } private string GetRenderingEngine(Enums.RenderingEngine renderingType) { var nameValues = new Dictionary { { Enums.RenderingEngine.Dot, "dot" }, { Enums.RenderingEngine.Neato, "neato" }, { Enums.RenderingEngine.Twopi, "twopi" }, { Enums.RenderingEngine.Circo, "circo" }, { Enums.RenderingEngine.Fdp, "fdp" }, { Enums.RenderingEngine.Sfdp, "sfdp" }, { Enums.RenderingEngine.Patchwork, "patchwork" }, { Enums.RenderingEngine.Osage, "osage" } }; return nameValues[renderingType]; } #endregion } }