langtools/test/tools/lib/toolbox/ModuleBuilder.java
changeset 39103 91a64ec5b970
parent 37758 3ecf9b414e05
child 40500 f293dbb81a53
--- a/langtools/test/tools/lib/toolbox/ModuleBuilder.java	Fri Jun 17 17:09:21 2016 -0600
+++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.java	Fri Jun 17 17:40:01 2016 -0700
@@ -27,83 +27,185 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
+/**
+ * Builder for module declarations.
+ */
 public class ModuleBuilder {
 
     private final ToolBox tb;
     private final String name;
-    private String requires = "";
-    private String exports = "";
-    private String uses = "";
-    private String provides = "";
-    private String modulePath = "";
+    private String comment = "";
+    private List<String> requires = new ArrayList<>();
+    private List<String> exports = new ArrayList<>();
+    private List<String> uses = new ArrayList<>();
+    private List<String> provides = new ArrayList<>();
     private List<String> content = new ArrayList<>();
+    private Set<Path> modulePath = new LinkedHashSet<>();
 
+    /**
+     * Creates a builder for a module.
+     * @param tb a Toolbox that can be used to compile the module declaration.
+     * @param name the name of the module to be built
+     */
     public ModuleBuilder(ToolBox tb, String name) {
         this.tb = tb;
         this.name = name;
     }
 
-    public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
-        return requires("public " + requires, modulePath);
+    /**
+     * Sets the doc comment for the declaration.
+     * @param comment the content of the comment, excluding the initial
+     *  '/**', leading whitespace and asterisks, and the final trailing '&#02a;/'.
+     * @return this builder
+     */
+    public ModuleBuilder comment(String comment) {
+        this.comment = comment;
+        return this;
     }
 
+    /**
+     * Adds a "requires public" directive to the declaration.
+     * @param requires the name of the module that is required
+     * @param modulePath a path in which to locate the modules
+     *    if the declaration is compiled
+     * @return this builder
+     */
+    public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
+        this.requires.add("requires public " + requires + ";");
+        this.modulePath.addAll(Arrays.asList(modulePath));
+        return this;
+    }
+
+    /**
+     * Adds a "requires" directive to the declaration.
+     * @param requires the name of the module that is required
+     * @param modulePath a path in while to locate the modules
+     *    if the declaration is compiled
+     * @return this builder
+     */
     public ModuleBuilder requires(String requires, Path... modulePath) {
-        this.requires += "    requires " + requires + ";\n";
-        this.modulePath += Arrays.stream(modulePath)
-                .map(Path::toString)
-                .collect(Collectors.joining(File.pathSeparator));
+        this.requires.add("requires " + requires + ";");
+        this.modulePath.addAll(Arrays.asList(modulePath));
         return this;
     }
 
+    /**
+     * Adds a qualified "exports" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @param module the name of the module to which it is to be exported
+     * @return this builder
+     */
     public ModuleBuilder exportsTo(String pkg, String module) {
-        return exports(pkg + " to " + module);
+        this.exports.add("exports " + pkg + " to " + module + ";");
+        return this;
     }
 
+    /**
+     * Adds an unqualified "exports" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @param module the name of the module to which it is to be exported
+     * @return this builder
+     */
     public ModuleBuilder exports(String pkg) {
-        this.exports += "    exports " + pkg + ";\n";
+        this.exports.add("exports " + pkg + ";");
         return this;
     }
 
-    public ModuleBuilder uses(String uses) {
-        this.uses += "    uses " + uses + ";\n";
+    /**
+     * Adds a "uses" directive to the declaration.
+     * @param service the name of the service type
+     * @return this builder
+     */
+    public ModuleBuilder uses(String service) {
+        this.uses.add("uses " + service + ";");
         return this;
     }
 
+    /**
+     * Adds a "provides" directive to the declaration.
+     * @param service the name of the service type
+     * @param implementation the name of the implementation type
+     * @return this builder
+     */
     public ModuleBuilder provides(String service, String implementation) {
-        this.provides += "    provides " + service + " with " + implementation + ";\n";
+        this.provides.add("provides " + service + " with " + implementation + ";");
         return this;
     }
 
+    /**
+     * Adds type definitions to the module.
+     * @param content a series of strings, each representing the content of
+     *  a compilation unit to be included with the module
+     * @return this builder
+     */
     public ModuleBuilder classes(String... content) {
         this.content.addAll(Arrays.asList(content));
         return this;
     }
 
-    public Path write(Path where) throws IOException {
-        Files.createDirectories(where);
+    /**
+     * Writes the module declaration and associated additional compilation
+     * units to a module directory within a given directory.
+     * @param srcDir the directory in which a directory will be created
+     *  to contain the source files for the module
+     * @return the directory containing the source files for the module
+     */
+    public Path write(Path srcDir) throws IOException {
+        Files.createDirectories(srcDir);
         List<String> sources = new ArrayList<>();
-        sources.add("module " + name + "{"
-                + requires
-                + exports
-                + uses
-                + provides
-                + "}");
+        StringBuilder sb = new StringBuilder();
+        if (!comment.isEmpty()) {
+            sb.append("/**\n").append(comment.replace("\n", " *")).append(" */\n");
+        }
+        sb.append("module ").append(name).append(" {");
+        requires.forEach(r -> sb.append("    " + r + "\n"));
+        exports.forEach(e -> sb.append("    " + e + "\n"));
+        uses.forEach(u -> sb.append("    " + u + "\n"));
+        provides.forEach(p -> sb.append("    " + p + "\n"));
+        sb.append("}");
+        sources.add(sb.toString());
         sources.addAll(content);
-        Path moduleSrc = where.resolve(name + "/src");
+        Path moduleSrc = srcDir.resolve(name);
         tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{}));
         return moduleSrc;
     }
 
-    public void build(Path where) throws IOException {
-        Path moduleSrc = write(where);
+    /**
+     * Writes the source files for the module to an interim directory,
+     * and then compiles them to a given directory.
+     * @param modules the directory in which a directory will be created
+     *    to contain the compiled class files for the module
+     * @throws IOException if an error occurs while compiling the files
+     */
+    public void build(Path modules) throws IOException {
+        build(Paths.get(modules + "Src"), modules);
+    }
+
+    /**
+     * Writes the source files for the module to a specified directory,
+     * and then compiles them to a given directory.
+     * @param srcDir the directory in which a directory will be created
+     *  to contain the source files for the module
+     * @param modules the directory in which a directory will be created
+     *    to contain the compiled class files for the module
+     * @throws IOException if an error occurs while compiling the files
+     */
+    public void build(Path src, Path modules) throws IOException {
+        Path moduleSrc = write(src);
+        String mp = modulePath.stream()
+                .map(Path::toString)
+                .collect(Collectors.joining(File.pathSeparator));
         new JavacTask(tb)
-                .outdir(where.resolve(name))
-                .options("-mp", modulePath)
+                .outdir(Files.createDirectories(modules.resolve(name)))
+                .options("-mp", mp)
                 .files(tb.findJavaFiles(moduleSrc))
                 .run()
                 .writeAll();