8180717: Upgrade the docs bundle index page
authormchung
Mon, 22 May 2017 11:08:26 -0700
changeset 45259 e09145bcfcc5
parent 45258 a72369e2e758
child 45260 773754edf3c5
child 45291 6e4400ff1934
child 45329 9a5dc512845a
8180717: Upgrade the docs bundle index page Reviewed-by: jjg, ihse
jdk/make/src/classes/build/tools/docs/GenDocsBundlePage.java
jdk/make/src/classes/build/tools/docs/docs-bundle-page.html
jdk/make/src/classes/build/tools/docs/docs-module-groups.properties
--- a/jdk/make/src/classes/build/tools/docs/GenDocsBundlePage.java	Mon May 22 17:31:07 2017 +0100
+++ b/jdk/make/src/classes/build/tools/docs/GenDocsBundlePage.java	Mon May 22 11:08:26 2017 -0700
@@ -31,18 +31,23 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.function.Predicate;
 import java.util.stream.Stream;
+import static java.util.stream.Collectors.*;
 
 /**
  * Build tool to generate the docs bundle index page.
@@ -104,59 +109,33 @@
     }
 
     private static final String HEADER_TITLE = "@HEADER_TITLE@";
+
+
     final Path outputfile;
     final String title;
-    final Map<String, String> moduleGroups;
-
+    final Map<String, Set<ModuleDescriptor>> moduleGroups = new HashMap<>();
     GenDocsBundlePage(String title, Path outputfile) throws IOException
     {
         this.outputfile = outputfile;
         this.title = title;
-        this.moduleGroups = moduleGroups();
-    }
 
-    static Map<String, String> moduleGroups() throws IOException {
+        // read module groups
         ModuleFinder finder = ModuleFinder.ofSystem();
-        Map<String, String> groups = new HashMap<>();
         try (InputStream in = GenDocsBundlePage.class.getResourceAsStream(MODULE_GROUPS_PROPS)) {
             Properties props = new Properties();
             props.load(in);
             for (String key: props.stringPropertyNames()) {
-                Set<String> mods = Stream.of(props.getProperty(key).split("\\s+"))
-                                         .filter(mn -> finder.find(mn).isPresent())
-                                         .map(String::trim)
-                                         .collect(Collectors.toSet());
+                Set<ModuleDescriptor> mods =
+                    Stream.of(props.getProperty(key).split("\\s+"))
+                          .map(String::trim)
+                          .flatMap(mn -> finder.find(mn).stream())
+                          .map(ModuleReference::descriptor)
+                          .collect(toSet());
 
-                // divide into 3 columns: Java SE, JDK, JavaFX
-                StringBuilder sb = new StringBuilder();
-                sb.append(mods.stream()
-                              .filter(mn -> mn.startsWith("java."))
-                              .sorted()
-                              .map(GenDocsBundlePage::toHRef)
-                              .collect(Collectors.joining("\n")));
-                sb.append("</td>\n<td>")
-                  .append(mods.stream()
-                              .filter(mn -> mn.startsWith("jdk."))
-                              .sorted()
-                              .map(GenDocsBundlePage::toHRef)
-                              .collect(Collectors.joining("\n")));
-                sb.append("</td>\n<td>");
-                if (mods.stream().anyMatch(mn -> mn.startsWith("javafx."))) {
-                    sb.append(mods.stream()
-                                  .filter(mn -> mn.startsWith("javafx."))
-                                  .sorted()
-                                  .map(GenDocsBundlePage::toHRef)
-                                  .collect(Collectors.joining("\n")));
-                }
                 String name = "@" + key.toUpperCase(Locale.ENGLISH) + "@";
-                groups.put(name, sb.toString());
-            }
+                moduleGroups.put(name, mods);
+            };
         }
-        return groups;
-    }
-
-    static String toHRef(String mn) {
-        return String.format("<a href=\"api/%s-summary.html\">%s</a><br>", mn, mn);
     }
 
     void run(BufferedReader reader) throws IOException {
@@ -174,13 +153,95 @@
         if (line.contains(HEADER_TITLE)) {
             line = line.replace(HEADER_TITLE, title);
         }
-        if (line.contains("@")) {
-            for (Map.Entry<String,String> e: moduleGroups.entrySet()) {
-                if (line.contains(e.getKey())) {
-                    line = line.replace(e.getKey(), e.getValue());
-                }
+        int i = line.indexOf('@');
+        int j = line.indexOf('@', i+1);
+        if (i >= 0 && i < j) {
+            String name = line.substring(i, j+1);
+            if (moduleGroups.containsKey(name)) {
+                line = line.replace(name, formatModuleGroup(name));
             }
         }
         return line;
     }
+
+    String toHRef(ModuleDescriptor md) {
+        String mn = md.name();
+        String formattedName;
+        if (hasExportedAPIs(md)) {
+            // has exported APIs
+            formattedName = mn;
+        } else if (!md.provides().isEmpty()) {
+            // a provider
+            formattedName = "<i>" + mn + "</i>";
+        } else {
+            // a tool
+            formattedName = "<i>" + mn + "</i>";
+        }
+        return String.format("<a href=\"api/%s-summary.html\">%s</a>",
+                             mn, formattedName);
+    }
+
+    String formatModuleGroup(String groupName) {
+        StringBuilder sb = new StringBuilder();
+        // organize in Java SE, JDK, JavaFX, JCP groups
+        Set<ModuleDescriptor> modules = moduleGroups.get(groupName);
+        Arrays.stream(ModuleGroup.values())
+            .forEach(g -> {
+                Set<ModuleDescriptor> mods = modules.stream()
+                    .filter(md -> g.predicate.test(md.name()))
+                    .collect(toSet());
+                if (!mods.isEmpty()) {
+                    sb.append("<div class=" + g.cssClass + ">\n");
+                    // modules with exported API
+                    mods.stream()
+                        .filter(this::hasExportedAPIs)
+                        .sorted(Comparator.comparing(ModuleDescriptor::name))
+                        .map(this::toHRef)
+                        .forEach(m -> sb.append(m).append("\n"));
+
+                    // tools and providers
+                    mods.stream()
+                        .filter(md -> !hasExportedAPIs(md))
+                        .sorted(Comparator.comparing(ModuleDescriptor::name))
+                        .map(this::toHRef)
+                        .forEach(m -> sb.append(m).append("\n"));
+                    sb.append("</div>");
+                }
+            });
+        return sb.toString();
+    }
+
+    private boolean hasExportedAPIs(ModuleDescriptor md) {
+        if (md.exports().stream().anyMatch(e -> !e.isQualified())) {
+            return true;
+        }
+        // this should check if any indirect exports
+        // checking requires transitive would be sufficient for JDK modules
+        if (md.requires().stream()
+              .map(ModuleDescriptor.Requires::modifiers)
+              .anyMatch(mods -> mods.contains(ModuleDescriptor.Requires.Modifier.TRANSITIVE))) {
+            return true;
+        }
+        return false;
+    }
+
+    private static final Set<String> NON_JAVA_SE_MODULES =
+        Set.of("java.jnlp", "java.smartcardio");
+
+    /**
+     * CSS class names are defined in docs-bundle-page.html
+     */
+    enum ModuleGroup {
+        JAVA_SE("javase", mn -> mn.startsWith("java.") && !NON_JAVA_SE_MODULES.contains(mn)),
+        JDK("jdk", mn -> mn.startsWith("jdk.")),
+        JAVAFX("javafx", mn -> mn.startsWith("javafx.")),
+        NON_JAVA_SE("jcp", NON_JAVA_SE_MODULES::contains);
+
+        final String cssClass;
+        final Predicate<String> predicate;
+        ModuleGroup(String cssClass, Predicate<String> predicate) {
+            this.cssClass = cssClass;
+            this.predicate = predicate;
+        }
+    }
 }
