< prev index next >
langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java
Print this page
*** 30,48 ****
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
- import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
--- 30,49 ----
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
+ import java.lang.module.ModuleDescriptor.*;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
+ import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
*** 74,108 ****
* Generate dotfile for all modules
*
* @param dir output directory
*/
public boolean genDotFiles(Path dir) throws IOException {
Files.createDirectories(dir);
for (String mn : configurations.keySet()) {
Path path = dir.resolve(mn + ".dot");
! genDotFile(path, mn, configurations.get(mn));
}
return true;
}
/**
* Generate dotfile of the given path
*/
! public void genDotFile(Path path, String name, Configuration configuration)
throws IOException
{
// transitive reduction
Graph<String> graph = apiOnly
? requiresTransitiveGraph(configuration, Set.of(name))
: gengraph(configuration);
! DotGraphBuilder builder = new DotGraphBuilder(name, graph);
! builder.subgraph("se", "java", DotGraphBuilder.ORANGE,
DotGraphBuilder.JAVA_SE_SUBGRAPH)
! .subgraph("jdk", "jdk", DotGraphBuilder.BLUE,
DotGraphBuilder.JDK_SUBGRAPH)
! .descriptors(graph.nodes().stream()
.map(mn -> configuration.findModule(mn).get()
.reference().descriptor()));
// build dot file
builder.build(path);
}
--- 75,117 ----
* Generate dotfile for all modules
*
* @param dir output directory
*/
public boolean genDotFiles(Path dir) throws IOException {
+ return genDotFiles(dir, DotGraphAttributes.DEFAULT);
+ }
+
+ public boolean genDotFiles(Path dir, Attributes attributes)
+ throws IOException
+ {
Files.createDirectories(dir);
for (String mn : configurations.keySet()) {
Path path = dir.resolve(mn + ".dot");
! genDotFile(path, mn, configurations.get(mn), attributes);
}
return true;
}
/**
* Generate dotfile of the given path
*/
! public void genDotFile(Path path, String name,
! Configuration configuration,
! Attributes attributes)
throws IOException
{
// transitive reduction
Graph<String> graph = apiOnly
? requiresTransitiveGraph(configuration, Set.of(name))
: gengraph(configuration);
! DotGraphBuilder builder = new DotGraphBuilder(name, graph, attributes);
! builder.subgraph("se", "java", attributes.javaSubgraphColor(),
DotGraphBuilder.JAVA_SE_SUBGRAPH)
! .subgraph("jdk", "jdk", attributes.jdkSubgraphColor(),
DotGraphBuilder.JDK_SUBGRAPH)
! .modules(graph.nodes().stream()
.map(mn -> configuration.findModule(mn).get()
.reference().descriptor()));
// build dot file
builder.build(path);
}
*** 116,129 ****
* in which V would not be re-exported from U.
*/
private Graph<String> gengraph(Configuration cf) {
Graph.Builder<String> builder = new Graph.Builder<>();
cf.modules().stream()
! .forEach(resolvedModule -> {
! String mn = resolvedModule.reference().descriptor().name();
builder.addNode(mn);
! resolvedModule.reads().stream()
.map(ResolvedModule::name)
.forEach(target -> builder.addEdge(mn, target));
});
Graph<String> rpg = requiresTransitiveGraph(cf, builder.nodes);
--- 125,138 ----
* in which V would not be re-exported from U.
*/
private Graph<String> gengraph(Configuration cf) {
Graph.Builder<String> builder = new Graph.Builder<>();
cf.modules().stream()
! .forEach(rm -> {
! String mn = rm.name();
builder.addNode(mn);
! rm.reads().stream()
.map(ResolvedModule::name)
.forEach(target -> builder.addEdge(mn, target));
});
Graph<String> rpg = requiresTransitiveGraph(cf, builder.nodes);
*** 147,172 ****
if (visited.contains(mn))
continue;
visited.add(mn);
builder.addNode(mn);
! ModuleDescriptor descriptor = cf.findModule(mn).get()
! .reference().descriptor();
! descriptor.requires().stream()
.filter(d -> d.modifiers().contains(TRANSITIVE)
|| d.name().equals("java.base"))
! .map(d -> d.name())
.forEach(d -> {
deque.add(d);
builder.addEdge(mn, d);
});
}
return builder.build().reduce();
}
! public static class DotGraphBuilder {
static final Set<String> JAVA_SE_SUBGRAPH = javaSE();
static final Set<String> JDK_SUBGRAPH = jdk();
private static Set<String> javaSE() {
String root = "java.se.ee";
--- 156,262 ----
if (visited.contains(mn))
continue;
visited.add(mn);
builder.addNode(mn);
! cf.findModule(mn).get()
! .reference().descriptor().requires().stream()
.filter(d -> d.modifiers().contains(TRANSITIVE)
|| d.name().equals("java.base"))
! .map(Requires::name)
.forEach(d -> {
deque.add(d);
builder.addEdge(mn, d);
});
}
return builder.build().reduce();
}
! public interface Attributes {
! static final String ORANGE = "#e76f00";
! static final String BLUE = "#437291";
! static final String BLACK = "#000000";
! static final String DARK_GRAY = "#999999";
! static final String LIGHT_GRAY = "#dddddd";
!
! int fontSize();
! String fontName();
! String fontColor();
!
! int arrowSize();
! int arrowWidth();
! String arrowColor();
!
! default double rankSep() {
! return 1;
! }
!
! default List<Set<String>> ranks() {
! return Collections.emptyList();
! }
!
! default int weightOf(String s, String t) {
! return 1;
! }
!
! default String requiresMandatedColor() {
! return LIGHT_GRAY;
! }
!
! default String javaSubgraphColor() {
! return ORANGE;
! }
!
! default String jdkSubgraphColor() {
! return BLUE;
! }
! }
!
! static class DotGraphAttributes implements Attributes {
! static final DotGraphAttributes DEFAULT = new DotGraphAttributes();
!
! static final String FONT_NAME = "DejaVuSans";
! static final int FONT_SIZE = 12;
! static final int ARROW_SIZE = 1;
! static final int ARROW_WIDTH = 2;
!
! @Override
! public int fontSize() {
! return FONT_SIZE;
! }
!
! @Override
! public String fontName() {
! return FONT_NAME;
! }
!
! @Override
! public String fontColor() {
! return BLACK;
! }
!
! @Override
! public int arrowSize() {
! return ARROW_SIZE;
! }
!
! @Override
! public int arrowWidth() {
! return ARROW_WIDTH;
! }
!
! @Override
! public String arrowColor() {
! return DARK_GRAY;
! }
! }
!
! private static class DotGraphBuilder {
! static final String REEXPORTS = "";
! static final String REQUIRES = "style=\"dashed\"";
!
static final Set<String> JAVA_SE_SUBGRAPH = javaSE();
static final Set<String> JDK_SUBGRAPH = jdk();
private static Set<String> javaSE() {
String root = "java.se.ee";
*** 213,276 ****
this.color = Objects.requireNonNull(color);
this.nodes = Objects.requireNonNull(nodes);
}
}
- static final String ORANGE = "#e76f00";
- static final String BLUE = "#437291";
- static final String GRAY = "#dddddd";
- static final String BLACK = "#000000";
-
- static final String FONT_NAME = "DejaVuSans";
- static final int FONT_SIZE = 12;
- static final int ARROW_SIZE = 1;
- static final int ARROW_WIDTH = 2;
- static final int RANK_SEP = 1;
-
- static final String REEXPORTS = "";
- static final String REQUIRES = "style=\"dashed\"";
- static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
-
- // can be configured
- static double rankSep = RANK_SEP;
- static String fontColor = BLACK;
- static String fontName = FONT_NAME;
- static int fontsize = FONT_SIZE;
- static int arrowWidth = ARROW_WIDTH;
- static int arrowSize = ARROW_SIZE;
- static final Map<String, Integer> weights = new HashMap<>();
- static final List<Set<String>> ranks = new ArrayList<>();
-
private final String name;
private final Graph<String> graph;
private final Set<ModuleDescriptor> descriptors = new TreeSet<>();
private final List<SubGraph> subgraphs = new ArrayList<>();
! public DotGraphBuilder(String name, Graph<String> graph) {
this.name = name;
this.graph = graph;
}
! public DotGraphBuilder descriptors(Stream<ModuleDescriptor> descriptors) {
descriptors.forEach(this.descriptors::add);
return this;
}
public void build(Path filename) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(filename);
PrintWriter out = new PrintWriter(writer)) {
out.format("digraph \"%s\" {%n", name);
out.format(" nodesep=.5;%n");
! out.format(" ranksep=%f;%n", rankSep);
out.format(" pencolor=transparent;%n");
! out.format(" node [shape=plaintext, fontname=\"%s\", fontsize=%d, margin=\".2,.2\"];%n",
! fontName, fontsize);
! out.format(" edge [penwidth=%d, color=\"#999999\", arrowhead=open, arrowsize=%d];%n",
! arrowWidth, arrowSize);
// same RANKS
! ranks.stream()
.map(nodes -> descriptors.stream()
.map(ModuleDescriptor::name)
.filter(nodes::contains)
.map(mn -> "\"" + mn + "\"")
.collect(joining(",")))
--- 303,350 ----
this.color = Objects.requireNonNull(color);
this.nodes = Objects.requireNonNull(nodes);
}
}
private final String name;
private final Graph<String> graph;
private final Set<ModuleDescriptor> descriptors = new TreeSet<>();
private final List<SubGraph> subgraphs = new ArrayList<>();
! private final Attributes attributes;
! public DotGraphBuilder(String name,
! Graph<String> graph,
! Attributes attributes) {
this.name = name;
this.graph = graph;
+ this.attributes = attributes;
}
! public DotGraphBuilder modules(Stream<ModuleDescriptor> descriptors) {
descriptors.forEach(this.descriptors::add);
return this;
}
public void build(Path filename) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(filename);
PrintWriter out = new PrintWriter(writer)) {
out.format("digraph \"%s\" {%n", name);
out.format(" nodesep=.5;%n");
! out.format(" ranksep=%f;%n", attributes.rankSep());
out.format(" pencolor=transparent;%n");
! out.format(" node [shape=plaintext, fontcolor=\"%s\", fontname=\"%s\","
! + " fontsize=%d, margin=\".2,.2\"];%n",
! attributes.fontColor(),
! attributes.fontName(),
! attributes.fontSize());
! out.format(" edge [penwidth=%d, color=\"%s\", arrowhead=open, arrowsize=%d];%n",
! attributes.arrowWidth(),
! attributes.arrowColor(),
! attributes.arrowSize());
// same RANKS
! attributes.ranks().stream()
.map(nodes -> descriptors.stream()
.map(ModuleDescriptor::name)
.filter(nodes::contains)
.map(mn -> "\"" + mn + "\"")
.collect(joining(",")))
*** 312,368 ****
.map(d -> d.name())
.collect(toSet());
String mn = md.name();
edges.stream().forEach(dn -> {
! String attr = dn.equals("java.base") ? REQUIRES_BASE
! : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
! int w = weightOf(mn, dn);
if (w > 1) {
if (!attr.isEmpty())
attr += ", ";
attr += "weight=" + w;
}
out.format(" \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
});
}
- public int weightOf(String s, String t) {
- int w = weights.getOrDefault(s + ":" + t, 1);
- if (w != 1)
- return w;
- if (s.startsWith("java.") && t.startsWith("java."))
- return 10;
- return 1;
- }
-
- public static void sameRankNodes(Set<String> nodes) {
- ranks.add(nodes);
- }
-
- public static void weight(String s, String t, int w) {
- weights.put(s + ":" + t, w);
- }
-
- public static void setRankSep(double value) {
- rankSep = value;
- }
-
- public static void setFontSize(int size) {
- fontsize = size;
- }
-
- public static void setFontColor(String color) {
- fontColor = color;
- }
-
- public static void setArrowSize(int size) {
- arrowSize = size;
- }
-
- public static void setArrowWidth(int width) {
- arrowWidth = width;
- }
}
}
--- 386,410 ----
.map(d -> d.name())
.collect(toSet());
String mn = md.name();
edges.stream().forEach(dn -> {
! String attr;
! if (dn.equals("java.base")) {
! attr = "color=\"" + attributes.requiresMandatedColor() + "\"";
! } else {
! attr = (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
! }
! int w = attributes.weightOf(mn, dn);
if (w > 1) {
if (!attr.isEmpty())
attr += ", ";
attr += "weight=" + w;
}
out.format(" \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
});
}
}
}
< prev index next >