package org.jboss.windup.reporting.renderer.dot;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.windup.reporting.renderer.GraphDataSerializer;
import org.jboss.windup.reporting.renderer.dot.DotConstants.DotGraphType;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
public class DotWriter implements GraphDataSerializer
{
private final Graph graph;
private String graphName = "G";
private String vertexLabelProperty = "label";
private DotGraphType graphType = DotGraphType.DIGRAPH;
private String fontSize = "12pt";
private String edgeLabel = "";
public DotWriter(Graph graph)
{
this.graph = graph;
}
public DotWriter(Graph graph, String graphName, String vertexLabelProperty, String edgeLabel,
DotGraphType graphType, String fontSize)
{
this.graph = graph;
this.graphName = graphName;
this.fontSize = fontSize;
this.vertexLabelProperty = vertexLabelProperty;
this.graphType = graphType;
this.edgeLabel = edgeLabel;
}
public void writeGraph(OutputStream os) throws IOException
{
writeGraphTag(os);
}
private void writeGraphTag(OutputStream os) throws IOException
{
String name = this.getDotSafeName(graphName);
IOUtils.write(graphType.getName() + " " + name + "{" + DotConstants.NL, os);
writeGraphNodes(os);
writeGraphEdges(os);
IOUtils.write("}", os);
}
private void writeGraphEdges(OutputStream os) throws IOException
{
for (Edge edge : graph.getEdges())
{
String label = edgeLabel;
String source = "" + edge.getVertex(Direction.OUT).getId().toString();
String target = "" + edge.getVertex(Direction.IN).getId().toString();
writeGraphEdge(label, source, target, os);
}
}
private void writeGraphEdge(String label, String source, String target, OutputStream os) throws IOException
{
final String startTag = getDotSafeName(source) + graphType.getEdge() + getDotSafeName(target);
final String endTag = DotConstants.END_LINE;
IOUtils.write(startTag, os);
if (StringUtils.isNotBlank(label))
{
writeOptions(os, new String[] { "label", label }, new String[] { "fontsize", fontSize });
}
IOUtils.write(endTag, os);
}
private void writeGraphNode(String id, String label, OutputStream os) throws IOException
{
final String tag = DotConstants.INDENT + getDotSafeName(id) + "[label = \"" + label + "\", fontsize = \""
+ fontSize + "\"]" + DotConstants.END_LINE;
IOUtils.write(tag, os);
}
private void writeGraphNodes(OutputStream os) throws IOException
{
// iterate the nodes.
for (Vertex vertex : graph.getVertices())
{
String id = "" + vertex.getId().toString();
String label = vertex.getProperty(vertexLabelProperty);
if (StringUtils.isBlank(label))
{
label = vertex.toString();
}
writeGraphNode(id, label, os);
}
}
private void writeOptions(OutputStream os, String[]... options) throws IOException
{
Map<String, String> map = new HashMap<>();
for (String[] option : options)
{
String key = option[0];
String value = option[1];
map.put(key, value);
}
writeOptions(map, os);
}
private void writeOptions(Map<String, String> options, OutputStream os) throws IOException
{
if (options == null || options.isEmpty())
{
return;
}
IOUtils.write("[", os);
StringBuilder builder = new StringBuilder();
for (String key : options.keySet())
{
builder.append(key + "=\"" + options.get(key) + "\", ");
}
String tag = builder.toString().trim();
tag = StringUtils.removeEnd(tag, ",");
IOUtils.write(tag, os);
IOUtils.write("]", os);
}
private String getDotSafeName(String inName)
{
String name = null;
if (StringUtils.isAlphanumeric(inName))
{
name = inName;
}
else
{
name = "\"" + inName + "\"";
}
return name;
}
}