Skip to content
Snippets Groups Projects
Commit 758d6d83 authored by Sören Henning's avatar Sören Henning
Browse files

added DotWriter

parent d6531126
No related branches found
No related tags found
1 merge request!17Get impletemented stages and Java 8
package kieker.analysis.graph;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import kieker.analysis.graph.export.graphml.GraphMLExporter;
import kieker.analysis.graph.impl.GraphImpl;
import kieker.analysis.util.dot.DotWriter;
public class GraphTester {
......@@ -100,6 +105,28 @@ public class GraphTester {
// DotExporter dotExporter = new DotExporter();
// dotExporter.export(graph, System.out);
// Could be useful for testing
System.out.println("DotWriter Test");
DotWriter dotWriter = new DotWriter(new PrintWriter(System.out));
try {
dotWriter.start("G");
dotWriter.addGraphAttribute("rotate", "90");
Map<String, String> defaultNodeAttributes = new HashMap<>();
defaultNodeAttributes.put("style", "filled");
dotWriter.addDefaultNodeAttributes(defaultNodeAttributes);
Map<String, String> nodeAttributes = new HashMap<>();
nodeAttributes.put("label", "LABEL Title");
dotWriter.addNode("102", nodeAttributes);
dotWriter.addNode("#id", nodeAttributes);
dotWriter.addEdge("102", "#id", new HashMap<>());
dotWriter.finish();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package kieker.analysis.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Joiner;
/**
* Simple class for building and representing dot graph files.
*
* @author Sören Henning
*
*/
public class DotBuilder {
private final String start;
private final String end;
private final StringBuilder body = new StringBuilder();
private Map<String, String> defaultNodeProperties;
private Map<String, String> defaultEdgeProperties;
private Map<String, String> defaultProperties;
private static final String START_BRACKET = "{";
private static final String END_BRACKET = "}";
private static final String DEFAULT_GRAPH_NAME = "G";
private static final String DEFAULT_GRAPH_TYPE = "digraph";
public DotBuilder() {
this(DEFAULT_GRAPH_NAME);
}
public DotBuilder(final String graphName) {
this(graphName, DEFAULT_GRAPH_TYPE);
}
// TODO graphType has to be one of "graph", "digraph" or "subgraph" so maybe use an enum
public DotBuilder(final String graphName, final String graphType) {
start = graphType + " " + graphName + " " + START_BRACKET + "\n";
end = END_BRACKET;
}
// TODO Deprecated
public DotBuilder(final String name, final Map<String, String> defaultNodeProperties, final Map<String, String> defaultEdgeProperties) {
this(name);
this.defaultNodeProperties = defaultNodeProperties;
this.defaultEdgeProperties = defaultEdgeProperties;
}
// TODO Deprecated
public DotBuilder(final String name, final Map<String, String> defaultNodeProperties, final Map<String, String> defaultEdgeProperties,
final Map<String, String> defaultProperties) {
this(name, defaultNodeProperties, defaultEdgeProperties);
this.defaultProperties = defaultProperties;
}
public void setDefaultNodeProperties(final Map<String, String> defaultNodeProperties) {
this.defaultNodeProperties = defaultNodeProperties;
}
public void setDefaultEdgeProperties(final Map<String, String> defaultEdgeProperties) {
this.defaultEdgeProperties = defaultEdgeProperties;
}
public void setDefaultProperties(final Map<String, String> defaultProperties) {
this.defaultProperties = defaultProperties;
}
public String get() {
return start + body.toString() + end;
}
@Override
public String toString() {
return get();
}
public void addNode(final String id) {
addNode(id, new HashMap<>());
}
public void addNode(final String id, final String label) {
Map<String, String> properties = new HashMap<String, String>();
properties.put("label", label);
addNode(id, properties);
}
public void addNode(final String id, final Map<String, String> properties) {
addElement('"' + id + '"', extendNodeProperties(properties));
}
public void addEdge(final String source, final String target) {
addEdge(source, target, new HashMap<>());
}
public void addEdge(final String source, final String target, final String label) {
Map<String, String> properties = new HashMap<String, String>();
properties.put("label", label);
addEdge(source, target, properties);
}
public void addEdge(final String source, final String target, final Map<String, String> properties) {
addElement('"' + source + '"' + " -> " + '"' + target + '"', extendEdgeProperties(properties));
}
public void addSubgraph(final String subgraph) {
body.append(subgraph + '\n');
}
private void addElement(final String element, final Map<String, String> properties) {
body.append(element);
if (properties != null && !properties.isEmpty()) {
body.append(" [");
Joiner.on("\", ").withKeyValueSeparator("=\"").appendTo(body, properties);
body.append("\"]");
}
body.append('\n');
}
private Map<String, String> extendNodeProperties(final Map<String, String> properties) {
return extendElementProperties(properties, defaultNodeProperties);
}
private Map<String, String> extendEdgeProperties(final Map<String, String> properties) {
return extendElementProperties(properties, defaultEdgeProperties);
}
private Map<String, String> extendElementProperties(final Map<String, String> properties, final Map<String, String> defaultElementProperties) {
if (defaultElementProperties != null) {
for (Entry<String, String> property : defaultElementProperties.entrySet()) {
properties.putIfAbsent(property.getKey(), property.getValue());
}
}
if (defaultProperties != null) {
for (Entry<String, String> property : defaultProperties.entrySet()) {
properties.putIfAbsent(property.getKey(), property.getValue());
}
}
return properties;
}
}
package kieker.analysis.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.base.Joiner;
/**
* Simple class for building and representing dot graph files.
*
* @author Sören Henning
*
*/
public class DotBuilder {
private final String start;
private final String end;
private final StringBuilder body = new StringBuilder();
private Map<String, String> graphProperties;
private Map<String, String> defaultNodeProperties;
private Map<String, String> defaultEdgeProperties;
private Map<String, Map<String, String>> nodes;
private Map<String, Map<String, String>> edges;
private List<DotBuilder> subgraphs;
private static final String START_BRACKET = "{";
private static final String END_BRACKET = "}";
private static final String DEFAULT_GRAPH_NAME = "G";
private static final String DEFAULT_GRAPH_TYPE = "digraph";
public DotBuilder() {
this(DEFAULT_GRAPH_NAME);
}
public DotBuilder(final String graphName) {
this(graphName, DEFAULT_GRAPH_TYPE);
}
// TODO graphType has to be one of "graph", "digraph" or "subgraph" so maybe use an enum
public DotBuilder(final String graphName, final String graphType) {
start = graphType + " " + graphName + " " + START_BRACKET + "\n";
end = END_BRACKET;
}
// TODO maybe rename
public void setDefaultNodeProperties(final Map<String, String> defaultNodeProperties) {
this.defaultNodeProperties = defaultNodeProperties;
}
// TODO maybe rename
public void setDefaultEdgeProperties(final Map<String, String> defaultEdgeProperties) {
this.defaultEdgeProperties = defaultEdgeProperties;
}
public String get() {
return start + body.toString() + end;
}
@Override
public String toString() {
return get();
}
public void addNode(final String id) {
addNode(id, new HashMap<>());
}
public void addNode(final String id, final Map<String, String> properties) {
addElement('"' + id + '"', properties);
}
public void addEdge(final String source, final String target) {
addEdge(source, target, new HashMap<>());
}
public void addEdge(final String source, final String target, final Map<String, String> properties) {
addElement('"' + source + '"' + " -> " + '"' + target + '"', properties);
}
public void addSubgraph(final String subgraph) {
body.append(subgraph + '\n');
}
private void addElement(final String element, final Map<String, String> properties) {
body.append(element);
if (properties != null && !properties.isEmpty()) {
body.append(" [");
Joiner.on("\", ").withKeyValueSeparator("=\"").appendTo(body, properties);
body.append("\"]");
}
body.append('\n');
}
}
package kieker.analysis.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Joiner;
/**
* Simple class for building and representing dot graph files.
*
* @deprecated use {@link dot.DotWriter} instead.
*
* @author Sören Henning
*
*/
@Deprecated
public class DotBuilderSupport {
private final String start;
private final String end;
private final StringBuilder body = new StringBuilder();
private Map<String, String> defaultNodeProperties;
private Map<String, String> defaultEdgeProperties;
private Map<String, String> defaultProperties;
private static final String START_BRACKET = "{";
private static final String END_BRACKET = "}";
private static final String DEFAULT_GRAPH_NAME = "G";
private static final String DEFAULT_GRAPH_TYPE = "digraph";
public DotBuilderSupport() {
this(DEFAULT_GRAPH_NAME);
}
public DotBuilderSupport(final String graphName) {
this(graphName, DEFAULT_GRAPH_TYPE);
}
// TODO graphType has to be one of "graph", "digraph" or "subgraph" so maybe use an enum
public DotBuilderSupport(final String graphName, final String graphType) {
start = graphType + " " + graphName + " " + START_BRACKET + "\n";
end = END_BRACKET;
}
// TODO Deprecated
public DotBuilderSupport(final String name, final Map<String, String> defaultNodeProperties, final Map<String, String> defaultEdgeProperties) {
this(name);
this.defaultNodeProperties = defaultNodeProperties;
this.defaultEdgeProperties = defaultEdgeProperties;
}
// TODO Deprecated
public DotBuilderSupport(final String name, final Map<String, String> defaultNodeProperties, final Map<String, String> defaultEdgeProperties,
final Map<String, String> defaultProperties) {
this(name, defaultNodeProperties, defaultEdgeProperties);
this.defaultProperties = defaultProperties;
}
public void setDefaultNodeProperties(final Map<String, String> defaultNodeProperties) {
this.defaultNodeProperties = defaultNodeProperties;
}
public void setDefaultEdgeProperties(final Map<String, String> defaultEdgeProperties) {
this.defaultEdgeProperties = defaultEdgeProperties;
}
public void setDefaultProperties(final Map<String, String> defaultProperties) {
this.defaultProperties = defaultProperties;
}
public String get() {
return start + body.toString() + end;
}
@Override
public String toString() {
return get();
}
public void addNode(final String id) {
addNode(id, new HashMap<>());
}
public void addNode(final String id, final String label) {
Map<String, String> properties = new HashMap<String, String>();
properties.put("label", label);
addNode(id, properties);
}
public void addNode(final String id, final Map<String, String> properties) {
addElement('"' + id + '"', extendNodeProperties(properties));
}
public void addEdge(final String source, final String target) {
addEdge(source, target, new HashMap<>());
}
public void addEdge(final String source, final String target, final String label) {
Map<String, String> properties = new HashMap<String, String>();
properties.put("label", label);
addEdge(source, target, properties);
}
public void addEdge(final String source, final String target, final Map<String, String> properties) {
addElement('"' + source + '"' + " -> " + '"' + target + '"', extendEdgeProperties(properties));
}
public void addSubgraph(final String subgraph) {
body.append(subgraph + '\n');
}
private void addElement(final String element, final Map<String, String> properties) {
body.append(element);
if (properties != null && !properties.isEmpty()) {
body.append(" [");
Joiner.on("\", ").withKeyValueSeparator("=\"").appendTo(body, properties);
body.append("\"]");
}
body.append('\n');
}
private Map<String, String> extendNodeProperties(final Map<String, String> properties) {
return extendElementProperties(properties, defaultNodeProperties);
}
private Map<String, String> extendEdgeProperties(final Map<String, String> properties) {
return extendElementProperties(properties, defaultEdgeProperties);
}
private Map<String, String> extendElementProperties(final Map<String, String> properties, final Map<String, String> defaultElementProperties) {
if (defaultElementProperties != null) {
for (Entry<String, String> property : defaultElementProperties.entrySet()) {
properties.putIfAbsent(property.getKey(), property.getValue());
}
}
if (defaultProperties != null) {
for (Entry<String, String> property : defaultProperties.entrySet()) {
properties.putIfAbsent(property.getKey(), property.getValue());
}
}
return properties;
}
}
......@@ -40,7 +40,7 @@ public class IndentWriter extends Writer {
}
private String getIndentChars() {
return new String(new char[indentLength]).replace('\0', indentChar);
return new String(new char[indented * indentLength]).replace('\0', indentChar);
}
@Override
......
package kieker.analysis.util.dot;
public final class DotGraph {
public static final String START_GRAPH_BRACKET = "{";
public static final String END_GRAPH_BRACKET = "}";
public static final String START_ATTRS_BRACKET = "[";
public static final String END_ATTRS_BRACKET = "]";
public static final String ATTR_CONNECTOR = "=";
public static final String DIRECTED_START_TOKEN = "digraph";
public static final String UNDIRECTED_START_TOKEN = "graph";
public static final String SUB_START_TOKEN = "subgraph";
public static final String NODE = "node";
public static final String EDGE = "edge";
public static final String CLUSTER_PREFIX = "cluster_";
public static final String DIRECTED_EDGE_CONNECTOR = "->";
public static final String UNDIRECTED_EDGE_CONNECTOR = "--";
}
package kieker.analysis.util.dot;
public enum DotGraphType {
DIRECTED, UNDIRECTED
}
package kieker.analysis.util.dot;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import java.util.stream.Collectors;
import kieker.analysis.util.IndentWriter;
/**
* Class to build and write a DOT Graph to a writer.
*
* @author Sören Henning
*
*/
public class DotWriter {
private final IndentWriter writer;
private DotWriterState state = DotWriterState.CREATED;
private int openSubgraphs = 0;
private DotGraphType graphType = DotGraphType.DIRECTED;
public DotWriter(final Writer writer) {
this.writer = new IndentWriter(writer);
}
public void start(final String name) throws IOException {
start(DotGraphType.DIRECTED, name);
}
public void start(final DotGraphType graphType, final String name) throws IOException {
checkState(DotWriterState.CREATED);
this.graphType = graphType;
String openToken;
if (graphType == DotGraphType.UNDIRECTED) {
openToken = DotGraph.UNDIRECTED_START_TOKEN;
} else {
openToken = DotGraph.DIRECTED_START_TOKEN;
}
writer.writeln(openToken + ' ' + name + ' ' + DotGraph.START_GRAPH_BRACKET);
writer.indent();
state = DotWriterState.STARTED;
}
public void finish() throws IOException {
checkState(DotWriterState.STARTED);
if (openSubgraphs > 0) {
throw new IllegalStateException("There are unclosed subgraphs.");
}
writer.unindent();
writer.writeln(DotGraph.END_GRAPH_BRACKET);
state = DotWriterState.FINISHED;
writer.close();
}
public void addDefaultNodeAttributes(final Map<String, String> attributes) throws IOException {
checkState(DotWriterState.STARTED);
writer.writeln(DotGraph.NODE + ' ' + assembleAttributes(attributes));
}
public void addDefaultEdgeAttributes(final Map<String, String> attributes) throws IOException {
checkState(DotWriterState.STARTED);
writer.writeln(DotGraph.EDGE + ' ' + assembleAttributes(attributes));
}
public void addGraphAttribute(final String key, final String value) throws IOException {
checkState(DotWriterState.STARTED);
writer.writeln(assembleAttribute(key, value));
}
public void addNode(final String id, final Map<String, String> attributes) throws IOException {
checkState(DotWriterState.STARTED);
writer.writeln('"' + id + '"' + ' ' + assembleAttributes(attributes));
}
public void addEdge(final String sourceId, final String targetId, final Map<String, String> attributes) throws IOException {
checkState(DotWriterState.STARTED);
String edgeConnector;
if (graphType == DotGraphType.UNDIRECTED) {
edgeConnector = DotGraph.UNDIRECTED_EDGE_CONNECTOR;
} else {
edgeConnector = DotGraph.DIRECTED_EDGE_CONNECTOR;
}
writer.writeln('"' + sourceId + '"' + ' ' + edgeConnector + ' ' + '"' + targetId + '"' + ' ' + assembleAttributes(attributes));
}
public void addSubgraphStart(final String name) throws IOException {
checkState(DotWriterState.STARTED);
writer.writeln(DotGraph.SUB_START_TOKEN + ' ' + name + ' ' + DotGraph.START_GRAPH_BRACKET);
writer.indent();
openSubgraphs++;
}
public void addSubgraphStop() throws IOException {
checkState(DotWriterState.STARTED);
if (openSubgraphs == 0) {
throw new IllegalStateException("There is no subgraph to close.");
}
writer.unindent();
writer.writeln(DotGraph.END_GRAPH_BRACKET);
openSubgraphs--;
}
public void addClusterStart(final String name) throws IOException {
addSubgraphStart(DotGraph.CLUSTER_PREFIX + name);
}
public void addClusterStop() throws IOException {
addSubgraphStop();
}
private void checkState(final DotWriterState expectedState) {
if (state != expectedState) {
switch (expectedState) {
case CREATED:
throw new IllegalStateException("The writing has already been started.");
case STARTED:
throw new IllegalStateException("The writing has never started or already been finished.");
case FINISHED:
throw new IllegalStateException("The writing has not been finished.");
default:
throw new IllegalStateException();
}
}
}
private String assembleAttributes(final Map<String, String> attributes) {
return DotGraph.START_ATTRS_BRACKET
+ attributes.entrySet().stream()
.map(e -> assembleAttribute(e.getKey(), e.getValue()))
.collect(Collectors.joining(","))
+ DotGraph.END_ATTRS_BRACKET;
}
private String assembleAttribute(final String key, final String value) {
return key + DotGraph.ATTR_CONNECTOR + '"' + value + '"';
}
private enum DotWriterState {
CREATED, STARTED, FINISHED
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment