langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/ModuleGenerator.java
changeset 44015 27aa35eb727c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/ModuleGenerator.java	Tue Feb 21 15:38:07 2017 -0800
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sampleapi.generator;
+
+import com.sun.source.tree.ModuleTree.ModuleKind;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.parser.Scanner;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.parser.Tokens;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCDirective;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.TreeMaker;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.ListBuffer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.ArrayList;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import sampleapi.SampleApi;
+import sampleapi.util.PoorDocCommentTable;
+
+import static com.sun.tools.javac.parser.Tokens.Comment.CommentStyle.JAVADOC;
+
+/**
+ *
+ * This class is responsible for loading module description from an XML and then generating the
+ * <code>module-info.java</code>. It is using {@link PackageGenerator} class for parsing content of the module.
+ */
+public class ModuleGenerator {
+
+    private static final String UNNAMED = "UNNAMED";
+    private static final String MODULE_INFO = "module-info.java";
+
+    public String name;
+    public String id;
+    public ModuleKind kind;
+    public final List<Exports> exportss = new ArrayList<>();
+    public final List<Opens> openss = new ArrayList<>();
+    public final List<Requires> requiress = new ArrayList<>();
+    public final List<Uses> usess = new ArrayList<>();
+    public final List<Provides> providess = new ArrayList<>();
+    public final List<PackageGenerator> packages = new ArrayList<>();
+
+    private ModuleGenerator() {
+    }
+
+    public static ModuleGenerator load(Element rootElement) {
+        ModuleGenerator result = new ModuleGenerator();
+        result.name = rootElement.getAttribute("name");
+        result.id = rootElement.getAttribute("id");
+        String kind = rootElement.getAttribute("kind");
+        result.kind = kind.isEmpty() ? ModuleKind.STRONG :
+                ModuleKind.valueOf(kind.toUpperCase());
+        //exports
+        NodeList exportsList = rootElement.getElementsByTagName("exports");
+        for (int i = 0; i < exportsList.getLength(); i++) {
+            Element exportsEl = (Element) exportsList.item(i);
+            Exports exports = new Exports(exportsEl.getAttribute("package"));
+            NodeList toList = exportsEl.getElementsByTagName("to");
+            for (int j = 0; j < toList.getLength(); j++) {
+                Element toElement = (Element) toList.item(j);
+                exports.modules.add(toElement.getAttribute("module"));
+            }
+            result.exportss.add(exports);
+        }
+        //opens
+        NodeList opensList = rootElement.getElementsByTagName("opens");
+        for (int i = 0; i < opensList.getLength(); i++) {
+            Element opensEl = (Element) opensList.item(i);
+            Opens opens = new Opens(opensEl.getAttribute("package"));
+            NodeList toList = opensEl.getElementsByTagName("to");
+            for (int j = 0; j < toList.getLength(); j++) {
+                Element toElement = (Element) toList.item(j);
+                opens.modules.add(toElement.getAttribute("module"));
+            }
+            result.openss.add(opens);
+        }
+        //requires
+        NodeList requiresList = rootElement.getElementsByTagName("requires");
+        for (int i = 0; i < requiresList.getLength(); i++) {
+            Element requiresEl = (Element) requiresList.item(i);
+            result.requiress.add(new Requires(requiresEl.getAttribute("module"),
+                    Boolean.parseBoolean(requiresEl.getAttribute("transitive")),
+                    Boolean.parseBoolean(requiresEl.getAttribute("static"))));
+        }
+        //uses
+        NodeList usesList = rootElement.getElementsByTagName("uses");
+        for (int i = 0; i < usesList.getLength(); i++) {
+            Element usesEl = (Element) usesList.item(i);
+            result.usess.add(new Uses(usesEl.getAttribute("service")));
+        }
+        //provides
+        NodeList providesList = rootElement.getElementsByTagName("provides");
+        for (int i = 0; i < providesList.getLength(); i++) {
+            Element providesEl = (Element) providesList.item(i);
+            Provides provides = new Provides(providesEl.getAttribute("service"));
+            NodeList implList = providesEl.getElementsByTagName("implementation");
+            for (int j = 0; j < implList.getLength(); j++) {
+                Element implElement = (Element) implList.item(j);
+                provides.implementations.add(implElement.getAttribute("class"));
+            }
+            result.providess.add(provides);
+        }
+        //packages
+        NodeList packagesList = rootElement.getElementsByTagName("package");
+        for (int i = 0; i < packagesList.getLength(); i++) {
+            result.packages.add(PackageGenerator
+                    .processDataSet((Element) packagesList.item(i)));
+        }
+        return result;
+    }
+
+    public void generate(Path outDir, SampleApi api) throws IOException {
+        Files.createDirectories(outDir);
+        Path moduleSourceDir;
+        if (!name.equals(UNNAMED)) {
+            moduleSourceDir = outDir.resolve(name);
+            Files.createDirectory(moduleSourceDir);
+            generateModuleInfo(moduleSourceDir, api);
+        } else {
+            moduleSourceDir = outDir;
+        }
+        packages.forEach(pkg -> pkg.generate(moduleSourceDir));
+    }
+
+    private void generateModuleInfo(Path moduleSourceDir, SampleApi api) throws IOException {
+        TreeMaker make = TreeMaker.instance(api.getContext());
+        Names names = Names.instance(api.getContext());
+        JCTree.JCExpression modQual = make.QualIdent(
+                new Symbol.ModuleSymbol(names.fromString(name), null));
+        ListBuffer<JCDirective> exportsBuffer = new ListBuffer<>();
+        exportss.forEach(e -> {
+            ListBuffer<JCExpression> modulesBuffer = new ListBuffer<>();
+            e.modules.stream()
+                    .map(m -> api.isId(m) ? api.moduleById(m).name : m)
+                    .forEach(m -> {
+                modulesBuffer.add(make.Ident(
+                        names.fromString(m)));
+            });
+            exportsBuffer.add(make.Exports(
+                    make.Ident(names.fromString(api.isId(e.pkg) ?
+                            api.packageById(e.pkg).packageName : e.pkg)),
+                    (modulesBuffer.size() > 0) ? modulesBuffer.toList() : null));
+        });
+        openss.forEach(o -> {
+            ListBuffer<JCExpression> modulesBuffer = new ListBuffer<>();
+            o.modules.stream()
+                    .map(m -> api.isId(m) ? api.moduleById(m).name : m)
+                    .forEach(m -> {
+                modulesBuffer.add(make.Ident(
+                        names.fromString(m)));
+            });
+            exportsBuffer.add(make.Opens(
+                    make.Ident(names.fromString(api.isId(o.pkg) ?
+                            api.packageById(o.pkg).packageName : o.pkg)),
+                    (modulesBuffer.size() > 0) ? modulesBuffer.toList() : null));
+        });
+        ListBuffer<JCDirective> requiresBuffer = new ListBuffer<>();
+        requiress.forEach(r -> requiresBuffer.add(make.Requires(
+                r.transitive, r.statc,
+                make.Ident(names.fromString(api.isId(r.module)
+                        ? api.moduleById(r.module).name : r.module)))));
+        ListBuffer<JCDirective> usesBuffer = new ListBuffer<>();
+        usess.forEach(u -> usesBuffer
+                .add(make.Uses(make.Ident(names.fromString(api.isId(u.service)
+                        ? api.classById(u.service) : u.service)))));
+        ListBuffer<JCDirective> providesBuffer = new ListBuffer<>();
+        providess.forEach(p -> {
+            ListBuffer<JCExpression> implementationsBuffer = new ListBuffer<>();
+            p.implementations.stream()
+                    .map(c -> api.isId(c) ? api.classById(c) : c)
+                    .forEach(i -> {
+                implementationsBuffer.add(make.Ident(names.fromString(i)));
+            });
+            providesBuffer.add(make.Provides(
+                make.Ident(names.fromString(api.isId(p.service) ?
+                        api.classById(p.service) : p.service)),
+                implementationsBuffer.toList()));
+        });
+        ListBuffer<JCDirective> fullList = new ListBuffer<>();
+        fullList.addAll(exportsBuffer.toList());
+        fullList.addAll(requiresBuffer.toList());
+        fullList.addAll(usesBuffer.toList());
+        fullList.addAll(providesBuffer.toList());
+        JCTree.JCModuleDecl mod = make.ModuleDef(
+                make.Modifiers(0), //TODO how to support this?
+                kind, modQual, fullList.toList());
+        ListBuffer<JCTree> top = new ListBuffer<>();
+        top.add(mod);
+        JCTree.JCCompilationUnit compilationUnit = make.TopLevel(top.toList());
+        try (OutputStream module_info = Files.newOutputStream(moduleSourceDir.resolve(MODULE_INFO))) {
+            module_info.write(compilationUnit.toString().getBytes());
+        }
+    }
+
+
+    public static class Requires {
+        public String module;
+        public boolean transitive;
+        public boolean statc;
+
+        private Requires(String module, boolean transitive, boolean statc) {
+            this.module = module;
+            this.transitive = transitive;
+            this.statc = this.statc;
+        }
+    }
+
+    public static class Exports {
+        public final String pkg;
+        public final List<String> modules = new ArrayList<>();
+
+        private Exports(String pkg) {
+            this.pkg = pkg;
+        }
+    }
+
+    public static class Opens {
+        public final String pkg;
+        public final List<String> modules = new ArrayList<>();
+
+        private Opens(String pkg) {
+            this.pkg = pkg;
+        }
+    }
+
+    public static class Uses {
+        public final String service;
+
+        private Uses(String service) {
+            this.service = service;
+        }
+    }
+
+    public static class Provides {
+        public final String service;
+        public final List<String> implementations = new ArrayList<>();
+
+        private Provides(String service) {
+            this.service = service;
+        }
+    }
+}