jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
changeset 44417 a431edba1629
parent 43808 c0a93657773d
--- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java	Wed Mar 29 13:16:12 2017 +0100
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java	Wed Mar 29 09:40:41 2017 -0700
@@ -26,7 +26,6 @@
 package build.tools.jigsaw;
 
 import com.sun.tools.jdeps.ModuleDotGraph;
-import com.sun.tools.jdeps.ModuleDotGraph.DotGraphBuilder;
 
 import java.io.IOException;
 import java.lang.module.Configuration;
@@ -36,10 +35,15 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * Generate the DOT file for a module graph for each module in the JDK
@@ -50,13 +54,19 @@
     public static void main(String[] args) throws Exception {
         Path dir = null;
         boolean spec = false;
+        Properties props = null;
         for (int i=0; i < args.length; i++) {
             String arg = args[i];
             if (arg.equals("--spec")) {
                 spec = true;
+            } else if (arg.equals("--dot-attributes")) {
+                if (i++ == args.length) {
+                    throw new IllegalArgumentException("Missing argument: --dot-attributes option");
+                }
+                props = new Properties();
+                props.load(Files.newInputStream(Paths.get(args[i])));
             } else if (arg.equals("--output")) {
-                i++;
-                dir = i < args.length ? Paths.get(args[i]) : null;
+                dir = ++i < args.length ? Paths.get(args[i]) : null;
             } else if (arg.startsWith("-")) {
                 throw new IllegalArgumentException("Invalid option: " + arg);
             }
@@ -67,11 +77,14 @@
             System.exit(1);
         }
 
-        // setup and configure the dot graph attributes
-        initDotGraphAttributes();
         Files.createDirectories(dir);
-
-        GenGraphs genGraphs = new GenGraphs(dir, spec);
+        ModuleGraphAttributes attributes;
+        if (props != null) {
+            attributes = new ModuleGraphAttributes(props);
+        } else {
+            attributes = new ModuleGraphAttributes();
+        }
+        GenGraphs genGraphs = new GenGraphs(dir, spec, attributes);
 
         // print dot file for each module
         Map<String, Configuration> configurations = new HashMap<>();
@@ -99,49 +112,149 @@
         genGraphs.genDotFiles(configurations);
     }
 
