pascal.taie.util.graph.DotDumper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tai-e Show documentation
Show all versions of tai-e Show documentation
An easy-to-learn/use static analysis framework for Java
The newest version!
/*
* Tai-e: A Static Analysis Framework for Java
*
* Copyright (C) 2022 Tian Tan
* Copyright (C) 2022 Yue Li
*
* This file is part of Tai-e.
*
* Tai-e is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* Tai-e is distributed in the hope that it will be useful,but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Tai-e. If not, see .
*/
package pascal.taie.util.graph;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Objects;
import java.util.function.Function;
/**
* Configurable dot dumper.
*
* @param type of graph nodes
*/
public class DotDumper {
private static final Logger logger = LogManager.getLogger(DotDumper.class);
private static final String INDENT = " ";
/**
* The output stream for dumping dot graph.
*/
private PrintStream out;
/**
* The function that converts a node to its string representation.
*/
private Function nodeToString = Objects::toString;
/**
* Global node attributes.
*/
private DotAttributes globalNodeAttrs = DotAttributes.of();
/**
* The labeler for nodes.
*/
private Function nodeLabeler = node -> null;
/**
* The node attributes.
*/
private Function nodeAttributer = node -> null;
/**
* The labeler for edges.
*/
private Function, String> edgeLabeler = edge -> null;
/**
* Global edge attributes.
*/
private DotAttributes globalEdgeAttrs = DotAttributes.of();
/**
* The function that maps an edge to its attributes.
*/
private Function, DotAttributes> edgeAttributer = edge -> null;
public DotDumper setNodeToString(Function nodeToString) {
this.nodeToString = nodeToString;
return this;
}
public DotDumper setGlobalNodeAttributes(DotAttributes attrs) {
globalNodeAttrs = attrs;
return this;
}
public DotDumper setNodeLabeler(Function nodeLabeler) {
this.nodeLabeler = nodeLabeler;
return this;
}
public DotDumper setNodeAttributer(
Function nodeAttributer) {
this.nodeAttributer = nodeAttributer;
return this;
}
public DotDumper setEdgeLabeler(Function, String> edgeLabeler) {
this.edgeLabeler = edgeLabeler;
return this;
}
public DotDumper setGlobalEdgeAttributes(DotAttributes attrs) {
globalEdgeAttrs = attrs;
return this;
}
public DotDumper setEdgeAttributer(Function, DotAttributes> edgeAttributer) {
this.edgeAttributer = edgeAttributer;
return this;
}
public void dump(Graph graph, File output) {
try (PrintStream out = new PrintStream(new FileOutputStream(output))) {
this.out = out;
// dump starts
out.println("digraph G {");
// dump global node attributes
out.printf("%snode [%s];%n", INDENT, globalNodeAttrs);
// dump global edge attributes
out.printf("%sedge [%s];%n", INDENT, globalEdgeAttrs);
// dump nodes
graph.forEach(this::dumpNode);
// dump edges
graph.forEach(n -> graph.getOutEdgesOf(n).forEach(this::dumpEdge));
// dump other information
dumpOthers();
// dump ends
out.println("}");
} catch (FileNotFoundException e) {
logger.warn("Failed to dump graph to {}", output.getAbsolutePath(), e);
}
}
/**
* Subclasses can override this method to dump other information
* other than type parameter <N>
.
*/
protected void dumpOthers() {
}
private void dumpNode(N node) {
dumpElement(node, this::nodeToString, nodeLabeler, nodeAttributer);
}
private String nodeToString(N node) {
return "\"" + nodeToString.apply(node) + "\"";
}
private void dumpEdge(Edge edge) {
dumpElement(edge, this::getEdgeRep, edgeLabeler, edgeAttributer);
}
private String getEdgeRep(Edge edge) {
return nodeToString(edge.source()) + " -> " + nodeToString(edge.target());
}
/**
* Dumps an element (either a node or an edge).
*
* @param elem element to be dumped
* @param toString function that returns string representation of {@code elem}
* @param labeler function that returns label of {@code elem}
* @param attributer function that returns attributes of {@code elem}
* @param type of the element
*/
protected void dumpElement(
T elem,
Function toString,
Function labeler,
Function attributer
) {
out.print(INDENT);
out.print(toString.apply(elem));
String label = labeler.apply(elem);
DotAttributes attrs = attributer.apply(elem);
if (label != null || attrs != null) {
out.print(" [");
if (label != null) {
out.printf("label=\"%s\",", label);
}
if (attrs != null) {
out.print(attrs);
}
out.print(']');
}
out.println(';');
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy