changeset 4071:bb0649dbe925

8173303: Add module-subgraph images to main platform documentation Reviewed-by: alanb, chegar, erikj, ihse, lancea Contributed-by: jonathan.gibbons@oracle.com, mandy.chung@oracle.com
author mchung
date Wed, 29 Mar 2017 09:41:36 -0700
parents cc3c67b12ef1
children 3b47c6cb966e
files src/java.compiler/share/classes/module-info.java src/jdk.compiler/share/classes/module-info.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css src/jdk.javadoc/share/classes/module-info.java src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java src/jdk.jdeps/share/classes/module-info.java src/jdk.jshell/share/classes/module-info.java
diffstat 7 files changed, 156 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.compiler/share/classes/module-info.java	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/java.compiler/share/classes/module-info.java	Wed Mar 29 09:41:36 2017 -0700
@@ -30,6 +30,7 @@
   * and define interfaces for tools such as compilers which can be invoked
   * from a program.
   *
+  * @moduleGraph
   * @since 9
   */
 module java.compiler {
--- a/src/jdk.compiler/share/classes/module-info.java	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/jdk.compiler/share/classes/module-info.java	Wed Mar 29 09:41:36 2017 -0700
@@ -27,6 +27,7 @@
  *  {@link javax.tools.ToolProvider#getSystemJavaCompiler system Java compiler}
  *  and its command line equivalent, <em>javac</em>, as well as <em>javah</em>.
  *
+ *  @moduleGraph
  *  @since 9
  */
 module jdk.compiler {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Wed Mar 29 09:41:36 2017 -0700
@@ -787,3 +787,15 @@
     font-style:italic;
     font-size:12px;
 }
+
+.moduleGraph span {
+    display:none;
+    position:absolute;
+}
+.moduleGraph:hover span {
+    display:block;
+    margin: -100px 0 0 100px;
+    z-index: 1;
+}
+
+
--- a/src/jdk.javadoc/share/classes/module-info.java	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/jdk.javadoc/share/classes/module-info.java	Wed Mar 29 09:41:36 2017 -0700
@@ -27,6 +27,7 @@
  *  {@link javax.tools.ToolProvider#getSystemDocumentationTool system documentation tool}
  *  and its command line equivalent, <em>javadoc</em>.
  *
+ *  @moduleGraph
  *  @since 9
  */
 module jdk.javadoc {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java	Wed Mar 29 09:41:36 2017 -0700
@@ -32,6 +32,7 @@
 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;
@@ -39,8 +40,8 @@
 import java.nio.file.Path;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Deque;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -76,10 +77,16 @@
      * @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));
+            genDotFile(path, mn, configurations.get(mn), attributes);
         }
         return true;
     }
@@ -87,7 +94,9 @@
     /**
      * Generate dotfile of the given path
      */