--- a/jdk/make/src/classes/build/tools/docs/docs-bundle-page.html	Mon May 22 17:31:07 2017 +0100
+++ b/jdk/make/src/classes/build/tools/docs/docs-bundle-page.html	Mon May 22 11:08:26 2017 -0700
@@ -26,91 +26,146 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
-  <meta http-equiv="content-type" content="text/html;" charset="utf-8">
-  <link rel="stylesheet" href="resources/jdk-default.css" type="text/css" />
-  <style type="text/css">
-    caption {
-      text-align: center;
-    }
-  </style>
 <title>@HEADER_TITLE@</title>
+
+<meta http-equiv="content-type" content="text/html;" charset="utf-8">
+<link rel="stylesheet" href="resources/jdk-default.css" type="text/css" />
+<style type="text/css">
+
+table a { text-decoration: none }
+table { border: none }
+th, td { border: 2px solid white; }
+thead th { background-color: #DDD }
+tbody th { background-color: #EEE }
+
+table div.javase, ul.key span.javase { background-color: #C6E7F3 }
+table div.jdk, ul.key span.jdk { background-color: #ECE1C5 }
+table div.javafx, ul.key span.javafx { background-color: #ECEDCC }
+table div.jcp, ul.key span.jcp { background-color: #E9E9E9 }
+td div { padding: 3px 5px; color: blue }
+table tbody td div a { padding: 0 .5em; margin: 0: 1em; }
+table tbody td div a:link { color: black }
+table tbody td div a:visited { color: black }
+table tbody td div a[href]:hover { color: black; text-decoration: underline }
+td { padding: 0 }
+table tbody td div a { padding: 0 .5em; margin: 0: 1em }
+
+.key { font-size: smaller; }
+ul.key li { display:inline-block; padding: 0 1em }
+ul.key span {
+  border: 1px solid black;
+  font-family: DejaVu Sans Mono, monospace;
+}
+ul.key span:before { content: " " }
+ul.key span:after { content: " " }
+
+caption {
+  text-align: center;
+}
+
+tr:nth-child(even), tr:nth-child(even) th[scope=row] {
+  background-color: #EEE;
+}
+tr:nth-child(odd), tr:nth-child(odd) th[scope=row] {
+  background-color: #EEE;
+}
+
+</style>
 </head>
-<body>
 
 <h1>@HEADER_TITLE@</h1>
 
 <ul>
 <li><a href="api/index.html">JDK API Specification</a></li>
-<li>Java Language Specification</li>
-<li>Java Virtual Machine Specification</li>
+<li><a href="https://docs.oracle.com/javase/specs/">
+    Java Language and Virtual Machine Specifications</a></li>
+<li><a href="https://www.oracle.com/pls/topic/lookup?ctx=javase9&id=tools_reference_overview">
+    Tools Reference</a></li>
 </ul>
 
+
 <table>
-<caption>Modules</caption>
+<caption style="display:none">JDK Modules</caption>
 <thead>
 <tr>
   <th scope="col">Group</th>
-  <th scope="col">Java SE</th>
-  <th scope="col">JDK</th>
-  <th scope="col">JavaFX</th>
+  <th scope="col">Modules</th>
 </tr>
 </thead>
 <tbody>
 <tr>
   <th scope="row">Foundation</th>
-  <td>@CORE_MODULES@</td>
+  <td>@JAVA_BASE@</td>
 </tr>
 <tr>
-<th scope="row">Security</th>
-  <td>@SECURITY_MODULES@</td>
-</tr>
-<tr>
-<th scope="row">Instrumentation and<br>Management</th>
-  <td>@INSTRUMENT_MGMT_MODULES@</td>
-</tr>
-<tr>
-<th scope="row">Integration</th>
+  <th scope="row">Integration</th>
   <td>@INTEGRATION_MODULES@</td>
 </tr>
 <tr>
   <th scope="row">User Interface</th>
-  <td>@UI_TOOLKITS_MODULES@</td>
+  <td>@UI_MODULES@</td>
+</tr>
+<tr>
+  <th scope="row">Compilation</th>
+  <td>@COMPILER_MODULES@</td>
 </tr>
 <tr>
-  <th scope="row">Compiler and Scripting</th>
-  <td>@COMPILER_SCRIPTING_MODULES@</td>
+  <th scope="row">Scripting</th>
+  <td>@SCRIPTING_MODULES@</td>
+</tr>
+<tr>
+  <th scope="row">Security</th>
+  <td>@SECURITY_MODULES@</td>
+</tr>
+<tr>
+  <th scope="row">Management</th>
+  <td>@MANAGEMENT_MODULES@</td>
 </tr>
 <tr>
-  <th scope="row">Debugging</th>
-  <td>@DEBUG_MODULES@</td>
+  <th scope="row">Instrumentation</th>
+  <td>@INSTRUMENT_MODULES@</td>
+</tr>
+<tr>
+  <th scope="row">Serviceability</th>
+  <td>@SVC_MODULES@</td>
 </tr>
 <tr>
-  <th scope="row">Tools and Tool APIs</th>
-  <td>@TOOL_MODULES@</td>
+  <th scope="row">Packaging</th>
+  <td>@PACKAGING_MODULES@</td>
 </tr>
 <tr>
-  <th scope="row">Incubating Features</th>
+  <th scope="row">Incubator</th>
   <td>@INCUBATOR_MODULES@</td>
 </tr>
 <tr>
+  <th scope="row">Non-Java SE</th>
+  <td>@OTHER_MODULES@</td>
+</tr>
+<tr>
   <th scope="row">Java EE</th>
   <td>@JAVA_EE_MODULES@</td>
 </tr>
 <tr>
-  <th scope="col"></th>
-  <th scope="col">Outside Java SE</th>
-  <th scope="col">JDK</th>
-  <th scope="col">JavaFX</th>
-</tr>
-<tr>
-  <th scope="row">Others</th>
-  <td>@OTHER_MODULES@</td>
+  <th scope="row">Aggregator</th>
+  <td>@AGGREGATOR_MODULES@</td>
 </tr>
 </tbody>
 </table>
 
+<p class="key">Key:
+<ul class="key">
+<li><span class="javase">&nbsp;</span>&nbsp; Java SE
+<li><span class="jdk">&nbsp;</span>&nbsp; JDK
+<li><span class="javafx">&nbsp;</span>&nbsp; JavaFX
+<li><span class="jcp">&nbsp;</span>&nbsp; Non-Java SE
+<li><i>italic</i> No Exported API (e.g. a tool or provider)</li>
+</ul>
+
 <p>
-<hr/>
-<a href="legal/cpyr.html">Copyright</a>&copy; 1993, 2017, Oracle and/or its affiliates. All rights reserved.</p>
+<hr>
+<a href="legal/cpyr.html">Copyright</a> &copy 1993, 2017, Oracle and/or its affiliates. All rights reserved.</p>
+
 </body>
 </html>
+	
+	
--- a/jdk/make/src/classes/build/tools/docs/docs-module-groups.properties	Mon May 22 17:31:07 2017 +0100
+++ b/jdk/make/src/classes/build/tools/docs/docs-module-groups.properties	Mon May 22 11:08:26 2017 -0700
@@ -1,13 +1,8 @@
 # Module Grouping for the docs bundle page
 #
 
-core_modules=\
-java.base \
-jdk.charsets \
-jdk.localedata \
-jdk.net \
-jdk.sctp \
-jdk.zipfs
+java_base=\
+java.base
 
 java_ee_modules=\
 java.activation \
@@ -17,6 +12,10 @@
 java.xml.ws \
 java.xml.ws.annotation
 
+aggregator_modules=\
+java.se \
+java.se.ee
+
 security_modules=\
 java.security.jgss \
 java.security.sasl \
@@ -26,18 +25,22 @@
 jdk.crypto.cryptoki \
 jdk.crypto.ec \
 jdk.crypto.mscapi \
-jdk.crypto.ucrypto
+jdk.crypto.ucrypto \
+jdk.policytool
 
-instrument_mgmt_modules=\
-java.instrument \
+instrument_modules=\
+java.instrument
+  
+management_modules=\
 java.management \
 java.management.rmi \
-jdk.jfr \
 jdk.management \
 jdk.management.agent \
 jdk.management.cmm \
 jdk.management.jfr \
 jdk.management.resource \
+jdk.snmp \
+jdk.jconsole
 
 integration_modules=\
 java.logging \
@@ -47,11 +50,18 @@
 java.sql \
 java.sql.rowset \
 java.xml \
+jdk.charsets \
+jdk.localedata \
+jdk.net \
+jdk.sctp \
+jdk.jsobject \
 jdk.httpserver \
 jdk.naming.dns \
-jdk.naming.rmi
+jdk.naming.rmi \
+jdk.xml.dom \
+jdk.zipfs
 
-ui_toolkits_modules=\
+ui_modules=\
 java.datatransfer \
 java.desktop \
 javafx.base \
@@ -63,39 +73,40 @@
 javafx.web \
 jdk.accessibility
 
-other_modules=\
-java.jnlp \
-java.smartcardio \
-jdk.jsobject \
-jdk.xml.dom
-
-debug_modules=\
-jdk.jdi \
-jdk.jdwp.agent
-
-tool_modules=\
+svc_modules=\
+jdk.jfr \
 jdk.attach \
-jdk.editpad \
+jdk.jcmd \
+jdk.jdi \
+jdk.jdwp.agent \
+jdk.jstatd \
+jdk.hotspot.agent
+
+packaging_modules=\
 jdk.jartool \
+jdk.jlink \
+jdk.pack \
+jdk.packager.services
+
+compiler_modules=\
+java.compiler \
+jdk.compiler \
 jdk.javadoc \
-jdk.jcmd \
-jdk.jconsole \
 jdk.jdeps \
-jdk.jlink \
+jdk.editpad \
 jdk.jshell \
-jdk.jstatd \
-jdk.pack \
-jdk.policytool \
-jdk.packager.services \
 jdk.rmic
 
-compiler_scripting_modules=\
-java.compiler \
+scripting_modules=\
 java.scripting \
-jdk.compiler \
 jdk.dynalink \
 jdk.scripting.nashorn \
 jdk.scripting.nashorn.shell
 
+other_modules=\
+java.jnlp \
+java.smartcardio
+  
 incubator_modules=\
 jdk.incubator.httpclient
+