-    static void initDotGraphAttributes() {
-        int h = 1000;
-        DotGraphBuilder.weight("java.se", "java.sql.rowset", h * 10);
-        DotGraphBuilder.weight("java.sql.rowset", "java.sql", h * 10);
-        DotGraphBuilder.weight("java.sql", "java.xml", h * 10);
-        DotGraphBuilder.weight("java.xml", "java.base", h * 10);
+    /**
+     * Custom dot file attributes.
+     */
+    static class ModuleGraphAttributes implements ModuleDotGraph.Attributes {
+        static Map<String, String> DEFAULT_ATTRIBUTES = Map.of(
+            "ranksep", "0.6",
+            "fontsize", "12",
+            "fontcolor", BLACK,
+            "fontname", "DejaVuSans",
+            "arrowsize", "1",
+            "arrowwidth", "2",
+            "arrowcolor", DARK_GRAY,
+            // custom
+            "requiresMandatedColor", LIGHT_GRAY,
+            "javaSubgraphColor", ORANGE,
+            "jdkSubgraphColor", BLUE
+        );
+
+        final Map<String, Integer> weights = new HashMap<>();
+        final List<Set<String>> ranks = new ArrayList<>();
+        final Map<String, String> attrs;
+        ModuleGraphAttributes(Map<String, String> attrs) {
+            int h = 1000;
+            weight("java.se", "java.sql.rowset", h * 10);
+            weight("java.sql.rowset", "java.sql", h * 10);
+            weight("java.sql", "java.xml", h * 10);
+            weight("java.xml", "java.base", h * 10);
+
+            ranks.add(Set.of("java.logging", "java.scripting", "java.xml"));
+            ranks.add(Set.of("java.sql"));
+            ranks.add(Set.of("java.compiler", "java.instrument"));
+            ranks.add(Set.of("java.desktop", "java.management"));
+            ranks.add(Set.of("java.corba", "java.xml.ws"));
+            ranks.add(Set.of("java.xml.bind", "java.xml.ws.annotation"));
+
+            this.attrs = attrs;
+        }
+
+        ModuleGraphAttributes() {
+            this(DEFAULT_ATTRIBUTES);
+        }
+        ModuleGraphAttributes(Properties props) {
+            this(toAttributes(props));
+        }
+
+        @Override
+        public double rankSep() {
+            return Double.valueOf(attrs.get("ranksep"));
+        }
+
+        @Override
+        public int fontSize() {
+            return Integer.valueOf(attrs.get("fontsize"));
+        }
+
+        @Override
+        public String fontName() {
+            return attrs.get("fontname");
+        }
 
-        DotGraphBuilder.sameRankNodes(Set.of("java.logging", "java.scripting", "java.xml"));
-        DotGraphBuilder.sameRankNodes(Set.of("java.sql"));
-        DotGraphBuilder.sameRankNodes(Set.of("java.compiler", "java.instrument"));
-        DotGraphBuilder.sameRankNodes(Set.of("java.desktop", "java.management"));
-        DotGraphBuilder.sameRankNodes(Set.of("java.corba", "java.xml.ws"));
-        DotGraphBuilder.sameRankNodes(Set.of("java.xml.bind", "java.xml.ws.annotation"));
-        DotGraphBuilder.setRankSep(0.7);
-        DotGraphBuilder.setFontSize(12);
-        DotGraphBuilder.setArrowSize(1);
-        DotGraphBuilder.setArrowWidth(2);
+        @Override
+        public String fontColor() {
+            return attrs.get("fontcolor");
+        }
+
+        @Override
+        public int arrowSize() {
+            return Integer.valueOf(attrs.get("arrowsize"));
+        }
+
+        @Override
+        public int arrowWidth() {
+            return Integer.valueOf(attrs.get("arrowwidth"));
+        }
+
+        @Override
+        public String arrowColor() {
+            return attrs.get("arrowcolor");
+        }
+
+        @Override
+        public List<Set<String>> ranks() {
+            return ranks;
+        }
+
+        @Override
+        public String requiresMandatedColor() {
+            return attrs.get("requiresMandatedColor");
+        }
+
+        @Override
+        public String javaSubgraphColor() {
+            return attrs.get("javaSubgraphColor");
+        }
+
+        @Override
+        public String jdkSubgraphColor() {
+            return attrs.get("jdkSubgraphColor");
+        }
+
+        @Override
+        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 void weight(String s, String t, int w) {
+            weights.put(s + ":" + t, w);
+        }
+
+        static Map<String, String> toAttributes(Properties props) {
+            return DEFAULT_ATTRIBUTES.keySet().stream()
+                .collect(Collectors.toMap(Function.identity(),
+                    k -> props.getProperty(k, DEFAULT_ATTRIBUTES.get(k))));
+        }
     }
 
     private final Path dir;
     private final boolean spec;
-    GenGraphs(Path dir, boolean spec) {
+    private final ModuleGraphAttributes attributes;
+    GenGraphs(Path dir, boolean spec, ModuleGraphAttributes attributes) {
         this.dir = dir;
         this.spec = spec;
+        this.attributes = attributes;
     }
 
     void genDotFiles(Map<String, Configuration> configurations) throws IOException {
         ModuleDotGraph dotGraph = new ModuleDotGraph(configurations, spec);
-        dotGraph.genDotFiles(dir);
+        dotGraph.genDotFiles(dir, attributes);
     }
 
+    /**
+     * Returns true for any name if generating graph for non-spec;
+     * otherwise, returns true except "jdk" and name with "jdk.internal." prefix
+     */
     boolean accept(String name, ModuleDescriptor descriptor) {
-        if (!spec) return true;
-
-        if (name.equals("jdk"))
-            return false;
-
-        if (name.equals("java.se") || name.equals("java.se.ee"))
+        if (!spec)
             return true;
 
-        // only the module that has exported API
-        return descriptor.exports().stream()
-                         .filter(e -> !e.isQualified())
-                         .findAny().isPresent();
+        return !name.equals("jdk") && !name.startsWith("jdk.internal.");
     }
-}
\ No newline at end of file
+}