-    public void genDotFile(Path path, String name, Configuration configuration)
+    public void genDotFile(Path path, String name,
+                           Configuration configuration,
+                           Attributes attributes)
         throws IOException
     {
         // transitive reduction
@@ -95,12 +104,12 @@
                 ? requiresTransitiveGraph(configuration, Set.of(name))
                 : gengraph(configuration);
 
-        DotGraphBuilder builder = new DotGraphBuilder(name, graph);
-        builder.subgraph("se", "java", DotGraphBuilder.ORANGE,
+        DotGraphBuilder builder = new DotGraphBuilder(name, graph, attributes);
+        builder.subgraph("se", "java", attributes.javaSubgraphColor(),
                          DotGraphBuilder.JAVA_SE_SUBGRAPH)
-               .subgraph("jdk", "jdk", DotGraphBuilder.BLUE,
+               .subgraph("jdk", "jdk", attributes.jdkSubgraphColor(),
                          DotGraphBuilder.JDK_SUBGRAPH)
-               .descriptors(graph.nodes().stream()
+               .modules(graph.nodes().stream()
                                  .map(mn -> configuration.findModule(mn).get()
                                                 .reference().descriptor()));
         // build dot file
@@ -118,12 +127,12 @@
     private Graph<String> gengraph(Configuration cf) {
         Graph.Builder<String> builder = new Graph.Builder<>();
         cf.modules().stream()
-            .forEach(resolvedModule -> {
-                String mn = resolvedModule.reference().descriptor().name();
+            .forEach(rm -> {
+                String mn = rm.name();
                 builder.addNode(mn);
-                resolvedModule.reads().stream()
-                    .map(ResolvedModule::name)
-                    .forEach(target -> builder.addEdge(mn, target));
+                rm.reads().stream()
+                  .map(ResolvedModule::name)
+                  .forEach(target -> builder.addEdge(mn, target));
             });
 
         Graph<String> rpg = requiresTransitiveGraph(cf, builder.nodes);
@@ -149,22 +158,103 @@
 
             visited.add(mn);
             builder.addNode(mn);
-            ModuleDescriptor descriptor = cf.findModule(mn).get()
-                .reference().descriptor();
-            descriptor.requires().stream()
-                .filter(d -> d.modifiers().contains(TRANSITIVE)
+            cf.findModule(mn).get()
+              .reference().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);
-                });
+              .map(Requires::name)
+              .forEach(d -> {
+                  deque.add(d);
+                  builder.addEdge(mn, d);
+              });
         }
 
         return builder.build().reduce();
     }
 
-    public static class DotGraphBuilder {
+    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();
 
@@ -215,41 +305,20 @@
             }
         }
 
-        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) {
+        private final Attributes attributes;
+        public DotGraphBuilder(String name,
+                               Graph<String> graph,
+                               Attributes attributes) {
             this.name = name;
             this.graph = graph;
+            this.attributes = attributes;
         }
 
-        public DotGraphBuilder descriptors(Stream<ModuleDescriptor> descriptors) {
+        public DotGraphBuilder modules(Stream<ModuleDescriptor> descriptors) {
             descriptors.forEach(this.descriptors::add);
             return this;
         }
@@ -260,22 +329,27 @@
 
                 out.format("digraph \"%s\" {%n", name);
                 out.format("  nodesep=.5;%n");
-                out.format("  ranksep=%f;%n", rankSep);
+                out.format("  ranksep=%f;%n", attributes.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);
+                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
-                ranks.stream()
-                     .map(nodes -> descriptors.stream()
+                attributes.ranks().stream()
+                    .map(nodes -> descriptors.stream()
                                         .map(ModuleDescriptor::name)
                                         .filter(nodes::contains)
                                         .map(mn -> "\"" + mn + "\"")
                                         .collect(joining(",")))
-                     .filter(group -> group.length() > 0)
-                     .forEach(group -> out.format("  {rank=same %s}%n", group));
+                    .filter(group -> group.length() > 0)
+                    .forEach(group -> out.format("  {rank=same %s}%n", group));
 
                 subgraphs.forEach(subgraph -> {
                     out.format("  subgraph %s {%n", subgraph.name);
@@ -314,10 +388,14 @@
 
             String mn = md.name();
             edges.stream().forEach(dn -> {
-                String attr = dn.equals("java.base") ? REQUIRES_BASE
-                    : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
+                String attr;
+                if (dn.equals("java.base")) {
+                    attr = "color=\"" + attributes.requiresMandatedColor() + "\"";
+                } else {
+                    attr = (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
+                }
 
-                int w = weightOf(mn, dn);
+                int w = attributes.weightOf(mn, dn);
                 if (w > 1) {
                     if (!attr.isEmpty())
                         attr += ", ";
@@ -328,41 +406,5 @@
             });
         }
 
-        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;
-        }
     }
 }
--- a/src/jdk.jdeps/share/classes/module-info.java	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/module-info.java	Wed Mar 29 09:41:36 2017 -0700
@@ -26,6 +26,7 @@
 /** Defines tools for analysing dependencies in Java libraries and programs, including
  *  the <em>jdeps</em> and <em>javap</em> tools.
  *
+ *  @moduleGraph
  *  @since 9
  */
 module jdk.jdeps {
--- a/src/jdk.jshell/share/classes/module-info.java	Wed Mar 29 10:27:23 2017 +0200
+++ b/src/jdk.jshell/share/classes/module-info.java	Wed Mar 29 09:41:36 2017 -0700
@@ -52,6 +52,7 @@
  *     definitions.
  * </p>
  *
+ * @moduleGraph
  * @since 9
  */
 module jdk.jshell {