< 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 >