
net.kemitix.dependency.digraph.maven.plugin.DotFileReportGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of digraph-dependency-maven-plugin Show documentation
Show all versions of digraph-dependency-maven-plugin Show documentation
Generates a DOT Digraph of dependencies between packages within a project
package net.kemitix.dependency.digraph.maven.plugin;
import net.kemitix.node.Node;
import javax.inject.Inject;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* Generates a dot file as dependency report generator.
*
* @author pcampbell
*/
class DotFileReportGenerator extends AbstractMojoService
implements ReportGenerator {
private Node base;
private final NodePathGenerator nodeIdGenerator;
/**
* Injected constructor.
*
* @param nodeIdGenerator the node id generator
*/
@Inject
DotFileReportGenerator(final NodePathGenerator nodeIdGenerator) {
this.nodeIdGenerator = nodeIdGenerator;
}
@Override
public String generate(final Node baseNode) {
base = baseNode;
final StringBuilder report = new StringBuilder();
report.append("digraph{compound=true;node[shape=box]\n");
report.append(renderNode(base));
report.append(renderUsages(base));
report.append("}");
return report.toString();
}
private String renderNode(final Node node) {
final StringBuilder render = new StringBuilder();
final String clusterId = nodeIdGenerator.getPath(node, base, "_");
final String nodeId = node.getData().getName();
final String headerFormat
= "subgraph \"cluster{0}\"'{'"
+ "label=\"{1}\";\"{1}\"[style=dotted]\n";
render.append(MessageFormat.format(headerFormat,
clusterId, nodeId));
node.getChildren().stream()
.sorted(new NodePackageDataComparator())
.forEach((Node child) -> {
if (child.getChildren().size() > 0) {
render.append(renderNode(child));
} else {
render.append(renderLeafPackage(child));
}
});
render.append("}\n");
return render.toString();
}
private String renderUsages(final Node node) {
final StringBuilder usages = new StringBuilder();
node.getChildren().stream()
.sorted(new NodePackageDataComparator())
.forEach((Node childNode) -> {
childNode.getData().getUses().stream()
.filter((Node n) -> n.isChildOf(base))
.sorted(new NodePackageDataComparator())
.forEach((Node n) -> {
usages.append(renderUsage(childNode, n));
});
usages.append(renderUsages(childNode));
});
return usages.toString();
}
private String renderUsage(
final Node tailNode,
final Node headNode) {
List attributes = new ArrayList<>();
// if tail node has children, then add ltail attribute
if (tailNode.getChildren().size() > 0) {
attributes.add(String.format("ltail=\"cluster%s\",",
nodeIdGenerator.getPath(tailNode, base, "_")));
}
// if head node has children, then add lhead attribute
if (headNode.getChildren().size() > 0) {
attributes.add(String.format("lhead=\"cluster%s\",",
nodeIdGenerator.getPath(headNode, base, "_")));
}
final StringBuilder attributeTag = new StringBuilder();
if (attributes.size() > 0) {
attributeTag.append("[");
attributes.forEach(attributeTag::append);
attributeTag.append("]");
}
return String.format("\"%s\"->\"%s\"%s%n",
nodeIdGenerator.getPath(tailNode, base, "."),
nodeIdGenerator.getPath(headNode, base, "."),
attributeTag);
}
private String renderLeafPackage(final Node node) {
return String.format("\"%s\"[label=\"%s\"];",
nodeIdGenerator.getPath(node, base, "."),
node.getData().getName());
}
/**
* Comparator for sorting {@link PackageData} {@link Node}s.
*/
@SuppressWarnings("serial")
private static class NodePackageDataComparator
implements Comparator>, Serializable {
NodePackageDataComparator() {
}
@Override
public int compare(
final Node o1,
final Node o2) {
return o1.getData().getName()
.compareTo(o2.getData().getName());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy